From e98e3350c03af4187e1d5fe007c7b460e378990c Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:38 +0000 Subject: netxen: code cleanup o remove unused structure defs. o remove unnecessary includes. o replace enums with specific #defines. o reduce footprint of stats structure. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 246 +++++++++++-------------------- drivers/net/netxen/netxen_nic_ethtool.c | 11 +- drivers/net/netxen/netxen_nic_hdr.h | 8 - drivers/net/netxen/netxen_nic_hw.c | 17 ++- drivers/net/netxen/netxen_nic_hw.h | 66 +++------ drivers/net/netxen/netxen_nic_main.c | 19 +-- drivers/net/netxen/netxen_nic_niu.c | 14 +- drivers/net/netxen/netxen_nic_phan_reg.h | 21 ++- 8 files changed, 146 insertions(+), 256 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index c40815169f35..184eb6f76d55 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -34,10 +34,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -49,18 +45,12 @@ #include #include -#include #include -#include -#include #include -#include #include #include -#include -#include #include "netxen_nic_hw.h" @@ -118,6 +108,7 @@ #define NX_P3_A2 0x30 #define NX_P3_B0 0x40 #define NX_P3_B1 0x41 +#define NX_P3_B2 0x42 #define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1) #define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0) @@ -203,18 +194,8 @@ #define MAX_RCV_DESCRIPTORS_10G 4096 #define MAX_JUMBO_RCV_DESCRIPTORS 1024 #define MAX_LRO_RCV_DESCRIPTORS 8 -#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS -#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS -#define MAX_RCV_DESC MAX_RCV_DESCRIPTORS -#define MAX_RCVSTATUS_DESC MAX_RCV_DESCRIPTORS -#define MAX_EPG_DESCRIPTORS (MAX_CMD_DESCRIPTORS * 8) -#define NUM_RCV_DESC (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \ - MAX_LRO_RCV_DESCRIPTORS) -#define MIN_TX_COUNT 4096 -#define MIN_RX_COUNT 4096 #define NETXEN_CTX_SIGNATURE 0xdee0 #define NETXEN_RCV_PRODUCER(ringid) (ringid) -#define MAX_FRAME_SIZE 0x10000 /* 64K MAX size for LSO */ #define PHAN_PEG_RCV_INITIALIZED 0xff01 #define PHAN_PEG_RCV_START_INITIALIZE 0xff00 @@ -384,11 +365,6 @@ struct rcv_desc { /* Note: sizeof(status_desc) should always be a mutliple of 2 */ -#define netxen_get_sts_desc_lro_cnt(status_desc) \ - ((status_desc)->lro & 0x7F) -#define netxen_get_sts_desc_lro_last_frag(status_desc) \ - (((status_desc)->lro & 0x80) >> 7) - #define netxen_get_sts_port(sts_data) \ ((sts_data) & 0x0F) #define netxen_get_sts_status(sts_data) \ @@ -434,10 +410,6 @@ struct status_desc { }; } __attribute__ ((aligned(16))); -enum { - NETXEN_RCV_PEG_0 = 0, - NETXEN_RCV_PEG_1 -}; /* The version of the main data structure */ #define NETXEN_BDINFO_VERSION 1 @@ -447,85 +419,35 @@ enum { /* Max number of Gig ports on a Phantom board */ #define NETXEN_MAX_PORTS 4 -typedef enum { - NETXEN_BRDTYPE_P1_BD = 0x0000, - NETXEN_BRDTYPE_P1_SB = 0x0001, - NETXEN_BRDTYPE_P1_SMAX = 0x0002, - NETXEN_BRDTYPE_P1_SOCK = 0x0003, - - NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008, - NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009, - NETXEN_BRDTYPE_P2_SB35_4G = 0x000a, - NETXEN_BRDTYPE_P2_SB31_10G = 0x000b, - NETXEN_BRDTYPE_P2_SB31_2G = 0x000c, - - NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d, - NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e, - NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f, - - NETXEN_BRDTYPE_P3_REF_QG = 0x0021, - NETXEN_BRDTYPE_P3_HMEZ = 0x0022, - NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023, - NETXEN_BRDTYPE_P3_4_GB = 0x0024, - NETXEN_BRDTYPE_P3_IMEZ = 0x0025, - NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026, - NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027, - NETXEN_BRDTYPE_P3_XG_LOM = 0x0028, - NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029, - NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a, - NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b, - NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031, - NETXEN_BRDTYPE_P3_10G_XFP = 0x0032, - NETXEN_BRDTYPE_P3_10G_TP = 0x0080 - -} netxen_brdtype_t; - -typedef enum { - NETXEN_BRDMFG_INVENTEC = 1 -} netxen_brdmfg; - -typedef enum { - MEM_ORG_128Mbx4 = 0x0, /* DDR1 only */ - MEM_ORG_128Mbx8 = 0x1, /* DDR1 only */ - MEM_ORG_128Mbx16 = 0x2, /* DDR1 only */ - MEM_ORG_256Mbx4 = 0x3, - MEM_ORG_256Mbx8 = 0x4, - MEM_ORG_256Mbx16 = 0x5, - MEM_ORG_512Mbx4 = 0x6, - MEM_ORG_512Mbx8 = 0x7, - MEM_ORG_512Mbx16 = 0x8, - MEM_ORG_1Gbx4 = 0x9, - MEM_ORG_1Gbx8 = 0xa, - MEM_ORG_1Gbx16 = 0xb, - MEM_ORG_2Gbx4 = 0xc, - MEM_ORG_2Gbx8 = 0xd, - MEM_ORG_2Gbx16 = 0xe, - MEM_ORG_128Mbx32 = 0x10002, /* GDDR only */ - MEM_ORG_256Mbx32 = 0x10005 /* GDDR only */ -} netxen_mn_mem_org_t; - -typedef enum { - MEM_ORG_512Kx36 = 0x0, - MEM_ORG_1Mx36 = 0x1, - MEM_ORG_2Mx36 = 0x2 -} netxen_sn_mem_org_t; - -typedef enum { - MEM_DEPTH_4MB = 0x1, - MEM_DEPTH_8MB = 0x2, - MEM_DEPTH_16MB = 0x3, - MEM_DEPTH_32MB = 0x4, - MEM_DEPTH_64MB = 0x5, - MEM_DEPTH_128MB = 0x6, - MEM_DEPTH_256MB = 0x7, - MEM_DEPTH_512MB = 0x8, - MEM_DEPTH_1GB = 0x9, - MEM_DEPTH_2GB = 0xa, - MEM_DEPTH_4GB = 0xb, - MEM_DEPTH_8GB = 0xc, - MEM_DEPTH_16GB = 0xd, - MEM_DEPTH_32GB = 0xe -} netxen_mem_depth_t; +#define NETXEN_BRDTYPE_P1_BD 0x0000 +#define NETXEN_BRDTYPE_P1_SB 0x0001 +#define NETXEN_BRDTYPE_P1_SMAX 0x0002 +#define NETXEN_BRDTYPE_P1_SOCK 0x0003 + +#define NETXEN_BRDTYPE_P2_SOCK_31 0x0008 +#define NETXEN_BRDTYPE_P2_SOCK_35 0x0009 +#define NETXEN_BRDTYPE_P2_SB35_4G 0x000a +#define NETXEN_BRDTYPE_P2_SB31_10G 0x000b +#define NETXEN_BRDTYPE_P2_SB31_2G 0x000c + +#define NETXEN_BRDTYPE_P2_SB31_10G_IMEZ 0x000d +#define NETXEN_BRDTYPE_P2_SB31_10G_HMEZ 0x000e +#define NETXEN_BRDTYPE_P2_SB31_10G_CX4 0x000f + +#define NETXEN_BRDTYPE_P3_REF_QG 0x0021 +#define NETXEN_BRDTYPE_P3_HMEZ 0x0022 +#define NETXEN_BRDTYPE_P3_10G_CX4_LP 0x0023 +#define NETXEN_BRDTYPE_P3_4_GB 0x0024 +#define NETXEN_BRDTYPE_P3_IMEZ 0x0025 +#define NETXEN_BRDTYPE_P3_10G_SFP_PLUS 0x0026 +#define NETXEN_BRDTYPE_P3_10000_BASE_T 0x0027 +#define NETXEN_BRDTYPE_P3_XG_LOM 0x0028 +#define NETXEN_BRDTYPE_P3_4_GB_MM 0x0029 +#define NETXEN_BRDTYPE_P3_10G_SFP_CT 0x002a +#define NETXEN_BRDTYPE_P3_10G_SFP_QT 0x002b +#define NETXEN_BRDTYPE_P3_10G_CX4 0x0031 +#define NETXEN_BRDTYPE_P3_10G_XFP 0x0032 +#define NETXEN_BRDTYPE_P3_10G_TP 0x0080 struct netxen_board_info { u32 header_version; @@ -676,17 +598,15 @@ struct netxen_new_user_info { #define PRIMARY_IMAGE_BAD 0xffffffff /* Flash memory map */ -typedef enum { - NETXEN_CRBINIT_START = 0, /* Crbinit section */ - NETXEN_BRDCFG_START = 0x4000, /* board config */ - NETXEN_INITCODE_START = 0x6000, /* pegtune code */ - NETXEN_BOOTLD_START = 0x10000, /* bootld */ - NETXEN_IMAGE_START = 0x43000, /* compressed image */ - NETXEN_SECONDARY_START = 0x200000, /* backup images */ - NETXEN_PXE_START = 0x3E0000, /* user defined region */ - NETXEN_USER_START = 0x3E8000, /* User defined region for new boards */ - NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */ -} netxen_flash_map_t; +#define NETXEN_CRBINIT_START 0 /* crbinit section */ +#define NETXEN_BRDCFG_START 0x4000 /* board config */ +#define NETXEN_INITCODE_START 0x6000 /* pegtune code */ +#define NETXEN_BOOTLD_START 0x10000 /* bootld */ +#define NETXEN_IMAGE_START 0x43000 /* compressed image */ +#define NETXEN_SECONDARY_START 0x200000 /* backup images */ +#define NETXEN_PXE_START 0x3E0000 /* PXE boot rom */ +#define NETXEN_USER_START 0x3E8000 /* Firmare info */ +#define NETXEN_FIXED_START 0x3F0000 /* backup of crbinit */ #define NX_FW_VERSION_OFFSET (NETXEN_USER_START+0x408) #define NX_FW_SIZE_OFFSET (NETXEN_USER_START+0x40c) @@ -708,21 +628,8 @@ typedef enum { #define NETXEN_FLASH_SECONDARY_SIZE (NETXEN_USER_START-NETXEN_SECONDARY_START) #define NETXEN_NUM_PRIMARY_SECTORS (0x20) #define NETXEN_NUM_CONFIG_SECTORS (1) -#define PFX "NetXen: " extern char netxen_nic_driver_name[]; -/* Note: Make sure to not call this before adapter->port is valid */ -#if !defined(NETXEN_DEBUG) -#define DPRINTK(klevel, fmt, args...) do { \ - } while (0) -#else -#define DPRINTK(klevel, fmt, args...) do { \ - printk(KERN_##klevel PFX "%s: %s: " fmt, __func__,\ - (adapter != NULL && adapter->netdev != NULL) ? \ - adapter->netdev->name : NULL, \ - ## args); } while(0) -#endif - /* Number of status descriptors to handle per interrupt */ #define MAX_STATUS_HANDLE (64) @@ -807,20 +714,14 @@ struct netxen_hardware_context { #define ETHERNET_FCS_SIZE 4 struct netxen_adapter_stats { - u64 rcvdbadskb; u64 xmitcalled; - u64 xmitedframes; u64 xmitfinished; - u64 badskblen; - u64 nocmddescriptor; - u64 polled; u64 rxdropped; u64 txdropped; u64 csummed; u64 no_rcv; u64 rxbytes; u64 txbytes; - u64 ints; }; /* @@ -1154,26 +1055,53 @@ typedef struct { #define NX_MAC_EVENT 0x1 -enum { - NX_NIC_H2C_OPCODE_START = 0, - NX_NIC_H2C_OPCODE_CONFIG_RSS, - NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL, - NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE, - NX_NIC_H2C_OPCODE_CONFIG_LED, - NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS, - NX_NIC_H2C_OPCODE_CONFIG_L2_MAC, - NX_NIC_H2C_OPCODE_LRO_REQUEST, - NX_NIC_H2C_OPCODE_GET_SNMP_STATS, - NX_NIC_H2C_OPCODE_PROXY_START_REQUEST, - NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST, - NX_NIC_H2C_OPCODE_PROXY_SET_MTU, - NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE, - NX_H2P_OPCODE_GET_FINGER_PRINT_REQUEST, - NX_H2P_OPCODE_INSTALL_LICENSE_REQUEST, - NX_H2P_OPCODE_GET_LICENSE_CAPABILITY_REQUEST, - NX_NIC_H2C_OPCODE_GET_NET_STATS, - NX_NIC_H2C_OPCODE_LAST -}; +/* + * Driver --> Firmware + */ +#define NX_NIC_H2C_OPCODE_START 0 +#define NX_NIC_H2C_OPCODE_CONFIG_RSS 1 +#define NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL 2 +#define NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE 3 +#define NX_NIC_H2C_OPCODE_CONFIG_LED 4 +#define NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS 5 +#define NX_NIC_H2C_OPCODE_CONFIG_L2_MAC 6 +#define NX_NIC_H2C_OPCODE_LRO_REQUEST 7 +#define NX_NIC_H2C_OPCODE_GET_SNMP_STATS 8 +#define NX_NIC_H2C_OPCODE_PROXY_START_REQUEST 9 +#define NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST 10 +#define NX_NIC_H2C_OPCODE_PROXY_SET_MTU 11 +#define NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE 12 +#define NX_NIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST 13 +#define NX_NIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST 14 +#define NX_NIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST 15 +#define NX_NIC_H2C_OPCODE_GET_NET_STATS 16 +#define NX_NIC_H2C_OPCODE_PROXY_UPDATE_P2V 17 +#define NX_NIC_H2C_OPCODE_CONFIG_IPADDR 18 +#define NX_NIC_H2C_OPCODE_CONFIG_LOOPBACK 19 +#define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE 20 +#define NX_NIC_H2C_OPCODE_GET_LINKEVENT 21 +#define NX_NIC_C2C_OPCODE 22 +#define NX_NIC_H2C_OPCODE_LAST 23 + +/* + * Firmware --> Driver + */ + +#define NX_NIC_C2H_OPCODE_START 128 +#define NX_NIC_C2H_OPCODE_CONFIG_RSS_RESPONSE 129 +#define NX_NIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE 130 +#define NX_NIC_C2H_OPCODE_CONFIG_MAC_RESPONSE 131 +#define NX_NIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE 132 +#define NX_NIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE 133 +#define NX_NIC_C2H_OPCODE_LRO_DELETE_RESPONSE 134 +#define NX_NIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE 135 +#define NX_NIC_C2H_OPCODE_GET_SNMP_STATS 136 +#define NX_NIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY 137 +#define NX_NIC_C2H_OPCODE_INSTALL_LICENSE_REPLY 138 +#define NX_NIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139 +#define NX_NIC_C2H_OPCODE_GET_NET_STATS_RESPONSE 140 +#define NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 +#define NX_NIC_C2H_OPCODE_LAST 142 #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ @@ -1491,7 +1419,7 @@ void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, #define NETXEN_MAX_SHORT_NAME 32 struct netxen_brdinfo { - netxen_brdtype_t brdtype; /* type of board */ + int brdtype; /* type of board */ long ports; /* max no of physical ports */ char short_name[NETXEN_MAX_SHORT_NAME]; }; diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index a677ff895184..fe910c1715d6 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -53,13 +52,9 @@ struct netxen_nic_stats { #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { - {"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)}, {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)}, - {"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)}, {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)}, - {"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)}, - {"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)}, - {"polled", NETXEN_NIC_STAT(stats.polled)}, + {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)}, {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, {"csummed", NETXEN_NIC_STAT(stats.csummed)}, {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)}, @@ -168,7 +163,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; - switch ((netxen_brdtype_t)adapter->ahw.board_type) { + switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: case NETXEN_BRDTYPE_P2_SB31_2G: case NETXEN_BRDTYPE_P3_REF_QG: @@ -227,7 +222,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) break; default: printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", - (netxen_brdtype_t)adapter->ahw.board_type); + adapter->ahw.board_type); return -EIO; } diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 016c62129c76..7f0ddbfa7b28 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -31,16 +31,8 @@ #ifndef __NETXEN_NIC_HDR_H_ #define __NETXEN_NIC_HDR_H_ -#include #include -#include -#include -#include -#include -#include #include -#include -#include /* for memset */ /* * The basic unit of access when reading/writing control registers. diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 5026811c04ce..67d63eecc9cb 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -48,6 +48,21 @@ #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) #define CRB_INDIRECT_2M (0x1e0000UL) +#ifndef readq +static inline u64 readq(void __iomem *addr) +{ + return readl(addr) | (((u64) readl(addr + 4)) << 32LL); +} +#endif + +#ifndef writeq +static inline void writeq(u64 val, void __iomem *addr) +{ + writel(((u32) (val)), (addr)); + writel(((u32) (val >> 32)), (addr + 4)); +} +#endif + #define CRB_WIN_LOCK_TIMEOUT 100000000 static crb_128M_2M_block_map_t crb_128M_2M_map[64] = { {{{0, 0, 0, 0} } }, /* 0: PCI */ @@ -2148,7 +2163,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) board_type = NETXEN_BRDTYPE_P3_10G_TP; } - switch ((netxen_brdtype_t)board_type) { + switch (board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: adapter->ahw.port_type = NETXEN_NIC_GBE; break; diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index 04b47a7993cd..f20c96591a87 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -36,35 +36,15 @@ /* Hardware memory size of 128 meg */ #define NETXEN_MEMADDR_MAX (128 * 1024 * 1024) -#ifndef readq -static inline u64 readq(void __iomem * addr) -{ - return readl(addr) | (((u64) readl(addr + 4)) << 32LL); -} -#endif - -#ifndef writeq -static inline void writeq(u64 val, void __iomem * addr) -{ - writel(((u32) (val)), (addr)); - writel(((u32) (val >> 32)), (addr + 4)); -} -#endif - struct netxen_adapter; #define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20) -struct netxen_port; void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); typedef u8 netxen_ethernet_macaddr_t[6]; /* Nibble or Byte mode for phy interface (GbE mode only) */ -typedef enum { - NETXEN_NIU_10_100_MB = 0, - NETXEN_NIU_1000_MB -} netxen_niu_gbe_ifmode_t; #define _netxen_crb_get_bit(var, bit) ((var >> bit) & 0x1) @@ -222,30 +202,28 @@ typedef enum { /* * PHY-Specific MII control/status registers. */ -typedef enum { - NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0, - NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3, - NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4, - NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5, - NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6, - NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7, - NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8, - NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9, - NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10, - NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20, - NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21, - NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24, - NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27 -} netxen_niu_phy_register_t; +#define NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL 0 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS 1 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 2 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 3 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG 4 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART 5 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE 6 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT 7 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE 8 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL 9 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS 10 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS 15 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL 16 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS 17 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE 18 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS 19 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE 20 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT 21 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL 24 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE 25 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET 26 +#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE 27 /* * PHY-Specific Status Register (reg 17). diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index aef77289bd34..85693c0f5637 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -29,7 +29,7 @@ */ #include -#include +#include #include "netxen_nic_hw.h" #include "netxen_nic.h" @@ -1598,10 +1598,6 @@ static void netxen_tx_timeout_task(struct work_struct *work) netif_wake_queue(adapter->netdev); } -/* - * netxen_nic_get_stats - Get System Network Statistics - * @netdev: network interface device structure - */ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); @@ -1609,22 +1605,11 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) memset(stats, 0, sizeof(*stats)); - /* total packets received */ stats->rx_packets = adapter->stats.no_rcv; - /* total packets transmitted */ - stats->tx_packets = adapter->stats.xmitedframes + - adapter->stats.xmitfinished; - /* total bytes received */ + stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes; - /* total bytes transmitted */ stats->tx_bytes = adapter->stats.txbytes; - /* bad packets received */ - stats->rx_errors = adapter->stats.rcvdbadskb; - /* packet transmit problems */ - stats->tx_errors = adapter->stats.nocmddescriptor; - /* no space in linux buffers */ stats->rx_dropped = adapter->stats.rxdropped; - /* no space available in linux */ stats->tx_dropped = adapter->stats.txdropped; return stats; diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index d85203203d4d..3310471ba1a0 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -342,9 +342,9 @@ static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, } if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n"); + printk(KERN_ERR "ERROR enabling PHY interrupts\n"); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); } /* @@ -380,9 +380,9 @@ static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, } if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n"); + printk(KERN_ERR "ERROR enabling PHY interrupts\n"); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); } int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) @@ -428,13 +428,13 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) | NETXEN_GB_MAC_PAUSED_FRMS); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR PFX + printk(KERN_ERR "ERROR enabling PHY interrupts\n"); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR PFX + printk(KERN_ERR "ERROR clearing PHY interrupts\n"); result = -1; } diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 50183335e43a..18ea35d51160 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -41,18 +41,18 @@ #define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) #define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) #define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) -#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) /* C0 EPG BUG */ +#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) #define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14) #define NX_CDRP_CRB_OFFSET NETXEN_NIC_REG(0x18) #define NX_ARG1_CRB_OFFSET NETXEN_NIC_REG(0x1c) #define NX_ARG2_CRB_OFFSET NETXEN_NIC_REG(0x20) #define NX_ARG3_CRB_OFFSET NETXEN_NIC_REG(0x24) #define NX_SIGN_CRB_OFFSET NETXEN_NIC_REG(0x28) -#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) /* 4 regs for perf */ +#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) #define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24) #define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28) #define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x2c) -#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x30) /* phantom init status */ +#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x30) #define CRB_MMAP_ADDR_3 NETXEN_NIC_REG(0x34) #define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x38) #define CRB_HOST_DUMMY_BUF_ADDR_HI NETXEN_NIC_REG(0x3c) @@ -65,7 +65,7 @@ #define CRB_MMAP_SIZE_1 NETXEN_NIC_REG(0x58) #define CRB_MMAP_SIZE_2 NETXEN_NIC_REG(0x5c) #define CRB_MMAP_SIZE_3 NETXEN_NIC_REG(0x60) -#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x64) /* interrupt coalescing */ +#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x64) #define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x68) #define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x6c) #define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x70) @@ -83,13 +83,13 @@ #define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xa0) #define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xa4) #define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xa8) -#define CRB_TX_STATE NETXEN_NIC_REG(0xac) /* Debug -performance */ +#define CRB_TX_STATE NETXEN_NIC_REG(0xac) #define CRB_TX_COUNT NETXEN_NIC_REG(0xb0) #define CRB_RX_STATE NETXEN_NIC_REG(0xb4) #define CRB_RX_PERF_DEBUG_1 NETXEN_NIC_REG(0xb8) -#define CRB_RX_LRO_CONTROL NETXEN_NIC_REG(0xbc) /* LRO On/OFF */ +#define CRB_RX_LRO_CONTROL NETXEN_NIC_REG(0xbc) #define CRB_RX_LRO_START_NUM NETXEN_NIC_REG(0xc0) -#define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) /* Multiport Mode */ +#define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) #define CRB_CMD_RING_SIZE NETXEN_NIC_REG(0xc8) #define CRB_DMA_SHIFT NETXEN_NIC_REG(0xcc) #define CRB_INT_VECTOR NETXEN_NIC_REG(0xd4) @@ -109,8 +109,6 @@ #define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0) #define CRB_CMD_PRODUCER_OFFSET_2 NETXEN_NIC_REG(0x1b8) #define CRB_CMD_CONSUMER_OFFSET_2 NETXEN_NIC_REG(0x1bc) - -// 1c0 to 1cc used for signature reg #define CRB_CMD_PRODUCER_OFFSET_3 NETXEN_NIC_REG(0x1d0) #define CRB_CMD_CONSUMER_OFFSET_3 NETXEN_NIC_REG(0x1d4) #define CRB_TEMP_STATE NETXEN_NIC_REG(0x1b4) @@ -120,8 +118,7 @@ #define CRB_V2P_2 NETXEN_NIC_REG(0x298) #define CRB_V2P_3 NETXEN_NIC_REG(0x29c) #define CRB_V2P(port) (CRB_V2P_0+((port)*4)) -#define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) -/* sw int status/mask registers */ +#define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) #define CRB_SW_INT_MASK_0 NETXEN_NIC_REG(0x1d8) #define CRB_SW_INT_MASK_1 NETXEN_NIC_REG(0x1e0) #define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) @@ -136,7 +133,7 @@ #define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) -#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) +#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) #define INTR_SCHEME_PERPORT 0x1 #define MSI_MODE_MULTIFUNC 0x1 -- cgit v1.2.3 From 1b1f789818c6be9437cfe199932ee13faafca60f Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:39 +0000 Subject: netxen: refactor netxen_adapter Rearrange members to align them at right offset. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 80 ++++++++++++++++++------------------ drivers/net/netxen/netxen_nic_ctx.c | 7 ---- drivers/net/netxen/netxen_nic_main.c | 11 ----- 3 files changed, 39 insertions(+), 59 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 184eb6f76d55..1165f53ea2ca 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -700,14 +700,13 @@ struct netxen_hardware_context { u8 cut_through; u8 revision_id; + u8 pci_func; + u8 linkup; u16 port_type; - int board_type; - u32 linkup; + u16 board_type; /* Address of cmd ring in Phantom */ struct cmd_desc_type0 *cmd_desc_head; dma_addr_t cmd_desc_phys_addr; - struct netxen_adapter *adapter; - int pci_func; }; #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ @@ -1146,61 +1145,52 @@ struct netxen_adapter { struct net_device *netdev; struct pci_dev *pdev; - int pci_using_dac; - struct net_device_stats net_stats; - int mtu; - int portnum; - u8 physical_port; - u16 tx_context_id; - - uint8_t mc_enabled; - uint8_t max_mc_count; nx_mac_list_t *mac_list; - struct netxen_legacy_intr_set legacy_intr; - - struct work_struct watchdog_task; - struct timer_list watchdog_timer; - struct work_struct tx_timeout_task; - u32 curr_window; u32 crb_win; rwlock_t adapter_lock; + spinlock_t tx_clean_lock; u32 cmd_producer; - __le32 *cmd_consumer; u32 last_cmd_consumer; u32 crb_addr_cmd_producer; u32 crb_addr_cmd_consumer; - spinlock_t tx_clean_lock; + __le32 *cmd_consumer; u32 num_txd; u32 num_rxd; u32 num_jumbo_rxd; u32 num_lro_rxd; - int max_rds_rings; - int max_sds_rings; + u8 max_rds_rings; + u8 max_sds_rings; + u8 driver_mismatch; + u8 msix_supported; + u8 rx_csum; + u8 pci_using_dac; + u8 portnum; + u8 physical_port; + + u8 mc_enabled; + u8 max_mc_count; + u16 tx_context_id; + u16 mtu; + u16 is_up; + u16 link_speed; + u16 link_duplex; + u16 link_autoneg; + u16 resv1; + u32 resv2; u32 flags; u32 irq; - int driver_mismatch; u32 temp; - u32 fw_major; u32 fw_version; - int msix_supported; - struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; - struct netxen_adapter_stats stats; - u16 link_speed; - u16 link_duplex; - u16 state; - u16 link_autoneg; - int rx_csum; - struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */ /* @@ -1209,15 +1199,9 @@ struct netxen_adapter { */ struct netxen_recv_context recv_ctx; - int is_up; - struct netxen_dummy_dma dummy_dma; - nx_nic_intr_coalesce_t coal; - /* Context interface shared between card and host */ struct netxen_ring_ctx *ctx_desc; dma_addr_t ctx_desc_phys_addr; - int intr_scheme; - int msi_mode; int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t); @@ -1238,7 +1222,21 @@ struct netxen_adapter { u32 (*pci_read_normalize)(struct netxen_adapter *, u64); unsigned long (*pci_set_window)(struct netxen_adapter *, unsigned long long); -}; /* netxen_adapter structure */ + + struct netxen_legacy_intr_set legacy_intr; + + struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; + + struct netxen_dummy_dma dummy_dma; + + struct work_struct watchdog_task; + struct timer_list watchdog_timer; + struct work_struct tx_timeout_task; + + struct net_device_stats net_stats; + + nx_nic_intr_coalesce_t coal; +}; /* * NetXen dma watchdog control structure diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 9234473bc08a..73f6debacf9c 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -624,9 +624,6 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (adapter->fw_major >= 4) { - adapter->intr_scheme = INTR_SCHEME_PERPORT; - adapter->msi_mode = MSI_MODE_MULTIFUNC; - err = nx_fw_cmd_create_rx_ctx(adapter); if (err) goto err_out_free; @@ -638,10 +635,6 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) sds_ring->crb_sts_consumer = recv_crb_registers[adapter->portnum].crb_sts_consumer; - adapter->intr_scheme = adapter->pci_read_normalize(adapter, - CRB_NIC_CAPABILITIES_FW); - adapter->msi_mode = adapter->pci_read_normalize(adapter, - CRB_NIC_MSI_MODE_FW); recv_ctx->sds_rings[0].crb_intr_mask = sw_int_mask[adapter->portnum]; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 85693c0f5637..853dee8057d9 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -462,8 +462,6 @@ netxen_setup_intr(struct netxen_adapter *adapter) struct pci_dev *pdev = adapter->pdev; adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); - adapter->intr_scheme = -1; - adapter->msi_mode = -1; if (adapter->ahw.revision_id >= NX_P3_B0) legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; @@ -726,15 +724,6 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || - (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { - printk(KERN_ERR "%s: Firmware interrupt scheme is " - "incompatible with driver\n", - netdev->name); - adapter->driver_mismatch = 1; - return -EINVAL; - } - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) handler = netxen_msix_intr; else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) -- cgit v1.2.3 From d877f1e344f5515988d9dcd6db5d4285911778a3 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:40 +0000 Subject: netxen: refactor transmit code o move tx stuff into nx_host_tx_ring structure, this will help managing multiple tx rings in future. o sanitize some variable names Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 42 ++++++++++++++--------------- drivers/net/netxen/netxen_nic_ctx.c | 49 +++++++++++++-------------------- drivers/net/netxen/netxen_nic_hw.c | 37 +++++++++++++------------ drivers/net/netxen/netxen_nic_init.c | 48 ++++++++++++++++++--------------- drivers/net/netxen/netxen_nic_main.c | 52 +++++++++++++++++------------------- 5 files changed, 108 insertions(+), 120 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 1165f53ea2ca..2aa658db103f 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -74,10 +74,10 @@ (sizeof(struct netxen_rx_buffer) * rds_ring->num_desc) #define STATUS_DESC_RINGSIZE(sds_ring) \ (sizeof(struct status_desc) * (sds_ring)->num_desc) -#define TX_BUFF_RINGSIZE(adapter) \ - (sizeof(struct netxen_cmd_buffer) * adapter->num_txd) -#define TX_DESC_RINGSIZE(adapter) \ - (sizeof(struct cmd_desc_type0) * adapter->num_txd) +#define TX_BUFF_RINGSIZE(tx_ring) \ + (sizeof(struct netxen_cmd_buffer) * tx_ring->num_desc) +#define TX_DESC_RINGSIZE(tx_ring) \ + (sizeof(struct cmd_desc_type0) * tx_ring->num_desc) #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) @@ -639,7 +639,7 @@ extern char netxen_nic_driver_name[]; */ struct netxen_skb_frag { u64 dma; - ulong length; + u64 length; }; #define _netxen_set_bits(config_word, start, bits, val) {\ @@ -704,9 +704,6 @@ struct netxen_hardware_context { u8 linkup; u16 port_type; u16 board_type; - /* Address of cmd ring in Phantom */ - struct cmd_desc_type0 *cmd_desc_head; - dma_addr_t cmd_desc_phys_addr; }; #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ @@ -752,14 +749,25 @@ struct nx_host_sds_ring { struct napi_struct napi; struct list_head free_list[NUM_RCV_DESC_RINGS]; - u16 clean_tx; - u16 post_rxd; int irq; dma_addr_t phys_addr; char name[IFNAMSIZ+4]; }; +struct nx_host_tx_ring { + u32 producer; + __le32 *hw_consumer; + u32 sw_consumer; + u32 crb_cmd_producer; + u32 crb_cmd_consumer; + u32 num_desc; + + struct netxen_cmd_buffer *cmd_buf_arr; + struct cmd_desc_type0 *desc_head; + dma_addr_t phys_addr; +}; + /* * Receive context. There is one such structure per instance of the * receive processing. Any state information that is relevant to @@ -1152,11 +1160,6 @@ struct netxen_adapter { rwlock_t adapter_lock; spinlock_t tx_clean_lock; - u32 cmd_producer; - u32 last_cmd_consumer; - u32 crb_addr_cmd_producer; - u32 crb_addr_cmd_consumer; - __le32 *cmd_consumer; u32 num_txd; u32 num_rxd; @@ -1191,13 +1194,8 @@ struct netxen_adapter { struct netxen_adapter_stats stats; - struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */ - - /* - * Receive instances. These can be either one per port, - * or one per peg, etc. - */ struct netxen_recv_context recv_ctx; + struct nx_host_tx_ring tx_ring; /* Context interface shared between card and host */ struct netxen_ring_ctx *ctx_desc; @@ -1409,7 +1407,7 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p); struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, - uint32_t crb_producer); + struct nx_host_tx_ring *tx_ring, uint32_t crb_producer); /* * NetXen Board information diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 73f6debacf9c..794335188a26 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -328,6 +328,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) int err = 0; u64 offset, phys_addr; dma_addr_t rq_phys_addr, rsp_phys_addr; + struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); rq_addr = pci_alloc_consistent(adapter->pdev, @@ -367,10 +368,8 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) prq_cds = &prq->cds_ring; - prq_cds->host_phys_addr = - cpu_to_le64(adapter->ahw.cmd_desc_phys_addr); - - prq_cds->ring_size = cpu_to_le32(adapter->num_txd); + prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr); + prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); phys_addr = rq_phys_addr; err = netxen_issue_cmd(adapter, @@ -383,8 +382,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) if (err == NX_RCODE_SUCCESS) { temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); - adapter->crb_addr_cmd_producer = - NETXEN_NIC_REG(temp - 0x200); + tx_ring->crb_cmd_producer = NETXEN_NIC_REG(temp - 0x200); #if 0 adapter->tx_state = le32_to_cpu(prsp->host_ctx_state); @@ -497,13 +495,13 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring; int ring; int func_id = adapter->portnum; - adapter->ctx_desc->cmd_ring_addr = - cpu_to_le64(adapter->ahw.cmd_desc_phys_addr); - adapter->ctx_desc->cmd_ring_size = - cpu_to_le32(adapter->num_txd); + tx_ring = &adapter->tx_ring; + adapter->ctx_desc->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); + adapter->ctx_desc->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); recv_ctx = &adapter->recv_ctx; @@ -535,25 +533,17 @@ static uint32_t sw_int_mask[4] = { int netxen_alloc_hw_resources(struct netxen_adapter *adapter) { - struct netxen_hardware_context *hw = &adapter->ahw; - u32 state = 0; void *addr; int err = 0; int ring; struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; - err = netxen_receive_peg_ready(adapter); - if (err) { - printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n", - state); - return err; - } - addr = pci_alloc_consistent(pdev, sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), &adapter->ctx_desc_phys_addr); @@ -568,13 +558,12 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) adapter->ctx_desc->cmd_consumer_offset = cpu_to_le64(adapter->ctx_desc_phys_addr + sizeof(struct netxen_ring_ctx)); - adapter->cmd_consumer = + tx_ring->hw_consumer = (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); /* cmd desc ring */ - addr = pci_alloc_consistent(pdev, - TX_DESC_RINGSIZE(adapter), - &hw->cmd_desc_phys_addr); + addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), + &tx_ring->phys_addr); if (addr == NULL) { dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", @@ -582,7 +571,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) return -ENOMEM; } - hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; + tx_ring->desc_head = (struct cmd_desc_type0 *)addr; recv_ctx = &adapter->recv_ctx; @@ -658,6 +647,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring; int ring; if (adapter->fw_major >= 4) { @@ -674,13 +664,12 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) adapter->ctx_desc = NULL; } - if (adapter->ahw.cmd_desc_head != NULL) { + tx_ring = &adapter->tx_ring; + if (tx_ring->desc_head != NULL) { pci_free_consistent(adapter->pdev, - sizeof(struct cmd_desc_type0) * - adapter->num_txd, - adapter->ahw.cmd_desc_head, - adapter->ahw.cmd_desc_phys_addr); - adapter->ahw.cmd_desc_head = NULL; + TX_DESC_RINGSIZE(tx_ring), + tx_ring->desc_head, tx_ring->phys_addr); + tx_ring->desc_head = NULL; } recv_ctx = &adapter->recv_ctx; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 67d63eecc9cb..8416962cc9ac 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -501,45 +501,44 @@ static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, static int netxen_send_cmd_descs(struct netxen_adapter *adapter, - struct cmd_desc_type0 *cmd_desc_arr, int nr_elements) + struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) { - uint32_t i, producer; + u32 i, producer, consumer; struct netxen_cmd_buffer *pbuf; struct cmd_desc_type0 *cmd_desc; - - if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) { - printk(KERN_WARNING "%s: Too many command descriptors in a " - "request\n", __func__); - return -EINVAL; - } + struct nx_host_tx_ring *tx_ring; i = 0; + tx_ring = &adapter->tx_ring; netif_tx_lock_bh(adapter->netdev); - producer = adapter->cmd_producer; + producer = tx_ring->producer; + consumer = tx_ring->sw_consumer; + + if (nr_desc > find_diff_among(producer, consumer, tx_ring->num_desc)) { + netif_tx_unlock_bh(adapter->netdev); + return -EBUSY; + } + do { cmd_desc = &cmd_desc_arr[i]; - pbuf = &adapter->cmd_buf_arr[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; pbuf->frag_count = 0; - /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ - memcpy(&adapter->ahw.cmd_desc_head[producer], + memcpy(&tx_ring->desc_head[producer], &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); - producer = get_next_index(producer, - adapter->num_txd); + producer = get_next_index(producer, tx_ring->num_desc); i++; - } while (i != nr_elements); - - adapter->cmd_producer = producer; + } while (i != nr_desc); - /* write producer index to start the xmit */ + tx_ring->producer = producer; - netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); + netxen_nic_update_cmd_producer(adapter, tx_ring, producer); netif_tx_unlock_bh(adapter->netdev); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 0759c35f16ac..8e45dcc27c7f 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -173,9 +173,10 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) struct netxen_cmd_buffer *cmd_buf; struct netxen_skb_frag *buffrag; int i, j; + struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; - cmd_buf = adapter->cmd_buf_arr; - for (i = 0; i < adapter->num_txd; i++) { + cmd_buf = tx_ring->cmd_buf_arr; + for (i = 0; i < tx_ring->num_desc; i++) { buffrag = cmd_buf->frag_array; if (buffrag->dma) { pci_unmap_single(adapter->pdev, buffrag->dma, @@ -203,6 +204,7 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_tx_ring *tx_ring; int ring; recv_ctx = &adapter->recv_ctx; @@ -214,8 +216,9 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) } } - if (adapter->cmd_buf_arr) - vfree(adapter->cmd_buf_arr); + tx_ring = &adapter->tx_ring; + if (tx_ring->cmd_buf_arr) + vfree(tx_ring->cmd_buf_arr); return; } @@ -224,21 +227,24 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; struct netxen_rx_buffer *rx_buf; int ring, i, num_rx_bufs; struct netxen_cmd_buffer *cmd_buf_arr; struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + tx_ring->num_desc = adapter->num_txd; cmd_buf_arr = - (struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(adapter)); + (struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(tx_ring)); if (cmd_buf_arr == NULL) { - printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n", + dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", netdev->name); return -ENOMEM; } - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(adapter)); - adapter->cmd_buf_arr = cmd_buf_arr; + memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); + tx_ring->cmd_buf_arr = cmd_buf_arr; recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { @@ -307,8 +313,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; sds_ring->irq = adapter->msix_entries[ring].vector; - sds_ring->clean_tx = (ring == 0); - sds_ring->post_rxd = (ring == 0); sds_ring->adapter = adapter; sds_ring->num_desc = adapter->num_rxd; @@ -990,23 +994,24 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) /* Process Command status ring */ int netxen_process_cmd_ring(struct netxen_adapter *adapter) { - u32 last_consumer, consumer; + u32 sw_consumer, hw_consumer; int count = 0, i; struct netxen_cmd_buffer *buffer; struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; struct netxen_skb_frag *frag; int done = 0; + struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; if (!spin_trylock(&adapter->tx_clean_lock)) return 1; - last_consumer = adapter->last_cmd_consumer; - barrier(); /* cmd_consumer can change underneath */ - consumer = le32_to_cpu(*(adapter->cmd_consumer)); + sw_consumer = tx_ring->sw_consumer; + barrier(); /* hw_consumer can change underneath */ + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); - while (last_consumer != consumer) { - buffer = &adapter->cmd_buf_arr[last_consumer]; + while (sw_consumer != hw_consumer) { + buffer = &tx_ring->cmd_buf_arr[sw_consumer]; if (buffer->skb) { frag = &buffer->frag_array[0]; pci_unmap_single(pdev, frag->dma, frag->length, @@ -1024,14 +1029,13 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) buffer->skb = NULL; } - last_consumer = get_next_index(last_consumer, - adapter->num_txd); + sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); if (++count >= MAX_STATUS_HANDLE) break; } if (count) { - adapter->last_cmd_consumer = last_consumer; + tx_ring->sw_consumer = sw_consumer; smp_mb(); if (netif_queue_stopped(netdev) && netif_running(netdev)) { netif_tx_lock(netdev); @@ -1053,9 +1057,9 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) * There is still a possible race condition and the host could miss an * interrupt. The card has to take care of this. */ - barrier(); /* cmd_consumer can change underneath */ - consumer = le32_to_cpu(*(adapter->cmd_consumer)); - done = (last_consumer == consumer); + barrier(); /* hw_consumer can change underneath */ + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); + done = (sw_consumer == hw_consumer); spin_unlock(&adapter->tx_clean_lock); return (done); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 853dee8057d9..22b2d491c782 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -107,10 +107,10 @@ static uint32_t crb_cmd_producer[4] = { void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, - uint32_t crb_producer) + struct nx_host_tx_ring *tx_ring, u32 producer) { adapter->pci_write_normalize(adapter, - adapter->crb_addr_cmd_producer, crb_producer); + tx_ring->crb_cmd_producer, producer); } static uint32_t crb_cmd_consumer[4] = { @@ -120,10 +120,10 @@ static uint32_t crb_cmd_consumer[4] = { static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, - u32 crb_consumer) + struct nx_host_tx_ring *tx_ring, u32 consumer) { adapter->pci_write_normalize(adapter, - adapter->crb_addr_cmd_consumer, crb_consumer); + tx_ring->crb_cmd_consumer, consumer); } static uint32_t msi_tgt_status[8] = { @@ -814,6 +814,7 @@ netxen_nic_attach(struct netxen_adapter *adapter) struct pci_dev *pdev = adapter->pdev; int err, ring; struct nx_host_rds_ring *rds_ring; + struct nx_host_tx_ring *tx_ring; err = netxen_init_firmware(adapter); if (err != 0) { @@ -843,13 +844,12 @@ netxen_nic_attach(struct netxen_adapter *adapter) } if (adapter->fw_major < 4) { - adapter->crb_addr_cmd_producer = - crb_cmd_producer[adapter->portnum]; - adapter->crb_addr_cmd_consumer = - crb_cmd_consumer[adapter->portnum]; + tx_ring = &adapter->tx_ring; + tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum]; + tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum]; - netxen_nic_update_cmd_producer(adapter, 0); - netxen_nic_update_cmd_consumer(adapter, 0); + netxen_nic_update_cmd_producer(adapter, tx_ring, 0); + netxen_nic_update_cmd_consumer(adapter, tx_ring, 0); } for (ring = 0; ring < adapter->max_rds_rings; ring++) { @@ -1304,7 +1304,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct netxen_hardware_context *hw = &adapter->ahw; + struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; unsigned int first_seg_len = skb->len - skb->data_len; struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; @@ -1315,28 +1315,26 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) u32 producer, consumer; int frag_count, no_of_desc; - u32 num_txd = adapter->num_txd; + u32 num_txd = tx_ring->num_desc; bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; - /* There 4 fragments per descriptor */ + /* 4 fragments per cmd des */ no_of_desc = (frag_count + 3) >> 2; - producer = adapter->cmd_producer; + producer = tx_ring->producer; smp_mb(); - consumer = adapter->last_cmd_consumer; + consumer = tx_ring->sw_consumer; if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) { netif_stop_queue(netdev); smp_mb(); return NETDEV_TX_BUSY; } - /* Copy the descriptors into the hardware */ - hwdesc = &hw->cmd_desc_head[producer]; + hwdesc = &tx_ring->desc_head[producer]; netxen_clear_cmddesc((u64 *)hwdesc); - /* Take skb->data itself */ - pbuf = &adapter->cmd_buf_arr[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; is_tso = netxen_tso_check(netdev, hwdesc, skb); @@ -1365,9 +1363,9 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if ((i & 0x3) == 0) { k = 0; producer = get_next_index(producer, num_txd); - hwdesc = &hw->cmd_desc_head[producer]; + hwdesc = &tx_ring->desc_head[producer]; netxen_clear_cmddesc((u64 *)hwdesc); - pbuf = &adapter->cmd_buf_arr[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; } frag = &skb_shinfo(skb)->frags[i - 1]; @@ -1419,8 +1417,8 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) more_hdr = 0; } /* copy the MAC/IP/TCP headers to the cmd descriptor list */ - hwdesc = &hw->cmd_desc_head[producer]; - pbuf = &adapter->cmd_buf_arr[producer]; + hwdesc = &tx_ring->desc_head[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; /* copy the first 64 bytes */ @@ -1429,8 +1427,8 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) producer = get_next_index(producer, num_txd); if (more_hdr) { - hwdesc = &hw->cmd_desc_head[producer]; - pbuf = &adapter->cmd_buf_arr[producer]; + hwdesc = &tx_ring->desc_head[producer]; + pbuf = &tx_ring->cmd_buf_arr[producer]; pbuf->skb = NULL; /* copy the next 64 bytes - should be enough except * for pathological case @@ -1443,10 +1441,10 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } } - adapter->cmd_producer = producer; + tx_ring->producer = producer; adapter->stats.txbytes += skb->len; - netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); + netxen_nic_update_cmd_producer(adapter, tx_ring, producer); adapter->stats.xmitcalled++; netdev->trans_start = jiffies; -- cgit v1.2.3 From 56a007871a6689db80e19f63fe6dc3692daa2a6f Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:41 +0000 Subject: netxen: defer firmware handshake Removed duplicate firmware handshake, defer it until first port (interface) is brought up. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_init.c | 59 ++++++++++++++---------------------- drivers/net/netxen/netxen_nic_main.c | 4 --- 3 files changed, 22 insertions(+), 42 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 2aa658db103f..7e208b31a27e 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1359,7 +1359,6 @@ unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); -int netxen_receive_peg_ready(struct netxen_adapter *adapter); int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 8e45dcc27c7f..9991951e6e05 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -108,42 +108,6 @@ static void crb_addr_transform_setup(void) crb_addr_transform(I2C0); } -int netxen_init_firmware(struct netxen_adapter *adapter) -{ - u32 state = 0, loops = 0, err = 0; - - /* Window 1 call */ - state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE); - - if (state == PHAN_INITIALIZE_ACK) - return 0; - - while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) { - msleep(1); - /* Window 1 call */ - state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE); - - loops++; - } - if (loops >= 2000) { - printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n", - state); - err = -EIO; - return err; - } - /* Window 1 call */ - adapter->pci_write_normalize(adapter, - CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); - adapter->pci_write_normalize(adapter, - CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); - adapter->pci_write_normalize(adapter, - CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); - adapter->pci_write_normalize(adapter, - CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); - - return err; -} - void netxen_release_rx_buffers(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; @@ -789,7 +753,8 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) return 0; } -int netxen_receive_peg_ready(struct netxen_adapter *adapter) +static int +netxen_receive_peg_ready(struct netxen_adapter *adapter) { u32 val = 0; int retries = 2000; @@ -813,6 +778,26 @@ int netxen_receive_peg_ready(struct netxen_adapter *adapter) return 0; } +int netxen_init_firmware(struct netxen_adapter *adapter) +{ + int err; + + err = netxen_receive_peg_ready(adapter); + if (err) + return err; + + adapter->pci_write_normalize(adapter, + CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); + adapter->pci_write_normalize(adapter, + CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); + adapter->pci_write_normalize(adapter, + CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); + adapter->pci_write_normalize(adapter, + CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); + + return err; +} + static int netxen_alloc_rx_skb(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring, diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 22b2d491c782..665fce561d4a 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1027,10 +1027,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_napi_add(adapter, netdev); - err = netxen_receive_peg_ready(adapter); - if (err) - goto err_out_disable_msi; - init_timer(&adapter->watchdog_timer); adapter->watchdog_timer.function = &netxen_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; -- cgit v1.2.3 From 3bf26ce3f4cc3c9e0d0478b4016c6113a16faaf1 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:42 +0000 Subject: netxen: async link event handling Add support for asynchronous events from firmware, received over one of the rx rings. Add support for event based phy interrupts, enhanced links status reporting from firmware. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 108 ++++++++++++++++++++++--------- drivers/net/netxen/netxen_nic_ethtool.c | 32 ++++++++- drivers/net/netxen/netxen_nic_hw.c | 22 +++++++ drivers/net/netxen/netxen_nic_init.c | 102 +++++++++++++++++++++++++++-- drivers/net/netxen/netxen_nic_main.c | 55 ++++++++++------ drivers/net/netxen/netxen_nic_phan_reg.h | 1 + 6 files changed, 263 insertions(+), 57 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 7e208b31a27e..f4d7e2db700b 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -354,6 +354,7 @@ struct rcv_desc { /* opcode field in status_desc */ #define NETXEN_NIC_RXPKT_DESC 0x04 #define NETXEN_OLD_RXPKT_DESC 0x3f +#define NETXEN_NIC_RESPONSE_DESC 0x05 /* for status field in status_desc */ #define STATUS_NEED_CKSUM (1) @@ -363,8 +364,11 @@ struct rcv_desc { #define STATUS_OWNER_HOST (0x1ULL << 56) #define STATUS_OWNER_PHANTOM (0x2ULL << 56) -/* Note: sizeof(status_desc) should always be a mutliple of 2 */ - +/* Status descriptor: + 0-3 port, 4-7 status, 8-11 type, 12-27 total_length + 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset + 53-55 desc_cnt, 56-57 owner, 58-63 opcode + */ #define netxen_get_sts_port(sts_data) \ ((sts_data) & 0x0F) #define netxen_get_sts_status(sts_data) \ @@ -379,35 +383,13 @@ struct rcv_desc { (((sts_data) >> 44) & 0x0F) #define netxen_get_sts_pkt_offset(sts_data) \ (((sts_data) >> 48) & 0x1F) +#define netxen_get_sts_desc_cnt(sts_data) \ + (((sts_data) >> 53) & 0x7) #define netxen_get_sts_opcode(sts_data) \ (((sts_data) >> 58) & 0x03F) struct status_desc { - /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length - 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset - 53-55 desc_cnt, 56-57 owner, 58-63 opcode - */ - __le64 status_desc_data; - union { - struct { - __le32 hash_value; - u8 hash_type; - u8 msg_type; - u8 unused; - union { - /* Bit pattern: 0-6 lro_count indicates frag - * sequence, 7 last_frag indicates last frag - */ - u8 lro; - - /* chained buffers */ - u8 nr_frags; - }; - }; - struct { - __le16 frag_handles[4]; - }; - }; + __le64 status_desc_data[2]; } __attribute__ ((aligned(16))); /* The version of the main data structure */ @@ -1114,6 +1096,66 @@ typedef struct { #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ +#define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) +#define NX_FW_CAPABILITY_SWITCHING (1 << 6) + +/* module types */ +#define LINKEVENT_MODULE_NOT_PRESENT 1 +#define LINKEVENT_MODULE_OPTICAL_UNKNOWN 2 +#define LINKEVENT_MODULE_OPTICAL_SRLR 3 +#define LINKEVENT_MODULE_OPTICAL_LRM 4 +#define LINKEVENT_MODULE_OPTICAL_SFP_1G 5 +#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE 6 +#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN 7 +#define LINKEVENT_MODULE_TWINAX 8 + +#define LINKSPEED_10GBPS 10000 +#define LINKSPEED_1GBPS 1000 +#define LINKSPEED_100MBPS 100 +#define LINKSPEED_10MBPS 10 + +#define LINKSPEED_ENCODED_10MBPS 0 +#define LINKSPEED_ENCODED_100MBPS 1 +#define LINKSPEED_ENCODED_1GBPS 2 + +#define LINKEVENT_AUTONEG_DISABLED 0 +#define LINKEVENT_AUTONEG_ENABLED 1 + +#define LINKEVENT_HALF_DUPLEX 0 +#define LINKEVENT_FULL_DUPLEX 1 + +#define LINKEVENT_LINKSPEED_MBPS 0 +#define LINKEVENT_LINKSPEED_ENCODED 1 + +/* firmware response header: + * 63:58 - message type + * 57:56 - owner + * 55:53 - desc count + * 52:48 - reserved + * 47:40 - completion id + * 39:32 - opcode + * 31:16 - error code + * 15:00 - reserved + */ +#define netxen_get_nic_msgtype(msg_hdr) \ + ((msg_hdr >> 58) & 0x3F) +#define netxen_get_nic_msg_compid(msg_hdr) \ + ((msg_hdr >> 40) & 0xFF) +#define netxen_get_nic_msg_opcode(msg_hdr) \ + ((msg_hdr >> 32) & 0xFF) +#define netxen_get_nic_msg_errcode(msg_hdr) \ + ((msg_hdr >> 16) & 0xFFFF) + +typedef struct { + union { + struct { + u64 hdr; + u64 body[7]; + }; + u64 words[8]; + }; +} nx_fw_msg_t; + typedef struct { __le64 qhdr; __le64 req_hdr; @@ -1177,15 +1219,21 @@ struct netxen_adapter { u8 mc_enabled; u8 max_mc_count; + u16 resv2; + u32 resv3; + + u8 has_link_events; + u8 resv1; u16 tx_context_id; u16 mtu; u16 is_up; + u16 link_speed; u16 link_duplex; u16 link_autoneg; - u16 resv1; + u16 module_type; - u32 resv2; + u32 capabilities; u32 flags; u32 irq; u32 temp; @@ -1398,6 +1446,8 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); int netxen_config_rss(struct netxen_adapter *adapter, int enable); +int netxen_linkevent_request(struct netxen_adapter *adapter, int enable); +void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index fe910c1715d6..5fde9e088a94 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -110,6 +110,7 @@ static int netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_adapter *adapter = netdev_priv(dev); + int check_sfp_module = 0; /* read which mode */ if (adapter->ahw.port_type == NETXEN_NIC_GBE) { @@ -143,6 +144,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->advertising = ADVERTISED_10000baseT_Full; } + if (netif_running(dev) && adapter->has_link_events) { + ecmd->speed = adapter->link_speed; + ecmd->autoneg = adapter->link_autoneg; + ecmd->duplex = adapter->link_duplex; + goto skip; + } + ecmd->port = PORT_TP; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { @@ -160,6 +168,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else return -EIO; +skip: ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; @@ -190,7 +199,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) case NETXEN_BRDTYPE_P3_HMEZ: ecmd->supported |= SUPPORTED_MII; ecmd->advertising |= ADVERTISED_MII; - ecmd->port = PORT_FIBRE; + ecmd->port = PORT_MII; ecmd->autoneg = AUTONEG_DISABLE; break; case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: @@ -198,6 +207,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) case NETXEN_BRDTYPE_P3_10G_SFP_QT: ecmd->advertising |= ADVERTISED_TP; ecmd->supported |= SUPPORTED_TP; + check_sfp_module = netif_running(dev) && + adapter->has_link_events; case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_XFP: ecmd->supported |= SUPPORTED_FIBRE; @@ -212,6 +223,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP); ecmd->port = PORT_FIBRE; + check_sfp_module = netif_running(dev) && + adapter->has_link_events; } else { ecmd->autoneg = AUTONEG_ENABLE; ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); @@ -226,6 +239,23 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) return -EIO; } + if (check_sfp_module) { + switch (adapter->module_type) { + case LINKEVENT_MODULE_OPTICAL_UNKNOWN: + case LINKEVENT_MODULE_OPTICAL_SRLR: + case LINKEVENT_MODULE_OPTICAL_LRM: + case LINKEVENT_MODULE_OPTICAL_SFP_1G: + ecmd->port = PORT_FIBRE; + break; + case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: + case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: + case LINKEVENT_MODULE_TWINAX: + ecmd->port = PORT_TP; + default: + ecmd->port = -1; + } + } + return 0; } diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 8416962cc9ac..33444a20e4f7 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -731,6 +731,28 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable) return rv; } +int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) +{ + nx_nic_req_t req; + u64 word; + int rv; + + memset(&req, 0, sizeof(nx_nic_req_t)); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + req.words[0] = cpu_to_le64(enable); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not configure link notification\n", + adapter->netdev->name); + } + + return rv; +} + /* * netxen_nic_change_mtu - Change the Maximum Transfer Unit * @returns 0 on success, negative on failure diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 9991951e6e05..974783c45321 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -795,9 +795,81 @@ int netxen_init_firmware(struct netxen_adapter *adapter) adapter->pci_write_normalize(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); + if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { + adapter->capabilities = netxen_nic_reg_read(adapter, + CRB_FW_CAPABILITIES_1); + } + return err; } +static void +netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) +{ + u32 cable_OUI; + u16 cable_len; + u16 link_speed; + u8 link_status, module, duplex, autoneg; + struct net_device *netdev = adapter->netdev; + + adapter->has_link_events = 1; + + cable_OUI = msg->body[1] & 0xffffffff; + cable_len = (msg->body[1] >> 32) & 0xffff; + link_speed = (msg->body[1] >> 48) & 0xffff; + + link_status = msg->body[2] & 0xff; + duplex = (msg->body[2] >> 16) & 0xff; + autoneg = (msg->body[2] >> 24) & 0xff; + + module = (msg->body[2] >> 8) & 0xff; + if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) { + printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n", + netdev->name, cable_OUI, cable_len); + } else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) { + printk(KERN_INFO "%s: unsupported cable length %d\n", + netdev->name, cable_len); + } + + netxen_advert_link_change(adapter, link_status); + + /* update link parameters */ + if (duplex == LINKEVENT_FULL_DUPLEX) + adapter->link_duplex = DUPLEX_FULL; + else + adapter->link_duplex = DUPLEX_HALF; + adapter->module_type = module; + adapter->link_autoneg = autoneg; + adapter->link_speed = link_speed; +} + +static void +netxen_handle_fw_message(int desc_cnt, int index, + struct nx_host_sds_ring *sds_ring) +{ + nx_fw_msg_t msg; + struct status_desc *desc; + int i = 0, opcode; + + while (desc_cnt > 0 && i < 8) { + desc = &sds_ring->desc_head[index]; + msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); + msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); + + index = get_next_index(index, sds_ring->num_desc); + desc_cnt--; + } + + opcode = netxen_get_nic_msg_opcode(msg.body[0]); + switch (opcode) { + case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: + netxen_handle_linkevent(sds_ring->adapter, &msg); + break; + default: + break; + } +} + static int netxen_alloc_rx_skb(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring, @@ -916,21 +988,35 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) int count = 0; u64 sts_data; - int opcode, ring, index, length, cksum, pkt_offset; + int opcode, ring, index, length, cksum, pkt_offset, desc_cnt; while (count < max) { desc = &sds_ring->desc_head[consumer]; - sts_data = le64_to_cpu(desc->status_desc_data); + sts_data = le64_to_cpu(desc->status_desc_data[0]); if (!(sts_data & STATUS_OWNER_HOST)) break; + desc_cnt = netxen_get_sts_desc_cnt(sts_data); ring = netxen_get_sts_type(sts_data); + if (ring > RCV_RING_JUMBO) - continue; + goto skip; opcode = netxen_get_sts_opcode(sts_data); + switch (opcode) { + case NETXEN_NIC_RXPKT_DESC: + case NETXEN_OLD_RXPKT_DESC: + break; + case NETXEN_NIC_RESPONSE_DESC: + netxen_handle_fw_message(desc_cnt, consumer, sds_ring); + default: + goto skip; + } + + WARN_ON(desc_cnt > 1); + index = netxen_get_sts_refhandle(sts_data); length = netxen_get_sts_totallength(sts_data); cksum = netxen_get_sts_status(sts_data); @@ -942,9 +1028,13 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) if (rxbuf) list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); - desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); - - consumer = get_next_index(consumer, sds_ring->num_desc); +skip: + for (; desc_cnt > 0; desc_cnt--) { + desc = &sds_ring->desc_head[consumer]; + desc->status_desc_data[0] = + cpu_to_le64(STATUS_OWNER_PHANTOM); + consumer = get_next_index(consumer, sds_ring->num_desc); + } count++; } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 665fce561d4a..bd93296be4dd 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -787,6 +787,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) if (adapter->max_sds_rings > 1) netxen_config_rss(adapter, 1); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_linkevent_request(adapter, 1); + return 0; } @@ -1493,26 +1496,9 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) return rv; } -static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) +void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) { struct net_device *netdev = adapter->netdev; - u32 val, port, linkup; - - port = adapter->physical_port; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3); - val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); - linkup = (val == XG_LINK_UP_P3); - } else { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); - if (adapter->ahw.port_type == NETXEN_NIC_GBE) - linkup = (val >> port) & 1; - else { - val = (val >> port*8) & 0xff; - linkup = (val == XG_LINK_UP); - } - } if (adapter->ahw.linkup && !linkup) { printk(KERN_INFO "%s: %s NIC Link is down\n", @@ -1523,7 +1509,9 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_stop_queue(netdev); } - netxen_nic_set_link_parameters(adapter); + if (!adapter->has_link_events) + netxen_nic_set_link_parameters(adapter); + } else if (!adapter->ahw.linkup && linkup) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); @@ -1533,10 +1521,34 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_wake_queue(netdev); } - netxen_nic_set_link_parameters(adapter); + if (!adapter->has_link_events) + netxen_nic_set_link_parameters(adapter); } } +static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) +{ + u32 val, port, linkup; + + port = adapter->physical_port; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3); + val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); + linkup = (val == XG_LINK_UP_P3); + } else { + val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); + if (adapter->ahw.port_type == NETXEN_NIC_GBE) + linkup = (val >> port) & 1; + else { + val = (val >> port*8) & 0xff; + linkup = (val == XG_LINK_UP); + } + } + + netxen_advert_link_change(adapter, linkup); +} + static void netxen_watchdog(unsigned long v) { struct netxen_adapter *adapter = (struct netxen_adapter *)v; @@ -1552,7 +1564,8 @@ void netxen_watchdog_task(struct work_struct *work) if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) return; - netxen_nic_handle_phy_intr(adapter); + if (!adapter->has_link_events) + netxen_nic_handle_phy_intr(adapter); if (netif_running(adapter->netdev)) mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 18ea35d51160..ecd622ead0e9 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -134,6 +134,7 @@ #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) #define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) +#define CRB_FW_CAPABILITIES_1 NETXEN_NIC_REG(0x128) #define INTR_SCHEME_PERPORT 0x1 #define MSI_MODE_MULTIFUNC 0x1 -- cgit v1.2.3 From 71dcddbdd35487eb931aa8aab28a2df474008754 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:43 +0000 Subject: netxen: allocate status rings dynamically This reduces netxen_adapter footprint when rss (msi-x) is disabled. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 10 +++++----- drivers/net/netxen/netxen_nic_main.c | 26 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f4d7e2db700b..e0f329ff3691 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -762,7 +762,7 @@ struct netxen_recv_context { u16 virt_port; struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS]; - struct nx_host_sds_ring sds_rings[NUM_STS_DESC_RINGS]; + struct nx_host_sds_ring *sds_rings; }; /* New HW context creation */ @@ -1203,10 +1203,10 @@ struct netxen_adapter { spinlock_t tx_clean_lock; - u32 num_txd; - u32 num_rxd; - u32 num_jumbo_rxd; - u32 num_lro_rxd; + u16 num_txd; + u16 num_rxd; + u16 num_jumbo_rxd; + u16 num_lro_rxd; u8 max_rds_rings; u8 max_sds_rings; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index bd93296be4dd..cbd47ae694ba 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -153,7 +153,24 @@ static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) adapter->legacy_intr.tgt_mask_reg, 0xfbff); } +static int +netxen_alloc_sds_rings(struct netxen_recv_context *recv_ctx, int count) +{ + int size = sizeof(struct nx_host_sds_ring) * count; + + recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL); + + return (recv_ctx->sds_rings == NULL); +} + static void +netxen_free_sds_rings(struct netxen_recv_context *recv_ctx) +{ + if (recv_ctx->sds_rings != NULL) + kfree(recv_ctx->sds_rings); +} + +static int netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) { int ring; @@ -165,11 +182,16 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) else adapter->max_sds_rings = 1; + if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) + return 1; + for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; netif_napi_add(netdev, &sds_ring->napi, netxen_nic_poll, NETXEN_NETDEV_WEIGHT); } + + return 0; } static void @@ -1028,7 +1050,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->irq = adapter->msix_entries[0].vector; - netxen_napi_add(adapter, netdev); + if (netxen_napi_add(adapter, netdev)) + goto err_out_disable_msi; init_timer(&adapter->watchdog_timer); adapter->watchdog_timer.function = &netxen_watchdog; @@ -1110,6 +1133,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_free_adapter_offload(adapter); netxen_teardown_intr(adapter); + netxen_free_sds_rings(&adapter->recv_ctx); netxen_cleanup_pci_map(adapter); -- cgit v1.2.3 From 1fbe63235893e5dce28fe91d8465dd231b0cb3d9 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:44 +0000 Subject: netxen: annotate register access functions o remove unnecessary length parameter since register access width is fixed 4 byte. o remove superfluous pci_read_normalize and pci_write_normalize functions. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 75 ++--------- drivers/net/netxen/netxen_nic_ctx.c | 18 ++- drivers/net/netxen/netxen_nic_ethtool.c | 45 +++---- drivers/net/netxen/netxen_nic_hw.c | 229 ++++++++++++++------------------ drivers/net/netxen/netxen_nic_init.c | 40 +++--- drivers/net/netxen/netxen_nic_main.c | 66 +++++---- drivers/net/netxen/netxen_nic_niu.c | 110 +++++++-------- 7 files changed, 239 insertions(+), 344 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index e0f329ff3691..1e4190dd0c16 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1258,14 +1258,12 @@ struct netxen_adapter { int (*init_port) (struct netxen_adapter *, int); int (*stop_port) (struct netxen_adapter *); - int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int); - int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int); + u32 (*hw_read_wx)(struct netxen_adapter *, ulong); + int (*hw_write_wx)(struct netxen_adapter *, ulong, u32); int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int); int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int); int (*pci_write_immediate)(struct netxen_adapter *, u64, u32); u32 (*pci_read_immediate)(struct netxen_adapter *, u64); - void (*pci_write_normalize)(struct netxen_adapter *, u64, u32); - u32 (*pci_read_normalize)(struct netxen_adapter *, u64); unsigned long (*pci_set_window)(struct netxen_adapter *, unsigned long long); @@ -1302,46 +1300,6 @@ struct netxen_adapter { #define netxen_get_dma_watchdog_disabled(config_word) \ (((config_word) >> 1) & 0x1) -/* Max number of xmit producer threads that can run simultaneously */ -#define MAX_XMIT_PRODUCERS 16 - -#define PCI_OFFSET_FIRST_RANGE(adapter, off) \ - ((adapter)->ahw.pci_base0 + (off)) -#define PCI_OFFSET_SECOND_RANGE(adapter, off) \ - ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START) -#define PCI_OFFSET_THIRD_RANGE(adapter, off) \ - ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START) - -static inline void __iomem *pci_base_offset(struct netxen_adapter *adapter, - unsigned long off) -{ - if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) { - return (adapter->ahw.pci_base0 + off); - } else if ((off < SECOND_PAGE_GROUP_END) && - (off >= SECOND_PAGE_GROUP_START)) { - return (adapter->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START); - } else if ((off < THIRD_PAGE_GROUP_END) && - (off >= THIRD_PAGE_GROUP_START)) { - return (adapter->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START); - } - return NULL; -} - -static inline void __iomem *pci_base(struct netxen_adapter *adapter, - unsigned long off) -{ - if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) { - return adapter->ahw.pci_base0; - } else if ((off < SECOND_PAGE_GROUP_END) && - (off >= SECOND_PAGE_GROUP_START)) { - return adapter->ahw.pci_base1; - } else if ((off < THIRD_PAGE_GROUP_END) && - (off >= THIRD_PAGE_GROUP_START)) { - return adapter->ahw.pci_base2; - } - return NULL; -} - int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter); int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter); int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter); @@ -1357,18 +1315,17 @@ int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu); void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val); int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off); void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value); -void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value); +u32 netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index); void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value); -void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value); +u32 netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index); int netxen_nic_get_board_info(struct netxen_adapter *adapter); void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); int netxen_nic_wol_supported(struct netxen_adapter *adapter); -int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len); +u32 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off); int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len); + ulong off, u32 data); int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, u64 off, void *data, int size); int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, @@ -1384,10 +1341,9 @@ unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw); -int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len); +u32 netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off); int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len); + ulong off, u32 data); int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, u64 off, void *data, int size); int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, @@ -1514,9 +1470,8 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter) u32 ctrl; /* check if already inactive */ - if (adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) - printk(KERN_ERR "failed to read dma watchdog status\n"); + ctrl = adapter->hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); if (netxen_get_dma_watchdog_enabled(ctrl) == 0) return 1; @@ -1534,9 +1489,8 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) { u32 ctrl; - if (adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) - printk(KERN_ERR "failed to read dma watchdog status\n"); + ctrl = adapter->hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); return (netxen_get_dma_watchdog_enabled(ctrl) == 0); } @@ -1546,9 +1500,8 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) { u32 ctrl; - if (adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) - printk(KERN_ERR "failed to read dma watchdog status\n"); + ctrl = adapter->hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); if (netxen_get_dma_watchdog_enabled(ctrl)) return 1; diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 794335188a26..7a13ee8144ee 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -41,8 +41,8 @@ netxen_api_lock(struct netxen_adapter *adapter) for (;;) { /* Acquire PCIE HW semaphore5 */ - netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done); + done = netxen_nic_read_w0(adapter, + NETXEN_PCIE_REG(PCIE_SEM5_LOCK)); if (done == 1) break; @@ -65,11 +65,9 @@ netxen_api_lock(struct netxen_adapter *adapter) static int netxen_api_unlock(struct netxen_adapter *adapter) { - u32 val; - /* Release PCIE HW semaphore5 */ netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val); + NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK)); return 0; } @@ -86,7 +84,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter) if (++timeout > NX_OS_CRB_RETRY_COUNT) return NX_CDRP_RSP_TIMEOUT; - netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp); + rsp = netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET); } while (!NX_CDRP_IS_RSP(rsp)); return rsp; @@ -125,7 +123,7 @@ netxen_issue_cmd(struct netxen_adapter *adapter, rcode = NX_RCODE_TIMEOUT; } else if (rsp == NX_CDRP_RSP_FAIL) { - netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode); + rcode = netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET); printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); @@ -517,11 +515,11 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc); - adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id), + adapter->hw_write_wx(adapter, CRB_CTX_ADDR_REG_LO(func_id), lower32(adapter->ctx_desc_phys_addr)); - adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id), + adapter->hw_write_wx(adapter, CRB_CTX_ADDR_REG_HI(func_id), upper32(adapter->ctx_desc_phys_addr)); - adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id), + adapter->hw_write_wx(adapter, CRB_CTX_SIGNATURE_REG(func_id), NETXEN_CTX_SIGNATURE | func_id); return 0; } diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 5fde9e088a94..6c5a111e80bf 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -92,11 +92,11 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) strncpy(drvinfo->driver, netxen_nic_driver_name, 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); write_lock_irqsave(&adapter->adapter_lock, flags); - fw_major = adapter->pci_read_normalize(adapter, + fw_major = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR); - fw_minor = adapter->pci_read_normalize(adapter, + fw_minor = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR); - fw_build = adapter->pci_read_normalize(adapter, + fw_build = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB); write_unlock_irqrestore(&adapter->adapter_lock, flags); sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); @@ -135,7 +135,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { u32 val; - adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &val, 4); + val = adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR); if (val == NETXEN_PORT_MODE_802_3_AP) { ecmd->supported = SUPPORTED_1000baseT_Full; ecmd->advertising = ADVERTISED_1000baseT_Full; @@ -156,8 +156,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { u16 pcifn = adapter->ahw.pci_func; - adapter->hw_read_wx(adapter, - P3_LINK_SPEED_REG(pcifn), &val, 4); + val = adapter->hw_read_wx(adapter, + P3_LINK_SPEED_REG(pcifn)); ecmd->speed = P3_LINK_SPEED_MHZ * P3_LINK_SPEED_VAL(pcifn, val); } else @@ -423,12 +423,12 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) | (adapter->pdev)->device; /* which mode */ - adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, ®s_buff[0], 4); + regs_buff[0] = adapter->hw_read_wx(adapter, NETXEN_NIU_MODE); mode = regs_buff[0]; /* Common registers to all the modes */ - adapter->hw_read_wx(adapter, - NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, ®s_buff[2], 4); + regs_buff[2] = adapter->hw_read_wx(adapter, + NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER); /* GB/XGB Mode */ mode = (mode / 2) - 1; window = 0; @@ -439,9 +439,8 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) window = adapter->physical_port * NETXEN_NIC_PORT_WINDOW; - adapter->hw_read_wx(adapter, - niu_registers[mode].reg[i - 3] + window, - ®s_buff[i], 4); + regs_buff[i] = adapter->hw_read_wx(adapter, + niu_registers[mode].reg[i - 3] + window); } } @@ -465,7 +464,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) return !val; } } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); + val = adapter->hw_read_wx(adapter, CRB_XG_STATE); return (val == XG_LINK_UP) ? 0 : 1; } return -EIO; @@ -529,10 +528,10 @@ netxen_nic_get_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ - netxen_nic_read_w0(adapter,NETXEN_NIU_GB_MAC_CONFIG_0(port), - &val); + val = netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port)); pause->rx_pause = netxen_gb_get_rx_flowctl(val); - netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val); + val = netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { case 0: pause->tx_pause = !(netxen_gb_get_gb0_mask(val)); @@ -552,7 +551,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; - netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val); + val = netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) pause->tx_pause = !(netxen_xg_get_xg0_mask(val)); else @@ -575,8 +574,8 @@ netxen_nic_set_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ - netxen_nic_read_w0(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), &val); + val = netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port)); if (pause->rx_pause) netxen_gb_rx_flowctl(val); @@ -586,7 +585,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), val); /* set autoneg */ - netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val); + val = netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { case 0: if (pause->tx_pause) @@ -618,7 +617,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return -EIO; - netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val); + val = netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) { if (pause->tx_pause) netxen_xg_unset_xg0_mask(val); @@ -644,14 +643,14 @@ static int netxen_nic_reg_test(struct net_device *dev) struct netxen_adapter *adapter = netdev_priv(dev); u32 data_read, data_written; - netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read); + data_read = netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0)); if ((data_read & 0xffff) != PHAN_VENDOR_ID) return 1; data_written = (u32)0xa5a5a5a5; netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written); - data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST); + data_read = adapter->hw_read_wx(adapter, CRB_SCRATCHPAD_TEST); if (data_written != data_read) return 1; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 33444a20e4f7..87cda65ef66b 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -63,6 +63,31 @@ static inline void writeq(u64 val, void __iomem *addr) } #endif +#define ADDR_IN_RANGE(addr, low, high) \ + (((addr) < (high)) && ((addr) >= (low))) + +#define PCI_OFFSET_FIRST_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base0 + (off)) +#define PCI_OFFSET_SECOND_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START) +#define PCI_OFFSET_THIRD_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START) + +static void __iomem *pci_base_offset(struct netxen_adapter *adapter, + unsigned long off) +{ + if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END)) + return PCI_OFFSET_FIRST_RANGE(adapter, off); + + if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END)) + return PCI_OFFSET_SECOND_RANGE(adapter, off); + + if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END)) + return PCI_OFFSET_THIRD_RANGE(adapter, off); + + return NULL; +} + #define CRB_WIN_LOCK_TIMEOUT 100000000 static crb_128M_2M_block_map_t crb_128M_2M_map[64] = { {{{0, 0, 0, 0} } }, /* 0: PCI */ @@ -294,18 +319,8 @@ static unsigned crb_hub_agt[64] = /* PCI Windowing for DDR regions. */ -#define ADDR_IN_RANGE(addr, low, high) \ - (((addr) <= (high)) && ((addr) >= (low))) - #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ -#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL -#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL -#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL -#define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL - -#define NETXEN_NIC_WINDOW_MARGIN 0x100000 - int netxen_nic_set_mac(struct net_device *netdev, void *p) { struct netxen_adapter *adapter = netdev_priv(netdev); @@ -346,9 +361,9 @@ netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter) if (adapter->mc_enabled) return 0; - adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + val = adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG); val |= (1UL << (28+port)); - adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); /* add broadcast addr to filter */ val = 0xffffff; @@ -377,9 +392,9 @@ netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter) if (!adapter->mc_enabled) return 0; - adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + val = adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG); val &= ~(1UL << (28+port)); - adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4); + adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); val = MAC_HI(addr); netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); @@ -848,8 +863,8 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); - adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4); - adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4); + mac_lo = adapter->hw_read_wx(adapter, crbaddr); + mac_hi = adapter->hw_read_wx(adapter, crbaddr+4); if (pci_func & 1) *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); @@ -867,8 +882,8 @@ static int crb_win_lock(struct netxen_adapter *adapter) while (!done) { /* acquire semaphore3 from PCI HW block */ - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4); + done = adapter->hw_read_wx(adapter, + NETXEN_PCIE_REG(PCIE_SEM7_LOCK)); if (done == 1) break; if (timeout >= CRB_WIN_LOCK_TIMEOUT) @@ -885,8 +900,8 @@ static void crb_win_unlock(struct netxen_adapter *adapter) { int val; - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4); + val = adapter->hw_read_wx(adapter, + NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK)); } /* @@ -1022,7 +1037,7 @@ netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, dev_info(&pdev->dev, "loading firmware from flash\n"); if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); if (fw) { @@ -1075,12 +1090,12 @@ netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, msleep(1); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); else { - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); } @@ -1168,8 +1183,8 @@ request_mn: netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&flashed_ver); if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { - adapter->hw_read_wx(adapter, - NX_PEG_TUNE_CAPABILITY, &capability, 4); + capability = adapter->hw_read_wx(adapter, + NX_PEG_TUNE_CAPABILITY); if (capability & NX_PEG_TUNE_MN_PRESENT) { fw_type = NX_P3_MN_ROMIMAGE; goto request_fw; @@ -1209,13 +1224,10 @@ load_fw: } int -netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) { void __iomem *addr; - BUG_ON(len != 4); - if (ADDR_IN_WINDOW1(off)) { addr = NETXEN_CRB_NORMALIZE(adapter, off); } else { /* Window 0 */ @@ -1228,7 +1240,7 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, return 1; } - writel(*(u32 *) data, addr); + writel(data, addr); if (!ADDR_IN_WINDOW1(off)) netxen_nic_pci_change_crbwindow_128M(adapter, 1); @@ -1236,13 +1248,11 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, return 0; } -int -netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +u32 +netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) { void __iomem *addr; - - BUG_ON(len != 4); + u32 data; if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ addr = NETXEN_CRB_NORMALIZE(adapter, off); @@ -1256,24 +1266,21 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, return 1; } - *(u32 *)data = readl(addr); + data = readl(addr); if (!ADDR_IN_WINDOW1(off)) netxen_nic_pci_change_crbwindow_128M(adapter, 1); - return 0; + return data; } int -netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) { unsigned long flags = 0; int rv; - BUG_ON(len != 4); - - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, 4); if (rv == -1) { printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", @@ -1286,26 +1293,24 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, write_lock_irqsave(&adapter->adapter_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); - writel(*(uint32_t *)data, (void __iomem *)off); + writel(data, (void __iomem *)off); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->adapter_lock, flags); } else - writel(*(uint32_t *)data, (void __iomem *)off); + writel(data, (void __iomem *)off); return 0; } -int -netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, - ulong off, void *data, int len) +u32 +netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) { unsigned long flags = 0; int rv; + u32 data; - BUG_ON(len != 4); - - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, 4); if (rv == -1) { printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", @@ -1318,47 +1323,45 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, write_lock_irqsave(&adapter->adapter_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); - *(uint32_t *)data = readl((void __iomem *)off); + data = readl((void __iomem *)off); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->adapter_lock, flags); } else - *(uint32_t *)data = readl((void __iomem *)off); + data = readl((void __iomem *)off); - return 0; + return data; } void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) { - adapter->hw_write_wx(adapter, off, &val, 4); + adapter->hw_write_wx(adapter, off, val); } int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) { - int val; - adapter->hw_read_wx(adapter, off, &val, 4); - return val; + return adapter->hw_read_wx(adapter, off); } /* Change the window to 0, write and change back to window 1. */ void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) { - adapter->hw_write_wx(adapter, index, &value, 4); + adapter->hw_write_wx(adapter, index, value); } /* Change the window to 0, read and change back to window 1. */ -void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value) +u32 netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index) { - adapter->hw_read_wx(adapter, index, value, 4); + return adapter->hw_read_wx(adapter, index); } void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value) { - adapter->hw_write_wx(adapter, index, &value, 4); + adapter->hw_write_wx(adapter, index, value); } -void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value) +u32 netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index) { - adapter->hw_read_wx(adapter, index, value, 4); + return adapter->hw_read_wx(adapter, index); } /* @@ -1461,17 +1464,6 @@ u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off) return readl((void __iomem *)(pci_base_offset(adapter, off))); } -void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter, - u64 off, u32 data) -{ - writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); -} - -u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off) -{ - return readl(NETXEN_CRB_NORMALIZE(adapter, off)); -} - unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, unsigned long long addr) @@ -1485,10 +1477,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, adapter->ahw.ddr_mn_window = window; adapter->hw_write_wx(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &window, 4); - adapter->hw_read_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &win_read, 4); + window); + win_read = adapter->hw_read_wx(adapter, + adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); if ((win_read << 17) != window) { printk(KERN_INFO "Written MNwin (0x%x) != " "Read MNwin (0x%x)\n", window, win_read); @@ -1505,10 +1496,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, adapter->ahw.ddr_mn_window = window; adapter->hw_write_wx(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &window, 4); - adapter->hw_read_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - &win_read, 4); + window); + win_read = adapter->hw_read_wx(adapter, + adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); if ((win_read >> 7) != window) { printk(KERN_INFO "%s: Written OCMwin (0x%x) != " "Read OCMwin (0x%x)\n", @@ -1523,10 +1513,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, adapter->ahw.qdr_sn_window = window; adapter->hw_write_wx(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, - &window, 4); - adapter->hw_read_wx(adapter, - adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, - &win_read, 4); + window); + win_read = adapter->hw_read_wx(adapter, + adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE); if (win_read != window) { printk(KERN_INFO "%s: Written MSwin (0x%x) != " "Read MSwin (0x%x)\n", @@ -1973,26 +1962,26 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { temp = off8 + (i << 3); adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4); + mem_crb+MIU_TEST_AGT_ADDR_LO, temp); temp = 0; adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4); + mem_crb+MIU_TEST_AGT_ADDR_HI, temp); temp = word[i] & 0xffffffff; adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4); + mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); temp = (word[i] >> 32) & 0xffffffff; adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4); + mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_CTRL, &temp, 4); + mem_crb+MIU_TEST_AGT_CTRL, temp); temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_CTRL, &temp, 4); + mem_crb+MIU_TEST_AGT_CTRL, temp); for (j = 0; j < MAX_CTL_CHECK; j++) { - adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + temp = adapter->hw_read_wx(adapter, + mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -2050,20 +2039,20 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { temp = off8 + (i << 3); adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4); + mem_crb + MIU_TEST_AGT_ADDR_LO, temp); temp = 0; adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4); + mem_crb + MIU_TEST_AGT_ADDR_HI, temp); temp = MIU_TA_CTL_ENABLE; adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + mem_crb + MIU_TEST_AGT_CTRL, temp); temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + mem_crb + MIU_TEST_AGT_CTRL, temp); for (j = 0; j < MAX_CTL_CHECK; j++) { - adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, &temp, 4); + temp = adapter->hw_read_wx(adapter, + mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -2078,8 +2067,8 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, start = off0[i] >> 2; end = (off0[i] + sz[i] - 1) >> 2; for (k = start; k <= end; k++) { - adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4); + temp = adapter->hw_read_wx(adapter, + mem_crb + MIU_TEST_AGT_RDDATA(k)); word[i] |= ((uint64_t)temp << (32 * k)); } } @@ -2122,29 +2111,14 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, u64 off, u32 data) { - adapter->hw_write_wx(adapter, off, &data, 4); + adapter->hw_write_wx(adapter, off, data); return 0; } u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off) { - u32 temp; - adapter->hw_read_wx(adapter, off, &temp, 4); - return temp; -} - -void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter, - u64 off, u32 data) -{ - adapter->hw_write_wx(adapter, off, &data, 4); -} - -u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off) -{ - u32 temp; - adapter->hw_read_wx(adapter, off, &temp, 4); - return temp; + return adapter->hw_read_wx(adapter, off); } int netxen_nic_get_board_info(struct netxen_adapter *adapter) @@ -2253,7 +2227,7 @@ void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, int data) { - adapter->hw_write_wx(adapter, off, &data, 4); + adapter->hw_write_wx(adapter, off, data); } void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) @@ -2270,8 +2244,8 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) } if (adapter->ahw.port_type == NETXEN_NIC_GBE) { - adapter->hw_read_wx(adapter, - NETXEN_PORT_MODE_ADDR, &port_mode, 4); + port_mode = adapter->hw_read_wx(adapter, + NETXEN_PORT_MODE_ADDR); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { adapter->link_speed = SPEED_1000; adapter->link_duplex = DUPLEX_FULL; @@ -2348,9 +2322,9 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) addr += sizeof(u32); } - adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4); - adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4); - adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4); + fw_major = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR); + fw_minor = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR); + fw_build = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB); adapter->fw_major = fw_major; adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); @@ -2373,8 +2347,7 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) fw_major, fw_minor, fw_build); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - adapter->hw_read_wx(adapter, - NETXEN_MIU_MN_CONTROL, &i, 4); + i = adapter->hw_read_wx(adapter, NETXEN_MIU_MN_CONTROL); adapter->ahw.cut_through = (i & 0x4) ? 1 : 0; dev_info(&pdev->dev, "firmware running in %s mode\n", adapter->ahw.cut_through ? "cut-through" : "legacy"); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 974783c45321..83116c2817b0 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -368,8 +368,8 @@ static int rom_lock(struct netxen_adapter *adapter) while (!done) { /* acquire semaphore2 from PCI HW block */ - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK), - &done); + done = netxen_nic_read_w0(adapter, + NETXEN_PCIE_REG(PCIE_SEM2_LOCK)); if (done == 1) break; if (timeout >= rom_lock_timeout) @@ -411,10 +411,8 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) static void netxen_rom_unlock(struct netxen_adapter *adapter) { - u32 val; - /* release semaphore2 */ - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val); + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK)); } @@ -623,7 +621,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } } - adapter->hw_write_wx(adapter, off, &buf[i].data, 4); + adapter->hw_write_wx(adapter, off, buf[i].data); msleep(init_delay); } @@ -633,8 +631,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* unreset_net_cache */ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, &val, 4); + val = adapter->hw_read_wx(adapter, + NETXEN_ROMUSB_GLB_SW_RESET); netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f)); } @@ -683,12 +681,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) hi = (addr >> 32) & 0xffffffff; lo = addr & 0xffffffff; - adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); - adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); + adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); + adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { uint32_t temp = 0; - adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4); + adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, temp); } return 0; @@ -730,7 +728,7 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) if (!pegtune_val) { do { - val = adapter->pci_read_normalize(adapter, + val = adapter->hw_read_wx(adapter, CRB_CMDPEG_STATE); if (val == PHAN_INITIALIZE_COMPLETE || @@ -742,7 +740,7 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) } while (--retries); if (!retries) { - pegtune_val = adapter->pci_read_normalize(adapter, + pegtune_val = adapter->hw_read_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE); printk(KERN_WARNING "netxen_phantom_init: init failed, " "pegtune_val=%x\n", pegtune_val); @@ -760,7 +758,7 @@ netxen_receive_peg_ready(struct netxen_adapter *adapter) int retries = 2000; do { - val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE); + val = adapter->hw_read_wx(adapter, CRB_RCVPEG_STATE); if (val == PHAN_PEG_RCV_INITIALIZED) return 0; @@ -786,13 +784,13 @@ int netxen_init_firmware(struct netxen_adapter *adapter) if (err) return err; - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { @@ -1059,7 +1057,7 @@ skip: if (count) { sds_ring->consumer = consumer; - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, sds_ring->crb_sts_consumer, consumer); } @@ -1178,7 +1176,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, if (count) { rds_ring->producer = producer; - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, rds_ring->crb_rcv_producer, (producer-1) & (rds_ring->num_desc-1)); @@ -1239,7 +1237,7 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, if (count) { rds_ring->producer = producer; - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, rds_ring->crb_rcv_producer, (producer - 1) & (rds_ring->num_desc - 1)); wmb(); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cbd47ae694ba..31966a044900 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -109,7 +109,7 @@ void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring, u32 producer) { - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, tx_ring->crb_cmd_producer, producer); } @@ -122,7 +122,7 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring, u32 consumer) { - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, tx_ring->crb_cmd_consumer, consumer); } @@ -139,14 +139,14 @@ static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0); + adapter->hw_write_wx(adapter, sds_ring->crb_intr_mask, 0); } static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1); + adapter->hw_write_wx(adapter, sds_ring->crb_intr_mask, 0x1); if (!NETXEN_IS_MSI_FAMILY(adapter)) adapter->pci_write_immediate(adapter, @@ -309,42 +309,41 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) if (first_boot == 0x55555555) { /* This is the first boot after power up */ - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 0; /* PCI bus master workaround */ - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(0x4), &first_boot, 4); + first_boot = adapter->hw_read_wx(adapter, NETXEN_PCIE_REG(0x4)); if (!(first_boot & 0x4)) { first_boot |= 0x4; adapter->hw_write_wx(adapter, - NETXEN_PCIE_REG(0x4), &first_boot, 4); - adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(0x4), &first_boot, 4); + NETXEN_PCIE_REG(0x4), first_boot); + first_boot = adapter->hw_read_wx(adapter, + NETXEN_PCIE_REG(0x4)); } /* This is the first boot after power up */ - adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4); + first_boot = adapter->hw_read_wx(adapter, + NETXEN_ROMUSB_GLB_SW_RESET); if (first_boot != 0x80000f) { /* clear the register for future unloads/loads */ - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_CAM_RAM(0x1fc), 0); return -EIO; } /* Start P2 boot loader */ - val = adapter->pci_read_normalize(adapter, + val = adapter->hw_read_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE); - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); timeout = 0; do { msleep(1); - val = adapter->pci_read_normalize(adapter, + val = adapter->hw_read_wx(adapter, NETXEN_CAM_RAM(0x1fc)); if (++timeout > 5000) @@ -365,23 +364,23 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) if (port_mode == NETXEN_PORT_MODE_802_3_AP) { data = NETXEN_PORT_MODE_802_3_AP; adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_XG) { data = NETXEN_PORT_MODE_XG; adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) { data = NETXEN_PORT_MODE_AUTO_NEG_1G; adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) { data = NETXEN_PORT_MODE_AUTO_NEG_XG; adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NETXEN_PORT_MODE_ADDR, data); } else { data = NETXEN_PORT_MODE_AUTO_NEG; adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, &data, 4); + NETXEN_PORT_MODE_ADDR, data); } if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) && @@ -391,7 +390,7 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG; } adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE, - &wol_port_mode, 4); + wol_port_mode); } } @@ -572,8 +571,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) adapter->hw_read_wx = netxen_nic_hw_read_wx_128M; adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M; adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M; - adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M; - adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M; adapter->pci_set_window = netxen_nic_pci_set_window_128M; adapter->pci_mem_read = netxen_nic_pci_mem_read_128M; adapter->pci_mem_write = netxen_nic_pci_mem_write_128M; @@ -595,9 +592,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M; adapter->pci_write_immediate = netxen_nic_pci_write_immediate_2M; - adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M; - adapter->pci_write_normalize = - netxen_nic_pci_write_normalize_2M; adapter->pci_set_window = netxen_nic_pci_set_window_2M; adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; @@ -680,7 +674,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) if (!first_driver) return 0; - first_boot = adapter->pci_read_normalize(adapter, + first_boot = adapter->hw_read_wx(adapter, NETXEN_CAM_RAM(0x1fc)); err = netxen_check_hw_init(adapter, first_boot); @@ -690,7 +684,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) } if (first_boot != 0x55555555) { - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); msleep(1); @@ -723,7 +717,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) val = (_NETXEN_NIC_LINUX_MAJOR << 16) | ((_NETXEN_NIC_LINUX_MINOR << 8)) | (_NETXEN_NIC_LINUX_SUBVERSION); - adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, val); + adapter->hw_write_wx(adapter, CRB_DRIVER_VERSION, val); /* Handshake with the card before we register the devices. */ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); @@ -1038,7 +1032,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ adapter->physical_port = adapter->portnum; if (adapter->fw_major < 4) { - i = adapter->pci_read_normalize(adapter, + i = adapter->hw_read_wx(adapter, CRB_V2P(adapter->portnum)); if (i != 0x55555555) adapter->physical_port = i; @@ -1486,7 +1480,7 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) uint32_t temp, temp_state, temp_val; int rv = 0; - temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE); + temp = adapter->hw_read_wx(adapter, CRB_TEMP_STATE); temp_state = nx_get_temp_state(temp); temp_val = nx_get_temp_val(temp); @@ -1557,11 +1551,11 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) port = adapter->physical_port; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3); + val = adapter->hw_read_wx(adapter, CRB_XG_STATE_P3); val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); linkup = (val == XG_LINK_UP_P3); } else { - val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); + val = adapter->hw_read_wx(adapter, CRB_XG_STATE); if (adapter->ahw.port_type == NETXEN_NIC_GBE) linkup = (val >> port) & 1; else { @@ -1656,14 +1650,14 @@ static irqreturn_t netxen_intr(int irq, void *data) } else { unsigned long our_int = 0; - our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR); + our_int = adapter->hw_read_wx(adapter, CRB_INT_VECTOR); /* not our interrupt */ if (!test_and_clear_bit((7 + adapter->portnum), &our_int)) return IRQ_NONE; /* claim interrupt */ - adapter->pci_write_normalize(adapter, + adapter->hw_write_wx(adapter, CRB_INT_VECTOR, (our_int & 0xffffffff)); } diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index 3310471ba1a0..b54a63a64e7b 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -105,9 +105,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, * so it cannot be in reset */ - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) - return -EIO; + mac_cfg0 = adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); if (netxen_gb_get_soft_reset(mac_cfg0)) { __u32 temp; temp = 0; @@ -116,8 +114,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, netxen_gb_tx_reset_mac(temp); netxen_gb_rx_reset_mac(temp); if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &temp, 4)) + NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) return -EIO; restore = 1; } @@ -125,43 +122,38 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), - &address, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) return -EIO; command = 0; /* turn off any prior activity */ - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), - &command, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; /* send read command */ netxen_gb_mii_mgmt_set_read_cycle(command); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), - &command, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; status = 0; do { - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_INDICATE(0), - &status, 4)) - return -EIO; + status = adapter->hw_read_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); timeout++; } while ((netxen_get_gb_mii_mgmt_busy(status) || netxen_get_gb_mii_mgmt_notvalid(status)) && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); if (timeout < NETXEN_NIU_PHY_WAITMAX) { - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_STATUS(0), - readval, 4)) - return -EIO; + *readval = adapter->hw_read_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_STATUS(0)); result = 0; } else result = -1; if (restore) if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) + NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) return -EIO; phy_unlock(adapter); return result; @@ -197,9 +189,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, * cannot be in reset */ - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) - return -EIO; + mac_cfg0 = adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); if (netxen_gb_get_soft_reset(mac_cfg0)) { __u32 temp; temp = 0; @@ -209,34 +199,31 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, netxen_gb_rx_reset_mac(temp); if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &temp, 4)) + NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) return -EIO; restore = 1; } command = 0; /* turn off any prior activity */ - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), - &command, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), - &address, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) return -EIO; - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), - &val, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_CTRL(0), val)) return -EIO; status = 0; do { - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_INDICATE(0), - &status, 4)) - return -EIO; + status = adapter->hw_read_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); timeout++; } while ((netxen_get_gb_mii_mgmt_busy(status)) && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); @@ -249,8 +236,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, /* restore the state of port 0 MAC in case we tampered with it */ if (restore) if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), - &mac_cfg0, 4)) + NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) return -EIO; return result; @@ -473,12 +459,10 @@ static int netxen_niu_macaddr_get(struct netxen_adapter *adapter, if ((phy < 0) || (phy > 3)) return -EINVAL; - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), - &stationhigh, 4)) - return -EIO; - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), - &stationlow, 4)) - return -EIO; + stationhigh = adapter->hw_read_wx(adapter, + NETXEN_NIU_GB_STATION_ADDR_0(phy)); + stationlow = adapter->hw_read_wx(adapter, + NETXEN_NIU_GB_STATION_ADDR_1(phy)); ((__le32 *)val)[1] = cpu_to_le32(stationhigh); ((__le32 *)val)[0] = cpu_to_le32(stationlow); @@ -508,13 +492,13 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter, memcpy(temp + 2, addr, 2); val = le32_to_cpu(*(__le32 *)temp); if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4)) + NETXEN_NIU_GB_STATION_ADDR_1(phy), val)) return -EIO; memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32)); val = le32_to_cpu(*(__le32 *)temp); if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4)) + NETXEN_NIU_GB_STATION_ADDR_0(phy), val)) return -2; netxen_niu_macaddr_get(adapter, @@ -545,8 +529,8 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) return -EINVAL; mac_cfg0 = 0; netxen_gb_soft_reset(mac_cfg0); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - &mac_cfg0, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0)) return -EIO; return 0; } @@ -565,7 +549,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) mac_cfg = 0; if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4)) + NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) return -EIO; return 0; } @@ -581,9 +565,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return -EINVAL; /* save previous contents */ - if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, - ®, 4)) - return -EIO; + reg = adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR); if (mode == NETXEN_NIU_PROMISC_MODE) { switch (port) { case 0: @@ -619,8 +601,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return -EIO; } } - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, - ®, 4)) + if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg)) return -EIO; return 0; } @@ -647,28 +628,28 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, case 0: memcpy(temp + 2, addr, 2); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, - &val, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_XGE_STATION_ADDR_0_1, val)) return -EIO; memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, - &val, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_XGE_STATION_ADDR_0_HI, val)) return -EIO; break; case 1: memcpy(temp + 2, addr, 2); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1, - &val, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_XG1_STATION_ADDR_0_1, val)) return -EIO; memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI, - &val, 4)) + if (adapter->hw_write_wx(adapter, + NETXEN_NIU_XG1_STATION_ADDR_0_HI, val)) return -EIO; break; @@ -689,9 +670,8 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, if (port > NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; - if (adapter->hw_read_wx(adapter, - NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), ®, 4)) - return -EIO; + reg = adapter->hw_read_wx(adapter, + NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); if (mode == NETXEN_NIU_PROMISC_MODE) reg = (reg | 0x2000UL); else -- cgit v1.2.3 From f98a9f693b5f4919d9c4085a2fd8d67c7e152f3e Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:45 +0000 Subject: netxen: sanitize function names Replace superfluous wrapper functions with two macros: NXWR32 replaces netxen_nic_reg_write, netxen_nic_write_w0, netxen_nic_read_w1, netxen_crb_writelit_adapter. NXRD32 replaces netxen_nic_reg_read, netxen_nic_read_w0, netxen_nic_read_w1. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 19 ++-- drivers/net/netxen/netxen_nic_ctx.c | 29 +++-- drivers/net/netxen/netxen_nic_ethtool.c | 59 +++++----- drivers/net/netxen/netxen_nic_hw.c | 187 ++++++++++---------------------- drivers/net/netxen/netxen_nic_init.c | 93 +++++++--------- drivers/net/netxen/netxen_nic_main.c | 83 ++++++-------- drivers/net/netxen/netxen_nic_niu.c | 169 ++++++++++------------------- 7 files changed, 233 insertions(+), 406 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 1e4190dd0c16..f13fd0282f55 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1312,12 +1312,11 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, /* Functions available from netxen_nic_hw.c */ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu); int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu); -void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val); -int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off); -void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value); -u32 netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index); -void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value); -u32 netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index); + +#define NXRD32(adapter, off) \ + (adapter->hw_read_wx(adapter, off)) +#define NXWR32(adapter, off, val) \ + (adapter->hw_write_wx(adapter, off, val)) int netxen_nic_get_board_info(struct netxen_adapter *adapter); void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); @@ -1348,8 +1347,6 @@ int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, u64 off, void *data, int size); int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, u64 off, void *data, int size); -void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, - unsigned long off, int data); int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, u64 off, u32 data); u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off); @@ -1478,8 +1475,7 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter) /* Send the disable request */ netxen_set_dma_watchdog_disable_req(ctrl); - netxen_crb_writelit_adapter(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); return 0; } @@ -1509,8 +1505,7 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) /* send the wakeup request */ netxen_set_dma_watchdog_enable_req(ctrl); - netxen_crb_writelit_adapter(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); return 0; } diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 7a13ee8144ee..32f48398398b 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -41,8 +41,7 @@ netxen_api_lock(struct netxen_adapter *adapter) for (;;) { /* Acquire PCIE HW semaphore5 */ - done = netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM5_LOCK)); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_LOCK)); if (done == 1) break; @@ -56,7 +55,7 @@ netxen_api_lock(struct netxen_adapter *adapter) } #if 0 - netxen_nic_write_w1(adapter, + NXWR32(adapter, NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER); #endif return 0; @@ -66,8 +65,7 @@ static int netxen_api_unlock(struct netxen_adapter *adapter) { /* Release PCIE HW semaphore5 */ - netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK)); + NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK)); return 0; } @@ -84,7 +82,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter) if (++timeout > NX_OS_CRB_RETRY_COUNT) return NX_CDRP_RSP_TIMEOUT; - rsp = netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET); + rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET); } while (!NX_CDRP_IS_RSP(rsp)); return rsp; @@ -104,16 +102,15 @@ netxen_issue_cmd(struct netxen_adapter *adapter, if (netxen_api_lock(adapter)) return NX_RCODE_TIMEOUT; - netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature); + NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); - netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1); + NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1); - netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2); + NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2); - netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3); + NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3); - netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET, - NX_CDRP_FORM_CMD(cmd)); + NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd)); rsp = netxen_poll_rsp(adapter); @@ -123,7 +120,7 @@ netxen_issue_cmd(struct netxen_adapter *adapter, rcode = NX_RCODE_TIMEOUT; } else if (rsp == NX_CDRP_RSP_FAIL) { - rcode = netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET); + rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET); printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); @@ -515,11 +512,11 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc); - adapter->hw_write_wx(adapter, CRB_CTX_ADDR_REG_LO(func_id), + NXWR32(adapter, CRB_CTX_ADDR_REG_LO(func_id), lower32(adapter->ctx_desc_phys_addr)); - adapter->hw_write_wx(adapter, CRB_CTX_ADDR_REG_HI(func_id), + NXWR32(adapter, CRB_CTX_ADDR_REG_HI(func_id), upper32(adapter->ctx_desc_phys_addr)); - adapter->hw_write_wx(adapter, CRB_CTX_SIGNATURE_REG(func_id), + NXWR32(adapter, CRB_CTX_SIGNATURE_REG(func_id), NETXEN_CTX_SIGNATURE | func_id); return 0; } diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 6c5a111e80bf..a452b2facb77 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -92,12 +92,9 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) strncpy(drvinfo->driver, netxen_nic_driver_name, 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); write_lock_irqsave(&adapter->adapter_lock, flags); - fw_major = adapter->hw_read_wx(adapter, - NETXEN_FW_VERSION_MAJOR); - fw_minor = adapter->hw_read_wx(adapter, - NETXEN_FW_VERSION_MINOR); - fw_build = adapter->hw_read_wx(adapter, - NETXEN_FW_VERSION_SUB); + fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); + fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); + fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); write_unlock_irqrestore(&adapter->adapter_lock, flags); sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); @@ -135,7 +132,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { u32 val; - val = adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR); + val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR); if (val == NETXEN_PORT_MODE_802_3_AP) { ecmd->supported = SUPPORTED_1000baseT_Full; ecmd->advertising = ADVERTISED_1000baseT_Full; @@ -156,8 +153,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { u16 pcifn = adapter->ahw.pci_func; - val = adapter->hw_read_wx(adapter, - P3_LINK_SPEED_REG(pcifn)); + val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn)); ecmd->speed = P3_LINK_SPEED_MHZ * P3_LINK_SPEED_VAL(pcifn, val); } else @@ -423,12 +419,11 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) | (adapter->pdev)->device; /* which mode */ - regs_buff[0] = adapter->hw_read_wx(adapter, NETXEN_NIU_MODE); + regs_buff[0] = NXRD32(adapter, NETXEN_NIU_MODE); mode = regs_buff[0]; /* Common registers to all the modes */ - regs_buff[2] = adapter->hw_read_wx(adapter, - NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER); + regs_buff[2] = NXRD32(adapter, NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER); /* GB/XGB Mode */ mode = (mode / 2) - 1; window = 0; @@ -439,7 +434,7 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) window = adapter->physical_port * NETXEN_NIC_PORT_WINDOW; - regs_buff[i] = adapter->hw_read_wx(adapter, + regs_buff[i] = NXRD32(adapter, niu_registers[mode].reg[i - 3] + window); } @@ -464,7 +459,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) return !val; } } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { - val = adapter->hw_read_wx(adapter, CRB_XG_STATE); + val = NXRD32(adapter, CRB_XG_STATE); return (val == XG_LINK_UP) ? 0 : 1; } return -EIO; @@ -528,10 +523,9 @@ netxen_nic_get_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ - val = netxen_nic_read_w0(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port)); + val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port)); pause->rx_pause = netxen_gb_get_rx_flowctl(val); - val = netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL); + val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { case 0: pause->tx_pause = !(netxen_gb_get_gb0_mask(val)); @@ -551,7 +545,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; - val = netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL); + val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) pause->tx_pause = !(netxen_xg_get_xg0_mask(val)); else @@ -574,18 +568,17 @@ netxen_nic_set_pauseparam(struct net_device *dev, if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ - val = netxen_nic_read_w0(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port)); + val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port)); if (pause->rx_pause) netxen_gb_rx_flowctl(val); else netxen_gb_unset_rx_flowctl(val); - netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), val); /* set autoneg */ - val = netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL); + val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { case 0: if (pause->tx_pause) @@ -613,11 +606,11 @@ netxen_nic_set_pauseparam(struct net_device *dev, netxen_gb_set_gb3_mask(val); break; } - netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); + NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return -EIO; - val = netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL); + val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) { if (pause->tx_pause) netxen_xg_unset_xg0_mask(val); @@ -629,7 +622,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, else netxen_xg_set_xg1_mask(val); } - netxen_nic_write_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, val); + NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val); } else { printk(KERN_ERR "%s: Unknown board type: %x\n", netxen_nic_driver_name, @@ -643,14 +636,14 @@ static int netxen_nic_reg_test(struct net_device *dev) struct netxen_adapter *adapter = netdev_priv(dev); u32 data_read, data_written; - data_read = netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0)); + data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0)); if ((data_read & 0xffff) != PHAN_VENDOR_ID) return 1; data_written = (u32)0xa5a5a5a5; - netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written); - data_read = adapter->hw_read_wx(adapter, CRB_SCRATCHPAD_TEST); + NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written); + data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST); if (data_written != data_read) return 1; @@ -767,11 +760,11 @@ netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) return; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); if (wol_cfg & (1UL << adapter->portnum)) wol->supported |= WAKE_MAGIC; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); if (wol_cfg & (1UL << adapter->portnum)) wol->wolopts |= WAKE_MAGIC; } @@ -788,16 +781,16 @@ netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EOPNOTSUPP; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); if (!(wol_cfg & (1 << adapter->portnum))) return -EOPNOTSUPP; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); if (wol->wolopts & WAKE_MAGIC) wol_cfg |= 1UL << adapter->portnum; else wol_cfg &= ~(1UL << adapter->portnum); - netxen_nic_reg_write(adapter, NETXEN_WOL_CONFIG, wol_cfg); + NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg); return 0; } diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 87cda65ef66b..9439f89869de 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -361,22 +361,20 @@ netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter) if (adapter->mc_enabled) return 0; - val = adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG); + val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG); val |= (1UL << (28+port)); - adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); + NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); /* add broadcast addr to filter */ val = 0xffffff; - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); - netxen_crb_writelit_adapter(adapter, - NETXEN_UNICAST_ADDR(port, 0)+4, val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val); /* add station addr to filter */ val = MAC_HI(addr); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val); val = MAC_LO(addr); - netxen_crb_writelit_adapter(adapter, - NETXEN_UNICAST_ADDR(port, 1)+4, val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val); adapter->mc_enabled = 1; return 0; @@ -392,18 +390,17 @@ netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter) if (!adapter->mc_enabled) return 0; - val = adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG); + val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG); val &= ~(1UL << (28+port)); - adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); + NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); val = MAC_HI(addr); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val); val = MAC_LO(addr); - netxen_crb_writelit_adapter(adapter, - NETXEN_UNICAST_ADDR(port, 0)+4, val); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0); - netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0); + NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0); adapter->mc_enabled = 0; return 0; @@ -419,10 +416,8 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, lo = MAC_LO(addr); hi = MAC_HI(addr); - netxen_crb_writelit_adapter(adapter, - NETXEN_MCAST_ADDR(port, index), hi); - netxen_crb_writelit_adapter(adapter, - NETXEN_MCAST_ADDR(port, index)+4, lo); + NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi); + NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo); return 0; } @@ -863,8 +858,8 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); - mac_lo = adapter->hw_read_wx(adapter, crbaddr); - mac_hi = adapter->hw_read_wx(adapter, crbaddr+4); + mac_lo = NXRD32(adapter, crbaddr); + mac_hi = NXRD32(adapter, crbaddr+4); if (pci_func & 1) *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); @@ -882,8 +877,7 @@ static int crb_win_lock(struct netxen_adapter *adapter) while (!done) { /* acquire semaphore3 from PCI HW block */ - done = adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(PCIE_SEM7_LOCK)); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_LOCK)); if (done == 1) break; if (timeout >= CRB_WIN_LOCK_TIMEOUT) @@ -891,8 +885,7 @@ static int crb_win_lock(struct netxen_adapter *adapter) timeout++; udelay(1); } - netxen_crb_writelit_adapter(adapter, - NETXEN_CRB_WIN_LOCK_ID, adapter->portnum); + NXWR32(adapter, NETXEN_CRB_WIN_LOCK_ID, adapter->portnum); return 0; } @@ -900,8 +893,7 @@ static void crb_win_unlock(struct netxen_adapter *adapter) { int val; - val = adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK)); + val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK)); } /* @@ -1037,8 +1029,7 @@ netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, dev_info(&pdev->dev, "loading firmware from flash\n"); if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - adapter->hw_write_wx(adapter, - NETXEN_ROMUSB_GLB_CAS_RST, 1); + NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); if (fw) { __le64 data; @@ -1090,13 +1081,10 @@ netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, msleep(1); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - adapter->hw_write_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); else { - adapter->hw_write_wx(adapter, - NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); - adapter->hw_write_wx(adapter, - NETXEN_ROMUSB_GLB_CAS_RST, 0); + NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); } return 0; @@ -1154,8 +1142,7 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, if (NETXEN_VERSION_CODE(major, minor, build) > ver) return -EINVAL; - netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc), - NETXEN_BDINFO_MAGIC); + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); return 0; } @@ -1183,8 +1170,7 @@ request_mn: netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&flashed_ver); if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { - capability = adapter->hw_read_wx(adapter, - NX_PEG_TUNE_CAPABILITY); + capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); if (capability & NX_PEG_TUNE_MN_PRESENT) { fw_type = NX_P3_MN_ROMIMAGE; goto request_fw; @@ -1332,38 +1318,6 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) return data; } -void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) -{ - adapter->hw_write_wx(adapter, off, val); -} - -int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) -{ - return adapter->hw_read_wx(adapter, off); -} - -/* Change the window to 0, write and change back to window 1. */ -void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) -{ - adapter->hw_write_wx(adapter, index, value); -} - -/* Change the window to 0, read and change back to window 1. */ -u32 netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index) -{ - return adapter->hw_read_wx(adapter, index); -} - -void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value) -{ - adapter->hw_write_wx(adapter, index, value); -} - -u32 netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index) -{ - return adapter->hw_read_wx(adapter, index); -} - /* * check memory access boundary. * used by test agent. support ddr access only for now @@ -1475,10 +1429,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, /* DDR network side */ window = MN_WIN(addr); adapter->ahw.ddr_mn_window = window; - adapter->hw_write_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, + NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, window); - win_read = adapter->hw_read_wx(adapter, + win_read = NXRD32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); if ((win_read << 17) != window) { printk(KERN_INFO "Written MNwin (0x%x) != " @@ -1494,10 +1447,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, window = OCM_WIN(addr); adapter->ahw.ddr_mn_window = window; - adapter->hw_write_wx(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, + NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, window); - win_read = adapter->hw_read_wx(adapter, + win_read = NXRD32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); if ((win_read >> 7) != window) { printk(KERN_INFO "%s: Written OCMwin (0x%x) != " @@ -1511,10 +1463,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, /* QDR network side */ window = MS_WIN(addr); adapter->ahw.qdr_sn_window = window; - adapter->hw_write_wx(adapter, - adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, + NXWR32(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, window); - win_read = adapter->hw_read_wx(adapter, + win_read = NXRD32(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE); if (win_read != window) { printk(KERN_INFO "%s: Written MSwin (0x%x) != " @@ -1961,27 +1912,20 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { temp = off8 + (i << 3); - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_ADDR_LO, temp); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); temp = 0; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_ADDR_HI, temp); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); temp = word[i] & 0xffffffff; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); temp = (word[i] >> 32) & 0xffffffff; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_CTRL, temp); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp); temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - adapter->hw_write_wx(adapter, - mem_crb+MIU_TEST_AGT_CTRL, temp); + NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL); + temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -2038,21 +1982,16 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { temp = off8 + (i << 3); - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_ADDR_LO, temp); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); temp = 0; - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_ADDR_HI, temp); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); temp = MIU_TA_CTL_ENABLE; - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, temp); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp); temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; - adapter->hw_write_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL, temp); + NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = adapter->hw_read_wx(adapter, - mem_crb + MIU_TEST_AGT_CTRL); + temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -2067,7 +2006,7 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, start = off0[i] >> 2; end = (off0[i] + sz[i] - 1) >> 2; for (k = start; k <= end; k++) { - temp = adapter->hw_read_wx(adapter, + temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_RDDATA(k)); word[i] |= ((uint64_t)temp << (32 * k)); } @@ -2111,14 +2050,14 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, u64 off, u32 data) { - adapter->hw_write_wx(adapter, off, data); + NXWR32(adapter, off, data); return 0; } u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off) { - return adapter->hw_read_wx(adapter, off); + return NXRD32(adapter, off); } int netxen_nic_get_board_info(struct netxen_adapter *adapter) @@ -2152,8 +2091,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) adapter->ahw.board_type = board_type; if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { - u32 gpio = netxen_nic_reg_read(adapter, - NETXEN_ROMUSB_GLB_PAD_GPIO_I); + u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I); if ((gpio & 0x8000) == 0) board_type = NETXEN_BRDTYPE_P3_10G_TP; } @@ -2205,8 +2143,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu) { new_mtu += MTU_FUDGE_FACTOR; - netxen_nic_write_w0(adapter, - NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port), + NXWR32(adapter, NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port), new_mtu); return 0; } @@ -2215,21 +2152,12 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu) { new_mtu += MTU_FUDGE_FACTOR; if (adapter->physical_port == 0) - netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, - new_mtu); + NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); else - netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, - new_mtu); + NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu); return 0; } -void -netxen_crb_writelit_adapter(struct netxen_adapter *adapter, - unsigned long off, int data) -{ - adapter->hw_write_wx(adapter, off, data); -} - void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) { __u32 status; @@ -2244,8 +2172,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) } if (adapter->ahw.port_type == NETXEN_NIC_GBE) { - port_mode = adapter->hw_read_wx(adapter, - NETXEN_PORT_MODE_ADDR); + port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { adapter->link_speed = SPEED_1000; adapter->link_duplex = DUPLEX_FULL; @@ -2322,9 +2249,9 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) addr += sizeof(u32); } - fw_major = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR); - fw_minor = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR); - fw_build = adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB); + fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); + fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); + fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); adapter->fw_major = fw_major; adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); @@ -2347,7 +2274,7 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) fw_major, fw_minor, fw_build); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - i = adapter->hw_read_wx(adapter, NETXEN_MIU_MN_CONTROL); + i = NXRD32(adapter, NETXEN_MIU_MN_CONTROL); adapter->ahw.cut_through = (i & 0x4) ? 1 : 0; dev_info(&pdev->dev, "firmware running in %s mode\n", adapter->ahw.cut_through ? "cut-through" : "legacy"); @@ -2362,9 +2289,9 @@ netxen_nic_wol_supported(struct netxen_adapter *adapter) if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 0; - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); if (wol_cfg & (1UL << adapter->portnum)) { - wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); if (wol_cfg & (1 << adapter->portnum)) return 1; } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 83116c2817b0..0c91238133f0 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -368,8 +368,7 @@ static int rom_lock(struct netxen_adapter *adapter) while (!done) { /* acquire semaphore2 from PCI HW block */ - done = netxen_nic_read_w0(adapter, - NETXEN_PCIE_REG(PCIE_SEM2_LOCK)); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK)); if (done == 1) break; if (timeout >= rom_lock_timeout) @@ -386,7 +385,7 @@ static int rom_lock(struct netxen_adapter *adapter) cpu_relax(); /*This a nop instr on i386 */ } } - netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER); + NXWR32(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER); return 0; } @@ -398,7 +397,7 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) cond_resched(); while (done == 0) { - done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS); + done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS); done &= 2; timeout++; if (timeout >= rom_max_timeout) { @@ -412,27 +411,27 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) static void netxen_rom_unlock(struct netxen_adapter *adapter) { /* release semaphore2 */ - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK)); + NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK)); } static int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); + NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); + NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); + NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { printk("Error waiting for rom done\n"); return -EIO; } /* reset abyte_cnt and dummy_byte_cnt */ - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); udelay(10); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); - *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); + *valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA); return 0; } @@ -496,8 +495,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* resetall */ rom_lock(adapter); - netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, - 0xffffffff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); netxen_rom_unlock(adapter); if (verbose) { @@ -621,7 +619,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } } - adapter->hw_write_wx(adapter, off, buf[i].data); + NXWR32(adapter, off, buf[i].data); msleep(init_delay); } @@ -631,33 +629,31 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* unreset_net_cache */ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - val = adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET); - netxen_crb_writelit_adapter(adapter, - NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f)); + val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f)); } /* p2dn replyCount */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e); + NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e); /* disable_peg_cache 0 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8); + NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8); /* disable_peg_cache 1 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8); + NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8); /* peg_clr_all */ /* peg_clr 0 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0); /* peg_clr 1 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0); /* peg_clr 2 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0); /* peg_clr 3 */ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0); + NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0); return 0; } @@ -681,12 +677,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) hi = (addr >> 32) & 0xffffffff; lo = addr & 0xffffffff; - adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); - adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); + NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); + NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { uint32_t temp = 0; - adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, temp); + NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp); } return 0; @@ -728,8 +724,7 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) if (!pegtune_val) { do { - val = adapter->hw_read_wx(adapter, - CRB_CMDPEG_STATE); + val = NXRD32(adapter, CRB_CMDPEG_STATE); if (val == PHAN_INITIALIZE_COMPLETE || val == PHAN_INITIALIZE_ACK) @@ -740,7 +735,7 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) } while (--retries); if (!retries) { - pegtune_val = adapter->hw_read_wx(adapter, + pegtune_val = NXRD32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE); printk(KERN_WARNING "netxen_phantom_init: init failed, " "pegtune_val=%x\n", pegtune_val); @@ -758,7 +753,7 @@ netxen_receive_peg_ready(struct netxen_adapter *adapter) int retries = 2000; do { - val = adapter->hw_read_wx(adapter, CRB_RCVPEG_STATE); + val = NXRD32(adapter, CRB_RCVPEG_STATE); if (val == PHAN_PEG_RCV_INITIALIZED) return 0; @@ -784,18 +779,13 @@ int netxen_init_firmware(struct netxen_adapter *adapter) if (err) return err; - adapter->hw_write_wx(adapter, - CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); - adapter->hw_write_wx(adapter, - CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); - adapter->hw_write_wx(adapter, - CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); - adapter->hw_write_wx(adapter, - CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); + NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); + NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); + NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); + NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { - adapter->capabilities = netxen_nic_reg_read(adapter, - CRB_FW_CAPABILITIES_1); + adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); } return err; @@ -1057,8 +1047,7 @@ skip: if (count) { sds_ring->consumer = consumer; - adapter->hw_write_wx(adapter, - sds_ring->crb_sts_consumer, consumer); + NXWR32(adapter, sds_ring->crb_sts_consumer, consumer); } return count; @@ -1176,8 +1165,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, if (count) { rds_ring->producer = producer; - adapter->hw_write_wx(adapter, - rds_ring->crb_rcv_producer, + NXWR32(adapter, rds_ring->crb_rcv_producer, (producer-1) & (rds_ring->num_desc-1)); if (adapter->fw_major < 4) { @@ -1237,8 +1225,7 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, if (count) { rds_ring->producer = producer; - adapter->hw_write_wx(adapter, - rds_ring->crb_rcv_producer, + NXWR32(adapter, rds_ring->crb_rcv_producer, (producer - 1) & (rds_ring->num_desc - 1)); wmb(); } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 31966a044900..8426092deda3 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -109,8 +109,7 @@ void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring, u32 producer) { - adapter->hw_write_wx(adapter, - tx_ring->crb_cmd_producer, producer); + NXWR32(adapter, tx_ring->crb_cmd_producer, producer); } static uint32_t crb_cmd_consumer[4] = { @@ -122,8 +121,7 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring, u32 consumer) { - adapter->hw_write_wx(adapter, - tx_ring->crb_cmd_consumer, consumer); + NXWR32(adapter, tx_ring->crb_cmd_consumer, consumer); } static uint32_t msi_tgt_status[8] = { @@ -139,14 +137,14 @@ static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - adapter->hw_write_wx(adapter, sds_ring->crb_intr_mask, 0); + NXWR32(adapter, sds_ring->crb_intr_mask, 0); } static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - adapter->hw_write_wx(adapter, sds_ring->crb_intr_mask, 0x1); + NXWR32(adapter, sds_ring->crb_intr_mask, 0x1); if (!NETXEN_IS_MSI_FAMILY(adapter)) adapter->pci_write_immediate(adapter, @@ -262,7 +260,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter) change = 0; - shift = netxen_nic_reg_read(adapter, CRB_DMA_SHIFT); + shift = NXRD32(adapter, CRB_DMA_SHIFT); if (shift >= 32) return 0; @@ -309,42 +307,34 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) if (first_boot == 0x55555555) { /* This is the first boot after power up */ - adapter->hw_write_wx(adapter, - NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 0; /* PCI bus master workaround */ - first_boot = adapter->hw_read_wx(adapter, NETXEN_PCIE_REG(0x4)); + first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4)); if (!(first_boot & 0x4)) { first_boot |= 0x4; - adapter->hw_write_wx(adapter, - NETXEN_PCIE_REG(0x4), first_boot); - first_boot = adapter->hw_read_wx(adapter, - NETXEN_PCIE_REG(0x4)); + NXWR32(adapter, NETXEN_PCIE_REG(0x4), first_boot); + first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4)); } /* This is the first boot after power up */ - first_boot = adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_SW_RESET); + first_boot = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET); if (first_boot != 0x80000f) { /* clear the register for future unloads/loads */ - adapter->hw_write_wx(adapter, - NETXEN_CAM_RAM(0x1fc), 0); + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), 0); return -EIO; } /* Start P2 boot loader */ - val = adapter->hw_read_wx(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE); - adapter->hw_write_wx(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); + val = NXRD32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE); + NXWR32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); timeout = 0; do { msleep(1); - val = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(0x1fc)); + val = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); if (++timeout > 5000) return -EIO; @@ -363,24 +353,19 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) (val == NETXEN_BRDTYPE_P3_XG_LOM)) { if (port_mode == NETXEN_PORT_MODE_802_3_AP) { data = NETXEN_PORT_MODE_802_3_AP; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, data); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_XG) { data = NETXEN_PORT_MODE_XG; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, data); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) { data = NETXEN_PORT_MODE_AUTO_NEG_1G; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, data); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) { data = NETXEN_PORT_MODE_AUTO_NEG_XG; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, data); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } else { data = NETXEN_PORT_MODE_AUTO_NEG; - adapter->hw_write_wx(adapter, - NETXEN_PORT_MODE_ADDR, data); + NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data); } if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) && @@ -389,8 +374,7 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) { wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG; } - adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE, - wol_port_mode); + NXWR32(adapter, NETXEN_WOL_PORT_MODE, wol_port_mode); } } @@ -674,8 +658,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) if (!first_driver) return 0; - first_boot = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(0x1fc)); + first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); err = netxen_check_hw_init(adapter, first_boot); if (err) { @@ -684,13 +667,12 @@ netxen_start_firmware(struct netxen_adapter *adapter) } if (first_boot != 0x55555555) { - adapter->hw_write_wx(adapter, - CRB_CMDPEG_STATE, 0); + NXWR32(adapter, CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); msleep(1); } - netxen_nic_reg_write(adapter, CRB_DMA_SHIFT, 0x55555555); + NXWR32(adapter, CRB_DMA_SHIFT, 0x55555555); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_set_port_mode(adapter); @@ -702,8 +684,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) val = 0x7654; if (adapter->ahw.port_type == NETXEN_NIC_XGBE) val |= 0x0f000000; - netxen_crb_writelit_adapter(adapter, - NETXEN_MAC_ADDR_CNTL_REG, val); + NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); } @@ -717,7 +698,7 @@ netxen_start_firmware(struct netxen_adapter *adapter) val = (_NETXEN_NIC_LINUX_MAJOR << 16) | ((_NETXEN_NIC_LINUX_MINOR << 8)) | (_NETXEN_NIC_LINUX_SUBVERSION); - adapter->hw_write_wx(adapter, CRB_DRIVER_VERSION, val); + NXWR32(adapter, CRB_DRIVER_VERSION, val); /* Handshake with the card before we register the devices. */ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); @@ -1032,8 +1013,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ adapter->physical_port = adapter->portnum; if (adapter->fw_major < 4) { - i = adapter->hw_read_wx(adapter, - CRB_V2P(adapter->portnum)); + i = NXRD32(adapter, CRB_V2P(adapter->portnum)); if (i != 0x55555555) adapter->physical_port = i; } @@ -1480,7 +1460,7 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) uint32_t temp, temp_state, temp_val; int rv = 0; - temp = adapter->hw_read_wx(adapter, CRB_TEMP_STATE); + temp = NXRD32(adapter, CRB_TEMP_STATE); temp_state = nx_get_temp_state(temp); temp_val = nx_get_temp_val(temp); @@ -1551,11 +1531,11 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) port = adapter->physical_port; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - val = adapter->hw_read_wx(adapter, CRB_XG_STATE_P3); + val = NXRD32(adapter, CRB_XG_STATE_P3); val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); linkup = (val == XG_LINK_UP_P3); } else { - val = adapter->hw_read_wx(adapter, CRB_XG_STATE); + val = NXRD32(adapter, CRB_XG_STATE); if (adapter->ahw.port_type == NETXEN_NIC_GBE) linkup = (val >> port) & 1; else { @@ -1650,15 +1630,14 @@ static irqreturn_t netxen_intr(int irq, void *data) } else { unsigned long our_int = 0; - our_int = adapter->hw_read_wx(adapter, CRB_INT_VECTOR); + our_int = NXRD32(adapter, CRB_INT_VECTOR); /* not our interrupt */ if (!test_and_clear_bit((7 + adapter->portnum), &our_int)) return IRQ_NONE; /* claim interrupt */ - adapter->hw_write_wx(adapter, - CRB_INT_VECTOR, (our_int & 0xffffffff)); + NXWR32(adapter, CRB_INT_VECTOR, (our_int & 0xffffffff)); } /* clear interrupt */ diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index b54a63a64e7b..5e2698bf575a 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -43,8 +43,7 @@ static int phy_lock(struct netxen_adapter *adapter) int done = 0, timeout = 0; while (!done) { - done = netxen_nic_reg_read(adapter, - NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); if (done == 1) break; if (timeout >= phy_lock_timeout) { @@ -59,8 +58,7 @@ static int phy_lock(struct netxen_adapter *adapter) } } - netxen_crb_writelit_adapter(adapter, - NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER); + NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER); return 0; } @@ -105,7 +103,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, * so it cannot be in reset */ - mac_cfg0 = adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); + mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); if (netxen_gb_get_soft_reset(mac_cfg0)) { __u32 temp; temp = 0; @@ -113,8 +111,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, netxen_gb_rx_reset_pb(temp); netxen_gb_tx_reset_mac(temp); netxen_gb_rx_reset_mac(temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) return -EIO; restore = 1; } @@ -122,38 +119,32 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) return -EIO; command = 0; /* turn off any prior activity */ - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; /* send read command */ netxen_gb_mii_mgmt_set_read_cycle(command); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; status = 0; do { - status = adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); + status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); timeout++; } while ((netxen_get_gb_mii_mgmt_busy(status) || netxen_get_gb_mii_mgmt_notvalid(status)) && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); if (timeout < NETXEN_NIU_PHY_WAITMAX) { - *readval = adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_STATUS(0)); + *readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0)); result = 0; } else result = -1; if (restore) - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) return -EIO; phy_unlock(adapter); return result; @@ -189,7 +180,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, * cannot be in reset */ - mac_cfg0 = adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); + mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); if (netxen_gb_get_soft_reset(mac_cfg0)) { __u32 temp; temp = 0; @@ -198,32 +189,27 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, netxen_gb_tx_reset_mac(temp); netxen_gb_rx_reset_mac(temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) return -EIO; restore = 1; } command = 0; /* turn off any prior activity */ - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) return -EIO; address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) return -EIO; - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_CTRL(0), val)) + if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val)) return -EIO; status = 0; do { - status = adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); + status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); timeout++; } while ((netxen_get_gb_mii_mgmt_busy(status)) && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); @@ -235,8 +221,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, /* restore the state of port 0 MAC in case we tampered with it */ if (restore) - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) return -EIO; return result; @@ -244,7 +229,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f); + NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x3f); return 0; } @@ -267,7 +252,7 @@ int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter) int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f); + NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x7f); return 0; } @@ -301,30 +286,21 @@ static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter) static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, int port, long enable) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x80000000); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x0000f0025); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), - 0xf1ff); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); - netxen_crb_writelit_adapter(adapter, - (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); + NXWR32(adapter, NETXEN_NIU_MODE, 0x2); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf1ff); + NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); + NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); + NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); + NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); if (enable) { /* * Do NOT enable flow control until a suitable solution for * shutting down pause frames is found. */ - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x5); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); } if (netxen_niu_gbe_enable_phy_interrupts(adapter)) @@ -339,30 +315,21 @@ static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port, long enable) { - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x80000000); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x0000f0025); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), - 0xf2ff); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); - netxen_crb_writelit_adapter(adapter, - (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); + NXWR32(adapter, NETXEN_NIU_MODE, 0x2); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf2ff); + NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); + NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); + NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); + NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); if (enable) { /* * Do NOT enable flow control until a suitable solution for * shutting down pause frames is found. */ - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), - 0x5); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); } if (netxen_niu_gbe_enable_phy_interrupts(adapter)) @@ -402,17 +369,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) * plugged in. */ - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0 - (port), + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), NETXEN_GB_MAC_SOFT_RESET); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0 - (port), - NETXEN_GB_MAC_RESET_PROT_BLK - | NETXEN_GB_MAC_ENABLE_TX_RX - | - NETXEN_GB_MAC_PAUSED_FRMS); + NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + NETXEN_GB_MAC_RESET_PROT_BLK | + NETXEN_GB_MAC_ENABLE_TX_RX | + NETXEN_GB_MAC_PAUSED_FRMS); if (netxen_niu_gbe_clear_phy_interrupts(adapter)) printk(KERN_ERR "ERROR clearing PHY interrupts\n"); @@ -433,10 +395,8 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) { if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); } return 0; @@ -459,10 +419,8 @@ static int netxen_niu_macaddr_get(struct netxen_adapter *adapter, if ((phy < 0) || (phy > 3)) return -EINVAL; - stationhigh = adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_0(phy)); - stationlow = adapter->hw_read_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_1(phy)); + stationhigh = NXRD32(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy)); + stationlow = NXRD32(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy)); ((__le32 *)val)[1] = cpu_to_le32(stationhigh); ((__le32 *)val)[0] = cpu_to_le32(stationlow); @@ -491,14 +449,12 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter, temp[0] = temp[1] = 0; memcpy(temp + 2, addr, 2); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_1(phy), val)) + if (NXWR32(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), val)) return -EIO; memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32)); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_STATION_ADDR_0(phy), val)) + if (NXWR32(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), val)) return -2; netxen_niu_macaddr_get(adapter, @@ -529,8 +485,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) return -EINVAL; mac_cfg0 = 0; netxen_gb_soft_reset(mac_cfg0); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0)) + if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0)) return -EIO; return 0; } @@ -548,8 +503,8 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) return -EINVAL; mac_cfg = 0; - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) + if (NXWR32(adapter, + NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) return -EIO; return 0; } @@ -565,7 +520,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return -EINVAL; /* save previous contents */ - reg = adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR); + reg = NXRD32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR); if (mode == NETXEN_NIU_PROMISC_MODE) { switch (port) { case 0: @@ -601,7 +556,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return -EIO; } } - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg)) + if (NXWR32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg)) return -EIO; return 0; } @@ -628,28 +583,24 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, case 0: memcpy(temp + 2, addr, 2); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XGE_STATION_ADDR_0_1, val)) + if (NXWR32(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, val)) return -EIO; memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XGE_STATION_ADDR_0_HI, val)) + if (NXWR32(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, val)) return -EIO; break; case 1: memcpy(temp + 2, addr, 2); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XG1_STATION_ADDR_0_1, val)) + if (NXWR32(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1, val)) return -EIO; memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); val = le32_to_cpu(*(__le32 *)temp); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_XG1_STATION_ADDR_0_HI, val)) + if (NXWR32(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI, val)) return -EIO; break; @@ -670,8 +621,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, if (port > NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; - reg = adapter->hw_read_wx(adapter, - NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); + reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); if (mode == NETXEN_NIU_PROMISC_MODE) reg = (reg | 0x2000UL); else @@ -682,8 +632,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, else reg = (reg & ~0x1000UL); - netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); return 0; } -- cgit v1.2.3 From f6d21f44122630cc9549b8ffbab23ea8c68254e0 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:46 +0000 Subject: netxen: enable rss for NX2031 Enable multiple rx rings for older NX2031 chip, firmware 3.4.336 or newer supports this feature. Signed-off-by: Amit Kumar Salecha Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 27 +++++-- drivers/net/netxen/netxen_nic_ctx.c | 127 +++++++++++++++++++++++-------- drivers/net/netxen/netxen_nic_main.c | 21 ++++- drivers/net/netxen/netxen_nic_phan_reg.h | 5 +- 4 files changed, 137 insertions(+), 43 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f13fd0282f55..ebd6c2edc343 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -195,6 +195,8 @@ #define MAX_JUMBO_RCV_DESCRIPTORS 1024 #define MAX_LRO_RCV_DESCRIPTORS 8 #define NETXEN_CTX_SIGNATURE 0xdee0 +#define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 +#define NETXEN_CTX_RESET 0xbad0 #define NETXEN_RCV_PRODUCER(ringid) (ringid) #define PHAN_PEG_RCV_INITIALIZED 0xff01 @@ -234,12 +236,19 @@ typedef u32 netxen_ctx_msg; #define netxen_set_msg_opcode(config_word, val) \ ((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28) -struct netxen_rcv_context { - __le64 rcv_ring_addr; - __le32 rcv_ring_size; +struct netxen_rcv_ring { + __le64 addr; + __le32 size; __le32 rsrvd; }; +struct netxen_sts_ring { + __le64 addr; + __le32 size; + __le16 msi_index; + __le16 rsvd; +} ; + struct netxen_ring_ctx { /* one command ring */ @@ -249,13 +258,18 @@ struct netxen_ring_ctx { __le32 rsrvd; /* three receive rings */ - struct netxen_rcv_context rcv_ctx[3]; + struct netxen_rcv_ring rcv_rings[NUM_RCV_DESC_RINGS]; - /* one status ring */ __le64 sts_ring_addr; __le32 sts_ring_size; __le32 ctx_id; + + __le64 rsrvd_2[3]; + __le32 sts_ring_count; + __le32 rsrvd_3; + struct netxen_sts_ring sts_rings[NUM_STS_DESC_RINGS]; + } __attribute__ ((aligned(64))); /* @@ -1219,7 +1233,8 @@ struct netxen_adapter { u8 mc_enabled; u8 max_mc_count; - u16 resv2; + u8 rss_supported; + u8 resv2; u32 resv3; u8 has_link_events; diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 32f48398398b..fd82adf4f876 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -441,7 +441,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x120) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x138), + { + NETXEN_NIC_REG(0x138), + NETXEN_NIC_REG_2(0x000), + NETXEN_NIC_REG_2(0x004), + NETXEN_NIC_REG_2(0x008), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_0, + NETXEN_NIC_REG_2(0x044), + NETXEN_NIC_REG_2(0x048), + NETXEN_NIC_REG_2(0x04c), + }, }, /* Instance 1 */ { @@ -454,7 +466,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x164) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x17c), + { + NETXEN_NIC_REG(0x17c), + NETXEN_NIC_REG_2(0x020), + NETXEN_NIC_REG_2(0x024), + NETXEN_NIC_REG_2(0x028), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_1, + NETXEN_NIC_REG_2(0x064), + NETXEN_NIC_REG_2(0x068), + NETXEN_NIC_REG_2(0x06c), + }, }, /* Instance 2 */ { @@ -467,7 +491,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x208) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x220), + { + NETXEN_NIC_REG(0x220), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_2, + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, }, /* Instance 3 */ { @@ -480,7 +516,19 @@ static struct netxen_recv_crb recv_crb_registers[] = { NETXEN_NIC_REG(0x24c) }, /* crb_sts_consumer: */ - NETXEN_NIC_REG(0x264), + { + NETXEN_NIC_REG(0x264), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, + /* sw_int_mask */ + { + CRB_SW_INT_MASK_3, + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + NETXEN_NIC_REG_2(0x03c), + }, }, }; @@ -492,40 +540,50 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) struct nx_host_sds_ring *sds_ring; struct nx_host_tx_ring *tx_ring; int ring; - int func_id = adapter->portnum; + int port = adapter->portnum; + struct netxen_ring_ctx *hwctx = adapter->ctx_desc; + u32 signature; tx_ring = &adapter->tx_ring; - adapter->ctx_desc->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); - adapter->ctx_desc->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); + hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); + hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; - adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr = + hwctx->rcv_rings[ring].addr = cpu_to_le64(rds_ring->phys_addr); - adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = + hwctx->rcv_rings[ring].size = cpu_to_le32(rds_ring->num_desc); } - sds_ring = &recv_ctx->sds_rings[0]; - adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); - adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc); - NXWR32(adapter, CRB_CTX_ADDR_REG_LO(func_id), + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + if (ring == 0) { + hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); + hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc); + } + hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr); + hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc); + hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring); + } + hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings); + + signature = (adapter->max_sds_rings > 1) ? + NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE; + + NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port), lower32(adapter->ctx_desc_phys_addr)); - NXWR32(adapter, CRB_CTX_ADDR_REG_HI(func_id), + NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port), upper32(adapter->ctx_desc_phys_addr)); - NXWR32(adapter, CRB_CTX_SIGNATURE_REG(func_id), - NETXEN_CTX_SIGNATURE | func_id); + NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), + signature | port); return 0; } -static uint32_t sw_int_mask[4] = { - CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1, - CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3 -}; - int netxen_alloc_hw_resources(struct netxen_adapter *adapter) { void *addr; @@ -538,6 +596,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; + int port = adapter->portnum; addr = pci_alloc_consistent(pdev, sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), @@ -549,7 +608,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) } memset(addr, 0, sizeof(struct netxen_ring_ctx)); adapter->ctx_desc = (struct netxen_ring_ctx *)addr; - adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum); + adapter->ctx_desc->ctx_id = cpu_to_le32(port); adapter->ctx_desc->cmd_consumer_offset = cpu_to_le64(adapter->ctx_desc_phys_addr + sizeof(struct netxen_ring_ctx)); @@ -586,8 +645,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (adapter->fw_major < 4) rds_ring->crb_rcv_producer = - recv_crb_registers[adapter->portnum]. - crb_rcv_producer[ring]; + recv_crb_registers[port].crb_rcv_producer[ring]; } for (ring = 0; ring < adapter->max_sds_rings; ring++) { @@ -604,6 +662,12 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) goto err_out_free; } sds_ring->desc_head = (struct status_desc *)addr; + + sds_ring->crb_sts_consumer = + recv_crb_registers[port].crb_sts_consumer[ring]; + + sds_ring->crb_intr_mask = + recv_crb_registers[port].sw_int_mask[ring]; } @@ -615,19 +679,11 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (err) goto err_out_free; } else { - sds_ring = &recv_ctx->sds_rings[0]; - sds_ring->crb_sts_consumer = - recv_crb_registers[adapter->portnum].crb_sts_consumer; - - recv_ctx->sds_rings[0].crb_intr_mask = - sw_int_mask[adapter->portnum]; - err = netxen_init_old_ctx(adapter); if (err) { netxen_free_hw_resources(adapter); return err; } - } return 0; @@ -645,9 +701,16 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) struct nx_host_tx_ring *tx_ring; int ring; + int port = adapter->portnum; + if (adapter->fw_major >= 4) { nx_fw_cmd_destroy_tx_ctx(adapter); nx_fw_cmd_destroy_rx_ctx(adapter); + } else { + netxen_api_lock(adapter); + NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), + NETXEN_CTX_RESET | port); + netxen_api_unlock(adapter); } if (adapter->ctx_desc != NULL) { diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 8426092deda3..da9b90da5207 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -175,7 +175,8 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) struct nx_host_sds_ring *sds_ring; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + if ((adapter->flags & NETXEN_NIC_MSIX_ENABLED) && + adapter->rss_supported) adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2; else adapter->max_sds_rings = 1; @@ -288,10 +289,22 @@ static void netxen_check_options(struct netxen_adapter *adapter) else if (adapter->ahw.port_type == NETXEN_NIC_GBE) adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + adapter->msix_supported = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { adapter->msix_supported = !!use_msi_x; - else - adapter->msix_supported = 0; + adapter->rss_supported = !!use_msi_x; + } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) { + switch (adapter->ahw.board_type) { + case NETXEN_BRDTYPE_P2_SB31_10G: + case NETXEN_BRDTYPE_P2_SB31_10G_CX4: + case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: + adapter->msix_supported = !!use_msi_x; + adapter->rss_supported = !!use_msi_x; + break; + default: + break; + } + } adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST; adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index ecd622ead0e9..845dcf436cf6 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -36,6 +36,8 @@ */ #define NIC_CRB_BASE NETXEN_CAM_RAM(0x200) #define NETXEN_NIC_REG(X) (NIC_CRB_BASE+(X)) +#define NIC_CRB_BASE_2 NETXEN_CAM_RAM(0x700) +#define NETXEN_NIC_REG_2(X) (NIC_CRB_BASE_2+(X)) #define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00) #define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) @@ -160,7 +162,8 @@ struct netxen_recv_crb { u32 crb_rcv_producer[NUM_RCV_DESC_RINGS]; - u32 crb_sts_consumer; + u32 crb_sts_consumer[NUM_STS_DESC_RINGS]; + u32 sw_int_mask[NUM_STS_DESC_RINGS]; }; /* -- cgit v1.2.3 From a92e9e65f0068a291a677c627a747fae1f230284 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 7 Apr 2009 22:50:47 +0000 Subject: netxen: enable GRO support Signed-off-by: Amit Kumar Salecha Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_init.c | 7 ++++--- drivers/net/netxen/netxen_nic_main.c | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 0c91238133f0..8893a973399a 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -923,7 +923,8 @@ no_skb: static struct netxen_rx_buffer * netxen_process_rcv(struct netxen_adapter *adapter, - int ring, int index, int length, int cksum, int pkt_offset) + int ring, int index, int length, int cksum, int pkt_offset, + struct nx_host_sds_ring *sds_ring) { struct net_device *netdev = adapter->netdev; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; @@ -951,7 +952,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, skb->protocol = eth_type_trans(skb, netdev); - netif_receive_skb(skb); + napi_gro_receive(&sds_ring->napi, skb); adapter->stats.no_rcv++; adapter->stats.rxbytes += length; @@ -1011,7 +1012,7 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) pkt_offset = netxen_get_sts_pkt_offset(sts_data); rxbuf = netxen_process_rcv(adapter, ring, index, - length, cksum, pkt_offset); + length, cksum, pkt_offset, sds_ring); if (rxbuf) list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index da9b90da5207..e877eefdfeb0 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -981,6 +981,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->features |= (NETIF_F_GRO); netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); if (NX_IS_REVISION_P3(revision_id)) { -- cgit v1.2.3 From ea7eaa39ffadffaa8f1dd1a1f85fa38bf8ae9d39 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 7 Apr 2009 22:50:48 +0000 Subject: netxen: cache align register map table Aligning register offset translation table imporves performance on rx side. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 9439f89869de..3bb2b8c74d92 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -89,7 +89,8 @@ static void __iomem *pci_base_offset(struct netxen_adapter *adapter, } #define CRB_WIN_LOCK_TIMEOUT 100000000 -static crb_128M_2M_block_map_t crb_128M_2M_map[64] = { +static crb_128M_2M_block_map_t +crb_128M_2M_map[64] __cacheline_aligned_in_smp = { {{{0, 0, 0, 0} } }, /* 0: PCI */ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ {1, 0x0110000, 0x0120000, 0x130000}, -- cgit v1.2.3 From 8509500ac4c82c1e31515ffda6028f88693f49fd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 8 Apr 2009 15:59:53 -0700 Subject: sfc: Don't specify unexistent IRQ Neither the lm90 driver nor the lm87 driver do support interrupts, so there is no point in specifying one when declaring the devices. Signed-off-by: Jean Delvare Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/boards.c | 2 -- drivers/net/sfc/sfe4001.c | 3 --- 2 files changed, 5 deletions(-) diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c index 5182ac5a1034..4a4c74c891b7 100644 --- a/drivers/net/sfc/boards.c +++ b/drivers/net/sfc/boards.c @@ -172,7 +172,6 @@ static const u8 sfe4002_lm87_regs[] = { static struct i2c_board_info sfe4002_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfe4002_lm87_channel, - .irq = -1, }; /****************************************************************************/ @@ -247,7 +246,6 @@ static const u8 sfn4112f_lm87_regs[] = { static struct i2c_board_info sfn4112f_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfn4112f_lm87_channel, - .irq = -1, }; #define SFN4112F_ACT_LED 0 diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 4eac5da81e5a..cee00ad49b57 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -296,7 +296,6 @@ static int sfe4001_check_hw(struct efx_nic *efx) static struct i2c_board_info sfe4001_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, }; /* This board uses an I2C expander to provider power to the PHY, which needs to @@ -389,12 +388,10 @@ static void sfn4111t_fini(struct efx_nic *efx) static struct i2c_board_info sfn4111t_a0_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, }; static struct i2c_board_info sfn4111t_r5_hwmon_info = { I2C_BOARD_INFO("max6646", 0x4d), - .irq = -1, }; int sfn4111t_init(struct efx_nic *efx) -- cgit v1.2.3 From a0c31fdfb7f158780faa43ab83cc08b414bebd7e Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 8 Apr 2009 16:01:16 -0700 Subject: ISDN: update Documentation/isdn/00-INDEX After the merging of mISDN, state which files refer only to the old isdn4linux subsystem. Also add a few missing files and sort alphabetically. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- Documentation/isdn/00-INDEX | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index 9fee5f2e5c62..33543ac7d81f 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX @@ -2,28 +2,20 @@ - this file (info on ISDN implementation for Linux) CREDITS - list of the kind folks that brought you this stuff. +HiSax.cert + - information about the ITU approval certification of the HiSax driver. INTERFACE - - description of Linklevel and Hardwarelevel ISDN interface. + - description of isdn4linux Link Level and Hardware Level interfaces. +INTERFACE.fax + - description of the fax subinterface of isdn4linux. README - general info on what you need and what to do for Linux ISDN. README.FAQ - general info for FAQ. -README.audio - - info for running audio over ISDN. -README.fax - - info for using Fax over ISDN. -README.icn - - info on the ICN-ISDN-card and its driver. README.HiSax - info on the HiSax driver which replaces the old teles. -README.hfc-pci - - info on hfc-pci based cards. -README.pcbit - - info on the PCBIT-D ISDN adapter and driver. -README.syncppp - - info on running Sync PPP over ISDN. -syncPPP.FAQ - - frequently asked questions about running PPP over ISDN. +README.audio + - info for running audio over ISDN. README.avmb1 - info on driver for AVM-B1 ISDN card. README.act2000 @@ -34,10 +26,25 @@ README.concap - info on "CONCAP" encapsulation protocol interface used for X.25. README.diversion - info on module for isdn diversion services. +README.fax + - info for using Fax over ISDN. +README.gigaset + - info on the drivers for Siemens Gigaset ISDN adapters +README.hfc-pci + - info on hfc-pci based cards. +README.hysdn + - info on driver for Hypercope active HYSDN cards +README.icn + - info on the ICN-ISDN-card and its driver. +README.mISDN + - info on the Modular ISDN subsystem (mISDN) +README.pcbit + - info on the PCBIT-D ISDN adapter and driver. README.sc - info on driver for Spellcaster cards. +README.syncppp + - info on running Sync PPP over ISDN. README.x25 - _ info for running X.25 over ISDN. -README.hysdn - - info on driver for Hypercope active HYSDN cards - + - info on running X.25 over ISDN. +syncPPP.FAQ + - frequently asked questions about running PPP over ISDN. -- cgit v1.2.3 From 5cd2fe6d54c91aa76893b3034f5f3473063c0202 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Thu, 9 Apr 2009 14:09:36 +0000 Subject: RDS/IW+IB: Set recv ring low water mark to 1/2 full. Currently the recv ring low water mark is 1/4 the depth. Performance measurements show that this limits iWARP throughput by flow controlling the rds-stress senders. Setting it to 1/2 seems to max the T3 performance. I tried even higher levels but that didn't help and it started to increase the rds thread cpu utilization. Signed-off-by: Steve Wise Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/ib_ring.c | 2 +- net/rds/iw_ring.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rds/ib_ring.c b/net/rds/ib_ring.c index 99a6ccae964c..ff97e8eda858 100644 --- a/net/rds/ib_ring.c +++ b/net/rds/ib_ring.c @@ -137,7 +137,7 @@ int rds_ib_ring_empty(struct rds_ib_work_ring *ring) int rds_ib_ring_low(struct rds_ib_work_ring *ring) { - return __rds_ib_ring_used(ring) <= (ring->w_nr >> 2); + return __rds_ib_ring_used(ring) <= (ring->w_nr >> 1); } /* diff --git a/net/rds/iw_ring.c b/net/rds/iw_ring.c index d422d4b5deef..da8e3b63f663 100644 --- a/net/rds/iw_ring.c +++ b/net/rds/iw_ring.c @@ -137,7 +137,7 @@ int rds_iw_ring_empty(struct rds_iw_work_ring *ring) int rds_iw_ring_low(struct rds_iw_work_ring *ring) { - return __rds_iw_ring_used(ring) <= (ring->w_nr >> 2); + return __rds_iw_ring_used(ring) <= (ring->w_nr >> 1); } -- cgit v1.2.3 From 11bc9421da3040c71fc96da1a31e95217e8cf2af Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 9 Apr 2009 14:09:37 +0000 Subject: RDS: Correct some iw references in rdma_transport.c Had some lingering instances of _iw_ variable names from when the listen code was centralized into rdma_transport.c Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/rdma_transport.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 7b19024f9706..7d0f901c93d5 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c @@ -34,7 +34,7 @@ #include "rdma_transport.h" -static struct rdma_cm_id *rds_iw_listen_id; +static struct rdma_cm_id *rds_rdma_listen_id; int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, struct rdma_cm_event *event) @@ -161,7 +161,7 @@ static int __init rds_rdma_listen_init(void) rdsdebug("cm %p listening on port %u\n", cm_id, RDS_PORT); - rds_iw_listen_id = cm_id; + rds_rdma_listen_id = cm_id; cm_id = NULL; out: if (cm_id) @@ -171,10 +171,10 @@ out: static void rds_rdma_listen_stop(void) { - if (rds_iw_listen_id) { - rdsdebug("cm %p\n", rds_iw_listen_id); - rdma_destroy_id(rds_iw_listen_id); - rds_iw_listen_id = NULL; + if (rds_rdma_listen_id) { + rdsdebug("cm %p\n", rds_rdma_listen_id); + rdma_destroy_id(rds_rdma_listen_id); + rds_rdma_listen_id = NULL; } } -- cgit v1.2.3 From d39e0602bb987133321d358d9b837d67c27b223d Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Thu, 9 Apr 2009 14:09:38 +0000 Subject: RDS/IW+IB: Set the RDS_LL_SEND_FULL bit when we're throttled. The RDS_LL_SEND_FULL bit should be set when we stop transmitted due to flow control. Otherwise the send worker will keep trying as opposed to sleeping until we unthrottle. Saves CPU. Signed-off-by: Steve Wise Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/ib_send.c | 2 +- net/rds/iw_send.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index cb6c52cb1c4c..fa684b7fc748 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -506,7 +506,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, flow_controlled++; } if (work_alloc == 0) { - rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc); + set_bit(RDS_LL_SEND_FULL, &conn->c_flags); rds_ib_stats_inc(s_ib_tx_throttle); ret = -ENOMEM; goto out; diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 22dd38ffd608..626290bc7e97 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c @@ -549,7 +549,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, flow_controlled++; } if (work_alloc == 0) { - rds_iw_ring_unalloc(&ic->i_send_ring, work_alloc); + set_bit(RDS_LL_SEND_FULL, &conn->c_flags); rds_iw_stats_inc(s_iw_tx_throttle); ret = -ENOMEM; goto out; -- cgit v1.2.3 From 7b70d0336da777c00395cc7a503497c2cdabd1a8 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Thu, 9 Apr 2009 14:09:39 +0000 Subject: RDS/IW+IB: Allow max credit advertise window. Fix hack that restricts the credit advertisement to 127. Signed-off-by: Steve Wise Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/ib.h | 2 +- net/rds/ib_recv.c | 2 +- net/rds/ib_send.c | 8 ++++---- net/rds/iw.h | 2 +- net/rds/iw_recv.c | 2 +- net/rds/iw_send.c | 8 ++++---- net/rds/rds.h | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/net/rds/ib.h b/net/rds/ib.h index 069206cae733..455ae73047fe 100644 --- a/net/rds/ib.h +++ b/net/rds/ib.h @@ -333,7 +333,7 @@ int rds_ib_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op); void rds_ib_send_add_credits(struct rds_connection *conn, unsigned int credits); void rds_ib_advertise_credits(struct rds_connection *conn, unsigned int posted); int rds_ib_send_grab_credits(struct rds_ib_connection *ic, u32 wanted, - u32 *adv_credits, int need_posted); + u32 *adv_credits, int need_posted, int max_posted); /* ib_stats.c */ DECLARE_PER_CPU(struct rds_ib_statistics, rds_ib_stats); diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 36d931573ff4..5709bad28329 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c @@ -524,7 +524,7 @@ void rds_ib_attempt_ack(struct rds_ib_connection *ic) } /* Can we get a send credit? */ - if (!rds_ib_send_grab_credits(ic, 1, &adv_credits, 0)) { + if (!rds_ib_send_grab_credits(ic, 1, &adv_credits, 0, RDS_MAX_ADV_CREDIT)) { rds_ib_stats_inc(s_ib_tx_throttle); clear_bit(IB_ACK_IN_FLIGHT, &ic->i_ack_flags); return; diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index fa684b7fc748..23bf830db2d5 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -311,7 +311,7 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) * and using atomic_cmpxchg when updating the two counters. */ int rds_ib_send_grab_credits(struct rds_ib_connection *ic, - u32 wanted, u32 *adv_credits, int need_posted) + u32 wanted, u32 *adv_credits, int need_posted, int max_posted) { unsigned int avail, posted, got = 0, advertise; long oldval, newval; @@ -351,7 +351,7 @@ try_again: * available. */ if (posted && (got || need_posted)) { - advertise = min_t(unsigned int, posted, RDS_MAX_ADV_CREDIT); + advertise = min_t(unsigned int, posted, max_posted); newval -= IB_SET_POST_CREDITS(advertise); } @@ -498,7 +498,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, credit_alloc = work_alloc; if (ic->i_flowctl) { - credit_alloc = rds_ib_send_grab_credits(ic, work_alloc, &posted, 0); + credit_alloc = rds_ib_send_grab_credits(ic, work_alloc, &posted, 0, RDS_MAX_ADV_CREDIT); adv_credits += posted; if (credit_alloc < work_alloc) { rds_ib_ring_unalloc(&ic->i_send_ring, work_alloc - credit_alloc); @@ -571,7 +571,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, /* * Update adv_credits since we reset the ACK_REQUIRED bit. */ - rds_ib_send_grab_credits(ic, 0, &posted, 1); + rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); adv_credits += posted; BUG_ON(adv_credits > 255); } else if (ic->i_rm != rm) diff --git a/net/rds/iw.h b/net/rds/iw.h index b4fb27252895..0715dde323e7 100644 --- a/net/rds/iw.h +++ b/net/rds/iw.h @@ -361,7 +361,7 @@ int rds_iw_xmit_rdma(struct rds_connection *conn, struct rds_rdma_op *op); void rds_iw_send_add_credits(struct rds_connection *conn, unsigned int credits); void rds_iw_advertise_credits(struct rds_connection *conn, unsigned int posted); int rds_iw_send_grab_credits(struct rds_iw_connection *ic, u32 wanted, - u32 *adv_credits, int need_posted); + u32 *adv_credits, int need_posted, int max_posted); /* ib_stats.c */ DECLARE_PER_CPU(struct rds_iw_statistics, rds_iw_stats); diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index fde470fa50d5..8683f5f66c4b 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c @@ -524,7 +524,7 @@ void rds_iw_attempt_ack(struct rds_iw_connection *ic) } /* Can we get a send credit? */ - if (!rds_iw_send_grab_credits(ic, 1, &adv_credits, 0)) { + if (!rds_iw_send_grab_credits(ic, 1, &adv_credits, 0, RDS_MAX_ADV_CREDIT)) { rds_iw_stats_inc(s_iw_tx_throttle); clear_bit(IB_ACK_IN_FLIGHT, &ic->i_ack_flags); return; diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 626290bc7e97..44a6a0551f28 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c @@ -347,7 +347,7 @@ void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context) * and using atomic_cmpxchg when updating the two counters. */ int rds_iw_send_grab_credits(struct rds_iw_connection *ic, - u32 wanted, u32 *adv_credits, int need_posted) + u32 wanted, u32 *adv_credits, int need_posted, int max_posted) { unsigned int avail, posted, got = 0, advertise; long oldval, newval; @@ -387,7 +387,7 @@ try_again: * available. */ if (posted && (got || need_posted)) { - advertise = min_t(unsigned int, posted, RDS_MAX_ADV_CREDIT); + advertise = min_t(unsigned int, posted, max_posted); newval -= IB_SET_POST_CREDITS(advertise); } @@ -541,7 +541,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, credit_alloc = work_alloc; if (ic->i_flowctl) { - credit_alloc = rds_iw_send_grab_credits(ic, work_alloc, &posted, 0); + credit_alloc = rds_iw_send_grab_credits(ic, work_alloc, &posted, 0, RDS_MAX_ADV_CREDIT); adv_credits += posted; if (credit_alloc < work_alloc) { rds_iw_ring_unalloc(&ic->i_send_ring, work_alloc - credit_alloc); @@ -614,7 +614,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, /* * Update adv_credits since we reset the ACK_REQUIRED bit. */ - rds_iw_send_grab_credits(ic, 0, &posted, 1); + rds_iw_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); adv_credits += posted; BUG_ON(adv_credits > 255); } else if (ic->i_rm != rm) diff --git a/net/rds/rds.h b/net/rds/rds.h index 619f0a30a4e5..1f82ec0d2066 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -132,7 +132,7 @@ struct rds_connection { #define RDS_FLAG_CONG_BITMAP 0x01 #define RDS_FLAG_ACK_REQUIRED 0x02 #define RDS_FLAG_RETRANSMITTED 0x04 -#define RDS_MAX_ADV_CREDIT 127 +#define RDS_MAX_ADV_CREDIT 255 /* * Maximum space available for extension headers. -- cgit v1.2.3 From 7acd4a794c1530af063e51f3f7171e75556458f3 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 9 Apr 2009 14:09:40 +0000 Subject: RDS: Fix ordering in a conditional Putting the constant first is a supposed "best practice" that actually makes the code harder to read. Thanks to Roland Dreier for finding a bug in this "simple, obviously correct" patch. Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/rdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rds/rdma.c b/net/rds/rdma.c index eaeeb91e1119..e390dc70b9d9 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -155,7 +155,7 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages, nr_pages, write, 0, pages, NULL); up_read(¤t->mm->mmap_sem); - if (0 <= ret && (unsigned) ret < nr_pages) { + if (ret >= 0 && ret < nr_pages) { while (ret--) put_page(pages[ret]); ret = -EFAULT; -- cgit v1.2.3 From 49f696914100780f6bf8e652d3468de0015d6172 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 9 Apr 2009 14:09:41 +0000 Subject: RDS: Establish connection before parsing CMSGs The first message to a remote node should prompt a new connection. Even an RDMA op via CMSG. Therefore move CMSG parsing to after connection establishment. Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/send.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/rds/send.c b/net/rds/send.c index 104fe033203d..a4a7f428cd76 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -854,11 +854,6 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rm->m_daddr = daddr; - /* Parse any control messages the user may have included. */ - ret = rds_cmsg_send(rs, rm, msg, &allocated_mr); - if (ret) - goto out; - /* rds_conn_create has a spinlock that runs with IRQ off. * Caching the conn in the socket helps a lot. */ if (rs->rs_conn && rs->rs_conn->c_faddr == daddr) @@ -874,6 +869,11 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rs->rs_conn = conn; } + /* Parse any control messages the user may have included. */ + ret = rds_cmsg_send(rs, rm, msg, &allocated_mr); + if (ret) + goto out; + if ((rm->m_rdma_cookie || rm->m_rdma_op) && conn->c_trans->xmit_rdma == NULL) { if (printk_ratelimit()) -- cgit v1.2.3 From 830eb7d56c18ff4c29acd8b0bb48db404660321f Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 9 Apr 2009 14:09:42 +0000 Subject: RDS: use get_user_pages_fast() Use the new function that is simpler and faster. Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/info.c | 5 +---- net/rds/rdma.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/net/rds/info.c b/net/rds/info.c index 1d885535214d..62aeef37aefe 100644 --- a/net/rds/info.c +++ b/net/rds/info.c @@ -188,10 +188,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval, ret = -ENOMEM; goto out; } - down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, start, nr_pages, 1, 0, - pages, NULL); - up_read(¤t->mm->mmap_sem); + ret = get_user_pages_fast(start, nr_pages, 1, pages); if (ret != nr_pages) { if (ret > 0) nr_pages = ret; diff --git a/net/rds/rdma.c b/net/rds/rdma.c index e390dc70b9d9..8dc83d2caa58 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -150,10 +150,7 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages, { int ret; - down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, user_addr, - nr_pages, write, 0, pages, NULL); - up_read(¤t->mm->mmap_sem); + ret = get_user_pages_fast(user_addr, nr_pages, write, pages); if (ret >= 0 && ret < nr_pages) { while (ret--) -- cgit v1.2.3 From 9c56a84478b708e5d8d34d28cc3a8e71842d5b05 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 9 Apr 2009 14:09:43 +0000 Subject: RDS: remove unused #include Remove unused #include in net/rds/af_rds.c. Signed-off-by: Huang Weiyi Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/af_rds.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 20cf16fc572f..b11e7e527864 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include "rds.h" -- cgit v1.2.3 From 05a178ecdc7396b78dfbb5d8bda65108b37b8672 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 9 Apr 2009 14:09:44 +0000 Subject: rds: use kmem_cache_zalloc instead of kmem_cache_alloc/memset Use kmem_cache_zalloc instead of kmem_cache_alloc/memset. Signed-off-by: Wei Yongjun Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/connection.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/rds/connection.c b/net/rds/connection.c index 273f064930a8..d14445c48304 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c @@ -148,14 +148,12 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, if (conn) goto out; - conn = kmem_cache_alloc(rds_conn_slab, gfp); + conn = kmem_cache_zalloc(rds_conn_slab, gfp); if (conn == NULL) { conn = ERR_PTR(-ENOMEM); goto out; } - memset(conn, 0, sizeof(*conn)); - INIT_HLIST_NODE(&conn->c_hash_node); conn->c_version = RDS_PROTOCOL_3_0; conn->c_laddr = laddr; -- cgit v1.2.3 From 5d57eeb52ae71a03c8e083a9b0a818a9b63ca440 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 9 Apr 2009 14:09:45 +0000 Subject: ERR_PTR() dereference in net/rds/iw.c rdma_create_id() returns ERR_PTR() not null. Found by smatch (http://repo.or.cz/w/smatch.git). Compile tested. regards, dan carpenter Signed-off-by: Dan Carpenter Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/iw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rds/iw.c b/net/rds/iw.c index b732efb5b634..d16e1cbc8e83 100644 --- a/net/rds/iw.c +++ b/net/rds/iw.c @@ -233,8 +233,8 @@ static int rds_iw_laddr_check(__be32 addr) * IB and iWARP capable NICs. */ cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP); - if (!cm_id) - return -EADDRNOTAVAIL; + if (IS_ERR(cm_id)) + return PTR_ERR(cm_id); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; -- cgit v1.2.3 From 94713bab649736177a1c33a39b7bb33cbd5af3a5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 9 Apr 2009 14:09:46 +0000 Subject: ERR_PTR() dereference in net/rds/ib.c rdma_create_id() doesn't return NULL, only ERR_PTR(). Found by smatch (http://repo.or.cz/w/smatch.git). Compile tested. regards, dan carpenter Signed-off-by: Dan Carpenter Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- net/rds/ib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rds/ib.c b/net/rds/ib.c index 4933b380985e..b9bcd32431e1 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -224,8 +224,8 @@ static int rds_ib_laddr_check(__be32 addr) * IB and iWARP capable NICs. */ cm_id = rdma_create_id(NULL, NULL, RDMA_PS_TCP); - if (!cm_id) - return -EADDRNOTAVAIL; + if (IS_ERR(cm_id)) + return PTR_ERR(cm_id); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; -- cgit v1.2.3 From fbb5a5583034e98f87fcff94183637486d7ada18 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 9 Apr 2009 14:09:47 +0000 Subject: MAINTAINERS: rds list is moderated Signed-off-by: Kyle McMartin Signed-off-by: Andy Grover Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index c3b215970f7b..28421c22ebae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3729,7 +3729,7 @@ S: Maintained RDS - RELIABLE DATAGRAM SOCKETS P: Andy Grover M: andy.grover@oracle.com -L: rds-devel@oss.oracle.com +L: rds-devel@oss.oracle.com (moderated for non-subscribers) S: Supported READ-COPY UPDATE (RCU) -- cgit v1.2.3 From 2132d38133f48ef51d28252bb9c0b792f5b57019 Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 9 Apr 2009 22:26:21 +0000 Subject: ixgbe: Enable another bit for flow control operation The discard pause frames bit was not enabled, so flow control frames could be passed up to the host. Enabled DPF to keep the frames off the stack. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 1 + drivers/net/ixgbe/ixgbe_common.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index de4db0dc7879..63aacd53aab7 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -322,6 +322,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) } /* Enable 802.3x based flow control settings. */ + fctrl_reg |= IXGBE_FCTRL_DPF; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 63ab6671d08e..846c9deeaa7a 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1700,6 +1700,7 @@ s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num) } /* Enable 802.3x based flow control settings. */ + mflcn_reg |= IXGBE_MFLCN_DPF; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); -- cgit v1.2.3 From d988eadbe2d93b5a2d4aa4ec46264e0f6213a71c Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 9 Apr 2009 22:26:40 +0000 Subject: ixgbe: fix IXGBE_MTQC values IXGBE_MTQC_64VF was wrong and 32VF not defined at all. This patch corrects that. Signed-off-by: Don Skidmore Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_type.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 030ff0a9ea67..0d250360b97e 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1553,7 +1553,8 @@ #define IXGBE_MTQC_RT_ENA 0x1 /* DCB Enable */ #define IXGBE_MTQC_VT_ENA 0x2 /* VMDQ2 Enable */ #define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */ -#define IXGBE_MTQC_64VF 0x8 /* 2 TX Queues per pool w/64VF's */ +#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */ +#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */ #define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */ /* Receive Descriptor bit definitions */ -- cgit v1.2.3 From 6e4e87d68a89028204fe744a8eda8f74bff5b6a9 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 9 Apr 2009 22:27:00 +0000 Subject: ixgbe: add support for addition VT_CTL defines These defines allow for definition of target pool for packets that pass L2 filtering but didn't pass any of the pool filters. They are needed to reset the default pool. Signed-off-by: Don Skidmore Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_type.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 0d250360b97e..50285c2dd8d3 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -958,6 +958,8 @@ #define IXGBE_VT_CTL_DIS_DEFPL 0x20000000 /* disable default pool */ #define IXGBE_VT_CTL_REPLEN 0x40000000 /* replication enabled */ #define IXGBE_VT_CTL_VT_ENABLE 0x00000001 /* Enable VT Mode */ +#define IXGBE_VT_CTL_POOL_SHIFT 7 +#define IXGBE_VT_CTL_POOL_MASK (0x3F << IXGBE_VT_CTL_POOL_SHIFT) /* VMOLR bitmasks */ #define IXGBE_VMOLR_AUPE 0x01000000 /* accept untagged packets */ -- cgit v1.2.3 From e80e887a959ca41066412582c5f79aae5ffd5821 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 9 Apr 2009 22:27:19 +0000 Subject: ixgbe: add define to support 82599 64 IVAR registers 82599 supports 64 IVAR registers this patch adds a define to allow us to access them. Signed-off-by: Don Skidmore Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_type.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 50285c2dd8d3..96e15d010906 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1150,6 +1150,7 @@ /* Interrupt Vector Allocation Registers */ #define IXGBE_IVAR_REG_NUM 25 +#define IXGBE_IVAR_REG_NUM_82599 64 #define IXGBE_IVAR_TXRX_ENTRY 96 #define IXGBE_IVAR_RX_ENTRY 64 #define IXGBE_IVAR_RX_QUEUE(_i) (0 + (_i)) -- cgit v1.2.3 From d3e9c56cafb98040c8601dcc784a773ac86da18b Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 9 Apr 2009 22:27:39 +0000 Subject: ixgbe: Don't return error in flow control configuration if FC is off When flow control is disabled, an invalid low/high watermark configuration should not matter. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 8 +++++--- drivers/net/ixgbe/ixgbe_common.c | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 63aacd53aab7..1e1d8b79f9e3 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -381,9 +381,11 @@ static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num) * because it causes the controller to just blast out fc packets. */ if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { - hw_dbg(hw, "Invalid water mark configuration\n"); - ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; - goto out; + if (hw->fc.requested_mode != ixgbe_fc_none) { + hw_dbg(hw, "Invalid water mark configuration\n"); + ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } } /* diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 846c9deeaa7a..2d4af5d2d3f7 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1907,9 +1907,11 @@ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num) * because it causes the controller to just blast out fc packets. */ if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { - hw_dbg(hw, "Invalid water mark configuration\n"); - ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; - goto out; + if (hw->fc.requested_mode != ixgbe_fc_none) { + hw_dbg(hw, "Invalid water mark configuration\n"); + ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; + goto out; + } } /* -- cgit v1.2.3 From 04f165ef4f18444854865d44a3359618480060af Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 9 Apr 2009 22:27:57 +0000 Subject: ixgbe: Move PHY ops initialization to centralize bus accesses When PHY operations are determined, the PHY must be identified. This identification causes bus access, and should be contained within its own routines. This also helps the 82599 PHY init paths for both SFP+ and KX/KX4 devices to be easier to maintain. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 77 ++++++++++++++++++++++++++++------------- drivers/net/ixgbe/ixgbe_82599.c | 70 ++++++++++++++++++++++++------------- drivers/net/ixgbe/ixgbe_main.c | 9 ++++- drivers/net/ixgbe/ixgbe_type.h | 1 + 4 files changed, 107 insertions(+), 50 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 1e1d8b79f9e3..a8151f25a4d0 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -73,20 +73,51 @@ static u16 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw) /** */ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + + /* Call PHY identify routine to get the phy type */ + ixgbe_identify_phy_generic(hw); + + mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; + mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; + mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; + mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw); + + return 0; +} + +/** + * ixgbe_init_phy_ops_82598 - PHY/SFP specific init + * @hw: pointer to hardware structure + * + * Initialize any function pointers that were not able to be + * set during get_invariants because the PHY/SFP type was + * not known. Perform the SFP init if necessary. + * + **/ +s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val = 0; u16 list_offset, data_offset; - /* Set the bus information prior to PHY identification */ - mac->ops.get_bus_info(hw); + /* Identify the PHY */ + phy->ops.identify(hw); - /* Call PHY identify routine to get the phy type */ - ixgbe_identify_phy_generic(hw); + /* Overwrite the link function pointers if copper PHY */ + if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { + mac->ops.setup_link = &ixgbe_setup_copper_link_82598; + mac->ops.setup_link_speed = + &ixgbe_setup_copper_link_speed_82598; + mac->ops.get_link_capabilities = + &ixgbe_get_copper_link_capabilities_82598; + } - /* PHY Init */ - switch (phy->type) { + switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = @@ -106,8 +137,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) /* Check to see if SFP+ module is supported */ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, - &list_offset, - &data_offset); + &list_offset, + &data_offset); if (ret_val != 0) { ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; @@ -117,21 +148,6 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) break; } - if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { - mac->ops.setup_link = &ixgbe_setup_copper_link_82598; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82598; - mac->ops.get_link_capabilities = - &ixgbe_get_copper_link_capabilities_82598; - } - - mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; - mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; - mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; - mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; - mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; - mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw); - out: return ret_val; } @@ -719,14 +735,23 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) } /* Reset PHY */ - if (hw->phy.reset_disable == false) + if (hw->phy.reset_disable == false) { + /* PHY ops must be identified and initialized prior to reset */ + + /* Init PHY and function pointers, perform SFP setup */ + status = hw->phy.ops.init(hw); + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto reset_hw_out; + hw->phy.ops.reset(hw); + } /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ - if (ixgbe_disable_pcie_master(hw) != 0) { + status = ixgbe_disable_pcie_master(hw); + if (status != 0) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); } @@ -773,6 +798,7 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); +reset_hw_out: return status; } @@ -1157,6 +1183,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = { static struct ixgbe_phy_operations phy_ops_82598 = { .identify = &ixgbe_identify_phy_generic, .identify_sfp = &ixgbe_identify_sfp_module_generic, + .init = &ixgbe_init_phy_ops_82598, .reset = &ixgbe_reset_phy_generic, .read_reg = &ixgbe_read_phy_reg_generic, .write_reg = &ixgbe_write_phy_reg_generic, diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index beae7e012609..9a9998985004 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -148,51 +148,60 @@ u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw) static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; - struct ixgbe_phy_info *phy = &hw->phy; - s32 ret_val; - /* Set the bus information prior to PHY identification */ - mac->ops.get_bus_info(hw); + ixgbe_init_mac_link_ops_82599(hw); - /* Call PHY identify routine to get the Cu or SFI phy type */ - ret_val = phy->ops.identify(hw); + mac->mcft_size = IXGBE_82599_MC_TBL_SIZE; + mac->vft_size = IXGBE_82599_VFT_TBL_SIZE; + mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES; + mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw); - if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) - goto get_invariants_out; + return 0; +} - ixgbe_init_mac_link_ops_82599(hw); +/** + * ixgbe_init_phy_ops_82599 - PHY/SFP specific init + * @hw: pointer to hardware structure + * + * Initialize any function pointers that were not able to be + * set during get_invariants because the PHY/SFP type was + * not known. Perform the SFP init if necessary. + * + **/ +s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) +{ + struct ixgbe_mac_info *mac = &hw->mac; + struct ixgbe_phy_info *phy = &hw->phy; + s32 ret_val = 0; - /* Setup SFP module if there is one present. */ - ret_val = mac->ops.setup_sfp(hw); + /* Identify the PHY or SFP module */ + ret_val = phy->ops.identify(hw); + + /* Setup function pointers based on detected SFP module and speeds */ + ixgbe_init_mac_link_ops_82599(hw); /* If copper media, overwrite with copper function pointers */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82599; mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82599; + &ixgbe_setup_copper_link_speed_82599; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_82599; } - /* PHY Init */ + /* Set necessary function pointers based on phy type */ switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = - &ixgbe_get_phy_firmware_version_tnx; + &ixgbe_get_phy_firmware_version_tnx; break; default: break; } - mac->mcft_size = IXGBE_82599_MC_TBL_SIZE; - mac->vft_size = IXGBE_82599_VFT_TBL_SIZE; - mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES; - mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES; - mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; - mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw); - -get_invariants_out: return ret_val; } @@ -708,13 +717,24 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) hw->mac.ops.stop_adapter(hw); /* Reset PHY */ - hw->phy.ops.reset(hw); + if (hw->phy.reset_disable == false) { + /* PHY ops must be identified and initialized prior to reset */ + + /* Init PHY and function pointers, perform SFP setup */ + status = hw->phy.ops.init(hw); + + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto reset_hw_out; + + hw->phy.ops.reset(hw); + } /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ - if (ixgbe_disable_pcie_master(hw) != 0) { + status = ixgbe_disable_pcie_master(hw); + if (status != 0) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); } @@ -775,6 +795,7 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); +reset_hw_out: return status; } @@ -1272,6 +1293,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = { static struct ixgbe_phy_operations phy_ops_82599 = { .identify = &ixgbe_identify_phy_82599, .identify_sfp = &ixgbe_identify_sfp_module_generic, + .init = &ixgbe_init_phy_ops_82599, .reset = &ixgbe_reset_phy_generic, .read_reg = &ixgbe_read_phy_reg_generic, .write_reg = &ixgbe_write_phy_reg_generic, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 9ef128ae6458..936a3efb3621 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4630,7 +4630,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* reset_hw fills in the perm_addr as well */ err = hw->mac.ops.reset_hw(hw); - if (err) { + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { + dev_err(&adapter->pdev->dev, "failed to load because an " + "unsupported SFP+ module type was detected.\n"); + goto err_sw_init; + } else if (err) { dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); goto err_sw_init; } @@ -4703,6 +4707,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, device_init_wakeup(&adapter->pdev->dev, true); device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + /* pick up the PCI bus settings for reporting later */ + hw->mac.ops.get_bus_info(hw); + /* print bus type/speed/width info */ dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n", ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s": diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 96e15d010906..06d7e8ae6225 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2150,6 +2150,7 @@ struct ixgbe_mac_operations { struct ixgbe_phy_operations { s32 (*identify)(struct ixgbe_hw *); s32 (*identify_sfp)(struct ixgbe_hw *); + s32 (*init)(struct ixgbe_hw *); s32 (*reset)(struct ixgbe_hw *); s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *); s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16); -- cgit v1.2.3 From 553b449784e27bb7244c41aa27397d29f213e5a3 Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 9 Apr 2009 22:28:15 +0000 Subject: ixgbe: Remove unnecessary PHY reset, properly identify multispeed fiber modules This patch does two things: 1) On 82599, the PHY is emedded in the MAC. On 82598, the SFP+ NIC has an external PHY. The reset in the SFP+ setup patch for 82598 is unnecessary on 82599, and adds extra dead time to device initialization. This removes that PHY reset for 82599 only. 2) On 82599, the SFP+ modules are multispeed fiber modules (10G/1G). We need to make sure to identify them properly for the remaining init sections to properly set them up. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 24 ++++++++++++++++-------- drivers/net/ixgbe/ixgbe_phy.c | 11 +++++++++++ drivers/net/ixgbe/ixgbe_phy.h | 1 + drivers/net/ixgbe/ixgbe_type.h | 1 + 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 9a9998985004..72a0d27a19af 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -102,6 +102,9 @@ s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { ixgbe_init_mac_link_ops_82599(hw); + + hw->phy.ops.reset = NULL; + ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); @@ -716,19 +719,24 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); - /* Reset PHY */ - if (hw->phy.reset_disable == false) { - /* PHY ops must be identified and initialized prior to reset */ + /* PHY ops must be identified and initialized prior to reset */ - /* Init PHY and function pointers, perform SFP setup */ - status = hw->phy.ops.init(hw); + /* Init PHY and function pointers, perform SFP setup */ + status = hw->phy.ops.init(hw); - if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) - goto reset_hw_out; + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) + goto reset_hw_out; - hw->phy.ops.reset(hw); + /* Setup SFP module if there is one present. */ + if (hw->phy.sfp_setup_needed) { + status = hw->mac.ops.setup_sfp(hw); + hw->phy.sfp_setup_needed = false; } + /* Reset PHY */ + if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL) + hw->phy.ops.reset(hw); + /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 14e9606aa3b3..6f11df756daa 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -552,6 +552,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 vendor_oui = 0; + enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; u8 identifier = 0; u8 comp_codes_1g = 0; u8 comp_codes_10g = 0; @@ -620,6 +621,16 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.sfp_type = ixgbe_sfp_type_unknown; } + if (hw->phy.sfp_type != stored_sfp_type) + hw->phy.sfp_setup_needed = true; + + /* Determine if the SFP+ PHY is dual speed or not. */ + if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) && + (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) || + ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && + (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) + hw->phy.multispeed_fiber = true; + /* Determine PHY vendor */ if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.id = identifier; diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index cc5f1b3287e1..c9964b7ce1b9 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -44,6 +44,7 @@ /* Bitmasks */ #define IXGBE_SFF_TWIN_AX_CAPABLE 0x80 #define IXGBE_SFF_1GBASESX_CAPABLE 0x1 +#define IXGBE_SFF_1GBASELX_CAPABLE 0x2 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 #define IXGBE_SFF_10GBASELR_CAPABLE 0x20 #define IXGBE_I2C_EEPROM_READ_MASK 0x100 diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 06d7e8ae6225..db65c05773ad 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2198,6 +2198,7 @@ struct ixgbe_phy_info { u32 addr; u32 id; enum ixgbe_sfp_type sfp_type; + bool sfp_setup_needed; u32 revision; enum ixgbe_media_type media_type; bool reset_disable; -- cgit v1.2.3 From 1eb99d5ac44e2a9ac0b2856c579ba4d7cc349ada Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Thu, 9 Apr 2009 22:28:33 +0000 Subject: ixgbe: Update the usage of orig_autoc to be more consistent The orig_autoc variable tracks the original setting of the autonegotiate state prior to trying a new speed. The usage is inconsistent and not very maintainable. This patch updates the usage to make it more consistent. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 15 +++++++++++---- drivers/net/ixgbe/ixgbe_82599.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index a8151f25a4d0..361c9d1d0117 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -165,12 +165,19 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, bool *autoneg) { s32 status = 0; + u32 autoc = 0; /* * Determine link capabilities based on the stored value of AUTOC, - * which represents EEPROM defaults. + * which represents EEPROM defaults. If AUTOC value has not been + * stored, use the current register value. */ - switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) { + if (hw->mac.orig_link_settings_stored) + autoc = hw->mac.orig_autoc; + else + autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; @@ -189,9 +196,9 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) + if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 72a0d27a19af..50b399c1e87f 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -221,8 +221,19 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, bool *negotiation) { s32 status = 0; + u32 autoc = 0; - switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) { + /* + * Determine link capabilities based on the stored value of AUTOC, + * which represents EEPROM defaults. If AUTOC value has not been + * stored, use the current register value. + */ + if (hw->mac.orig_link_settings_stored) + autoc = hw->mac.orig_autoc; + else + autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *negotiation = false; @@ -246,22 +257,22 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, case IXGBE_AUTOC_LMS_KX4_KX_KR: case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP) + if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) + if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII: *speed = IXGBE_LINK_SPEED_100_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP) + if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP) + if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; @@ -572,6 +583,7 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, s32 status = 0; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); + u32 orig_autoc = 0; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; @@ -583,6 +595,13 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, hw->mac.ops.get_link_capabilities(hw, &link_capabilities, &autoneg); speed &= link_capabilities; + /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/ + if (hw->mac.orig_link_settings_stored) + orig_autoc = hw->mac.orig_autoc; + else + orig_autoc = autoc; + + if (speed == IXGBE_LINK_SPEED_UNKNOWN) { status = IXGBE_ERR_LINK_SETUP; } else if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || @@ -591,9 +610,9 @@ s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, /* Set KX4/KX/KR support according to speed requested */ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); if (speed & IXGBE_LINK_SPEED_10GB_FULL) - if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP) + if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; - if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP) + if (orig_autoc & IXGBE_AUTOC_KR_SUPP) autoc |= IXGBE_AUTOC_KR_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; -- cgit v1.2.3 From 04193058c1005551af93f04a4b975fbd7f95cad5 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Thu, 9 Apr 2009 22:28:50 +0000 Subject: ixgbe: Update get_physical_layer() calls, plus a version bump Not all physical connection types are being correctly identified. This fixes that issue, and cleans up the logic to make it more maintainable. Also clean up the code for device capabilities from the EEPROM to support multiple SKUs of the same hardware. Bump the version to reflect all the updates since the 82599 merge. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 85 +++++++++++++++++-------- drivers/net/ixgbe/ixgbe_82599.c | 134 +++++++++++++++++++++++++++++----------- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/ixgbe/ixgbe_phy.c | 8 +-- drivers/net/ixgbe/ixgbe_type.h | 10 ++- 5 files changed, 169 insertions(+), 70 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 361c9d1d0117..a7ae4d45b53d 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1089,35 +1089,56 @@ out: static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; + u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; + u16 ext_ability = 0; + + hw->phy.ops.identify(hw); + + /* Copper PHY must be checked before AUTOC LMS to determine correct + * physical layer because 10GBase-T PHYs use LMS = KX4/KX */ + if (hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_cu_unknown) { + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); + if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; + if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; + if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) + physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; + goto out; + } - switch (hw->device_id) { - case IXGBE_DEV_ID_82598: - /* Default device ID is mezzanine card KX/KX4 */ - physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | - IXGBE_PHYSICAL_LAYER_1000BASE_KX); - break; - case IXGBE_DEV_ID_82598_BX: - physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; - case IXGBE_DEV_ID_82598EB_CX4: - case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; - break; - case IXGBE_DEV_ID_82598_DA_DUAL_PORT: - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + switch (autoc & IXGBE_AUTOC_LMS_MASK) { + case IXGBE_AUTOC_LMS_1G_AN: + case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: + if (pma_pmd_1g == IXGBE_AUTOC_1G_KX) + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX; + else + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; break; - case IXGBE_DEV_ID_82598AF_DUAL_PORT: - case IXGBE_DEV_ID_82598AF_SINGLE_PORT: - case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: + if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; + else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; + else /* XAUI */ + physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; - case IXGBE_DEV_ID_82598EB_XF_LR: - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + case IXGBE_AUTOC_LMS_KX4_AN: + case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: + if (autoc & IXGBE_AUTOC_KX_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; + if (autoc & IXGBE_AUTOC_KX4_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; break; - case IXGBE_DEV_ID_82598AT: - physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T | - IXGBE_PHYSICAL_LAYER_1000BASE_T); + default: break; - case IXGBE_DEV_ID_82598EB_SFP_LOM: + } + + if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.identify_sfp(hw); switch (hw->phy.sfp_type) { @@ -1134,13 +1155,25 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } - break; + } + switch (hw->device_id) { + case IXGBE_DEV_ID_82598_DA_DUAL_PORT: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + break; + case IXGBE_DEV_ID_82598AF_DUAL_PORT: + case IXGBE_DEV_ID_82598AF_SINGLE_PORT: + case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + break; + case IXGBE_DEV_ID_82598EB_XF_LR: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + break; default: - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } +out: return physical_layer; } diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 50b399c1e87f..b3f4e96a018c 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1177,53 +1177,98 @@ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); + u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; + u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; + u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; + u16 ext_ability = 0; u8 comp_codes_10g = 0; - switch (hw->device_id) { - case IXGBE_DEV_ID_82599: - case IXGBE_DEV_ID_82599_KX4: - /* Default device ID is mezzanine card KX/KX4 */ - physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | - IXGBE_PHYSICAL_LAYER_1000BASE_KX); + hw->phy.ops.identify(hw); + + if (hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_cu_unknown) { + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); + if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; + if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; + if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) + physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; + goto out; + } + + switch (autoc & IXGBE_AUTOC_LMS_MASK) { + case IXGBE_AUTOC_LMS_1G_AN: + case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: + if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) { + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX | + IXGBE_PHYSICAL_LAYER_1000BASE_BX; + goto out; + } else + /* SFI mode so read SFP module */ + goto sfp_check; break; - case IXGBE_DEV_ID_82599_SFP: - hw->phy.ops.identify_sfp(hw); + case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: + if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; + else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; + goto out; + break; + case IXGBE_AUTOC_LMS_10G_SERIAL: + if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) { + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR; + goto out; + } else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) + goto sfp_check; + break; + case IXGBE_AUTOC_LMS_KX4_KX_KR: + case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: + if (autoc & IXGBE_AUTOC_KX_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; + if (autoc & IXGBE_AUTOC_KX4_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; + if (autoc & IXGBE_AUTOC_KR_SUPP) + physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR; + goto out; + break; + default: + goto out; + break; + } - switch (hw->phy.sfp_type) { - case ixgbe_sfp_type_da_cu: - case ixgbe_sfp_type_da_cu_core0: - case ixgbe_sfp_type_da_cu_core1: - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; - break; - case ixgbe_sfp_type_sr: +sfp_check: + /* SFP check must be done last since DA modules are sometimes used to + * test KR mode - we need to id KR mode correctly before SFP module. + * Call identify_sfp because the pluggable module may have changed */ + hw->phy.ops.identify_sfp(hw); + if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) + goto out; + + switch (hw->phy.type) { + case ixgbe_phy_tw_tyco: + case ixgbe_phy_tw_unknown: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + break; + case ixgbe_phy_sfp_avago: + case ixgbe_phy_sfp_ftl: + case ixgbe_phy_sfp_intel: + case ixgbe_phy_sfp_unknown: + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); + if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; - break; - case ixgbe_sfp_type_lr: + else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; - break; - case ixgbe_sfp_type_srlr_core0: - case ixgbe_sfp_type_srlr_core1: - hw->phy.ops.read_i2c_eeprom(hw, - IXGBE_SFF_10GBE_COMP_CODES, - &comp_codes_10g); - if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) - physical_layer = - IXGBE_PHYSICAL_LAYER_10GBASE_SR; - else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) - physical_layer = - IXGBE_PHYSICAL_LAYER_10GBASE_LR; - else - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; - default: - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; - break; - } break; default: - physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } +out: return physical_layer; } @@ -1271,6 +1316,22 @@ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) return 0; } +/** + * ixgbe_get_device_caps_82599 - Get additional device capabilities + * @hw: pointer to hardware structure + * @device_caps: the EEPROM word with the extra device capabilities + * + * This function will read the EEPROM location for the device capabilities, + * and return the word through device_caps. + **/ +s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps) +{ + hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); + + return 0; +} + + static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, @@ -1280,6 +1341,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82599, .enable_rx_dma = &ixgbe_enable_rx_dma_82599, .get_mac_addr = &ixgbe_get_mac_addr_generic, + .get_device_caps = &ixgbe_get_device_caps_82599, .stop_adapter = &ixgbe_stop_adapter_generic, .get_bus_info = &ixgbe_get_bus_info_generic, .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 936a3efb3621..2856486e1655 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -47,7 +47,7 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "2.0.8-k2" +#define DRV_VERSION "2.0.16-k2" const char ixgbe_driver_version[] = DRV_VERSION; static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 6f11df756daa..f3258ec901fe 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -632,7 +632,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.multispeed_fiber = true; /* Determine PHY vendor */ - if (hw->phy.type == ixgbe_phy_unknown) { + if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = identifier; hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE0, @@ -682,9 +682,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) goto out; } - hw->eeprom.ops.read(hw, IXGBE_PHY_ENFORCE_INTEL_SFP_OFFSET, - &enforce_sfp); - if (!(enforce_sfp & IXGBE_PHY_ALLOW_ANY_SFP)) { + /* This is guaranteed to be 82599, no need to check for NULL */ + hw->mac.ops.get_device_caps(hw, &enforce_sfp); + if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) { status = 0; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index db65c05773ad..a3317d8fbf6a 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -862,6 +862,7 @@ #define IXGBE_MDIO_PHY_EXT_ABILITY 0xB /* Ext Ability Reg */ #define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */ #define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */ +#define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ @@ -898,8 +899,6 @@ #define IXGBE_CONTROL_NL 0x000F #define IXGBE_CONTROL_EOL_NL 0x0FFF #define IXGBE_CONTROL_SOL_NL 0x0000 -#define IXGBE_PHY_ENFORCE_INTEL_SFP_OFFSET 0x002C -#define IXGBE_PHY_ALLOW_ANY_SFP 0x1 /* General purpose Interrupt Enable */ #define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */ @@ -1385,6 +1384,7 @@ #define IXGBE_FW_PTR 0x0F #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 +#define IXGBE_DEVICE_CAPS 0x2C #define IXGBE_PCIE_MSIX_82599_CAPS 0x72 #define IXGBE_PCIE_MSIX_82598_CAPS 0x62 @@ -1428,6 +1428,8 @@ #define IXGBE_EERD_ATTEMPTS 100000 #endif +#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 + /* PCI Bus Info */ #define IXGBE_PCI_LINK_STATUS 0xB2 #define IXGBE_PCI_LINK_WIDTH 0x3F0 @@ -1865,7 +1867,7 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_UNKNOWN 0 #define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001 #define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002 -#define IXGBE_PHYSICAL_LAYER_100BASE_T 0x0004 +#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004 #define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008 #define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010 #define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020 @@ -1874,6 +1876,7 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100 #define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200 #define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400 +#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800 enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, @@ -2105,6 +2108,7 @@ struct ixgbe_mac_operations { enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); u32 (*get_supported_physical_layer)(struct ixgbe_hw *); s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); + s32 (*get_device_caps)(struct ixgbe_hw *, u16 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); void (*set_lan_id)(struct ixgbe_hw *); -- cgit v1.2.3 From 8d1c3c0746098bee8ad116073120166347f21719 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Thu, 9 Apr 2009 22:29:10 +0000 Subject: ixgbe: Be explict with what we are !'ing in ixgbe_sfp_config_module_task() GCC warns: drivers/net/ixgbe/ixgbe_main.c: In function 'ixgbe_sfp_config_module_task': drivers/net/ixgbe/ixgbe_main.c:3920: warning: suggest parantheses around operand of '!' or change '&' to '&&' or '!' to '~' Which I think is right. Bracket to remove ambiguity. Signed-off-by: Tony Breeds Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2856486e1655..813c5bc1a8fa 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3917,7 +3917,7 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) } hw->mac.ops.setup_sfp(hw); - if (!adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK) + if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK)) /* This will also work for DA Twinax connections */ schedule_work(&adapter->multispeed_fiber_task); adapter->flags &= ~IXGBE_FLAG_IN_SFP_MOD_TASK; -- cgit v1.2.3 From 728a9972d1f290608e730b9ccec2061aa81f6609 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Mon, 13 Apr 2009 15:41:22 -0700 Subject: be2net: changes for checksum and segmentation offload - Enables Rx checksum feature by default. - Disables support for ipv6 tso. - Changes in Rx path to handle Rx completions with various checksum options. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 9b75aa630062..8994b03d80ac 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -637,6 +637,22 @@ static void be_rx_stats_update(struct be_adapter *adapter, stats->be_rx_bytes += pktsize; } +static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) +{ + u8 l4_cksm, ip_version, ipcksm, tcpf = 0, udpf = 0, ipv6_chk; + + l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); + ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp); + ip_version = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp); + if (ip_version) { + tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); + udpf = AMAP_GET_BITS(struct amap_eth_rx_compl, udpf, rxcp); + } + ipv6_chk = (ip_version && (tcpf || udpf)); + + return ((l4_cksm && ipv6_chk && ipcksm) && cso) ? false : true; +} + static struct be_rx_page_info * get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) { @@ -752,9 +768,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, { struct sk_buff *skb; u32 vtp, vid; - int l4_cksm; - l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN); @@ -769,10 +783,10 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb_fill_rx_data(adapter, skb, rxcp); - if (l4_cksm && adapter->rx_csum) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else + if (do_pkt_csum(rxcp, adapter->rx_csum)) skb->ip_summed = CHECKSUM_NONE; + else + skb->ip_summed = CHECKSUM_UNNECESSARY; skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, adapter->netdev); @@ -1626,10 +1640,12 @@ static void be_netdev_init(struct net_device *netdev) netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + NETIF_F_IPV6_CSUM; netdev->flags |= IFF_MULTICAST; + adapter->rx_csum = true; + BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); -- cgit v1.2.3 From 54cb2284dce50672c40248b8e95940318ec2ca41 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 8 Apr 2009 22:16:38 +0000 Subject: at76c50x-usb: remove pointless conditional before kfree_skb() Remove pointless conditional before kfree_skb(). Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/wireless/at76c50x-usb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 0c02f1c2bd94..c220c9758d09 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -2309,8 +2309,7 @@ static void at76_delete_device(struct at76_priv *priv) del_timer_sync(&ledtrig_tx_timer); - if (priv->rx_skb) - kfree_skb(priv->rx_skb); + kfree_skb(priv->rx_skb); usb_put_dev(priv->udev); -- cgit v1.2.3 From 710b523ac59426e8bfdea3533f42118e46b9cbfb Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 9 Apr 2009 07:11:55 +0000 Subject: kaweth: Clean up code The driver kaweth yields a -EBUSY error when starting, and a -ETIME error when shutting down. These errors are avoided, and the RX status is further checked for other potential errors. Signed-off-by: Larry Finger Signed-off-by: David S. Miller --- drivers/net/usb/kaweth.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 3d0d0b0b37c5..e01314789718 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -31,7 +31,6 @@ ****************************************************************/ /* TODO: - * Fix in_interrupt() problem * Develop test procedures for USB net interfaces * Run test procedures * Fix bugs from previous two steps @@ -606,14 +605,30 @@ static void kaweth_usb_receive(struct urb *urb) struct sk_buff *skb; - if(unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) - /* we are killed - set a flag and wake the disconnect handler */ - { + if (unlikely(status == -EPIPE)) { + kaweth->stats.rx_errors++; kaweth->end = 1; wake_up(&kaweth->term_wait); + dbg("Status was -EPIPE."); return; } - + if (unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) { + /* we are killed - set a flag and wake the disconnect handler */ + kaweth->end = 1; + wake_up(&kaweth->term_wait); + dbg("Status was -ECONNRESET or -ESHUTDOWN."); + return; + } + if (unlikely(status == -EPROTO || status == -ETIME || + status == -EILSEQ)) { + kaweth->stats.rx_errors++; + dbg("Status was -EPROTO, -ETIME, or -EILSEQ."); + return; + } + if (unlikely(status == -EOVERFLOW)) { + kaweth->stats.rx_errors++; + dbg("Status was -EOVERFLOW."); + } spin_lock(&kaweth->device_lock); if (IS_BLOCKED(kaweth->status)) { spin_unlock(&kaweth->device_lock); @@ -883,13 +898,16 @@ static void kaweth_set_rx_mode(struct net_device *net) ****************************************************************/ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) { + int result; __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap; + kaweth->packet_filter_bitmap = 0; if (packet_filter_bitmap == 0) return; - { - int result; + if (in_interrupt()) + return; + result = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_PACKET_FILTER, @@ -906,7 +924,6 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) else { dbg("Set Rx mode to %d", packet_filter_bitmap); } - } } /**************************************************************** -- cgit v1.2.3 From 0ee904c35cc3fdd26a9c76077d9692d458309186 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Sat, 11 Apr 2009 14:50:23 +0000 Subject: drivers/net: replace BUG() with BUG_ON() if possible Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/atl1e/atl1e_main.c | 3 +-- drivers/net/atlx/atl1.c | 7 +++---- drivers/net/chelsio/sge.c | 4 ++-- drivers/net/fs_enet/mii-fec.c | 6 ++---- drivers/net/ixgb/ixgb_osdep.h | 2 +- drivers/net/pppol2tp.c | 3 +-- drivers/net/tulip/winbond-840.c | 3 +-- drivers/net/virtio_net.c | 12 ++++-------- drivers/net/wireless/ath5k/reset.c | 5 ++--- drivers/net/wireless/ath9k/ath9k.h | 6 +----- drivers/net/wireless/ipw2x00/ipw2200.c | 7 ++----- drivers/net/wireless/libertas/if_usb.c | 3 +-- drivers/net/wireless/libertas_tf/if_usb.c | 3 +-- 13 files changed, 22 insertions(+), 42 deletions(-) diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index fb57b750866b..adac06195c8f 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -1794,8 +1794,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc)); tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - if (tx_buffer->skb) - BUG(); + BUG_ON(tx_buffer->skb); tx_buffer->skb = NULL; tx_buffer->length = diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 0ab22540bf59..13f0bdc32449 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2207,8 +2207,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, nr_frags = skb_shinfo(skb)->nr_frags; next_to_use = atomic_read(&tpd_ring->next_to_use); buffer_info = &tpd_ring->buffer_info[next_to_use]; - if (unlikely(buffer_info->skb)) - BUG(); + BUG_ON(buffer_info->skb); /* put skb in last TPD */ buffer_info->skb = NULL; @@ -2274,8 +2273,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, ATL1_MAX_TX_BUF_LEN; for (i = 0; i < nseg; i++) { buffer_info = &tpd_ring->buffer_info[next_to_use]; - if (unlikely(buffer_info->skb)) - BUG(); + BUG_ON(buffer_info->skb); + buffer_info->skb = NULL; buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ? ATL1_MAX_TX_BUF_LEN : buf_len; diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 58f6fc055f6a..5e97a1a71d88 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1149,8 +1149,8 @@ static inline void write_tx_desc(struct cmdQ_e *e, dma_addr_t mapping, unsigned int len, unsigned int gen, unsigned int eop) { - if (unlikely(len > SGE_TX_DESC_MAX_PLEN)) - BUG(); + BUG_ON(len > SGE_TX_DESC_MAX_PLEN); + e->addr_lo = (u32)mapping; e->addr_hi = (u64)mapping >> 32; e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen); diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 28077cc1b949..61aaae444b40 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -54,8 +54,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) fec_t __iomem *fecp = fec->fecp; int i, ret = -1; - if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) - BUG(); + BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); /* Add PHY address to register command. */ out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); @@ -79,8 +78,7 @@ static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, int i; /* this must never happen */ - if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) - BUG(); + BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); /* Add PHY address to register command. */ out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h index d92e72bd627a..371a6be4d965 100644 --- a/drivers/net/ixgb/ixgb_osdep.h +++ b/drivers/net/ixgb/ixgb_osdep.h @@ -40,7 +40,7 @@ #include #undef ASSERT -#define ASSERT(x) if (!(x)) BUG() +#define ASSERT(x) BUG_ON(!(x)) #define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) #ifdef DBG diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 5b07dd8e5c04..5981debcde5e 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -1238,8 +1238,7 @@ static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel) struct pppol2tp_session *session; struct sock *sk; - if (tunnel == NULL) - BUG(); + BUG_ON(tunnel == NULL); PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, "%s: closing all sessions...\n", tunnel->name); diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 264e61404f34..842b1a2c40d4 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1601,8 +1601,7 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state) /* no more hardware accesses behind this line. */ - BUG_ON(np->csr6); - if (ioread32(ioaddr + IntrEnable)) BUG(); + BUG_ON(np->csr6 || ioread32(ioaddr + IntrEnable)); /* pci_power_off(pdev, -1); */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 9c82a39497e5..071855871524 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -621,12 +621,9 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, virtio_net_ctrl_ack status = ~0; unsigned int tmp; - if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { - BUG(); /* Caller should know better */ - return false; - } - - BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX); + /* Caller should know better */ + BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) || + (out + in > VIRTNET_SEND_COMMAND_SG_MAX)); out++; /* Add header */ in++; /* Add return status */ @@ -640,8 +637,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2)); sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); - if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0) - BUG(); + BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi)); vi->cvq->vq_ops->kick(vi->cvq); diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 7a17d31b2fd9..cb5e15f97095 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -54,9 +54,8 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, u32 coef_scaled, coef_exp, coef_man, ds_coef_exp, ds_coef_man, clock; - if (!(ah->ah_version == AR5K_AR5212) || - !(channel->hw_value & CHANNEL_OFDM)) - BUG(); + BUG_ON(!(ah->ah_version == AR5K_AR5212) || + !(channel->hw_value & CHANNEL_OFDM)); /* Get coefficient * ALGO: coef = (5 * clock * carrier_freq) / 2) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 2689a08a2844..7b1b40aaf09d 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -53,11 +53,7 @@ struct ath_node; #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define ASSERT(exp) do { \ - if (unlikely(!(exp))) { \ - BUG(); \ - } \ - } while (0) +#define ASSERT(exp) BUG_ON(!(exp)) #define TSF_TO_TU(_h,_l) \ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index bd4dbcfe1bbe..9a123fbcc359 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -3176,11 +3176,8 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) /* Start the Dma */ rc = ipw_fw_dma_enable(priv); - if (priv->sram_desc.last_cb_index > 0) { - /* the DMA is already ready this would be a bug. */ - BUG(); - goto out; - } + /* the DMA is already ready this would be a bug. */ + BUG_ON(priv->sram_desc.last_cb_index > 0); do { chunk = (struct fw_chunk *)(data + offset); diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index ea3dc038be76..d649caebf08a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -686,8 +686,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, return; } - if (!in_interrupt()) - BUG(); + BUG_ON(!in_interrupt()); spin_lock(&priv->driver_lock); diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 59634c33b1f9..392337b37b1d 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -461,8 +461,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, return; } - if (!in_interrupt()) - BUG(); + BUG_ON(!in_interrupt()); spin_lock(&priv->driver_lock); memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN, -- cgit v1.2.3 From 861ab44059350e5cab350238606cf8814abab93b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 5 Apr 2009 08:40:04 +0000 Subject: NET/r8169: Rework suspend and resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recent changes of the PCI PM core allow us to simplify the suspend and resume handling in a number of device drivers, since they don't need to carry out the general PCI PM operations, such as changing the power state of the device, during suspend and resume any more. Simplify the suspend and resume callbacks of r8169 using the observation that the PCI PM core can take care of some operations carried out by the driver. Additionally, make the shutdown callback of r8169 only put the device into a low power state if the system is going to be powered off (kexec is known to have problems with network adapters that are put into low power states on shutdown). This patch has been tested on MSI Wind U100. Signed-off-by: Rafael J. Wysocki Tested-by: Bruno Prémont Signed-off-by: David S. Miller --- drivers/net/r8169.c | 61 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0b6e8c896835..c812e16b7ab4 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3791,16 +3791,13 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) return &dev->stats; } -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) +static void rtl8169_net_suspend(struct net_device *dev) { - struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; if (!netif_running(dev)) - goto out_pci_suspend; + return; netif_device_detach(dev); netif_stop_queue(dev); @@ -3812,24 +3809,25 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) rtl8169_rx_missed(dev, ioaddr); spin_unlock_irq(&tp->lock); +} + +#ifdef CONFIG_PM + +static int rtl8169_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct net_device *dev = pci_get_drvdata(pdev); -out_pci_suspend: - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), - (tp->features & RTL_FEATURE_WOL) ? 1 : 0); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + rtl8169_net_suspend(dev); return 0; } -static int rtl8169_resume(struct pci_dev *pdev) +static int rtl8169_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - if (!netif_running(dev)) goto out; @@ -3840,23 +3838,42 @@ out: return 0; } +static struct dev_pm_ops rtl8169_pm_ops = { + .suspend = rtl8169_suspend, + .resume = rtl8169_resume, + .freeze = rtl8169_suspend, + .thaw = rtl8169_resume, + .poweroff = rtl8169_suspend, + .restore = rtl8169_resume, +}; + +#define RTL8169_PM_OPS (&rtl8169_pm_ops) + +#else /* !CONFIG_PM */ + +#define RTL8169_PM_OPS NULL + +#endif /* !CONFIG_PM */ + static void rtl_shutdown(struct pci_dev *pdev) { - rtl8169_suspend(pdev, PMSG_SUSPEND); -} + struct net_device *dev = pci_get_drvdata(pdev); + + rtl8169_net_suspend(dev); -#endif /* CONFIG_PM */ + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, true); + pci_set_power_state(pdev, PCI_D3hot); + } +} static struct pci_driver rtl8169_pci_driver = { .name = MODULENAME, .id_table = rtl8169_pci_tbl, .probe = rtl8169_init_one, .remove = __devexit_p(rtl8169_remove_one), -#ifdef CONFIG_PM - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, .shutdown = rtl_shutdown, -#endif + .driver.pm = RTL8169_PM_OPS, }; static int __init rtl8169_init_module(void) -- cgit v1.2.3 From 76620aafd66f0004829764940c5466144969cffc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 16 Apr 2009 02:02:07 -0700 Subject: gro: New frags interface to avoid copying shinfo It turns out that copying a 16-byte area at ~800k times a second can be really expensive :) This patch redesigns the frags GRO interface to avoid copying that area twice. The two disciples of the frags interface have been converted. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/cxgb3/adapter.h | 2 +- drivers/net/cxgb3/sge.c | 53 +++++++++++++++++------------ drivers/net/sfc/rx.c | 26 ++++++++++----- include/linux/if_vlan.h | 6 ++-- include/linux/netdevice.h | 22 ++++++------ net/8021q/vlan_core.c | 4 +-- net/core/dev.c | 81 ++++++++++++++++++++------------------------- 7 files changed, 101 insertions(+), 93 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 714df2b675e6..322434ac42fc 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -195,7 +195,7 @@ struct sge_qset { /* an SGE queue set */ struct sge_rspq rspq; struct sge_fl fl[SGE_RXQ_PER_SET]; struct sge_txq txq[SGE_TXQ_PER_SET]; - struct napi_gro_fraginfo lro_frag_tbl; + int nomem; int lro_enabled; void *lro_va; struct net_device *netdev; diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 26d3587f3399..73d569e758ec 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -654,7 +654,8 @@ static void t3_reset_qset(struct sge_qset *q) q->txq_stopped = 0; q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */ q->rx_reclaim_timer.function = NULL; - q->lro_frag_tbl.nr_frags = q->lro_frag_tbl.len = 0; + q->nomem = 0; + napi_free_frags(&q->napi); } @@ -2074,20 +2075,19 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, struct sge_fl *fl, int len, int complete) { struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; + struct sk_buff *skb = NULL; struct cpl_rx_pkt *cpl; - struct skb_frag_struct *rx_frag = qs->lro_frag_tbl.frags; - int nr_frags = qs->lro_frag_tbl.nr_frags; - int frag_len = qs->lro_frag_tbl.len; + struct skb_frag_struct *rx_frag; + int nr_frags; int offset = 0; - if (!nr_frags) { - offset = 2 + sizeof(struct cpl_rx_pkt); - qs->lro_va = cpl = sd->pg_chunk.va + 2; + if (!qs->nomem) { + skb = napi_get_frags(&qs->napi); + qs->nomem = !skb; } fl->credits--; - len -= offset; pci_dma_sync_single_for_cpu(adap->pdev, pci_unmap_addr(sd, dma_addr), fl->buf_size - SGE_PG_RSVD, @@ -2100,21 +2100,38 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, fl->alloc_size, PCI_DMA_FROMDEVICE); + if (!skb) { + put_page(sd->pg_chunk.page); + if (complete) + qs->nomem = 0; + return; + } + + rx_frag = skb_shinfo(skb)->frags; + nr_frags = skb_shinfo(skb)->nr_frags; + + if (!nr_frags) { + offset = 2 + sizeof(struct cpl_rx_pkt); + qs->lro_va = sd->pg_chunk.va + 2; + } + len -= offset; + prefetch(qs->lro_va); rx_frag += nr_frags; rx_frag->page = sd->pg_chunk.page; rx_frag->page_offset = sd->pg_chunk.offset + offset; rx_frag->size = len; - frag_len += len; - qs->lro_frag_tbl.nr_frags++; - qs->lro_frag_tbl.len = frag_len; + skb->len += len; + skb->data_len += len; + skb->truesize += len; + skb_shinfo(skb)->nr_frags++; if (!complete) return; - qs->lro_frag_tbl.ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = CHECKSUM_UNNECESSARY; cpl = qs->lro_va; if (unlikely(cpl->vlan_valid)) { @@ -2123,15 +2140,11 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, struct vlan_group *grp = pi->vlan_grp; if (likely(grp != NULL)) { - vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan), - &qs->lro_frag_tbl); - goto out; + vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan)); + return; } } - napi_gro_frags(&qs->napi, &qs->lro_frag_tbl); - -out: - qs->lro_frag_tbl.nr_frags = qs->lro_frag_tbl.len = 0; + napi_gro_frags(&qs->napi); } /** @@ -2300,8 +2313,6 @@ no_mem: if (fl->use_pages) { void *addr = fl->sdesc[fl->cidx].pg_chunk.va; - prefetch(&qs->lro_frag_tbl); - prefetch(addr); #if L1_CACHE_BYTES < 128 prefetch(addr + L1_CACHE_BYTES); diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 66d7fe3db3e6..01f9432c31ef 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -450,17 +450,27 @@ static void efx_rx_packet_lro(struct efx_channel *channel, /* Pass the skb/page into the LRO engine */ if (rx_buf->page) { - struct napi_gro_fraginfo info; + struct sk_buff *skb = napi_get_frags(napi); - info.frags[0].page = rx_buf->page; - info.frags[0].page_offset = efx_rx_buf_offset(rx_buf); - info.frags[0].size = rx_buf->len; - info.nr_frags = 1; - info.ip_summed = CHECKSUM_UNNECESSARY; - info.len = rx_buf->len; + if (!skb) { + put_page(rx_buf->page); + goto out; + } + + skb_shinfo(skb)->frags[0].page = rx_buf->page; + skb_shinfo(skb)->frags[0].page_offset = + efx_rx_buf_offset(rx_buf); + skb_shinfo(skb)->frags[0].size = rx_buf->len; + skb_shinfo(skb)->nr_frags = 1; + + skb->len = rx_buf->len; + skb->data_len = rx_buf->len; + skb->truesize += rx_buf->len; + skb->ip_summed = CHECKSUM_UNNECESSARY; - napi_gro_frags(napi, &info); + napi_gro_frags(napi); +out: EFX_BUG_ON_PARANOID(rx_buf->skb); rx_buf->page = NULL; } else { diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index e1ff5b14310e..7ff9af1d0f05 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -118,8 +118,7 @@ extern int vlan_hwaccel_do_receive(struct sk_buff *skb); extern int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb); extern int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, - unsigned int vlan_tci, - struct napi_gro_fraginfo *info); + unsigned int vlan_tci); #else static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) @@ -154,8 +153,7 @@ static inline int vlan_gro_receive(struct napi_struct *napi, } static inline int vlan_gro_frags(struct napi_struct *napi, - struct vlan_group *grp, unsigned int vlan_tci, - struct napi_gro_fraginfo *info) + struct vlan_group *grp, unsigned int vlan_tci) { return NET_RX_DROP; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2e7783f4a755..54db3ebf2193 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1047,14 +1047,6 @@ struct packet_type { struct list_head list; }; -struct napi_gro_fraginfo { - skb_frag_t frags[MAX_SKB_FRAGS]; - unsigned int nr_frags; - unsigned int ip_summed; - unsigned int len; - __wsum csum; -}; - #include #include @@ -1442,12 +1434,18 @@ extern int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); extern void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb); -extern struct sk_buff * napi_fraginfo_skb(struct napi_struct *napi, - struct napi_gro_fraginfo *info); +extern struct sk_buff * napi_get_frags(struct napi_struct *napi); extern int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret); -extern int napi_gro_frags(struct napi_struct *napi, - struct napi_gro_fraginfo *info); +extern struct sk_buff * napi_frags_skb(struct napi_struct *napi); +extern int napi_gro_frags(struct napi_struct *napi); + +static inline void napi_free_frags(struct napi_struct *napi) +{ + kfree_skb(napi->skb); + napi->skb = NULL; +} + extern void netif_nit_deliver(struct sk_buff *skb); extern int dev_valid_name(const char *name); extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 654e45f5719d..c1f51e4a01b2 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -114,9 +114,9 @@ int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, EXPORT_SYMBOL(vlan_gro_receive); int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, - unsigned int vlan_tci, struct napi_gro_fraginfo *info) + unsigned int vlan_tci) { - struct sk_buff *skb = napi_fraginfo_skb(napi, info); + struct sk_buff *skb = napi_frags_skb(napi); if (!skb) return NET_RX_DROP; diff --git a/net/core/dev.c b/net/core/dev.c index 91d792d17e09..619fa141b8f5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2519,16 +2519,10 @@ void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) } EXPORT_SYMBOL(napi_reuse_skb); -struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, - struct napi_gro_fraginfo *info) +struct sk_buff *napi_get_frags(struct napi_struct *napi) { struct net_device *dev = napi->dev; struct sk_buff *skb = napi->skb; - struct ethhdr *eth; - skb_frag_t *frag; - int i; - - napi->skb = NULL; if (!skb) { skb = netdev_alloc_skb(dev, GRO_MAX_HEAD + NET_IP_ALIGN); @@ -2536,47 +2530,14 @@ struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, goto out; skb_reserve(skb, NET_IP_ALIGN); - } - - BUG_ON(info->nr_frags > MAX_SKB_FRAGS); - frag = &info->frags[info->nr_frags - 1]; - for (i = skb_shinfo(skb)->nr_frags; i < info->nr_frags; i++) { - skb_fill_page_desc(skb, i, frag->page, frag->page_offset, - frag->size); - frag++; + napi->skb = skb; } - skb_shinfo(skb)->nr_frags = info->nr_frags; - - skb->data_len = info->len; - skb->len += info->len; - skb->truesize += info->len; - - skb_reset_mac_header(skb); - skb_gro_reset_offset(skb); - - eth = skb_gro_header(skb, sizeof(*eth)); - if (!eth) { - napi_reuse_skb(napi, skb); - skb = NULL; - goto out; - } - - skb_gro_pull(skb, sizeof(*eth)); - - /* - * This works because the only protocols we care about don't require - * special handling. We'll fix it up properly at the end. - */ - skb->protocol = eth->h_proto; - - skb->ip_summed = info->ip_summed; - skb->csum = info->csum; out: return skb; } -EXPORT_SYMBOL(napi_fraginfo_skb); +EXPORT_SYMBOL(napi_get_frags); int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) { @@ -2606,9 +2567,39 @@ int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret) } EXPORT_SYMBOL(napi_frags_finish); -int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) +struct sk_buff *napi_frags_skb(struct napi_struct *napi) +{ + struct sk_buff *skb = napi->skb; + struct ethhdr *eth; + + napi->skb = NULL; + + skb_reset_mac_header(skb); + skb_gro_reset_offset(skb); + + eth = skb_gro_header(skb, sizeof(*eth)); + if (!eth) { + napi_reuse_skb(napi, skb); + skb = NULL; + goto out; + } + + skb_gro_pull(skb, sizeof(*eth)); + + /* + * This works because the only protocols we care about don't require + * special handling. We'll fix it up properly at the end. + */ + skb->protocol = eth->h_proto; + +out: + return skb; +} +EXPORT_SYMBOL(napi_frags_skb); + +int napi_gro_frags(struct napi_struct *napi) { - struct sk_buff *skb = napi_fraginfo_skb(napi, info); + struct sk_buff *skb = napi_frags_skb(napi); if (!skb) return NET_RX_DROP; @@ -2712,7 +2703,7 @@ void netif_napi_del(struct napi_struct *napi) struct sk_buff *skb, *next; list_del_init(&napi->dev_list); - kfree_skb(napi->skb); + napi_free_frags(napi); for (skb = napi->gro_list; skb; skb = next) { next = skb->next; -- cgit v1.2.3 From d130fe5c95739472b61b30f3f2b401ee43d5e3ea Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 07:58:27 +0000 Subject: ipw2x00: remove old compat_net_dev_ops code Since both ipw2100 and ipw2200 are already converted to new net_device_ops this code is useless. Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/wireless/ipw2x00/libipw_module.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 92a26922e792..8ce6e961c5da 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -154,10 +154,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv) goto failed; } ieee = netdev_priv(dev); -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev->hard_start_xmit = ieee80211_xmit; - dev->change_mtu = ieee80211_change_mtu; -#endif ieee->dev = dev; -- cgit v1.2.3 From 84381eed93c974024402eda250c9e7890b72ca4a Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 07:58:28 +0000 Subject: usbnet: remove old compat_net_dev_ops code Since all usb network drivers are already converted to net_device_ops this code is useless. Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f3a2fce6166c..2b8b9036aff6 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1185,12 +1185,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) #endif net->netdev_ops = &usbnet_netdev_ops; -#ifdef CONFIG_COMPAT_NET_DEV_OPS - net->hard_start_xmit = usbnet_start_xmit; - net->open = usbnet_open; - net->stop = usbnet_stop; - net->tx_timeout = usbnet_tx_timeout; -#endif net->watchdog_timeo = TX_TIMEOUT_JIFFIES; net->ethtool_ops = &usbnet_ethtool_ops; -- cgit v1.2.3 From eb9bdaee550e4a56592ae12171b0be6de8fc9d17 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 07:58:29 +0000 Subject: 8390(p): remove old compat_net_dev_ops code Remove compat_net_dev_ops code and use struct net_device_ops instead of it. Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/8390.c | 10 ++-------- drivers/net/8390p.c | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/8390.c b/drivers/net/8390.c index ec3e22e6306f..21153dea8ebe 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -74,14 +74,8 @@ EXPORT_SYMBOL(ei_netdev_ops); struct net_device *__alloc_ei_netdev(int size) { struct net_device *dev = ____alloc_ei_netdev(size); -#ifdef CONFIG_COMPAT_NET_DEV_OPS - if (dev) { - dev->hard_start_xmit = ei_start_xmit; - dev->get_stats = ei_get_stats; - dev->set_multicast_list = ei_set_multicast_list; - dev->tx_timeout = ei_tx_timeout; - } -#endif + if (dev) + dev->netdev_ops = &ei_netdev_ops; return dev; } EXPORT_SYMBOL(__alloc_ei_netdev); diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c index da863c91d1d0..6ec11dafdb18 100644 --- a/drivers/net/8390p.c +++ b/drivers/net/8390p.c @@ -79,14 +79,8 @@ EXPORT_SYMBOL(eip_netdev_ops); struct net_device *__alloc_eip_netdev(int size) { struct net_device *dev = ____alloc_ei_netdev(size); -#ifdef CONFIG_COMPAT_NET_DEV_OPS - if (dev) { - dev->hard_start_xmit = eip_start_xmit; - dev->get_stats = eip_get_stats; - dev->set_multicast_list = eip_set_multicast_list; - dev->tx_timeout = eip_tx_timeout; - } -#endif + if (dev) + dev->netdev_ops = &eip_netdev_ops; return dev; } EXPORT_SYMBOL(__alloc_eip_netdev); -- cgit v1.2.3 From 7a4762abf20531fc8d0bdbe132bc63181b8bebe8 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:35 +0000 Subject: bmac: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/bmac.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 44d015f70d1c..9578a3dfac01 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1247,6 +1247,16 @@ static const struct ethtool_ops bmac_ethtool_ops = { .get_link = ethtool_op_get_link, }; +static const struct net_device_ops bmac_netdev_ops = { + .ndo_open = bmac_open, + .ndo_stop = bmac_close, + .ndo_start_xmit = bmac_output, + .ndo_set_multicast_list = bmac_set_multicast, + .ndo_set_mac_address = bmac_set_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match) { int j, rev, ret; @@ -1308,12 +1318,8 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i bmac_enable_and_reset_chip(dev); bmwrite(dev, INTDISABLE, DisableAll); - dev->open = bmac_open; - dev->stop = bmac_close; + dev->netdev_ops = &bmac_netdev_ops; dev->ethtool_ops = &bmac_ethtool_ops; - dev->hard_start_xmit = bmac_output; - dev->set_multicast_list = bmac_set_multicast; - dev->set_mac_address = bmac_set_address; bmac_get_station_address(dev, addr); if (bmac_verify_checksum(dev) != 0) -- cgit v1.2.3 From 63ef7d89cbecc249339a59c7a1ec58d2e8e88ea5 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:36 +0000 Subject: cpmac: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/cpmac.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 3f476c7c0736..af305c0b34d1 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1093,6 +1093,19 @@ static int cpmac_stop(struct net_device *dev) return 0; } +static const struct net_device_ops cpmac_netdev_ops = { + .ndo_open = cpmac_open, + .ndo_stop = cpmac_stop, + .ndo_start_xmit = cpmac_start_xmit, + .ndo_tx_timeout = cpmac_tx_timeout, + .ndo_set_multicast_list = cpmac_set_multicast_list, + .ndo_so_ioctl = cpmac_ioctl, + .ndo_set_config = cpmac_config, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int external_switch; static int __devinit cpmac_probe(struct platform_device *pdev) @@ -1143,14 +1156,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) dev->irq = platform_get_irq_byname(pdev, "irq"); - dev->open = cpmac_open; - dev->stop = cpmac_stop; - dev->set_config = cpmac_config; - dev->hard_start_xmit = cpmac_start_xmit; - dev->do_ioctl = cpmac_ioctl; - dev->set_multicast_list = cpmac_set_multicast_list; - dev->tx_timeout = cpmac_tx_timeout; - dev->ethtool_ops = &cpmac_ethtool_ops; + dev->netdev_ops = &cpmac_netdev_ops; + dev->ethtool_ops = &cpmac_ethtool_ops; netif_napi_add(dev, &priv->napi, cpmac_poll, 64); -- cgit v1.2.3 From d88106b70178a87203a23108c47eaa1f20c424b5 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:37 +0000 Subject: dm9000: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/dm9000.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index d8350860c0f8..e402e91bf188 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -1170,6 +1170,21 @@ dm9000_stop(struct net_device *ndev) return 0; } +static const struct net_device_ops dm9000_netdev_ops = { + .ndo_open = dm9000_open, + .ndo_stop = dm9000_stop, + .ndo_start_xmit = dm9000_start_xmit, + .ndo_tx_timeout = dm9000_timeout, + .ndo_set_multicast_list = dm9000_hash_table, + .ndo_do_ioctl = dm9000_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = dm9000_poll_controller, +#endif +}; + #define res_size(_r) (((_r)->end - (_r)->start) + 1) /* @@ -1339,18 +1354,9 @@ dm9000_probe(struct platform_device *pdev) /* driver system function */ ether_setup(ndev); - ndev->open = &dm9000_open; - ndev->hard_start_xmit = &dm9000_start_xmit; - ndev->tx_timeout = &dm9000_timeout; - ndev->watchdog_timeo = msecs_to_jiffies(watchdog); - ndev->stop = &dm9000_stop; - ndev->set_multicast_list = &dm9000_hash_table; - ndev->ethtool_ops = &dm9000_ethtool_ops; - ndev->do_ioctl = &dm9000_ioctl; - -#ifdef CONFIG_NET_POLL_CONTROLLER - ndev->poll_controller = &dm9000_poll_controller; -#endif + ndev->netdev_ops = &dm9000_netdev_ops; + ndev->watchdog_timeo = msecs_to_jiffies(watchdog); + ndev->ethtool_ops = &dm9000_ethtool_ops; db->msg_enable = NETIF_MSG_LINK; db->mii.phy_id_mask = 0x1f; -- cgit v1.2.3 From 2e303a929f2178420820cbfab581ca1c7efa18e8 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:38 +0000 Subject: hplance: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/hplance.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 2e802634d366..3e3528ade259 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -71,6 +71,19 @@ static struct dio_driver hplance_driver = { .remove = __devexit_p(hplance_remove_one), }; +static const struct net_device_ops hplance_netdev_ops = { + .ndo_open = hplance_open, + .ndo_stop = hplance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = lance_set_multicast, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = lance_poll, +#endif +}; + /* Find all the HP Lance boards and initialise them... */ static int __devinit hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent) @@ -135,13 +148,7 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d) /* Fill the dev fields */ dev->base_addr = va; - dev->open = &hplance_open; - dev->stop = &hplance_close; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = lance_poll; -#endif - dev->hard_start_xmit = &lance_start_xmit; - dev->set_multicast_list = &lance_set_multicast; + dev->netdev_ops = &hplance_netdev_ops; dev->dma = 0; for (i=0; i<6; i++) { -- cgit v1.2.3 From e186d174e04a7c79606e1ee57abb7470861b3b00 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:39 +0000 Subject: ibmveth: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 5c6315df86b9..0a51b0bd1e49 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1203,6 +1203,20 @@ static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev) return ret; } +static const struct net_device_ops ibmveth_netdev_ops = { + .ndo_open = ibmveth_open, + .ndo_stop = ibmveth_close, + .ndo_start_xmit = ibmveth_start_xmit, + .ndo_set_multicast_list = ibmveth_set_multicast_list, + .ndo_do_ioctl = ibmveth_ioctl, + .ndo_change_mtu = ibmveth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ibmveth_poll_controller, +#endif +}; + static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { int rc, i; @@ -1265,17 +1279,9 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ memcpy(&adapter->mac_addr, mac_addr_p, 6); netdev->irq = dev->irq; - netdev->open = ibmveth_open; - netdev->stop = ibmveth_close; - netdev->hard_start_xmit = ibmveth_start_xmit; - netdev->set_multicast_list = ibmveth_set_multicast_list; - netdev->do_ioctl = ibmveth_ioctl; - netdev->ethtool_ops = &netdev_ethtool_ops; - netdev->change_mtu = ibmveth_change_mtu; + netdev->netdev_ops = &ibmveth_netdev_ops; + netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = ibmveth_poll_controller; -#endif netdev->features |= NETIF_F_LLTX; spin_lock_init(&adapter->stats_lock); -- cgit v1.2.3 From 602355a03508bf54dbf113234ef72d75080a492d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:40 +0000 Subject: irda/au1k_ir: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/au1k_ir.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 941164076a2b..204def0f6451 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -198,6 +198,17 @@ static int au1k_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } +static const struct net_device_ops au1k_irda_netdev_ops = { + .ndo_open = au1k_irda_start, + .ndo_stop = au1k_irda_stop, + .ndo_start_xmit = au1k_irda_hard_xmit, + .ndo_tx_timeout = au1k_tx_timeout, + .ndo_do_ioctl = au1k_irda_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int au1k_irda_net_init(struct net_device *dev) { struct au1k_private *aup = netdev_priv(dev); @@ -209,11 +220,7 @@ static int au1k_irda_net_init(struct net_device *dev) if (err) goto out1; - dev->open = au1k_irda_start; - dev->hard_start_xmit = au1k_irda_hard_xmit; - dev->stop = au1k_irda_stop; - dev->do_ioctl = au1k_irda_ioctl; - dev->tx_timeout = au1k_tx_timeout; + dev->netdev_ops = &au1k_irda_netdev_ops; irda_init_max_qos_capabilies(&aup->qos); -- cgit v1.2.3 From c76ccd6a256004cca1127c9afb5474638fc78b74 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:41 +0000 Subject: irda/pxaficp_ir: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/pxaficp_ir.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index e775338b525f..e8ced56b050f 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -797,6 +797,16 @@ static int pxa_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } +static const struct net_device_ops pxa_irda_netdev_ops = { + .ndo_open = pxa_irda_start, + .ndo_stop = pxa_irda_stop, + .ndo_start_xmit = pxa_irda_hard_xmit, + .ndo_do_ioctl = pxa_irda_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int pxa_irda_probe(struct platform_device *pdev) { struct net_device *dev; @@ -845,10 +855,7 @@ static int pxa_irda_probe(struct platform_device *pdev) if (err) goto err_startup; - dev->hard_start_xmit = pxa_irda_hard_xmit; - dev->open = pxa_irda_start; - dev->stop = pxa_irda_stop; - dev->do_ioctl = pxa_irda_ioctl; + dev->netdev_ops = &pxa_irda_netdev_ops; irda_init_max_qos_capabilies(&si->qos); -- cgit v1.2.3 From a1de966682551debbe690672e760487cc555c05f Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:42 +0000 Subject: irda/sa1100_ir: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/sa1100_ir.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 7a2b003954ca..44a748e72332 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -875,6 +875,16 @@ static int sa1100_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } +static const struct net_device_ops sa1100_irda_netdev_ops = { + .ndo_open = sa1100_irda_start, + .ndo_stop = sa1100_irda_stop, + .ndo_start_xmit = sa1100_irda_hard_xmit, + .ndo_do_ioctl = sa1100_irda_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int sa1100_irda_probe(struct platform_device *pdev) { struct net_device *dev; @@ -913,11 +923,8 @@ static int sa1100_irda_probe(struct platform_device *pdev) if (err) goto err_mem_5; - dev->hard_start_xmit = sa1100_irda_hard_xmit; - dev->open = sa1100_irda_start; - dev->stop = sa1100_irda_stop; - dev->do_ioctl = sa1100_irda_ioctl; - dev->irq = IRQ_Ser2ICP; + dev->netdev_ops = &sa1100_irda_netdev_ops; + dev->ir = IRQ_Ser2ICP; irda_init_max_qos_capabilies(&si->qos); -- cgit v1.2.3 From c2775360e82760be3ad7339a7a1442c45c35b395 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:43 +0000 Subject: iseries_veth: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/iseries_veth.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index cb793c2bade2..264654da85d1 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1021,6 +1021,16 @@ static const struct ethtool_ops ops = { .get_link = veth_get_link, }; +static const struct net_device_ops veth_netdev_ops = { + .ndo_open = veth_open, + .ndo_stop = veth_close, + .ndo_start_xmit = veth_start_xmit, + .ndo_change_mtu = veth_change_mtu, + .ndo_set_multicast_list = veth_set_multicast_list, + .ndo_set_mac_address = NULL, + .ndo_validate_addr = eth_validate_addr, +}; + static struct net_device *veth_probe_one(int vlan, struct vio_dev *vio_dev) { @@ -1067,12 +1077,7 @@ static struct net_device *veth_probe_one(int vlan, memcpy(&port->mac_addr, mac_addr, ETH_ALEN); - dev->open = veth_open; - dev->hard_start_xmit = veth_start_xmit; - dev->stop = veth_close; - dev->change_mtu = veth_change_mtu; - dev->set_mac_address = NULL; - dev->set_multicast_list = veth_set_multicast_list; + dev->netdev = &veth_netdev_ops; SET_ETHTOOL_OPS(dev, &ops); SET_NETDEV_DEV(dev, vdev); -- cgit v1.2.3 From e7090e347ad8bce0de35f9fe2b95e22e4ae8fbab Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:44 +0000 Subject: ixp2000/ixpdev: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/ixp2000/ixpdev.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index d3bf2f017cc2..2a0174b62e96 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -270,6 +270,18 @@ static int ixpdev_close(struct net_device *dev) return 0; } +static const struct net_device_ops ixpdev_netdev_ops = { + .ndo_open = ixpdev_open, + .ndo_stop = ixpdev_close, + .ndo_start_xmit = ixpdev_xmit, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ixpdev_poll_controller, +#endif +}; + struct net_device *ixpdev_alloc(int channel, int sizeof_priv) { struct net_device *dev; @@ -279,12 +291,7 @@ struct net_device *ixpdev_alloc(int channel, int sizeof_priv) if (dev == NULL) return NULL; - dev->hard_start_xmit = ixpdev_xmit; - dev->open = ixpdev_open; - dev->stop = ixpdev_close; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ixpdev_poll_controller; -#endif + dev->netdev_ops = &ixpdev_netdev_ops; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; -- cgit v1.2.3 From 502a326f833927a84a8de29f5fb638aa9da15f4b Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:45 +0000 Subject: jazzsonic: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/jazzsonic.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 14248cfc3dfd..d12106b47bf2 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -96,6 +96,18 @@ static int jazzsonic_close(struct net_device* dev) return err; } +static const struct net_device_ops sonic_netdev_ops = { + .ndo_open = jazzsonic_open, + .ndo_stop = jazzsonic_close, + .ndo_start_xmit = sonic_send_packet, + .ndo_get_stats = sonic_get_stats, + .ndo_set_multicast_list = sonic_multicast_list, + .ndo_tx_timeout = sonic_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int __init sonic_probe1(struct net_device *dev) { static unsigned version_printed; @@ -179,12 +191,7 @@ static int __init sonic_probe1(struct net_device *dev) lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS * SONIC_BUS_SCALE(lp->dma_bitmode)); - dev->open = jazzsonic_open; - dev->stop = jazzsonic_close; - dev->hard_start_xmit = sonic_send_packet; - dev->get_stats = sonic_get_stats; - dev->set_multicast_list = &sonic_multicast_list; - dev->tx_timeout = sonic_tx_timeout; + dev->netdev_ops = &sonic_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; /* -- cgit v1.2.3 From 52b031ff3987a079ea759d81447312f1665dbfbd Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:46 +0000 Subject: korina: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/korina.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 38d6649a29c4..dc238567cae1 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -1081,6 +1081,21 @@ static int korina_close(struct net_device *dev) return 0; } +static const struct net_device_ops korina_netdev_ops = { + .ndo_open = korina_open, + .ndo_stop = korina_close, + .ndo_start_xmit = korina_send_packet, + .ndo_set_multicast_list = korina_multicast_list, + .ndo_tx_timeout = korina_tx_timeout, + .ndo_do_ioctl = korina_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = korina_poll_controller, +#endif +}; + static int korina_probe(struct platform_device *pdev) { struct korina_device *bif = platform_get_drvdata(pdev); @@ -1149,17 +1164,9 @@ static int korina_probe(struct platform_device *pdev) dev->irq = lp->rx_irq; lp->dev = dev; - dev->open = korina_open; - dev->stop = korina_close; - dev->hard_start_xmit = korina_send_packet; - dev->set_multicast_list = &korina_multicast_list; + dev->netdev_ops = &korina_netdev_ops; dev->ethtool_ops = &netdev_ethtool_ops; - dev->tx_timeout = korina_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - dev->do_ioctl = &korina_ioctl; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = korina_poll_controller; -#endif netif_napi_add(dev, &lp->napi, korina_poll, 64); lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); -- cgit v1.2.3 From 71f4367ca24830d967fca7a9c1cfb944b08742e5 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:47 +0000 Subject: lib82596: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/lib82596.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 7415f517491d..070fa4500871 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1036,6 +1036,19 @@ static void print_eth(unsigned char *add, char *str) printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n", add, add + 6, add, add[12], add[13], str); } +static const struct net_device_ops i596_netdev_ops = { + .ndo_open = i596_open, + .ndo_stop = i596_close, + .ndo_start_xmit = i596_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_tx_timeout = i596_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = i596_poll_controller, +#endif +}; static int __devinit i82596_probe(struct net_device *dev) { @@ -1062,16 +1075,8 @@ static int __devinit i82596_probe(struct net_device *dev) return -ENOMEM; } - /* The 82596-specific entries in the device structure. */ - dev->open = i596_open; - dev->stop = i596_close; - dev->hard_start_xmit = i596_start_xmit; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = i596_tx_timeout; + dev->netdev_ops = &i596_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = i596_poll_controller; -#endif memset(dma, 0, sizeof(struct i596_dma)); lp->dma = dma; -- cgit v1.2.3 From 488b4abcd750c0a600eefa4d9ab42aad980ace11 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:48 +0000 Subject: mace: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/mace.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/mace.c b/drivers/net/mace.c index feebbd92aff2..1ad740bc8878 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -94,6 +94,16 @@ static void __mace_set_address(struct net_device *dev, void *addr); */ static unsigned char *dummy_buf; +static const struct net_device_ops mace_netdev_ops = { + .ndo_open = mace_open, + .ndo_stop = mace_close, + .ndo_start_xmit = mace_xmit_start, + .ndo_set_multicast_list = mace_set_multicast, + .ndo_set_mac_address = mace_set_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match) { struct device_node *mace = macio_get_of_node(mdev); @@ -207,11 +217,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i } } - dev->open = mace_open; - dev->stop = mace_close; - dev->hard_start_xmit = mace_xmit_start; - dev->set_multicast_list = mace_set_multicast; - dev->set_mac_address = mace_set_address; + dev->netdev_ops = &mace_netdev_ops; /* * Most of what is below could be moved to mace_open() -- cgit v1.2.3 From 0d3936a8b11b72e1387923342e33fdad553271d4 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:49 +0000 Subject: macmace: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/macmace.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 274e99bb63ac..44f3c2896f20 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -180,6 +180,17 @@ static void mace_dma_off(struct net_device *dev) psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100); } +static const struct net_device_ops mace_netdev_ops = { + .ndo_open = mace_open, + .ndo_stop = mace_close, + .ndo_start_xmit = mace_xmit_start, + .ndo_tx_timeout = mace_tx_timeout, + .ndo_set_multicast_list = mace_set_multicast, + .ndo_set_mac_address = mace_set_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + /* * Not really much of a probe. The hardware table tells us if this * model of Macintrash has a MACE (AV macintoshes) @@ -240,13 +251,8 @@ static int __devinit mace_probe(struct platform_device *pdev) return -ENODEV; } - dev->open = mace_open; - dev->stop = mace_close; - dev->hard_start_xmit = mace_xmit_start; - dev->tx_timeout = mace_tx_timeout; + dev->netdev_ops = &mace_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; - dev->set_multicast_list = mace_set_multicast; - dev->set_mac_address = mace_set_address; printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n", dev->name, dev->dev_addr); -- cgit v1.2.3 From d53bc2df189f1e11a947eed077f0360bfadf9986 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:50 +0000 Subject: meth: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/meth.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/net/meth.c b/drivers/net/meth.c index aa08987f6e81..46ffdb464ac4 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -769,9 +769,17 @@ static int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } } -/* - * Return statistics to the caller - */ +static const struct net_device_ops meth_netdev_ops = { + .ndo_open = meth_open, + .ndo_stop = meth_release, + .ndo_start_xmit = meth_tx, + .ndo_do_ioctl = meth_ioctl, + .ndo_tx_timeout = meth_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + /* * The init function. */ @@ -785,16 +793,10 @@ static int __init meth_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - dev->open = meth_open; - dev->stop = meth_release; - dev->hard_start_xmit = meth_tx; - dev->do_ioctl = meth_ioctl; -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = meth_tx_timeout; - dev->watchdog_timeo = timeout; -#endif - dev->irq = MACE_ETHERNET_IRQ; - dev->base_addr = (unsigned long)&mace->eth; + dev->netdev_ops = &meth_netdev_ops; + dev->watchdog_timeo = timeout; + dev->irq = MACE_ETHERNET_IRQ; + dev->base_addr = (unsigned long)&mace->eth; memcpy(dev->dev_addr, o2meth_eaddr, 6); priv = netdev_priv(dev); -- cgit v1.2.3 From d6771e0b895f04e8bbd12f12fb3a97e130a4a5f4 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:51 +0000 Subject: mipsnet: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/mipsnet.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 664835b822fb..b3b9a147d09a 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -237,6 +237,16 @@ static void mipsnet_set_mclist(struct net_device *dev) { } +static const struct net_device_ops mipsnet_netdev_ops = { + .ndo_open = mipsnet_open, + .ndo_stop = mipsnet_close, + .ndo_start_xmit = mipsnet_xmit, + .ndo_set_multicast_list = mipsnet_set_mclist, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int __init mipsnet_probe(struct platform_device *dev) { struct net_device *netdev; @@ -250,10 +260,7 @@ static int __init mipsnet_probe(struct platform_device *dev) platform_set_drvdata(dev, netdev); - netdev->open = mipsnet_open; - netdev->stop = mipsnet_close; - netdev->hard_start_xmit = mipsnet_xmit; - netdev->set_multicast_list = mipsnet_set_mclist; + netdev->netdev_ops = &mipsnet_netdev_ops; /* * TODO: probe for these or load them from PARAM -- cgit v1.2.3 From 96cd55ea0edac7f6d51d2391d5cc1b5c2e360e67 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:52 +0000 Subject: mvme147: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/mvme147.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c index 435e5a847c43..93c709d63e2f 100644 --- a/drivers/net/mvme147.c +++ b/drivers/net/mvme147.c @@ -57,6 +57,17 @@ typedef void (*writerap_t)(void *, unsigned short); typedef void (*writerdp_t)(void *, unsigned short); typedef unsigned short (*readrdp_t)(void *); +static const struct net_device_ops lance_netdev_ops = { + .ndo_open = m147lance_open, + .ndo_stop = m147lance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = lance_set_multicast, + .ndo_tx_timeout = lance_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + /* Initialise the one and only on-board 7990 */ struct net_device * __init mvme147lance_probe(int unit) { @@ -81,11 +92,7 @@ struct net_device * __init mvme147lance_probe(int unit) /* Fill the dev fields */ dev->base_addr = (unsigned long)MVME147_LANCE_BASE; - dev->open = &m147lance_open; - dev->stop = &m147lance_close; - dev->hard_start_xmit = &lance_start_xmit; - dev->set_multicast_list = &lance_set_multicast; - dev->tx_timeout = &lance_tx_timeout; + dev->netdev_ops = &lance_netdev_ops; dev->dma = 0; addr=(u_long *)ETHERNET_ADDRESS; -- cgit v1.2.3 From cd732de21e3d4f0b905fdbee8abfbb8192144b3d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:53 +0000 Subject: netx-eth: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/netx-eth.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index 1861d5bbd96b..946366dcc992 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -301,6 +301,17 @@ netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value) while (readl(NETX_MIIMU) & MIIMU_SNRDY); } +static const struct net_device_ops netx_eth_netdev_ops = { + .ndo_open = netx_eth_open, + .ndo_stop = netx_eth_close, + .ndo_start_xmit = netx_eth_hard_start_xmit, + .ndo_tx_timeout = netx_eth_timeout, + .ndo_set_multicast_list = netx_eth_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int netx_eth_enable(struct net_device *ndev) { struct netx_eth_priv *priv = netdev_priv(ndev); @@ -309,12 +320,8 @@ static int netx_eth_enable(struct net_device *ndev) ether_setup(ndev); - ndev->open = netx_eth_open; - ndev->stop = netx_eth_close; - ndev->hard_start_xmit = netx_eth_hard_start_xmit; - ndev->tx_timeout = netx_eth_timeout; + ndev->netdev_ops = &netx_eth_netdev_ops; ndev->watchdog_timeo = msecs_to_jiffies(5000); - ndev->set_multicast_list = netx_eth_set_multicast_list; priv->msg_enable = NETIF_MSG_LINK; priv->mii.phy_id_mask = 0x1f; -- cgit v1.2.3 From 9e0ac841f42df4e7acdab7dc1620de0933ed56d7 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:54 +0000 Subject: pasemi_mac: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/pasemi_mac.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 5eeb5a87b738..067caba43656 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -1735,6 +1735,19 @@ out: return ret; } +static const struct net_device_ops pasemi_netdev_ops = { + .ndo_open = pasemi_mac_open, + .ndo_stop = pasemi_mac_close, + .ndo_start_xmit = pasemi_mac_start_tx, + .ndo_set_multicast_list = pasemi_mac_set_rx_mode, + .ndo_set_mac_address = pasemi_mac_set_mac_addr, + .ndo_change_mtu = pasemi_mac_change_mtu, + .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = pasemi_mac_netpoll, +#endif +}; + static int __devinit pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1817,19 +1830,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out; } - dev->open = pasemi_mac_open; - dev->stop = pasemi_mac_close; - dev->hard_start_xmit = pasemi_mac_start_tx; - dev->set_multicast_list = pasemi_mac_set_rx_mode; - dev->set_mac_address = pasemi_mac_set_mac_addr; + dev->netdev_ops = &pasemi_netdev_ops; dev->mtu = PE_DEF_MTU; /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = pasemi_mac_netpoll; -#endif - dev->change_mtu = pasemi_mac_change_mtu; dev->ethtool_ops = &pasemi_mac_ethtool_ops; if (err) -- cgit v1.2.3 From 1ec847f6d46f041bb2ae65efc7b00d122b03d212 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:55 +0000 Subject: pci-skeleton: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/pci-skeleton.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index c95fd72c3bb9..8c1f6988f398 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -728,6 +728,17 @@ err_out: return rc; } +static const struct net_device_ops netdrv_netdev_ops = { + .ndo_open = netdrv_open, + .ndo_stop = netdrv_close, + .ndo_start_xmit = netdrv_start_xmit, + .ndo_set_multicast_list = netdrv_set_rx_mode, + .ndo_do_ioctl = netdrv_ioctl, + .ndo_tx_timeout = netdrv_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; static int __devinit netdrv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -769,13 +780,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, ((u16 *) (dev->dev_addr))[i] = le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); - /* The Rtl8139-specific entries in the device structure. */ - dev->open = netdrv_open; - dev->hard_start_xmit = netdrv_start_xmit; - dev->stop = netdrv_close; - dev->set_multicast_list = netdrv_set_rx_mode; - dev->do_ioctl = netdrv_ioctl; - dev->tx_timeout = netdrv_tx_timeout; + dev->netdev_ops = &netdrv_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->irq = pdev->irq; -- cgit v1.2.3 From a33a2bb3c9f38c79e97f6ed720412d946e894e81 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:56 +0000 Subject: rionet: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/rionet.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index ec59e29807a6..8702e7acdee6 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -428,6 +428,15 @@ static const struct ethtool_ops rionet_ethtool_ops = { .get_link = ethtool_op_get_link, }; +static const struct net_device_ops rionet_netdev_ops = { + .ndo_open = rionet_open, + .ndo_stop = rionet_close, + .ndo_start_xmit = rionet_start_xmit, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +}; + static int rionet_setup_netdev(struct rio_mport *mport) { int rc = 0; @@ -466,10 +475,7 @@ static int rionet_setup_netdev(struct rio_mport *mport) ndev->dev_addr[4] = device_id >> 8; ndev->dev_addr[5] = device_id & 0xff; - /* Fill in the driver function table */ - ndev->open = &rionet_open; - ndev->hard_start_xmit = &rionet_start_xmit; - ndev->stop = &rionet_close; + ndev->netdev_ops = &rionet_netdev_ops; ndev->mtu = RIO_MAX_MSG_SIZE - 14; ndev->features = NETIF_F_LLTX; SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops); -- cgit v1.2.3 From b4cf3421afce25655233cf66f6ec545baa8cb6ae Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:57 +0000 Subject: sb1250-mac: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/sb1250-mac.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index ce7551e17ba7..aaeebf57a9a4 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2271,6 +2271,21 @@ static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) return 0; } +static const struct net_device_ops sbmac_netdev_ops = { + .ndo_open = sbmac_open, + .ndo_stop = sbmac_close, + .ndo_start_xmit = sbmac_start_tx, + .ndo_set_multicast_list = sbmac_set_rx_mode, + .ndo_tx_timeout = sbmac_tx_timeout, + .ndo_do_ioctl = sbmac_mii_ioctl, + .ndo_change_mtu = sb1250_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = sbmac_netpoll, +#endif +}; + /********************************************************************** * SBMAC_INIT(dev) * @@ -2327,21 +2342,11 @@ static int sbmac_init(struct platform_device *pldev, long long base) spin_lock_init(&(sc->sbm_lock)); - dev->open = sbmac_open; - dev->hard_start_xmit = sbmac_start_tx; - dev->stop = sbmac_close; - dev->set_multicast_list = sbmac_set_rx_mode; - dev->do_ioctl = sbmac_mii_ioctl; - dev->tx_timeout = sbmac_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; + dev->netdev_ops = &sbmac_netdev_ops; + dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, &sc->napi, sbmac_poll, 16); - dev->change_mtu = sb1250_change_mtu; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = sbmac_netpoll; -#endif - dev->irq = UNIT_INT(idx); /* This is needed for PASS2 for Rx H/W checksum feature */ -- cgit v1.2.3 From 8c2c6be186097aafd8f8a17927203b457545cc69 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:58 +0000 Subject: sgiseeq: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/sgiseeq.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 97d68560067d..5fb88ca6dd7f 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -709,6 +709,17 @@ static inline void setup_rx_ring(struct net_device *dev, dma_sync_desc_dev(dev, &buf[i]); } +static const struct net_device_ops sgiseeq_netdev_ops = { + .ndo_open = sgiseeq_open, + .ndo_stop = sgiseeq_close, + .ndo_start_xmit = sgiseeq_start_xmit, + .ndo_tx_timeout = timeout, + .ndo_set_multicast_list = sgiseeq_set_multicast, + .ndo_set_mac_address = sgiseeq_set_mac_address, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init sgiseeq_probe(struct platform_device *pdev) { struct sgiseeq_platform_data *pd = pdev->dev.platform_data; @@ -775,13 +786,8 @@ static int __init sgiseeq_probe(struct platform_device *pdev) SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT | SEEQ_CTRL_ENCARR; - dev->open = sgiseeq_open; - dev->stop = sgiseeq_close; - dev->hard_start_xmit = sgiseeq_start_xmit; - dev->tx_timeout = timeout; + dev->netdev_ops = &sgiseeq_netdev_ops; dev->watchdog_timeo = (200 * HZ) / 1000; - dev->set_multicast_list = sgiseeq_set_multicast; - dev->set_mac_address = sgiseeq_set_mac_address; dev->irq = irq; if (register_netdev(dev)) { -- cgit v1.2.3 From ec4e0cff9b8c97f5d63c8f1bdf7f44fb65fa8e3b Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:52:59 +0000 Subject: smc911x: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/smc911x.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 293610334a77..bc4976ac8712 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1774,6 +1774,20 @@ static int __devinit smc911x_findirq(struct net_device *dev) return probe_irq_off(cookie); } +static const struct net_device_ops smc911x_netdev_ops = { + .ndo_open = smc911x_open, + .ndo_stop = smc911x_close, + .ndo_start_xmit = smc911x_hard_start_xmit, + .ndo_tx_timeout = smc911x_timeout, + .ndo_set_multicast_list = smc911x_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = smc911x_poll_controller, +#endif +}; + /* * Function: smc911x_probe(unsigned long ioaddr) * @@ -1940,16 +1954,9 @@ static int __devinit smc911x_probe(struct net_device *dev) /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); - dev->open = smc911x_open; - dev->stop = smc911x_close; - dev->hard_start_xmit = smc911x_hard_start_xmit; - dev->tx_timeout = smc911x_timeout; + dev->netdev_ops = &smc911x_netdev_ops; dev->watchdog_timeo = msecs_to_jiffies(watchdog); - dev->set_multicast_list = smc911x_set_multicast_list; dev->ethtool_ops = &smc911x_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = smc911x_poll_controller; -#endif INIT_WORK(&lp->phy_configure, smc911x_phy_configure); lp->mii.phy_id_mask = 0x1f; -- cgit v1.2.3 From 2160187a0a1cdeeeff1d41f53333bea91c82f259 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 15 Apr 2009 12:53:00 +0000 Subject: sun3lance: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/sun3lance.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index e5beb299cbd0..9bd9dadb8534 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -294,6 +294,16 @@ out: return ERR_PTR(err); } +static const struct net_device_ops lance_netdev_ops = { + .ndo_open = lance_open, + .ndo_stop = lance_close, + .ndo_start_xmit = lance_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_set_mac_address = NULL, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init lance_probe( struct net_device *dev) { unsigned long ioaddr; @@ -397,12 +407,7 @@ static int __init lance_probe( struct net_device *dev) if (did_version++ == 0) printk( version ); - /* The LANCE-specific entries in the device structure. */ - dev->open = &lance_open; - dev->hard_start_xmit = &lance_start_xmit; - dev->stop = &lance_close; - dev->set_multicast_list = &set_multicast_list; - dev->set_mac_address = NULL; + dev->netdev_ops = &lance_netdev_ops; // KLUDGE -- REMOVE ME set_bit(__LINK_STATE_PRESENT, &dev->state); -- cgit v1.2.3 From f44d6305280378cb34319e0118e18d84cc7ac773 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 03:11:30 +0000 Subject: fec: switch to writel/readl Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 279 ++++++++++++++++++++++-------------------------------- drivers/net/fec.h | 119 +++++++++-------------- 2 files changed, 161 insertions(+), 237 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index a515acccc61f..37b333265629 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -165,7 +165,7 @@ typedef struct { */ struct fec_enet_private { /* Hardware registers of the FEC device */ - volatile fec_t *hwp; + void __iomem *hwp; struct net_device *netdev; @@ -288,15 +288,11 @@ static int mii_queue(struct net_device *dev, int request, static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct fec_enet_private *fep; - volatile fec_t *fecp; + struct fec_enet_private *fep = netdev_priv(dev); volatile cbd_t *bdp; unsigned short status; unsigned long flags; - fep = netdev_priv(dev); - fecp = (volatile fec_t*)dev->base_addr; - if (!fep->link) { /* Link is down or autonegotiation is in progress. */ return 1; @@ -363,7 +359,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; /* Trigger transmission start */ - fecp->fec_x_des_active = 0; + writel(0, fep->hwp + FEC_X_DES_ACTIVE); /* If this was the last BD in the ring, start at the beginning again. */ @@ -436,29 +432,25 @@ static irqreturn_t fec_enet_interrupt(int irq, void * dev_id) { struct net_device *dev = dev_id; - volatile fec_t *fecp; + struct fec_enet_private *fep = netdev_priv(dev); uint int_events; irqreturn_t ret = IRQ_NONE; - fecp = (volatile fec_t*)dev->base_addr; - - /* Get the interrupt events that caused us to be here. - */ + /* Get the interrupt events that caused us to be here. */ do { - int_events = fecp->fec_ievent; - fecp->fec_ievent = int_events; + int_events = readl(fep->hwp + FEC_IEVENT); + writel(int_events, fep->hwp + FEC_IEVENT); - /* Handle receive event in its own function. - */ + /* Handle receive event in its own function. */ if (int_events & FEC_ENET_RXF) { ret = IRQ_HANDLED; fec_enet_rx(dev); } /* Transmit OK, or non-fatal error. Update the buffer - descriptors. FEC handles all errors, we just discover - them as part of the transmit process. - */ + * descriptors. FEC handles all errors, we just discover + * them as part of the transmit process. + */ if (int_events & FEC_ENET_TXF) { ret = IRQ_HANDLED; fec_enet_tx(dev); @@ -555,8 +547,7 @@ fec_enet_tx(struct net_device *dev) static void fec_enet_rx(struct net_device *dev) { - struct fec_enet_private *fep; - volatile fec_t *fecp; + struct fec_enet_private *fep = netdev_priv(dev); volatile cbd_t *bdp; unsigned short status; struct sk_buff *skb; @@ -567,9 +558,6 @@ fec_enet_rx(struct net_device *dev) flush_cache_all(); #endif - fep = netdev_priv(dev); - fecp = (volatile fec_t*)dev->base_addr; - spin_lock_irq(&fep->hw_lock); /* First, grab all of the stats for the incoming packet. @@ -665,7 +653,7 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { * incoming frames. On a heavily loaded network, we should be * able to keep up at the expense of system resources. */ - fecp->fec_r_des_active = 0; + writel(0, fep->hwp + FEC_R_DES_ACTIVE); #endif } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */ fep->cur_rx = (cbd_t *)bdp; @@ -690,30 +678,25 @@ static void fec_enet_mii(struct net_device *dev) { struct fec_enet_private *fep; - volatile fec_t *ep; mii_list_t *mip; - uint mii_reg; fep = netdev_priv(dev); spin_lock_irq(&fep->mii_lock); - ep = fep->hwp; - mii_reg = ep->fec_mii_data; - if ((mip = mii_head) == NULL) { printk("MII and no head!\n"); goto unlock; } if (mip->mii_func != NULL) - (*(mip->mii_func))(mii_reg, dev); + (*(mip->mii_func))(readl(fep->hwp + FEC_MII_DATA), dev); mii_head = mip->mii_next; mip->mii_next = mii_free; mii_free = mip; if ((mip = mii_head) != NULL) - ep->fec_mii_data = mip->mii_regval; + writel(mip->mii_regval, fep->hwp + FEC_MII_DATA); unlock: spin_unlock_irq(&fep->mii_lock); @@ -745,7 +728,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi mii_tail = mip; } else { mii_head = mii_tail = mip; - fep->hwp->fec_mii_data = regval; + writel(regval, fep->hwp + FEC_MII_DATA); } } else { retval = 1; @@ -1245,11 +1228,8 @@ static void __inline__ fec_phy_ack_intr(void) static void __inline__ fec_get_mac(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - volatile fec_t *fecp; unsigned char *iap, tmpaddr[ETH_ALEN]; - fecp = fep->hwp; - if (FEC_FLASHMAC) { /* * Get MAC address from FLASH. @@ -1263,8 +1243,8 @@ static void __inline__ fec_get_mac(struct net_device *dev) (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) iap = fec_mac_default; } else { - *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; - *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); + *((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW); + *((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16); iap = &tmpaddr[0]; } @@ -1456,11 +1436,9 @@ static void mii_discover_phy(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep; - volatile fec_t *fecp; uint phytype; fep = netdev_priv(dev); - fecp = fep->hwp; if (fep->phy_addr < 32) { if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) { @@ -1478,7 +1456,8 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) } else { printk("FEC: No PHY device found.\n"); /* Disable external MII interface */ - fecp->fec_mii_speed = fep->phy_speed = 0; + writel(0, fep->hwp + FEC_MII_SPEED); + fep->phy_speed = 0; #ifdef HAVE_mii_link_interrupt fec_disable_phy_intr(); #endif @@ -1582,32 +1561,31 @@ fec_enet_close(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct fec_enet_private *fep; - volatile fec_t *ep; + struct fec_enet_private *fep = netdev_priv(dev); struct dev_mc_list *dmi; - unsigned int i, j, bit, data, crc; + unsigned int i, j, bit, data, crc, tmp; unsigned char hash; - fep = netdev_priv(dev); - ep = fep->hwp; - if (dev->flags&IFF_PROMISC) { - ep->fec_r_cntrl |= 0x0008; + tmp = readl(fep->hwp + FEC_R_CNTRL); + tmp |= 0x8; + writel(tmp, fep->hwp + FEC_R_CNTRL); } else { - - ep->fec_r_cntrl &= ~0x0008; + tmp = readl(fep->hwp + FEC_R_CNTRL); + tmp &= ~0x8; + writel(tmp, fep->hwp + FEC_R_CNTRL); if (dev->flags & IFF_ALLMULTI) { /* Catch all multicast addresses, so set the * filter to all 1's. */ - ep->fec_grp_hash_table_high = 0xffffffff; - ep->fec_grp_hash_table_low = 0xffffffff; + writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); } else { /* Clear filter and add the addresses in hash register. */ - ep->fec_grp_hash_table_high = 0; - ep->fec_grp_hash_table_low = 0; + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); dmi = dev->mc_list; @@ -1637,10 +1615,15 @@ static void set_multicast_list(struct net_device *dev) */ hash = (crc >> (32 - HASH_BITS)) & 0x3f; - if (hash > 31) - ep->fec_grp_hash_table_high |= 1 << (hash - 32); - else - ep->fec_grp_hash_table_low |= 1 << hash; + if (hash > 31) { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + tmp |= 1 << (hash - 32); + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + } else { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); + tmp |= 1 << hash; + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + } } } } @@ -1651,16 +1634,14 @@ static void set_multicast_list(struct net_device *dev) static void fec_set_mac_address(struct net_device *dev) { - volatile fec_t *fecp; - - fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp; + struct fec_enet_private *fep = netdev_priv(dev); /* Set station address. */ - fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) | - (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24); - fecp->fec_addr_high = (dev->dev_addr[5] << 16) | - (dev->dev_addr[4] << 24); - + writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) | + (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), + fep->hwp + FEC_ADDR_LOW); + writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), + fep + FEC_ADDR_HIGH); } /* @@ -1674,7 +1655,6 @@ int __init fec_enet_init(struct net_device *dev, int index) unsigned long mem_addr; volatile cbd_t *bdp; cbd_t *cbd_base; - volatile fec_t *fecp; int i, j; /* Allocate memory for buffer descriptors. @@ -1689,17 +1669,13 @@ int __init fec_enet_init(struct net_device *dev, int index) spin_lock_init(&fep->hw_lock); spin_lock_init(&fep->mii_lock); - /* Create an Ethernet device instance. - */ - fecp = (volatile fec_t *)dev->base_addr; - fep->index = index; - fep->hwp = fecp; + fep->hwp = (void __iomem *)dev->base_addr; fep->netdev = dev; /* Whack a reset. We should wait for this. */ - fecp->fec_ecntrl = 1; + writel(1, fep->hwp + FEC_ECNTRL); udelay(10); /* Set the Ethernet address */ @@ -1708,12 +1684,12 @@ int __init fec_enet_init(struct net_device *dev, int index) #else { unsigned long l; - l = fecp->fec_addr_low; + l = readl(fep->hwp + FEC_ADDR_LOW); dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24); dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16); dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8); dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0); - l = fecp->fec_addr_high; + l = readl(fep->hwp + FEC_ADDR_HIGH); dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24); dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16); } @@ -1783,22 +1759,22 @@ int __init fec_enet_init(struct net_device *dev, int index) /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = fep->bd_dma; - fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) - * RX_RING_SIZE; + writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); + writel((unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE, + fep->hwp + FEC_X_DES_START); #ifdef HAVE_mii_link_interrupt fec_request_mii_intr(dev); #endif - fecp->fec_grp_hash_table_high = 0; - fecp->fec_grp_hash_table_low = 0; - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fecp->fec_ecntrl = 2; - fecp->fec_r_des_active = 0; + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); + writel(2, fep->hwp + FEC_ECNTRL); + writel(0, fep->hwp + FEC_R_DES_ACTIVE); #ifndef CONFIG_M5272 - fecp->fec_hash_table_high = 0; - fecp->fec_hash_table_low = 0; + writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_HASH_TABLE_LOW); #endif /* The FEC Ethernet specific entries in the device structure. */ @@ -1814,20 +1790,21 @@ int __init fec_enet_init(struct net_device *dev, int index) mii_free = mii_cmds; /* setup MII interface */ - fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; - fecp->fec_x_cntrl = 0x00; + writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); + writel(0, fep->hwp + FEC_X_CNTRL); /* * Set MII speed to 2.5 MHz */ fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1; - fecp->fec_mii_speed = fep->phy_speed; + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); fec_restart(dev, 0); /* Clear and enable interrupts */ - fecp->fec_ievent = 0xffc00000; - fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII); + writel(0xffc00000, fep->hwp + FEC_IEVENT); + writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, + fep->hwp + FEC_IMASK); /* Queue up command to detect the PHY and initialize the * remainder of the interface. @@ -1846,47 +1823,36 @@ int __init fec_enet_init(struct net_device *dev, int index) static void fec_restart(struct net_device *dev, int duplex) { - struct fec_enet_private *fep; + struct fec_enet_private *fep = netdev_priv(dev); volatile cbd_t *bdp; - volatile fec_t *fecp; int i; - fep = netdev_priv(dev); - fecp = fep->hwp; - - /* Whack a reset. We should wait for this. - */ - fecp->fec_ecntrl = 1; + /* Whack a reset. We should wait for this. */ + writel(1, fep->hwp + FEC_ECNTRL); udelay(10); - /* Clear any outstanding interrupt. - */ - fecp->fec_ievent = 0xffc00000; + /* Clear any outstanding interrupt. */ + writel(0xffc00000, fep->hwp + FEC_IEVENT); - /* Set station address. - */ + /* Set station address. */ fec_set_mac_address(dev); - /* Reset all multicast. - */ - fecp->fec_grp_hash_table_high = 0; - fecp->fec_grp_hash_table_low = 0; + /* Reset all multicast. */ + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - /* Set maximum receive buffer size. - */ - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + /* Set maximum receive buffer size. */ + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); - /* Set receive and transmit descriptor base. - */ - fecp->fec_r_des_start = fep->bd_dma; - fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t) - * RX_RING_SIZE; + /* Set receive and transmit descriptor base. */ + writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); + writel((unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE, + fep->hwp + FEC_X_DES_START); fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; fep->cur_rx = fep->rx_bd_base; - /* Reset SKB transmit buffers. - */ + /* Reset SKB transmit buffers. */ fep->skb_cur = fep->skb_dirty = 0; for (i=0; i<=TX_RING_MOD_MASK; i++) { if (fep->tx_skbuff[i] != NULL) { @@ -1895,96 +1861,81 @@ fec_restart(struct net_device *dev, int duplex) } } - /* Initialize the receive buffer descriptors. - */ + /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; for (i=0; icbd_sc = BD_ENET_RX_EMPTY; bdp++; } - /* Set the last buffer to wrap. - */ + /* Set the last buffer to wrap. */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* ...and the same for transmmit. - */ + /* ...and the same for transmmit. */ bdp = fep->tx_bd_base; for (i=0; icbd_sc = 0; bdp->cbd_bufaddr = 0; bdp++; } - /* Set the last buffer to wrap. - */ + /* Set the last buffer to wrap. */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* Enable MII mode. - */ + /* Enable MII mode. */ if (duplex) { - fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */ - fecp->fec_x_cntrl = 0x04; /* FD enable */ + /* MII enable / FD enable */ + writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); + writel(0x04, fep->hwp + FEC_X_CNTRL); } else { - /* MII enable|No Rcv on Xmit */ - fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06; - fecp->fec_x_cntrl = 0x00; + /* MII enable / No Rcv on Xmit */ + writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL); + writel(0x0, fep->hwp + FEC_X_CNTRL); } fep->full_duplex = duplex; - /* Set MII speed. - */ - fecp->fec_mii_speed = fep->phy_speed; + /* Set MII speed. */ + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - /* And last, enable the transmit and receive processing. - */ - fecp->fec_ecntrl = 2; - fecp->fec_r_des_active = 0; + /* And last, enable the transmit and receive processing. */ + writel(2, fep->hwp + FEC_ECNTRL); + writel(0, fep->hwp + FEC_R_DES_ACTIVE); - /* Enable interrupts we wish to service. - */ - fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII); + /* Enable interrupts we wish to service. */ + writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, + fep->hwp + FEC_IMASK); } static void fec_stop(struct net_device *dev) { - volatile fec_t *fecp; - struct fec_enet_private *fep; - - fep = netdev_priv(dev); - fecp = fep->hwp; + struct fec_enet_private *fep = netdev_priv(dev); /* ** We cannot expect a graceful transmit stop without link !!! */ - if (fep->link) - { - fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ + if (fep->link) { + writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ udelay(10); - if (!(fecp->fec_ievent & FEC_ENET_GRA)) + if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA)) printk("fec_stop : Graceful transmit stop did not complete !\n"); - } + } - /* Whack a reset. We should wait for this. - */ - fecp->fec_ecntrl = 1; + /* Whack a reset. We should wait for this. */ + writel(1, fep->hwp + FEC_ECNTRL); udelay(10); - /* Clear outstanding MII command interrupts. - */ - fecp->fec_ievent = FEC_ENET_MII; + /* Clear outstanding MII command interrupts. */ + writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); - fecp->fec_imask = FEC_ENET_MII; - fecp->fec_mii_speed = fep->phy_speed; + writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); } static int __devinit diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 76c64c92e190..5474ba39d46c 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -20,82 +20,55 @@ * registers in the same peripheral device on different models * of the ColdFire! */ -typedef struct fec { - unsigned long fec_reserved0; - unsigned long fec_ievent; /* Interrupt event reg */ - unsigned long fec_imask; /* Interrupt mask reg */ - unsigned long fec_reserved1; - unsigned long fec_r_des_active; /* Receive descriptor reg */ - unsigned long fec_x_des_active; /* Transmit descriptor reg */ - unsigned long fec_reserved2[3]; - unsigned long fec_ecntrl; /* Ethernet control reg */ - unsigned long fec_reserved3[6]; - unsigned long fec_mii_data; /* MII manage frame reg */ - unsigned long fec_mii_speed; /* MII speed control reg */ - unsigned long fec_reserved4[7]; - unsigned long fec_mib_ctrlstat; /* MIB control/status reg */ - unsigned long fec_reserved5[7]; - unsigned long fec_r_cntrl; /* Receive control reg */ - unsigned long fec_reserved6[15]; - unsigned long fec_x_cntrl; /* Transmit Control reg */ - unsigned long fec_reserved7[7]; - unsigned long fec_addr_low; /* Low 32bits MAC address */ - unsigned long fec_addr_high; /* High 16bits MAC address */ - unsigned long fec_opd; /* Opcode + Pause duration */ - unsigned long fec_reserved8[10]; - unsigned long fec_hash_table_high; /* High 32bits hash table */ - unsigned long fec_hash_table_low; /* Low 32bits hash table */ - unsigned long fec_grp_hash_table_high;/* High 32bits hash table */ - unsigned long fec_grp_hash_table_low; /* Low 32bits hash table */ - unsigned long fec_reserved9[7]; - unsigned long fec_x_wmrk; /* FIFO transmit water mark */ - unsigned long fec_reserved10; - unsigned long fec_r_bound; /* FIFO receive bound reg */ - unsigned long fec_r_fstart; /* FIFO receive start reg */ - unsigned long fec_reserved11[11]; - unsigned long fec_r_des_start; /* Receive descriptor ring */ - unsigned long fec_x_des_start; /* Transmit descriptor ring */ - unsigned long fec_r_buff_size; /* Maximum receive buff size */ -} fec_t; +#define FEC_IEVENT 0x004 /* Interrupt event reg */ +#define FEC_IMASK 0x008 /* Interrupt mask reg */ +#define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ +#define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ +#define FEC_ECNTRL 0x024 /* Ethernet control reg */ +#define FEC_MII_DATA 0x040 /* MII manage frame reg */ +#define FEC_MII_SPEED 0x044 /* MII speed control reg */ +#define FEC_MIB_CTRLSTAT 0x064 /* MIB control/status reg */ +#define FEC_R_CNTRL 0x084 /* Receive control reg */ +#define FEC_X_CNTRL 0x0c4 /* Transmit Control reg */ +#define FEC_ADDR_LOW 0x0e4 /* Low 32bits MAC address */ +#define FEC_ADDR_HIGH 0x0e8 /* High 16bits MAC address */ +#define FEC_OPD 0x0ec /* Opcode + Pause duration */ +#define FEC_HASH_TABLE_HIGH 0x118 /* High 32bits hash table */ +#define FEC_HASH_TABLE_LOW 0x11c /* Low 32bits hash table */ +#define FEC_GRP_HASH_TABLE_HIGH 0x120 /* High 32bits hash table */ +#define FEC_GRP_HASH_TABLE_LOW 0x124 /* Low 32bits hash table */ +#define FEC_X_WMRK 0x144 /* FIFO transmit water mark */ +#define FEC_R_BOUND 0x14c /* FIFO receive bound reg */ +#define FEC_R_FSTART 0x150 /* FIFO receive start reg */ +#define FEC_R_DES_START 0x180 /* Receive descriptor ring */ +#define FEC_X_DES_START 0x184 /* Transmit descriptor ring */ +#define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ #else -/* - * Define device register set address map. - */ -typedef struct fec { - unsigned long fec_ecntrl; /* Ethernet control reg */ - unsigned long fec_ievent; /* Interrupt even reg */ - unsigned long fec_imask; /* Interrupt mask reg */ - unsigned long fec_ivec; /* Interrupt vec status reg */ - unsigned long fec_r_des_active; /* Receive descriptor reg */ - unsigned long fec_x_des_active; /* Transmit descriptor reg */ - unsigned long fec_reserved1[10]; - unsigned long fec_mii_data; /* MII manage frame reg */ - unsigned long fec_mii_speed; /* MII speed control reg */ - unsigned long fec_reserved2[17]; - unsigned long fec_r_bound; /* FIFO receive bound reg */ - unsigned long fec_r_fstart; /* FIFO receive start reg */ - unsigned long fec_reserved3[4]; - unsigned long fec_x_wmrk; /* FIFO transmit water mark */ - unsigned long fec_reserved4; - unsigned long fec_x_fstart; /* FIFO transmit start reg */ - unsigned long fec_reserved5[21]; - unsigned long fec_r_cntrl; /* Receive control reg */ - unsigned long fec_max_frm_len; /* Maximum frame length reg */ - unsigned long fec_reserved6[14]; - unsigned long fec_x_cntrl; /* Transmit Control reg */ - unsigned long fec_reserved7[158]; - unsigned long fec_addr_low; /* Low 32bits MAC address */ - unsigned long fec_addr_high; /* High 16bits MAC address */ - unsigned long fec_grp_hash_table_high;/* High 32bits hash table */ - unsigned long fec_grp_hash_table_low; /* Low 32bits hash table */ - unsigned long fec_r_des_start; /* Receive descriptor ring */ - unsigned long fec_x_des_start; /* Transmit descriptor ring */ - unsigned long fec_r_buff_size; /* Maximum receive buff size */ - unsigned long reserved8[9]; - unsigned long fec_fifo_ram[112]; /* FIFO RAM buffer */ -} fec_t; +#define FEC_ECNTRL; 0x000 /* Ethernet control reg */ +#define FEC_IEVENT; 0x004 /* Interrupt even reg */ +#define FEC_IMASK; 0x008 /* Interrupt mask reg */ +#define FEC_IVEC; 0x00c /* Interrupt vec status reg */ +#define FEC_R_DES_ACTIVE; 0x010 /* Receive descriptor reg */ +#define FEC_X_DES_ACTIVE; 0x01c /* Transmit descriptor reg */ +#define FEC_MII_DATA 0x040 /* MII manage frame reg */ +#define FEC_MII_SPEED 0x044 /* MII speed control reg */ +#define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ +#define FEC_R_FSTART 0x090 /* FIFO receive start reg */ +#define FEC_X_WMRK 0x0a4 /* FIFO transmit water mark */ +#define FEC_X_FSTART 0x0ac /* FIFO transmit start reg */ +#define FEC_R_CNTRL 0x104 /* Receive control reg */ +#define FEC_MAX_FRM_LEN 0x108 /* Maximum frame length reg */ +#define FEC_X_CNTRL 0x144 /* Transmit Control reg */ +#define FEC_ADDR_LOW 0x3c0 /* Low 32bits MAC address */ +#define FEC_ADDR_HIGH 0x3c4 /* High 16bits MAC address */ +#define FEC_GRP_HASH_TABLE_HIGH 0x3c8 /* High 32bits hash table */ +#define FEC_GRP_HASH_TABLE_LOW 0x3cc /* Low 32bits hash table */ +#define FEC_R_DES_START 0x3d0 /* Receive descriptor ring */ +#define FEC_X_DES_START 0x3d4 /* Transmit descriptor ring */ +#define FEC_R_BUFF_SIZE 0x3d8 /* Maximum receive buff size */ +#define FEC_FIFO_RAM 0x400 /* FIFO RAM buffer */ #endif /* CONFIG_M5272 */ -- cgit v1.2.3 From 2e28532f7e63c3011f7b3c1516cfebd5321bdd15 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:16 +0000 Subject: fec: do not typedef struct types Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 37 ++++++++++++++++++++----------------- drivers/net/fec.h | 8 ++++---- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 37b333265629..f8396fb30326 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -180,10 +180,14 @@ struct fec_enet_private { /* CPM dual port RAM relative addresses. */ dma_addr_t bd_dma; - cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ - cbd_t *tx_bd_base; - cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ - cbd_t *dirty_tx; /* The ring entries to be free()ed. */ + /* Address of Rx and Tx buffers. */ + struct bufdesc *rx_bd_base; + struct bufdesc *tx_bd_base; + /* The next free ring entry */ + struct bufdesc *cur_rx, *cur_tx; + /* The ring entries to be free()ed. */ + struct bufdesc *dirty_tx; + uint tx_full; /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ spinlock_t hw_lock; @@ -289,7 +293,7 @@ static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - volatile cbd_t *bdp; + struct bufdesc *bdp; unsigned short status; unsigned long flags; @@ -374,7 +378,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } - fep->cur_tx = (cbd_t *)bdp; + fep->cur_tx = bdp; spin_unlock_irqrestore(&fep->hw_lock, flags); @@ -391,7 +395,7 @@ fec_timeout(struct net_device *dev) #ifndef final_version { int i; - cbd_t *bdp; + struct bufdesc *bdp; printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", @@ -471,7 +475,7 @@ static void fec_enet_tx(struct net_device *dev) { struct fec_enet_private *fep; - volatile cbd_t *bdp; + struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; @@ -534,7 +538,7 @@ fec_enet_tx(struct net_device *dev) netif_wake_queue(dev); } } - fep->dirty_tx = (cbd_t *)bdp; + fep->dirty_tx = bdp; spin_unlock_irq(&fep->hw_lock); } @@ -548,7 +552,7 @@ static void fec_enet_rx(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - volatile cbd_t *bdp; + struct bufdesc *bdp; unsigned short status; struct sk_buff *skb; ushort pkt_len; @@ -656,7 +660,7 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { writel(0, fep->hwp + FEC_R_DES_ACTIVE); #endif } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */ - fep->cur_rx = (cbd_t *)bdp; + fep->cur_rx = bdp; #if 0 /* Doing this here will allow us to process all frames in the @@ -1653,8 +1657,7 @@ int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); unsigned long mem_addr; - volatile cbd_t *bdp; - cbd_t *cbd_base; + struct bufdesc *bdp, *cbd_base; int i, j; /* Allocate memory for buffer descriptors. @@ -1695,7 +1698,7 @@ int __init fec_enet_init(struct net_device *dev, int index) } #endif - cbd_base = (cbd_t *)mem_addr; + cbd_base = (struct bufdesc *)mem_addr; /* Set receive and transmit descriptor base. */ @@ -1760,7 +1763,7 @@ int __init fec_enet_init(struct net_device *dev, int index) /* Set receive and transmit descriptor base. */ writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); - writel((unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE, + writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); #ifdef HAVE_mii_link_interrupt @@ -1824,7 +1827,7 @@ static void fec_restart(struct net_device *dev, int duplex) { struct fec_enet_private *fep = netdev_priv(dev); - volatile cbd_t *bdp; + struct bufdesc *bdp; int i; /* Whack a reset. We should wait for this. */ @@ -1846,7 +1849,7 @@ fec_restart(struct net_device *dev, int duplex) /* Set receive and transmit descriptor base. */ writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); - writel((unsigned long)fep->bd_dma + sizeof(cbd_t) * RX_RING_SIZE, + writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 5474ba39d46c..30b7dd671336 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -77,17 +77,17 @@ * Define the buffer descriptor structure. */ #ifdef CONFIG_ARCH_MXC -typedef struct bufdesc { +struct bufdesc { unsigned short cbd_datlen; /* Data length */ unsigned short cbd_sc; /* Control and status info */ unsigned long cbd_bufaddr; /* Buffer address */ -} cbd_t; +}; #else -typedef struct bufdesc { +struct bufdesc { unsigned short cbd_sc; /* Control and status info */ unsigned short cbd_datlen; /* Data length */ unsigned long cbd_bufaddr; /* Buffer address */ -} cbd_t; +}; #endif /* -- cgit v1.2.3 From 8d4dd5cff892e18a34422852c05a88b79ff978ed Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:17 +0000 Subject: fec: remove unnecessary cast Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index f8396fb30326..e03b1773966d 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1660,11 +1660,10 @@ int __init fec_enet_init(struct net_device *dev, int index) struct bufdesc *bdp, *cbd_base; int i, j; - /* Allocate memory for buffer descriptors. - */ - mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE, - &fep->bd_dma, GFP_KERNEL); - if (mem_addr == 0) { + /* Allocate memory for buffer descriptors. */ + cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, + GFP_KERNEL); + if (!cbd_base) { printk("FEC: allocate descriptor memory failed?\n"); return -ENOMEM; } @@ -1698,10 +1697,7 @@ int __init fec_enet_init(struct net_device *dev, int index) } #endif - cbd_base = (struct bufdesc *)mem_addr; - - /* Set receive and transmit descriptor base. - */ + /* Set receive and transmit descriptor base. */ fep->rx_bd_base = cbd_base; fep->tx_bd_base = cbd_base + RX_RING_SIZE; -- cgit v1.2.3 From 22f6b860da25abe2c3e33347ccb806e6bcc57390 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:18 +0000 Subject: fec: Codingstyle cleanups Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 354 +++++++++++++++++++++--------------------------------- 1 file changed, 139 insertions(+), 215 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index e03b1773966d..672566b89ecf 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -86,8 +86,7 @@ static unsigned char fec_mac_default[] = { #endif #endif /* CONFIG_M5272 */ -/* Forward declarations of some structures to support different PHYs -*/ +/* Forward declarations of some structures to support different PHYs */ typedef struct { uint mii_data; @@ -123,8 +122,7 @@ typedef struct { #error "FEC: descriptor ring size constants too large" #endif -/* Interrupt events/masks. -*/ +/* Interrupt events/masks. */ #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ #define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ #define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ @@ -177,15 +175,14 @@ struct fec_enet_private { ushort skb_cur; ushort skb_dirty; - /* CPM dual port RAM relative addresses. - */ + /* CPM dual port RAM relative addresses */ dma_addr_t bd_dma; - /* Address of Rx and Tx buffers. */ + /* Address of Rx and Tx buffers */ struct bufdesc *rx_bd_base; struct bufdesc *tx_bd_base; /* The next free ring entry */ struct bufdesc *cur_rx, *cur_tx; - /* The ring entries to be free()ed. */ + /* The ring entries to be free()ed */ struct bufdesc *dirty_tx; uint tx_full; @@ -245,19 +242,16 @@ static mii_list_t *mii_tail; static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *)); -/* Make MII read/write commands for the FEC. -*/ +/* Make MII read/write commands for the FEC */ #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ (VAL & 0xffff)) #define mk_mii_end 0 -/* Transmitter timeout. -*/ -#define TX_TIMEOUT (2*HZ) +/* Transmitter timeout */ +#define TX_TIMEOUT (2 * HZ) -/* Register definitions for the PHY. -*/ +/* Register definitions for the PHY */ #define MII_REG_CR 0 /* Control Register */ #define MII_REG_SR 1 /* Status Register */ @@ -307,7 +301,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) bdp = fep->cur_tx; status = bdp->cbd_sc; -#ifndef final_version + if (status & BD_ENET_TX_READY) { /* Ooops. All transmit buffers are full. Bail out. * This should not happen, since dev->tbusy should be set. @@ -316,21 +310,18 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&fep->hw_lock, flags); return 1; } -#endif - /* Clear all of the status flags. - */ + /* Clear all of the status flags */ status &= ~BD_ENET_TX_STATS; - /* Set buffer length and buffer pointer. - */ + /* Set buffer length and buffer pointer */ bdp->cbd_bufaddr = __pa(skb->data); bdp->cbd_datlen = skb->len; /* - * On some FEC implementations data must be aligned on - * 4-byte boundaries. Use bounce buffers to copy data - * and get it aligned. Ugh. + * On some FEC implementations data must be aligned on + * 4-byte boundaries. Use bounce buffers to copy data + * and get it aligned. Ugh. */ if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { unsigned int index; @@ -339,8 +330,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); } - /* Save skb pointer. - */ + /* Save skb pointer */ fep->tx_skbuff[fep->skb_cur] = skb; dev->stats.tx_bytes += skb->len; @@ -355,7 +345,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ - status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; @@ -365,13 +354,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Trigger transmission start */ writel(0, fep->hwp + FEC_X_DES_ACTIVE); - /* If this was the last BD in the ring, start at the beginning again. - */ - if (status & BD_ENET_TX_WRAP) { + /* If this was the last BD in the ring, start at the beginning again. */ + if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; - } else { + else bdp++; - } if (bdp == fep->dirty_tx) { fep->tx_full = 1; @@ -429,9 +416,6 @@ fec_timeout(struct net_device *dev) netif_wake_queue(dev); } -/* The interrupt handler. - * This is called from the MPC core interrupt. - */ static irqreturn_t fec_enet_interrupt(int irq, void * dev_id) { @@ -440,12 +424,10 @@ fec_enet_interrupt(int irq, void * dev_id) uint int_events; irqreturn_t ret = IRQ_NONE; - /* Get the interrupt events that caused us to be here. */ do { int_events = readl(fep->hwp + FEC_IEVENT); writel(int_events, fep->hwp + FEC_IEVENT); - /* Handle receive event in its own function. */ if (int_events & FEC_ENET_RXF) { ret = IRQ_HANDLED; fec_enet_rx(dev); @@ -506,31 +488,27 @@ fec_enet_tx(struct net_device *dev) dev->stats.tx_packets++; } -#ifndef final_version if (status & BD_ENET_TX_READY) printk("HEY! Enet xmit interrupt and TX_READY.\n"); -#endif + /* Deferred means some collisions occurred during transmit, * but we eventually sent the packet OK. */ if (status & BD_ENET_TX_DEF) dev->stats.collisions++; - /* Free the sk buffer associated with this last transmit. - */ + /* Free the sk buffer associated with this last transmit */ dev_kfree_skb_any(skb); fep->tx_skbuff[fep->skb_dirty] = NULL; fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; - /* Update pointer to next buffer descriptor to be transmitted. - */ + /* Update pointer to next buffer descriptor to be transmitted */ if (status & BD_ENET_TX_WRAP) bdp = fep->tx_bd_base; else bdp++; - /* Since we have freed up a buffer, the ring is no longer - * full. + /* Since we have freed up a buffer, the ring is no longer full */ if (fep->tx_full) { fep->tx_full = 0; @@ -569,114 +547,93 @@ fec_enet_rx(struct net_device *dev) */ bdp = fep->cur_rx; -while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { + while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { -#ifndef final_version - /* Since we have allocated space to hold a complete frame, - * the last indicator should be set. - */ - if ((status & BD_ENET_RX_LAST) == 0) - printk("FEC ENET: rcv is not +last\n"); -#endif + /* Since we have allocated space to hold a complete frame, + * the last indicator should be set. + */ + if ((status & BD_ENET_RX_LAST) == 0) + printk("FEC ENET: rcv is not +last\n"); - if (!fep->opened) - goto rx_processing_done; + if (!fep->opened) + goto rx_processing_done; - /* Check for errors. */ - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | + /* Check for errors. */ + if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) { - dev->stats.rx_errors++; - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { - /* Frame too long or too short. */ - dev->stats.rx_length_errors++; + dev->stats.rx_errors++; + if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { + /* Frame too long or too short. */ + dev->stats.rx_length_errors++; + } + if (status & BD_ENET_RX_NO) /* Frame alignment */ + dev->stats.rx_frame_errors++; + if (status & BD_ENET_RX_CR) /* CRC Error */ + dev->stats.rx_crc_errors++; + if (status & BD_ENET_RX_OV) /* FIFO overrun */ + dev->stats.rx_fifo_errors++; } - if (status & BD_ENET_RX_NO) /* Frame alignment */ - dev->stats.rx_frame_errors++; - if (status & BD_ENET_RX_CR) /* CRC Error */ - dev->stats.rx_crc_errors++; - if (status & BD_ENET_RX_OV) /* FIFO overrun */ - dev->stats.rx_fifo_errors++; - } - /* Report late collisions as a frame error. - * On this error, the BD is closed, but we don't know what we - * have in the buffer. So, just drop this frame on the floor. - */ - if (status & BD_ENET_RX_CL) { - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; - goto rx_processing_done; - } + /* Report late collisions as a frame error. + * On this error, the BD is closed, but we don't know what we + * have in the buffer. So, just drop this frame on the floor. + */ + if (status & BD_ENET_RX_CL) { + dev->stats.rx_errors++; + dev->stats.rx_frame_errors++; + goto rx_processing_done; + } - /* Process the incoming frame. - */ - dev->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; - dev->stats.rx_bytes += pkt_len; - data = (__u8*)__va(bdp->cbd_bufaddr); + /* Process the incoming frame. */ + dev->stats.rx_packets++; + pkt_len = bdp->cbd_datlen; + dev->stats.rx_bytes += pkt_len; + data = (__u8*)__va(bdp->cbd_bufaddr); - dma_sync_single(NULL, (unsigned long)__pa(data), + dma_sync_single(NULL, (unsigned long)__pa(data), pkt_len - 4, DMA_FROM_DEVICE); - /* This does 16 byte alignment, exactly what we need. - * The packet length includes FCS, but we don't want to - * include that when passing upstream as it messes up - * bridging applications. - */ - skb = dev_alloc_skb(pkt_len-4); - - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - dev->stats.rx_dropped++; - } else { - skb_put(skb,pkt_len-4); /* Make room */ - skb_copy_to_linear_data(skb, data, pkt_len-4); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - } - rx_processing_done: - - /* Clear the status flags for this buffer. - */ - status &= ~BD_ENET_RX_STATS; + /* This does 16 byte alignment, exactly what we need. + * The packet length includes FCS, but we don't want to + * include that when passing upstream as it messes up + * bridging applications. + */ + skb = dev_alloc_skb(pkt_len - 4); - /* Mark the buffer empty. - */ - status |= BD_ENET_RX_EMPTY; - bdp->cbd_sc = status; + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", + dev->name); + dev->stats.rx_dropped++; + } else { + skb_put(skb, pkt_len - 4); /* Make room */ + skb_copy_to_linear_data(skb, data, pkt_len - 4); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + } +rx_processing_done: + /* Clear the status flags for this buffer */ + status &= ~BD_ENET_RX_STATS; - /* Update BD pointer to next entry. - */ - if (status & BD_ENET_RX_WRAP) - bdp = fep->rx_bd_base; - else - bdp++; + /* Mark the buffer empty */ + status |= BD_ENET_RX_EMPTY; + bdp->cbd_sc = status; -#if 1 - /* Doing this here will keep the FEC running while we process - * incoming frames. On a heavily loaded network, we should be - * able to keep up at the expense of system resources. - */ - writel(0, fep->hwp + FEC_R_DES_ACTIVE); -#endif - } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */ + /* Update BD pointer to next entry */ + if (status & BD_ENET_RX_WRAP) + bdp = fep->rx_bd_base; + else + bdp++; + /* Doing this here will keep the FEC running while we process + * incoming frames. On a heavily loaded network, we should be + * able to keep up at the expense of system resources. + */ + writel(0, fep->hwp + FEC_R_DES_ACTIVE); + } fep->cur_rx = bdp; -#if 0 - /* Doing this here will allow us to process all frames in the - * ring before the FEC is allowed to put more there. On a heavily - * loaded network, some frames may be lost. Unfortunately, this - * increases the interrupt overhead since we can potentially work - * our way back to the interrupt return only to come right back - * here. - */ - fecp->fec_r_des_active = 0; -#endif - spin_unlock_irq(&fep->hw_lock); } - /* called from interrupt context */ static void fec_enet_mii(struct net_device *dev) @@ -714,8 +671,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi mii_list_t *mip; int retval; - /* Add PHY address to register command. - */ + /* Add PHY address to register command */ fep = netdev_priv(dev); spin_lock_irqsave(&fep->mii_lock, flags); @@ -1358,11 +1314,6 @@ static void mii_relink(struct work_struct *work) fec_restart(dev, duplex); } else fec_stop(dev); - -#if 0 - enable_irq(fep->mii_irq); -#endif - } /* mii_queue_relink is called in interrupt context from mii_link_interrupt */ @@ -1371,12 +1322,12 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) struct fec_enet_private *fep = netdev_priv(dev); /* - ** We cannot queue phy_task twice in the workqueue. It - ** would cause an endless loop in the workqueue. - ** Fortunately, if the last mii_relink entry has not yet been - ** executed now, it will do the job for the current interrupt, - ** which is just what we want. - */ + * We cannot queue phy_task twice in the workqueue. It + * would cause an endless loop in the workqueue. + * Fortunately, if the last mii_relink entry has not yet been + * executed now, it will do the job for the current interrupt, + * which is just what we want. + */ if (fep->mii_phy_task_queued) return; @@ -1407,8 +1358,7 @@ phy_cmd_t const phy_cmd_config[] = { { mk_mii_end, } }; -/* Read remainder of PHY ID. -*/ +/* Read remainder of PHY ID. */ static void mii_discover_phy3(uint mii_reg, struct net_device *dev) { @@ -1447,8 +1397,7 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) if (fep->phy_addr < 32) { if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) { - /* Got first part of ID, now get remainder. - */ + /* Got first part of ID, now get remainder */ fep->phy_id = phytype << 16; mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3); @@ -1468,8 +1417,7 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) } } -/* This interrupt occurs when the PHY detects a link change. -*/ +/* This interrupt occurs when the PHY detects a link change */ #ifdef HAVE_mii_link_interrupt static irqreturn_t mii_link_interrupt(int irq, void * dev_id) @@ -1479,10 +1427,6 @@ mii_link_interrupt(int irq, void * dev_id) fec_phy_ack_intr(); -#if 0 - disable_irq(fep->mii_irq); /* disable now, enable later */ -#endif - mii_do_cmd(dev, fep->phy->ack_int); mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ @@ -1533,7 +1477,7 @@ fec_enet_open(struct net_device *dev) netif_start_queue(dev); fep->opened = 1; - return 0; /* Success */ + return 0; } static int @@ -1541,8 +1485,7 @@ fec_enet_close(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - /* Don't know what to do yet. - */ + /* Don't know what to do yet. */ fep->opened = 0; netif_stop_queue(dev); fec_stop(dev); @@ -1570,7 +1513,7 @@ static void set_multicast_list(struct net_device *dev) unsigned int i, j, bit, data, crc, tmp; unsigned char hash; - if (dev->flags&IFF_PROMISC) { + if (dev->flags & IFF_PROMISC) { tmp = readl(fep->hwp + FEC_R_CNTRL); tmp |= 0x8; writel(tmp, fep->hwp + FEC_R_CNTRL); @@ -1581,42 +1524,37 @@ static void set_multicast_list(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { /* Catch all multicast addresses, so set the - * filter to all 1's. + * filter to all 1's */ writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); } else { - /* Clear filter and add the addresses in hash register. - */ + /* Clear filter and add the addresses in hash register + */ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); dmi = dev->mc_list; - for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) - { - /* Only support group multicast for now. - */ + for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) { + /* Only support group multicast for now */ if (!(dmi->dmi_addr[0] & 1)) continue; - /* calculate crc32 value of mac address - */ + /* calculate crc32 value of mac address */ crc = 0xffffffff; - for (i = 0; i < dmi->dmi_addrlen; i++) - { + for (i = 0; i < dmi->dmi_addrlen; i++) { data = dmi->dmi_addr[i]; - for (bit = 0; bit < 8; bit++, data >>= 1) - { + for (bit = 0; bit < 8; bit++, data >>= 1) { crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0); } } /* only upper 6 bits (HASH_BITS) are used - which point to specific bit in he hash registers - */ + * which point to specific bit in he hash registers + */ hash = (crc >> (32 - HASH_BITS)) & 0x3f; if (hash > 31) { @@ -1633,8 +1571,7 @@ static void set_multicast_list(struct net_device *dev) } } -/* Set a MAC change in hardware. - */ +/* Set a MAC change in hardware. */ static void fec_set_mac_address(struct net_device *dev) { @@ -1675,8 +1612,7 @@ int __init fec_enet_init(struct net_device *dev, int index) fep->hwp = (void __iomem *)dev->base_addr; fep->netdev = dev; - /* Whack a reset. We should wait for this. - */ + /* Whack a reset. We should wait for this. */ writel(1, fep->hwp + FEC_ECNTRL); udelay(10); @@ -1706,18 +1642,15 @@ int __init fec_enet_init(struct net_device *dev, int index) fep->skb_cur = fep->skb_dirty = 0; - /* Initialize the receive buffer descriptors. - */ + /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; for (i=0; icbd_sc = BD_ENET_RX_EMPTY; bdp->cbd_bufaddr = __pa(mem_addr); @@ -1726,13 +1659,11 @@ int __init fec_enet_init(struct net_device *dev, int index) } } - /* Set the last buffer to wrap. - */ + /* Set the last buffer to wrap */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* ...and the same for transmmit. - */ + /* ...and the same for transmit */ bdp = fep->tx_bd_base; for (i=0, j=FEC_ENET_TX_FRPPG; i= FEC_ENET_TX_FRPPG) { @@ -1744,20 +1675,17 @@ int __init fec_enet_init(struct net_device *dev, int index) } fep->tx_bounce[i] = (unsigned char *) mem_addr; - /* Initialize the BD for every fragment in the page. - */ + /* Initialize the BD for every fragment in the page */ bdp->cbd_sc = 0; bdp->cbd_bufaddr = 0; bdp++; } - /* Set the last buffer to wrap. - */ + /* Set the last buffer to wrap */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* Set receive and transmit descriptor base. - */ + /* Set receive and transmit descriptor base */ writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); @@ -1776,7 +1704,7 @@ int __init fec_enet_init(struct net_device *dev, int index) writel(0, fep->hwp + FEC_HASH_TABLE_LOW); #endif - /* The FEC Ethernet specific entries in the device structure. */ + /* The FEC Ethernet specific entries in the device structure */ dev->open = fec_enet_open; dev->hard_start_xmit = fec_enet_start_xmit; dev->tx_timeout = fec_timeout; @@ -1792,9 +1720,7 @@ int __init fec_enet_init(struct net_device *dev, int index) writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); writel(0, fep->hwp + FEC_X_CNTRL); - /* - * Set MII speed to 2.5 MHz - */ + /* Set MII speed to 2.5 MHz */ fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1; writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); @@ -1853,8 +1779,8 @@ fec_restart(struct net_device *dev, int duplex) /* Reset SKB transmit buffers. */ fep->skb_cur = fep->skb_dirty = 0; - for (i=0; i<=TX_RING_MOD_MASK; i++) { - if (fep->tx_skbuff[i] != NULL) { + for (i = 0; i <= TX_RING_MOD_MASK; i++) { + if (fep->tx_skbuff[i]) { dev_kfree_skb_any(fep->tx_skbuff[i]); fep->tx_skbuff[i] = NULL; } @@ -1862,20 +1788,20 @@ fec_restart(struct net_device *dev, int duplex) /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; - for (i=0; icbd_sc = BD_ENET_RX_EMPTY; bdp++; } - /* Set the last buffer to wrap. */ + /* Set the last buffer to wrap */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* ...and the same for transmmit. */ + /* ...and the same for transmit */ bdp = fep->tx_bd_base; - for (i=0; icbd_sc = 0; @@ -1883,11 +1809,11 @@ fec_restart(struct net_device *dev, int duplex) bdp++; } - /* Set the last buffer to wrap. */ + /* Set the last buffer to wrap */ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* Enable MII mode. */ + /* Enable MII mode */ if (duplex) { /* MII enable / FD enable */ writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); @@ -1899,14 +1825,14 @@ fec_restart(struct net_device *dev, int duplex) } fep->full_duplex = duplex; - /* Set MII speed. */ + /* Set MII speed */ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); - /* And last, enable the transmit and receive processing. */ + /* And last, enable the transmit and receive processing */ writel(2, fep->hwp + FEC_ECNTRL); writel(0, fep->hwp + FEC_R_DES_ACTIVE); - /* Enable interrupts we wish to service. */ + /* Enable interrupts we wish to service */ writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, fep->hwp + FEC_IMASK); } @@ -1916,9 +1842,7 @@ fec_stop(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - /* - ** We cannot expect a graceful transmit stop without link !!! - */ + /* We cannot expect a graceful transmit stop without link !!! */ if (fep->link) { writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ udelay(10); -- cgit v1.2.3 From 4e8318368af44488f6438a31537ddb57de0d4e00 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:19 +0000 Subject: fec: refactor set_multicast_list() to make it more readable Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 99 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 672566b89ecf..6ac1b90c5820 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1517,57 +1517,60 @@ static void set_multicast_list(struct net_device *dev) tmp = readl(fep->hwp + FEC_R_CNTRL); tmp |= 0x8; writel(tmp, fep->hwp + FEC_R_CNTRL); - } else { - tmp = readl(fep->hwp + FEC_R_CNTRL); - tmp &= ~0x8; - writel(tmp, fep->hwp + FEC_R_CNTRL); + return; + } - if (dev->flags & IFF_ALLMULTI) { - /* Catch all multicast addresses, so set the - * filter to all 1's - */ - writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - } else { - /* Clear filter and add the addresses in hash register - */ - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - - dmi = dev->mc_list; - - for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) { - /* Only support group multicast for now */ - if (!(dmi->dmi_addr[0] & 1)) - continue; - - /* calculate crc32 value of mac address */ - crc = 0xffffffff; - - for (i = 0; i < dmi->dmi_addrlen; i++) { - data = dmi->dmi_addr[i]; - for (bit = 0; bit < 8; bit++, data >>= 1) { - crc = (crc >> 1) ^ - (((crc ^ data) & 1) ? CRC32_POLY : 0); - } - } - - /* only upper 6 bits (HASH_BITS) are used - * which point to specific bit in he hash registers - */ - hash = (crc >> (32 - HASH_BITS)) & 0x3f; - - if (hash > 31) { - tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - tmp |= 1 << (hash - 32); - writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - } else { - tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); - tmp |= 1 << hash; - writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - } + tmp = readl(fep->hwp + FEC_R_CNTRL); + tmp &= ~0x8; + writel(tmp, fep->hwp + FEC_R_CNTRL); + + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's + */ + writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + + return; + } + + /* Clear filter and add the addresses in hash register + */ + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + + dmi = dev->mc_list; + + for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) { + /* Only support group multicast for now */ + if (!(dmi->dmi_addr[0] & 1)) + continue; + + /* calculate crc32 value of mac address */ + crc = 0xffffffff; + + for (i = 0; i < dmi->dmi_addrlen; i++) { + data = dmi->dmi_addr[i]; + for (bit = 0; bit < 8; bit++, data >>= 1) { + crc = (crc >> 1) ^ + (((crc ^ data) & 1) ? CRC32_POLY : 0); } } + + /* only upper 6 bits (HASH_BITS) are used + * which point to specific bit in he hash registers + */ + hash = (crc >> (32 - HASH_BITS)) & 0x3f; + + if (hash > 31) { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + tmp |= 1 << (hash - 32); + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + } else { + tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); + tmp |= 1 << hash; + writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + } } } -- cgit v1.2.3 From 4f1ceb4b46d523382f5a46622af9d3315a9b3e7f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:20 +0000 Subject: fec: refactor init function fec_enet_init() does the hardware initialisation and then calls fec_restart() which does the same initialisation again, so we can safely remove the initialisation from fec_enet_init(). Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 39 ++++----------------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 6ac1b90c5820..5ca2d6bcc23a 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1615,10 +1615,6 @@ int __init fec_enet_init(struct net_device *dev, int index) fep->hwp = (void __iomem *)dev->base_addr; fep->netdev = dev; - /* Whack a reset. We should wait for this. */ - writel(1, fep->hwp + FEC_ECNTRL); - udelay(10); - /* Set the Ethernet address */ #ifdef CONFIG_M5272 fec_get_mac(dev); @@ -1640,11 +1636,6 @@ int __init fec_enet_init(struct net_device *dev, int index) fep->rx_bd_base = cbd_base; fep->tx_bd_base = cbd_base + RX_RING_SIZE; - fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; - fep->cur_rx = fep->rx_bd_base; - - fep->skb_cur = fep->skb_dirty = 0; - /* Initialize the receive buffer descriptors. */ bdp = fep->rx_bd_base; for (i=0; icbd_sc |= BD_SC_WRAP; - /* Set receive and transmit descriptor base */ - writel(fep->bd_dma, fep->hwp + FEC_R_DES_START); - writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE, - fep->hwp + FEC_X_DES_START); - #ifdef HAVE_mii_link_interrupt fec_request_mii_intr(dev); #endif - - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); - writel(2, fep->hwp + FEC_ECNTRL); - writel(0, fep->hwp + FEC_R_DES_ACTIVE); -#ifndef CONFIG_M5272 - writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -#endif - /* The FEC Ethernet specific entries in the device structure */ dev->open = fec_enet_open; dev->hard_start_xmit = fec_enet_start_xmit; @@ -1719,21 +1694,11 @@ int __init fec_enet_init(struct net_device *dev, int index) mii_cmds[i].mii_next = &mii_cmds[i+1]; mii_free = mii_cmds; - /* setup MII interface */ - writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL); - writel(0, fep->hwp + FEC_X_CNTRL); - /* Set MII speed to 2.5 MHz */ fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1; - writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); fec_restart(dev, 0); - /* Clear and enable interrupts */ - writel(0xffc00000, fep->hwp + FEC_IEVENT); - writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII, - fep->hwp + FEC_IMASK); - /* Queue up command to detect the PHY and initialize the * remainder of the interface. */ @@ -1768,6 +1733,10 @@ fec_restart(struct net_device *dev, int duplex) /* Reset all multicast. */ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); +#ifndef CONFIG_M5272 + writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); + writel(0, fep->hwp + FEC_HASH_TABLE_LOW); +#endif /* Set maximum receive buffer size. */ writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); -- cgit v1.2.3 From 8549889c3369f7653bd98861c3d2cf97d810dc37 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:21 +0000 Subject: fec: align receive packets Otherwise we get a lot of alignment errors Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 5ca2d6bcc23a..ba3eb54b63f5 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -598,13 +598,14 @@ fec_enet_rx(struct net_device *dev) * include that when passing upstream as it messes up * bridging applications. */ - skb = dev_alloc_skb(pkt_len - 4); + skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN); - if (skb == NULL) { + if (unlikely(!skb)) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; } else { + skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len - 4); /* Make room */ skb_copy_to_linear_data(skb, data, pkt_len - 4); skb->protocol = eth_type_trans(skb, dev); -- cgit v1.2.3 From 3644ee00c43cca08c9baac7eaea22250aaf84182 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:22 +0000 Subject: fec: remove debugging printks These printks in fec_timeout do not give useful information in a production kernel. Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index ba3eb54b63f5..7b3e331dd442 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -377,41 +377,8 @@ fec_timeout(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - printk("%s: transmit timed out.\n", dev->name); dev->stats.tx_errors++; -#ifndef final_version - { - int i; - struct bufdesc *bdp; - - printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", - (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", - (unsigned long)fep->dirty_tx, - (unsigned long)fep->cur_rx); - - bdp = fep->tx_bd_base; - printk(" tx: %u buffers\n", TX_RING_SIZE); - for (i = 0 ; i < TX_RING_SIZE; i++) { - printk(" %08x: %04x %04x %08x\n", - (uint) bdp, - bdp->cbd_sc, - bdp->cbd_datlen, - (int) bdp->cbd_bufaddr); - bdp++; - } - bdp = fep->rx_bd_base; - printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE); - for (i = 0 ; i < RX_RING_SIZE; i++) { - printk(" %08x: %04x %04x %08x\n", - (uint) bdp, - bdp->cbd_sc, - bdp->cbd_datlen, - (int) bdp->cbd_bufaddr); - bdp++; - } - } -#endif fec_restart(dev, fep->full_duplex); netif_wake_queue(dev); } -- cgit v1.2.3 From 009fda83ee2f38e5deb9d62fc54a904a92645fe4 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:23 +0000 Subject: fec: switch to net_device_ops Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 7b3e331dd442..54ee493768f1 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -210,17 +210,13 @@ struct fec_enet_private { int full_duplex; }; -static int fec_enet_open(struct net_device *dev); -static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); static void fec_enet_mii(struct net_device *dev); static irqreturn_t fec_enet_interrupt(int irq, void * dev_id); static void fec_enet_tx(struct net_device *dev); static void fec_enet_rx(struct net_device *dev); static int fec_enet_close(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); static void fec_restart(struct net_device *dev, int duplex); static void fec_stop(struct net_device *dev); -static void fec_set_mac_address(struct net_device *dev); /* MII processing. We keep this as simple as possible. Requests are @@ -1410,7 +1406,6 @@ fec_enet_open(struct net_device *dev) /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ - fec_set_mac_address(dev); fep->sequence_done = 0; fep->link = 0; @@ -1543,19 +1538,35 @@ static void set_multicast_list(struct net_device *dev) } /* Set a MAC change in hardware. */ -static void -fec_set_mac_address(struct net_device *dev) +static int +fec_set_mac_address(struct net_device *dev, void *p) { struct fec_enet_private *fep = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - /* Set station address. */ writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) | (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), fep->hwp + FEC_ADDR_LOW); writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), fep + FEC_ADDR_HIGH); + return 0; } +static const struct net_device_ops fec_netdev_ops = { + .ndo_open = fec_enet_open, + .ndo_stop = fec_enet_close, + .ndo_start_xmit = fec_enet_start_xmit, + .ndo_set_multicast_list = set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_tx_timeout = fec_timeout, + .ndo_set_mac_address = fec_set_mac_address, +}; + /* * XXX: We need to clean up on failure exits here. * @@ -1651,12 +1662,8 @@ int __init fec_enet_init(struct net_device *dev, int index) fec_request_mii_intr(dev); #endif /* The FEC Ethernet specific entries in the device structure */ - dev->open = fec_enet_open; - dev->hard_start_xmit = fec_enet_start_xmit; - dev->tx_timeout = fec_timeout; dev->watchdog_timeo = TX_TIMEOUT; - dev->stop = fec_enet_close; - dev->set_multicast_list = set_multicast_list; + dev->netdev_ops = &fec_netdev_ops; for (i=0; ihwp + FEC_IEVENT); - /* Set station address. */ - fec_set_mac_address(dev); - /* Reset all multicast. */ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); -- cgit v1.2.3 From f0b3fbeae11a526c3d308b691684589ee37c359b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:24 +0000 Subject: FEC Buffer rework Allocate buffers in fec_open and free them again in fec_close. This makes it possible to use this driver as a module. Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 139 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 54ee493768f1..54d6f86d9f6d 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -172,6 +172,7 @@ struct fec_enet_private { /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; + struct sk_buff* rx_skbuff[RX_RING_SIZE]; ushort skb_cur; ushort skb_dirty; @@ -335,8 +336,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Push the data cache so the CPM does not get stale memory * data. */ - dma_sync_single(NULL, bdp->cbd_bufaddr, - bdp->cbd_datlen, DMA_TO_DEVICE); + bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, + FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. @@ -429,7 +430,11 @@ fec_enet_tx(struct net_device *dev) bdp = fep->dirty_tx; while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { - if (bdp == fep->cur_tx && fep->tx_full == 0) break; + if (bdp == fep->cur_tx && fep->tx_full == 0) + break; + + dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); + bdp->cbd_bufaddr = 0; skb = fep->tx_skbuff[fep->skb_dirty]; /* Check for errors. */ @@ -553,8 +558,8 @@ fec_enet_rx(struct net_device *dev) dev->stats.rx_bytes += pkt_len; data = (__u8*)__va(bdp->cbd_bufaddr); - dma_sync_single(NULL, (unsigned long)__pa(data), - pkt_len - 4, DMA_FROM_DEVICE); + dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen, + DMA_FROM_DEVICE); /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to @@ -574,6 +579,9 @@ fec_enet_rx(struct net_device *dev) skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); } + + bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen, + DMA_FROM_DEVICE); rx_processing_done: /* Clear the status flags for this buffer */ status &= ~BD_ENET_RX_STATS; @@ -1398,15 +1406,86 @@ mii_link_interrupt(int irq, void * dev_id) } #endif +static void fec_enet_free_buffers(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + int i; + struct sk_buff *skb; + struct bufdesc *bdp; + + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + skb = fep->rx_skbuff[i]; + + if (bdp->cbd_bufaddr) + dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); + if (skb) + dev_kfree_skb(skb); + bdp++; + } + + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) + kfree(fep->tx_bounce[i]); +} + +static int fec_enet_alloc_buffers(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + int i; + struct sk_buff *skb; + struct bufdesc *bdp; + + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE); + if (!skb) { + fec_enet_free_buffers(dev); + return -ENOMEM; + } + fep->rx_skbuff[i] = skb; + + bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, + FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); + bdp->cbd_sc = BD_ENET_RX_EMPTY; + bdp++; + } + + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) { + fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); + + bdp->cbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; + } + + /* Set the last buffer to wrap. */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + return 0; +} + static int fec_enet_open(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); + int ret; /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ + ret = fec_enet_alloc_buffers(dev); + if (ret) + return ret; + fep->sequence_done = 0; fep->link = 0; @@ -1453,6 +1532,8 @@ fec_enet_close(struct net_device *dev) netif_stop_queue(dev); fec_stop(dev); + fec_enet_free_buffers(dev); + return 0; } @@ -1575,9 +1656,8 @@ static const struct net_device_ops fec_netdev_ops = { int __init fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); - unsigned long mem_addr; - struct bufdesc *bdp, *cbd_base; - int i, j; + struct bufdesc *cbd_base; + int i; /* Allocate memory for buffer descriptors. */ cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, @@ -1615,49 +1695,6 @@ int __init fec_enet_init(struct net_device *dev, int index) fep->rx_bd_base = cbd_base; fep->tx_bd_base = cbd_base + RX_RING_SIZE; - /* Initialize the receive buffer descriptors. */ - bdp = fep->rx_bd_base; - for (i=0; icbd_sc = BD_ENET_RX_EMPTY; - bdp->cbd_bufaddr = __pa(mem_addr); - mem_addr += FEC_ENET_RX_FRSIZE; - bdp++; - } - } - - /* Set the last buffer to wrap */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - /* ...and the same for transmit */ - bdp = fep->tx_bd_base; - for (i=0, j=FEC_ENET_TX_FRPPG; i= FEC_ENET_TX_FRPPG) { - mem_addr = __get_free_page(GFP_KERNEL); - j = 1; - } else { - mem_addr += FEC_ENET_TX_FRSIZE; - j++; - } - fep->tx_bounce[i] = (unsigned char *) mem_addr; - - /* Initialize the BD for every fragment in the page */ - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } - - /* Set the last buffer to wrap */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - #ifdef HAVE_mii_link_interrupt fec_request_mii_intr(dev); #endif -- cgit v1.2.3 From fe957c40ec5e2763b9977c565beab3bde3aaf85b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 15 Apr 2009 01:32:25 +0000 Subject: fec: call fec_restart() in fec_open() We called fec_stop() in fec_enet_close(), thus we have to call fec_restart() in fec_enet_open(). Signed-off-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/fec.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 54d6f86d9f6d..63eaf5de2300 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1489,6 +1489,8 @@ fec_enet_open(struct net_device *dev) fep->sequence_done = 0; fep->link = 0; + fec_restart(dev, 1); + if (fep->phy) { mii_do_cmd(dev, fep->phy->ack_int); mii_do_cmd(dev, fep->phy->config); @@ -1505,18 +1507,14 @@ fec_enet_open(struct net_device *dev) schedule(); mii_do_cmd(dev, fep->phy->startup); - - /* Set the initial link state to true. A lot of hardware - * based on this device does not implement a PHY interrupt, - * so we are never notified of link change. - */ - fep->link = 1; - } else { - fep->link = 1; /* lets just try it and see */ - /* no phy, go full duplex, it's most likely a hub chip */ - fec_restart(dev, 1); } + /* Set the initial link state to true. A lot of hardware + * based on this device does not implement a PHY interrupt, + * so we are never notified of link change. + */ + fep->link = 1; + netif_start_queue(dev); fep->opened = 1; return 0; -- cgit v1.2.3 From 590818250684d18bb0e30c45d79971dcdff96ad0 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 16 Apr 2009 02:23:56 +0000 Subject: myri10ge: force stats update in ethtool gstats Force a statistics update when our ethtool gstats routine is called. Otherwise, ethtool will continue to read stale stats until something forces an update by reading /proc/net/dev This requires putting a lock around the stats update to guard against 2 threads (one via ethtool, and one via procfs) updating the stats at once. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index f2c4a665e93f..a833cdd85466 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -361,6 +361,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) __raw_writel((__force __u32) val, (__force void __iomem *)p); } +static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); + static int myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, struct myri10ge_cmd *data, int atomic) @@ -1803,6 +1805,8 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, int slice; int i; + /* force stats update */ + (void)myri10ge_get_stats(netdev); for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) data[i] = ((unsigned long *)&mgp->stats)[i]; @@ -2969,6 +2973,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) struct net_device_stats *stats = &mgp->stats; int i; + spin_lock(&mgp->stats_lock); memset(stats, 0, sizeof(*stats)); for (i = 0; i < mgp->num_slices; i++) { slice_stats = &mgp->ss[i].stats; @@ -2979,6 +2984,7 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) stats->rx_dropped += slice_stats->rx_dropped; stats->tx_dropped += slice_stats->tx_dropped; } + spin_unlock(&mgp->stats_lock); return stats; } @@ -3902,6 +3908,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, (unsigned long)mgp); + spin_lock_init(&mgp->stats_lock); SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); status = register_netdev(netdev); -- cgit v1.2.3 From 2d90b0aa3bc484189940444bcddcbe0ebbb53af5 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 16 Apr 2009 02:24:59 +0000 Subject: myri10ge: allow per-board firmware overriding Add myri10ge_fw_names to override the default firmware on a per-board basis. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index a833cdd85466..77de964fe676 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -255,6 +255,7 @@ struct myri10ge_priv { u32 read_write_dma; u32 link_changes; u32 msg_enable; + unsigned int board_number; }; static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat"; @@ -266,6 +267,13 @@ static char *myri10ge_fw_name = NULL; module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); +#define MYRI10GE_MAX_BOARDS 8 +static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] = + {[0...(MYRI10GE_MAX_BOARDS - 1)] = NULL }; +module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL, + 0444); +MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board"); + static int myri10ge_ecrc_enable = 1; module_param(myri10ge_ecrc_enable, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E"); @@ -3259,6 +3267,8 @@ abort: static void myri10ge_select_firmware(struct myri10ge_priv *mgp) { + int overridden = 0; + if (myri10ge_force_firmware == 0) { int link_width, exp_cap; u16 lnk; @@ -3292,10 +3302,18 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) } } if (myri10ge_fw_name != NULL) { - dev_info(&mgp->pdev->dev, "overriding firmware to %s\n", - myri10ge_fw_name); + overridden = 1; mgp->fw_name = myri10ge_fw_name; } + if (mgp->board_number < MYRI10GE_MAX_BOARDS && + myri10ge_fw_names[mgp->board_number] != NULL && + strlen(myri10ge_fw_names[mgp->board_number])) { + mgp->fw_name = myri10ge_fw_names[mgp->board_number]; + overridden = 1; + } + if (overridden) + dev_info(&mgp->pdev->dev, "overriding firmware to %s\n", + mgp->fw_name); } #ifdef CONFIG_PM @@ -3760,6 +3778,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int status = -ENXIO; int dac_enabled; unsigned hdr_offset, ss_offset; + static int board_number; netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES); if (netdev == NULL) { @@ -3776,6 +3795,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp->pause = myri10ge_flow_control; mgp->intr_coal_delay = myri10ge_intr_coal_delay; mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT); + mgp->board_number = board_number; init_waitqueue_head(&mgp->down_wq); if (pci_enable_device(pdev)) { @@ -3926,6 +3946,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->irq, mgp->tx_boundary, mgp->fw_name, (mgp->wc_enabled ? "Enabled" : "Disabled")); + board_number++; return 0; abort_with_state: -- cgit v1.2.3 From 97131079183cd671e18e661f1a387cdb5dffd313 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 16 Apr 2009 02:29:22 +0000 Subject: myri10ge: add MODULE_DEVICE_TABLE Add MODULE_DEVICE_TABLE so that modinfo reports pci device id aliases. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 77de964fe676..4a2ab4ebfb82 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.4-1.401" +#define MYRI10GE_VERSION_STR "1.4.4-1.412" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -4036,6 +4036,8 @@ static struct pci_device_id myri10ge_pci_tbl[] = { {0}, }; +MODULE_DEVICE_TABLE(pci, myri10ge_pci_tbl); + static struct pci_driver myri10ge_driver = { .name = "myri10ge", .probe = myri10ge_probe, -- cgit v1.2.3 From 6498be3fba7b102132241be5763263e8e8bf6f9e Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 16 Apr 2009 17:56:57 -0700 Subject: myri10ge: fix tx ring size in ethtool -g Fix tx ring size reported via ethtool -g. Signed-off-by: Brice Goglin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 4a2ab4ebfb82..291944d0aea3 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1696,7 +1696,7 @@ myri10ge_get_ringparam(struct net_device *netdev, ring->rx_mini_max_pending = mgp->ss[0].rx_small.mask + 1; ring->rx_max_pending = mgp->ss[0].rx_big.mask + 1; ring->rx_jumbo_max_pending = 0; - ring->tx_max_pending = mgp->ss[0].rx_small.mask + 1; + ring->tx_max_pending = mgp->ss[0].tx.mask + 1; ring->rx_mini_pending = ring->rx_mini_max_pending; ring->rx_pending = ring->rx_max_pending; ring->rx_jumbo_pending = ring->rx_jumbo_max_pending; -- cgit v1.2.3 From f6a2629353718e588820b731af43a445b6f35648 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 16 Apr 2009 15:23:03 +0000 Subject: irda: include etherdevice.h for eth_*() functions Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/au1k_ir.c | 1 + drivers/net/irda/pxaficp_ir.c | 1 + drivers/net/irda/sa1100_ir.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 204def0f6451..269153eedd26 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index e8ced56b050f..3376a4f39e0a 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -14,6 +14,7 @@ */ #include #include +#include #include #include diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 44a748e72332..4ed763670a97 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From d32da050a340214c5dae0d014e39f75548cac2f2 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 16 Apr 2009 15:48:17 +0000 Subject: wan/pc300_drv: convert to net_device_ops On Fri, Apr 17, 2009 at 05:23:02AM +0400, Alexander Beregalov wrote: > > Signed-off-by: Alexander Beregalov > --- > drivers/net/wan/pc300_drv.c | 22 ++++++++++++++-------- > 1 files changed, 14 insertions(+), 8 deletions(-) > > diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c > index c23fde0..df10a4c 100644 > --- a/drivers/net/wan/pc300_drv.c > +++ b/drivers/net/wan/pc300_drv.c > @@ -225,6 +225,7 @@ static char rcsid[] = > #include > #include > #include > +#include > #include > #include > #include > @@ -3246,6 +3247,18 @@ static inline void show_version(void) > rcsvers, rcsdate, __DATE__, __TIME__); > } /* show_version */ > > +static const struct net_device_ops cpc_netdev_ops = { > + .ndo_init = NULL, > + .ndo_open = cpc_open, > + .ndo_stop = cpc_close, > + .ndo_tx_timeout = cpc_tx_timeout, > + .ndo_set_multicast_list = NULL, In this case ndo_init and ndo_set_multicast_list are not needed. >From 1507a5a797a5f0005696a9bf10e390caca9c3800 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Fri, 17 Apr 2009 05:45:48 +0400 Subject: [PATCH] wan/pc300_drv: convert to net_device_ops Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/wan/pc300_drv.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index c23fde0c0344..79dabc557bd3 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -225,6 +225,7 @@ static char rcsid[] = #include #include #include +#include #include #include #include @@ -3246,6 +3247,16 @@ static inline void show_version(void) rcsvers, rcsdate, __DATE__, __TIME__); } /* show_version */ +static const struct net_device_ops cpc_netdev_ops = { + .ndo_open = cpc_open, + .ndo_stop = cpc_close, + .ndo_tx_timeout = cpc_tx_timeout, + .ndo_set_mac_address = NULL, + .ndo_change_mtu = cpc_change_mtu, + .ndo_do_ioctl = cpc_ioctl, + .ndo_validate_addr = eth_validate_addr, +}; + static void cpc_init_card(pc300_t * card) { int i, devcount = 0; @@ -3357,18 +3368,11 @@ static void cpc_init_card(pc300_t * card) dev->mem_start = card->hw.ramphys; dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1; dev->irq = card->hw.irq; - dev->init = NULL; dev->tx_queue_len = PC300_TX_QUEUE_LEN; dev->mtu = PC300_DEF_MTU; - dev->open = cpc_open; - dev->stop = cpc_close; - dev->tx_timeout = cpc_tx_timeout; + dev->netdev_ops = &cpc_netdev_ops; dev->watchdog_timeo = PC300_TX_TIMEOUT; - dev->set_multicast_list = NULL; - dev->set_mac_address = NULL; - dev->change_mtu = cpc_change_mtu; - dev->do_ioctl = cpc_ioctl; if (register_hdlc_device(dev) == 0) { printk("%s: Cyclades-PC300/", dev->name); -- cgit v1.2.3 From 573636cbafeba88f7c88832ae053dafe265bf94b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Apr 2009 04:52:48 -0700 Subject: [PATCH] net: remove superfluous call to synchronize_net() inet_register_protosw() function is responsible for adding a new inet protocol into a global table (inetsw[]) that is used with RCU rules. As soon as the store of the pointer is done, other cpus might see this new protocol in inetsw[], so we have to make sure new protocol is ready for use. All pending memory updates should thus be committed to memory before setting the pointer. This is correctly done using rcu_assign_pointer() synchronize_net() is typically used at unregister time, after unsetting the pointer, to make sure no other cpu is still using the object we want to dismantle. Using it at register time is only adding an artificial delay that could hide a real bug, and this bug could popup if/when synchronize_rcu() can proceed faster than now. This saves about 13 ms on boot time on a HZ=1000 8 cpus machine ;) (4 calls to inet_register_protosw(), and about 3200 us per call) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 7f03373b8c07..170689681aa2 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1003,8 +1003,6 @@ void inet_register_protosw(struct inet_protosw *p) out: spin_unlock_bh(&inetsw_lock); - synchronize_net(); - return; out_permanent: -- cgit v1.2.3 From 7fe624f5607ed98de0034adf130e857474dffc2b Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Fri, 17 Apr 2009 15:45:15 -0700 Subject: myri10ge: fix compile error A compilation error snuck into 2d90b0aa3bc484189940444bcddcbe0ebbb53af5 due to an over-zealous indent script removing spaces around array initialization ellipsis. The attached patch fixes the myri10ge compilation in net-next. Signed-off-by: Andrew Gallatin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 291944d0aea3..140794a8d56a 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -269,7 +269,7 @@ MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); #define MYRI10GE_MAX_BOARDS 8 static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] = - {[0...(MYRI10GE_MAX_BOARDS - 1)] = NULL }; + {[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL }; module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL, 0444); MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board"); -- cgit v1.2.3 From 3ef8e4e9e4d18910cd03dcd481a5dced437b83cf Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Sun, 19 Apr 2009 18:42:58 -0700 Subject: iseries_veth: fix build breakage Reported-by: Stephen Rothwell Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/iseries_veth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 264654da85d1..e44215cb1882 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -1077,7 +1077,7 @@ static struct net_device *veth_probe_one(int vlan, memcpy(&port->mac_addr, mac_addr, ETH_ALEN); - dev->netdev = &veth_netdev_ops; + dev->netdev_ops = &veth_netdev_ops; SET_ETHTOOL_OPS(dev, &ops); SET_NETDEV_DEV(dev, vdev); -- cgit v1.2.3 From 5438646724c34c2180664a57f862a1da8dd21db1 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 17 Apr 2009 20:44:27 +0000 Subject: ixgbe: fix link down initial state As reported by Andrew Lutomirski All the intel wired ethernet drivers were calling netif_carrier_off and netif_stop_queue (or variants) before calling register_netdevice This is incorrect behavior as was pointed out by davem, and causes ifconfig and friends to report a strange state before first link after the driver was loaded, since without a netif_carrier_off, the stack assumes carrier_on, but before register_netdev, netlink messages are not sent out telling link state. This apparently confused *some* versions of networkmanager. Signed-off-by: Jesse Brandeburg Reported-by: Andrew Lutomirski Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 0d9a3ac043a6..d5d9589ae086 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3459,6 +3459,8 @@ static int ixgbe_open(struct net_device *netdev) if (test_bit(__IXGBE_TESTING, &adapter->state)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = ixgbe_setup_all_tx_resources(adapter); if (err) @@ -4772,13 +4774,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ hw->mac.ops.start_hw(hw); - netif_carrier_off(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + #ifdef CONFIG_IXGBE_DCA if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; -- cgit v1.2.3 From 3a6d1bc4163fee27c312184d5f1a9cc1e110d300 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 17 Apr 2009 20:44:29 +0000 Subject: ixgb: fix link down initial state As reported by Andrew Lutomirski All the intel wired ethernet drivers were calling netif_carrier_off and netif_stop_queue (or variants) before calling register_netdevice This is incorrect behavior as was pointed out by davem, and causes ifconfig and friends to report a strange state before first link after the driver was loaded, since without a netif_carrier_off, the stack assumes carrier_on, but before register_netdev, netlink messages are not sent out telling link state. This apparently confused *some* versions of networkmanager. in addition this driver appeared to need a netif_start_queue at the end of open. Signed-off-by: Jesse Brandeburg Reported-by: Andrew Lutomirski Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgb/ixgb_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 4a0826b8f6f2..ff741ca110f5 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -471,10 +471,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_register; - /* we're going to reset, so assume we have no link for now */ - + /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - netif_stop_queue(netdev); DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n"); ixgb_check_options(adapter); @@ -592,6 +590,8 @@ ixgb_open(struct net_device *netdev) if (err) goto err_setup_tx; + netif_carrier_off(netdev); + /* allocate receive descriptors */ err = ixgb_setup_rx_resources(adapter); @@ -602,6 +602,8 @@ ixgb_open(struct net_device *netdev) if (err) goto err_up; + netif_start_queue(netdev); + return 0; err_up: -- cgit v1.2.3 From b168dfc51604ec293db16dc4d558043585578a2d Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 17 Apr 2009 20:44:32 +0000 Subject: igb: fix link down inital state As reported by Andrew Lutomirski All the intel wired ethernet drivers were calling netif_carrier_off and netif_stop_queue (or variants) before calling register_netdevice This is incorrect behavior as was pointed out by davem, and causes ifconfig and friends to report a strange state before first link after the driver was loaded, since without a netif_carrier_off, the stack assumes carrier_on, but before register_netdev, netlink messages are not sent out telling link state. This apparently confused *some* versions of networkmanager. Signed-off-by: Jesse Brandeburg Reported-by: Andrew Lutomirski Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 08c801490c72..ceaa58554679 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1442,15 +1442,14 @@ static int __devinit igb_probe(struct pci_dev *pdev, * driver. */ igb_get_hw_control(adapter); - /* tell the stack to leave us alone until igb_open() is called */ - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + #ifdef CONFIG_IGB_DCA if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IGB_FLAG_DCA_ENABLED; @@ -1699,6 +1698,8 @@ static int igb_open(struct net_device *netdev) if (test_bit(__IGB_TESTING, &adapter->state)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = igb_setup_all_tx_resources(adapter); if (err) -- cgit v1.2.3 From 9c563d20671e5fbe3045fd79c18b306ccb77b0b6 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 17 Apr 2009 20:44:34 +0000 Subject: e1000e: indicate link down at load As reported by Andrew Lutomirski All the intel wired ethernet drivers were calling netif_carrier_off and netif_stop_queue (or variants) before calling register_netdevice This is incorrect behavior as was pointed out by davem, and causes ifconfig and friends to report a strange state before first link after the driver was loaded, since without a netif_carrier_off, the stack assumes carrier_on, but before register_netdev, netlink messages are not sent out telling link state. This apparently confused *some* versions of networkmanager. Andy tested this for e1000e and confirmed it was working for him. see thread: http://marc.info/?l=linux-netdev&m=123946479705636&w=2 Signed-off-by: Jesse Brandeburg Tested-by: Andy Lutomirski Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 1693ed116b16..c0ff550262ff 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3072,6 +3072,8 @@ static int e1000_open(struct net_device *netdev) if (test_bit(__E1000_TESTING, &adapter->state)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = e1000e_setup_tx_resources(adapter); if (err) @@ -5037,15 +5039,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (!(adapter->flags & FLAG_HAS_AMT)) e1000_get_hw_control(adapter); - /* tell the stack to leave us alone until e1000_open() is called */ - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + e1000_print_device_info(adapter); return 0; -- cgit v1.2.3 From eb62efd287fe6e12d18083287e38e4a811c28256 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 17 Apr 2009 20:44:36 +0000 Subject: e1000: init link state correctly As reported by Andrew Lutomirski All the intel wired ethernet drivers were calling netif_carrier_off and netif_stop_queue (or variants) before calling register_netdevice This is incorrect behavior as was pointed out by davem, and causes ifconfig and friends to report a strange state before first link after the driver was loaded. This apparently confused *some* versions of networkmanager. Andy tested this for e1000e and confirmed it was working for him. Signed-off-by: Jesse Brandeburg Reported-by: Andrew Lutomirski Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ef12931d302a..9bdcf4d2ab19 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1234,15 +1234,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev, !e1000_check_mng_mode(hw)) e1000_get_hw_control(adapter); - /* tell the stack to leave us alone until e1000_open() is called */ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); cards_found++; @@ -1441,6 +1440,8 @@ static int e1000_open(struct net_device *netdev) if (test_bit(__E1000_TESTING, &adapter->flags)) return -EBUSY; + netif_carrier_off(netdev); + /* allocate transmit descriptors */ err = e1000_setup_all_tx_resources(adapter); if (err) -- cgit v1.2.3 From 7eebb0b28f755e297d355a205bb04945b256db6b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 Apr 2009 22:03:10 +0000 Subject: loopback: packet drops accounting We can in some situations drop packets in netif_rx() loopback driver does not report these (unlikely) drops to its stats, and incorrectly change packets/bytes counts. After this patch applied, "ifconfig lo" can reports these drops as in : # ifconfig lo lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:692562900 errors:3228 dropped:3228 overruns:0 frame:0 TX packets:692562900 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2865674174 (2.6 GiB) TX bytes:2865674174 (2.6 GiB) I initialy chose to reflect those errors only in tx_dropped/tx_errors, but David convinced me that it was really RX errors, as loopback_xmit() really starts a RX process. (calling eth_type_trans() for example, that itself pulls the ethernet header) These errors are accounted in rx_dropped/rx_errors. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/loopback.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b7d438a367f3..6f71157bea8e 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -62,6 +62,7 @@ struct pcpu_lstats { unsigned long packets; unsigned long bytes; + unsigned long drops; }; /* @@ -71,18 +72,22 @@ struct pcpu_lstats { static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) { struct pcpu_lstats *pcpu_lstats, *lb_stats; + int len; skb_orphan(skb); - skb->protocol = eth_type_trans(skb,dev); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ pcpu_lstats = dev->ml_priv; lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id()); - lb_stats->bytes += skb->len; - lb_stats->packets++; - netif_rx(skb); + len = skb->len; + if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { + lb_stats->bytes += len; + lb_stats->packets++; + } else + lb_stats->drops++; return 0; } @@ -93,6 +98,7 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev) struct net_device_stats *stats = &dev->stats; unsigned long bytes = 0; unsigned long packets = 0; + unsigned long drops = 0; int i; pcpu_lstats = dev->ml_priv; @@ -102,11 +108,14 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev) lb_stats = per_cpu_ptr(pcpu_lstats, i); bytes += lb_stats->bytes; packets += lb_stats->packets; + drops += lb_stats->drops; } stats->rx_packets = packets; stats->tx_packets = packets; - stats->rx_bytes = bytes; - stats->tx_bytes = bytes; + stats->rx_dropped = drops; + stats->rx_errors = drops; + stats->rx_bytes = bytes; + stats->tx_bytes = bytes; return stats; } -- cgit v1.2.3 From a0f82f64e26929776c58a5c93c2ecb38e3d82815 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 19 Apr 2009 09:43:48 +0000 Subject: syncookies: remove last_synq_overflow from struct tcp_sock last_synq_overflow eats 4 or 8 bytes in struct tcp_sock, even though it is only used when a listening sockets syn queue is full. We can (ab)use rx_opt.ts_recent_stamp to store the same information; it is not used otherwise as long as a socket is in listen state. Move linger2 around to avoid splitting struct mtu_probe across cacheline boundary on 32 bit arches. Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- include/linux/tcp.h | 4 +--- include/net/tcp.h | 13 +++++++++++++ net/ipv4/syncookies.c | 5 ++--- net/ipv6/syncookies.c | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 9d5078bd23a3..8afac76cd748 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -377,7 +377,7 @@ struct tcp_sock { unsigned int keepalive_time; /* time before keep alive takes place */ unsigned int keepalive_intvl; /* time interval between keep alive probes */ - unsigned long last_synq_overflow; + int linger2; /* Receiver side RTT estimation */ struct { @@ -406,8 +406,6 @@ struct tcp_sock { /* TCP MD5 Signagure Option information */ struct tcp_md5sig_info *md5sig_info; #endif - - int linger2; }; static inline struct tcp_sock *tcp_sk(const struct sock *sk) diff --git a/include/net/tcp.h b/include/net/tcp.h index 1b94b9bfe2dc..b55b4891029e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -265,6 +265,19 @@ static inline int tcp_too_many_orphans(struct sock *sk, int num) atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]); } +/* syncookies: remember time of last synqueue overflow */ +static inline void tcp_synq_overflow(struct sock *sk) +{ + tcp_sk(sk)->rx_opt.ts_recent_stamp = jiffies; +} + +/* syncookies: no recent synqueue overflow on this listening socket? */ +static inline int tcp_synq_no_recent_overflow(const struct sock *sk) +{ + unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; + return time_after(jiffies, last_overflow + TCP_TIMEOUT_INIT); +} + extern struct proto tcp_prot; #define TCP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field) diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index b35a950d2e06..cd2b97f1b6e1 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -161,13 +161,12 @@ static __u16 const msstab[] = { */ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) { - struct tcp_sock *tp = tcp_sk(sk); const struct iphdr *iph = ip_hdr(skb); const struct tcphdr *th = tcp_hdr(skb); int mssind; const __u16 mss = *mssp; - tp->last_synq_overflow = jiffies; + tcp_synq_overflow(sk); /* XXX sort msstab[] by probability? Binary search? */ for (mssind = 0; mss > msstab[mssind + 1]; mssind++) @@ -268,7 +267,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, if (!sysctl_tcp_syncookies || !th->ack) goto out; - if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || + if (tcp_synq_no_recent_overflow(sk) || (mss = cookie_check(skb, cookie)) == 0) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); goto out; diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 711175e0571f..8c2513982b61 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -131,7 +131,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) int mssind; const __u16 mss = *mssp; - tcp_sk(sk)->last_synq_overflow = jiffies; + tcp_synq_overflow(sk); for (mssind = 0; mss > msstab[mssind + 1]; mssind++) ; @@ -175,7 +175,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) if (!sysctl_tcp_syncookies || !th->ack) goto out; - if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || + if (tcp_synq_no_recent_overflow(sk) || (mss = cookie_check(skb, cookie)) == 0) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); goto out; -- cgit v1.2.3 From 624f8e5082efd0348ccf7e3d3f4bfc41efead26c Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 06:55:01 +0000 Subject: tg3: Allow screaming interrupt detection The tg3 driver's ISR is coded to accept interrupts as its own if the status block tag does not equal the last tag the driver has seen. The last_tag field is updated from tg3_poll. In a screaming interrupt situation from another device sharing tg3's IRQ, tg3_poll does not get a chance to be called, so the last_tag will always be out of sync with the status block tag. Consequently, the driver will continually declare the screaming interrupts as its own, thus thwarting the screaming interrupt detection logic. This patch solves the problem by creating a new last_irq_tag member and recording the status block tag in the ISR. The ISR then checks the last_irq_tag for interrupt ownership. Many thanks to John Marvin for the detailed bug report and analysis and Michael Chan for the bugfix. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Tested-by: John Marvin Signed-off-by: David S. Miller --- drivers/net/tg3.c | 29 +++++++++++++++++------------ drivers/net/tg3.h | 1 + 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 201be425643a..e4fa02c79278 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4656,6 +4656,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) * so we must read it before checking for more work. */ tp->last_tag = sblk->status_tag; + tp->last_irq_tag = tp->last_tag; rmb(); } else sblk->status &= ~SD_STATUS_UPDATED; @@ -4811,7 +4812,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if (unlikely(sblk->status_tag == tp->last_tag)) { + if (unlikely(sblk->status_tag == tp->last_irq_tag)) { if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) || (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { handled = 0; @@ -4831,18 +4832,22 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id) * excessive spurious interrupts can be worse in some cases. */ tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); + + /* + * In a shared interrupt configuration, sometimes other devices' + * interrupts will scream. We record the current status tag here + * so that the above check can report that the screaming interrupts + * are unhandled. Eventually they will be silenced. + */ + tp->last_irq_tag = sblk->status_tag; + if (tg3_irq_sync(tp)) goto out; - if (napi_schedule_prep(&tp->napi)) { - prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); - /* Update last_tag to mark that this status has been - * seen. Because interrupt may be shared, we may be - * racing with tg3_poll(), so only update last_tag - * if tg3_poll() is not scheduled. - */ - tp->last_tag = sblk->status_tag; - __napi_schedule(&tp->napi); - } + + prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]); + + napi_schedule(&tp->napi); + out: return IRQ_RETVAL(handled); } @@ -6156,6 +6161,7 @@ static int tg3_chip_reset(struct tg3 *tp) tp->hw_status->status_tag = 0; } tp->last_tag = 0; + tp->last_irq_tag = 0; smp_mb(); synchronize_irq(tp->pdev->irq); @@ -7138,7 +7144,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(100); tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); - tp->last_tag = 0; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index cb4c62abdd21..ca71a49a3fd5 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2501,6 +2501,7 @@ struct tg3 { struct tg3_hw_status *hw_status; dma_addr_t status_mapping; u32 last_tag; + u32 last_irq_tag; u32 msg_enable; -- cgit v1.2.3 From df259d8cba7d7880dc04d34c7a6e0ce15fbc9644 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 06:57:14 +0000 Subject: tg3: Handle NVRAM absent cases Some 57780 ASIC revision parts do not have NVRAM. Code the driver so that it is tolerant of this configuration. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 36 ++++++++++++++++++++++++++++++++---- drivers/net/tg3.h | 1 + 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e4fa02c79278..9b04954b6943 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8544,6 +8544,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u32 i, offset, len, b_offset, b_count; __be32 val; + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + return -EINVAL; + if (tp->link_config.phy_is_low_power) return -EAGAIN; @@ -8609,7 +8612,8 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if (tp->link_config.phy_is_low_power) return -EAGAIN; - if (eeprom->magic != TG3_EEPROM_MAGIC) + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + eeprom->magic != TG3_EEPROM_MAGIC) return -EINVAL; offset = eeprom->offset; @@ -9206,6 +9210,9 @@ static int tg3_test_nvram(struct tg3 *tp) __be32 *buf; int i, j, k, err = 0, size; + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + return 0; + if (tg3_nvram_read(tp, 0, &magic) != 0) return -EIO; @@ -10188,7 +10195,8 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) { u32 val; - if (tg3_nvram_read(tp, 0, &val) != 0) + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + tg3_nvram_read(tp, 0, &val) != 0) return; /* Selfboot format */ @@ -10570,6 +10578,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) } break; default: + tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM; return; } @@ -11370,7 +11379,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp) unsigned int i; u32 magic; - if (tg3_nvram_read(tp, 0x0, &magic)) + if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || + tg3_nvram_read(tp, 0x0, &magic)) goto out_not_found; if (magic == TG3_EEPROM_MAGIC) { @@ -11462,6 +11472,15 @@ static void __devinit tg3_read_partno(struct tg3 *tp) out_not_found: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) strcpy(tp->board_part_number, "BCM95906"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780) + strcpy(tp->board_part_number, "BCM57780"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760) + strcpy(tp->board_part_number, "BCM57760"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790) + strcpy(tp->board_part_number, "BCM57790"); else strcpy(tp->board_part_number, "none"); } @@ -11672,6 +11691,14 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) { u32 val; + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) { + tp->fw_ver[0] = 's'; + tp->fw_ver[1] = 'b'; + tp->fw_ver[2] = '\0'; + + return; + } + if (tg3_nvram_read(tp, 0, &val)) return; @@ -12459,7 +12486,8 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) } if (!addr_ok) { /* Next, try NVRAM. */ - if (!tg3_nvram_read_be32(tp, mac_offset + 0, &hi) && + if (!(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) && + !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) && !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) { memcpy(&dev->dev_addr[0], ((char *)&hi) + 2, 2); memcpy(&dev->dev_addr[2], (char *)&lo, sizeof(lo)); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ca71a49a3fd5..afbabf283c51 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2636,6 +2636,7 @@ struct tg3 { #define TG3_FLG3_CLKREQ_BUG 0x00000800 #define TG3_FLG3_PHY_ENABLE_APD 0x00001000 #define TG3_FLG3_5755_PLUS 0x00002000 +#define TG3_FLG3_NO_NVRAM 0x00004000 struct timer_list timer; u16 timer_counter; -- cgit v1.2.3 From 33466d938f43ab65312466ba5472b9c6ee200cce Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 06:57:41 +0000 Subject: tg3: Prevent send BD corruption On rare occasions, send BD corruptions can occur. This patch fixes the problem by increasing the L1 entry threshold to 4 milliseconds. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 7 +++++++ drivers/net/tg3.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 9b04954b6943..ed7a86df98cd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6717,6 +6717,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_CPMU_HST_ACC, val); } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) { + val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK; + val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN | + PCIE_PWR_MGMT_L1_THRESH_4MS; + tw32(PCIE_PWR_MGMT_THRESH, val); + } + /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. But do not set this on PCI Express diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index afbabf283c51..f1016cb1a89a 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1697,6 +1697,8 @@ #define PCIE_PWR_MGMT_THRESH 0x00007d28 #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 +#define PCIE_PWR_MGMT_L1_THRESH_4MS 0x0000ff00 +#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN 0x01000000 /* OTP bit definitions */ -- cgit v1.2.3 From 8d519ab2866c92f5d722085492a124f016f601aa Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 06:58:01 +0000 Subject: tg3: Allow 5761 WOL and LED fixes to 5761S too The 5761 WOL and LED fixes used the PCI device ID to as the activation key. The 5761S requires the same process. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ed7a86df98cd..c5c3d2853144 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1950,7 +1950,8 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); - } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) { /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */ u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | @@ -12183,7 +12184,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; - if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) { /* Turn off the debug UART. */ tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) -- cgit v1.2.3 From 9cf74ebb634fe79587cf9a1d5ff971391dd12e1b Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 06:58:27 +0000 Subject: tg3: Limit CLKREQ fix to A[01] of 57780 asic rev This patch restricts the CLKREQ bugfix to the A0 and A1 revisions of 57780 ASIC rev chips. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 ++- drivers/net/tg3.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c5c3d2853144..0501fb48a004 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -11992,7 +11992,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_57780_A1) tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG; } } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index f1016cb1a89a..b3347c41a1a3 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -95,6 +95,8 @@ #define CHIPREV_ID_5752_A1 0x6001 #define CHIPREV_ID_5714_A2 0x9002 #define CHIPREV_ID_5906_A1 0xc001 +#define CHIPREV_ID_57780_A0 0x57780000 +#define CHIPREV_ID_57780_A1 0x57780001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 -- cgit v1.2.3 From daba2a631d2b7831b6a021b36d61314a9153526e Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 06:58:52 +0000 Subject: tg3: Restore LAA sooner in shutdown sequence After a shutdown reset, the LAA needs to be restored before posting the post-reset signature in shared memory. If the LAA is not restored before then, the bootcode will assume the factory default MAC address and WOL will not work with the LAA. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0501fb48a004..f2b7ff80df98 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2456,8 +2456,6 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } - __tg3_set_mac_addr(tp, 0); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u32 val; @@ -6357,6 +6355,8 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) tg3_abort_hw(tp, silent); err = tg3_chip_reset(tp); + __tg3_set_mac_addr(tp, 0); + tg3_write_sig_legacy(tp, kind); tg3_write_sig_post_reset(tp, kind); -- cgit v1.2.3 From bb9e63e27117b469a151c61fb0045a8ec4cced5d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 20 Apr 2009 07:13:31 +0000 Subject: tg3: Update version to 3.99 This patch updates the tg3 version to 3.99. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f2b7ff80df98..eb65e25989f3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.98" -#define DRV_MODULE_RELDATE "February 25, 2009" +#define DRV_MODULE_VERSION "3.99" +#define DRV_MODULE_RELDATE "April 20, 2009" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3 From 03ad032bb78b2732b607ed198e951240e1d21e59 Mon Sep 17 00:00:00 2001 From: Peter Holik Date: Sat, 18 Apr 2009 07:24:17 +0000 Subject: export usbnet_get_ethernet_addr from usbnet and fixed cdc_ether.c because of using the same function get_ethernet_addr as cdc_ether.c i export usbnet_get_ethernet_addr from usbnet and fixed cdc_ether (suggested by Oliver Neukum). Signed-off-by: Peter Holik Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 33 +-------------------------------- drivers/net/usb/usbnet.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb/usbnet.h | 1 + 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 55e8ecc3a9e5..01fd528306ec 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -389,36 +388,6 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) } } -static u8 nibble(unsigned char c) -{ - if (likely(isdigit(c))) - return c - '0'; - c = toupper(c); - if (likely(isxdigit(c))) - return 10 + c - 'A'; - return 0; -} - -static inline int -get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e) -{ - int tmp, i; - unsigned char buf [13]; - - tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf); - if (tmp != 12) { - dev_dbg(&dev->udev->dev, - "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp); - if (tmp >= 0) - tmp = -EINVAL; - return tmp; - } - for (i = tmp = 0; i < 6; i++, tmp += 2) - dev->net->dev_addr [i] = - (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); - return 0; -} - static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) { int status; @@ -428,7 +397,7 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) if (status < 0) return status; - status = get_ethernet_addr(dev, info->ether); + status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress); if (status < 0) { usb_set_intfdata(info->data, NULL); usb_driver_release_interface(driver_of(intf), info->data); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 2b8b9036aff6..c94de6243140 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,36 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_get_endpoints); +static u8 nibble(unsigned char c) +{ + if (likely(isdigit(c))) + return c - '0'; + c = toupper(c); + if (likely(isxdigit(c))) + return 10 + c - 'A'; + return 0; +} + +int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress) +{ + int tmp, i; + unsigned char buf [13]; + + tmp = usb_string(dev->udev, iMACAddress, buf, sizeof buf); + if (tmp != 12) { + dev_dbg(&dev->udev->dev, + "bad MAC string %d fetch, %d\n", iMACAddress, tmp); + if (tmp >= 0) + tmp = -EINVAL; + return tmp; + } + for (i = tmp = 0; i < 6; i++, tmp += 2) + dev->net->dev_addr [i] = + (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); + return 0; +} +EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr); + static void intr_complete (struct urb *urb); static int init_status (struct usbnet *dev, struct usb_interface *intf) diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 36fabb95c7d3..5d44059f6d63 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -183,6 +183,7 @@ extern void usbnet_tx_timeout (struct net_device *net); extern int usbnet_change_mtu (struct net_device *net, int new_mtu); extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *); +extern int usbnet_get_ethernet_addr(struct usbnet *, int); extern void usbnet_defer_kevent (struct usbnet *, int); extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); extern void usbnet_unlink_rx_urbs(struct usbnet *); -- cgit v1.2.3 From 4510d7cb8b4e7d389652b8a4f89fad469a5ecc92 Mon Sep 17 00:00:00 2001 From: Peter Holik Date: Sat, 18 Apr 2009 07:24:21 +0000 Subject: usb driver for intellon int51x1 based PLC like devolo dlan duo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usb driver for intellon int51x1 based PLC like devolo dlan duo with improvements suggested by the guys of the mailinglist: - name and prefix with int51x1 (Florian Fainelli) - use conversion functions cpu_to_le16 / le16_to_cpu (Oliver Neukum) - use pskb_may_pull instead of skb->len (Ilpo Järvinen) - better code in tx_fixup (Ilpo Järvinen) - use gotos for error handling (Ilpo Järvinen) - better description (Jon Smirl) Signed-off-by: Peter Holik Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 8 ++ drivers/net/usb/Makefile | 1 + drivers/net/usb/int51x1.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 drivers/net/usb/int51x1.c diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 8ee21030e9ac..e00b5b1f6743 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -345,4 +345,12 @@ config USB_HSO To compile this driver as a module, choose M here: the module will be called hso. +config USB_NET_INT51X1 + tristate "Intellon PLC based usb adapter" + depends on USB_USBNET + help + Choose this option if you're using a 14Mb USB-based PLC + (Powerline Communications) solution with an Intellon + INT51x1/INT5200 chip, like the "devolo dLan duo". + endmenu diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 88a87eeb376a..f4402a06e52c 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -19,4 +19,5 @@ obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o +obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c new file mode 100644 index 000000000000..55cf7081de10 --- /dev/null +++ b/drivers/net/usb/int51x1.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2009 Peter Holik + * + * Intellon usb PLC (Powerline Communications) usb net driver + * + * http://www.tandel.be/downloads/INT51X1_Datasheet.pdf + * + * Based on the work of Jan 'RedBully' Seiffert + */ + +/* + * 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; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define INT51X1_VENDOR_ID 0x09e1 +#define INT51X1_PRODUCT_ID 0x5121 + +#define INT51X1_HEADER_SIZE 2 /* 2 byte header */ + +#define PACKET_TYPE_PROMISCUOUS (1 << 0) +#define PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ +#define PACKET_TYPE_DIRECTED (1 << 2) +#define PACKET_TYPE_BROADCAST (1 << 3) +#define PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ + +#define SET_ETHERNET_PACKET_FILTER 0x43 + +static int int51x1_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + int len; + + if (!(pskb_may_pull(skb, INT51X1_HEADER_SIZE))) { + deverr(dev, "unexpected tiny rx frame"); + return 0; + } + + len = le16_to_cpu(*(__le16 *)&skb->data[skb->len - 2]); + + skb_trim(skb, len); + + return 1; +} + +static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev, + struct sk_buff *skb, gfp_t flags) +{ + int pack_len = skb->len; + int pack_with_header_len = pack_len + INT51X1_HEADER_SIZE; + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + int need_tail = 0; + __le16 *len; + + /* if packet and our header is smaler than 64 pad to 64 (+ ZLP) */ + if ((pack_with_header_len) < dev->maxpacket) + need_tail = dev->maxpacket - pack_with_header_len + 1; + /* + * usbnet would send a ZLP if packetlength mod urbsize == 0 for us, + * but we need to know ourself, because this would add to the length + * we send down to the device... + */ + else if (!(pack_with_header_len % dev->maxpacket)) + need_tail = 1; + + if (!skb_cloned(skb) && + (headroom + tailroom >= need_tail + INT51X1_HEADER_SIZE)) { + if (headroom < INT51X1_HEADER_SIZE || tailroom < need_tail) { + skb->data = memmove(skb->head + INT51X1_HEADER_SIZE, + skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + } + } else { + struct sk_buff *skb2; + + skb2 = skb_copy_expand(skb, + INT51X1_HEADER_SIZE, + need_tail, + flags); + dev_kfree_skb_any(skb); + if (!skb2) + return NULL; + skb = skb2; + } + + pack_len += need_tail; + pack_len &= 0x07ff; + + len = (__le16 *) __skb_push(skb, INT51X1_HEADER_SIZE); + *len = cpu_to_le16(pack_len); + + if(need_tail) + memset(__skb_put(skb, need_tail), 0, need_tail); + + return skb; +} + +static void int51x1_async_cmd_callback(struct urb *urb) +{ + struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; + int status = urb->status; + + if (status < 0) + dev_warn(&urb->dev->dev, "async callback failed with %d\n", status); + + kfree(req); + usb_free_urb(urb); +} + +static void int51x1_set_multicast(struct net_device *netdev) +{ + struct usb_ctrlrequest *req; + int status; + struct urb *urb; + struct usbnet *dev = netdev_priv(netdev); + u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST; + + if (netdev->flags & IFF_PROMISC) { + /* do not expect to see traffic of other PLCs */ + filter |= PACKET_TYPE_PROMISCUOUS; + devinfo(dev, "promiscuous mode enabled"); + } else if (netdev->mc_count || + (netdev->flags & IFF_ALLMULTI)) { + filter |= PACKET_TYPE_ALL_MULTICAST; + devdbg(dev, "receive all multicast enabled"); + } else { + /* ~PROMISCUOUS, ~MULTICAST */ + devdbg(dev, "receive own packets only"); + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + devwarn(dev, "Error allocating URB"); + return; + } + + req = kmalloc(sizeof(*req), GFP_ATOMIC); + if (!req) { + devwarn(dev, "Error allocating control msg"); + goto out; + } + + req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + req->bRequest = SET_ETHERNET_PACKET_FILTER; + req->wValue = cpu_to_le16(filter); + req->wIndex = 0; + req->wLength = 0; + + usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), + (void *)req, NULL, 0, + int51x1_async_cmd_callback, + (void *)req); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + devwarn(dev, "Error submitting control msg, sts=%d", status); + goto out1; + } + return; +out1: + kfree(req); +out: + usb_free_urb(urb); +} + +static const struct net_device_ops int51x1_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = int51x1_set_multicast, +}; + +static int int51x1_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status = usbnet_get_ethernet_addr(dev, 3); + + if (status) + return status; + + dev->net->hard_header_len += INT51X1_HEADER_SIZE; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + dev->net->netdev_ops = &int51x1_netdev_ops; + + return usbnet_get_endpoints(dev, intf); +} + +static const struct driver_info int51x1_info = { + .description = "Intellon usb powerline adapter", + .bind = int51x1_bind, + .rx_fixup = int51x1_rx_fixup, + .tx_fixup = int51x1_tx_fixup, + .in = 1, + .out = 2, + .flags = FLAG_ETHER, +}; + +static const struct usb_device_id products[] = { + { + USB_DEVICE(INT51X1_VENDOR_ID, INT51X1_PRODUCT_ID), + .driver_info = (unsigned long) &int51x1_info, + }, + {}, +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver int51x1_driver = { + .name = "int51x1", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + +static int __init int51x1_init(void) +{ + return usb_register(&int51x1_driver); +} +module_init(int51x1_init); + +static void __exit int51x1_exit(void) +{ + usb_deregister(&int51x1_driver); +} +module_exit(int51x1_exit); + +MODULE_AUTHOR("Peter Holik"); +MODULE_DESCRIPTION("Intellon usb powerline adapter"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b1b67dd45a6b629eb41553856805aaa1614fbb83 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 20 Apr 2009 04:49:28 +0000 Subject: net: factor out ethtool invocation of vlan/macvlan drivers Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 22 +++------------------- include/linux/netdevice.h | 24 +++++++++++++++++++++++- net/8021q/vlan_dev.c | 23 +++-------------------- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 214a8cf2b708..329cd50d0e29 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -374,36 +374,20 @@ static void macvlan_ethtool_get_drvinfo(struct net_device *dev, static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) { const struct macvlan_dev *vlan = netdev_priv(dev); - struct net_device *lowerdev = vlan->lowerdev; - - if (lowerdev->ethtool_ops == NULL || - lowerdev->ethtool_ops->get_rx_csum == NULL) - return 0; - return lowerdev->ethtool_ops->get_rx_csum(lowerdev); + return dev_ethtool_get_rx_csum(vlan->lowerdev); } static int macvlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { const struct macvlan_dev *vlan = netdev_priv(dev); - struct net_device *lowerdev = vlan->lowerdev; - - if (!lowerdev->ethtool_ops || - !lowerdev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - - return lowerdev->ethtool_ops->get_settings(lowerdev, cmd); + return dev_ethtool_get_settings(vlan->lowerdev, cmd); } static u32 macvlan_ethtool_get_flags(struct net_device *dev) { const struct macvlan_dev *vlan = netdev_priv(dev); - struct net_device *lowerdev = vlan->lowerdev; - - if (!lowerdev->ethtool_ops || - !lowerdev->ethtool_ops->get_flags) - return 0; - return lowerdev->ethtool_ops->get_flags(lowerdev); + return dev_ethtool_get_flags(vlan->lowerdev); } static const struct ethtool_ops macvlan_ethtool_ops = { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 54db3ebf2193..31167451d08d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -42,6 +42,7 @@ #include #include +#include #include #include #ifdef CONFIG_DCB @@ -49,7 +50,6 @@ #endif struct vlan_group; -struct ethtool_ops; struct netpoll_info; /* 802.11 specific */ struct wireless_dev; @@ -1906,6 +1906,28 @@ static inline int skb_bond_should_drop(struct sk_buff *skb) } extern struct pernet_operations __net_initdata loopback_net_ops; + +static inline int dev_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) + return -EOPNOTSUPP; + return dev->ethtool_ops->get_settings(dev, cmd); +} + +static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_rx_csum) + return 0; + return dev->ethtool_ops->get_rx_csum(dev); +} + +static inline u32 dev_ethtool_get_flags(struct net_device *dev) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_flags) + return 0; + return dev->ethtool_ops->get_flags(dev); +} #endif /* __KERNEL__ */ #endif /* _LINUX_DEV_H */ diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6b0921364014..04dc8c8a6854 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -666,13 +666,7 @@ static int vlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - struct net_device *real_dev = vlan->real_dev; - - if (!real_dev->ethtool_ops || - !real_dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - - return real_dev->ethtool_ops->get_settings(real_dev, cmd); + return dev_ethtool_get_settings(vlan->real_dev, cmd); } static void vlan_ethtool_get_drvinfo(struct net_device *dev, @@ -686,24 +680,13 @@ static void vlan_ethtool_get_drvinfo(struct net_device *dev, static u32 vlan_ethtool_get_rx_csum(struct net_device *dev) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - struct net_device *real_dev = vlan->real_dev; - - if (real_dev->ethtool_ops == NULL || - real_dev->ethtool_ops->get_rx_csum == NULL) - return 0; - return real_dev->ethtool_ops->get_rx_csum(real_dev); + return dev_ethtool_get_rx_csum(vlan->real_dev); } static u32 vlan_ethtool_get_flags(struct net_device *dev) { const struct vlan_dev_info *vlan = vlan_dev_info(dev); - struct net_device *real_dev = vlan->real_dev; - - if (!(real_dev->features & NETIF_F_HW_VLAN_RX) || - real_dev->ethtool_ops == NULL || - real_dev->ethtool_ops->get_flags == NULL) - return 0; - return real_dev->ethtool_ops->get_flags(real_dev); + return dev_ethtool_get_flags(vlan->real_dev); } static const struct ethtool_ops vlan_ethtool_ops = { -- cgit v1.2.3 From d035fbccc4edd2bd69d9314faf03ba832b85a1d7 Mon Sep 17 00:00:00 2001 From: Jianjun Kong Date: Mon, 20 Apr 2009 04:05:34 +0000 Subject: rtl8139: unify the struct's name unify the struct's name of "struct rtl8139_private *np" to "struct rtl8139_private *tp" most of them like this: struct rtl8139_private *tp = netdev_priv(dev); Signed-off-by: Amos Kong Signed-off-by: David S. Miller --- drivers/net/8139too.c | 92 +++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 29df398b7727..00fe1301a9c4 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -2292,11 +2292,11 @@ static int rtl8139_close (struct net_device *dev) other threads or interrupts aren't messing with the 8139. */ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; + struct rtl8139_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; - spin_lock_irq(&np->lock); - if (rtl_chip_info[np->chipset].flags & HasLWake) { + spin_lock_irq(&tp->lock); + if (rtl_chip_info[tp->chipset].flags & HasLWake) { u8 cfg3 = RTL_R8 (Config3); u8 cfg5 = RTL_R8 (Config5); @@ -2317,7 +2317,7 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (cfg5 & Cfg5_BWF) wol->wolopts |= WAKE_BCAST; } - spin_unlock_irq(&np->lock); + spin_unlock_irq(&tp->lock); } @@ -2326,19 +2326,19 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) aren't messing with the 8139. */ static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct rtl8139_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->mmio_addr; + struct rtl8139_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; u32 support; u8 cfg3, cfg5; - support = ((rtl_chip_info[np->chipset].flags & HasLWake) + support = ((rtl_chip_info[tp->chipset].flags & HasLWake) ? (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST) : 0); if (wol->wolopts & ~support) return -EINVAL; - spin_lock_irq(&np->lock); + spin_lock_irq(&tp->lock); cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic); if (wol->wolopts & WAKE_PHY) cfg3 |= Cfg3_LinkUp; @@ -2359,87 +2359,87 @@ static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & WAKE_BCAST) cfg5 |= Cfg5_BWF; RTL_W8 (Config5, cfg5); /* need not unlock via Cfg9346 */ - spin_unlock_irq(&np->lock); + spin_unlock_irq(&tp->lock); return 0; } static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pci_dev)); - info->regdump_len = np->regs_len; + strcpy(info->bus_info, pci_name(tp->pci_dev)); + info->regdump_len = tp->regs_len; } static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct rtl8139_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii, cmd); - spin_unlock_irq(&np->lock); + struct rtl8139_private *tp = netdev_priv(dev); + spin_lock_irq(&tp->lock); + mii_ethtool_gset(&tp->mii, cmd); + spin_unlock_irq(&tp->lock); return 0; } static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); int rc; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii, cmd); - spin_unlock_irq(&np->lock); + spin_lock_irq(&tp->lock); + rc = mii_ethtool_sset(&tp->mii, cmd); + spin_unlock_irq(&tp->lock); return rc; } static int rtl8139_nway_reset(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii); + struct rtl8139_private *tp = netdev_priv(dev); + return mii_nway_restart(&tp->mii); } static u32 rtl8139_get_link(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii); + struct rtl8139_private *tp = netdev_priv(dev); + return mii_link_ok(&tp->mii); } static u32 rtl8139_get_msglevel(struct net_device *dev) { - struct rtl8139_private *np = netdev_priv(dev); - return np->msg_enable; + struct rtl8139_private *tp = netdev_priv(dev); + return tp->msg_enable; } static void rtl8139_set_msglevel(struct net_device *dev, u32 datum) { - struct rtl8139_private *np = netdev_priv(dev); - np->msg_enable = datum; + struct rtl8139_private *tp = netdev_priv(dev); + tp->msg_enable = datum; } static int rtl8139_get_regs_len(struct net_device *dev) { - struct rtl8139_private *np; + struct rtl8139_private *tp; /* TODO: we are too slack to do reg dumping for pio, for now */ if (use_io) return 0; - np = netdev_priv(dev); - return np->regs_len; + tp = netdev_priv(dev); + return tp->regs_len; } static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { - struct rtl8139_private *np; + struct rtl8139_private *tp; /* TODO: we are too slack to do reg dumping for pio, for now */ if (use_io) return; - np = netdev_priv(dev); + tp = netdev_priv(dev); regs->version = RTL_REGS_VER; - spin_lock_irq(&np->lock); - memcpy_fromio(regbuf, np->mmio_addr, regs->len); - spin_unlock_irq(&np->lock); + spin_lock_irq(&tp->lock); + memcpy_fromio(regbuf, tp->mmio_addr, regs->len); + spin_unlock_irq(&tp->lock); } static int rtl8139_get_sset_count(struct net_device *dev, int sset) @@ -2454,12 +2454,12 @@ static int rtl8139_get_sset_count(struct net_device *dev, int sset) static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); - data[0] = np->xstats.early_rx; - data[1] = np->xstats.tx_buf_mapped; - data[2] = np->xstats.tx_timeouts; - data[3] = np->xstats.rx_lost_in_ring; + data[0] = tp->xstats.early_rx; + data[1] = tp->xstats.tx_buf_mapped; + data[2] = tp->xstats.tx_timeouts; + data[3] = tp->xstats.rx_lost_in_ring; } static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -2486,15 +2486,15 @@ static const struct ethtool_ops rtl8139_ethtool_ops = { static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct rtl8139_private *np = netdev_priv(dev); + struct rtl8139_private *tp = netdev_priv(dev); int rc; if (!netif_running(dev)) return -EINVAL; - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); + spin_lock_irq(&tp->lock); + rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL); + spin_unlock_irq(&tp->lock); return rc; } -- cgit v1.2.3 From 0cededf3ffbb775c3716aa1d246338fdc24b1259 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 17 Apr 2009 12:03:48 +0000 Subject: ucc_geth: Move freeing of TX packets to NAPI context This will make the system alot more responsive while ping flooding the ucc_geth ethernet interface. Also set NAPI weight to 64 as this is a common value. Signed-off-by: Joakim Tjernlund Signed-off-by: Anton Vorontsov Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 31 +++++++++++-------------------- drivers/net/ucc_geth.h | 1 - 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index d3f39e86eb95..98f961e92ca9 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3216,7 +3216,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) dev->stats.tx_packets++; /* Free the sk buffer associated with this TxBD */ - dev_kfree_skb_irq(ugeth-> + dev_kfree_skb(ugeth-> tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]); ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; ugeth->skb_dirtytx[txQ] = @@ -3250,9 +3250,15 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget) for (i = 0; i < ug_info->numQueuesRx; i++) howmany += ucc_geth_rx(ugeth, i, budget - howmany); + /* Tx event processing */ + spin_lock(&ugeth->lock); + for (i = 0; i < ug_info->numQueuesTx; i++) + ucc_geth_tx(ugeth->ndev, i); + spin_unlock(&ugeth->lock); + if (howmany < budget) { napi_complete(napi); - setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS); + setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS); } return howmany; @@ -3266,8 +3272,6 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) struct ucc_geth_info *ug_info; register u32 ucce; register u32 uccm; - register u32 tx_mask; - u8 i; ugeth_vdbg("%s: IN", __func__); @@ -3281,27 +3285,14 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) out_be32(uccf->p_ucce, ucce); /* check for receive events that require processing */ - if (ucce & UCCE_RX_EVENTS) { + if (ucce & (UCCE_RX_EVENTS | UCCE_TX_EVENTS)) { if (napi_schedule_prep(&ugeth->napi)) { - uccm &= ~UCCE_RX_EVENTS; + uccm &= ~(UCCE_RX_EVENTS | UCCE_TX_EVENTS); out_be32(uccf->p_uccm, uccm); __napi_schedule(&ugeth->napi); } } - /* Tx event processing */ - if (ucce & UCCE_TX_EVENTS) { - spin_lock(&ugeth->lock); - tx_mask = UCC_GETH_UCCE_TXB0; - for (i = 0; i < ug_info->numQueuesTx; i++) { - if (ucce & tx_mask) - ucc_geth_tx(dev, i); - ucce &= ~tx_mask; - tx_mask <<= 1; - } - spin_unlock(&ugeth->lock); - } - /* Errors and other events */ if (ucce & UCCE_OTHER) { if (ucce & UCC_GETH_UCCE_BSY) @@ -3734,7 +3725,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma dev->netdev_ops = &ucc_geth_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); - netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT); + netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64); dev->mtu = 1500; ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 2f8ee7c87efe..602764799df0 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -852,7 +852,6 @@ struct ucc_geth_hardware_statistics { /* Driver definitions */ #define TX_BD_RING_LEN 0x10 #define RX_BD_RING_LEN 0x10 -#define UCC_GETH_DEV_WEIGHT TX_BD_RING_LEN #define TX_RING_MOD_MASK(size) (size-1) #define RX_RING_MOD_MASK(size) (size-1) -- cgit v1.2.3 From 0a1ec07a67bd8b0033dace237249654d015efa21 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Apr 2009 01:25:46 +0000 Subject: net: skb_copy_datagram_const_iovec() There's an skb_copy_datagram_iovec() to copy out of a paged skb, but it modifies the iovec, and does not support starting at an offset in the destination. We want both in tun.c, so let's add the function. It's a carbon copy of skb_copy_datagram_iovec() with enough changes to be annoying. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/linux/skbuff.h | 5 +++ include/linux/socket.h | 2 ++ net/core/datagram.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ net/core/iovec.c | 26 ++++++++++++++ 4 files changed, 125 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 5fd389162f01..af2b21bdda83 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1717,6 +1717,11 @@ extern int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, struct iovec *from, int len); +extern int skb_copy_datagram_const_iovec(const struct sk_buff *from, + int offset, + const struct iovec *to, + int to_offset, + int size); extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); diff --git a/include/linux/socket.h b/include/linux/socket.h index 421afb4d29b0..171b08db9c4f 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -318,6 +318,8 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata, extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode); extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); +extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, + int offset, int len); extern int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, int __user *ulen); extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr); extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); diff --git a/net/core/datagram.c b/net/core/datagram.c index d0de644b378d..4dbb05cd572b 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -338,6 +338,98 @@ fault: return -EFAULT; } +/** + * skb_copy_datagram_const_iovec - Copy a datagram to an iovec. + * @skb: buffer to copy + * @offset: offset in the buffer to start copying from + * @to: io vector to copy to + * @to_offset: offset in the io vector to start copying to + * @len: amount of data to copy from buffer to iovec + * + * Returns 0 or -EFAULT. + * Note: the iovec is not modified during the copy. + */ +int skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset, + const struct iovec *to, int to_offset, + int len) +{ + int start = skb_headlen(skb); + int i, copy = start - offset; + + /* Copy header. */ + if (copy > 0) { + if (copy > len) + copy = len; + if (memcpy_toiovecend(to, skb->data + offset, to_offset, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + to_offset += copy; + } + + /* Copy paged appendix. Hmm... why does this look so complicated? */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + WARN_ON(start > offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + int err; + u8 *vaddr; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; + + if (copy > len) + copy = len; + vaddr = kmap(page); + err = memcpy_toiovecend(to, vaddr + frag->page_offset + + offset - start, to_offset, copy); + kunmap(page); + if (err) + goto fault; + if (!(len -= copy)) + return 0; + offset += copy; + to_offset += copy; + } + start = end; + } + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + WARN_ON(start > offset + len); + + end = start + list->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_datagram_const_iovec(list, + offset - start, + to, to_offset, + copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + to_offset += copy; + } + start = end; + } + } + if (!len) + return 0; + +fault: + return -EFAULT; +} +EXPORT_SYMBOL(skb_copy_datagram_const_iovec); + /** * skb_copy_datagram_from_iovec - Copy a datagram from an iovec. * @skb: buffer to copy diff --git a/net/core/iovec.c b/net/core/iovec.c index 4c9c0121c9da..a215545c0a34 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -97,6 +97,31 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) return 0; } +/* + * Copy kernel to iovec. Returns -EFAULT on error. + */ + +int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, + int offset, int len) +{ + int copy; + for (; len > 0; ++iov) { + /* Skip over the finished iovecs */ + if (unlikely(offset >= iov->iov_len)) { + offset -= iov->iov_len; + continue; + } + copy = min_t(unsigned int, iov->iov_len - offset, len); + offset = 0; + if (copy_to_user(iov->iov_base, kdata, copy)) + return -EFAULT; + kdata += copy; + len -= copy; + } + + return 0; +} + /* * Copy iovec to kernel. Returns -EFAULT on error. * @@ -236,3 +261,4 @@ EXPORT_SYMBOL(csum_partial_copy_fromiovecend); EXPORT_SYMBOL(memcpy_fromiovec); EXPORT_SYMBOL(memcpy_fromiovecend); EXPORT_SYMBOL(memcpy_toiovec); +EXPORT_SYMBOL(memcpy_toiovecend); -- cgit v1.2.3 From 43b39dcdbdf823a1c0ac1f2aa2d76bd2f210adc8 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Apr 2009 01:25:59 +0000 Subject: tun: fix tun_chr_aio_read so that aio works aio_read gets const struct iovec * but tun_chr_aio_read casts this to struct iovec * and modifies the iovec. As a result, attempts to use io_submit to get packets from a tun device fail with weird errors such as EINVAL. Fix by using the new skb_copy_datagram_const_iovec. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/tun.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 735bf41c654a..3b513e29d392 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -683,7 +683,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, /* Put packet to the user space buffer */ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, struct sk_buff *skb, - struct iovec *iv, int len) + const struct iovec *iv, int len) { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; @@ -697,7 +697,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, pi.flags |= TUN_PKT_STRIP; } - if (memcpy_toiovec(iv, (void *) &pi, sizeof(pi))) + if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi))) return -EFAULT; total += sizeof(pi); } @@ -730,14 +730,15 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, gso.csum_offset = skb->csum_offset; } /* else everything is zero */ - if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso)))) + if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, + sizeof(gso)))) return -EFAULT; total += sizeof(gso); } len = min_t(int, skb->len, len); - skb_copy_datagram_iovec(skb, 0, iv, len); + skb_copy_datagram_const_iovec(skb, 0, iv, total, len); total += len; tun->dev->stats.tx_packets++; @@ -792,7 +793,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, } netif_wake_queue(tun->dev); - ret = tun_put_user(tun, skb, (struct iovec *) iv, len); + ret = tun_put_user(tun, skb, iv, len); kfree_skb(skb); break; } -- cgit v1.2.3 From 6f26c9a7555e5bcca3560919db9b852015077dae Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 20 Apr 2009 01:26:11 +0000 Subject: tun: fix tun_chr_aio_write so that aio works aio_write gets const struct iovec * but tun_chr_aio_write casts this to struct iovec * and modifies the iovec. As a result, attempts to use io_submit to send packets to a tun device fail with weird errors such as EINVAL. Since tun is the only user of skb_copy_datagram_from_iovec, we can fix this simply by changing the later so that it does not touch the iovec passed to it. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/tun.c | 13 ++++++++----- include/linux/skbuff.h | 3 ++- include/linux/socket.h | 4 ++-- net/core/datagram.c | 20 ++++++++++++++------ net/core/iovec.c | 7 ++++--- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3b513e29d392..589f0ca668d6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -540,31 +540,34 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, /* Get packet from user space buffer */ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, - struct iovec *iv, size_t count, + const struct iovec *iv, size_t count, int noblock) { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; size_t len = count, align = 0; struct virtio_net_hdr gso = { 0 }; + int offset = 0; if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) > count) return -EINVAL; - if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) + if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) return -EFAULT; + offset += sizeof(pi); } if (tun->flags & TUN_VNET_HDR) { if ((len -= sizeof(gso)) > count) return -EINVAL; - if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso))) + if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) return -EFAULT; if (gso.hdr_len > len) return -EINVAL; + offset += sizeof(pi); } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { @@ -581,7 +584,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, return PTR_ERR(skb); } - if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) { + if (skb_copy_datagram_from_iovec(skb, 0, iv, offset, len)) { tun->dev->stats.rx_dropped++; kfree_skb(skb); return -EFAULT; @@ -673,7 +676,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); - result = tun_get_user(tun, (struct iovec *)iv, iov_length(iv, count), + result = tun_get_user(tun, iv, iov_length(iv, count), file->f_flags & O_NONBLOCK); tun_put(tun); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index af2b21bdda83..1b5c3d298f43 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1715,7 +1715,8 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, struct iovec *iov); extern int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, - struct iovec *from, + const struct iovec *from, + int from_offset, int len); extern int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset, diff --git a/include/linux/socket.h b/include/linux/socket.h index 171b08db9c4f..42a0396f2c59 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -309,8 +309,8 @@ struct ucred { #ifdef __KERNEL__ extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); -extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, - int offset, int len); +extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len); extern int csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, diff --git a/net/core/datagram.c b/net/core/datagram.c index 4dbb05cd572b..914d5fa773b4 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -435,13 +435,15 @@ EXPORT_SYMBOL(skb_copy_datagram_const_iovec); * @skb: buffer to copy * @offset: offset in the buffer to start copying to * @from: io vector to copy to + * @from_offset: offset in the io vector to start copying from * @len: amount of data to copy to buffer from iovec * * Returns 0 or -EFAULT. - * Note: the iovec is modified during the copy. + * Note: the iovec is not modified during the copy. */ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, - struct iovec *from, int len) + const struct iovec *from, int from_offset, + int len) { int start = skb_headlen(skb); int i, copy = start - offset; @@ -450,11 +452,12 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, if (copy > 0) { if (copy > len) copy = len; - if (memcpy_fromiovec(skb->data + offset, from, copy)) + if (memcpy_fromiovecend(skb->data + offset, from, 0, copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; + from_offset += copy; } /* Copy paged appendix. Hmm... why does this look so complicated? */ @@ -473,8 +476,9 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, if (copy > len) copy = len; vaddr = kmap(page); - err = memcpy_fromiovec(vaddr + frag->page_offset + - offset - start, from, copy); + err = memcpy_fromiovecend(vaddr + frag->page_offset + + offset - start, + from, from_offset, copy); kunmap(page); if (err) goto fault; @@ -482,6 +486,7 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, if (!(len -= copy)) return 0; offset += copy; + from_offset += copy; } start = end; } @@ -500,11 +505,14 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, copy = len; if (skb_copy_datagram_from_iovec(list, offset - start, - from, copy)) + from, + from_offset, + copy)) goto fault; if ((len -= copy) == 0) return 0; offset += copy; + from_offset += copy; } start = end; } diff --git a/net/core/iovec.c b/net/core/iovec.c index a215545c0a34..40a76ce19d9f 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -147,10 +147,11 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len) } /* - * For use with ip_build_xmit + * Copy iovec from kernel. Returns -EFAULT on error. */ -int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset, - int len) + +int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len) { /* Skip over the finished iovecs */ while (offset >= iov->iov_len) { -- cgit v1.2.3 From bf98a82633b97fb638fcee0fae3c0de54d1f7b05 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Tue, 21 Apr 2009 18:12:11 -0700 Subject: sa1100_ir: fix build breakage Fix simple typo. Caused by commit a1de966682551debbe690672e760487cc555c05f ("irda/sa1100_ir: convert to net_device_ops"). Reported-by: Stephen Rothwell Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/sa1100_ir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 4ed763670a97..2aeb2e6aec1b 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -925,7 +925,7 @@ static int sa1100_irda_probe(struct platform_device *pdev) goto err_mem_5; dev->netdev_ops = &sa1100_irda_netdev_ops; - dev->ir = IRQ_Ser2ICP; + dev->irq = IRQ_Ser2ICP; irda_init_max_qos_capabilies(&si->qos); -- cgit v1.2.3 From 4cb9be7ab47820a1fa747569f5f035a5f628c91b Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 21 Apr 2009 18:42:05 +0000 Subject: e1000/e1000e/igb/ixgb: do not use netif_wake_queue un-necessarily It was pointed out that the Intel wired ethernet drivers do not need to wake the tx queue since netif_carrier_on/off will take care of the qdisc management in order to guarantee the correct handling of the transmit routine enable state. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 4 ++-- drivers/net/e1000e/netdev.c | 8 ++++---- drivers/net/igb/igb_main.c | 4 ++-- drivers/net/ixgb/ixgb_main.c | 5 ++--- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 112e6b039983..71d4fe15976a 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -498,6 +498,8 @@ int e1000_up(struct e1000_adapter *adapter) e1000_irq_enable(adapter); + netif_wake_queue(adapter->netdev); + /* fire a link change interrupt to start the watchdog */ ew32(ICS, E1000_ICS_LSC); return 0; @@ -2591,7 +2593,6 @@ static void e1000_watchdog(unsigned long data) ew32(TCTL, tctl); netif_carrier_on(netdev); - netif_wake_queue(netdev); mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); adapter->smartspeed = 0; } else { @@ -2608,7 +2609,6 @@ static void e1000_watchdog(unsigned long data) printk(KERN_INFO "e1000: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_stop_queue(netdev); mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); /* 80003ES2LAN workaround-- diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 9048f8e6a8ce..da6b37e05bea 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2826,6 +2826,8 @@ int e1000e_up(struct e1000_adapter *adapter) e1000_configure_msix(adapter); e1000_irq_enable(adapter); + netif_wake_queue(adapter->netdev); + /* fire a link change interrupt to start the watchdog */ ew32(ICS, E1000_ICS_LSC); return 0; @@ -2848,7 +2850,7 @@ void e1000e_down(struct e1000_adapter *adapter) ew32(RCTL, rctl & ~E1000_RCTL_EN); /* flush and sleep below */ - netif_tx_stop_all_queues(netdev); + netif_stop_queue(netdev); /* disable transmits in the hardware */ tctl = er32(TCTL); @@ -3130,7 +3132,7 @@ static int e1000_open(struct net_device *netdev) e1000_irq_enable(adapter); - netif_tx_start_all_queues(netdev); + netif_start_queue(netdev); /* fire a link status change interrupt to start the watchdog */ ew32(ICS, E1000_ICS_LSC); @@ -3600,7 +3602,6 @@ static void e1000_watchdog_task(struct work_struct *work) phy->ops.cfg_on_link_up(hw); netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, @@ -3614,7 +3615,6 @@ static void e1000_watchdog_task(struct work_struct *work) printk(KERN_INFO "e1000e: %s NIC Link is Down\n", adapter->netdev->name); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ceaa58554679..183235d46aee 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -942,6 +942,8 @@ int igb_up(struct igb_adapter *adapter) rd32(E1000_ICR); igb_irq_enable(adapter); + netif_tx_start_all_queues(adapter->netdev); + /* Fire a link change interrupt to start the watchdog. */ wr32(E1000_ICS, E1000_ICS_LSC); return 0; @@ -2664,7 +2666,6 @@ static void igb_watchdog_task(struct work_struct *work) } netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); igb_ping_all_vfs(adapter); @@ -2681,7 +2682,6 @@ static void igb_watchdog_task(struct work_struct *work) printk(KERN_INFO "igb: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); igb_ping_all_vfs(adapter); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index ff741ca110f5..cb9ecc48f6d0 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -266,6 +266,8 @@ ixgb_up(struct ixgb_adapter *adapter) napi_enable(&adapter->napi); ixgb_irq_enable(adapter); + netif_wake_queue(netdev); + mod_timer(&adapter->watchdog_timer, jiffies); return 0; @@ -1118,7 +1120,6 @@ ixgb_watchdog(unsigned long data) adapter->link_speed = 10000; adapter->link_duplex = FULL_DUPLEX; netif_carrier_on(netdev); - netif_wake_queue(netdev); } } else { if (netif_carrier_ok(netdev)) { @@ -1127,8 +1128,6 @@ ixgb_watchdog(unsigned long data) printk(KERN_INFO "ixgb: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); - netif_stop_queue(netdev); - } } -- cgit v1.2.3 From 362b76edb78923face033e18e4ffc85df8db0f28 Mon Sep 17 00:00:00 2001 From: Mateusz Mandera Date: Wed, 22 Apr 2009 02:24:28 -0700 Subject: 8390p: Get rid of init_module/cleanup_module This trivial patch just "gets rid of" init_module and cleanup_module from drivers/net/8390p.c Signed-off-by: Mateusz Mandera Signed-off-by: David S. Miller --- drivers/net/8390p.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c index 6ec11dafdb18..cacdd86a27d0 100644 --- a/drivers/net/8390p.c +++ b/drivers/net/8390p.c @@ -91,16 +91,15 @@ void NS8390p_init(struct net_device *dev, int startp) } EXPORT_SYMBOL(NS8390p_init); -#if defined(MODULE) - -int init_module(void) +static int __init 8390p_init_module(void) { return 0; } -void cleanup_module(void) +static void __exit 8390p_cleanup_module(void) { } -#endif /* MODULE */ +module_init(8390p_init_module); +module_exit(8390p_cleanup_module); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From f74d0f5cacb7023422098dd5c98e3ce06787ba56 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 25 Mar 2009 08:30:15 +0300 Subject: p54spi: mask value read from SPI_ADRS_DMA_WRITE_CTRL in p54spi_wait_bit Mask value read from SPI_ADRS_DMA_WRITE_CTRL in p54spi_wait_bit. Without this, 'fw_upload not allowed to DMA write' is observed at both N800 and N810. Signed-off-by: Max Filippov Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index d1fe577de3d4..55402729d21b 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -171,7 +171,7 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) for (i = 0; i < 2000; i++) { p54spi_spi_read(priv, reg, &buffer, sizeof(buffer)); - if (buffer == bits) + if ((buffer & bits) == bits) return 1; msleep(1); -- cgit v1.2.3 From 5e3af1d2d3e6c0011b4c22514d39c73dcbc6674f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 25 Mar 2009 13:45:01 +0100 Subject: p54spi: fix p54spi_upload_firmware Instead of firmware itself p54_upload_firmware was sending to the device content of struct firmware and the following random garbage. Notice '&' before priv->firmware->data at p54spi_spi_write. But simple removing of '&' sign triggered BUG_ON at dma_cache_maint. Thus kmemdup - kfree workaround. Signed-off-by: Max Filippov Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 55402729d21b..bed894ae04b5 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -228,8 +228,15 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev) static int p54spi_upload_firmware(struct ieee80211_hw *dev) { struct p54s_priv *priv = dev->priv; - unsigned long fw_len, fw_addr; - long _fw_len; + unsigned long fw_len, _fw_len; + unsigned int offset = 0; + int err = 0; + u8 *fw; + + fw_len = priv->firmware->size; + fw = kmemdup(priv->firmware->data, fw_len, GFP_KERNEL); + if (!fw) + return -ENOMEM; /* stop the device */ p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( @@ -244,9 +251,6 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) msleep(TARGET_BOOT_SLEEP); - fw_addr = ISL38XX_DEV_FIRMWARE_ADDR; - fw_len = priv->firmware->size; - while (fw_len > 0) { _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); @@ -257,23 +261,20 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) cpu_to_le32(HOST_ALLOWED)) == 0) { dev_err(&priv->spi->dev, "fw_upload not allowed " "to DMA write."); - return -EAGAIN; + err = -EAGAIN; + goto out; } p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(_fw_len)); - p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, - cpu_to_le32(fw_addr)); + p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, cpu_to_le32( + ISL38XX_DEV_FIRMWARE_ADDR + offset)); p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, - &priv->firmware->data, _fw_len); + (fw + offset), _fw_len); fw_len -= _fw_len; - fw_addr += _fw_len; - - /* FIXME: I think this doesn't work if firmware is large, - * this loop goes to second round. fw->data is not - * increased at all! */ + offset += _fw_len; } BUG_ON(fw_len != 0); @@ -292,7 +293,10 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT)); msleep(TARGET_BOOT_SLEEP); - return 0; + +out: + kfree(fw); + return err; } static void p54spi_power_off(struct p54s_priv *priv) -- cgit v1.2.3 From 684d6b360222f31b6b9be9a63aa5c6ed5674c890 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 25 Mar 2009 09:51:16 -0700 Subject: libertas: support mesh for various firmware versions CMD_MESH_CONFIG command ID and a couple of structure members in TxPD, RxPD have been changed in firmware version 10.x.y.z and newer. Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 26 +++++++++++++++++-- drivers/net/wireless/libertas/defs.h | 21 ++++++++++++++++ drivers/net/wireless/libertas/dev.h | 1 + drivers/net/wireless/libertas/host.h | 3 ++- drivers/net/wireless/libertas/hostcmd.h | 28 ++++++++++++++++++--- drivers/net/wireless/libertas/main.c | 44 ++++++++++++++++++++------------- drivers/net/wireless/libertas/rx.c | 33 +++++++------------------ drivers/net/wireless/libertas/tx.c | 8 ++++-- drivers/net/wireless/libertas/types.h | 2 ++ 9 files changed, 116 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 8c3605cdc64c..c455b9abbfc0 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -119,6 +119,19 @@ int lbs_update_hw_spec(struct lbs_private *priv) lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", cmd.hwifversion, cmd.version); + /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ + /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ + /* 5.110.22 have mesh command with 0xa3 command id */ + /* 10.0.0.p0 FW brings in mesh config command with different id */ + /* Check FW version MSB and initialize mesh_fw_ver */ + if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) + priv->mesh_fw_ver = MESH_FW_OLD; + else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && + (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) + priv->mesh_fw_ver = MESH_FW_NEW; + else + priv->mesh_fw_ver = MESH_NONE; + /* Clamp region code to 8-bit since FW spec indicates that it should * only ever be 8-bit, even though the field size is 16-bit. Some firmware * returns non-zero high 8 bits here. @@ -1036,17 +1049,26 @@ static int __lbs_mesh_config_send(struct lbs_private *priv, uint16_t action, uint16_t type) { int ret; + u16 command = CMD_MESH_CONFIG_OLD; lbs_deb_enter(LBS_DEB_CMD); - cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG); + /* + * Command id is 0xac for v10 FW along with mesh interface + * id in bits 14-13-12. + */ + if (priv->mesh_fw_ver == MESH_FW_NEW) + command = CMD_MESH_CONFIG | + (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); + + cmd->hdr.command = cpu_to_le16(command); cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); cmd->hdr.result = 0; cmd->type = cpu_to_le16(type); cmd->action = cpu_to_le16(action); - ret = lbs_cmd_with_response(priv, CMD_MESH_CONFIG, cmd); + ret = lbs_cmd_with_response(priv, command, cmd); lbs_deb_leave(LBS_DEB_CMD); return ret; diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index e8dfde39abfc..48da157d6cda 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -227,6 +227,20 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define TxPD_CONTROL_WDS_FRAME (1<<17) #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME +/** Mesh interface ID */ +#define MESH_IFACE_ID 0x0001 +/** Mesh id should be in bits 14-13-12 */ +#define MESH_IFACE_BIT_OFFSET 0x000c +/** Mesh enable bit in FW capability */ +#define MESH_CAPINFO_ENABLE_MASK (1<<16) + +/** FW definition from Marvell v5 */ +#define MRVL_FW_V5 (0x05) +/** FW definition from Marvell v10 */ +#define MRVL_FW_V10 (0x0a) +/** FW major revision definition */ +#define MRVL_FW_MAJOR_REV(x) ((x)>>24) + /** RxPD status */ #define MRVDRV_RXPD_STATUS_OK 0x0001 @@ -380,6 +394,13 @@ enum KEY_INFO_WPA { KEY_INFO_WPA_ENABLED = 0x04 }; +/** mesh_fw_ver */ +enum _mesh_fw_ver { + MESH_NONE = 0, /* MESH is not supported */ + MESH_FW_OLD, /* MESH is supported in FW V5 */ + MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ +}; + /* Default values for fwt commands. */ #define FWT_DEFAULT_METRIC 0 #define FWT_DEFAULT_DIR 1 diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 27e81fd97c94..cbaafa653b6a 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -101,6 +101,7 @@ struct lbs_mesh_stats { /** Private structure for the MV device */ struct lbs_private { int mesh_open; + int mesh_fw_ver; int infra_open; int mesh_autostart_enabled; diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index d4457ef808a6..8ff8ac9d817e 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -83,7 +83,8 @@ #define CMD_FWT_ACCESS 0x0095 #define CMD_802_11_MONITOR_MODE 0x0098 #define CMD_MESH_ACCESS 0x009b -#define CMD_MESH_CONFIG 0x00a3 +#define CMD_MESH_CONFIG_OLD 0x00a3 +#define CMD_MESH_CONFIG 0x00ac #define CMD_SET_BOOT2_VER 0x00a5 #define CMD_802_11_BEACON_CTRL 0x00b0 diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index a899aeb676bb..391c54ab2b09 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -13,8 +13,19 @@ /* TxPD descriptor */ struct txpd { - /* Current Tx packet status */ - __le32 tx_status; + /* union to cope up with later FW revisions */ + union { + /* Current Tx packet status */ + __le32 tx_status; + struct { + /* BSS type: client, AP, etc. */ + u8 bss_type; + /* BSS number */ + u8 bss_num; + /* Reserved */ + __le16 reserved; + } bss; + } u; /* Tx control */ __le32 tx_control; __le32 tx_packet_location; @@ -36,8 +47,17 @@ struct txpd { /* RxPD Descriptor */ struct rxpd { - /* Current Rx packet status */ - __le16 status; + /* union to cope up with later FW revisions */ + union { + /* Current Rx packet status */ + __le16 status; + struct { + /* BSS type: client, AP, etc. */ + u8 bss_type; + /* BSS number */ + u8 bss_num; + } bss; + } u; /* SNR */ u8 snr; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8ae935ac32f1..89575e448015 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1307,8 +1307,10 @@ int lbs_start_card(struct lbs_private *priv) lbs_update_channel(priv); - /* 5.0.16p0 is known to NOT support any mesh */ - if (priv->fwrelease > 0x05001000) { + /* Check mesh FW version and appropriately send the mesh start + * command + */ + if (priv->mesh_fw_ver == MESH_FW_OLD) { /* Enable mesh, if supported, and work out which TLV it uses. 0x100 + 291 is an unofficial value used in 5.110.20.pXX 0x100 + 37 is the official value used in 5.110.21.pXX @@ -1322,27 +1324,35 @@ int lbs_start_card(struct lbs_private *priv) It's just that 5.110.20.pXX will not have done anything useful */ - priv->mesh_tlv = 0x100 + 291; + priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->curbssparams.channel)) { - priv->mesh_tlv = 0x100 + 37; + priv->mesh_tlv = TLV_TYPE_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->curbssparams.channel)) priv->mesh_tlv = 0; } - if (priv->mesh_tlv) { - lbs_add_mesh(priv); - - if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) - lbs_pr_err("cannot register lbs_mesh attribute\n"); - - /* While rtap isn't related to mesh, only mesh-enabled - * firmware implements the rtap functionality via - * CMD_802_11_MONITOR_MODE. - */ - if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) - lbs_pr_err("cannot register lbs_rtap attribute\n"); - } + } else if (priv->mesh_fw_ver == MESH_FW_NEW) { + /* 10.0.0.pXX new firmwares should succeed with TLV + * 0x100+37; Do not invoke command with old TLV. + */ + priv->mesh_tlv = TLV_TYPE_MESH_ID; + if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, + priv->curbssparams.channel)) + priv->mesh_tlv = 0; + } + if (priv->mesh_tlv) { + lbs_add_mesh(priv); + + if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) + lbs_pr_err("cannot register lbs_mesh attribute\n"); + + /* While rtap isn't related to mesh, only mesh-enabled + * firmware implements the rtap functionality via + * CMD_802_11_MONITOR_MODE. + */ + if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) + lbs_pr_err("cannot register lbs_rtap attribute\n"); } lbs_debugfs_init_one(priv, dev); diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 8e669775cb5d..820c22d9220f 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -160,8 +160,15 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) p_rx_pkt = (struct rxpackethdr *) skb->data; p_rx_pd = &p_rx_pkt->rx_pd; - if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME)) - dev = priv->mesh_dev; + if (priv->mesh_dev) { + if (priv->mesh_fw_ver == MESH_FW_OLD) { + if (p_rx_pd->rx_control & RxPD_MESH_FRAME) + dev = priv->mesh_dev; + } else if (priv->mesh_fw_ver == MESH_FW_NEW) { + if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID) + dev = priv->mesh_dev; + } + } lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min_t(unsigned int, skb->len, 100)); @@ -174,18 +181,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) goto done; } - /* - * Check rxpd status and update 802.3 stat, - */ - if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { - lbs_deb_rx("rx err: frame received with bad status\n"); - lbs_pr_alert("rxpd not ok\n"); - dev->stats.rx_errors++; - ret = 0; - dev_kfree_skb(skb); - goto done; - } - lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); @@ -334,14 +329,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, goto done; } - /* - * Check rxpd status and update 802.3 stat, - */ - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { - //lbs_deb_rx("rx err: frame received with bad status\n"); - dev->stats.rx_errors++; - } - lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); @@ -353,8 +340,6 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, radiotap_hdr.hdr.it_pad = 0; radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr)); radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT); - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) - radiotap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS; radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate); /* XXX must check no carryout */ radiotap_hdr.antsignal = prxpd->snr + prxpd->nf; diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index f10aa39a6b68..160cfd8311c0 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -132,8 +132,12 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) txpd->tx_packet_length = cpu_to_le16(pkt_len); txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); - if (dev == priv->mesh_dev) - txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); + if (dev == priv->mesh_dev) { + if (priv->mesh_fw_ver == MESH_FW_OLD) + txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); + else if (priv->mesh_fw_ver == MESH_FW_NEW) + txpd->u.bss.bss_num = MESH_IFACE_ID; + } lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index fb7a2d1a2525..de03b9c9c204 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -94,6 +94,8 @@ struct ieeetypes_assocrsp { #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) #define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) +#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) +#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) /** TLV related data structures*/ struct mrvlietypesheader { -- cgit v1.2.3 From 4f5cab969bdbec1ab0c5b690282372b4978123ac Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 26 Mar 2009 06:38:25 +0300 Subject: p54spi: fix p54spi_tx_frame DMA transfer initiation and skb cleanup p54spi_tx_frame wasn't waiting for HOST_ALLOWED in SPI_ADRS_DMA_WRITE_CTRL. This resulted in frequent 'WR_READY timeout' on beacon resubmission. Also don't free skb on error path, as it gets freed on p54spi_wq_tx. Signed-off-by: Max Filippov Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index bed894ae04b5..f8af09610180 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -179,6 +179,25 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) return 0; } +static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base, + const void *buf, size_t len) +{ + p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, + cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); + + if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, + cpu_to_le32(HOST_ALLOWED)) == 0) { + dev_err(&priv->spi->dev, "spi_write_dma not allowed " + "to DMA write."); + return -EAGAIN; + } + + p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len)); + p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base); + p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len); + return 0; +} + static int p54spi_request_firmware(struct ieee80211_hw *dev) { struct p54s_priv *priv = dev->priv; @@ -254,24 +273,11 @@ static int p54spi_upload_firmware(struct ieee80211_hw *dev) while (fw_len > 0) { _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); - p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, - cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); - - if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, - cpu_to_le32(HOST_ALLOWED)) == 0) { - dev_err(&priv->spi->dev, "fw_upload not allowed " - "to DMA write."); - err = -EAGAIN; + err = p54spi_spi_write_dma(priv, cpu_to_le32( + ISL38XX_DEV_FIRMWARE_ADDR + offset), + (fw + offset), _fw_len); + if (err < 0) goto out; - } - - p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, - cpu_to_le16(_fw_len)); - p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, cpu_to_le32( - ISL38XX_DEV_FIRMWARE_ADDR + offset)); - - p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, - (fw + offset), _fw_len); fw_len -= _fw_len; offset += _fw_len; @@ -418,27 +424,21 @@ static irqreturn_t p54spi_interrupt(int irq, void *config) static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) { struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - struct p54s_dma_regs dma_regs; unsigned long timeout; int ret = 0; u32 ints; p54spi_wakeup(priv); - dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE); - dma_regs.len = cpu_to_le16(skb->len); - dma_regs.addr = hdr->req_id; - - p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, - sizeof(dma_regs)); - - p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len); + ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len); + if (ret < 0) + goto out; timeout = jiffies + 2 * HZ; ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); while (!(ints & SPI_HOST_INT_WR_READY)) { if (time_after(jiffies, timeout)) { - dev_err(&priv->spi->dev, "WR_READY timeout"); + dev_err(&priv->spi->dev, "WR_READY timeout\n"); ret = -1; goto out; } @@ -448,9 +448,9 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); p54spi_sleep(priv); -out: if (FREE_AFTER_TX(skb)) p54_free_skb(priv->hw, skb); +out: return ret; } -- cgit v1.2.3 From 6da3a13e4fcab0ff58592087d28bd283caf23d88 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 26 Mar 2009 10:14:08 -0700 Subject: iwlwifi: merge and better support of suspend/resume for iwlagn and iwl3945 With mac80211's help to call stop() and start() in mac80211 suspend/resume function, both iwlagn and iwl3945 no longer calling stop() and start(); remove un-necessary STATUS_IN_SUSPEND bit from both header files and functions, Move apm_ops.stop() function into pci_suspend() to ensure DMA is stopped before go into suspend mode. iwl3945 has the similar suspend/resume function as iwlagn, so move both functions to iwlcore to be shared by both drivers. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 54 ++----------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 40 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 5 ++- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 62 ++++------------------------- 6 files changed, 56 insertions(+), 108 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ab7aaf6872c7..29bc0d2656bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -162,7 +162,6 @@ struct iwl3945_frame { #define STATUS_TEMPERATURE 8 #define STATUS_GEO_CONFIGURED 9 #define STATUS_EXIT_PENDING 10 -#define STATUS_IN_SUSPEND 11 #define STATUS_STATISTICS 12 #define STATUS_SCANNING 13 #define STATUS_SCAN_ABORTING 14 diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3889158b359c..2cb073efb95d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1654,7 +1654,7 @@ static void __iwl_down(struct iwl_priv *priv) ieee80211_stop_queues(priv->hw); /* If we have not previously called iwl_init() then - * clear all bits but the RF Kill and SUSPEND bits and return */ + * clear all bits but the RF Kill bits and return */ if (!iwl_is_init(priv)) { priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | @@ -1662,23 +1662,19 @@ static void __iwl_down(struct iwl_priv *priv) STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; goto exit; } - /* ...otherwise clear out all the status bits but the RF Kill and - * SUSPEND bits and continue taking the NIC down. */ + /* ...otherwise clear out all the status bits but the RF Kill + * bits and continue taking the NIC down. */ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << STATUS_FW_ERROR | test_bit(STATUS_EXIT_PENDING, &priv->status) << @@ -1703,7 +1699,7 @@ static void __iwl_down(struct iwl_priv *priv) udelay(5); /* FIXME: apm_ops.suspend(priv) */ - if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) + if (exit_pending) priv->cfg->ops->lib->apm_ops.stop(priv); else priv->cfg->ops->lib->apm_ops.reset(priv); @@ -2064,9 +2060,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_INFO(priv, "Start UP work done.\n"); - if (test_bit(STATUS_IN_SUSPEND, &priv->status)) - return 0; - /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from * mac80211 will not be run successfully. */ ret = wait_event_interruptible_timeout(priv->wait_command_queue, @@ -3566,45 +3559,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) ieee80211_free_hw(priv->hw); } -#ifdef CONFIG_PM - -static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - - if (priv->is_open) { - set_bit(STATUS_IN_SUSPEND, &priv->status); - iwl_mac_stop(priv->hw); - priv->is_open = 1; - } - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int iwl_pci_resume(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); - iwl_enable_interrupts(priv); - - if (priv->is_open) - iwl_mac_start(priv->hw); - - clear_bit(STATUS_IN_SUSPEND, &priv->status); - return 0; -} - -#endif /* CONFIG_PM */ /***************************************************************************** * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c54fb93e9d72..2e44d6e19e2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2112,3 +2112,43 @@ void iwl_rx_reply_error(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_reply_error); +#ifdef CONFIG_PM + +int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct iwl_priv *priv = pci_get_drvdata(pdev); + + /* + * This function is called when system goes into suspend state + * mac80211 will call iwl_mac_stop() from the mac80211 suspend function + * first but since iwl_mac_stop() has no knowledge of who the caller is, + * it will not call apm_ops.stop() to stop the DMA operation. + * Calling apm_ops.stop here to make sure we stop the DMA. + */ + priv->cfg->ops->lib->apm_ops.stop(priv); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} +EXPORT_SYMBOL(iwl_pci_suspend); + +int iwl_pci_resume(struct pci_dev *pdev) +{ + struct iwl_priv *priv = pci_get_drvdata(pdev); + int ret; + + pci_set_power_state(pdev, PCI_D0); + ret = pci_enable_device(pdev); + if (ret) + return ret; + pci_restore_state(pdev); + iwl_enable_interrupts(priv); + + return 0; +} +EXPORT_SYMBOL(iwl_pci_resume); + +#endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a8eac8c3c1fa..5d4904584686 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -432,6 +432,10 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); return pci_lnk_ctl; } +#ifdef CONFIG_PM +int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); +int iwl_pci_resume(struct pci_dev *pdev); +#endif /* CONFIG_PM */ /***************************************************** * Error Handling Debugging @@ -458,7 +462,6 @@ void iwlcore_free_geos(struct iwl_priv *priv); #define STATUS_TEMPERATURE 8 #define STATUS_GEO_CONFIGURED 9 #define STATUS_EXIT_PENDING 10 -#define STATUS_IN_SUSPEND 11 #define STATUS_STATISTICS 12 #define STATUS_SCANNING 13 #define STATUS_SCAN_ABORTING 14 diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 64eb585f1578..af1d1214b184 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -456,8 +456,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, test_bit(STATUS_GEO_CONFIGURED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", test_bit(STATUS_EXIT_PENDING, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n", - test_bit(STATUS_IN_SUSPEND, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", test_bit(STATUS_STATISTICS, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index da61ecd62882..afb838b39a6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2996,7 +2996,7 @@ static void __iwl3945_down(struct iwl_priv *priv) ieee80211_stop_queues(priv->hw); /* If we have not previously called iwl3945_init() then - * clear all bits but the RF Kill and SUSPEND bits and return */ + * clear all bits but the RF Kill bits and return */ if (!iwl_is_init(priv)) { priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | @@ -3004,23 +3004,19 @@ static void __iwl3945_down(struct iwl_priv *priv) STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; goto exit; } - /* ...otherwise clear out all the status bits but the RF Kill and - * SUSPEND bits and continue taking the NIC down. */ + /* ...otherwise clear out all the status bits but the RF Kill + * bits and continue taking the NIC down. */ priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_IN_SUSPEND, &priv->status) << - STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << STATUS_FW_ERROR | test_bit(STATUS_EXIT_PENDING, &priv->status) << @@ -3044,7 +3040,7 @@ static void __iwl3945_down(struct iwl_priv *priv) udelay(5); - if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) + if (exit_pending) priv->cfg->ops->lib->apm_ops.stop(priv); else priv->cfg->ops->lib->apm_ops.reset(priv); @@ -3097,10 +3093,8 @@ static int __iwl3945_up(struct iwl_priv *priv) clear_bit(STATUS_RF_KILL_HW, &priv->status); else { set_bit(STATUS_RF_KILL_HW, &priv->status); - if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { - IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); - return -ENODEV; - } + IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); + return -ENODEV; } iwl_write32(priv, CSR_INT, 0xFFFFFFFF); @@ -3592,9 +3586,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_INFO(priv, "Start UP work.\n"); - if (test_bit(STATUS_IN_SUSPEND, &priv->status)) - return 0; - /* Wait for START_ALIVE from ucode. Otherwise callbacks from * mac80211 will not be run successfully. */ ret = wait_event_interruptible_timeout(priv->wait_command_queue, @@ -5233,43 +5224,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) ieee80211_free_hw(priv->hw); } -#ifdef CONFIG_PM - -static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - - if (priv->is_open) { - set_bit(STATUS_IN_SUSPEND, &priv->status); - iwl3945_mac_stop(priv->hw); - priv->is_open = 1; - } - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int iwl3945_pci_resume(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); - - if (priv->is_open) - iwl3945_mac_start(priv->hw); - - clear_bit(STATUS_IN_SUSPEND, &priv->status); - return 0; -} - -#endif /* CONFIG_PM */ /***************************************************************************** * @@ -5283,8 +5237,8 @@ static struct pci_driver iwl3945_driver = { .probe = iwl3945_pci_probe, .remove = __devexit_p(iwl3945_pci_remove), #ifdef CONFIG_PM - .suspend = iwl3945_pci_suspend, - .resume = iwl3945_pci_resume, + .suspend = iwl_pci_suspend, + .resume = iwl_pci_resume, #endif }; -- cgit v1.2.3 From 488829f1b141858944a24fd793220fa1d52cd9a6 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Thu, 26 Mar 2009 10:14:10 -0700 Subject: iwl3945: use iwl_mac_conf_tx 3945 now uses iwl_mac_conf_tx. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 43 -------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 43 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 48 +---------------------------- 4 files changed, 46 insertions(+), 90 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2cb073efb95d..1f5ee55778f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2628,49 +2628,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - int q; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); - return 0; - } - - q = AC_NUM - 1 - queue; - - spin_lock_irqsave(&priv->lock, flags); - - priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->txop * 32)); - - priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; - priv->qos_data.qos_active = 1; - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_activate_qos(priv, 1); - else if (priv->assoc_id && iwl_is_associated(priv)) - iwl_activate_qos(priv, 0); - - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2e44d6e19e2b..7609bfced10f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2112,6 +2112,49 @@ void iwl_rx_reply_error(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_reply_error); +int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + int q; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + if (queue >= AC_NUM) { + IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); + return 0; + } + + q = AC_NUM - 1 - queue; + + spin_lock_irqsave(&priv->lock, flags); + + priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); + priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); + priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; + priv->qos_data.def_qos_parm.ac[q].edca_txop = + cpu_to_le16((params->txop * 32)); + + priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; + priv->qos_data.qos_active = 1; + + if (priv->iw_mode == NL80211_IFTYPE_AP) + iwl_activate_qos(priv, 1); + else if (priv->assoc_id && iwl_is_associated(priv)) + iwl_activate_qos(priv, 0); + + spin_unlock_irqrestore(&priv->lock, flags); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + return 0; +} +EXPORT_SYMBOL(iwl_mac_conf_tx); #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5d4904584686..d56edcd97aa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -225,6 +225,8 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, void iwl_hw_detect(struct iwl_priv *priv); void iwl_reset_qos(struct iwl_priv *priv); void iwl_activate_qos(struct iwl_priv *priv, u8 force); +int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params); void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); int iwl_check_rxon_cmd(struct iwl_priv *priv); int iwl_full_rxon_required(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index afb838b39a6c..ed31030c7643 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4100,52 +4100,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - int q; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); - return 0; - } - - q = AC_NUM - 1 - queue; - - spin_lock_irqsave(&priv->lock, flags); - - priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->txop * 32)); - - priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; - priv->qos_data.qos_active = 1; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_activate_qos(priv, 1); - else if (priv->assoc_id && iwl_is_associated(priv)) - iwl_activate_qos(priv, 0); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats) { @@ -4809,7 +4763,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, .get_tx_stats = iwl3945_mac_get_tx_stats, - .conf_tx = iwl3945_mac_conf_tx, + .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl3945_mac_reset_tsf, .bss_info_changed = iwl3945_bss_info_changed, .hw_scan = iwl_mac_hw_scan -- cgit v1.2.3 From 9f201a87831af9458df1eda65941c955f2da87ed Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 27 Mar 2009 07:50:53 +0300 Subject: p54spi: compensate firmware alignment bug in p54spi_rx Firmware may insert up to 4 padding bytes after the lmac header, but it does not amend the size of SPI data transfer. Such packets has correct data size in header, thus referencing past the end of allocated skb. Put extra 4 bytes to the end of the received skb to compensate for this case. Signed-off-by: Max Filippov Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index f8af09610180..52023127cf37 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -395,7 +395,12 @@ static int p54spi_rx(struct p54s_priv *priv) return 0; } - skb = dev_alloc_skb(len); + + /* Firmware may insert up to 4 padding bytes after the lmac header, + * but it does not amend the size of SPI data transfer. + * Such packets has correct data size in header, thus referencing + * past the end of allocated skb. Reserve extra 4 bytes for this case */ + skb = dev_alloc_skb(len + 4); if (!skb) { dev_err(&priv->spi->dev, "could not alloc skb"); return 0; @@ -403,6 +408,9 @@ static int p54spi_rx(struct p54s_priv *priv) p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); p54spi_sleep(priv); + /* Put additional bytes to compensate for the possible + * alignment-caused truncation */ + skb_put(skb, 4); if (p54_rx(priv->hw, skb) == 0) dev_kfree_skb(skb); -- cgit v1.2.3 From b0741a1a2b00d9b4d88ba60016c88e42f176e4d6 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 27 Mar 2009 13:08:45 +0530 Subject: mac80211: Don't access managed mode bits in non-managed mode This fixes a stupid bug introduced in 25f85c31d4f.. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- net/mac80211/wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 959aa8379ccf..a52fb3a4a455 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -675,7 +675,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, !sdata->default_key, keybuf, erq->length); - if (!ret) { + if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) { if (remove) sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED; else -- cgit v1.2.3 From f4a11bb0c2d5968ea35f95bdbabdd453862f202a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Mar 2009 12:40:28 +0100 Subject: nl80211: validate some input better This patch changes nl80211 to: * validate that any IE input is a valid IE (stream) * move some validation code before locking * require that a reason code is given for both deauth/disassoc Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 114 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2456e4ee445e..2f449ddcbc72 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -118,6 +118,36 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, }; +/* IE validation */ +static bool is_valid_ie_attr(const struct nlattr *attr) +{ + const u8 *pos; + int len; + + if (!attr) + return true; + + pos = nla_data(attr); + len = nla_len(attr); + + while (len) { + u8 elemlen; + + if (len < 2) + return false; + len -= 2; + + elemlen = pos[1]; + if (elemlen > len) + return false; + + len -= elemlen; + pos += 2 + elemlen; + } + + return true; +} + /* message building helper */ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, int flags, u8 cmd) @@ -1069,6 +1099,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) struct beacon_parameters params; int haveinfo = 0; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2442,6 +2475,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) enum ieee80211_band band; size_t ie_len; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2710,6 +2746,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2731,11 +2773,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC]) { - err = -EINVAL; - goto out; - } - wiphy = &drv->wiphy; memset(&req, 0, sizeof(req)); @@ -2788,6 +2825,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC] || + !info->attrs[NL80211_ATTR_SSID]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2809,12 +2853,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC] || - !info->attrs[NL80211_ATTR_SSID]) { - err = -EINVAL; - goto out; - } - wiphy = &drv->wiphy; memset(&req, 0, sizeof(req)); @@ -2856,6 +2894,15 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_REASON_CODE]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2877,24 +2924,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC]) { - err = -EINVAL; - goto out; - } - wiphy = &drv->wiphy; memset(&req, 0, sizeof(req)); req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); - if (info->attrs[NL80211_ATTR_REASON_CODE]) { - req.reason_code = - nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); - if (req.reason_code == 0) { - /* Reason Code 0 is reserved */ - err = -EINVAL; - goto out; - } + req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + if (req.reason_code == 0) { + /* Reason Code 0 is reserved */ + err = -EINVAL; + goto out; } if (info->attrs[NL80211_ATTR_IE]) { @@ -2920,6 +2959,15 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_REASON_CODE]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2941,24 +2989,16 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) goto out; } - if (!info->attrs[NL80211_ATTR_MAC]) { - err = -EINVAL; - goto out; - } - wiphy = &drv->wiphy; memset(&req, 0, sizeof(req)); req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); - if (info->attrs[NL80211_ATTR_REASON_CODE]) { - req.reason_code = - nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); - if (req.reason_code == 0) { - /* Reason Code 0 is reserved */ - err = -EINVAL; - goto out; - } + req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]); + if (req.reason_code == 0) { + /* Reason Code 0 is reserved */ + err = -EINVAL; + goto out; } if (info->attrs[NL80211_ATTR_IE]) { -- cgit v1.2.3 From c1c6b14b22af0f85d05a70405dc3fba5de840c7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Mar 2009 11:32:46 +0200 Subject: rfkill: remove deprecated state constants I only did superficial review, but these constants are stupid to have and without proper warnings nobody will review the code anyway, no amount of shouting will help. Also fix wimax to use correct states. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- arch/arm/mach-pxa/tosa-bt.c | 4 ++-- drivers/net/usb/hso.c | 4 ++-- include/linux/rfkill.h | 8 -------- net/wimax/op-rfkill.c | 8 ++++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c index fb0294bd4310..bde42aa29374 100644 --- a/arch/arm/mach-pxa/tosa-bt.c +++ b/arch/arm/mach-pxa/tosa-bt.c @@ -38,9 +38,9 @@ static void tosa_bt_off(struct tosa_bt_data *data) static int tosa_bt_toggle_radio(void *data, enum rfkill_state state) { pr_info("BT_RADIO going: %s\n", - state == RFKILL_STATE_ON ? "on" : "off"); + state == RFKILL_STATE_UNBLOCKED ? "on" : "off"); - if (state == RFKILL_STATE_ON) { + if (state == RFKILL_STATE_UNBLOCKED) { pr_info("TOSA_BT: going ON\n"); tosa_bt_on(data); } else { diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index f84b78d94c40..d696e5fbc176 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2484,7 +2484,7 @@ static int add_net_device(struct hso_device *hso_dev) static int hso_radio_toggle(void *data, enum rfkill_state state) { struct hso_device *hso_dev = data; - int enabled = (state == RFKILL_STATE_ON); + int enabled = (state == RFKILL_STATE_UNBLOCKED); int rv; mutex_lock(&hso_dev->mutex); @@ -2522,7 +2522,7 @@ static void hso_create_rfkill(struct hso_device *hso_dev, snprintf(rfkn, 20, "hso-%d", interface->altsetting->desc.bInterfaceNumber); hso_net->rfkill->name = rfkn; - hso_net->rfkill->state = RFKILL_STATE_ON; + hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED; hso_net->rfkill->data = hso_dev; hso_net->rfkill->toggle_radio = hso_radio_toggle; if (rfkill_register(hso_net->rfkill) < 0) { diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 164332cbb77c..e1ec7d9aa49c 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -52,14 +52,6 @@ enum rfkill_state { RFKILL_STATE_MAX, /* marker for last valid state */ }; -/* - * These are DEPRECATED, drivers using them should be verified to - * comply with the rfkill usage guidelines in Documentation/rfkill.txt - * and then converted to use the new names for rfkill_state - */ -#define RFKILL_STATE_OFF RFKILL_STATE_SOFT_BLOCKED -#define RFKILL_STATE_ON RFKILL_STATE_UNBLOCKED - /** * struct rfkill - rfkill control structure. * @name: Name of the switch. diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c index 2b75aee04217..870032faece2 100644 --- a/net/wimax/op-rfkill.c +++ b/net/wimax/op-rfkill.c @@ -113,7 +113,7 @@ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev, if (state != wimax_dev->rf_hw) { wimax_dev->rf_hw = state; rfkill_state = state == WIMAX_RF_ON ? - RFKILL_STATE_OFF : RFKILL_STATE_ON; + RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; if (wimax_dev->rf_hw == WIMAX_RF_ON && wimax_dev->rf_sw == WIMAX_RF_ON) wimax_state = WIMAX_ST_READY; @@ -259,10 +259,10 @@ int wimax_rfkill_toggle_radio(void *data, enum rfkill_state state) d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); switch (state) { - case RFKILL_STATE_ON: + case RFKILL_STATE_SOFT_BLOCKED: rf_state = WIMAX_RF_OFF; break; - case RFKILL_STATE_OFF: + case RFKILL_STATE_UNBLOCKED: rf_state = WIMAX_RF_ON; break; default: @@ -361,7 +361,7 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev) wimax_dev->rfkill = rfkill; rfkill->name = wimax_dev->name; - rfkill->state = RFKILL_STATE_OFF; + rfkill->state = RFKILL_STATE_UNBLOCKED; rfkill->data = wimax_dev; rfkill->toggle_radio = wimax_rfkill_toggle_radio; rfkill->user_claim_unsupported = 1; -- cgit v1.2.3 From 621cac85297de5ba655e3430b007dd2e0da91da6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Mar 2009 14:14:31 +0100 Subject: rfkill: remove user_claim stuff Almost all drivers do not support user_claim, so remove it completely and always report -EOPNOTSUPP to userspace. Since userspace cannot really drive rfkill _anyway_ (due to the odd restrictions imposed by the documentation) having this code is just pointless. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/rfkill.txt | 16 +++++------ drivers/net/wireless/ath9k/main.c | 1 - drivers/net/wireless/b43/rfkill.c | 1 - drivers/net/wireless/b43legacy/rfkill.c | 1 - drivers/net/wireless/iwlwifi/iwl-rfkill.c | 1 - drivers/platform/x86/acer-wmi.c | 1 - drivers/platform/x86/hp-wmi.c | 3 --- drivers/platform/x86/sony-laptop.c | 4 --- drivers/platform/x86/toshiba_acpi.c | 1 - include/linux/rfkill.h | 6 ----- net/rfkill/rfkill.c | 45 +++---------------------------- net/wimax/op-rfkill.c | 1 - 12 files changed, 9 insertions(+), 72 deletions(-) diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index 4d3ee317a4a3..40c3a3f10816 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt @@ -521,16 +521,12 @@ status of the system. Input devices may issue events that are related to rfkill. These are the various KEY_* events and SW_* events supported by rfkill-input.c. -******IMPORTANT****** -When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL -SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it -has set to true the user_claim attribute for that particular switch. This rule -is *absolute*; do NOT violate it. -******IMPORTANT****** - -Userspace must not assume it is the only source of control for rfkill switches. -Their state CAN and WILL change due to firmware actions, direct user actions, -and the rfkill-input EPO override for *_RFKILL_ALL. +Userspace may not change the state of an rfkill switch in response to an +input event, it should refrain from changing states entirely. + +Userspace cannot assume it is the only source of control for rfkill switches. +Their state can change due to firmware actions, direct user actions, and the +rfkill-input EPO override for *_RFKILL_ALL. When rfkill-input is not active, userspace must initiate a rfkill status change by writing to the "state" attribute in order for anything to happen. diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 13d4e6756c99..0607df20e497 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1267,7 +1267,6 @@ static int ath_init_sw_rfkill(struct ath_softc *sc) sc->rf_kill.rfkill->data = sc; sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED; - sc->rf_kill.rfkill->user_claim_unsupported = 1; return 0; } diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index afad42358693..9e1d00bc24d3 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -139,7 +139,6 @@ void b43_rfkill_init(struct b43_wldev *dev) rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; rfk->rfkill->data = dev; rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; - rfk->rfkill->user_claim_unsupported = 1; rfk->poll_dev = input_allocate_polled_device(); if (!rfk->poll_dev) { diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index b32bf6a94f19..4b0c7d27a51f 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -142,7 +142,6 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev) rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; rfk->rfkill->data = dev; rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; - rfk->rfkill->user_claim_unsupported = 1; rfk->poll_dev = input_allocate_polled_device(); if (!rfk->poll_dev) { diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 2ad9faf1508a..65605ad44e4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -91,7 +91,6 @@ int iwl_rfkill_init(struct iwl_priv *priv) priv->rfkill->data = priv; priv->rfkill->state = RFKILL_STATE_UNBLOCKED; priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; - priv->rfkill->user_claim_unsupported = 1; priv->rfkill->dev.class->suspend = NULL; priv->rfkill->dev.class->resume = NULL; diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 0f6e43bf4fc2..62d02b3c998e 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1005,7 +1005,6 @@ enum rfkill_type type, char *name, u32 cap) *data = cap; rfkill_dev->data = data; rfkill_dev->toggle_radio = acer_rfkill_set; - rfkill_dev->user_claim_unsupported = 1; err = rfkill_register(rfkill_dev); if (err) { diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 50d9019de2be..fe171fad12cf 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -434,7 +434,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) wifi_rfkill->name = "hp-wifi"; wifi_rfkill->state = hp_wmi_wifi_state(); wifi_rfkill->toggle_radio = hp_wmi_wifi_set; - wifi_rfkill->user_claim_unsupported = 1; err = rfkill_register(wifi_rfkill); if (err) goto add_sysfs_error; @@ -446,7 +445,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) bluetooth_rfkill->name = "hp-bluetooth"; bluetooth_rfkill->state = hp_wmi_bluetooth_state(); bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set; - bluetooth_rfkill->user_claim_unsupported = 1; err = rfkill_register(bluetooth_rfkill); if (err) goto register_bluetooth_error; @@ -457,7 +455,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) wwan_rfkill->name = "hp-wwan"; wwan_rfkill->state = hp_wmi_wwan_state(); wwan_rfkill->toggle_radio = hp_wmi_wwan_set; - wwan_rfkill->user_claim_unsupported = 1; err = rfkill_register(wwan_rfkill); if (err) goto register_wwan_err; diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index d3c92d777bde..184e99e72684 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1097,7 +1097,6 @@ static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) sony_wifi_rfkill->name = "sony-wifi"; sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wifi_rfkill->get_state = sony_nc_rfkill_get; - sony_wifi_rfkill->user_claim_unsupported = 1; sony_wifi_rfkill->data = (void *)SONY_WIFI; err = rfkill_register(sony_wifi_rfkill); if (err) @@ -1119,7 +1118,6 @@ static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) sony_bluetooth_rfkill->name = "sony-bluetooth"; sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; - sony_bluetooth_rfkill->user_claim_unsupported = 1; sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; err = rfkill_register(sony_bluetooth_rfkill); if (err) @@ -1140,7 +1138,6 @@ static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) sony_wwan_rfkill->name = "sony-wwan"; sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wwan_rfkill->get_state = sony_nc_rfkill_get; - sony_wwan_rfkill->user_claim_unsupported = 1; sony_wwan_rfkill->data = (void *)SONY_WWAN; err = rfkill_register(sony_wwan_rfkill); if (err) @@ -1161,7 +1158,6 @@ static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) sony_wimax_rfkill->name = "sony-wimax"; sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wimax_rfkill->get_state = sony_nc_rfkill_get; - sony_wimax_rfkill->user_claim_unsupported = 1; sony_wimax_rfkill->data = (void *)SONY_WIMAX; err = rfkill_register(sony_wimax_rfkill); if (err) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 9f187265db8e..4345089f5171 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -803,7 +803,6 @@ static int __init toshiba_acpi_init(void) toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name; toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio; - toshiba_acpi.rfk_dev->user_claim_unsupported = 1; toshiba_acpi.rfk_dev->data = &toshiba_acpi; if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) { diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index e1ec7d9aa49c..de18ef227e00 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -58,9 +58,6 @@ enum rfkill_state { * @type: Radio type which the button controls, the value stored * here should be a value from enum rfkill_type. * @state: State of the switch, "UNBLOCKED" means radio can operate. - * @user_claim_unsupported: Whether the hardware supports exclusive - * RF-kill control by userspace. Set this before registering. - * @user_claim: Set when the switch is controlled exlusively by userspace. * @mutex: Guards switch state transitions. It serializes callbacks * and also protects the state. * @data: Pointer to the RF button drivers private data which will be @@ -83,9 +80,6 @@ struct rfkill { const char *name; enum rfkill_type type; - bool user_claim_unsupported; - bool user_claim; - /* the mutex serializes callbacks and also protects * the state */ struct mutex mutex; diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 3eaa39403c13..df1269c5ca70 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -200,7 +200,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, rfkill_global_states[type].current_state = state; list_for_each_entry(rfkill, &rfkill_list, node) { - if ((!rfkill->user_claim) && (rfkill->type == type)) { + if (rfkill->type == type) { mutex_lock(&rfkill->mutex); rfkill_toggle_radio(rfkill, state, 0); mutex_unlock(&rfkill->mutex); @@ -447,53 +447,14 @@ static ssize_t rfkill_claim_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct rfkill *rfkill = to_rfkill(dev); - - return sprintf(buf, "%d\n", rfkill->user_claim); + return sprintf(buf, "%d\n", 0); } static ssize_t rfkill_claim_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct rfkill *rfkill = to_rfkill(dev); - unsigned long claim_tmp; - bool claim; - int error; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (rfkill->user_claim_unsupported) - return -EOPNOTSUPP; - - error = strict_strtoul(buf, 0, &claim_tmp); - if (error) - return error; - claim = !!claim_tmp; - - /* - * Take the global lock to make sure the kernel is not in - * the middle of rfkill_switch_all - */ - error = mutex_lock_killable(&rfkill_global_mutex); - if (error) - return error; - - if (rfkill->user_claim != claim) { - if (!claim && !rfkill_epo_lock_active) { - mutex_lock(&rfkill->mutex); - rfkill_toggle_radio(rfkill, - rfkill_global_states[rfkill->type].current_state, - 0); - mutex_unlock(&rfkill->mutex); - } - rfkill->user_claim = claim; - } - - mutex_unlock(&rfkill_global_mutex); - - return error ? error : count; + return -EOPNOTSUPP; } static struct device_attribute rfkill_dev_attrs[] = { diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c index 870032faece2..a3616e2ccb8a 100644 --- a/net/wimax/op-rfkill.c +++ b/net/wimax/op-rfkill.c @@ -364,7 +364,6 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev) rfkill->state = RFKILL_STATE_UNBLOCKED; rfkill->data = wimax_dev; rfkill->toggle_radio = wimax_rfkill_toggle_radio; - rfkill->user_claim_unsupported = 1; /* Initialize the input device for the hw key */ input_dev = input_allocate_device(); -- cgit v1.2.3 From fd7fbb17bec7b055fafec4d0ae3bfb4ed60cad8b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 27 Mar 2009 14:16:44 +0100 Subject: rfkill-input: remove unused code There's a lot of rfkill-input code that cannot ever be compiled and is useless until somebody needs and tests it -- therefore remove it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/rfkill/rfkill-input.c | 69 ----------------------------------------------- 1 file changed, 69 deletions(-) diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index 84efde97c5a7..60a34f3b5f65 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c @@ -47,12 +47,6 @@ enum rfkill_global_sched_op { RFKILL_GLOBAL_OP_UNBLOCK, }; -/* - * Currently, the code marked with RFKILL_NEED_SWSET is inactive. - * If handling of EV_SW SW_WLAN/WWAN/BLUETOOTH/etc is needed in the - * future, when such events are added, that code will be necessary. - */ - struct rfkill_task { struct delayed_work dwork; @@ -65,14 +59,6 @@ struct rfkill_task { /* pending regular switch operations (1=pending) */ unsigned long sw_pending[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; -#ifdef RFKILL_NEED_SWSET - /* set operation pending (1=pending) */ - unsigned long sw_setpending[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; - - /* desired state for pending set operation (1=unblock) */ - unsigned long sw_newstate[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; -#endif - /* should the state be complemented (1=yes) */ unsigned long sw_togglestate[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; @@ -111,24 +97,6 @@ static void __rfkill_handle_global_op(enum rfkill_global_sched_op op) } } -#ifdef RFKILL_NEED_SWSET -static void __rfkill_handle_normal_op(const enum rfkill_type type, - const bool sp, const bool s, const bool c) -{ - enum rfkill_state state; - - if (sp) - state = (s) ? RFKILL_STATE_UNBLOCKED : - RFKILL_STATE_SOFT_BLOCKED; - else - state = rfkill_get_global_state(type); - - if (c) - state = rfkill_state_complement(state); - - rfkill_switch_all(type, state); -} -#else static void __rfkill_handle_normal_op(const enum rfkill_type type, const bool c) { @@ -140,7 +108,6 @@ static void __rfkill_handle_normal_op(const enum rfkill_type type, rfkill_switch_all(type, state); } -#endif static void rfkill_task_handler(struct work_struct *work) { @@ -171,21 +138,11 @@ static void rfkill_task_handler(struct work_struct *work) i < RFKILL_TYPE_MAX) { if (test_and_clear_bit(i, task->sw_pending)) { bool c; -#ifdef RFKILL_NEED_SWSET - bool sp, s; - sp = test_and_clear_bit(i, - task->sw_setpending); - s = test_bit(i, task->sw_newstate); -#endif c = test_and_clear_bit(i, task->sw_togglestate); spin_unlock_irq(&task->lock); -#ifdef RFKILL_NEED_SWSET - __rfkill_handle_normal_op(i, sp, s, c); -#else __rfkill_handle_normal_op(i, c); -#endif spin_lock_irq(&task->lock); } @@ -238,32 +195,6 @@ static void rfkill_schedule_global_op(enum rfkill_global_sched_op op) spin_unlock_irqrestore(&rfkill_task.lock, flags); } -#ifdef RFKILL_NEED_SWSET -/* Use this if you need to add EV_SW SW_WLAN/WWAN/BLUETOOTH/etc handling */ - -static void rfkill_schedule_set(enum rfkill_type type, - enum rfkill_state desired_state) -{ - unsigned long flags; - - if (rfkill_is_epo_lock_active()) - return; - - spin_lock_irqsave(&rfkill_task.lock, flags); - if (!rfkill_task.global_op_pending) { - set_bit(type, rfkill_task.sw_pending); - set_bit(type, rfkill_task.sw_setpending); - clear_bit(type, rfkill_task.sw_togglestate); - if (desired_state) - set_bit(type, rfkill_task.sw_newstate); - else - clear_bit(type, rfkill_task.sw_newstate); - rfkill_schedule_ratelimited(); - } - spin_unlock_irqrestore(&rfkill_task.lock, flags); -} -#endif - static void rfkill_schedule_toggle(enum rfkill_type type) { unsigned long flags; -- cgit v1.2.3 From 07f62d01c1f476a3b328a44faafdfd103a4dedc3 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 27 Mar 2009 22:20:27 +0800 Subject: cfg80211: remove duplicated #include Remove duplicated #include in include/net/cfg80211.h. Signed-off-by: Huang Weiyi Signed-off-by: John W. Linville --- include/net/cfg80211.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5389afdc1297..d1b8f0d53c57 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -10,7 +10,6 @@ #include #include /* remove once we remove the wext stuff */ -#include /* * 802.11 configuration in-kernel interface -- cgit v1.2.3 From c0ed418977edf60f1df9933e1ccd48920a28eb66 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 27 Mar 2009 22:21:36 +0800 Subject: nl80211: remove duplicated #include Remove duplicated #include in net/wireless/core.h. Signed-off-by: Huang Weiyi Signed-off-by: John W. Linville --- net/wireless/core.h | 1 - 1 file changed, 1 deletion(-) diff --git a/net/wireless/core.h b/net/wireless/core.h index 0a592e4295f0..fcee83a0c9bb 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 1778092e1739155acec35a3bccee2fb8a1ae4e91 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2009 20:52:47 +0200 Subject: nl80211: Require auth type for NL80211_CMD_AUTHENTICATE NL80211_ATTR_AUTH_TYPE is a required parameter for NL80211_CMD_AUTHENTICATE. We are currently (by chance) defaulting to open system authentication if the attribute is not specified. It is better to just reject the invalid command. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2f449ddcbc72..c04df6a6af78 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2752,6 +2752,9 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_MAC]) return -EINVAL; + if (!info->attrs[NL80211_ATTR_AUTH_TYPE]) + return -EINVAL; + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -2798,13 +2801,10 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } - if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { - req.auth_type = - nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); - if (!nl80211_valid_auth_type(req.auth_type)) { - err = -EINVAL; - goto out; - } + req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]); + if (!nl80211_valid_auth_type(req.auth_type)) { + err = -EINVAL; + goto out; } err = drv->ops->auth(&drv->wiphy, dev, &req); -- cgit v1.2.3 From 53b46b8444f600cc1744521ea096ea0c5d494dd0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2009 20:53:56 +0200 Subject: nl80211: Generate deauth/disassoc event for locally generated frames Previously, nl80211 mlme events were generated only for received deauthentication and disassociation frames. We need to do the same for locally generated ones in order to let applications know that we disconnected (e.g., when AP does not reply to a probe). Rename the nl80211 and cfg80211 functions (s/rx_//) to make it clearer that they are used for both received and locally generated frames. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/net/cfg80211.h | 16 ++++++++-------- net/mac80211/mlme.c | 8 ++++++-- net/wireless/mlme.c | 13 ++++++------- net/wireless/nl80211.c | 11 +++++------ net/wireless/nl80211.h | 12 ++++++------ 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d1b8f0d53c57..ec33096fc655 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -917,28 +917,28 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len); /** - * cfg80211_send_rx_deauth - notification of processed deauthentication + * cfg80211_send_deauth - notification of processed deauthentication * @dev: network device * @buf: deauthentication frame (header + body) * @len: length of the frame data * * This function is called whenever deauthentication has been processed in - * station mode. + * station mode. This includes both received deauthentication frames and + * locally generated ones. */ -void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, - size_t len); +void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); /** - * cfg80211_send_rx_disassoc - notification of processed disassociation + * cfg80211_send_disassoc - notification of processed disassociation * @dev: network device * @buf: disassociation response frame (header + body) * @len: length of the frame data * * This function is called whenever disassociation has been processed in - * station mode. + * station mode. This includes both received disassociation frames and locally + * generated ones. */ -void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, - size_t len); +void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len); /** * cfg80211_hold_bss - exclude bss from expiration diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 132938b073dc..08db02c237c9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -325,6 +325,10 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* u.deauth.reason_code == u.disassoc.reason_code */ mgmt->u.deauth.reason_code = cpu_to_le16(reason); + if (stype == IEEE80211_STYPE_DEAUTH) + cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len); + else + cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len); ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED); } @@ -1187,7 +1191,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, true, false, 0); ifmgd->flags &= ~IEEE80211_STA_AUTHENTICATED; - cfg80211_send_rx_deauth(sdata->dev, (u8 *) mgmt, len); + cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, len); } @@ -1218,7 +1222,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, } ieee80211_set_disassoc(sdata, false, false, reason_code); - cfg80211_send_rx_disassoc(sdata->dev, (u8 *) mgmt, len); + cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, len); } diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index bec5721b6f99..33ff7cca496b 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -28,19 +28,18 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) } EXPORT_SYMBOL(cfg80211_send_rx_assoc); -void cfg80211_send_rx_deauth(struct net_device *dev, const u8 *buf, size_t len) +void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) { struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - nl80211_send_rx_deauth(rdev, dev, buf, len); + nl80211_send_deauth(rdev, dev, buf, len); } -EXPORT_SYMBOL(cfg80211_send_rx_deauth); +EXPORT_SYMBOL(cfg80211_send_deauth); -void cfg80211_send_rx_disassoc(struct net_device *dev, const u8 *buf, - size_t len) +void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) { struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - nl80211_send_rx_disassoc(rdev, dev, buf, len); + nl80211_send_disassoc(rdev, dev, buf, len); } -EXPORT_SYMBOL(cfg80211_send_rx_disassoc); +EXPORT_SYMBOL(cfg80211_send_disassoc); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c04df6a6af78..195424eee77d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3415,17 +3415,16 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_ASSOCIATE); } -void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *buf, - size_t len) +void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, size_t len) { nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_DEAUTHENTICATE); } -void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *netdev, const u8 *buf, - size_t len) +void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *buf, + size_t len) { nl80211_send_mlme_event(rdev, netdev, buf, len, NL80211_CMD_DISASSOCIATE); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b77af4ab80be..55686fc264f0 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -17,11 +17,11 @@ extern void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, extern void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *buf, size_t len); -extern void nl80211_send_rx_deauth(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - const u8 *buf, size_t len); -extern void nl80211_send_rx_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *netdev, - const u8 *buf, size_t len); +extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len); +extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *buf, size_t len); #endif /* __NET_WIRELESS_NL80211_H */ -- cgit v1.2.3 From a3b8b0569fbef725597f05278ec58083321f6e9d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2009 21:59:49 +0200 Subject: nl80211: Add Michael MIC failure event Define a new nl80211 event, NL80211_CMD_MICHAEL_MIC_FAILURE, to be used to notify user space about locally detected Michael MIC failures. This matches with the MLME-MICHAELMICFAILURE.indication() primitive. Since we do not actually have TSC in the skb anymore when mac80211_ev_michael_mic_failure() is called, that function is changed to take in the TSC as an optional parameter instead of as a requirement to include the TSC after the hdr field (which we did not really follow). For now, TSC is not included in the events from mac80211, but it could be added at some point. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 28 ++++++++++++++++++++++++++++ include/net/cfg80211.h | 16 ++++++++++++++++ net/mac80211/event.c | 17 +++++++++-------- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/rx.c | 2 +- net/mac80211/wpa.c | 2 +- net/wireless/mlme.c | 10 ++++++++++ net/wireless/nl80211.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 5 +++++ 9 files changed, 111 insertions(+), 11 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index cbe8ce3bf486..27f230f063b3 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -199,6 +199,14 @@ * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). * + * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael + * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the + * event includes %NL80211_ATTR_MAC to describe the source MAC address of + * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key + * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and + * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this + * event matches with MLME-MICHAELMICFAILURE.indication() primitive + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -260,6 +268,8 @@ enum nl80211_commands { NL80211_CMD_DEAUTHENTICATE, NL80211_CMD_DISASSOCIATE, + NL80211_CMD_MICHAEL_MIC_FAILURE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -408,6 +418,9 @@ enum nl80211_commands { * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and * %NL80211_CMD_DISASSOCIATE, u16 * + * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as + * a u32 + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -492,6 +505,8 @@ enum nl80211_attrs { NL80211_ATTR_AUTH_TYPE, NL80211_ATTR_REASON_CODE, + NL80211_ATTR_KEY_TYPE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1062,4 +1077,17 @@ enum nl80211_auth_type { NL80211_AUTHTYPE_FT, NL80211_AUTHTYPE_NETWORK_EAP, }; + +/** + * enum nl80211_key_type - Key Type + * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key + * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key + * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) + */ +enum nl80211_key_type { + NL80211_KEYTYPE_GROUP, + NL80211_KEYTYPE_PAIRWISE, + NL80211_KEYTYPE_PEERKEY, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ec33096fc655..f8bf0c86650b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -957,4 +957,20 @@ void cfg80211_hold_bss(struct cfg80211_bss *bss); */ void cfg80211_unhold_bss(struct cfg80211_bss *bss); +/** + * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP) + * @dev: network device + * @addr: The source MAC address of the frame + * @key_type: The key type that the received frame used + * @key_id: Key identifier (0..3) + * @tsc: The TSC value of the frame that generated the MIC failure (6 octets) + * + * This function is called whenever the local MAC detects a MIC failure in a + * received frame. This matches with MLME-MICHAELMICFAILURE.indication() + * primitive. + */ +void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, + enum nl80211_key_type key_type, int key_id, + const u8 *tsc); + #endif /* __NET_CFG80211_H */ diff --git a/net/mac80211/event.c b/net/mac80211/event.c index 0d95561c0ee0..f288d01a6344 100644 --- a/net/mac80211/event.c +++ b/net/mac80211/event.c @@ -12,12 +12,12 @@ #include "ieee80211_i.h" /* - * indicate a failed Michael MIC to userspace; the passed packet - * (in the variable hdr) must be long enough to extract the TKIP - * fields like TSC + * Indicate a failed Michael MIC to userspace. If the caller knows the TSC of + * the frame that generated the MIC failure (i.e., if it was provided by the + * driver or is still in the frame), it should provide that information. */ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, - struct ieee80211_hdr *hdr) + struct ieee80211_hdr *hdr, const u8 *tsc) { union iwreq_data wrqu; char *buf = kmalloc(128, GFP_ATOMIC); @@ -34,8 +34,9 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke kfree(buf); } - /* - * TODO: re-add support for sending MIC failure indication - * with all info via nl80211 - */ + cfg80211_michael_mic_failure(sdata->dev, hdr->addr2, + (hdr->addr1[0] & 0x01) ? + NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE, + keyidx, tsc); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e6ed78cb16b3..312347d102c8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1060,7 +1060,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, int rate, int erp, int short_preamble); void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, - struct ieee80211_hdr *hdr); + struct ieee80211_hdr *hdr, const u8 *tsc); void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5fa7aedd90ed..19c4b4589fee 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1932,7 +1932,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, !ieee80211_is_auth(hdr->frame_control)) goto ignore; - mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); + mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL); ignore: dev_kfree_skb(rx->skb); rx->skb = NULL; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 4f8bfea278f2..dcfae8884b86 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -122,7 +122,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, - (void *) skb->data); + (void *) skb->data, NULL); return RX_DROP_UNUSABLE; } diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 33ff7cca496b..1407244a647e 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -43,3 +43,13 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) nl80211_send_disassoc(rdev, dev, buf, len); } EXPORT_SYMBOL(cfg80211_send_disassoc); + +void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, + enum nl80211_key_type key_type, int key_id, + const u8 *tsc) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_michael_mic_failure(rdev, dev, addr, key_type, key_id, tsc); +} +EXPORT_SYMBOL(cfg80211_michael_mic_failure); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 195424eee77d..1394115cde95 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3430,6 +3430,46 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, NL80211_CMD_DISASSOCIATE); } +void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *addr, + enum nl80211_key_type key_type, int key_id, + const u8 *tsc) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_MICHAEL_MIC_FAILURE); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + if (addr) + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, key_type); + NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_id); + if (tsc) + NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + /* initialisation/exit functions */ int nl80211_init(void) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 55686fc264f0..e4b92cccd157 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -23,5 +23,10 @@ extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev, extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *buf, size_t len); +extern void +nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *addr, + enum nl80211_key_type key_type, + int key_id, const u8 *tsc); #endif /* __NET_WIRELESS_NL80211_H */ -- cgit v1.2.3 From 295936c56672e82369c6d989e27d3a87495808e4 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 27 Mar 2009 17:21:05 -0400 Subject: ath9k: Update maintainers for ath9k This has been the case really, we just forgot to update it. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2dc197c362b3..6dfcb6d03a97 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -888,6 +888,12 @@ P: Luis R. Rodriguez M: lrodriguez@atheros.com P: Jouni Malinen M: jmalinen@atheros.com +P: Sujith Manoharan +M: Sujith.Manoharan@atheros.com +P: Vasanthakumar Thiagarajan +M: vasanth@atheros.com +P: Senthil Balasubramanian +M: senthilkumar@atheros.com L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org S: Supported -- cgit v1.2.3 From 807e37394b5a1dc23a2908b59f34edbbae67e9ea Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 27 Mar 2009 17:47:27 -0400 Subject: ath5k: fix scanning in AR2424 AR5K_PHY_PLL_40MHZ_5413 should not be ORed with AR5K_PHY_MODE_RAD_RF5112 for 5 GHz channels. The incorrect PLL value breaks scanning in the countries where 5 GHz channels are allowed. Signed-off-by: Pavel Roskin Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index cb5e15f97095..775fdf78554b 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -358,7 +358,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) mode |= AR5K_PHY_MODE_FREQ_5GHZ; if (ah->ah_radio == AR5K_RF5413) - clock |= AR5K_PHY_PLL_40MHZ_5413; + clock = AR5K_PHY_PLL_40MHZ_5413; else clock |= AR5K_PHY_PLL_40MHZ; -- cgit v1.2.3 From 32c1628f153a5468cf48be5e5c04cd599ae9e01d Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 28 Mar 2009 01:46:14 +0100 Subject: ar9170: fix hang on stop This patch fixes a locking problem which freezes the network core. The deadlock goes as follows: - ar9170_op_stop - is called 1. change the state to IDLE 2. > take the MUTEX < 3. cancel_SYNC all pending work, which means "block until a work_struct's callback has terminated" => if filter_config_work was queued it tries to get the MUTEX, before checking the device state... Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ar9170/main.c index 5996ff9f7f47..5f55754d968f 100644 --- a/drivers/net/wireless/ar9170/main.c +++ b/drivers/net/wireless/ar9170/main.c @@ -742,8 +742,9 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) if (IS_STARTED(ar)) ar->state = AR9170_IDLE; - mutex_lock(&ar->mutex); + flush_workqueue(ar->hw->workqueue); + mutex_lock(&ar->mutex); cancel_delayed_work_sync(&ar->tx_status_janitor); cancel_work_sync(&ar->filter_config_work); cancel_work_sync(&ar->beacon_work); @@ -1123,10 +1124,10 @@ static void ar9170_set_filters(struct work_struct *work) filter_config_work); int err; - mutex_lock(&ar->mutex); if (unlikely(!IS_STARTED(ar))) - goto unlock; + return ; + mutex_lock(&ar->mutex); if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) { err = ar9170_set_operating_mode(ar); if (err) -- cgit v1.2.3 From 440ddadaee6d0d5e8a7ee53ac913f78a8e5570a1 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 28 Mar 2009 20:51:24 +0100 Subject: rt2x00: Move Move pci_dev specific access to rt2x00pci pci_dev->irq and pci_name(pci_dev) access should be limited to rt2x00pci only. This is more generic and allows a rt2x00 pci driver to be controlled as PCI device but also as platform driver (needed for rt2800pci SoC support). Signed-off-by: Felix Fietkau Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 18 ++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00pci.c | 16 ++++++++++++---- drivers/net/wireless/rt2x00/rt61pci.c | 7 +------ drivers/net/wireless/rt2x00/rt61pci.h | 6 ------ 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0f08773328c6..411eb9cbb4e5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1361,7 +1361,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2460, value, reg); + rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && !rt2x00_rf(&rt2x00dev->chip, RF2421)) { diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 276a8232aaa0..e1be67ca23d8 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1525,7 +1525,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2560, value, reg); + rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && !rt2x00_rf(&rt2x00dev->chip, RF2523) && diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 84bd6f19acb0..e03d69975ea4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -671,6 +671,12 @@ struct rt2x00_dev { */ unsigned long flags; + /* + * Device information, Bus IRQ and name (PCI, SoC) + */ + int irq; + const char *name; + /* * Chipset identification. */ @@ -860,6 +866,18 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, rt2x00dev->chip.rev = rev; } +static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev, + const u16 rt) +{ + rt2x00dev->chip.rt = rt; +} + +static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev, + const u16 rf, const u32 rev) +{ + rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev); +} + static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) { return (chipset->rt == chip); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 9730b4f8fd26..cdd5154bd4c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -170,7 +170,6 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) { - struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); struct data_queue *queue; int status; @@ -186,11 +185,11 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) /* * Register interrupt handler. */ - status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler, - IRQF_SHARED, pci_name(pci_dev), rt2x00dev); + status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler, + IRQF_SHARED, rt2x00dev->name, rt2x00dev); if (status) { ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", - pci_dev->irq, status); + rt2x00dev->irq, status); goto exit; } @@ -270,6 +269,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; + u16 chip; retval = pci_request_regions(pci_dev, pci_name(pci_dev)); if (retval) { @@ -307,6 +307,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) rt2x00dev->dev = &pci_dev->dev; rt2x00dev->ops = ops; rt2x00dev->hw = hw; + rt2x00dev->irq = pci_dev->irq; + rt2x00dev->name = pci_name(pci_dev); + + /* + * Determine RT chipset by reading PCI header. + */ + pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); + rt2x00_set_chip_rt(rt2x00dev, chip); retval = rt2x00pci_alloc_reg(rt2x00dev); if (retval) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 2ca8b7a9722c..4346cd1494bc 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2308,7 +2308,6 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) u32 reg; u16 value; u16 eeprom; - u16 device; /* * Read EEPROM word for configuration. @@ -2317,14 +2316,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify RF chipset. - * To determine the RT chip we have to read the - * PCI header of the device. */ - pci_read_config_word(to_pci_dev(rt2x00dev->dev), - PCI_CONFIG_HEADER_DEVICE, &device); value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, device, value, reg); + rt2x00_set_chip_rf(rt2x00dev, value, reg); if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && !rt2x00_rf(&rt2x00dev->chip, RF5325) && diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 41e8959919f6..6c71f77c8165 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -62,12 +62,6 @@ * PCI registers. */ -/* - * PCI Configuration Header - */ -#define PCI_CONFIG_HEADER_VENDOR 0x0000 -#define PCI_CONFIG_HEADER_DEVICE 0x0002 - /* * HOST_CMD_CSR: For HOST to interrupt embedded processor */ -- cgit v1.2.3 From a57e2e84b65d1b89c4b1effeceb27b181226b950 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 28 Mar 2009 20:51:41 +0100 Subject: rt2x00: Fix Sparse warning rt2x00link_reset_qual() is not declared in a header, and is only internally used within rt2x00link.c. It should be declared as static. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 7eb5cd7e5f32..eb9b981b9139 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -387,7 +387,7 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) rt2x00link_antenna_reset(rt2x00dev); } -void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) +static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) { struct link_qual *qual = &rt2x00dev->link.qual; -- cgit v1.2.3 From 616de35da94df8748771a014ef898360d5f4d0c8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 29 Mar 2009 13:19:31 +0200 Subject: b43: Do not "select" HW_RANDOM Auto-depend on HW_RANDOM, rather than "select"ing it. This way the user has the choice to enable or disable HWRNG support. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 8 +++++++- drivers/net/wireless/b43/b43.h | 4 +++- drivers/net/wireless/b43/main.c | 8 +++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index aab71a70ba78..21572e40b79d 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -3,7 +3,6 @@ config B43 depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA select SSB select FW_LOADER - select HW_RANDOM ---help--- b43 is a driver for the Broadcom 43xx series wireless devices. @@ -106,6 +105,13 @@ config B43_RFKILL depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43) default y +# This config option automatically enables b43 HW-RNG support, +# if the HW-RNG core is enabled. +config B43_HWRNG + bool + depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43) + default y + config B43_DEBUG bool "Broadcom 43xx debugging" depends on B43 diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index beaf18d6e8a7..cc1db7e5c664 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -625,9 +625,11 @@ struct b43_wl { /* Stats about the wireless interface */ struct ieee80211_low_level_stats ieee_stats; +#ifdef CONFIG_B43_HWRNG struct hwrng rng; - u8 rng_initialized; + bool rng_initialized; char rng_name[30 + 1]; +#endif /* CONFIG_B43_HWRNG */ /* The RF-kill button */ struct b43_rfkill rfkill; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 79b685e300c7..09e0c60d96df 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2980,6 +2980,7 @@ static void b43_security_init(struct b43_wldev *dev) b43_clear_keys(dev); } +#ifdef CONFIG_B43_HWRNG static int b43_rng_read(struct hwrng *rng, u32 *data) { struct b43_wl *wl = (struct b43_wl *)rng->priv; @@ -2995,17 +2996,21 @@ static int b43_rng_read(struct hwrng *rng, u32 *data) return (sizeof(u16)); } +#endif /* CONFIG_B43_HWRNG */ static void b43_rng_exit(struct b43_wl *wl) { +#ifdef CONFIG_B43_HWRNG if (wl->rng_initialized) hwrng_unregister(&wl->rng); +#endif /* CONFIG_B43_HWRNG */ } static int b43_rng_init(struct b43_wl *wl) { - int err; + int err = 0; +#ifdef CONFIG_B43_HWRNG snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); wl->rng.name = wl->rng_name; @@ -3018,6 +3023,7 @@ static int b43_rng_init(struct b43_wl *wl) b43err(wl, "Failed to register the random " "number generator (%d)\n", err); } +#endif /* CONFIG_B43_HWRNG */ return err; } -- cgit v1.2.3 From 8782b41d13c8e5f9a201477d3c15edf9fe7c372c Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Mon, 30 Mar 2009 14:17:00 +0530 Subject: ath9k: No need to abort Rx path when autosleep is enabled. For chipsets supporting autosleep feature, there is no need to abort Rx engine since they are capable of automatically going back to sleep after receiving a packet. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0607df20e497..97cf83fa8555 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2325,26 +2325,33 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ieee80211_conf *conf = &hw->conf; + struct ath_hw *ah = sc->sc_ah; mutex_lock(&sc->mutex); if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { - if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { - sc->imask |= ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); + if (!(ah->caps.hw_caps & + ATH9K_HW_CAP_AUTOSLEEP)) { + if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { + sc->imask |= ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } + ath9k_hw_setrxabort(sc->sc_ah, 1); } - ath9k_hw_setrxabort(sc->sc_ah, 1); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); } else { ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; - if (sc->imask & ATH9K_INT_TIM_TIMER) { - sc->imask &= ~ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); + if (!(ah->caps.hw_caps & + ATH9K_HW_CAP_AUTOSLEEP)) { + ath9k_hw_setrxabort(sc->sc_ah, 0); + sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; + if (sc->imask & ATH9K_INT_TIM_TIMER) { + sc->imask &= ~ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } } } } -- cgit v1.2.3 From bdbdf46daa6dccb472f56559854477faddc44de9 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:22 +0530 Subject: ath9k: Remove a few unused flags This patch removes unused HW capability flags and HW operation variables, and a chainmask flag that we don't use anywhere. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 25 +++++++++--------- drivers/net/wireless/ath9k/hw.c | 21 --------------- drivers/net/wireless/ath9k/hw.h | 52 +++++++++++++------------------------- drivers/net/wireless/ath9k/main.c | 2 -- drivers/net/wireless/ath9k/rc.h | 1 - 5 files changed, 30 insertions(+), 71 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 7b1b40aaf09d..1dfc3816a2d8 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -525,19 +525,18 @@ struct ath_rfkill { #define SC_OP_BEACONS BIT(1) #define SC_OP_RXAGGR BIT(2) #define SC_OP_TXAGGR BIT(3) -#define SC_OP_CHAINMASK_UPDATE BIT(4) -#define SC_OP_FULL_RESET BIT(5) -#define SC_OP_PREAMBLE_SHORT BIT(6) -#define SC_OP_PROTECT_ENABLE BIT(7) -#define SC_OP_RXFLUSH BIT(8) -#define SC_OP_LED_ASSOCIATED BIT(9) -#define SC_OP_RFKILL_REGISTERED BIT(10) -#define SC_OP_RFKILL_SW_BLOCKED BIT(11) -#define SC_OP_RFKILL_HW_BLOCKED BIT(12) -#define SC_OP_WAIT_FOR_BEACON BIT(13) -#define SC_OP_LED_ON BIT(14) -#define SC_OP_SCANNING BIT(15) -#define SC_OP_TSF_RESET BIT(16) +#define SC_OP_FULL_RESET BIT(4) +#define SC_OP_PREAMBLE_SHORT BIT(5) +#define SC_OP_PROTECT_ENABLE BIT(6) +#define SC_OP_RXFLUSH BIT(7) +#define SC_OP_LED_ASSOCIATED BIT(8) +#define SC_OP_RFKILL_REGISTERED BIT(9) +#define SC_OP_RFKILL_SW_BLOCKED BIT(10) +#define SC_OP_RFKILL_HW_BLOCKED BIT(11) +#define SC_OP_WAIT_FOR_BEACON BIT(12) +#define SC_OP_LED_ON BIT(13) +#define SC_OP_SCANNING BIT(14) +#define SC_OP_TSF_RESET BIT(15) struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index b15eaf8417ff..13d8c2a4efae 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -363,10 +363,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ah->config.ack_6mb = 0x0; ah->config.cwm_ignore_extcca = 0; ah->config.pcie_powersave_enable = 0; - ah->config.pcie_l1skp_enable = 0; ah->config.pcie_clock_req = 0; - ah->config.pcie_power_reset = 0x100; - ah->config.pcie_restore = 0; ah->config.pcie_waen = 0; ah->config.analog_shiftreg = 1; ah->config.ht_enable = 1; @@ -375,13 +372,6 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ah->config.cck_trig_high = 200; ah->config.cck_trig_low = 100; ah->config.enable_ani = 1; - ah->config.noise_immunity_level = 4; - ah->config.ofdm_weaksignal_det = 1; - ah->config.cck_weaksignal_thr = 0; - ah->config.spur_immunity_level = 2; - ah->config.firstep_level = 0; - ah->config.rssi_thr_high = 40; - ah->config.rssi_thr_low = 7; ah->config.diversity_control = 0; ah->config.antenna_switch_swap = 0; @@ -3343,8 +3333,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; - pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD; - if (ah->config.ht_enable) pCap->hw_caps |= ATH9K_HW_CAP_HT; else @@ -3368,7 +3356,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->keycache_size = AR_KEYTABLE_SIZE; pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; - pCap->num_mr_retries = 4; pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; if (AR_SREV_9285_10_OR_LATER(ah)) @@ -3378,14 +3365,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->num_gpio_pins = AR_NUM_GPIO; - if (AR_SREV_9280_10_OR_LATER(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_WOW; - pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT; - } else { - pCap->hw_caps &= ~ATH9K_HW_CAP_WOW; - pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT; - } - if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { pCap->hw_caps |= ATH9K_HW_CAP_CST; pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 0b594e0ee260..5ba6a4b60356 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -124,29 +124,24 @@ enum wireless_mode { }; enum ath9k_hw_caps { - ATH9K_HW_CAP_CHAN_SPREAD = BIT(0), - ATH9K_HW_CAP_MIC_AESCCM = BIT(1), - ATH9K_HW_CAP_MIC_CKIP = BIT(2), - ATH9K_HW_CAP_MIC_TKIP = BIT(3), - ATH9K_HW_CAP_CIPHER_AESCCM = BIT(4), - ATH9K_HW_CAP_CIPHER_CKIP = BIT(5), - ATH9K_HW_CAP_CIPHER_TKIP = BIT(6), - ATH9K_HW_CAP_VEOL = BIT(7), - ATH9K_HW_CAP_BSSIDMASK = BIT(8), - ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(9), - ATH9K_HW_CAP_CHAN_HALFRATE = BIT(10), - ATH9K_HW_CAP_CHAN_QUARTERRATE = BIT(11), - ATH9K_HW_CAP_HT = BIT(12), - ATH9K_HW_CAP_GTT = BIT(13), - ATH9K_HW_CAP_FASTCC = BIT(14), - ATH9K_HW_CAP_RFSILENT = BIT(15), - ATH9K_HW_CAP_WOW = BIT(16), - ATH9K_HW_CAP_CST = BIT(17), - ATH9K_HW_CAP_ENHANCEDPM = BIT(18), - ATH9K_HW_CAP_AUTOSLEEP = BIT(19), - ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20), - ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21), - ATH9K_HW_CAP_BT_COEX = BIT(22) + ATH9K_HW_CAP_MIC_AESCCM = BIT(0), + ATH9K_HW_CAP_MIC_CKIP = BIT(1), + ATH9K_HW_CAP_MIC_TKIP = BIT(2), + ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), + ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), + ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), + ATH9K_HW_CAP_VEOL = BIT(6), + ATH9K_HW_CAP_BSSIDMASK = BIT(7), + ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), + ATH9K_HW_CAP_HT = BIT(9), + ATH9K_HW_CAP_GTT = BIT(10), + ATH9K_HW_CAP_FASTCC = BIT(11), + ATH9K_HW_CAP_RFSILENT = BIT(12), + ATH9K_HW_CAP_CST = BIT(13), + ATH9K_HW_CAP_ENHANCEDPM = BIT(14), + ATH9K_HW_CAP_AUTOSLEEP = BIT(15), + ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), + ATH9K_HW_CAP_BT_COEX = BIT(17) }; enum ath9k_capability_type { @@ -166,7 +161,6 @@ struct ath9k_hw_capabilities { u16 keycache_size; u16 low_5ghz_chan, high_5ghz_chan; u16 low_2ghz_chan, high_2ghz_chan; - u16 num_mr_retries; u16 rts_aggr_limit; u8 tx_chainmask; u8 rx_chainmask; @@ -184,11 +178,8 @@ struct ath9k_ops_config { int ack_6mb; int cwm_ignore_extcca; u8 pcie_powersave_enable; - u8 pcie_l1skp_enable; u8 pcie_clock_req; u32 pcie_waen; - int pcie_power_reset; - u8 pcie_restore; u8 analog_shiftreg; u8 ht_enable; u32 ofdm_trig_low; @@ -196,13 +187,6 @@ struct ath9k_ops_config { u32 cck_trig_high; u32 cck_trig_low; u32 enable_ani; - u8 noise_immunity_level; - u32 ofdm_weaksignal_det; - u32 cck_weaksignal_thr; - u8 spur_immunity_level; - u8 firstep_level; - int8_t rssi_thr_high; - int8_t rssi_thr_low; u16 diversity_control; u16 antenna_switch_swap; int serialize_regmode; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 97cf83fa8555..74fe777b54e4 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -287,7 +287,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, } spin_unlock_bh(&sc->sc_resetlock); - sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; sc->sc_flags &= ~SC_OP_FULL_RESET; if (ath_startrecv(sc) != 0) { @@ -416,7 +415,6 @@ set_timer: */ void ath_update_chainmask(struct ath_softc *sc, int is_ht) { - sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; if (is_ht || (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index 199a3ce57d64..ec72dd29da00 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h @@ -24,7 +24,6 @@ struct ath_softc; #define ATH_RATE_MAX 30 #define RATE_TABLE_SIZE 64 #define MAX_TX_RATE_PHY 48 -#define WLAN_CTRL_FRAME_SIZE (2+2+6+4) /* VALID_ALL - valid for 20/40/Legacy, * VALID - Legacy only, -- cgit v1.2.3 From 6ed6a05e5c8061cdcd69a418c90c5f11979ce650 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:24 +0530 Subject: ath9k: Remove redundant chainmask check We get the valid chainmasks on HW attach, checking it again during reset is redundant. This patch removes the check. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 13d8c2a4efae..22ef93f3d47c 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -2189,14 +2189,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ah->txchainmask = sc->tx_chainmask; ah->rxchainmask = sc->rx_chainmask; - if (AR_SREV_9285(ah)) { - ah->txchainmask &= 0x1; - ah->rxchainmask &= 0x1; - } else if (AR_SREV_9280(ah)) { - ah->txchainmask &= 0x3; - ah->rxchainmask &= 0x3; - } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; -- cgit v1.2.3 From d8baa9392666d1c50ef42e9f6fbbb0cf536327b9 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:25 +0530 Subject: ath9k: Cleanup debug messages Clean debug messages to use appropriate levels, remove useless messages, and trim the number of debug levels. Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ani.c | 8 ++- drivers/net/wireless/ath9k/beacon.c | 7 +-- drivers/net/wireless/ath9k/debug.h | 24 ++++----- drivers/net/wireless/ath9k/eeprom.c | 24 ++++----- drivers/net/wireless/ath9k/hw.c | 101 ++++++++++++++++-------------------- drivers/net/wireless/ath9k/mac.c | 63 ++++++++++++---------- drivers/net/wireless/ath9k/main.c | 6 +-- drivers/net/wireless/ath9k/phy.c | 4 +- drivers/net/wireless/ath9k/phy.h | 3 -- drivers/net/wireless/ath9k/recv.c | 4 +- 10 files changed, 115 insertions(+), 129 deletions(-) diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c index 6c5e887d50d7..1aeafb511ddd 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath9k/ani.c @@ -569,8 +569,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, DPRINTF(ah->ah_sc, ATH_DBG_ANI, "phyCnt1 0x%x, resetting " "counter value to 0x%x\n", - phyCnt1, - aniState->ofdmPhyErrBase); + phyCnt1, aniState->ofdmPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_MASK_1, @@ -580,8 +579,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, DPRINTF(ah->ah_sc, ATH_DBG_ANI, "phyCnt2 0x%x, resetting " "counter value to 0x%x\n", - phyCnt2, - aniState->cckPhyErrBase); + phyCnt2, aniState->cckPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); REG_WRITE(ah, AR_PHY_ERR_MASK_2, @@ -667,7 +665,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 cc = REG_READ(ah, AR_CCCNT); if (cycles == 0 || cycles > cc) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "cycle counter wrap. ExtBusy = 0\n"); good = 0; } else { diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index ec995730632d..5b2752b43be4 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -43,7 +43,7 @@ static int ath_beaconq_config(struct ath_softc *sc) if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { DPRINTF(sc, ATH_DBG_FATAL, - "unable to update h/w beacon queue parameters\n"); + "Unable to update h/w beacon queue parameters\n"); return 0; } else { ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); @@ -132,11 +132,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, avp = (void *)vif->drv_priv; cabq = sc->beacon.cabq; - if (avp->av_bcbuf == NULL) { - DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n", - avp, avp->av_bcbuf); + if (avp->av_bcbuf == NULL) return NULL; - } /* Release the old beacon first */ diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath9k/debug.h index 7b0e5419d2bc..23298b90b52b 100644 --- a/drivers/net/wireless/ath9k/debug.h +++ b/drivers/net/wireless/ath9k/debug.h @@ -19,20 +19,16 @@ enum ATH_DEBUG { ATH_DBG_RESET = 0x00000001, - ATH_DBG_REG_IO = 0x00000002, - ATH_DBG_QUEUE = 0x00000004, - ATH_DBG_EEPROM = 0x00000008, - ATH_DBG_CALIBRATE = 0x00000010, - ATH_DBG_CHANNEL = 0x00000020, - ATH_DBG_INTERRUPT = 0x00000040, - ATH_DBG_REGULATORY = 0x00000080, - ATH_DBG_ANI = 0x00000100, - ATH_DBG_POWER_MGMT = 0x00000200, - ATH_DBG_XMIT = 0x00000400, - ATH_DBG_BEACON = 0x00001000, - ATH_DBG_CONFIG = 0x00002000, - ATH_DBG_KEYCACHE = 0x00004000, - ATH_DBG_FATAL = 0x00008000, + ATH_DBG_QUEUE = 0x00000002, + ATH_DBG_EEPROM = 0x00000004, + ATH_DBG_CALIBRATE = 0x00000008, + ATH_DBG_INTERRUPT = 0x00000010, + ATH_DBG_REGULATORY = 0x00000020, + ATH_DBG_ANI = 0x00000040, + ATH_DBG_XMIT = 0x00000080, + ATH_DBG_BEACON = 0x00000100, + ATH_DBG_CONFIG = 0x00000200, + ATH_DBG_FATAL = 0x00000400, ATH_DBG_ANY = 0xffffffff }; diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index ffc36b0361c7..44fee5ae8925 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c @@ -783,11 +783,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PDADC (%d,%4x): %4.4x %8.8x\n", i, regChainOffset, regOffset, reg32); - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PDADC: Chain %d | " "PDADC %3d Value %3d | " "PDADC %3d Value %3d | " @@ -910,7 +910,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ah->eep_ops->get_eeprom_rev(ah) <= 2) twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " "EXT_ADDITIVE %d\n", ctlMode, numCtlModes, isHt40CtlMode, @@ -918,7 +918,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " "chan %d\n", @@ -941,7 +941,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, IS_CHAN_2GHZ(chan), AR5416_EEP4K_NUM_BAND_EDGES); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " MATCH-EE_IDX %d: ch %d is2 %d " "2xMinEdge %d chainmask %d chains %d\n", i, freq, IS_CHAN_2GHZ(chan), @@ -961,7 +961,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " SEL-Min ctlMode %d pCtlMode %d " "2xMaxEdge %d sP %d minCtlPwr %d\n", ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, @@ -2234,11 +2234,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PDADC (%d,%4x): %4.4x %8.8x\n", i, regChainOffset, regOffset, reg32); - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PDADC: Chain %d | PDADC %3d " "Value %3d | PDADC %3d Value %3d | " "PDADC %3d Value %3d | PDADC %3d " @@ -2415,14 +2415,14 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ah->eep_ops->get_eeprom_rev(ah) <= 2) twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " "EXT_ADDITIVE %d\n", ctlMode, numCtlModes, isHt40CtlMode, (pCtlMode[ctlMode] & EXT_ADDITIVE)); for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " "chan %d\n", @@ -2441,7 +2441,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " MATCH-EE_IDX %d: ch %d is2 %d " "2xMinEdge %d chainmask %d chains %d\n", i, freq, IS_CHAN_2GHZ(chan), @@ -2460,7 +2460,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, minCtlPower = min(twiceMaxEdgePower, scaledPower); - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, " SEL-Min ctlMode %d pCtlMode %d " "2xMaxEdge %d sP %d minCtlPwr %d\n", ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 22ef93f3d47c..169d8efa69dc 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -97,7 +97,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) udelay(AH_TIME_QUANTUM); } - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", timeout, reg, REG_READ(ah, reg), mask, val); @@ -181,7 +181,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, } break; default: - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Unknown phy %u (rate ix %u)\n", rates->info[rateix].phy, rateix); txTime = 0; @@ -306,7 +306,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (rdData != wrData) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "address test failed " "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", addr, wrData, rdData); @@ -318,7 +318,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) REG_WRITE(ah, addr, wrData); rdData = REG_READ(ah, addr); if (wrData != rdData) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "address test failed " "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", addr, wrData, rdData); @@ -453,8 +453,8 @@ static int ath9k_hw_rfattach(struct ath_hw *ah) rfStatus = ath9k_hw_init_rf(ah, &ecode); if (!rfStatus) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "RF setup failed, status %u\n", ecode); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "RF setup failed, status: %u\n", ecode); return ecode; } @@ -478,10 +478,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) case AR_RAD2122_SREV_MAJOR: break; default: - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "5G Radio Chip Rev 0x%02X is not " - "supported by this driver\n", - ah->hw_version.analog5GhzRev); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Radio Chip Rev 0x%02X not supported\n", + val & AR_RADIO_SREV_MAJOR); return -EOPNOTSUPP; } @@ -503,12 +502,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) ah->macaddr[2 * i] = eeval >> 8; ah->macaddr[2 * i + 1] = eeval & 0xff; } - if (sum == 0 || sum == 0xffff * 3) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "mac address read failed: %pM\n", - ah->macaddr); + if (sum == 0 || sum == 0xffff * 3) return -EADDRNOTAVAIL; - } return 0; } @@ -565,11 +560,8 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) { int ecode; - if (!ath9k_hw_chip_test(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, - "hardware self-test failed\n"); + if (!ath9k_hw_chip_test(ah)) return -ENODEV; - } ecode = ath9k_hw_rf_claim(ah); if (ecode != 0) @@ -611,13 +603,13 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ah->intr_mitigation = true; if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - DPRINTF(sc, ATH_DBG_RESET, "Couldn't reset chip\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); ecode = -EIO; goto bad; } if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - DPRINTF(sc, ATH_DBG_RESET, "Couldn't wakeup chip\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); ecode = -EIO; goto bad; } @@ -640,7 +632,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && (ah->hw_version.macVersion != AR_SREV_VERSION_9160) && (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) { - DPRINTF(sc, ATH_DBG_RESET, + DPRINTF(sc, ATH_DBG_FATAL, "Mac Chip Rev 0x%02x.%x is not supported by " "this driver\n", ah->hw_version.macVersion, ah->hw_version.macRev); @@ -680,10 +672,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, if (AR_SREV_9280_10_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - DPRINTF(sc, ATH_DBG_RESET, - "This Mac Chip Rev 0x%02x.%x is \n", - ah->hw_version.macVersion, ah->hw_version.macRev); - if (AR_SREV_9285_12_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, @@ -875,8 +863,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ecode = ath9k_hw_init_macaddr(ah); if (ecode != 0) { - DPRINTF(sc, ATH_DBG_RESET, - "failed initializing mac address\n"); + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to initialize MAC address\n"); goto bad; } @@ -1193,23 +1181,23 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, switch (ah->hw_version.devid) { case AR9280_DEVID_PCI: if (reg == 0x7894) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "ini VAL: %x EEPROM: %x\n", value, (pBase->version & 0xff)); if ((pBase->version & 0xff) > 0x0a) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PWDCLKIND: %d\n", pBase->pwdclkind); value &= ~AR_AN_TOP2_PWDCLKIND; value |= AR_AN_TOP2_PWDCLKIND & (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); } else { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "PWDCLKIND Earlier Rev\n"); } - DPRINTF(ah->ah_sc, ATH_DBG_ANY, + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "final ini VAL: %x\n", value); } break; @@ -1356,13 +1344,13 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, min((u32) MAX_RATE_POWER, (u32) ah->regulatory.power_limit)); if (status != 0) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, - "error init'ing transmit power\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Error initializing transmit power\n"); return -EIO; } if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "ar5416SetRfRegs failed\n"); return -EIO; } @@ -1668,7 +1656,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Could not kill baseband RX\n"); return false; } @@ -1677,14 +1665,14 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, if (AR_SREV_9280_10_OR_LATER(ah)) { if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "failed to set channel\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Failed to set channel\n"); return false; } } else { if (!(ath9k_hw_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "failed to set channel\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Failed to set channel\n"); return false; } } @@ -1696,7 +1684,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, min((u32) MAX_RATE_POWER, (u32) ah->regulatory.power_limit)) != 0) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "error init'ing transmit power\n"); + "Error initializing transmit power\n"); return false; } @@ -2224,7 +2212,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_mark_phy_inactive(ah); if (!ath9k_hw_chip_reset(ah, chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); return -EINVAL; } @@ -2367,8 +2355,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) u32 keyType; if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, - "entry %u out of range\n", entry); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); return false; } @@ -2404,8 +2392,8 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) u32 macHi, macLo; if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, - "entry %u out of range\n", entry); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); return false; } @@ -2436,8 +2424,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, u32 keyType; if (entry >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, - "entry %u out of range\n", entry); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keycache entry %u out of range\n", entry); return false; } @@ -2447,7 +2435,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, break; case ATH9K_CIPHER_AES_CCM: if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "AES-CCM not supported by mac rev 0x%x\n", ah->hw_version.macRev); return false; @@ -2458,14 +2446,14 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, keyType = AR_KEYTABLE_TYPE_TKIP; if (ATH9K_IS_MIC_ENABLED(ah) && entry + 64 >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "entry %u inappropriate for TKIP\n", entry); return false; } break; case ATH9K_CIPHER_WEP: if (k->kv_len < LEN_WEP40) { - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_ANY, "WEP key length %u too small\n", k->kv_len); return false; } @@ -2480,7 +2468,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, keyType = AR_KEYTABLE_TYPE_CLR; break; default: - DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "cipher %u not supported\n", k->kv_type); return false; } @@ -2698,7 +2686,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) AR_RTC_FORCE_WAKE_EN); } if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); return false; } @@ -2719,9 +2707,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) "UNDEFINED" }; - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n", - modes[ah->power_mode], modes[mode], - setChip ? "set chip " : ""); + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", + modes[ah->power_mode], modes[mode]); switch (mode) { case ATH9K_PM_AWAKE: @@ -2735,7 +2722,7 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) ath9k_set_power_network_sleep(ah, setChip); break; default: - DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Unknown power mode %u\n", mode); return false; } diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index e0a6dee45839..8ae4ec21667b 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c @@ -49,7 +49,7 @@ bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); REG_WRITE(ah, AR_Q_TXE, 1 << q); @@ -110,13 +110,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " + "inactive queue: %u\n", q); return false; } @@ -146,7 +148,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) break; DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "TSF have moved while trying to set " + "TSF has moved while trying to set " "quiet time TSF: 0x%08x\n", tsfLow); } @@ -158,8 +160,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_XMIT, - "Failed to stop Tx DMA in 100 " + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + "Failed to stop TX DMA in 100 " "msec after killing last frame\n"); break; } @@ -454,17 +456,19 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " + "inactive queue: %u\n", q); return false; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); qi->tqi_ver = qinfo->tqi_ver; qi->tqi_subtype = qinfo->tqi_subtype; @@ -521,13 +525,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " + "inactive queue: %u\n", q); return false; } @@ -575,22 +581,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, ATH9K_TX_QUEUE_INACTIVE) break; if (q == pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "no available tx queue\n"); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "No available TX queue\n"); return -1; } break; default: - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", + type); return -1; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); qi = &ah->txq[q]; if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "tx queue %u already active\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "TX queue: %u already active\n", q); return -1; } memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); @@ -620,16 +627,18 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " + "inactive queue: %u\n", q); return false; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; ah->txok_interrupt_mask &= ~(1 << q); @@ -650,17 +659,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) u32 cwMin, chanCwMin, value; if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " + "invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " + "inactive queue: %u\n", q); return true; } - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q); + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { if (chan && IS_CHAN_B(chan)) @@ -894,7 +905,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) reg = REG_READ(ah, AR_OBS_BUS_1); DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "rx failed to go idle in 10 ms RXSM=0x%x\n", reg); + "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); return false; } @@ -949,8 +960,8 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) } if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "dma failed to stop in %d ms " + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "DMA failed to stop in %d ms " "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", AH_RX_STOP_DMA_TIMEOUT / 1000, REG_READ(ah, AR_CR), diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 74fe777b54e4..1b43cb41363c 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -674,7 +674,7 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { /* TX MIC entry failed. No need to proceed further */ - DPRINTF(sc, ATH_DBG_KEYCACHE, + DPRINTF(sc, ATH_DBG_FATAL, "Setting TX MIC Key Failed\n"); return 0; } @@ -1400,7 +1400,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) /* Get the hardware key cache size. */ sc->keymax = ah->caps.keycache_size; if (sc->keymax > ATH_KEYMAX) { - DPRINTF(sc, ATH_DBG_KEYCACHE, + DPRINTF(sc, ATH_DBG_ANY, "Warning, using only %u entries in %u key cache\n", ATH_KEYMAX, sc->keymax); sc->keymax = ATH_KEYMAX; @@ -2602,7 +2602,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); - DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n"); + DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); switch (cmd) { case SET_KEY: diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c index 8bcba906929a..5ec9ce91d979 100644 --- a/drivers/net/wireless/ath9k/phy.c +++ b/drivers/net/wireless/ath9k/phy.c @@ -46,7 +46,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = ((freq - 704) * 2 - 3040) / 10; bModeSynth = 1; } else { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid channel %u MHz\n", freq); return false; } @@ -79,7 +79,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); aModeRefSel = ath9k_hw_reverse_bits(1, 2); } else { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid channel %u MHz\n", freq); return false; } diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 0f7f8e0c9c95..296d0e985f25 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h @@ -556,9 +556,6 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int r; \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, \ - "RF 0x%x V 0x%x\n", \ - INI_RA((iniarray), r, 0), (regData)[r]); \ DO_DELAY(regWr); \ } \ } while (0) diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index dd1f30156740..efa57ae8901c 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -320,7 +320,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, + DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on RX init\n"); error = -ENOMEM; break; @@ -675,7 +675,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) bf->bf_buf_addr))) { dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, + DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on RX\n"); break; } -- cgit v1.2.3 From eef7a57430c83b0419ba943bb1650ed5c349d454 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:28 +0530 Subject: ath9k: Change return value of ath9k_hw_fill_cap_info This routine always return true, checking for false in the return value is invalid. Fix this. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 10 ++-------- drivers/net/wireless/ath9k/hw.h | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 169d8efa69dc..4ad1508e4752 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -837,11 +837,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, if (AR_SREV_9280_20(ah)) ath9k_hw_init_txgain_ini(ah); - if (!ath9k_hw_fill_cap_info(ah)) { - DPRINTF(sc, ATH_DBG_RESET, "failed ath9k_hw_fill_cap_info\n"); - ecode = -EINVAL; - goto bad; - } + ath9k_hw_fill_cap_info(ah); if ((ah->hw_version.devid == AR9280_DEVID_PCI) && test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { @@ -3228,7 +3224,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, /* HW Capabilities */ /*******************/ -bool ath9k_hw_fill_cap_info(struct ath_hw *ah) +void ath9k_hw_fill_cap_info(struct ath_hw *ah) { struct ath9k_hw_capabilities *pCap = &ah->caps; u16 capField = 0, eeval; @@ -3403,8 +3399,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah) ah->btactive_gpio = 6; ah->wlanactive_gpio = 5; } - - return true; } bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 5ba6a4b60356..c50faae22c59 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -557,7 +557,7 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error); void ath9k_hw_rfdetach(struct ath_hw *ah); int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange); -bool ath9k_hw_fill_cap_info(struct ath_hw *ah); +void ath9k_hw_fill_cap_info(struct ath_hw *ah); bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, u32 capability, u32 *result); bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, -- cgit v1.2.3 From 0ef1f168b6bc82b0b157c568e764b75961867970 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:35 +0530 Subject: ath9k: Remove redundant variable for Interrupt Mitigation The state is already stored in ath9k_ops_config, so remove the duplicate variable in ath_hw. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 14 +++++--------- drivers/net/wireless/ath9k/hw.h | 3 +-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 4ad1508e4752..bb208f51b561 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -380,7 +380,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } - ah->config.intr_mitigation = 1; + ah->config.intr_mitigation = true; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) @@ -599,9 +599,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, ath9k_hw_set_defaults(ah); - if (ah->config.intr_mitigation != 0) - ah->intr_mitigation = true; - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); ecode = -EIO; @@ -1028,7 +1025,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, AR_IMR_RXORN | AR_IMR_BCNMISC; - if (ah->intr_mitigation) + if (ah->config.intr_mitigation) ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; else ah->mask_reg |= AR_IMR_RXOK; @@ -2301,8 +2298,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_OBS, 8); - if (ah->intr_mitigation) { - + if (ah->config.intr_mitigation) { REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); } @@ -2908,7 +2904,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) *masked = isr & ATH9K_INT_COMMON; - if (ah->intr_mitigation) { + if (ah->config.intr_mitigation) { if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) *masked |= ATH9K_INT_RX; } @@ -3026,7 +3022,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) } if (ints & ATH9K_INT_RX) { mask |= AR_IMR_RXERR; - if (ah->intr_mitigation) + if (ah->config.intr_mitigation) mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; else mask |= AR_IMR_RXOK | AR_IMR_RXDESC; diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index c50faae22c59..5a1128ddb464 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -190,7 +190,7 @@ struct ath9k_ops_config { u16 diversity_control; u16 antenna_switch_swap; int serialize_regmode; - int intr_mitigation; + bool intr_mitigation; #define SPUR_DISABLE 0 #define SPUR_ENABLE_IOCTL 1 #define SPUR_ENABLE_EEPROM 2 @@ -524,7 +524,6 @@ struct ath_hw { enum ath9k_ani_cmd ani_function; u32 intr_txqs; - bool intr_mitigation; enum ath9k_ht_extprotspacing extprotspacing; u8 txchainmask; u8 rxchainmask; -- cgit v1.2.3 From a22be22ab8fe571cce88d0d30b49f297a563c4a7 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:36 +0530 Subject: ath9k: Avoid unneeded casts Change the void pointer to struct sk_buff and access bf_mpdu directly, removing all casts in the process. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath9k/beacon.c | 10 +++++----- drivers/net/wireless/ath9k/xmit.c | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 1dfc3816a2d8..9adc991cb05f 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -130,7 +130,7 @@ struct ath_buf { struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or an aggregate) */ struct ath_buf *bf_next; /* next subframe in the aggregate */ - void *bf_mpdu; /* enclosing frame structure */ + struct sk_buff *bf_mpdu; /* enclosing frame structure */ struct ath_desc *bf_desc; /* virtual addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer */ diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 5b2752b43be4..eb4759fc6a0d 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -59,7 +59,7 @@ static int ath_beaconq_config(struct ath_softc *sc) static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_buf *bf) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; struct ath_hw *ah = sc->sc_ah; struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; @@ -138,7 +138,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, /* Release the old beacon first */ bf = avp->av_bcbuf; - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; if (skb) { dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); @@ -226,7 +226,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, return; bf = avp->av_bcbuf; - skb = (struct sk_buff *) bf->bf_mpdu; + skb = bf->bf_mpdu; ath_beacon_setup(sc, avp, bf); @@ -299,7 +299,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) /* release the previous beacon frame, if it already exists. */ bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); @@ -371,7 +371,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 689bdbf78808..87bbeaa6432f 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -283,7 +283,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; rcu_read_lock(); @@ -444,7 +444,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, u16 aggr_limit, legacy = 0, maxampdu; int i; - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; @@ -1452,7 +1452,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - skb = (struct sk_buff *)bf->bf_mpdu; + skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; hdr = (struct ieee80211_hdr *)skb->data; @@ -1586,7 +1586,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_control *txctl) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_node *an = NULL; @@ -1860,7 +1860,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad, int txok, bool update_rc) { - struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; + struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); -- cgit v1.2.3 From a119cc492fc720de7fcaf7c1b9394d6c025d276d Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:38 +0530 Subject: ath9k: Cleanup buffer status handling Using a u32 to store a single flag is overkill. Use a bool to store whether the buffer is stale or not. Also, use u8 instead of u32 to store the buffer type. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 13 +++++++------ drivers/net/wireless/ath9k/xmit.c | 9 ++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 9adc991cb05f..e6c39c1c1a28 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -74,13 +74,17 @@ struct ath_config { /*************************/ #define ATH_TXBUF_RESET(_bf) do { \ - (_bf)->bf_status = 0; \ + (_bf)->bf_stale = false; \ (_bf)->bf_lastbf = NULL; \ (_bf)->bf_next = NULL; \ memset(&((_bf)->bf_state), 0, \ sizeof(struct ath_buf_state)); \ } while (0) +#define ATH_RXBUF_RESET(_bf) do { \ + (_bf)->bf_stale = false; \ + } while (0) + /** * enum buffer_type - Buffer type flags * @@ -106,7 +110,7 @@ struct ath_buf_state { int bfs_seqno; int bfs_tidno; int bfs_retries; - u32 bf_type; + u8 bf_type; u32 bfs_keyix; enum ath9k_key_type bfs_keytype; }; @@ -134,15 +138,12 @@ struct ath_buf { struct ath_desc *bf_desc; /* virtual addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer */ - u32 bf_status; + bool bf_stale; u16 bf_flags; struct ath_buf_state bf_state; dma_addr_t bf_dmacontext; }; -#define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0) -#define ATH_BUFSTATUS_STALE 0x00000002 - struct ath_descdma { const char *dd_name; struct ath_desc *dd_desc; diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 87bbeaa6432f..735256faa0b2 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -380,8 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); } else { /* retry the un-acked ones */ - if (bf->bf_next == NULL && - bf_last->bf_status & ATH_BUFSTATUS_STALE) { + if (bf->bf_next == NULL && bf_last->bf_stale) { struct ath_buf *tbf; tbf = ath_clone_txbuf(sc, bf_last); @@ -1004,7 +1003,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - if (bf->bf_status & ATH_BUFSTATUS_STALE) { + if (bf->bf_stale) { list_del(&bf->list); spin_unlock_bh(&txq->axq_lock); @@ -1941,7 +1940,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * it with the STALE flag. */ bf_held = NULL; - if (bf->bf_status & ATH_BUFSTATUS_STALE) { + if (bf->bf_stale) { bf_held = bf; if (list_is_last(&bf_held->list, &txq->axq_q)) { txq->axq_link = NULL; @@ -1982,7 +1981,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) * however leave the last descriptor back as the holding * descriptor for hw. */ - lastbf->bf_status |= ATH_BUFSTATUS_STALE; + lastbf->bf_stale = true; INIT_LIST_HEAD(&bf_head); if (!list_is_singular(&lastbf->list)) list_cut_position(&bf_head, -- cgit v1.2.3 From ae459af12816b507aed3fcb2b9fc933c212ea12e Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:40 +0530 Subject: ath9k: Remove a couple of unused variables in descriptor handling Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 2 -- drivers/net/wireless/ath9k/main.c | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index e6c39c1c1a28..dc42ad129b23 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -145,12 +145,10 @@ struct ath_buf { }; struct ath_descdma { - const char *dd_name; struct ath_desc *dd_desc; dma_addr_t dd_desc_paddr; u32 dd_desc_len; struct ath_buf *dd_bufptr; - dma_addr_t dd_dmacontext; }; int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 1b43cb41363c..f5a541b864ce 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1789,7 +1789,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, goto fail; } - dd->dd_name = name; dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; /* @@ -1819,7 +1818,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, } ds = dd->dd_desc; DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - dd->dd_name, ds, (u32) dd->dd_desc_len, + name, ds, (u32) dd->dd_desc_len, ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); /* allocate buffers */ -- cgit v1.2.3 From 5cc93992cc4cf12ddfe63c8a5be2d509e6678e99 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:41 +0530 Subject: ath9k: Remove unused structures struct aggr_rifs_param and ath_tx_stat are not used anywhere. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index dc42ad129b23..9a12f76988da 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -294,26 +294,6 @@ struct ath_tx_control { #define ATH_TX_XRETRY 0x02 #define ATH_TX_BAR 0x04 -/* All RSSI values are noise floor adjusted */ -struct ath_tx_stat { - int rssi; - int rssictl[ATH_MAX_ANTENNA]; - int rssiextn[ATH_MAX_ANTENNA]; - int rateieee; - int rateKbps; - int ratecode; - int flags; - u32 airtime; /* time on air per final tx rate */ -}; - -struct aggr_rifs_param { - int param_max_frames; - int param_max_len; - int param_rl; - int param_al; - struct ath_rc_series *param_rcs; -}; - struct ath_node { struct ath_softc *an_sc; struct ath_atx_tid tid[WME_NUM_TID]; -- cgit v1.2.3 From 7dd58748592db1e5a77cfbddb8beffcfdb0242fe Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:42 +0530 Subject: ath9k: Check for root debugfs file Creation of the root debugfs file could have failed for some reason, check properly before proceeding in this case. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/debug.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index fdf9528fa49b..97df20cbf528 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c @@ -498,6 +498,9 @@ int ath9k_init_debug(struct ath_softc *sc) { sc->debug.debug_mask = ath9k_debug; + if (!ath9k_debugfs_root) + return -ENOENT; + sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), ath9k_debugfs_root); if (!sc->debug.debugfs_phy) -- cgit v1.2.3 From 4658b985170d9d0c88304d2d4459938b600f8c0b Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:43 +0530 Subject: ath9k: Remove TIM from the interrupt mask We never handle TIM, TIM_TIMER is used instead. Remove this and the unnecessary swBeaconProcess variable. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 1 - drivers/net/wireless/ath9k/main.c | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 9a12f76988da..0ef89bb73f31 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -66,7 +66,6 @@ struct ath_config { u32 ath_aggr_prot; u16 txpowlimit; u8 cabqReadytime; - u8 swBeaconProcess; }; /*************************/ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index f5a541b864ce..0c1cc2d62a80 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1542,9 +1542,6 @@ static int ath_init(u16 devid, struct ath_softc *sc) sc->beacon.bslot_aphy[i] = NULL; } - /* save MISC configurations */ - sc->config.swBeaconProcess = 1; - /* setup channels and rates */ sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; @@ -2253,17 +2250,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, sc->imask |= ATH9K_INT_TSFOOR; } - /* - * Some hardware processes the TIM IE and fires an - * interrupt when the TIM bit is set. For hardware - * that does, if not overridden by configuration, - * enable the TIM interrupt when operating as station. - */ - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && - (conf->type == NL80211_IFTYPE_STATION) && - !sc->config.swBeaconProcess) - sc->imask |= ATH9K_INT_TIM; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); if (conf->type == NL80211_IFTYPE_AP) { -- cgit v1.2.3 From 797fe5cbefdb91f796502677e3a6623262eb9fcd Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:45 +0530 Subject: ath9k: Remove the useless do..while loops These are unnecessary constructs in a function. This patch removes these from both RX and TX init routines. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath9k/recv.c | 83 ++++++++++++++++++-------------------- drivers/net/wireless/ath9k/xmit.c | 40 ++++++++---------- 3 files changed, 57 insertions(+), 68 deletions(-) diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 0ef89bb73f31..c92d46fa9d51 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -340,7 +340,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_init(struct ath_softc *sc, int nbufs); -int ath_tx_cleanup(struct ath_softc *sc); +void ath_tx_cleanup(struct ath_softc *sc); struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index efa57ae8901c..b46badd21f73 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -283,54 +283,51 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) struct ath_buf *bf; int error = 0; - do { - spin_lock_init(&sc->rx.rxflushlock); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_lock_init(&sc->rx.rxbuflock); - - sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, - min(sc->cachelsz, - (u16)64)); + spin_lock_init(&sc->rx.rxflushlock); + sc->sc_flags &= ~SC_OP_RXFLUSH; + spin_lock_init(&sc->rx.rxbuflock); - DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - sc->cachelsz, sc->rx.bufsize); + sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, + min(sc->cachelsz, (u16)64)); - /* Initialize rx descriptors */ + DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", + sc->cachelsz, sc->rx.bufsize); - error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, - "rx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", error); - break; - } + /* Initialize rx descriptors */ - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); - if (skb == NULL) { - error = -ENOMEM; - break; - } + error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, + "rx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "failed to allocate rx descriptors: %d\n", error); + goto err; + } - bf->bf_mpdu = skb; - bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, - sc->rx.bufsize, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error() on RX init\n"); - error = -ENOMEM; - break; - } - bf->bf_dmacontext = bf->bf_buf_addr; + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); + if (skb == NULL) { + error = -ENOMEM; + goto err; } - sc->rx.rxlink = NULL; - } while (0); + bf->bf_mpdu = skb; + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + sc->rx.bufsize, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, + bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + DPRINTF(sc, ATH_DBG_FATAL, + "dma_mapping_error() on RX init\n"); + error = -ENOMEM; + goto err; + } + bf->bf_dmacontext = bf->bf_buf_addr; + } + sc->rx.rxlink = NULL; +err: if (error) ath_rx_cleanup(sc); @@ -345,10 +342,8 @@ void ath_rx_cleanup(struct ath_softc *sc) list_for_each_entry(bf, &sc->rx.rxbuf, list) { skb = bf->bf_mpdu; if (skb) { - dma_unmap_single(sc->dev, - bf->bf_buf_addr, - sc->rx.bufsize, - DMA_FROM_DEVICE); + dma_unmap_single(sc->dev, bf->bf_buf_addr, + sc->rx.bufsize, DMA_FROM_DEVICE); dev_kfree_skb(skb); } } diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 735256faa0b2..628b780d8844 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -2047,44 +2047,38 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) { int error = 0; - do { - spin_lock_init(&sc->tx.txbuflock); + spin_lock_init(&sc->tx.txbuflock); - error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, - "tx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", - error); - break; - } - - error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", - error); - break; - } + error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, + "tx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate tx descriptors: %d\n", error); + goto err; + } - } while (0); + error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, + "beacon", ATH_BCBUF, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate beacon descriptors: %d\n", error); + goto err; + } +err: if (error != 0) ath_tx_cleanup(sc); return error; } -int ath_tx_cleanup(struct ath_softc *sc) +void ath_tx_cleanup(struct ath_softc *sc) { if (sc->beacon.bdma.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); if (sc->tx.txdma.dd_desc_len != 0) ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); - - return 0; } void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) -- cgit v1.2.3 From 1ffb0610be915650cff44c69dc6728215eae08c0 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:46 +0530 Subject: ath9k: Initialize values when setting up the queue parameters Also fix a small typo. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0c1cc2d62a80..0917def0e081 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -922,7 +922,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); } else { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n"); + DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); sc->curaid = 0; } } @@ -2036,8 +2036,7 @@ static int ath9k_start(struct ieee80211_hw *hw) * here except setup the interrupt mask. */ if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to start recv logic\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); r = -EIO; goto mutex_unlock; } @@ -2551,6 +2550,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, mutex_lock(&sc->mutex); + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + qi.tqi_aifs = params->aifs; qi.tqi_cwmin = params->cw_min; qi.tqi_cwmax = params->cw_max; -- cgit v1.2.3 From 87792efc7d20a21844eb7f4247e7b9027e783ec0 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:48 +0530 Subject: ath9k: Trivial fix to handle AMPDU params properly Handle aggregation params only when aggregation is supported. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0917def0e081..99a6852871e2 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -434,12 +434,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) an = (struct ath_node *)sta->drv_priv; - if (sc->sc_flags & SC_OP_TXAGGR) + if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); - - an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + - sta->ht_cap.ampdu_factor); - an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); + an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + + sta->ht_cap.ampdu_factor); + an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); + } } static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) -- cgit v1.2.3 From 063d8be37d6f5818976a1185db4af55c5a5ae809 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:49 +0530 Subject: ath9k: Clean Interrupt handling routine This patch cleans up the ISR, removing a unnecessary do..while loop, and waking up the chip before getting the pending interrupts. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 197 ++++++++++++++++++-------------------- 1 file changed, 95 insertions(+), 102 deletions(-) diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 99a6852871e2..76c58cc74b27 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -456,133 +456,124 @@ static void ath9k_tasklet(unsigned long data) u32 status = sc->intrstatus; if (status & ATH9K_INT_FATAL) { - /* need a chip reset */ ath_reset(sc, false); return; - } else { + } - if (status & - (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { - spin_lock_bh(&sc->rx.rxflushlock); - ath_rx_tasklet(sc, 0); - spin_unlock_bh(&sc->rx.rxflushlock); - } - /* XXX: optimize this */ - if (status & ATH9K_INT_TX) - ath_tx_tasklet(sc); + if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { + spin_lock_bh(&sc->rx.rxflushlock); + ath_rx_tasklet(sc, 0); + spin_unlock_bh(&sc->rx.rxflushlock); } + if (status & ATH9K_INT_TX) + ath_tx_tasklet(sc); + /* re-enable hardware interrupt */ ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); } irqreturn_t ath_isr(int irq, void *dev) { +#define SCHED_INTR ( \ + ATH9K_INT_FATAL | \ + ATH9K_INT_RXORN | \ + ATH9K_INT_RXEOL | \ + ATH9K_INT_RX | \ + ATH9K_INT_TX | \ + ATH9K_INT_BMISS | \ + ATH9K_INT_CST | \ + ATH9K_INT_TSFOOR) + struct ath_softc *sc = dev; struct ath_hw *ah = sc->sc_ah; enum ath9k_int status; bool sched = false; - do { - if (sc->sc_flags & SC_OP_INVALID) { - /* - * The hardware is not ready/present, don't - * touch anything. Note this can happen early - * on if the IRQ is shared. - */ - return IRQ_NONE; - } - if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ - return IRQ_NONE; - } + /* + * The hardware is not ready/present, don't + * touch anything. Note this can happen early + * on if the IRQ is shared. + */ + if (sc->sc_flags & SC_OP_INVALID) + return IRQ_NONE; - /* - * Figure out the reason(s) for the interrupt. Note - * that the hal returns a pseudo-ISR that may include - * bits we haven't explicitly enabled so we mask the - * value to insure we only process bits we requested. - */ - ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ + ath9k_ps_wakeup(sc); - status &= sc->imask; /* discard unasked-for bits */ + /* shared irq, not for us */ + + if (!ath9k_hw_intrpend(ah)) { + ath9k_ps_restore(sc); + return IRQ_NONE; + } + + /* + * Figure out the reason(s) for the interrupt. Note + * that the hal returns a pseudo-ISR that may include + * bits we haven't explicitly enabled so we mask the + * value to insure we only process bits we requested. + */ + ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ + status &= sc->imask; /* discard unasked-for bits */ + + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). + */ + if (!status) { + ath9k_ps_restore(sc); + return IRQ_NONE; + } + /* Cache the status */ + sc->intrstatus = status; + + if (status & SCHED_INTR) + sched = true; + + /* + * If a FATAL or RXORN interrupt is received, we have to reset the + * chip immediately. + */ + if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) + goto chip_reset; + + if (status & ATH9K_INT_SWBA) + tasklet_schedule(&sc->bcon_tasklet); + + if (status & ATH9K_INT_TXURN) + ath9k_hw_updatetxtriglevel(ah, true); + + if (status & ATH9K_INT_MIB) { /* - * If there are no status bits set, then this interrupt was not - * for me (should have been caught above). + * Disable interrupts until we service the MIB + * interrupt; otherwise it will continue to + * fire. */ - if (!status) - return IRQ_NONE; - - sc->intrstatus = status; - ath9k_ps_wakeup(sc); + ath9k_hw_set_interrupts(ah, 0); + /* + * Let the hal handle the event. We assume + * it will clear whatever condition caused + * the interrupt. + */ + ath9k_hw_procmibevent(ah, &sc->nodestats); + ath9k_hw_set_interrupts(ah, sc->imask); + } - if (status & ATH9K_INT_FATAL) { - /* need a chip reset */ - sched = true; - } else if (status & ATH9K_INT_RXORN) { - /* need a chip reset */ + if (status & ATH9K_INT_TIM_TIMER) { + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + /* Clear RxAbort bit so that we can + * receive frames */ + ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); + ath9k_hw_setrxabort(ah, 0); sched = true; - } else { - if (status & ATH9K_INT_SWBA) { - /* schedule a tasklet for beacon handling */ - tasklet_schedule(&sc->bcon_tasklet); - } - if (status & ATH9K_INT_RXEOL) { - /* - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work - * at least on older hardware revs. - */ - sched = true; - } - - if (status & ATH9K_INT_TXURN) - /* bump tx trigger level */ - ath9k_hw_updatetxtriglevel(ah, true); - /* XXX: optimize this */ - if (status & ATH9K_INT_RX) - sched = true; - if (status & ATH9K_INT_TX) - sched = true; - if (status & ATH9K_INT_BMISS) - sched = true; - /* carrier sense timeout */ - if (status & ATH9K_INT_CST) - sched = true; - if (status & ATH9K_INT_MIB) { - /* - * Disable interrupts until we service the MIB - * interrupt; otherwise it will continue to - * fire. - */ - ath9k_hw_set_interrupts(ah, 0); - /* - * Let the hal handle the event. We assume - * it will clear whatever condition caused - * the interrupt. - */ - ath9k_hw_procmibevent(ah, &sc->nodestats); - ath9k_hw_set_interrupts(ah, sc->imask); - } - if (status & ATH9K_INT_TIM_TIMER) { - if (!(ah->caps.hw_caps & - ATH9K_HW_CAP_AUTOSLEEP)) { - /* Clear RxAbort bit so that we can - * receive frames */ - ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); - ath9k_hw_setrxabort(ah, 0); - sched = true; - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; - } - } - if (status & ATH9K_INT_TSFOOR) { - /* FIXME: Handle this interrupt for power save */ - sched = true; - } + sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; } - ath9k_ps_restore(sc); - } while (0); + } +chip_reset: + + ath9k_ps_restore(sc); ath_debug_stat_interrupt(sc, status); if (sched) { @@ -592,6 +583,8 @@ irqreturn_t ath_isr(int irq, void *dev) } return IRQ_HANDLED; + +#undef SCHED_INTR } static u32 ath_get_extchanmode(struct ath_softc *sc, -- cgit v1.2.3 From c6483cfe7147534719197c03a99848f49e004308 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:56 +0530 Subject: ath9k: Determine number of streams from HT capabilities The number of streams supported by a STA can be determined directly from the HT capabilities. Remove the redundant variable storing the stream cap. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 18 ++++++++---------- drivers/net/wireless/ath9k/rc.h | 2 -- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 824ccbb8b7b8..a6933ccab483 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -524,7 +524,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, u32 valid; for (i = 0; i < rate_table->rate_cnt; i++) { - valid = (ath_rc_priv->single_stream ? + valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? rate_table->info[i].valid_single_stream : rate_table->info[i].valid); if (valid == 1) { @@ -557,9 +557,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; - u32 valid = (ath_rc_priv->single_stream ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); + u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? + rate_table->info[j].valid_single_stream : + rate_table->info[j].valid); u8 rate = rateset->rs_rates[i]; u8 dot11rate = rate_table->info[j].dot11rate; @@ -603,7 +603,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, for (i = 0; i < rateset->rs_nrates; i++) { for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; - u32 valid = (ath_rc_priv->single_stream ? + u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? rate_table->info[j].valid_single_stream : rate_table->info[j].valid); u8 rate = rateset->rs_rates[i]; @@ -740,9 +740,10 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, if (rate > (ath_rc_priv->rate_table_size - 1)) rate = ath_rc_priv->rate_table_size - 1; - ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || + ASSERT((rate_table->info[rate].valid && + (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) || (rate_table->info[rate].valid_single_stream && - ath_rc_priv->single_stream)); + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))); return rate; } @@ -1422,9 +1423,6 @@ static void ath_rc_init(struct ath_softc *sc, } ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG; - /* Set stream capability */ - ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1; - if (!rateset->rs_nrates) { /* No working rate, just initialize valid rates */ hi = ath_rc_init_validrates(ath_rc_priv, rate_table, diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index ec72dd29da00..bdfd2052077c 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h @@ -157,7 +157,6 @@ struct ath_rateset { * @probe_interval: interval for ratectrl to probe for other rates * @prev_data_rix: rate idx of last data frame * @ht_cap: HT capabilities - * @single_stream: When TRUE, only single TX stream possible * @neg_rates: Negotatied rates * @neg_ht_rates: Negotiated HT rates */ @@ -175,7 +174,6 @@ struct ath_rate_priv { u8 max_valid_rate; u8 valid_rate_index[RATE_TABLE_SIZE]; u8 ht_cap; - u8 single_stream; u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; u8 rc_phy_mode; -- cgit v1.2.3 From f5c38ef06e005705ef87b7a77752c183bacb94cc Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 30 Mar 2009 15:28:57 +0530 Subject: ath9k: Fix bug in determining HT40 mode This patch fixes a bug in checking for HT40 mode. The STA's mode can be determined from the cached HT capabilities, use that and remove the redundant variable 'rc_phy_mode'. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 6 ++---- drivers/net/wireless/ath9k/rc.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index a6933ccab483..a13668b9b6dc 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1321,7 +1321,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, * 40 to 20 => don't update */ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) + !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; rix = ath_rc_get_rateindex(rate_table, &rates[i]); @@ -1346,9 +1346,8 @@ static void ath_rc_tx_status(struct ath_softc *sc, /* If HT40 and we have switched mode from 40 to 20 => don't update */ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) { + !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) return; - } rix = ath_rc_get_rateindex(rate_table, &rates[i]); ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, @@ -1421,7 +1420,6 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->valid_phy_rateidx[i][j] = 0; ath_rc_priv->valid_phy_ratecnt[i] = 0; } - ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG; if (!rateset->rs_nrates) { /* No working rate, just initialize valid rates */ diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index bdfd2052077c..e3abd76103fd 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h @@ -176,7 +176,6 @@ struct ath_rate_priv { u8 ht_cap; u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; - u8 rc_phy_mode; u8 rate_max_phy; u32 rssi_time; u32 rssi_down_time; -- cgit v1.2.3 From d5522e039586fdf72493225a88b944f726b69671 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Mar 2009 13:23:35 +0200 Subject: mac80211: move ieee80211_enable_ht function to mlme.c It really belongs into that file since it is only relevant for managed mode. Move 1:1, not even whitespace changes, but make it static and remove from header file. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ht.c | 83 ---------------------------------------------- net/mac80211/ieee80211_i.h | 3 -- net/mac80211/mlme.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 86 deletions(-) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 4e3c72f20de7..73bd427750ef 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -83,89 +83,6 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, ht_cap->mcs.rx_mask[32/8] |= 1; } -/* - * ieee80211_enable_ht should be called only after the operating band - * has been determined as ht configuration depends on the hw's - * HT abilities for a specific band. - */ -u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, - struct ieee80211_ht_info *hti, - u16 ap_ht_cap_flags) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_bss_ht_conf ht; - struct sta_info *sta; - u32 changed = 0; - bool enable_ht = true, ht_changed; - enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - memset(&ht, 0, sizeof(ht)); - - /* HT is not supported */ - if (!sband->ht_cap.ht_supported) - enable_ht = false; - - /* check that channel matches the right operating channel */ - if (local->hw.conf.channel->center_freq != - ieee80211_channel_to_frequency(hti->control_chan)) - enable_ht = false; - - if (enable_ht) { - channel_type = NL80211_CHAN_HT20; - - if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && - (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { - switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - channel_type = NL80211_CHAN_HT40MINUS; - break; - } - } - } - - ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || - channel_type != local->hw.conf.channel_type; - - local->oper_channel_type = channel_type; - - if (ht_changed) { - /* channel_type change automatically detected */ - ieee80211_hw_config(local, 0); - - rcu_read_lock(); - - sta = sta_info_get(local, ifmgd->bssid); - if (sta) - rate_control_rate_update(local, sband, sta, - IEEE80211_RC_HT_CHANGED); - - rcu_read_unlock(); - - } - - /* disable HT */ - if (!enable_ht) - return 0; - - ht.operation_mode = le16_to_cpu(hti->operation_mode); - - /* if bss configuration changed store the new one */ - if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) { - changed |= BSS_CHANGED_HT; - sdata->vif.bss_conf.ht = ht; - } - - return changed; -} - void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) { int i; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 312347d102c8..73d9f894ed5d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -995,9 +995,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_sta_ht_cap *ht_cap); -u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, - struct ieee80211_ht_info *hti, - u16 ap_ht_cap_flags); void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 08db02c237c9..4ce5b9c22324 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -80,6 +80,89 @@ static int ieee80211_compatible_rates(struct ieee80211_bss *bss, return count; } +/* + * ieee80211_enable_ht should be called only after the operating band + * has been determined as ht configuration depends on the hw's + * HT abilities for a specific band. + */ +static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, + struct ieee80211_ht_info *hti, + u16 ap_ht_cap_flags) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_bss_ht_conf ht; + struct sta_info *sta; + u32 changed = 0; + bool enable_ht = true, ht_changed; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + memset(&ht, 0, sizeof(ht)); + + /* HT is not supported */ + if (!sband->ht_cap.ht_supported) + enable_ht = false; + + /* check that channel matches the right operating channel */ + if (local->hw.conf.channel->center_freq != + ieee80211_channel_to_frequency(hti->control_chan)) + enable_ht = false; + + if (enable_ht) { + channel_type = NL80211_CHAN_HT20; + + if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && + (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && + (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { + switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + channel_type = NL80211_CHAN_HT40PLUS; + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + channel_type = NL80211_CHAN_HT40MINUS; + break; + } + } + } + + ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || + channel_type != local->hw.conf.channel_type; + + local->oper_channel_type = channel_type; + + if (ht_changed) { + /* channel_type change automatically detected */ + ieee80211_hw_config(local, 0); + + rcu_read_lock(); + + sta = sta_info_get(local, ifmgd->bssid); + if (sta) + rate_control_rate_update(local, sband, sta, + IEEE80211_RC_HT_CHANGED); + + rcu_read_unlock(); + + } + + /* disable HT */ + if (!enable_ht) + return 0; + + ht.operation_mode = le16_to_cpu(hti->operation_mode); + + /* if bss configuration changed store the new one */ + if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) { + changed |= BSS_CHANGED_HT; + sdata->vif.bss_conf.ht = ht; + } + + return changed; +} + /* frame sending functions */ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) -- cgit v1.2.3 From 42639fcd443d97a9a471f4b8269620286dd7036b Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 30 Mar 2009 08:05:29 -0400 Subject: ath5k: reduce exported channel list Claiming every available 5 ghz channel has a couple of negative side-effects: scanning takes a long time, and the channel list overflows the available buffer space for netlink commands, resulting in: $ iw phy phy0 info command failed: No buffer space available (-105) This patch adds a modparam so people who want to see all the channels can do so by passing all_channels=1. By default users will see a smaller list of channels. This also halves scan time, from 10 seconds down to less than 5 when using world regulatory. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Reported-by: Simon Farnsworth Tested-By: Simon Farnsworth Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index a08bc8a4fb69..d8c60c53d953 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -64,6 +64,10 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static int modparam_all_channels; +module_param_named(all_channels, modparam_all_channels, int, 0444); +MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); + /******************\ * Internal defines * @@ -862,6 +866,20 @@ ath5k_ieee2mhz(short chan) return 2212 + chan * 20; } +/* + * Returns true for the channel numbers used without all_channels modparam. + */ +static bool ath5k_is_standard_channel(short chan) +{ + return ((chan <= 14) || + /* UNII 1,2 */ + ((chan & 3) == 0 && chan >= 36 && chan <= 64) || + /* midband */ + ((chan & 3) == 0 && chan >= 100 && chan <= 140) || + /* UNII-3 */ + ((chan & 3) == 1 && chan >= 149 && chan <= 165)); +} + static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, @@ -899,6 +917,9 @@ ath5k_copy_channels(struct ath5k_hw *ah, if (!ath5k_channel_ok(ah, freq, chfreq)) continue; + if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) + continue; + /* Write channel info and increment counter */ channels[count].center_freq = freq; channels[count].band = (chfreq == CHANNEL_2GHZ) ? -- cgit v1.2.3 From ae3d2462f89db4592ea71e8f6e326d4b38dc952c Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Mon, 30 Mar 2009 11:04:04 -0700 Subject: net/ps3: Update maintainer Update the MAINTAINERS entry for PS3 NETWORK SUPPORT. CC: Masakazu Mokuno Signed-off-by: Geoff Levand Signed-off-by: John W. Linville --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6dfcb6d03a97..3dfe1a7c9a93 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4427,8 +4427,8 @@ S: Maintained F: drivers/ata/sata_promise.* PS3 NETWORK SUPPORT -P: Masakazu Mokuno -M: mokuno@sm.sony.co.jp +P: Geoff Levand +M: geoffrey.levand@am.sony.com L: netdev@vger.kernel.org L: cbe-oss-dev@ozlabs.org S: Supported -- cgit v1.2.3 From cf3a9579f61c643c15c172da0baf5429578b0ba3 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 25 Mar 2009 03:11:58 +0100 Subject: p54: clean up p54.h's struct p54_common This patch rearrange and regroups most elements in p54_common. Signed-off-by: Christian Lamparter Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 67 ++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index ecf8b6ed5a47..04d95a143383 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -133,55 +133,72 @@ struct p54_led_dev { struct p54_common { struct ieee80211_hw *hw; - u32 rx_start; - u32 rx_end; - struct sk_buff_head tx_queue; void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb); int (*open)(struct ieee80211_hw *dev); void (*stop)(struct ieee80211_hw *dev); - int mode; + struct sk_buff_head tx_queue; + struct mutex conf_mutex; + + /* memory management (as seen by the firmware) */ + u32 rx_start; + u32 rx_end; u16 rx_mtu; u8 headroom; u8 tailroom; - struct mutex conf_mutex; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; + + /* firmware/hardware info */ + unsigned int tx_hdr_len; + unsigned int fw_var; + unsigned int fw_interface; + u8 version; + + /* (e)DCF / QOS state */ + bool use_short_slot; + struct ieee80211_tx_queue_stats tx_stats[8]; + struct p54_edcf_queue_param qos_params[8]; + + /* Radio data */ + u16 rxhw; u8 rx_diversity_mask; u8 tx_diversity_mask; + unsigned int output_power; + int noise; + /* calibration, output power limit and rssi<->dBm conversation data */ struct pda_iq_autocal_entry *iq_autocal; unsigned int iq_autocal_len; - struct p54_cal_database *output_limit; struct p54_cal_database *curve_data; + struct p54_cal_database *output_limit; struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; + + /* BBP/MAC state */ + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u16 wakeup_timer; unsigned int filter_flags; - bool use_short_slot; - u16 rxhw; - u8 version; - unsigned int tx_hdr_len; - unsigned int fw_var; - unsigned int fw_interface; - unsigned int output_power; - u32 tsf_low32; - u32 tsf_high32; + int mode; + u32 tsf_low32, tsf_high32; u32 basic_rate_mask; - u16 wakeup_timer; u16 aid; - struct ieee80211_tx_queue_stats tx_stats[8]; - struct p54_edcf_queue_param qos_params[8]; - struct ieee80211_low_level_stats stats; - struct delayed_work work; struct sk_buff *cached_beacon; - int noise; - void *eeprom; - struct completion eeprom_comp; + + /* cryptographic engine information */ u8 privacy_caps; u8 rx_keycache_size; + /* LED management */ #ifdef CONFIG_P54_LEDS struct p54_led_dev assoc_led; struct p54_led_dev tx_led; #endif /* CONFIG_P54_LEDS */ u16 softled_state; /* bit field of glowing LEDs */ + + /* statistics */ + struct ieee80211_low_level_stats stats; + struct delayed_work work; + + /* eeprom handling */ + void *eeprom; + struct completion eeprom_comp; }; int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); -- cgit v1.2.3 From dce072580e095d1fb7be59a1be30dc0e8307821b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 25 Mar 2009 03:12:18 +0100 Subject: p54: more SoftLED updates This patch hopefully finishes the SoftLED code: - It adds two more LEDs (rx and radio). (the FW claims it can support up to 16 LEDs, but I doubt that any vendor put more than 4 on a board) - update the LEDs in a _delayed_ workqueue. No one reported any more crashes. (see: "PATCH] p54: fix race condition in memory management") So we can stop burning the mm code. Signed-off-by: Christian Lamparter Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 9 ++-- drivers/net/wireless/p54/p54common.c | 84 ++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 04d95a143383..4499035359a6 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -125,6 +125,7 @@ struct p54_led_dev { struct led_classdev led_dev; char name[P54_LED_MAX_NAME_LEN + 1]; + unsigned int toggled; unsigned int index; unsigned int registered; }; @@ -186,10 +187,10 @@ struct p54_common { u8 rx_keycache_size; /* LED management */ -#ifdef CONFIG_P54_LEDS - struct p54_led_dev assoc_led; - struct p54_led_dev tx_led; -#endif /* CONFIG_P54_LEDS */ +#ifdef CONFIG_MAC80211_LEDS + struct p54_led_dev leds[4]; + struct delayed_work led_work; +#endif /* CONFIG_MAC80211_LEDS */ u16 softled_state; /* bit field of glowing LEDs */ /* statistics */ diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c8f0232ee5e0..696067e69ee4 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2088,6 +2088,9 @@ static void p54_stop(struct ieee80211_hw *dev) priv->softled_state = 0; p54_set_leds(dev); +#ifdef CONFIG_P54_LEDS + cancel_delayed_work_sync(&priv->led_work); +#endif /* CONFIG_P54_LEDS */ cancel_delayed_work_sync(&priv->work); if (priv->cached_beacon) p54_tx_cancel(dev, priv->cached_beacon); @@ -2421,6 +2424,43 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, } #ifdef CONFIG_P54_LEDS +static void p54_update_leds(struct work_struct *work) +{ + struct p54_common *priv = container_of(work, struct p54_common, + led_work.work); + int err, i, tmp, blink_delay = 400; + bool rerun = false; + + /* Don't toggle the LED, when the device is down. */ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return ; + + for (i = 0; i < ARRAY_SIZE(priv->leds); i++) + if (priv->leds[i].toggled) { + priv->softled_state |= BIT(i); + + tmp = 70 + 200 / (priv->leds[i].toggled); + if (tmp < blink_delay) + blink_delay = tmp; + + if (priv->leds[i].led_dev.brightness == LED_OFF) + rerun = true; + + priv->leds[i].toggled = + !!priv->leds[i].led_dev.brightness; + } else + priv->softled_state &= ~BIT(i); + + err = p54_set_leds(priv->hw); + if (err && net_ratelimit()) + printk(KERN_ERR "%s: failed to update LEDs.\n", + wiphy_name(priv->hw->wiphy)); + + if (rerun) + queue_delayed_work(priv->hw->workqueue, &priv->led_work, + msecs_to_jiffies(blink_delay)); +} + static void p54_led_brightness_set(struct led_classdev *led_dev, enum led_brightness brightness) { @@ -2428,28 +2468,23 @@ static void p54_led_brightness_set(struct led_classdev *led_dev, led_dev); struct ieee80211_hw *dev = led->hw_dev; struct p54_common *priv = dev->priv; - int err; - /* Don't toggle the LED, when the device is down. */ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) return ; - if (brightness != LED_OFF) - priv->softled_state |= BIT(led->index); - else - priv->softled_state &= ~BIT(led->index); - - err = p54_set_leds(dev); - if (err && net_ratelimit()) - printk(KERN_ERR "%s: failed to update %s LED.\n", - wiphy_name(dev->wiphy), led_dev->name); + if (brightness) { + led->toggled++; + queue_delayed_work(priv->hw->workqueue, &priv->led_work, + HZ/10); + } } static int p54_register_led(struct ieee80211_hw *dev, - struct p54_led_dev *led, unsigned int led_index, char *name, char *trigger) { + struct p54_common *priv = dev->priv; + struct p54_led_dev *led = &priv->leds[led_index]; int err; if (led->registered) @@ -2482,19 +2517,30 @@ static int p54_init_leds(struct ieee80211_hw *dev) * TODO: * Figure out if the EEPROM contains some hints about the number * of available/programmable LEDs of the device. - * But for now, we can assume that we have two programmable LEDs. */ - err = p54_register_led(dev, &priv->assoc_led, 0, "assoc", + INIT_DELAYED_WORK(&priv->led_work, p54_update_leds); + + err = p54_register_led(dev, 0, "assoc", ieee80211_get_assoc_led_name(dev)); if (err) return err; - err = p54_register_led(dev, &priv->tx_led, 1, "tx", + err = p54_register_led(dev, 1, "tx", ieee80211_get_tx_led_name(dev)); if (err) return err; + err = p54_register_led(dev, 2, "rx", + ieee80211_get_rx_led_name(dev)); + if (err) + return err; + + err = p54_register_led(dev, 3, "radio", + ieee80211_get_radio_led_name(dev)); + if (err) + return err; + err = p54_set_leds(dev); return err; } @@ -2502,11 +2548,11 @@ static int p54_init_leds(struct ieee80211_hw *dev) static void p54_unregister_leds(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; + int i; - if (priv->tx_led.registered) - led_classdev_unregister(&priv->tx_led.led_dev); - if (priv->assoc_led.registered) - led_classdev_unregister(&priv->assoc_led.led_dev); + for (i = 0; i < ARRAY_SIZE(priv->leds); i++) + if (priv->leds[i].registered) + led_classdev_unregister(&priv->leds[i].led_dev); } #endif /* CONFIG_P54_LEDS */ -- cgit v1.2.3 From f13027af5cd567757c18b85776232e31a2ba55d4 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 25 Mar 2009 03:12:49 +0100 Subject: p54: add beacon filtering support This patch adds beacon filtering support to p54. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 1 + drivers/net/wireless/p54/p54common.c | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 4499035359a6..d6354faaa2bc 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -134,6 +134,7 @@ struct p54_led_dev { struct p54_common { struct ieee80211_hw *hw; + struct ieee80211_vif *vif; void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb); int (*open)(struct ieee80211_hw *dev); void (*stop)(struct ieee80211_hw *dev); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 696067e69ee4..cb490584cb8e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1044,6 +1044,7 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb) static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) { + struct p54_common *priv = dev->priv; struct p54_hdr *hdr = (struct p54_hdr *) skb->data; struct p54_trap *trap = (struct p54_trap *) hdr->data; u16 event = le16_to_cpu(trap->event); @@ -1057,6 +1058,8 @@ static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) wiphy_name(dev->wiphy), freq); break; case P54_TRAP_NO_BEACON: + if (priv->vif) + ieee80211_beacon_loss(priv->vif); break; case P54_TRAP_SCAN: break; @@ -1939,7 +1942,8 @@ static int p54_set_ps(struct ieee80211_hw *dev) int i; if (dev->conf.flags & IEEE80211_CONF_PS) - mode = P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC; + mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | + P54_PSM_CHECKSUM | P54_PSM_MCBC; else mode = P54_PSM_CAM; @@ -1957,9 +1961,10 @@ static int p54_set_ps(struct ieee80211_hw *dev) psm->intervals[i].periods = cpu_to_le16(1); } - psm->beacon_rssi_skip_max = 60; + psm->beacon_rssi_skip_max = 200; psm->rssi_delta_threshold = 0; - psm->nr = 0; + psm->nr = 10; + psm->exclude[0] = 0; priv->tx(dev, skb); @@ -2114,6 +2119,8 @@ static int p54_add_interface(struct ieee80211_hw *dev, return -EOPNOTSUPP; } + priv->vif = conf->vif; + switch (conf->type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: @@ -2138,6 +2145,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev, struct p54_common *priv = dev->priv; mutex_lock(&priv->conf_mutex); + priv->vif = NULL; if (priv->cached_beacon) p54_tx_cancel(dev, priv->cached_beacon); priv->mode = NL80211_IFTYPE_MONITOR; @@ -2590,7 +2598,8 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) skb_queue_head_init(&priv->tx_queue); dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_NOISE_DBM | + IEEE80211_HW_BEACON_FILTER; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | -- cgit v1.2.3 From 5c8fa4f7e7fcceabb3b37d7ec66d3e7115a4bba3 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 26 Mar 2009 23:39:53 +0200 Subject: rndis_wlan: initiate cfg80211 conversion Signed-off-by: John W. Linville Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 114 ++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index db91db776508..c995d7c3139c 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -316,12 +318,44 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, #define COMMAND_BUFFER_SIZE (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set)) +static const struct ieee80211_channel rndis_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + +static const struct ieee80211_rate rndis_rates[] = { + { .bitrate = 10 }, + { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60 }, + { .bitrate = 90 }, + { .bitrate = 120 }, + { .bitrate = 180 }, + { .bitrate = 240 }, + { .bitrate = 360 }, + { .bitrate = 480 }, + { .bitrate = 540 } +}; + /* RNDIS device private data */ struct rndis_wext_private { - char name[32]; - struct usbnet *usbdev; + struct wireless_dev wdev; + struct workqueue_struct *workqueue; struct delayed_work stats_work; struct work_struct work; @@ -329,6 +363,10 @@ struct rndis_wext_private { spinlock_t stats_lock; unsigned long work_pending; + struct ieee80211_supported_band band; + struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; + struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; + struct iw_statistics iwstats; struct iw_statistics privstats; @@ -369,7 +407,8 @@ struct rndis_wext_private { }; -static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 }; +struct cfg80211_ops rndis_config_ops = { }; +void *rndis_wiphy_privid = &rndis_wiphy_privid; static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; @@ -1151,15 +1190,15 @@ static int rndis_iw_get_range(struct net_device *dev, /* fill in 802.11g rates */ if (has_80211g_rates) { num = range->num_bitrates; - for (i = 0; i < ARRAY_SIZE(rates_80211g); i++) { + for (i = 4; i < ARRAY_SIZE(rndis_rates); i++) { for (j = 0; j < num; j++) { if (range->bitrate[j] == - rates_80211g[i] * 1000000) + rndis_rates[i].bitrate * 100000) break; } if (j == num) range->bitrate[range->num_bitrates++] = - rates_80211g[i] * 1000000; + rndis_rates[i].bitrate * 100000; if (range->num_bitrates == IW_MAX_BITRATES) break; } @@ -1204,17 +1243,6 @@ static int rndis_iw_get_range(struct net_device *dev, } -static int rndis_iw_get_name(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - strcpy(wrqu->name, priv->name); - return 0; -} - - static int rndis_iw_set_essid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { @@ -2165,7 +2193,7 @@ static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev) static const iw_handler rndis_iw_handler[] = { IW_IOCTL(SIOCSIWCOMMIT) = rndis_iw_commit, - IW_IOCTL(SIOCGIWNAME) = rndis_iw_get_name, + IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq, IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq, IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode, @@ -2338,12 +2366,6 @@ static int rndis_wext_get_caps(struct usbnet *usbdev) break; } } - if (priv->caps & CAP_MODE_80211A) - strcat(priv->name, "a"); - if (priv->caps & CAP_MODE_80211B) - strcat(priv->name, "b"); - if (priv->caps & CAP_MODE_80211G) - strcat(priv->name, "g"); } return retval; @@ -2538,20 +2560,28 @@ static const struct net_device_ops rndis_wext_netdev_ops = { static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) { + struct wiphy *wiphy; struct rndis_wext_private *priv; int retval, len; __le32 tmp; - /* allocate rndis private data */ - priv = kzalloc(sizeof(struct rndis_wext_private), GFP_KERNEL); - if (!priv) + /* allocate wiphy and rndis private data + * NOTE: We only support a single virtual interface, so wiphy + * and wireless_dev are somewhat synonymous for this device. + */ + wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wext_private)); + if (!wiphy) return -ENOMEM; + priv = wiphy_priv(wiphy); + usbdev->net->ieee80211_ptr = &priv->wdev; + priv->wdev.wiphy = wiphy; + priv->wdev.iftype = NL80211_IFTYPE_STATION; + /* These have to be initialized before calling generic_rndis_bind(). * Otherwise we'll be in big trouble in rndis_wext_early_init(). */ usbdev->driver_priv = priv; - strcpy(priv->name, "IEEE802.11"); usbdev->net->wireless_handlers = &rndis_iw_handlers; priv->usbdev = usbdev; @@ -2595,7 +2625,31 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) | IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; + /* fill-out wiphy structure and register w/ cfg80211 */ + memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN); + wiphy->privid = rndis_wiphy_privid; + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC); + wiphy->max_scan_ssids = 1; + + /* TODO: fill-out band information based on priv->caps */ rndis_wext_get_caps(usbdev); + + memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); + memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rndis_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(rndis_rates); + wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + set_wiphy_dev(wiphy, &usbdev->udev->dev); + + if (wiphy_register(wiphy)) { + wiphy_free(wiphy); + return -ENODEV; + } + set_default_iw_params(usbdev); /* turn radio on */ @@ -2632,9 +2686,11 @@ static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf) if (priv && priv->wpa_ie_len) kfree(priv->wpa_ie); - kfree(priv); rndis_unbind(usbdev, intf); + + wiphy_unregister(priv->wdev.wiphy); + wiphy_free(priv->wdev.wiphy); } -- cgit v1.2.3 From 964c1d417e4738d359ba263921a7b9c18fa711c4 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 26 Mar 2009 23:40:01 +0200 Subject: rndis_wlan: convert get/set mode to cfg80211 Signed-off-by: John W. Linville [edit: made rndis_change_virtual_intf static] Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 95 ++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index c995d7c3139c..a8758603e01c 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -406,8 +406,17 @@ struct rndis_wext_private { u8 command_buffer[COMMAND_BUFFER_SIZE]; }; +/* + * cfg80211 ops + */ +static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params); + +struct cfg80211_ops rndis_config_ops = { + .change_virtual_intf = rndis_change_virtual_intf, +}; -struct cfg80211_ops rndis_config_ops = { }; void *rndis_wiphy_privid = &rndis_wiphy_privid; static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; @@ -1124,6 +1133,37 @@ static void set_multicast_list(struct usbnet *usbdev) } +/* + * cfg80211 ops + */ +static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct net_device *dev; + struct usbnet *usbdev; + int mode; + + /* we're under RTNL */ + dev = __dev_get_by_index(&init_net, ifindex); + if (!dev) + return -ENODEV; + usbdev = netdev_priv(dev); + + switch (type) { + case NL80211_IFTYPE_ADHOC: + mode = ndis_80211_infra_adhoc; + break; + case NL80211_IFTYPE_STATION: + mode = ndis_80211_infra_infra; + break; + default: + return -EINVAL; + } + + return set_infra_mode(usbdev, mode); +} + /* * wireless extension handlers */ @@ -1450,55 +1490,6 @@ static int rndis_iw_get_auth(struct net_device *dev, } -static int rndis_iw_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - switch (priv->infra_mode) { - case ndis_80211_infra_adhoc: - wrqu->mode = IW_MODE_ADHOC; - break; - case ndis_80211_infra_infra: - wrqu->mode = IW_MODE_INFRA; - break; - /*case ndis_80211_infra_auto_unknown:*/ - default: - wrqu->mode = IW_MODE_AUTO; - break; - } - devdbg(usbdev, "SIOCGIWMODE: %08x", wrqu->mode); - return 0; -} - - -static int rndis_iw_set_mode(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - int mode; - - devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode); - - switch (wrqu->mode) { - case IW_MODE_ADHOC: - mode = ndis_80211_infra_adhoc; - break; - case IW_MODE_INFRA: - mode = ndis_80211_infra_infra; - break; - /*case IW_MODE_AUTO:*/ - default: - mode = ndis_80211_infra_auto_unknown; - break; - } - - return set_infra_mode(usbdev, mode); -} - - static int rndis_iw_set_encode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -2196,8 +2187,8 @@ static const iw_handler rndis_iw_handler[] = IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq, IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq, - IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode, - IW_IOCTL(SIOCGIWMODE) = rndis_iw_get_mode, + IW_IOCTL(SIOCSIWMODE) = (iw_handler) cfg80211_wext_siwmode, + IW_IOCTL(SIOCGIWMODE) = (iw_handler) cfg80211_wext_giwmode, IW_IOCTL(SIOCGIWRANGE) = rndis_iw_get_range, IW_IOCTL(SIOCSIWAP) = rndis_iw_set_bssid, IW_IOCTL(SIOCGIWAP) = rndis_iw_get_bssid, -- cgit v1.2.3 From 06aa7afaaa21a4e7f1bcb196bd3f29193924a603 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 26 Mar 2009 23:40:09 +0200 Subject: cfg80211: add cfg80211_inform_bss Added cfg80211_inform_bss() for full-mac devices to use. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- include/net/cfg80211.h | 8 ++++++++ net/wireless/scan.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f8bf0c86650b..2b1f6c69773c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -863,6 +863,14 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, struct ieee80211_mgmt *mgmt, size_t len, s32 signal, gfp_t gfp); +struct cfg80211_bss* +cfg80211_inform_bss(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *bssid, + u64 timestamp, u16 capability, u16 beacon_interval, + const u8 *ie, size_t ielen, + s32 signal, gfp_t gfp); + struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, struct ieee80211_channel *channel, const u8 *bssid, diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 2ae65b39b529..1396248dc5cc 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -414,6 +414,55 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, return found; } +struct cfg80211_bss* +cfg80211_inform_bss(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *bssid, + u64 timestamp, u16 capability, u16 beacon_interval, + const u8 *ie, size_t ielen, + s32 signal, gfp_t gfp) +{ + struct cfg80211_internal_bss *res; + size_t privsz; + + if (WARN_ON(!wiphy)) + return NULL; + + privsz = wiphy->bss_priv_size; + + if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && + (signal < 0 || signal > 100))) + return NULL; + + res = kzalloc(sizeof(*res) + privsz + ielen, gfp); + if (!res) + return NULL; + + memcpy(res->pub.bssid, bssid, ETH_ALEN); + res->pub.channel = channel; + res->pub.signal = signal; + res->pub.tsf = timestamp; + res->pub.beacon_interval = beacon_interval; + res->pub.capability = capability; + /* point to after the private area */ + res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; + memcpy(res->pub.information_elements, ie, ielen); + res->pub.len_information_elements = ielen; + + kref_init(&res->ref); + + res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0); + if (!res) + return NULL; + + if (res->pub.capability & WLAN_CAPABILITY_ESS) + regulatory_hint_found_beacon(wiphy, channel, gfp); + + /* cfg80211_bss_update gives us a referenced result */ + return &res->pub; +} +EXPORT_SYMBOL(cfg80211_inform_bss); + struct cfg80211_bss * cfg80211_inform_bss_frame(struct wiphy *wiphy, struct ieee80211_channel *channel, -- cgit v1.2.3 From 4bd7f03e915b6946307ce57f20718c6547734b5d Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 26 Mar 2009 23:40:16 +0200 Subject: rndis_wlan: change quality level scale Change quality level scale to match cfg80211 CFG80211_SIGNAL_TYPE_UNSPEC. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a8758603e01c..9e7956d9c6be 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1269,7 +1269,7 @@ static int rndis_iw_get_range(struct net_device *dev, range->max_frag = 2346; range->max_qual.qual = 100; - range->max_qual.level = 154; + range->max_qual.level = 100; range->max_qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; @@ -1712,7 +1712,7 @@ static char *rndis_translate_scan(struct net_device *dev, devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); iwe.cmd = IWEVQUAL; iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->rssi)); - iwe.u.qual.level = le32_to_cpu(bssid->rssi); + iwe.u.qual.level = level_to_qual(le32_to_cpu(bssid->rssi)); iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; @@ -2400,7 +2400,7 @@ static void rndis_update_wireless_stats(struct work_struct *work) if (ret == 0) { memset(&iwstats.qual, 0, sizeof(iwstats.qual)); iwstats.qual.qual = level_to_qual(le32_to_cpu(rssi)); - iwstats.qual.level = le32_to_cpu(rssi); + iwstats.qual.level = level_to_qual(le32_to_cpu(rssi)); iwstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; -- cgit v1.2.3 From 4d2a369ec09167f423c0783b1cf85cee8102544f Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 26 Mar 2009 23:40:23 +0200 Subject: rndis_wlan: convert get range to cfg80211 Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 110 +------------------------------------- 1 file changed, 2 insertions(+), 108 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9e7956d9c6be..4252903cf89a 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1176,113 +1176,6 @@ static int rndis_iw_commit(struct net_device *dev, } -static int rndis_iw_get_range(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - int len, ret, i, j, num, has_80211g_rates; - u8 rates[8]; - __le32 tx_power; - - devdbg(usbdev, "SIOCGIWRANGE"); - - /* clear iw_range struct */ - memset(range, 0, sizeof(*range)); - wrqu->data.length = sizeof(*range); - - range->txpower_capa = IW_TXPOW_MWATT; - range->num_txpower = 1; - if (priv->caps & CAP_SUPPORT_TXPOWER) { - len = sizeof(tx_power); - ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, - &tx_power, &len); - if (ret == 0 && le32_to_cpu(tx_power) != 0xFF) - range->txpower[0] = le32_to_cpu(tx_power); - else - range->txpower[0] = get_bcm4320_power(priv); - } else - range->txpower[0] = get_bcm4320_power(priv); - - len = sizeof(rates); - ret = rndis_query_oid(usbdev, OID_802_11_SUPPORTED_RATES, &rates, - &len); - has_80211g_rates = 0; - if (ret == 0) { - j = 0; - for (i = 0; i < len; i++) { - if (rates[i] == 0) - break; - range->bitrate[j] = (rates[i] & 0x7f) * 500000; - /* check for non 802.11b rates */ - if (range->bitrate[j] == 6000000 || - range->bitrate[j] == 9000000 || - (range->bitrate[j] >= 12000000 && - range->bitrate[j] != 22000000)) - has_80211g_rates = 1; - j++; - } - range->num_bitrates = j; - } else - range->num_bitrates = 0; - - /* fill in 802.11g rates */ - if (has_80211g_rates) { - num = range->num_bitrates; - for (i = 4; i < ARRAY_SIZE(rndis_rates); i++) { - for (j = 0; j < num; j++) { - if (range->bitrate[j] == - rndis_rates[i].bitrate * 100000) - break; - } - if (j == num) - range->bitrate[range->num_bitrates++] = - rndis_rates[i].bitrate * 100000; - if (range->num_bitrates == IW_MAX_BITRATES) - break; - } - - /* estimated max real througput in bps */ - range->throughput = 54 * 1000 * 1000 / 2; - - /* ~35% more with afterburner */ - if (priv->param_afterburner) - range->throughput = range->throughput / 100 * 135; - } else { - /* estimated max real througput in bps */ - range->throughput = 11 * 1000 * 1000 / 2; - } - - range->num_channels = 14; - - for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) { - range->freq[i].i = i + 1; - range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000; - range->freq[i].e = 1; - } - range->num_frequency = i; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - range->max_qual.qual = 100; - range->max_qual.level = 100; - range->max_qual.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_INVALID; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = WIRELESS_EXT; - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - return 0; -} - - static int rndis_iw_set_essid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { @@ -2189,7 +2082,7 @@ static const iw_handler rndis_iw_handler[] = IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq, IW_IOCTL(SIOCSIWMODE) = (iw_handler) cfg80211_wext_siwmode, IW_IOCTL(SIOCGIWMODE) = (iw_handler) cfg80211_wext_giwmode, - IW_IOCTL(SIOCGIWRANGE) = rndis_iw_get_range, + IW_IOCTL(SIOCGIWRANGE) = (iw_handler) cfg80211_wext_giwrange, IW_IOCTL(SIOCSIWAP) = rndis_iw_set_bssid, IW_IOCTL(SIOCGIWAP) = rndis_iw_get_bssid, IW_IOCTL(SIOCSIWSCAN) = rndis_iw_set_scan, @@ -2633,6 +2526,7 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(rndis_rates); wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; set_wiphy_dev(wiphy, &usbdev->udev->dev); -- cgit v1.2.3 From 71a7b26d3e6404e43574f80236c00eaa39b2525e Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 26 Mar 2009 23:40:31 +0200 Subject: rndis_wlan: convert scan to cfg80211 Convert scan function to cfg80211. Unlike old scan code new code waits 1 sec before getting scan data from device and passing forward to cfg80211. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 341 ++++++++++++++++---------------------- 1 file changed, 147 insertions(+), 194 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 4252903cf89a..239e6a14eae2 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -356,8 +356,11 @@ struct rndis_wext_private { struct wireless_dev wdev; + struct cfg80211_scan_request *scan_request; + struct workqueue_struct *workqueue; struct delayed_work stats_work; + struct delayed_work scan_work; struct work_struct work; struct mutex command_lock; spinlock_t stats_lock; @@ -413,8 +416,12 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, enum nl80211_iftype type, u32 *flags, struct vif_params *params); +static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request); + struct cfg80211_ops rndis_config_ops = { .change_virtual_intf = rndis_change_virtual_intf, + .scan = rndis_scan, }; void *rndis_wiphy_privid = &rndis_wiphy_privid; @@ -1164,6 +1171,142 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, return set_infra_mode(usbdev, mode); } + +#define SCAN_DELAY_JIFFIES (HZ) +static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) +{ + struct usbnet *usbdev = netdev_priv(dev); + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + int ret; + __le32 tmp; + + devdbg(usbdev, "cfg80211.scan"); + + if (!request) + return -EINVAL; + + if (priv->scan_request && priv->scan_request != request) + return -EBUSY; + + priv->scan_request = request; + + tmp = cpu_to_le32(1); + ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, + sizeof(tmp)); + if (ret == 0) { + /* Wait before retrieving scan results from device */ + queue_delayed_work(priv->workqueue, &priv->scan_work, + SCAN_DELAY_JIFFIES); + } + + return ret; +} + + +static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, + struct ndis_80211_bssid_ex *bssid) +{ + struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); + struct ieee80211_channel *channel; + s32 signal; + u64 timestamp; + u16 capability; + u16 beacon_interval; + struct ndis_80211_fixed_ies *fixed; + int ie_len, bssid_len; + u8 *ie; + + /* parse bssid structure */ + bssid_len = le32_to_cpu(bssid->length); + + if (bssid_len < sizeof(struct ndis_80211_bssid_ex) + + sizeof(struct ndis_80211_fixed_ies)) + return NULL; + + fixed = (struct ndis_80211_fixed_ies *)bssid->ies; + + ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); + ie_len = min(bssid_len - (int)sizeof(*bssid), + (int)le32_to_cpu(bssid->ie_length)); + ie_len -= sizeof(struct ndis_80211_fixed_ies); + if (ie_len < 0) + return NULL; + + /* extract data for cfg80211_inform_bss */ + channel = ieee80211_get_channel(priv->wdev.wiphy, + KHZ_TO_MHZ(le32_to_cpu(bssid->config.ds_config))); + if (!channel) + return NULL; + + signal = level_to_qual(le32_to_cpu(bssid->rssi)); + timestamp = le64_to_cpu(*(__le64 *)fixed->timestamp); + capability = le16_to_cpu(fixed->capabilities); + beacon_interval = le16_to_cpu(fixed->beacon_interval); + + return cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, + timestamp, capability, beacon_interval, ie, ie_len, signal, + GFP_KERNEL); +} + + +static int rndis_check_bssid_list(struct usbnet *usbdev) +{ + void *buf = NULL; + struct ndis_80211_bssid_list_ex *bssid_list; + struct ndis_80211_bssid_ex *bssid; + int ret = -EINVAL, len, count, bssid_len; + + devdbg(usbdev, "check_bssid_list"); + + len = CONTROL_BUFFER_SIZE; + buf = kmalloc(len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); + if (ret != 0) + goto out; + + bssid_list = buf; + bssid = bssid_list->bssid; + bssid_len = le32_to_cpu(bssid->length); + count = le32_to_cpu(bssid_list->num_items); + devdbg(usbdev, "check_bssid_list: %d BSSIDs found", count); + + while (count && ((void *)bssid + bssid_len) <= (buf + len)) { + rndis_bss_info_update(usbdev, bssid); + + bssid = (void *)bssid + bssid_len; + bssid_len = le32_to_cpu(bssid->length); + count--; + } + +out: + kfree(buf); + return ret; +} + + +static void rndis_get_scan_results(struct work_struct *work) +{ + struct rndis_wext_private *priv = + container_of(work, struct rndis_wext_private, scan_work.work); + struct usbnet *usbdev = priv->usbdev; + int ret; + + devdbg(usbdev, "get_scan_results"); + + ret = rndis_check_bssid_list(usbdev); + + cfg80211_scan_done(priv->scan_request, ret < 0); + + priv->scan_request = NULL; +} + + /* * wireless extension handlers */ @@ -1531,198 +1674,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, } -static int rndis_iw_set_scan(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - union iwreq_data evt; - int ret = -EINVAL; - __le32 tmp; - - devdbg(usbdev, "SIOCSIWSCAN"); - - if (wrqu->data.flags == 0) { - tmp = cpu_to_le32(1); - ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, - sizeof(tmp)); - evt.data.flags = 0; - evt.data.length = 0; - wireless_send_event(dev, SIOCGIWSCAN, &evt, NULL); - } - return ret; -} - - -static char *rndis_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *cev, - char *end_buf, - struct ndis_80211_bssid_ex *bssid) -{ - struct usbnet *usbdev = netdev_priv(dev); - u8 *ie; - char *current_val; - int bssid_len, ie_len, i; - u32 beacon, atim; - struct iw_event iwe; - unsigned char sbuf[32]; - - bssid_len = le32_to_cpu(bssid->length); - - devdbg(usbdev, "BSSID %pM", bssid->mac); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_ADDR_LEN); - - devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length), - bssid->ssid.essid); - iwe.cmd = SIOCGIWESSID; - iwe.u.essid.length = le32_to_cpu(bssid->ssid.length); - iwe.u.essid.flags = 1; - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, bssid->ssid.essid); - - devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra)); - iwe.cmd = SIOCGIWMODE; - switch (le32_to_cpu(bssid->net_infra)) { - case ndis_80211_infra_adhoc: - iwe.u.mode = IW_MODE_ADHOC; - break; - case ndis_80211_infra_infra: - iwe.u.mode = IW_MODE_INFRA; - break; - /*case ndis_80211_infra_auto_unknown:*/ - default: - iwe.u.mode = IW_MODE_AUTO; - break; - } - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_UINT_LEN); - - devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config)); - iwe.cmd = SIOCGIWFREQ; - dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq); - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_FREQ_LEN); - - devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->rssi)); - iwe.u.qual.level = level_to_qual(le32_to_cpu(bssid->rssi)); - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_INVALID; - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_QUAL_LEN); - - devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy)); - iwe.cmd = SIOCGIWENCODE; - iwe.u.data.length = 0; - if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all) - iwe.u.data.flags = IW_ENCODE_DISABLED; - else - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); - - devdbg(usbdev, "RATES:"); - current_val = cev + iwe_stream_lcp_len(info); - iwe.cmd = SIOCGIWRATE; - for (i = 0; i < sizeof(bssid->rates); i++) { - if (bssid->rates[i] & 0x7f) { - iwe.u.bitrate.value = - ((bssid->rates[i] & 0x7f) * - 500000); - devdbg(usbdev, " %d", iwe.u.bitrate.value); - current_val = iwe_stream_add_value(info, cev, - current_val, end_buf, &iwe, - IW_EV_PARAM_LEN); - } - } - - if ((current_val - cev) > iwe_stream_lcp_len(info)) - cev = current_val; - - beacon = le32_to_cpu(bssid->config.beacon_period); - devdbg(usbdev, "BCN_INT %d", beacon); - iwe.cmd = IWEVCUSTOM; - snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); - iwe.u.data.length = strlen(sbuf); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); - - atim = le32_to_cpu(bssid->config.atim_window); - devdbg(usbdev, "ATIM %d", atim); - iwe.cmd = IWEVCUSTOM; - snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); - iwe.u.data.length = strlen(sbuf); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); - - ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); - ie_len = min(bssid_len - (int)sizeof(*bssid), - (int)le32_to_cpu(bssid->ie_length)); - ie_len -= sizeof(struct ndis_80211_fixed_ies); - while (ie_len >= 2 && 2 + ie[1] <= ie_len) { - if ((ie[0] == WLAN_EID_GENERIC && ie[1] >= 4 && - memcmp(ie + 2, "\x00\x50\xf2\x01", 4) == 0) || - ie[0] == WLAN_EID_RSN) { - devdbg(usbdev, "IE: WPA%d", - (ie[0] == WLAN_EID_RSN) ? 2 : 1); - iwe.cmd = IWEVGENIE; - /* arbitrary cut-off at 64 */ - iwe.u.data.length = min(ie[1] + 2, 64); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, ie); - } - - ie_len -= 2 + ie[1]; - ie += 2 + ie[1]; - } - - return cev; -} - - -static int rndis_iw_get_scan(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - void *buf = NULL; - char *cev = extra; - struct ndis_80211_bssid_list_ex *bssid_list; - struct ndis_80211_bssid_ex *bssid; - int ret = -EINVAL, len, count, bssid_len; - - devdbg(usbdev, "SIOCGIWSCAN"); - - len = CONTROL_BUFFER_SIZE; - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); - - if (ret != 0) - goto out; - - bssid_list = buf; - bssid = bssid_list->bssid; - bssid_len = le32_to_cpu(bssid->length); - count = le32_to_cpu(bssid_list->num_items); - devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); - - while (count && ((void *)bssid + bssid_len) <= (buf + len)) { - cev = rndis_translate_scan(dev, info, cev, - extra + IW_SCAN_MAX_DATA, bssid); - bssid = (void *)bssid + bssid_len; - bssid_len = le32_to_cpu(bssid->length); - count--; - } - -out: - wrqu->data.length = cev - extra; - wrqu->data.flags = 0; - kfree(buf); - return ret; -} - - static int rndis_iw_set_genie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -2085,8 +2036,8 @@ static const iw_handler rndis_iw_handler[] = IW_IOCTL(SIOCGIWRANGE) = (iw_handler) cfg80211_wext_giwrange, IW_IOCTL(SIOCSIWAP) = rndis_iw_set_bssid, IW_IOCTL(SIOCGIWAP) = rndis_iw_get_bssid, - IW_IOCTL(SIOCSIWSCAN) = rndis_iw_set_scan, - IW_IOCTL(SIOCGIWSCAN) = rndis_iw_get_scan, + IW_IOCTL(SIOCSIWSCAN) = (iw_handler) cfg80211_wext_siwscan, + IW_IOCTL(SIOCGIWSCAN) = (iw_handler) cfg80211_wext_giwscan, IW_IOCTL(SIOCSIWESSID) = rndis_iw_set_essid, IW_IOCTL(SIOCGIWESSID) = rndis_iw_get_essid, IW_IOCTL(SIOCSIWNICKN) = rndis_iw_set_nick, @@ -2547,6 +2498,7 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); queue_delayed_work(priv->workqueue, &priv->stats_work, round_jiffies_relative(STATS_UPDATE_JIFFIES)); + INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results); INIT_WORK(&priv->work, rndis_wext_worker); return 0; @@ -2565,6 +2517,7 @@ static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf) disassociate(usbdev, 0); cancel_delayed_work_sync(&priv->stats_work); + cancel_delayed_work_sync(&priv->scan_work); cancel_work_sync(&priv->work); flush_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue); -- cgit v1.2.3 From 55a3757a5703ebc58612ffbfbcb7f193dae17df7 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 27 Mar 2009 12:45:30 -0700 Subject: iwlwifi: change check triggering device restart after rfkill change The STATUS_ALIVE value cannot be used because it is cleared when interface is brought down and will not be set if rfkill is enabled when interface is started again. The interface can thus not be brought up if rfkill was enabled before stopping the interface and disabled after starting the interface. Change the test to use priv->is_open instead, this will be set when interface is started whether rfkill is enabled or not. Thanks to Helmut Schaa for the suggested fix. Signed-off-by: Reinette Chatre Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7609bfced10f..82abb1f9087f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2054,7 +2054,7 @@ void iwl_bg_rf_kill(struct work_struct *work) "HW and/or SW RF Kill no longer active, restarting " "device\n"); if (!test_bit(STATUS_EXIT_PENDING, &priv->status) && - test_bit(STATUS_ALIVE, &priv->status)) + priv->is_open) queue_work(priv->workqueue, &priv->restart); } else { /* make sure mac80211 stop sending Tx frame */ -- cgit v1.2.3 From fc2ada30cacc28c96eabc598d3ef294338d8dcf5 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 30 Mar 2009 22:30:27 -0400 Subject: ath9k: separate ath9k specific code from ath9k_regd_get_ctl() Until ath5k and ath9k share common channel structures, they will have to implement their own get_ctl() function. Split out the portion that only relies on the current band and reg domain so that it can be common code. Signed-off-by: Bob Copeland Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/regd.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index 4ca625102291..43ed35ba95cf 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -16,6 +16,7 @@ #include #include +#include #include "ath9k.h" #include "regd_common.h" @@ -492,28 +493,37 @@ int ath9k_regd_init(struct ath_hw *ah) return 0; } -u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan) +static +u32 ath9k_regd_get_band_ctl(struct ath_hw *ah, enum ieee80211_band band) { - u32 ctl = NO_CTL; - if (!ah->regulatory.regpair || (ah->regulatory.country_code == CTRY_DEFAULT && is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) { - if (IS_CHAN_B(chan)) - ctl = SD_NO_CTL | CTL_11B; - else if (IS_CHAN_G(chan)) - ctl = SD_NO_CTL | CTL_11G; - else - ctl = SD_NO_CTL | CTL_11A; - return ctl; + return SD_NO_CTL; + } + + switch (band) { + case IEEE80211_BAND_2GHZ: + return ah->regulatory.regpair->reg_2ghz_ctl; + case IEEE80211_BAND_5GHZ: + return ah->regulatory.regpair->reg_5ghz_ctl; + default: + return NO_CTL; } + return NO_CTL; +} + +u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan) +{ + u32 ctl = ath9k_regd_get_band_ctl(ah, chan->chan->band); + if (IS_CHAN_B(chan)) - ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B; + ctl |= CTL_11B; else if (IS_CHAN_G(chan)) - ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G; + ctl |= CTL_11G; else - ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A; + ctl |= CTL_11A; return ctl; } -- cgit v1.2.3 From c02cf3738c9dbc446c160b9d49a001eb2be316c8 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 30 Mar 2009 22:30:28 -0400 Subject: ath9k: pass regd structure directly to regulatory functions All regulatory information is encapsulated by the ath9k_regulatory struct, so we can now change all the callers to take that directly instead of struct ath_hw. This in turn will enable us to move the regulatory functions to common code also used by ath5k, since both can use this regulatory struct. Signed-off-by: Bob Copeland Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 6 +- drivers/net/wireless/ath9k/main.c | 18 +++--- drivers/net/wireless/ath9k/regd.c | 118 ++++++++++++++++++++------------------ drivers/net/wireless/ath9k/regd.h | 17 ++++-- 4 files changed, 86 insertions(+), 73 deletions(-) diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index bb208f51b561..a8465bb418a9 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1331,7 +1331,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, ath9k_olc_init(ah); status = ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(ah, chan), + ath9k_regd_get_ctl(&ah->regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, @@ -1671,7 +1671,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, } if (ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(ah, chan), + ath9k_regd_get_ctl(&ah->regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, @@ -3710,7 +3710,7 @@ bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); if (ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(ah, chan), + ath9k_regd_get_ctl(&ah->regulatory, chan), channel->max_antenna_gain * 2, channel->max_power * 2, min((u32) MAX_RATE_POWER, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 76c58cc74b27..3647a47d939d 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1406,7 +1406,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) for (i = 0; i < sc->keymax; i++) ath9k_hw_keyreset(ah, (u16) i); - if (ath9k_regd_init(sc->sc_ah)) + if (ath9k_regd_init(&sc->sc_ah->regulatory)) goto bad; /* default to MONITOR mode */ @@ -1614,6 +1614,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) struct ieee80211_hw *hw = sc->hw; const struct ieee80211_regdomain *regd; int error = 0, i; + struct ath9k_regulatory *reg; DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); @@ -1621,6 +1622,8 @@ int ath_attach(u16 devid, struct ath_softc *sc) if (error != 0) return error; + reg = &sc->sc_ah->regulatory; + /* get mac address from hardware and set in mac80211 */ SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); @@ -1653,10 +1656,10 @@ int ath_attach(u16 devid, struct ath_softc *sc) goto error_attach; #endif - if (ath9k_is_world_regd(sc->sc_ah)) { + if (ath9k_is_world_regd(reg)) { /* Anything applied here (prior to wiphy registration) gets * saved on the wiphy orig_* parameters */ - regd = ath9k_world_regdomain(sc->sc_ah); + regd = ath9k_world_regdomain(reg); hw->wiphy->custom_regulatory = true; hw->wiphy->strict_regulatory = false; } else { @@ -1667,7 +1670,9 @@ int ath_attach(u16 devid, struct ath_softc *sc) } wiphy_apply_custom_regulatory(hw->wiphy, regd); ath9k_reg_apply_radar_flags(hw->wiphy); - ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER); + ath9k_reg_apply_world_flags(hw->wiphy, + NL80211_REGDOM_SET_BY_DRIVER, + reg); INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); @@ -1675,9 +1680,8 @@ int ath_attach(u16 devid, struct ath_softc *sc) error = ieee80211_register_hw(hw); - if (!ath9k_is_world_regd(sc->sc_ah)) { - error = regulatory_hint(hw->wiphy, - sc->sc_ah->regulatory.alpha2); + if (!ath9k_is_world_regd(reg)) { + error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) goto error_attach; } diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index 43ed35ba95cf..7eaa59e4a7d1 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c @@ -113,14 +113,14 @@ static inline bool is_wwr_sku(u16 regd) (regd == WORLD); } -static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah) +static u16 ath9k_regd_get_eepromRD(struct ath9k_regulatory *reg) { - return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG; + return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; } -bool ath9k_is_world_regd(struct ath_hw *ah) +bool ath9k_is_world_regd(struct ath9k_regulatory *reg) { - return is_wwr_sku(ath9k_regd_get_eepromRD(ah)); + return is_wwr_sku(ath9k_regd_get_eepromRD(reg)); } const struct ieee80211_regdomain *ath9k_default_world_regdomain(void) @@ -129,9 +129,10 @@ const struct ieee80211_regdomain *ath9k_default_world_regdomain(void) return &ath9k_world_regdom_64; } -const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah) +const struct +ieee80211_regdomain *ath9k_world_regdomain(struct ath9k_regulatory *reg) { - switch (ah->regulatory.regpair->regDmnEnum) { + switch (reg->regpair->regDmnEnum) { case 0x60: case 0x61: case 0x62: @@ -312,14 +313,10 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) } void ath9k_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) + enum nl80211_reg_initiator initiator, + struct ath9k_regulatory *reg) { - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; - - switch (ah->regulatory.regpair->regDmnEnum) { + switch (reg->regpair->regDmnEnum) { case 0x60: case 0x63: case 0x66: @@ -334,12 +331,9 @@ void ath9k_reg_apply_world_flags(struct wiphy *wiphy, return; } -int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +static int ath9k_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, struct ath9k_regulatory *reg) { - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - /* We always apply this */ ath9k_reg_apply_radar_flags(wiphy); @@ -349,17 +343,28 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) case NL80211_REGDOM_SET_BY_USER: break; case NL80211_REGDOM_SET_BY_COUNTRY_IE: - if (ath9k_is_world_regd(sc->sc_ah)) - ath9k_reg_apply_world_flags(wiphy, request->initiator); + if (ath9k_is_world_regd(reg)) + ath9k_reg_apply_world_flags(wiphy, request->initiator, + reg); break; } return 0; } -bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah) +int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath9k_regulatory *reg = &sc->sc_ah->regulatory; + + return ath9k_reg_notifier_apply(wiphy, request, reg); +} + +bool ath9k_regd_is_eeprom_valid(struct ath9k_regulatory *reg) { - u16 rd = ath9k_regd_get_eepromRD(ah); + u16 rd = ath9k_regd_get_eepromRD(reg); int i; if (rd & COUNTRY_ERD_FLAG) { @@ -374,8 +379,8 @@ bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah) if (regDomainPairs[i].regDmnEnum == rd) return true; } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "invalid regulatory domain/country code 0x%x\n", rd); + printk(KERN_DEBUG + "ath9k: invalid regulatory domain/country code 0x%x\n", rd); return false; } @@ -434,41 +439,40 @@ ath9k_get_regpair(int regdmn) return NULL; } -int ath9k_regd_init(struct ath_hw *ah) +int ath9k_regd_init(struct ath9k_regulatory *reg) { struct country_code_to_enum_rd *country = NULL; u16 regdmn; - if (!ath9k_regd_is_eeprom_valid(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Invalid EEPROM contents\n"); + if (!ath9k_regd_is_eeprom_valid(reg)) { + printk(KERN_DEBUG "ath9k: Invalid EEPROM contents\n"); return -EINVAL; } - regdmn = ath9k_regd_get_eepromRD(ah); - ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn); + regdmn = ath9k_regd_get_eepromRD(reg); + reg->country_code = ath9k_regd_get_default_country(regdmn); - if (ah->regulatory.country_code == CTRY_DEFAULT && + if (reg->country_code == CTRY_DEFAULT && regdmn == CTRY_DEFAULT) - ah->regulatory.country_code = CTRY_UNITED_STATES; + reg->country_code = CTRY_UNITED_STATES; - if (ah->regulatory.country_code == CTRY_DEFAULT) { + if (reg->country_code == CTRY_DEFAULT) { country = NULL; } else { - country = ath9k_regd_find_country(ah->regulatory.country_code); + country = ath9k_regd_find_country(reg->country_code); if (country == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Country is NULL!!!!, cc= %d\n", - ah->regulatory.country_code); + printk(KERN_DEBUG + "ath9k: Country is NULL!!!!, cc= %d\n", + reg->country_code); return -EINVAL; } else regdmn = country->regDmnEnum; } - ah->regulatory.regpair = ath9k_get_regpair(regdmn); + reg->regpair = ath9k_get_regpair(regdmn); - if (!ah->regulatory.regpair) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + if (!reg->regpair) { + printk(KERN_DEBUG "ath9k: " "No regulatory domain pair found, cannot continue\n"); return -EINVAL; } @@ -477,36 +481,36 @@ int ath9k_regd_init(struct ath_hw *ah) country = ath9k_regd_find_country_by_rd(regdmn); if (country) { - ah->regulatory.alpha2[0] = country->isoName[0]; - ah->regulatory.alpha2[1] = country->isoName[1]; + reg->alpha2[0] = country->isoName[0]; + reg->alpha2[1] = country->isoName[1]; } else { - ah->regulatory.alpha2[0] = '0'; - ah->regulatory.alpha2[1] = '0'; + reg->alpha2[0] = '0'; + reg->alpha2[1] = '0'; } - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "Country alpha2 being used: %c%c\n" - "Regulatory.Regpair detected: 0x%0x\n", - ah->regulatory.alpha2[0], ah->regulatory.alpha2[1], - ah->regulatory.regpair->regDmnEnum); + printk(KERN_DEBUG "ath9k: Country alpha2 being used: %c%c\n", + reg->alpha2[0], reg->alpha2[1]); + printk(KERN_DEBUG "ath9k: Regpair detected: 0x%0x\n", + reg->regpair->regDmnEnum); return 0; } static -u32 ath9k_regd_get_band_ctl(struct ath_hw *ah, enum ieee80211_band band) +u32 ath9k_regd_get_band_ctl(struct ath9k_regulatory *reg, + enum ieee80211_band band) { - if (!ah->regulatory.regpair || - (ah->regulatory.country_code == CTRY_DEFAULT && - is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) { + if (!reg->regpair || + (reg->country_code == CTRY_DEFAULT && + is_wwr_sku(ath9k_regd_get_eepromRD(reg)))) { return SD_NO_CTL; } switch (band) { case IEEE80211_BAND_2GHZ: - return ah->regulatory.regpair->reg_2ghz_ctl; + return reg->regpair->reg_2ghz_ctl; case IEEE80211_BAND_5GHZ: - return ah->regulatory.regpair->reg_5ghz_ctl; + return reg->regpair->reg_5ghz_ctl; default: return NO_CTL; } @@ -514,9 +518,9 @@ u32 ath9k_regd_get_band_ctl(struct ath_hw *ah, enum ieee80211_band band) return NO_CTL; } -u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan) +u32 ath9k_regd_get_ctl(struct ath9k_regulatory *reg, struct ath9k_channel *chan) { - u32 ctl = ath9k_regd_get_band_ctl(ah, chan->chan->band); + u32 ctl = ath9k_regd_get_band_ctl(reg, chan->chan->band); if (IS_CHAN_B(chan)) ctl |= CTL_11B; diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h index 9f5fbd4eea7a..61fa42ebfbc4 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath9k/regd.h @@ -17,6 +17,8 @@ #ifndef REGD_H #define REGD_H +#include + #define COUNTRY_ERD_FLAG 0x8000 #define WORLDWIDE_ROAMING_FLAG 0x4000 @@ -233,15 +235,18 @@ enum CountryCode { CTRY_BELGIUM2 = 5002 }; -bool ath9k_is_world_regd(struct ath_hw *ah); -const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah); +bool ath9k_is_world_regd(struct ath9k_regulatory *reg); +const struct ieee80211_regdomain *ath9k_world_regdomain( + struct ath9k_regulatory *reg); const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); void ath9k_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator); + enum nl80211_reg_initiator, + struct ath9k_regulatory *reg); void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); -int ath9k_regd_init(struct ath_hw *ah); -bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah); -u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan); +int ath9k_regd_init(struct ath9k_regulatory *reg); +bool ath9k_regd_is_eeprom_valid(struct ath9k_regulatory *reg); +u32 ath9k_regd_get_ctl(struct ath9k_regulatory *reg, + struct ath9k_channel *chan); int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); #endif -- cgit v1.2.3 From 3a702e49c03ba959e3f5bb2b74ec9921a81c8c98 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 30 Mar 2009 22:30:29 -0400 Subject: atheros: introduce ath module containing common ath5k/ath9k/ar9170 code This change creates a new module, ath.ko, which includes code that can be shared between ath5k, ath9k and ar9170. For now, extract most of the ath9k regulatory code so it can also be used in ath5k. Signed-off-by: Bob Copeland Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 1 + drivers/net/wireless/ath/Kconfig | 4 + drivers/net/wireless/ath/Makefile | 3 + drivers/net/wireless/ath/regd.c | 519 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/regd.h | 272 ++++++++++++++++ drivers/net/wireless/ath/regd_common.h | 473 +++++++++++++++++++++++++++ drivers/net/wireless/ath9k/Kconfig | 1 + drivers/net/wireless/ath9k/Makefile | 1 - drivers/net/wireless/ath9k/eeprom.h | 2 + drivers/net/wireless/ath9k/hw.c | 15 + drivers/net/wireless/ath9k/hw.h | 5 +- drivers/net/wireless/ath9k/main.c | 31 +- drivers/net/wireless/ath9k/regd.c | 533 ------------------------------- drivers/net/wireless/ath9k/regd.h | 252 --------------- drivers/net/wireless/ath9k/regd_common.h | 473 --------------------------- 16 files changed, 1315 insertions(+), 1271 deletions(-) create mode 100644 drivers/net/wireless/ath/Kconfig create mode 100644 drivers/net/wireless/ath/Makefile create mode 100644 drivers/net/wireless/ath/regd.c create mode 100644 drivers/net/wireless/ath/regd.h create mode 100644 drivers/net/wireless/ath/regd_common.h delete mode 100644 drivers/net/wireless/ath9k/regd.c delete mode 100644 drivers/net/wireless/ath9k/regd.h delete mode 100644 drivers/net/wireless/ath9k/regd_common.h diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 8a0823588c51..9e2c7e26fcbf 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -483,6 +483,7 @@ config MWL8K will be called mwl8k. If unsure, say N. source "drivers/net/wireless/p54/Kconfig" +source "drivers/net/wireless/ath/Kconfig" source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/ath9k/Kconfig" source "drivers/net/wireless/ar9170/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 50e7fba7f0ea..104639e2783d 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_RT2X00) += rt2x00/ obj-$(CONFIG_P54_COMMON) += p54/ +obj-$(CONFIG_ATH_COMMON) += ath/ obj-$(CONFIG_ATH5K) += ath5k/ obj-$(CONFIG_ATH9K) += ath9k/ obj-$(CONFIG_AR9170_USB) += ar9170/ diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig new file mode 100644 index 000000000000..c2873a24baae --- /dev/null +++ b/drivers/net/wireless/ath/Kconfig @@ -0,0 +1,4 @@ +config ATH_COMMON + tristate "Atheros Wireless Cards Shared Support" + depends on ATH5K || ATH9K + diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile new file mode 100644 index 000000000000..bc77646f90ad --- /dev/null +++ b/drivers/net/wireless/ath/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_ATH_COMMON) += ath.o +ath-objs := regd.o + diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c new file mode 100644 index 000000000000..4d3935b6fbdd --- /dev/null +++ b/drivers/net/wireless/ath/regd.c @@ -0,0 +1,519 @@ +/* + * 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 +#include +#include +#include +#include +#include "regd.h" +#include "regd_common.h" + +/* + * This is a set of common rules used by our world regulatory domains. + * We have 12 world regulatory domains. To save space we consolidate + * the regulatory domains in 5 structures by frequency and change + * the flags on our reg_notifier() on a case by case basis. + */ + +/* Only these channels all allow active scan on all world regulatory domains */ +#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + +/* We enable active scan on these a case by case basis by regulatory domain */ +#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ + NL80211_RRF_PASSIVE_SCAN) +#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) + +/* We allow IBSS on these on a case by case basis by regulatory domain */ +#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) +#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) +#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\ + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) + +#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ + ATH9K_2GHZ_CH12_13, \ + ATH9K_2GHZ_CH14 + +#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ + ATH9K_5GHZ_5470_5850 +/* This one skips what we call "mid band" */ +#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ + ATH9K_5GHZ_5725_5850 + +/* Can be used for: + * 0x60, 0x61, 0x62 */ +static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { + .n_reg_rules = 5, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_ALL, + ATH9K_5GHZ_ALL, + } +}; + +/* Can be used by 0x63 and 0x65 */ +static const struct ieee80211_regdomain ath_world_regdom_63_65 = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_2GHZ_CH12_13, + ATH9K_5GHZ_NO_MIDBAND, + } +}; + +/* Can be used by 0x64 only */ +static const struct ieee80211_regdomain ath_world_regdom_64 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_5GHZ_NO_MIDBAND, + } +}; + +/* Can be used by 0x66 and 0x69 */ +static const struct ieee80211_regdomain ath_world_regdom_66_69 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_5GHZ_ALL, + } +}; + +/* Can be used by 0x67, 0x6A and 0x68 */ +static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + ATH9K_2GHZ_CH01_11, + ATH9K_2GHZ_CH12_13, + ATH9K_5GHZ_ALL, + } +}; + +static inline bool is_wwr_sku(u16 regd) +{ + return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || + (regd == WORLD); +} + +static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) +{ + return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; +} + +bool ath_is_world_regd(struct ath_regulatory *reg) +{ + return is_wwr_sku(ath_regd_get_eepromRD(reg)); +} +EXPORT_SYMBOL(ath_is_world_regd); + +const struct ieee80211_regdomain *ath_default_world_regdomain(void) +{ + /* this is the most restrictive */ + return &ath_world_regdom_64; +} +EXPORT_SYMBOL(ath_default_world_regdomain); + +const struct +ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) +{ + switch (reg->regpair->regDmnEnum) { + case 0x60: + case 0x61: + case 0x62: + return &ath_world_regdom_60_61_62; + case 0x63: + case 0x65: + return &ath_world_regdom_63_65; + case 0x64: + return &ath_world_regdom_64; + case 0x66: + case 0x69: + return &ath_world_regdom_66_69; + case 0x67: + case 0x68: + case 0x6A: + return &ath_world_regdom_67_68_6A; + default: + WARN_ON(1); + return ath_default_world_regdomain(); + } +} +EXPORT_SYMBOL(ath_world_regdomain); + +/* Frequency is one where radar detection is required */ +static bool ath_is_radar_freq(u16 center_freq) +{ + return (center_freq >= 5260 && center_freq <= 5700); +} + +/* + * N.B: These exception rules do not apply radar freqs. + * + * - We enable adhoc (or beaconing) if allowed by 11d + * - We enable active scan if the channel is allowed by 11d + * - If no country IE has been processed and a we determine we have + * received a beacon on a channel we can enable active scan and + * adhoc (or beaconing). + */ +static void ath_reg_apply_beaconing_flags( + struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + const struct ieee80211_reg_rule *reg_rule; + struct ieee80211_channel *ch; + unsigned int i; + u32 bandwidth = 0; + int r; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + + if (!wiphy->bands[band]) + continue; + + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) { + + ch = &sband->channels[i]; + + if (ath_is_radar_freq(ch->center_freq) || + (ch->flags & IEEE80211_CHAN_RADAR)) + continue; + + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { + r = freq_reg_info(wiphy, ch->center_freq, + &bandwidth, ®_rule); + if (r) + continue; + /* + * If 11d had a rule for this channel ensure + * we enable adhoc/beaconing if it allows us to + * use it. Note that we would have disabled it + * by applying our static world regdomain by + * default during init, prior to calling our + * regulatory_hint(). + */ + if (!(reg_rule->flags & + NL80211_RRF_NO_IBSS)) + ch->flags &= + ~IEEE80211_CHAN_NO_IBSS; + if (!(reg_rule->flags & + NL80211_RRF_PASSIVE_SCAN)) + ch->flags &= + ~IEEE80211_CHAN_PASSIVE_SCAN; + } else { + if (ch->beacon_found) + ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN); + } + } + } + +} + +/* Allows active scan scan on Ch 12 and 13 */ +static void ath_reg_apply_active_scan_flags( + struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + const struct ieee80211_reg_rule *reg_rule; + u32 bandwidth = 0; + int r; + + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + + /* + * If no country IE has been received always enable active scan + * on these channels. This is only done for specific regulatory SKUs + */ + if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { + ch = &sband->channels[11]; /* CH 12 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + ch = &sband->channels[12]; /* CH 13 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + return; + } + + /* + * If a country IE has been recieved check its rule for this + * channel first before enabling active scan. The passive scan + * would have been enforced by the initial processing of our + * custom regulatory domain. + */ + + ch = &sband->channels[11]; /* CH 12 */ + r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + if (!r) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } + + ch = &sband->channels[12]; /* CH 13 */ + r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + if (!r) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } +} + +/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ +void ath_reg_apply_radar_flags(struct wiphy *wiphy) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; + + if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + return; + + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (!ath_is_radar_freq(ch->center_freq)) + continue; + /* We always enable radar detection/DFS on this + * frequency range. Additionally we also apply on + * this frequency range: + * - If STA mode does not yet have DFS supports disable + * active scanning + * - If adhoc mode does not support DFS yet then + * disable adhoc in the frequency. + * - If AP mode does not yet support radar detection/DFS + * do not allow AP mode + */ + if (!(ch->flags & IEEE80211_CHAN_DISABLED)) + ch->flags |= IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; + } +} +EXPORT_SYMBOL(ath_reg_apply_radar_flags); + +void ath_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct ath_regulatory *reg) +{ + switch (reg->regpair->regDmnEnum) { + case 0x60: + case 0x63: + case 0x66: + case 0x67: + ath_reg_apply_beaconing_flags(wiphy, initiator); + break; + case 0x68: + ath_reg_apply_beaconing_flags(wiphy, initiator); + ath_reg_apply_active_scan_flags(wiphy, initiator); + break; + } + return; +} +EXPORT_SYMBOL(ath_reg_apply_world_flags); + +int ath_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, struct ath_regulatory *reg) +{ + /* We always apply this */ + ath_reg_apply_radar_flags(wiphy); + + switch (request->initiator) { + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: + break; + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + if (ath_is_world_regd(reg)) + ath_reg_apply_world_flags(wiphy, request->initiator, + reg); + break; + } + + return 0; +} +EXPORT_SYMBOL(ath_reg_notifier_apply); + +bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) +{ + u16 rd = ath_regd_get_eepromRD(reg); + int i; + + if (rd & COUNTRY_ERD_FLAG) { + /* EEPROM value is a country code */ + u16 cc = rd & ~COUNTRY_ERD_FLAG; + for (i = 0; i < ARRAY_SIZE(allCountries); i++) + if (allCountries[i].countryCode == cc) + return true; + } else { + /* EEPROM value is a regpair value */ + for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) + if (regDomainPairs[i].regDmnEnum == rd) + return true; + } + printk(KERN_DEBUG + "ath: invalid regulatory domain/country code 0x%x\n", rd); + return false; +} +EXPORT_SYMBOL(ath_regd_is_eeprom_valid); + +/* EEPROM country code to regpair mapping */ +static struct country_code_to_enum_rd* +ath_regd_find_country(u16 countryCode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(allCountries); i++) { + if (allCountries[i].countryCode == countryCode) + return &allCountries[i]; + } + return NULL; +} + +/* EEPROM rd code to regpair mapping */ +static struct country_code_to_enum_rd* +ath_regd_find_country_by_rd(int regdmn) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(allCountries); i++) { + if (allCountries[i].regDmnEnum == regdmn) + return &allCountries[i]; + } + return NULL; +} + +/* Returns the map of the EEPROM set RD to a country code */ +static u16 ath_regd_get_default_country(u16 rd) +{ + if (rd & COUNTRY_ERD_FLAG) { + struct country_code_to_enum_rd *country = NULL; + u16 cc = rd & ~COUNTRY_ERD_FLAG; + + country = ath_regd_find_country(cc); + if (country != NULL) + return cc; + } + + return CTRY_DEFAULT; +} + +static struct reg_dmn_pair_mapping* +ath_get_regpair(int regdmn) +{ + int i; + + if (regdmn == NO_ENUMRD) + return NULL; + for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { + if (regDomainPairs[i].regDmnEnum == regdmn) + return ®DomainPairs[i]; + } + return NULL; +} + +int ath_regd_init(struct ath_regulatory *reg) +{ + struct country_code_to_enum_rd *country = NULL; + u16 regdmn; + + if (!ath_regd_is_eeprom_valid(reg)) { + printk(KERN_DEBUG "ath: Invalid EEPROM contents\n"); + return -EINVAL; + } + + regdmn = ath_regd_get_eepromRD(reg); + reg->country_code = ath_regd_get_default_country(regdmn); + + if (reg->country_code == CTRY_DEFAULT && + regdmn == CTRY_DEFAULT) + reg->country_code = CTRY_UNITED_STATES; + + if (reg->country_code == CTRY_DEFAULT) { + country = NULL; + } else { + country = ath_regd_find_country(reg->country_code); + if (country == NULL) { + printk(KERN_DEBUG + "ath: Country is NULL!!!!, cc= %d\n", + reg->country_code); + return -EINVAL; + } else + regdmn = country->regDmnEnum; + } + + reg->regpair = ath_get_regpair(regdmn); + + if (!reg->regpair) { + printk(KERN_DEBUG "ath: " + "No regulatory domain pair found, cannot continue\n"); + return -EINVAL; + } + + if (!country) + country = ath_regd_find_country_by_rd(regdmn); + + if (country) { + reg->alpha2[0] = country->isoName[0]; + reg->alpha2[1] = country->isoName[1]; + } else { + reg->alpha2[0] = '0'; + reg->alpha2[1] = '0'; + } + + printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n", + reg->alpha2[0], reg->alpha2[1]); + printk(KERN_DEBUG "ath: Regpair detected: 0x%0x\n", + reg->regpair->regDmnEnum); + + return 0; +} +EXPORT_SYMBOL(ath_regd_init); + +u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, + enum ieee80211_band band) +{ + if (!reg->regpair || + (reg->country_code == CTRY_DEFAULT && + is_wwr_sku(ath_regd_get_eepromRD(reg)))) { + return SD_NO_CTL; + } + + switch (band) { + case IEEE80211_BAND_2GHZ: + return reg->regpair->reg_2ghz_ctl; + case IEEE80211_BAND_5GHZ: + return reg->regpair->reg_5ghz_ctl; + default: + return NO_CTL; + } + + return NO_CTL; +} +EXPORT_SYMBOL(ath_regd_get_band_ctl); diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h new file mode 100644 index 000000000000..981f5cf2bdb8 --- /dev/null +++ b/drivers/net/wireless/ath/regd.h @@ -0,0 +1,272 @@ +/* + * 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 REGD_H +#define REGD_H + +#include + +#include +#include + +#define NO_CTL 0xff +#define SD_NO_CTL 0xE0 +#define NO_CTL 0xff +#define CTL_MODE_M 7 +#define CTL_11A 0 +#define CTL_11B 1 +#define CTL_11G 2 +#define CTL_2GHT20 5 +#define CTL_5GHT20 6 +#define CTL_2GHT40 7 +#define CTL_5GHT40 8 + +#define CTRY_DEBUG 0x1ff +#define CTRY_DEFAULT 0 + +#define COUNTRY_ERD_FLAG 0x8000 +#define WORLDWIDE_ROAMING_FLAG 0x4000 + +#define MULTI_DOMAIN_MASK 0xFF00 + +#define WORLD_SKU_MASK 0x00F0 +#define WORLD_SKU_PREFIX 0x0060 + +#define CHANNEL_HALF_BW 10 +#define CHANNEL_QUARTER_BW 5 + +struct reg_dmn_pair_mapping { + u16 regDmnEnum; + u16 reg_5ghz_ctl; + u16 reg_2ghz_ctl; +}; + +struct country_code_to_enum_rd { + u16 countryCode; + u16 regDmnEnum; + const char *isoName; +}; + +struct ath_regulatory { + char alpha2[2]; + u16 country_code; + u16 max_power_level; + u32 tp_scale; + u16 current_rd; + u16 current_rd_ext; + int16_t power_limit; + struct reg_dmn_pair_mapping *regpair; +}; + +enum CountryCode { + CTRY_ALBANIA = 8, + CTRY_ALGERIA = 12, + CTRY_ARGENTINA = 32, + CTRY_ARMENIA = 51, + CTRY_AUSTRALIA = 36, + CTRY_AUSTRIA = 40, + CTRY_AZERBAIJAN = 31, + CTRY_BAHRAIN = 48, + CTRY_BELARUS = 112, + CTRY_BELGIUM = 56, + CTRY_BELIZE = 84, + CTRY_BOLIVIA = 68, + CTRY_BOSNIA_HERZ = 70, + CTRY_BRAZIL = 76, + CTRY_BRUNEI_DARUSSALAM = 96, + CTRY_BULGARIA = 100, + CTRY_CANADA = 124, + CTRY_CHILE = 152, + CTRY_CHINA = 156, + CTRY_COLOMBIA = 170, + CTRY_COSTA_RICA = 188, + CTRY_CROATIA = 191, + CTRY_CYPRUS = 196, + CTRY_CZECH = 203, + CTRY_DENMARK = 208, + CTRY_DOMINICAN_REPUBLIC = 214, + CTRY_ECUADOR = 218, + CTRY_EGYPT = 818, + CTRY_EL_SALVADOR = 222, + CTRY_ESTONIA = 233, + CTRY_FAEROE_ISLANDS = 234, + CTRY_FINLAND = 246, + CTRY_FRANCE = 250, + CTRY_GEORGIA = 268, + CTRY_GERMANY = 276, + CTRY_GREECE = 300, + CTRY_GUATEMALA = 320, + CTRY_HONDURAS = 340, + CTRY_HONG_KONG = 344, + CTRY_HUNGARY = 348, + CTRY_ICELAND = 352, + CTRY_INDIA = 356, + CTRY_INDONESIA = 360, + CTRY_IRAN = 364, + CTRY_IRAQ = 368, + CTRY_IRELAND = 372, + CTRY_ISRAEL = 376, + CTRY_ITALY = 380, + CTRY_JAMAICA = 388, + CTRY_JAPAN = 392, + CTRY_JORDAN = 400, + CTRY_KAZAKHSTAN = 398, + CTRY_KENYA = 404, + CTRY_KOREA_NORTH = 408, + CTRY_KOREA_ROC = 410, + CTRY_KOREA_ROC2 = 411, + CTRY_KOREA_ROC3 = 412, + CTRY_KUWAIT = 414, + CTRY_LATVIA = 428, + CTRY_LEBANON = 422, + CTRY_LIBYA = 434, + CTRY_LIECHTENSTEIN = 438, + CTRY_LITHUANIA = 440, + CTRY_LUXEMBOURG = 442, + CTRY_MACAU = 446, + CTRY_MACEDONIA = 807, + CTRY_MALAYSIA = 458, + CTRY_MALTA = 470, + CTRY_MEXICO = 484, + CTRY_MONACO = 492, + CTRY_MOROCCO = 504, + CTRY_NEPAL = 524, + CTRY_NETHERLANDS = 528, + CTRY_NETHERLANDS_ANTILLES = 530, + CTRY_NEW_ZEALAND = 554, + CTRY_NICARAGUA = 558, + CTRY_NORWAY = 578, + CTRY_OMAN = 512, + CTRY_PAKISTAN = 586, + CTRY_PANAMA = 591, + CTRY_PAPUA_NEW_GUINEA = 598, + CTRY_PARAGUAY = 600, + CTRY_PERU = 604, + CTRY_PHILIPPINES = 608, + CTRY_POLAND = 616, + CTRY_PORTUGAL = 620, + CTRY_PUERTO_RICO = 630, + CTRY_QATAR = 634, + CTRY_ROMANIA = 642, + CTRY_RUSSIA = 643, + CTRY_SAUDI_ARABIA = 682, + CTRY_SERBIA_MONTENEGRO = 891, + CTRY_SINGAPORE = 702, + CTRY_SLOVAKIA = 703, + CTRY_SLOVENIA = 705, + CTRY_SOUTH_AFRICA = 710, + CTRY_SPAIN = 724, + CTRY_SRI_LANKA = 144, + CTRY_SWEDEN = 752, + CTRY_SWITZERLAND = 756, + CTRY_SYRIA = 760, + CTRY_TAIWAN = 158, + CTRY_THAILAND = 764, + CTRY_TRINIDAD_Y_TOBAGO = 780, + CTRY_TUNISIA = 788, + CTRY_TURKEY = 792, + CTRY_UAE = 784, + CTRY_UKRAINE = 804, + CTRY_UNITED_KINGDOM = 826, + CTRY_UNITED_STATES = 840, + CTRY_UNITED_STATES_FCC49 = 842, + CTRY_URUGUAY = 858, + CTRY_UZBEKISTAN = 860, + CTRY_VENEZUELA = 862, + CTRY_VIET_NAM = 704, + CTRY_YEMEN = 887, + CTRY_ZIMBABWE = 716, + CTRY_JAPAN1 = 393, + CTRY_JAPAN2 = 394, + CTRY_JAPAN3 = 395, + CTRY_JAPAN4 = 396, + CTRY_JAPAN5 = 397, + CTRY_JAPAN6 = 4006, + CTRY_JAPAN7 = 4007, + CTRY_JAPAN8 = 4008, + CTRY_JAPAN9 = 4009, + CTRY_JAPAN10 = 4010, + CTRY_JAPAN11 = 4011, + CTRY_JAPAN12 = 4012, + CTRY_JAPAN13 = 4013, + CTRY_JAPAN14 = 4014, + CTRY_JAPAN15 = 4015, + CTRY_JAPAN16 = 4016, + CTRY_JAPAN17 = 4017, + CTRY_JAPAN18 = 4018, + CTRY_JAPAN19 = 4019, + CTRY_JAPAN20 = 4020, + CTRY_JAPAN21 = 4021, + CTRY_JAPAN22 = 4022, + CTRY_JAPAN23 = 4023, + CTRY_JAPAN24 = 4024, + CTRY_JAPAN25 = 4025, + CTRY_JAPAN26 = 4026, + CTRY_JAPAN27 = 4027, + CTRY_JAPAN28 = 4028, + CTRY_JAPAN29 = 4029, + CTRY_JAPAN30 = 4030, + CTRY_JAPAN31 = 4031, + CTRY_JAPAN32 = 4032, + CTRY_JAPAN33 = 4033, + CTRY_JAPAN34 = 4034, + CTRY_JAPAN35 = 4035, + CTRY_JAPAN36 = 4036, + CTRY_JAPAN37 = 4037, + CTRY_JAPAN38 = 4038, + CTRY_JAPAN39 = 4039, + CTRY_JAPAN40 = 4040, + CTRY_JAPAN41 = 4041, + CTRY_JAPAN42 = 4042, + CTRY_JAPAN43 = 4043, + CTRY_JAPAN44 = 4044, + CTRY_JAPAN45 = 4045, + CTRY_JAPAN46 = 4046, + CTRY_JAPAN47 = 4047, + CTRY_JAPAN48 = 4048, + CTRY_JAPAN49 = 4049, + CTRY_JAPAN50 = 4050, + CTRY_JAPAN51 = 4051, + CTRY_JAPAN52 = 4052, + CTRY_JAPAN53 = 4053, + CTRY_JAPAN54 = 4054, + CTRY_JAPAN55 = 4055, + CTRY_JAPAN56 = 4056, + CTRY_JAPAN57 = 4057, + CTRY_JAPAN58 = 4058, + CTRY_JAPAN59 = 4059, + CTRY_AUSTRALIA2 = 5000, + CTRY_CANADA2 = 5001, + CTRY_BELGIUM2 = 5002 +}; + +bool ath_is_world_regd(struct ath_regulatory *reg); +const +struct ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg); +const struct ieee80211_regdomain *ath_default_world_regdomain(void); +void ath_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator, + struct ath_regulatory *reg); +void ath_reg_apply_radar_flags(struct wiphy *wiphy); +int ath_regd_init(struct ath_regulatory *reg); +bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg); +u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, + enum ieee80211_band band); +int ath_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, + struct ath_regulatory *reg); + +#endif diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h new file mode 100644 index 000000000000..4d0e298cd1c7 --- /dev/null +++ b/drivers/net/wireless/ath/regd_common.h @@ -0,0 +1,473 @@ +/* + * 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 REGD_COMMON_H +#define REGD_COMMON_H + +enum EnumRd { + NO_ENUMRD = 0x00, + NULL1_WORLD = 0x03, + NULL1_ETSIB = 0x07, + NULL1_ETSIC = 0x08, + FCC1_FCCA = 0x10, + FCC1_WORLD = 0x11, + FCC4_FCCA = 0x12, + FCC5_FCCA = 0x13, + FCC6_FCCA = 0x14, + + FCC2_FCCA = 0x20, + FCC2_WORLD = 0x21, + FCC2_ETSIC = 0x22, + FCC6_WORLD = 0x23, + FRANCE_RES = 0x31, + FCC3_FCCA = 0x3A, + FCC3_WORLD = 0x3B, + + ETSI1_WORLD = 0x37, + ETSI3_ETSIA = 0x32, + ETSI2_WORLD = 0x35, + ETSI3_WORLD = 0x36, + ETSI4_WORLD = 0x30, + ETSI4_ETSIC = 0x38, + ETSI5_WORLD = 0x39, + ETSI6_WORLD = 0x34, + ETSI_RESERVED = 0x33, + + MKK1_MKKA = 0x40, + MKK1_MKKB = 0x41, + APL4_WORLD = 0x42, + MKK2_MKKA = 0x43, + APL_RESERVED = 0x44, + APL2_WORLD = 0x45, + APL2_APLC = 0x46, + APL3_WORLD = 0x47, + MKK1_FCCA = 0x48, + APL2_APLD = 0x49, + MKK1_MKKA1 = 0x4A, + MKK1_MKKA2 = 0x4B, + MKK1_MKKC = 0x4C, + + APL3_FCCA = 0x50, + APL1_WORLD = 0x52, + APL1_FCCA = 0x53, + APL1_APLA = 0x54, + APL1_ETSIC = 0x55, + APL2_ETSIC = 0x56, + APL5_WORLD = 0x58, + APL6_WORLD = 0x5B, + APL7_FCCA = 0x5C, + APL8_WORLD = 0x5D, + APL9_WORLD = 0x5E, + + WOR0_WORLD = 0x60, + WOR1_WORLD = 0x61, + WOR2_WORLD = 0x62, + WOR3_WORLD = 0x63, + WOR4_WORLD = 0x64, + WOR5_ETSIC = 0x65, + + WOR01_WORLD = 0x66, + WOR02_WORLD = 0x67, + EU1_WORLD = 0x68, + + WOR9_WORLD = 0x69, + WORA_WORLD = 0x6A, + WORB_WORLD = 0x6B, + + MKK3_MKKB = 0x80, + MKK3_MKKA2 = 0x81, + MKK3_MKKC = 0x82, + + MKK4_MKKB = 0x83, + MKK4_MKKA2 = 0x84, + MKK4_MKKC = 0x85, + + MKK5_MKKB = 0x86, + MKK5_MKKA2 = 0x87, + MKK5_MKKC = 0x88, + + MKK6_MKKB = 0x89, + MKK6_MKKA2 = 0x8A, + MKK6_MKKC = 0x8B, + + MKK7_MKKB = 0x8C, + MKK7_MKKA2 = 0x8D, + MKK7_MKKC = 0x8E, + + MKK8_MKKB = 0x8F, + MKK8_MKKA2 = 0x90, + MKK8_MKKC = 0x91, + + MKK14_MKKA1 = 0x92, + MKK15_MKKA1 = 0x93, + + MKK10_FCCA = 0xD0, + MKK10_MKKA1 = 0xD1, + MKK10_MKKC = 0xD2, + MKK10_MKKA2 = 0xD3, + + MKK11_MKKA = 0xD4, + MKK11_FCCA = 0xD5, + MKK11_MKKA1 = 0xD6, + MKK11_MKKC = 0xD7, + MKK11_MKKA2 = 0xD8, + + MKK12_MKKA = 0xD9, + MKK12_FCCA = 0xDA, + MKK12_MKKA1 = 0xDB, + MKK12_MKKC = 0xDC, + MKK12_MKKA2 = 0xDD, + + MKK13_MKKB = 0xDE, + + MKK3_MKKA = 0xF0, + MKK3_MKKA1 = 0xF1, + MKK3_FCCA = 0xF2, + MKK4_MKKA = 0xF3, + MKK4_MKKA1 = 0xF4, + MKK4_FCCA = 0xF5, + MKK9_MKKA = 0xF6, + MKK10_MKKA = 0xF7, + MKK6_MKKA1 = 0xF8, + MKK6_FCCA = 0xF9, + MKK7_MKKA1 = 0xFA, + MKK7_FCCA = 0xFB, + MKK9_FCCA = 0xFC, + MKK9_MKKA1 = 0xFD, + MKK9_MKKC = 0xFE, + MKK9_MKKA2 = 0xFF, + + WORLD = 0x0199, + DEBUG_REG_DMN = 0x01ff, +}; + +enum ctl_group { + CTL_FCC = 0x10, + CTL_MKK = 0x40, + CTL_ETSI = 0x30, +}; + +/* Regpair to CTL band mapping */ +static struct reg_dmn_pair_mapping regDomainPairs[] = { + /* regpair, 5 GHz CTL, 2 GHz CTL */ + {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN}, + {NULL1_WORLD, NO_CTL, CTL_ETSI}, + {NULL1_ETSIB, NO_CTL, CTL_ETSI}, + {NULL1_ETSIC, NO_CTL, CTL_ETSI}, + + {FCC2_FCCA, CTL_FCC, CTL_FCC}, + {FCC2_WORLD, CTL_FCC, CTL_ETSI}, + {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC3_FCCA, CTL_FCC, CTL_FCC}, + {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC4_FCCA, CTL_FCC, CTL_FCC}, + {FCC5_FCCA, CTL_FCC, CTL_FCC}, + {FCC6_FCCA, CTL_FCC, CTL_FCC}, + {FCC6_WORLD, CTL_FCC, CTL_ETSI}, + + {ETSI1_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI2_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI3_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, + + /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ + {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, + {FRANCE_RES, CTL_ETSI, CTL_ETSI}, + + {FCC1_WORLD, CTL_FCC, CTL_ETSI}, + {FCC1_FCCA, CTL_FCC, CTL_FCC}, + {APL1_WORLD, CTL_FCC, CTL_ETSI}, + {APL2_WORLD, CTL_FCC, CTL_ETSI}, + {APL3_WORLD, CTL_FCC, CTL_ETSI}, + {APL4_WORLD, CTL_FCC, CTL_ETSI}, + {APL5_WORLD, CTL_FCC, CTL_ETSI}, + {APL6_WORLD, CTL_ETSI, CTL_ETSI}, + {APL8_WORLD, CTL_ETSI, CTL_ETSI}, + {APL9_WORLD, CTL_ETSI, CTL_ETSI}, + + {APL3_FCCA, CTL_FCC, CTL_FCC}, + {APL1_ETSIC, CTL_FCC, CTL_ETSI}, + {APL2_ETSIC, CTL_FCC, CTL_ETSI}, + {APL2_APLD, CTL_FCC, NO_CTL}, + + {MKK1_MKKA, CTL_MKK, CTL_MKK}, + {MKK1_MKKB, CTL_MKK, CTL_MKK}, + {MKK1_FCCA, CTL_MKK, CTL_FCC}, + {MKK1_MKKA1, CTL_MKK, CTL_MKK}, + {MKK1_MKKA2, CTL_MKK, CTL_MKK}, + {MKK1_MKKC, CTL_MKK, CTL_MKK}, + + {MKK2_MKKA, CTL_MKK, CTL_MKK}, + {MKK3_MKKA, CTL_MKK, CTL_MKK}, + {MKK3_MKKB, CTL_MKK, CTL_MKK}, + {MKK3_MKKA1, CTL_MKK, CTL_MKK}, + {MKK3_MKKA2, CTL_MKK, CTL_MKK}, + {MKK3_MKKC, CTL_MKK, CTL_MKK}, + {MKK3_FCCA, CTL_MKK, CTL_FCC}, + + {MKK4_MKKA, CTL_MKK, CTL_MKK}, + {MKK4_MKKB, CTL_MKK, CTL_MKK}, + {MKK4_MKKA1, CTL_MKK, CTL_MKK}, + {MKK4_MKKA2, CTL_MKK, CTL_MKK}, + {MKK4_MKKC, CTL_MKK, CTL_MKK}, + {MKK4_FCCA, CTL_MKK, CTL_FCC}, + + {MKK5_MKKB, CTL_MKK, CTL_MKK}, + {MKK5_MKKA2, CTL_MKK, CTL_MKK}, + {MKK5_MKKC, CTL_MKK, CTL_MKK}, + + {MKK6_MKKB, CTL_MKK, CTL_MKK}, + {MKK6_MKKA1, CTL_MKK, CTL_MKK}, + {MKK6_MKKA2, CTL_MKK, CTL_MKK}, + {MKK6_MKKC, CTL_MKK, CTL_MKK}, + {MKK6_FCCA, CTL_MKK, CTL_FCC}, + + {MKK7_MKKB, CTL_MKK, CTL_MKK}, + {MKK7_MKKA1, CTL_MKK, CTL_MKK}, + {MKK7_MKKA2, CTL_MKK, CTL_MKK}, + {MKK7_MKKC, CTL_MKK, CTL_MKK}, + {MKK7_FCCA, CTL_MKK, CTL_FCC}, + + {MKK8_MKKB, CTL_MKK, CTL_MKK}, + {MKK8_MKKA2, CTL_MKK, CTL_MKK}, + {MKK8_MKKC, CTL_MKK, CTL_MKK}, + + {MKK9_MKKA, CTL_MKK, CTL_MKK}, + {MKK9_FCCA, CTL_MKK, CTL_FCC}, + {MKK9_MKKA1, CTL_MKK, CTL_MKK}, + {MKK9_MKKA2, CTL_MKK, CTL_MKK}, + {MKK9_MKKC, CTL_MKK, CTL_MKK}, + + {MKK10_MKKA, CTL_MKK, CTL_MKK}, + {MKK10_FCCA, CTL_MKK, CTL_FCC}, + {MKK10_MKKA1, CTL_MKK, CTL_MKK}, + {MKK10_MKKA2, CTL_MKK, CTL_MKK}, + {MKK10_MKKC, CTL_MKK, CTL_MKK}, + + {MKK11_MKKA, CTL_MKK, CTL_MKK}, + {MKK11_FCCA, CTL_MKK, CTL_FCC}, + {MKK11_MKKA1, CTL_MKK, CTL_MKK}, + {MKK11_MKKA2, CTL_MKK, CTL_MKK}, + {MKK11_MKKC, CTL_MKK, CTL_MKK}, + + {MKK12_MKKA, CTL_MKK, CTL_MKK}, + {MKK12_FCCA, CTL_MKK, CTL_FCC}, + {MKK12_MKKA1, CTL_MKK, CTL_MKK}, + {MKK12_MKKA2, CTL_MKK, CTL_MKK}, + {MKK12_MKKC, CTL_MKK, CTL_MKK}, + + {MKK13_MKKB, CTL_MKK, CTL_MKK}, + {MKK14_MKKA1, CTL_MKK, CTL_MKK}, + {MKK15_MKKA1, CTL_MKK, CTL_MKK}, + + {WOR0_WORLD, NO_CTL, NO_CTL}, + {WOR1_WORLD, NO_CTL, NO_CTL}, + {WOR2_WORLD, NO_CTL, NO_CTL}, + {WOR3_WORLD, NO_CTL, NO_CTL}, + {WOR4_WORLD, NO_CTL, NO_CTL}, + {WOR5_ETSIC, NO_CTL, NO_CTL}, + {WOR01_WORLD, NO_CTL, NO_CTL}, + {WOR02_WORLD, NO_CTL, NO_CTL}, + {EU1_WORLD, NO_CTL, NO_CTL}, + {WOR9_WORLD, NO_CTL, NO_CTL}, + {WORA_WORLD, NO_CTL, NO_CTL}, + {WORB_WORLD, NO_CTL, NO_CTL}, +}; + +static struct country_code_to_enum_rd allCountries[] = { + {CTRY_DEBUG, NO_ENUMRD, "DB"}, + {CTRY_DEFAULT, FCC1_FCCA, "CO"}, + {CTRY_ALBANIA, NULL1_WORLD, "AL"}, + {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, + {CTRY_ARGENTINA, APL3_WORLD, "AR"}, + {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, + {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, + {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, + {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, + {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, + {CTRY_BAHRAIN, APL6_WORLD, "BH"}, + {CTRY_BELARUS, ETSI1_WORLD, "BY"}, + {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, + {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, + {CTRY_BELIZE, APL1_ETSIC, "BZ"}, + {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, + {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, + {CTRY_BRAZIL, FCC3_WORLD, "BR"}, + {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, + {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, + {CTRY_CANADA, FCC2_FCCA, "CA"}, + {CTRY_CANADA2, FCC6_FCCA, "CA"}, + {CTRY_CHILE, APL6_WORLD, "CL"}, + {CTRY_CHINA, APL1_WORLD, "CN"}, + {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, + {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, + {CTRY_CROATIA, ETSI3_WORLD, "HR"}, + {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, + {CTRY_CZECH, ETSI3_WORLD, "CZ"}, + {CTRY_DENMARK, ETSI1_WORLD, "DK"}, + {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"}, + {CTRY_ECUADOR, FCC1_WORLD, "EC"}, + {CTRY_EGYPT, ETSI3_WORLD, "EG"}, + {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"}, + {CTRY_ESTONIA, ETSI1_WORLD, "EE"}, + {CTRY_FINLAND, ETSI1_WORLD, "FI"}, + {CTRY_FRANCE, ETSI1_WORLD, "FR"}, + {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, + {CTRY_GERMANY, ETSI1_WORLD, "DE"}, + {CTRY_GREECE, ETSI1_WORLD, "GR"}, + {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, + {CTRY_HONDURAS, NULL1_WORLD, "HN"}, + {CTRY_HONG_KONG, FCC2_WORLD, "HK"}, + {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, + {CTRY_ICELAND, ETSI1_WORLD, "IS"}, + {CTRY_INDIA, APL6_WORLD, "IN"}, + {CTRY_INDONESIA, APL1_WORLD, "ID"}, + {CTRY_IRAN, APL1_WORLD, "IR"}, + {CTRY_IRELAND, ETSI1_WORLD, "IE"}, + {CTRY_ISRAEL, NULL1_WORLD, "IL"}, + {CTRY_ITALY, ETSI1_WORLD, "IT"}, + {CTRY_JAMAICA, ETSI1_WORLD, "JM"}, + + {CTRY_JAPAN, MKK1_MKKA, "JP"}, + {CTRY_JAPAN1, MKK1_MKKB, "JP"}, + {CTRY_JAPAN2, MKK1_FCCA, "JP"}, + {CTRY_JAPAN3, MKK2_MKKA, "JP"}, + {CTRY_JAPAN4, MKK1_MKKA1, "JP"}, + {CTRY_JAPAN5, MKK1_MKKA2, "JP"}, + {CTRY_JAPAN6, MKK1_MKKC, "JP"}, + {CTRY_JAPAN7, MKK3_MKKB, "JP"}, + {CTRY_JAPAN8, MKK3_MKKA2, "JP"}, + {CTRY_JAPAN9, MKK3_MKKC, "JP"}, + {CTRY_JAPAN10, MKK4_MKKB, "JP"}, + {CTRY_JAPAN11, MKK4_MKKA2, "JP"}, + {CTRY_JAPAN12, MKK4_MKKC, "JP"}, + {CTRY_JAPAN13, MKK5_MKKB, "JP"}, + {CTRY_JAPAN14, MKK5_MKKA2, "JP"}, + {CTRY_JAPAN15, MKK5_MKKC, "JP"}, + {CTRY_JAPAN16, MKK6_MKKB, "JP"}, + {CTRY_JAPAN17, MKK6_MKKA2, "JP"}, + {CTRY_JAPAN18, MKK6_MKKC, "JP"}, + {CTRY_JAPAN19, MKK7_MKKB, "JP"}, + {CTRY_JAPAN20, MKK7_MKKA2, "JP"}, + {CTRY_JAPAN21, MKK7_MKKC, "JP"}, + {CTRY_JAPAN22, MKK8_MKKB, "JP"}, + {CTRY_JAPAN23, MKK8_MKKA2, "JP"}, + {CTRY_JAPAN24, MKK8_MKKC, "JP"}, + {CTRY_JAPAN25, MKK3_MKKA, "JP"}, + {CTRY_JAPAN26, MKK3_MKKA1, "JP"}, + {CTRY_JAPAN27, MKK3_FCCA, "JP"}, + {CTRY_JAPAN28, MKK4_MKKA1, "JP"}, + {CTRY_JAPAN29, MKK4_FCCA, "JP"}, + {CTRY_JAPAN30, MKK6_MKKA1, "JP"}, + {CTRY_JAPAN31, MKK6_FCCA, "JP"}, + {CTRY_JAPAN32, MKK7_MKKA1, "JP"}, + {CTRY_JAPAN33, MKK7_FCCA, "JP"}, + {CTRY_JAPAN34, MKK9_MKKA, "JP"}, + {CTRY_JAPAN35, MKK10_MKKA, "JP"}, + {CTRY_JAPAN36, MKK4_MKKA, "JP"}, + {CTRY_JAPAN37, MKK9_FCCA, "JP"}, + {CTRY_JAPAN38, MKK9_MKKA1, "JP"}, + {CTRY_JAPAN39, MKK9_MKKC, "JP"}, + {CTRY_JAPAN40, MKK9_MKKA2, "JP"}, + {CTRY_JAPAN41, MKK10_FCCA, "JP"}, + {CTRY_JAPAN42, MKK10_MKKA1, "JP"}, + {CTRY_JAPAN43, MKK10_MKKC, "JP"}, + {CTRY_JAPAN44, MKK10_MKKA2, "JP"}, + {CTRY_JAPAN45, MKK11_MKKA, "JP"}, + {CTRY_JAPAN46, MKK11_FCCA, "JP"}, + {CTRY_JAPAN47, MKK11_MKKA1, "JP"}, + {CTRY_JAPAN48, MKK11_MKKC, "JP"}, + {CTRY_JAPAN49, MKK11_MKKA2, "JP"}, + {CTRY_JAPAN50, MKK12_MKKA, "JP"}, + {CTRY_JAPAN51, MKK12_FCCA, "JP"}, + {CTRY_JAPAN52, MKK12_MKKA1, "JP"}, + {CTRY_JAPAN53, MKK12_MKKC, "JP"}, + {CTRY_JAPAN54, MKK12_MKKA2, "JP"}, + {CTRY_JAPAN57, MKK13_MKKB, "JP"}, + {CTRY_JAPAN58, MKK14_MKKA1, "JP"}, + {CTRY_JAPAN59, MKK15_MKKA1, "JP"}, + + {CTRY_JORDAN, ETSI2_WORLD, "JO"}, + {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"}, + {CTRY_KOREA_NORTH, APL9_WORLD, "KP"}, + {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, + {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, + {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, + {CTRY_KUWAIT, NULL1_WORLD, "KW"}, + {CTRY_LATVIA, ETSI1_WORLD, "LV"}, + {CTRY_LEBANON, NULL1_WORLD, "LB"}, + {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, + {CTRY_LITHUANIA, ETSI1_WORLD, "LT"}, + {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"}, + {CTRY_MACAU, FCC2_WORLD, "MO"}, + {CTRY_MACEDONIA, NULL1_WORLD, "MK"}, + {CTRY_MALAYSIA, APL8_WORLD, "MY"}, + {CTRY_MALTA, ETSI1_WORLD, "MT"}, + {CTRY_MEXICO, FCC1_FCCA, "MX"}, + {CTRY_MONACO, ETSI4_WORLD, "MC"}, + {CTRY_MOROCCO, NULL1_WORLD, "MA"}, + {CTRY_NEPAL, APL1_WORLD, "NP"}, + {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, + {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, + {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, + {CTRY_NORWAY, ETSI1_WORLD, "NO"}, + {CTRY_OMAN, APL6_WORLD, "OM"}, + {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, + {CTRY_PANAMA, FCC1_FCCA, "PA"}, + {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, + {CTRY_PERU, APL1_WORLD, "PE"}, + {CTRY_PHILIPPINES, APL1_WORLD, "PH"}, + {CTRY_POLAND, ETSI1_WORLD, "PL"}, + {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, + {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, + {CTRY_QATAR, NULL1_WORLD, "QA"}, + {CTRY_ROMANIA, NULL1_WORLD, "RO"}, + {CTRY_RUSSIA, NULL1_WORLD, "RU"}, + {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, + {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, + {CTRY_SINGAPORE, APL6_WORLD, "SG"}, + {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, + {CTRY_SLOVENIA, ETSI1_WORLD, "SI"}, + {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"}, + {CTRY_SPAIN, ETSI1_WORLD, "ES"}, + {CTRY_SRI_LANKA, FCC3_WORLD, "LK"}, + {CTRY_SWEDEN, ETSI1_WORLD, "SE"}, + {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, + {CTRY_SYRIA, NULL1_WORLD, "SY"}, + {CTRY_TAIWAN, APL3_FCCA, "TW"}, + {CTRY_THAILAND, NULL1_WORLD, "TH"}, + {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, + {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, + {CTRY_TURKEY, ETSI3_WORLD, "TR"}, + {CTRY_UKRAINE, NULL1_WORLD, "UA"}, + {CTRY_UAE, NULL1_WORLD, "AE"}, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, + {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, + /* This "PS" is for US public safety actually... to support this we + * would need to assign new special alpha2 to CRDA db as with the world + * regdomain and use another alpha2 */ + {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, + {CTRY_URUGUAY, APL2_WORLD, "UY"}, + {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, + {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, + {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, + {CTRY_YEMEN, NULL1_WORLD, "YE"}, + {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"}, +}; + +#endif diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig index 90a8dd873786..0ed1ac312aa6 100644 --- a/drivers/net/wireless/ath9k/Kconfig +++ b/drivers/net/wireless/ath9k/Kconfig @@ -2,6 +2,7 @@ config ATH9K tristate "Atheros 802.11n wireless cards support" depends on PCI && MAC80211 && WLAN_80211 depends on RFKILL || RFKILL=n + select ATH_COMMON select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile index 1a4d4eab6fe8..783bc39eb2ff 100644 --- a/drivers/net/wireless/ath9k/Makefile +++ b/drivers/net/wireless/ath9k/Makefile @@ -4,7 +4,6 @@ ath9k-y += hw.o \ calib.o \ ani.o \ phy.o \ - regd.o \ beacon.o \ main.o \ recv.o \ diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index 25b68c881ff1..9a7715df5cff 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h @@ -17,6 +17,8 @@ #ifndef EEPROM_H #define EEPROM_H +#include + #define AH_USE_EEPROM 0x1 #ifdef __BIG_ENDIAN diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index a8465bb418a9..24299e65fdcf 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -1220,6 +1220,21 @@ static void ath9k_olc_init(struct ath_hw *ah) ah->PDADCdelta = 0; } +static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, + struct ath9k_channel *chan) +{ + u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); + + if (IS_CHAN_B(chan)) + ctl |= CTL_11B; + else if (IS_CHAN_G(chan)) + ctl |= CTL_11G; + else + ctl |= CTL_11A; + + return ctl; +} + static int ath9k_hw_process_ini(struct ath_hw *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 5a1128ddb464..984ac7da09d6 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -25,10 +25,11 @@ #include "ani.h" #include "eeprom.h" #include "calib.h" -#include "regd.h" #include "reg.h" #include "phy.h" +#include "../ath/regd.h" + #define ATHEROS_VENDOR_ID 0x168c #define AR5416_DEVID_PCI 0x0023 #define AR5416_DEVID_PCIE 0x0024 @@ -404,7 +405,7 @@ struct ath_hw { struct ath9k_hw_version hw_version; struct ath9k_ops_config config; struct ath9k_hw_capabilities caps; - struct ath9k_regulatory regulatory; + struct ath_regulatory regulatory; struct ath9k_channel channels[38]; struct ath9k_channel *curchan; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 3647a47d939d..d779f00c9b9d 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1406,7 +1406,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) for (i = 0; i < sc->keymax; i++) ath9k_hw_keyreset(ah, (u16) i); - if (ath9k_regd_init(&sc->sc_ah->regulatory)) + if (ath_regd_init(&sc->sc_ah->regulatory)) goto bad; /* default to MONITOR mode */ @@ -1570,6 +1570,17 @@ bad: return error; } +static int ath9k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_regulatory *reg = &sc->sc_ah->regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | @@ -1614,7 +1625,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) struct ieee80211_hw *hw = sc->hw; const struct ieee80211_regdomain *regd; int error = 0, i; - struct ath9k_regulatory *reg; + struct ath_regulatory *reg; DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); @@ -1656,23 +1667,23 @@ int ath_attach(u16 devid, struct ath_softc *sc) goto error_attach; #endif - if (ath9k_is_world_regd(reg)) { + if (ath_is_world_regd(reg)) { /* Anything applied here (prior to wiphy registration) gets * saved on the wiphy orig_* parameters */ - regd = ath9k_world_regdomain(reg); + regd = ath_world_regdomain(reg); hw->wiphy->custom_regulatory = true; hw->wiphy->strict_regulatory = false; } else { /* This gets applied in the case of the absense of CRDA, * it's our own custom world regulatory domain, similar to * cfg80211's but we enable passive scanning */ - regd = ath9k_default_world_regdomain(); + regd = ath_default_world_regdomain(); } wiphy_apply_custom_regulatory(hw->wiphy, regd); - ath9k_reg_apply_radar_flags(hw->wiphy); - ath9k_reg_apply_world_flags(hw->wiphy, - NL80211_REGDOM_SET_BY_DRIVER, - reg); + ath_reg_apply_radar_flags(hw->wiphy); + ath_reg_apply_world_flags(hw->wiphy, + NL80211_REGDOM_SET_BY_DRIVER, + reg); INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); @@ -1680,7 +1691,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) error = ieee80211_register_hw(hw); - if (!ath9k_is_world_regd(reg)) { + if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) goto error_attach; diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c deleted file mode 100644 index 7eaa59e4a7d1..000000000000 --- a/drivers/net/wireless/ath9k/regd.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * 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 -#include -#include -#include "ath9k.h" -#include "regd_common.h" - -/* - * This is a set of common rules used by our world regulatory domains. - * We have 12 world regulatory domains. To save space we consolidate - * the regulatory domains in 5 structures by frequency and change - * the flags on our reg_notifier() on a case by case basis. - */ - -/* Only these channels all allow active scan on all world regulatory domains */ -#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) - -/* We enable active scan on these a case by case basis by regulatory domain */ -#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN) -#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) - -/* We allow IBSS on these on a case by case basis by regulatory domain */ -#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) - -#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ - ATH9K_2GHZ_CH12_13, \ - ATH9K_2GHZ_CH14 - -#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ - ATH9K_5GHZ_5470_5850 -/* This one skips what we call "mid band" */ -#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ - ATH9K_5GHZ_5725_5850 - -/* Can be used for: - * 0x60, 0x61, 0x62 */ -static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = { - .n_reg_rules = 5, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_ALL, - ATH9K_5GHZ_ALL, - } -}; - -/* Can be used by 0x63 and 0x65 */ -static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_2GHZ_CH12_13, - ATH9K_5GHZ_NO_MIDBAND, - } -}; - -/* Can be used by 0x64 only */ -static const struct ieee80211_regdomain ath9k_world_regdom_64 = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_5GHZ_NO_MIDBAND, - } -}; - -/* Can be used by 0x66 and 0x69 */ -static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_5GHZ_ALL, - } -}; - -/* Can be used by 0x67, 0x6A and 0x68 */ -static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_2GHZ_CH12_13, - ATH9K_5GHZ_ALL, - } -}; - -static inline bool is_wwr_sku(u16 regd) -{ - return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || - (regd == WORLD); -} - -static u16 ath9k_regd_get_eepromRD(struct ath9k_regulatory *reg) -{ - return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; -} - -bool ath9k_is_world_regd(struct ath9k_regulatory *reg) -{ - return is_wwr_sku(ath9k_regd_get_eepromRD(reg)); -} - -const struct ieee80211_regdomain *ath9k_default_world_regdomain(void) -{ - /* this is the most restrictive */ - return &ath9k_world_regdom_64; -} - -const struct -ieee80211_regdomain *ath9k_world_regdomain(struct ath9k_regulatory *reg) -{ - switch (reg->regpair->regDmnEnum) { - case 0x60: - case 0x61: - case 0x62: - return &ath9k_world_regdom_60_61_62; - case 0x63: - case 0x65: - return &ath9k_world_regdom_63_65; - case 0x64: - return &ath9k_world_regdom_64; - case 0x66: - case 0x69: - return &ath9k_world_regdom_66_69; - case 0x67: - case 0x68: - case 0x6A: - return &ath9k_world_regdom_67_68_6A; - default: - WARN_ON(1); - return ath9k_default_world_regdomain(); - } -} - -/* Frequency is one where radar detection is required */ -static bool ath9k_is_radar_freq(u16 center_freq) -{ - return (center_freq >= 5260 && center_freq <= 5700); -} - -/* - * N.B: These exception rules do not apply radar freqs. - * - * - We enable adhoc (or beaconing) if allowed by 11d - * - We enable active scan if the channel is allowed by 11d - * - If no country IE has been processed and a we determine we have - * received a beacon on a channel we can enable active scan and - * adhoc (or beaconing). - */ -static void ath9k_reg_apply_beaconing_flags( - struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) -{ - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - const struct ieee80211_reg_rule *reg_rule; - struct ieee80211_channel *ch; - unsigned int i; - u32 bandwidth = 0; - int r; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - - if (!wiphy->bands[band]) - continue; - - sband = wiphy->bands[band]; - - for (i = 0; i < sband->n_channels; i++) { - - ch = &sband->channels[i]; - - if (ath9k_is_radar_freq(ch->center_freq) || - (ch->flags & IEEE80211_CHAN_RADAR)) - continue; - - if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - r = freq_reg_info(wiphy, ch->center_freq, - &bandwidth, ®_rule); - if (r) - continue; - /* - * If 11d had a rule for this channel ensure - * we enable adhoc/beaconing if it allows us to - * use it. Note that we would have disabled it - * by applying our static world regdomain by - * default during init, prior to calling our - * regulatory_hint(). - */ - if (!(reg_rule->flags & - NL80211_RRF_NO_IBSS)) - ch->flags &= - ~IEEE80211_CHAN_NO_IBSS; - if (!(reg_rule->flags & - NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= - ~IEEE80211_CHAN_PASSIVE_SCAN; - } else { - if (ch->beacon_found) - ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN); - } - } - } - -} - -/* Allows active scan scan on Ch 12 and 13 */ -static void ath9k_reg_apply_active_scan_flags( - struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - const struct ieee80211_reg_rule *reg_rule; - u32 bandwidth = 0; - int r; - - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; - - /* - * If no country IE has been received always enable active scan - * on these channels. This is only done for specific regulatory SKUs - */ - if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { - ch = &sband->channels[11]; /* CH 12 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - ch = &sband->channels[12]; /* CH 13 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - return; - } - - /* - * If a country IE has been recieved check its rule for this - * channel first before enabling active scan. The passive scan - * would have been enforced by the initial processing of our - * custom regulatory domain. - */ - - ch = &sband->channels[11]; /* CH 12 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); - if (!r) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - } - - ch = &sband->channels[12]; /* CH 13 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); - if (!r) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - } -} - -/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ -void ath9k_reg_apply_radar_flags(struct wiphy *wiphy) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - unsigned int i; - - if (!wiphy->bands[IEEE80211_BAND_5GHZ]) - return; - - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - if (!ath9k_is_radar_freq(ch->center_freq)) - continue; - /* We always enable radar detection/DFS on this - * frequency range. Additionally we also apply on - * this frequency range: - * - If STA mode does not yet have DFS supports disable - * active scanning - * - If adhoc mode does not support DFS yet then - * disable adhoc in the frequency. - * - If AP mode does not yet support radar detection/DFS - * do not allow AP mode - */ - if (!(ch->flags & IEEE80211_CHAN_DISABLED)) - ch->flags |= IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; - } -} - -void ath9k_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator, - struct ath9k_regulatory *reg) -{ - switch (reg->regpair->regDmnEnum) { - case 0x60: - case 0x63: - case 0x66: - case 0x67: - ath9k_reg_apply_beaconing_flags(wiphy, initiator); - break; - case 0x68: - ath9k_reg_apply_beaconing_flags(wiphy, initiator); - ath9k_reg_apply_active_scan_flags(wiphy, initiator); - break; - } - return; -} - -static int ath9k_reg_notifier_apply(struct wiphy *wiphy, - struct regulatory_request *request, struct ath9k_regulatory *reg) -{ - /* We always apply this */ - ath9k_reg_apply_radar_flags(wiphy); - - switch (request->initiator) { - case NL80211_REGDOM_SET_BY_DRIVER: - case NL80211_REGDOM_SET_BY_CORE: - case NL80211_REGDOM_SET_BY_USER: - break; - case NL80211_REGDOM_SET_BY_COUNTRY_IE: - if (ath9k_is_world_regd(reg)) - ath9k_reg_apply_world_flags(wiphy, request->initiator, - reg); - break; - } - - return 0; -} - -int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath9k_regulatory *reg = &sc->sc_ah->regulatory; - - return ath9k_reg_notifier_apply(wiphy, request, reg); -} - -bool ath9k_regd_is_eeprom_valid(struct ath9k_regulatory *reg) -{ - u16 rd = ath9k_regd_get_eepromRD(reg); - int i; - - if (rd & COUNTRY_ERD_FLAG) { - /* EEPROM value is a country code */ - u16 cc = rd & ~COUNTRY_ERD_FLAG; - for (i = 0; i < ARRAY_SIZE(allCountries); i++) - if (allCountries[i].countryCode == cc) - return true; - } else { - /* EEPROM value is a regpair value */ - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) - if (regDomainPairs[i].regDmnEnum == rd) - return true; - } - printk(KERN_DEBUG - "ath9k: invalid regulatory domain/country code 0x%x\n", rd); - return false; -} - -/* EEPROM country code to regpair mapping */ -static struct country_code_to_enum_rd* -ath9k_regd_find_country(u16 countryCode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].countryCode == countryCode) - return &allCountries[i]; - } - return NULL; -} - -/* EEPROM rd code to regpair mapping */ -static struct country_code_to_enum_rd* -ath9k_regd_find_country_by_rd(int regdmn) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].regDmnEnum == regdmn) - return &allCountries[i]; - } - return NULL; -} - -/* Returns the map of the EEPROM set RD to a country code */ -static u16 ath9k_regd_get_default_country(u16 rd) -{ - if (rd & COUNTRY_ERD_FLAG) { - struct country_code_to_enum_rd *country = NULL; - u16 cc = rd & ~COUNTRY_ERD_FLAG; - - country = ath9k_regd_find_country(cc); - if (country != NULL) - return cc; - } - - return CTRY_DEFAULT; -} - -static struct reg_dmn_pair_mapping* -ath9k_get_regpair(int regdmn) -{ - int i; - - if (regdmn == NO_ENUMRD) - return NULL; - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { - if (regDomainPairs[i].regDmnEnum == regdmn) - return ®DomainPairs[i]; - } - return NULL; -} - -int ath9k_regd_init(struct ath9k_regulatory *reg) -{ - struct country_code_to_enum_rd *country = NULL; - u16 regdmn; - - if (!ath9k_regd_is_eeprom_valid(reg)) { - printk(KERN_DEBUG "ath9k: Invalid EEPROM contents\n"); - return -EINVAL; - } - - regdmn = ath9k_regd_get_eepromRD(reg); - reg->country_code = ath9k_regd_get_default_country(regdmn); - - if (reg->country_code == CTRY_DEFAULT && - regdmn == CTRY_DEFAULT) - reg->country_code = CTRY_UNITED_STATES; - - if (reg->country_code == CTRY_DEFAULT) { - country = NULL; - } else { - country = ath9k_regd_find_country(reg->country_code); - if (country == NULL) { - printk(KERN_DEBUG - "ath9k: Country is NULL!!!!, cc= %d\n", - reg->country_code); - return -EINVAL; - } else - regdmn = country->regDmnEnum; - } - - reg->regpair = ath9k_get_regpair(regdmn); - - if (!reg->regpair) { - printk(KERN_DEBUG "ath9k: " - "No regulatory domain pair found, cannot continue\n"); - return -EINVAL; - } - - if (!country) - country = ath9k_regd_find_country_by_rd(regdmn); - - if (country) { - reg->alpha2[0] = country->isoName[0]; - reg->alpha2[1] = country->isoName[1]; - } else { - reg->alpha2[0] = '0'; - reg->alpha2[1] = '0'; - } - - printk(KERN_DEBUG "ath9k: Country alpha2 being used: %c%c\n", - reg->alpha2[0], reg->alpha2[1]); - printk(KERN_DEBUG "ath9k: Regpair detected: 0x%0x\n", - reg->regpair->regDmnEnum); - - return 0; -} - -static -u32 ath9k_regd_get_band_ctl(struct ath9k_regulatory *reg, - enum ieee80211_band band) -{ - if (!reg->regpair || - (reg->country_code == CTRY_DEFAULT && - is_wwr_sku(ath9k_regd_get_eepromRD(reg)))) { - return SD_NO_CTL; - } - - switch (band) { - case IEEE80211_BAND_2GHZ: - return reg->regpair->reg_2ghz_ctl; - case IEEE80211_BAND_5GHZ: - return reg->regpair->reg_5ghz_ctl; - default: - return NO_CTL; - } - - return NO_CTL; -} - -u32 ath9k_regd_get_ctl(struct ath9k_regulatory *reg, struct ath9k_channel *chan) -{ - u32 ctl = ath9k_regd_get_band_ctl(reg, chan->chan->band); - - if (IS_CHAN_B(chan)) - ctl |= CTL_11B; - else if (IS_CHAN_G(chan)) - ctl |= CTL_11G; - else - ctl |= CTL_11A; - - return ctl; -} diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h deleted file mode 100644 index 61fa42ebfbc4..000000000000 --- a/drivers/net/wireless/ath9k/regd.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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 REGD_H -#define REGD_H - -#include - -#define COUNTRY_ERD_FLAG 0x8000 -#define WORLDWIDE_ROAMING_FLAG 0x4000 - -#define MULTI_DOMAIN_MASK 0xFF00 - -#define WORLD_SKU_MASK 0x00F0 -#define WORLD_SKU_PREFIX 0x0060 - -#define CHANNEL_HALF_BW 10 -#define CHANNEL_QUARTER_BW 5 - -struct reg_dmn_pair_mapping { - u16 regDmnEnum; - u16 reg_5ghz_ctl; - u16 reg_2ghz_ctl; -}; - -struct country_code_to_enum_rd { - u16 countryCode; - u16 regDmnEnum; - const char *isoName; -}; - -struct ath9k_regulatory { - char alpha2[2]; - u16 country_code; - u16 max_power_level; - u32 tp_scale; - u16 current_rd; - u16 current_rd_ext; - int16_t power_limit; - struct reg_dmn_pair_mapping *regpair; -}; - -enum CountryCode { - CTRY_ALBANIA = 8, - CTRY_ALGERIA = 12, - CTRY_ARGENTINA = 32, - CTRY_ARMENIA = 51, - CTRY_AUSTRALIA = 36, - CTRY_AUSTRIA = 40, - CTRY_AZERBAIJAN = 31, - CTRY_BAHRAIN = 48, - CTRY_BELARUS = 112, - CTRY_BELGIUM = 56, - CTRY_BELIZE = 84, - CTRY_BOLIVIA = 68, - CTRY_BOSNIA_HERZ = 70, - CTRY_BRAZIL = 76, - CTRY_BRUNEI_DARUSSALAM = 96, - CTRY_BULGARIA = 100, - CTRY_CANADA = 124, - CTRY_CHILE = 152, - CTRY_CHINA = 156, - CTRY_COLOMBIA = 170, - CTRY_COSTA_RICA = 188, - CTRY_CROATIA = 191, - CTRY_CYPRUS = 196, - CTRY_CZECH = 203, - CTRY_DENMARK = 208, - CTRY_DOMINICAN_REPUBLIC = 214, - CTRY_ECUADOR = 218, - CTRY_EGYPT = 818, - CTRY_EL_SALVADOR = 222, - CTRY_ESTONIA = 233, - CTRY_FAEROE_ISLANDS = 234, - CTRY_FINLAND = 246, - CTRY_FRANCE = 250, - CTRY_GEORGIA = 268, - CTRY_GERMANY = 276, - CTRY_GREECE = 300, - CTRY_GUATEMALA = 320, - CTRY_HONDURAS = 340, - CTRY_HONG_KONG = 344, - CTRY_HUNGARY = 348, - CTRY_ICELAND = 352, - CTRY_INDIA = 356, - CTRY_INDONESIA = 360, - CTRY_IRAN = 364, - CTRY_IRAQ = 368, - CTRY_IRELAND = 372, - CTRY_ISRAEL = 376, - CTRY_ITALY = 380, - CTRY_JAMAICA = 388, - CTRY_JAPAN = 392, - CTRY_JORDAN = 400, - CTRY_KAZAKHSTAN = 398, - CTRY_KENYA = 404, - CTRY_KOREA_NORTH = 408, - CTRY_KOREA_ROC = 410, - CTRY_KOREA_ROC2 = 411, - CTRY_KOREA_ROC3 = 412, - CTRY_KUWAIT = 414, - CTRY_LATVIA = 428, - CTRY_LEBANON = 422, - CTRY_LIBYA = 434, - CTRY_LIECHTENSTEIN = 438, - CTRY_LITHUANIA = 440, - CTRY_LUXEMBOURG = 442, - CTRY_MACAU = 446, - CTRY_MACEDONIA = 807, - CTRY_MALAYSIA = 458, - CTRY_MALTA = 470, - CTRY_MEXICO = 484, - CTRY_MONACO = 492, - CTRY_MOROCCO = 504, - CTRY_NEPAL = 524, - CTRY_NETHERLANDS = 528, - CTRY_NETHERLANDS_ANTILLES = 530, - CTRY_NEW_ZEALAND = 554, - CTRY_NICARAGUA = 558, - CTRY_NORWAY = 578, - CTRY_OMAN = 512, - CTRY_PAKISTAN = 586, - CTRY_PANAMA = 591, - CTRY_PAPUA_NEW_GUINEA = 598, - CTRY_PARAGUAY = 600, - CTRY_PERU = 604, - CTRY_PHILIPPINES = 608, - CTRY_POLAND = 616, - CTRY_PORTUGAL = 620, - CTRY_PUERTO_RICO = 630, - CTRY_QATAR = 634, - CTRY_ROMANIA = 642, - CTRY_RUSSIA = 643, - CTRY_SAUDI_ARABIA = 682, - CTRY_SERBIA_MONTENEGRO = 891, - CTRY_SINGAPORE = 702, - CTRY_SLOVAKIA = 703, - CTRY_SLOVENIA = 705, - CTRY_SOUTH_AFRICA = 710, - CTRY_SPAIN = 724, - CTRY_SRI_LANKA = 144, - CTRY_SWEDEN = 752, - CTRY_SWITZERLAND = 756, - CTRY_SYRIA = 760, - CTRY_TAIWAN = 158, - CTRY_THAILAND = 764, - CTRY_TRINIDAD_Y_TOBAGO = 780, - CTRY_TUNISIA = 788, - CTRY_TURKEY = 792, - CTRY_UAE = 784, - CTRY_UKRAINE = 804, - CTRY_UNITED_KINGDOM = 826, - CTRY_UNITED_STATES = 840, - CTRY_UNITED_STATES_FCC49 = 842, - CTRY_URUGUAY = 858, - CTRY_UZBEKISTAN = 860, - CTRY_VENEZUELA = 862, - CTRY_VIET_NAM = 704, - CTRY_YEMEN = 887, - CTRY_ZIMBABWE = 716, - CTRY_JAPAN1 = 393, - CTRY_JAPAN2 = 394, - CTRY_JAPAN3 = 395, - CTRY_JAPAN4 = 396, - CTRY_JAPAN5 = 397, - CTRY_JAPAN6 = 4006, - CTRY_JAPAN7 = 4007, - CTRY_JAPAN8 = 4008, - CTRY_JAPAN9 = 4009, - CTRY_JAPAN10 = 4010, - CTRY_JAPAN11 = 4011, - CTRY_JAPAN12 = 4012, - CTRY_JAPAN13 = 4013, - CTRY_JAPAN14 = 4014, - CTRY_JAPAN15 = 4015, - CTRY_JAPAN16 = 4016, - CTRY_JAPAN17 = 4017, - CTRY_JAPAN18 = 4018, - CTRY_JAPAN19 = 4019, - CTRY_JAPAN20 = 4020, - CTRY_JAPAN21 = 4021, - CTRY_JAPAN22 = 4022, - CTRY_JAPAN23 = 4023, - CTRY_JAPAN24 = 4024, - CTRY_JAPAN25 = 4025, - CTRY_JAPAN26 = 4026, - CTRY_JAPAN27 = 4027, - CTRY_JAPAN28 = 4028, - CTRY_JAPAN29 = 4029, - CTRY_JAPAN30 = 4030, - CTRY_JAPAN31 = 4031, - CTRY_JAPAN32 = 4032, - CTRY_JAPAN33 = 4033, - CTRY_JAPAN34 = 4034, - CTRY_JAPAN35 = 4035, - CTRY_JAPAN36 = 4036, - CTRY_JAPAN37 = 4037, - CTRY_JAPAN38 = 4038, - CTRY_JAPAN39 = 4039, - CTRY_JAPAN40 = 4040, - CTRY_JAPAN41 = 4041, - CTRY_JAPAN42 = 4042, - CTRY_JAPAN43 = 4043, - CTRY_JAPAN44 = 4044, - CTRY_JAPAN45 = 4045, - CTRY_JAPAN46 = 4046, - CTRY_JAPAN47 = 4047, - CTRY_JAPAN48 = 4048, - CTRY_JAPAN49 = 4049, - CTRY_JAPAN50 = 4050, - CTRY_JAPAN51 = 4051, - CTRY_JAPAN52 = 4052, - CTRY_JAPAN53 = 4053, - CTRY_JAPAN54 = 4054, - CTRY_JAPAN55 = 4055, - CTRY_JAPAN56 = 4056, - CTRY_JAPAN57 = 4057, - CTRY_JAPAN58 = 4058, - CTRY_JAPAN59 = 4059, - CTRY_AUSTRALIA2 = 5000, - CTRY_CANADA2 = 5001, - CTRY_BELGIUM2 = 5002 -}; - -bool ath9k_is_world_regd(struct ath9k_regulatory *reg); -const struct ieee80211_regdomain *ath9k_world_regdomain( - struct ath9k_regulatory *reg); -const struct ieee80211_regdomain *ath9k_default_world_regdomain(void); -void ath9k_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator, - struct ath9k_regulatory *reg); -void ath9k_reg_apply_radar_flags(struct wiphy *wiphy); -int ath9k_regd_init(struct ath9k_regulatory *reg); -bool ath9k_regd_is_eeprom_valid(struct ath9k_regulatory *reg); -u32 ath9k_regd_get_ctl(struct ath9k_regulatory *reg, - struct ath9k_channel *chan); -int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); - -#endif diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h deleted file mode 100644 index 4d0e298cd1c7..000000000000 --- a/drivers/net/wireless/ath9k/regd_common.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - * 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 REGD_COMMON_H -#define REGD_COMMON_H - -enum EnumRd { - NO_ENUMRD = 0x00, - NULL1_WORLD = 0x03, - NULL1_ETSIB = 0x07, - NULL1_ETSIC = 0x08, - FCC1_FCCA = 0x10, - FCC1_WORLD = 0x11, - FCC4_FCCA = 0x12, - FCC5_FCCA = 0x13, - FCC6_FCCA = 0x14, - - FCC2_FCCA = 0x20, - FCC2_WORLD = 0x21, - FCC2_ETSIC = 0x22, - FCC6_WORLD = 0x23, - FRANCE_RES = 0x31, - FCC3_FCCA = 0x3A, - FCC3_WORLD = 0x3B, - - ETSI1_WORLD = 0x37, - ETSI3_ETSIA = 0x32, - ETSI2_WORLD = 0x35, - ETSI3_WORLD = 0x36, - ETSI4_WORLD = 0x30, - ETSI4_ETSIC = 0x38, - ETSI5_WORLD = 0x39, - ETSI6_WORLD = 0x34, - ETSI_RESERVED = 0x33, - - MKK1_MKKA = 0x40, - MKK1_MKKB = 0x41, - APL4_WORLD = 0x42, - MKK2_MKKA = 0x43, - APL_RESERVED = 0x44, - APL2_WORLD = 0x45, - APL2_APLC = 0x46, - APL3_WORLD = 0x47, - MKK1_FCCA = 0x48, - APL2_APLD = 0x49, - MKK1_MKKA1 = 0x4A, - MKK1_MKKA2 = 0x4B, - MKK1_MKKC = 0x4C, - - APL3_FCCA = 0x50, - APL1_WORLD = 0x52, - APL1_FCCA = 0x53, - APL1_APLA = 0x54, - APL1_ETSIC = 0x55, - APL2_ETSIC = 0x56, - APL5_WORLD = 0x58, - APL6_WORLD = 0x5B, - APL7_FCCA = 0x5C, - APL8_WORLD = 0x5D, - APL9_WORLD = 0x5E, - - WOR0_WORLD = 0x60, - WOR1_WORLD = 0x61, - WOR2_WORLD = 0x62, - WOR3_WORLD = 0x63, - WOR4_WORLD = 0x64, - WOR5_ETSIC = 0x65, - - WOR01_WORLD = 0x66, - WOR02_WORLD = 0x67, - EU1_WORLD = 0x68, - - WOR9_WORLD = 0x69, - WORA_WORLD = 0x6A, - WORB_WORLD = 0x6B, - - MKK3_MKKB = 0x80, - MKK3_MKKA2 = 0x81, - MKK3_MKKC = 0x82, - - MKK4_MKKB = 0x83, - MKK4_MKKA2 = 0x84, - MKK4_MKKC = 0x85, - - MKK5_MKKB = 0x86, - MKK5_MKKA2 = 0x87, - MKK5_MKKC = 0x88, - - MKK6_MKKB = 0x89, - MKK6_MKKA2 = 0x8A, - MKK6_MKKC = 0x8B, - - MKK7_MKKB = 0x8C, - MKK7_MKKA2 = 0x8D, - MKK7_MKKC = 0x8E, - - MKK8_MKKB = 0x8F, - MKK8_MKKA2 = 0x90, - MKK8_MKKC = 0x91, - - MKK14_MKKA1 = 0x92, - MKK15_MKKA1 = 0x93, - - MKK10_FCCA = 0xD0, - MKK10_MKKA1 = 0xD1, - MKK10_MKKC = 0xD2, - MKK10_MKKA2 = 0xD3, - - MKK11_MKKA = 0xD4, - MKK11_FCCA = 0xD5, - MKK11_MKKA1 = 0xD6, - MKK11_MKKC = 0xD7, - MKK11_MKKA2 = 0xD8, - - MKK12_MKKA = 0xD9, - MKK12_FCCA = 0xDA, - MKK12_MKKA1 = 0xDB, - MKK12_MKKC = 0xDC, - MKK12_MKKA2 = 0xDD, - - MKK13_MKKB = 0xDE, - - MKK3_MKKA = 0xF0, - MKK3_MKKA1 = 0xF1, - MKK3_FCCA = 0xF2, - MKK4_MKKA = 0xF3, - MKK4_MKKA1 = 0xF4, - MKK4_FCCA = 0xF5, - MKK9_MKKA = 0xF6, - MKK10_MKKA = 0xF7, - MKK6_MKKA1 = 0xF8, - MKK6_FCCA = 0xF9, - MKK7_MKKA1 = 0xFA, - MKK7_FCCA = 0xFB, - MKK9_FCCA = 0xFC, - MKK9_MKKA1 = 0xFD, - MKK9_MKKC = 0xFE, - MKK9_MKKA2 = 0xFF, - - WORLD = 0x0199, - DEBUG_REG_DMN = 0x01ff, -}; - -enum ctl_group { - CTL_FCC = 0x10, - CTL_MKK = 0x40, - CTL_ETSI = 0x30, -}; - -/* Regpair to CTL band mapping */ -static struct reg_dmn_pair_mapping regDomainPairs[] = { - /* regpair, 5 GHz CTL, 2 GHz CTL */ - {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN}, - {NULL1_WORLD, NO_CTL, CTL_ETSI}, - {NULL1_ETSIB, NO_CTL, CTL_ETSI}, - {NULL1_ETSIC, NO_CTL, CTL_ETSI}, - - {FCC2_FCCA, CTL_FCC, CTL_FCC}, - {FCC2_WORLD, CTL_FCC, CTL_ETSI}, - {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, - {FCC3_FCCA, CTL_FCC, CTL_FCC}, - {FCC3_WORLD, CTL_FCC, CTL_ETSI}, - {FCC4_FCCA, CTL_FCC, CTL_FCC}, - {FCC5_FCCA, CTL_FCC, CTL_FCC}, - {FCC6_FCCA, CTL_FCC, CTL_FCC}, - {FCC6_WORLD, CTL_FCC, CTL_ETSI}, - - {ETSI1_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI2_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI3_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, - - /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ - {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, - {FRANCE_RES, CTL_ETSI, CTL_ETSI}, - - {FCC1_WORLD, CTL_FCC, CTL_ETSI}, - {FCC1_FCCA, CTL_FCC, CTL_FCC}, - {APL1_WORLD, CTL_FCC, CTL_ETSI}, - {APL2_WORLD, CTL_FCC, CTL_ETSI}, - {APL3_WORLD, CTL_FCC, CTL_ETSI}, - {APL4_WORLD, CTL_FCC, CTL_ETSI}, - {APL5_WORLD, CTL_FCC, CTL_ETSI}, - {APL6_WORLD, CTL_ETSI, CTL_ETSI}, - {APL8_WORLD, CTL_ETSI, CTL_ETSI}, - {APL9_WORLD, CTL_ETSI, CTL_ETSI}, - - {APL3_FCCA, CTL_FCC, CTL_FCC}, - {APL1_ETSIC, CTL_FCC, CTL_ETSI}, - {APL2_ETSIC, CTL_FCC, CTL_ETSI}, - {APL2_APLD, CTL_FCC, NO_CTL}, - - {MKK1_MKKA, CTL_MKK, CTL_MKK}, - {MKK1_MKKB, CTL_MKK, CTL_MKK}, - {MKK1_FCCA, CTL_MKK, CTL_FCC}, - {MKK1_MKKA1, CTL_MKK, CTL_MKK}, - {MKK1_MKKA2, CTL_MKK, CTL_MKK}, - {MKK1_MKKC, CTL_MKK, CTL_MKK}, - - {MKK2_MKKA, CTL_MKK, CTL_MKK}, - {MKK3_MKKA, CTL_MKK, CTL_MKK}, - {MKK3_MKKB, CTL_MKK, CTL_MKK}, - {MKK3_MKKA1, CTL_MKK, CTL_MKK}, - {MKK3_MKKA2, CTL_MKK, CTL_MKK}, - {MKK3_MKKC, CTL_MKK, CTL_MKK}, - {MKK3_FCCA, CTL_MKK, CTL_FCC}, - - {MKK4_MKKA, CTL_MKK, CTL_MKK}, - {MKK4_MKKB, CTL_MKK, CTL_MKK}, - {MKK4_MKKA1, CTL_MKK, CTL_MKK}, - {MKK4_MKKA2, CTL_MKK, CTL_MKK}, - {MKK4_MKKC, CTL_MKK, CTL_MKK}, - {MKK4_FCCA, CTL_MKK, CTL_FCC}, - - {MKK5_MKKB, CTL_MKK, CTL_MKK}, - {MKK5_MKKA2, CTL_MKK, CTL_MKK}, - {MKK5_MKKC, CTL_MKK, CTL_MKK}, - - {MKK6_MKKB, CTL_MKK, CTL_MKK}, - {MKK6_MKKA1, CTL_MKK, CTL_MKK}, - {MKK6_MKKA2, CTL_MKK, CTL_MKK}, - {MKK6_MKKC, CTL_MKK, CTL_MKK}, - {MKK6_FCCA, CTL_MKK, CTL_FCC}, - - {MKK7_MKKB, CTL_MKK, CTL_MKK}, - {MKK7_MKKA1, CTL_MKK, CTL_MKK}, - {MKK7_MKKA2, CTL_MKK, CTL_MKK}, - {MKK7_MKKC, CTL_MKK, CTL_MKK}, - {MKK7_FCCA, CTL_MKK, CTL_FCC}, - - {MKK8_MKKB, CTL_MKK, CTL_MKK}, - {MKK8_MKKA2, CTL_MKK, CTL_MKK}, - {MKK8_MKKC, CTL_MKK, CTL_MKK}, - - {MKK9_MKKA, CTL_MKK, CTL_MKK}, - {MKK9_FCCA, CTL_MKK, CTL_FCC}, - {MKK9_MKKA1, CTL_MKK, CTL_MKK}, - {MKK9_MKKA2, CTL_MKK, CTL_MKK}, - {MKK9_MKKC, CTL_MKK, CTL_MKK}, - - {MKK10_MKKA, CTL_MKK, CTL_MKK}, - {MKK10_FCCA, CTL_MKK, CTL_FCC}, - {MKK10_MKKA1, CTL_MKK, CTL_MKK}, - {MKK10_MKKA2, CTL_MKK, CTL_MKK}, - {MKK10_MKKC, CTL_MKK, CTL_MKK}, - - {MKK11_MKKA, CTL_MKK, CTL_MKK}, - {MKK11_FCCA, CTL_MKK, CTL_FCC}, - {MKK11_MKKA1, CTL_MKK, CTL_MKK}, - {MKK11_MKKA2, CTL_MKK, CTL_MKK}, - {MKK11_MKKC, CTL_MKK, CTL_MKK}, - - {MKK12_MKKA, CTL_MKK, CTL_MKK}, - {MKK12_FCCA, CTL_MKK, CTL_FCC}, - {MKK12_MKKA1, CTL_MKK, CTL_MKK}, - {MKK12_MKKA2, CTL_MKK, CTL_MKK}, - {MKK12_MKKC, CTL_MKK, CTL_MKK}, - - {MKK13_MKKB, CTL_MKK, CTL_MKK}, - {MKK14_MKKA1, CTL_MKK, CTL_MKK}, - {MKK15_MKKA1, CTL_MKK, CTL_MKK}, - - {WOR0_WORLD, NO_CTL, NO_CTL}, - {WOR1_WORLD, NO_CTL, NO_CTL}, - {WOR2_WORLD, NO_CTL, NO_CTL}, - {WOR3_WORLD, NO_CTL, NO_CTL}, - {WOR4_WORLD, NO_CTL, NO_CTL}, - {WOR5_ETSIC, NO_CTL, NO_CTL}, - {WOR01_WORLD, NO_CTL, NO_CTL}, - {WOR02_WORLD, NO_CTL, NO_CTL}, - {EU1_WORLD, NO_CTL, NO_CTL}, - {WOR9_WORLD, NO_CTL, NO_CTL}, - {WORA_WORLD, NO_CTL, NO_CTL}, - {WORB_WORLD, NO_CTL, NO_CTL}, -}; - -static struct country_code_to_enum_rd allCountries[] = { - {CTRY_DEBUG, NO_ENUMRD, "DB"}, - {CTRY_DEFAULT, FCC1_FCCA, "CO"}, - {CTRY_ALBANIA, NULL1_WORLD, "AL"}, - {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, - {CTRY_ARGENTINA, APL3_WORLD, "AR"}, - {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, - {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, - {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, - {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, - {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, - {CTRY_BAHRAIN, APL6_WORLD, "BH"}, - {CTRY_BELARUS, ETSI1_WORLD, "BY"}, - {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, - {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, - {CTRY_BELIZE, APL1_ETSIC, "BZ"}, - {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, - {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, - {CTRY_BRAZIL, FCC3_WORLD, "BR"}, - {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, - {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, - {CTRY_CANADA, FCC2_FCCA, "CA"}, - {CTRY_CANADA2, FCC6_FCCA, "CA"}, - {CTRY_CHILE, APL6_WORLD, "CL"}, - {CTRY_CHINA, APL1_WORLD, "CN"}, - {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, - {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, - {CTRY_CROATIA, ETSI3_WORLD, "HR"}, - {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, - {CTRY_CZECH, ETSI3_WORLD, "CZ"}, - {CTRY_DENMARK, ETSI1_WORLD, "DK"}, - {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"}, - {CTRY_ECUADOR, FCC1_WORLD, "EC"}, - {CTRY_EGYPT, ETSI3_WORLD, "EG"}, - {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"}, - {CTRY_ESTONIA, ETSI1_WORLD, "EE"}, - {CTRY_FINLAND, ETSI1_WORLD, "FI"}, - {CTRY_FRANCE, ETSI1_WORLD, "FR"}, - {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, - {CTRY_GERMANY, ETSI1_WORLD, "DE"}, - {CTRY_GREECE, ETSI1_WORLD, "GR"}, - {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, - {CTRY_HONDURAS, NULL1_WORLD, "HN"}, - {CTRY_HONG_KONG, FCC2_WORLD, "HK"}, - {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, - {CTRY_ICELAND, ETSI1_WORLD, "IS"}, - {CTRY_INDIA, APL6_WORLD, "IN"}, - {CTRY_INDONESIA, APL1_WORLD, "ID"}, - {CTRY_IRAN, APL1_WORLD, "IR"}, - {CTRY_IRELAND, ETSI1_WORLD, "IE"}, - {CTRY_ISRAEL, NULL1_WORLD, "IL"}, - {CTRY_ITALY, ETSI1_WORLD, "IT"}, - {CTRY_JAMAICA, ETSI1_WORLD, "JM"}, - - {CTRY_JAPAN, MKK1_MKKA, "JP"}, - {CTRY_JAPAN1, MKK1_MKKB, "JP"}, - {CTRY_JAPAN2, MKK1_FCCA, "JP"}, - {CTRY_JAPAN3, MKK2_MKKA, "JP"}, - {CTRY_JAPAN4, MKK1_MKKA1, "JP"}, - {CTRY_JAPAN5, MKK1_MKKA2, "JP"}, - {CTRY_JAPAN6, MKK1_MKKC, "JP"}, - {CTRY_JAPAN7, MKK3_MKKB, "JP"}, - {CTRY_JAPAN8, MKK3_MKKA2, "JP"}, - {CTRY_JAPAN9, MKK3_MKKC, "JP"}, - {CTRY_JAPAN10, MKK4_MKKB, "JP"}, - {CTRY_JAPAN11, MKK4_MKKA2, "JP"}, - {CTRY_JAPAN12, MKK4_MKKC, "JP"}, - {CTRY_JAPAN13, MKK5_MKKB, "JP"}, - {CTRY_JAPAN14, MKK5_MKKA2, "JP"}, - {CTRY_JAPAN15, MKK5_MKKC, "JP"}, - {CTRY_JAPAN16, MKK6_MKKB, "JP"}, - {CTRY_JAPAN17, MKK6_MKKA2, "JP"}, - {CTRY_JAPAN18, MKK6_MKKC, "JP"}, - {CTRY_JAPAN19, MKK7_MKKB, "JP"}, - {CTRY_JAPAN20, MKK7_MKKA2, "JP"}, - {CTRY_JAPAN21, MKK7_MKKC, "JP"}, - {CTRY_JAPAN22, MKK8_MKKB, "JP"}, - {CTRY_JAPAN23, MKK8_MKKA2, "JP"}, - {CTRY_JAPAN24, MKK8_MKKC, "JP"}, - {CTRY_JAPAN25, MKK3_MKKA, "JP"}, - {CTRY_JAPAN26, MKK3_MKKA1, "JP"}, - {CTRY_JAPAN27, MKK3_FCCA, "JP"}, - {CTRY_JAPAN28, MKK4_MKKA1, "JP"}, - {CTRY_JAPAN29, MKK4_FCCA, "JP"}, - {CTRY_JAPAN30, MKK6_MKKA1, "JP"}, - {CTRY_JAPAN31, MKK6_FCCA, "JP"}, - {CTRY_JAPAN32, MKK7_MKKA1, "JP"}, - {CTRY_JAPAN33, MKK7_FCCA, "JP"}, - {CTRY_JAPAN34, MKK9_MKKA, "JP"}, - {CTRY_JAPAN35, MKK10_MKKA, "JP"}, - {CTRY_JAPAN36, MKK4_MKKA, "JP"}, - {CTRY_JAPAN37, MKK9_FCCA, "JP"}, - {CTRY_JAPAN38, MKK9_MKKA1, "JP"}, - {CTRY_JAPAN39, MKK9_MKKC, "JP"}, - {CTRY_JAPAN40, MKK9_MKKA2, "JP"}, - {CTRY_JAPAN41, MKK10_FCCA, "JP"}, - {CTRY_JAPAN42, MKK10_MKKA1, "JP"}, - {CTRY_JAPAN43, MKK10_MKKC, "JP"}, - {CTRY_JAPAN44, MKK10_MKKA2, "JP"}, - {CTRY_JAPAN45, MKK11_MKKA, "JP"}, - {CTRY_JAPAN46, MKK11_FCCA, "JP"}, - {CTRY_JAPAN47, MKK11_MKKA1, "JP"}, - {CTRY_JAPAN48, MKK11_MKKC, "JP"}, - {CTRY_JAPAN49, MKK11_MKKA2, "JP"}, - {CTRY_JAPAN50, MKK12_MKKA, "JP"}, - {CTRY_JAPAN51, MKK12_FCCA, "JP"}, - {CTRY_JAPAN52, MKK12_MKKA1, "JP"}, - {CTRY_JAPAN53, MKK12_MKKC, "JP"}, - {CTRY_JAPAN54, MKK12_MKKA2, "JP"}, - {CTRY_JAPAN57, MKK13_MKKB, "JP"}, - {CTRY_JAPAN58, MKK14_MKKA1, "JP"}, - {CTRY_JAPAN59, MKK15_MKKA1, "JP"}, - - {CTRY_JORDAN, ETSI2_WORLD, "JO"}, - {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"}, - {CTRY_KOREA_NORTH, APL9_WORLD, "KP"}, - {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, - {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, - {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, - {CTRY_KUWAIT, NULL1_WORLD, "KW"}, - {CTRY_LATVIA, ETSI1_WORLD, "LV"}, - {CTRY_LEBANON, NULL1_WORLD, "LB"}, - {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, - {CTRY_LITHUANIA, ETSI1_WORLD, "LT"}, - {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"}, - {CTRY_MACAU, FCC2_WORLD, "MO"}, - {CTRY_MACEDONIA, NULL1_WORLD, "MK"}, - {CTRY_MALAYSIA, APL8_WORLD, "MY"}, - {CTRY_MALTA, ETSI1_WORLD, "MT"}, - {CTRY_MEXICO, FCC1_FCCA, "MX"}, - {CTRY_MONACO, ETSI4_WORLD, "MC"}, - {CTRY_MOROCCO, NULL1_WORLD, "MA"}, - {CTRY_NEPAL, APL1_WORLD, "NP"}, - {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, - {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, - {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, - {CTRY_NORWAY, ETSI1_WORLD, "NO"}, - {CTRY_OMAN, APL6_WORLD, "OM"}, - {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, - {CTRY_PANAMA, FCC1_FCCA, "PA"}, - {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, - {CTRY_PERU, APL1_WORLD, "PE"}, - {CTRY_PHILIPPINES, APL1_WORLD, "PH"}, - {CTRY_POLAND, ETSI1_WORLD, "PL"}, - {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, - {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, - {CTRY_QATAR, NULL1_WORLD, "QA"}, - {CTRY_ROMANIA, NULL1_WORLD, "RO"}, - {CTRY_RUSSIA, NULL1_WORLD, "RU"}, - {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, - {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, - {CTRY_SINGAPORE, APL6_WORLD, "SG"}, - {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, - {CTRY_SLOVENIA, ETSI1_WORLD, "SI"}, - {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"}, - {CTRY_SPAIN, ETSI1_WORLD, "ES"}, - {CTRY_SRI_LANKA, FCC3_WORLD, "LK"}, - {CTRY_SWEDEN, ETSI1_WORLD, "SE"}, - {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, - {CTRY_SYRIA, NULL1_WORLD, "SY"}, - {CTRY_TAIWAN, APL3_FCCA, "TW"}, - {CTRY_THAILAND, NULL1_WORLD, "TH"}, - {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, - {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, - {CTRY_TURKEY, ETSI3_WORLD, "TR"}, - {CTRY_UKRAINE, NULL1_WORLD, "UA"}, - {CTRY_UAE, NULL1_WORLD, "AE"}, - {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, - {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, - /* This "PS" is for US public safety actually... to support this we - * would need to assign new special alpha2 to CRDA db as with the world - * regdomain and use another alpha2 */ - {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, - {CTRY_URUGUAY, APL2_WORLD, "UY"}, - {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, - {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, - {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, - {CTRY_YEMEN, NULL1_WORLD, "YE"}, - {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"}, -}; - -#endif -- cgit v1.2.3 From e3bb249be89dd387e78ca382d08fad31745edac9 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 30 Mar 2009 22:30:30 -0400 Subject: ath: move more setup code into ath_regd_init Setup the wiphy regulatory parameters when first initializing the Atheros regulatory module. We can remove five exported symbols this way and simplify the driver code for both ath5k and ath9k. Signed-off-by: Bob Copeland Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 55 ++++++++++++++++++++++++++++++--------- drivers/net/wireless/ath/regd.h | 12 +++------ drivers/net/wireless/ath9k/main.c | 47 +++++++++------------------------ 3 files changed, 58 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 4d3935b6fbdd..3ccf21cceb5a 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -126,14 +126,13 @@ bool ath_is_world_regd(struct ath_regulatory *reg) } EXPORT_SYMBOL(ath_is_world_regd); -const struct ieee80211_regdomain *ath_default_world_regdomain(void) +static const struct ieee80211_regdomain *ath_default_world_regdomain(void) { /* this is the most restrictive */ return &ath_world_regdom_64; } -EXPORT_SYMBOL(ath_default_world_regdomain); -const struct +static const struct ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) { switch (reg->regpair->regDmnEnum) { @@ -158,7 +157,6 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) return ath_default_world_regdomain(); } } -EXPORT_SYMBOL(ath_world_regdomain); /* Frequency is one where radar detection is required */ static bool ath_is_radar_freq(u16 center_freq) @@ -285,7 +283,7 @@ static void ath_reg_apply_active_scan_flags( } /* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ -void ath_reg_apply_radar_flags(struct wiphy *wiphy) +static void ath_reg_apply_radar_flags(struct wiphy *wiphy) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; @@ -316,11 +314,10 @@ void ath_reg_apply_radar_flags(struct wiphy *wiphy) IEEE80211_CHAN_PASSIVE_SCAN; } } -EXPORT_SYMBOL(ath_reg_apply_radar_flags); -void ath_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator, - struct ath_regulatory *reg) +static void ath_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct ath_regulatory *reg) { switch (reg->regpair->regDmnEnum) { case 0x60: @@ -336,7 +333,6 @@ void ath_reg_apply_world_flags(struct wiphy *wiphy, } return; } -EXPORT_SYMBOL(ath_reg_apply_world_flags); int ath_reg_notifier_apply(struct wiphy *wiphy, struct regulatory_request *request, struct ath_regulatory *reg) @@ -360,7 +356,7 @@ int ath_reg_notifier_apply(struct wiphy *wiphy, } EXPORT_SYMBOL(ath_reg_notifier_apply); -bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) +static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) { u16 rd = ath_regd_get_eepromRD(reg); int i; @@ -381,7 +377,6 @@ bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) "ath: invalid regulatory domain/country code 0x%x\n", rd); return false; } -EXPORT_SYMBOL(ath_regd_is_eeprom_valid); /* EEPROM country code to regpair mapping */ static struct country_code_to_enum_rd* @@ -438,7 +433,40 @@ ath_get_regpair(int regdmn) return NULL; } -int ath_regd_init(struct ath_regulatory *reg) +static int ath_regd_init_wiphy(struct ath_regulatory *reg, struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; + wiphy->strict_regulatory = true; + + if (ath_is_world_regd(reg)) { + /* + * Anything applied here (prior to wiphy registration) gets + * saved on the wiphy orig_* parameters + */ + regd = ath_world_regdomain(reg); + wiphy->custom_regulatory = true; + wiphy->strict_regulatory = false; + } else { + /* + * This gets applied in the case of the absense of CRDA, + * it's our own custom world regulatory domain, similar to + * cfg80211's but we enable passive scanning. + */ + regd = ath_default_world_regdomain(); + } + wiphy_apply_custom_regulatory(wiphy, regd); + ath_reg_apply_radar_flags(wiphy); + ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); + return 0; +} + +int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) { struct country_code_to_enum_rd *country = NULL; u16 regdmn; @@ -492,6 +520,7 @@ int ath_regd_init(struct ath_regulatory *reg) printk(KERN_DEBUG "ath: Regpair detected: 0x%0x\n", reg->regpair->regDmnEnum); + ath_regd_init_wiphy(reg, wiphy, reg_notifier); return 0; } EXPORT_SYMBOL(ath_regd_init); diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 981f5cf2bdb8..eba7c7123b50 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -254,15 +254,9 @@ enum CountryCode { }; bool ath_is_world_regd(struct ath_regulatory *reg); -const -struct ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg); -const struct ieee80211_regdomain *ath_default_world_regdomain(void); -void ath_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator, - struct ath_regulatory *reg); -void ath_reg_apply_radar_flags(struct wiphy *wiphy); -int ath_regd_init(struct ath_regulatory *reg); -bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg); +int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)); u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, enum ieee80211_band band); int ath_reg_notifier_apply(struct wiphy *wiphy, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index d779f00c9b9d..8b6a7ea4e59b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1352,6 +1352,17 @@ void ath_detach(struct ath_softc *sc) ath9k_ps_restore(sc); } +static int ath9k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_regulatory *reg = &sc->sc_ah->regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + static int ath_init(u16 devid, struct ath_softc *sc) { struct ath_hw *ah = NULL; @@ -1406,7 +1417,8 @@ static int ath_init(u16 devid, struct ath_softc *sc) for (i = 0; i < sc->keymax; i++) ath9k_hw_keyreset(ah, (u16) i); - if (ath_regd_init(&sc->sc_ah->regulatory)) + if (ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, + ath9k_reg_notifier)) goto bad; /* default to MONITOR mode */ @@ -1570,17 +1582,6 @@ bad: return error; } -static int ath9k_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_regulatory *reg = &sc->sc_ah->regulatory; - - return ath_reg_notifier_apply(wiphy, request, reg); -} - void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | @@ -1600,9 +1601,6 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - hw->wiphy->reg_notifier = ath9k_reg_notifier; - hw->wiphy->strict_regulatory = true; - hw->queues = 4; hw->max_rates = 4; hw->channel_change_time = 5000; @@ -1623,7 +1621,6 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; - const struct ieee80211_regdomain *regd; int error = 0, i; struct ath_regulatory *reg; @@ -1667,24 +1664,6 @@ int ath_attach(u16 devid, struct ath_softc *sc) goto error_attach; #endif - if (ath_is_world_regd(reg)) { - /* Anything applied here (prior to wiphy registration) gets - * saved on the wiphy orig_* parameters */ - regd = ath_world_regdomain(reg); - hw->wiphy->custom_regulatory = true; - hw->wiphy->strict_regulatory = false; - } else { - /* This gets applied in the case of the absense of CRDA, - * it's our own custom world regulatory domain, similar to - * cfg80211's but we enable passive scanning */ - regd = ath_default_world_regdomain(); - } - wiphy_apply_custom_regulatory(hw->wiphy, regd); - ath_reg_apply_radar_flags(hw->wiphy); - ath_reg_apply_world_flags(hw->wiphy, - NL80211_REGDOM_SET_BY_DRIVER, - reg); - INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); sc->wiphy_scheduler_int = msecs_to_jiffies(500); -- cgit v1.2.3 From f769c36bd71ebe8d7a5f83764f0428d36ebced35 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 30 Mar 2009 22:30:31 -0400 Subject: ath5k: use regulatory infrastructure Make ath5k select the ath module and add in the hooks to make the eeprom regulatory hint and reg notifier take effect. Changes to attach.c Changes-licensed-under: ISC Changes to base.c Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/Kconfig | 1 + drivers/net/wireless/ath5k/ath5k.h | 5 +++-- drivers/net/wireless/ath5k/base.c | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig index 75383a5df992..509b6f94f73b 100644 --- a/drivers/net/wireless/ath5k/Kconfig +++ b/drivers/net/wireless/ath5k/Kconfig @@ -1,6 +1,7 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + select ATH_COMMON select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 0b616e72fe05..48c18d11c507 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -27,6 +27,8 @@ #include #include +#include "../ath/regd.h" + /* RX/TX descriptor hw structs * TODO: Driver part should only see sw structs */ #include "desc.h" @@ -1039,8 +1041,6 @@ struct ath5k_hw { bool ah_5ghz; bool ah_2ghz; -#define ah_regdomain ah_capabilities.cap_regdomain.reg_current -#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw #define ah_modes ah_capabilities.cap_mode #define ah_ee_version ah_capabilities.cap_eeprom.ee_version @@ -1065,6 +1065,7 @@ struct ath5k_hw { u32 ah_gpio[AR5K_MAX_GPIO]; int ah_gpio_npins; + struct ath_regulatory ah_regulatory; struct ath5k_capabilities ah_capabilities; struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index d8c60c53d953..ff6d4f839734 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -709,6 +709,15 @@ err_no_irq: * Driver Initialization * \***********************/ +static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath5k_softc *sc = hw->priv; + struct ath_regulatory *reg = &sc->ah->ah_regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + static int ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) { @@ -797,12 +806,23 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) memset(sc->bssidmask, 0xff, ETH_ALEN); ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); + ah->ah_regulatory.current_rd = + ah->ah_capabilities.cap_eeprom.ee_regdomain; + ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); + if (ret) { + ATH5K_ERR(sc, "can't initialize regulatory system\n"); + goto err_queues; + } + ret = ieee80211_register_hw(hw); if (ret) { ATH5K_ERR(sc, "can't register ieee80211 hw\n"); goto err_queues; } + if (!ath_is_world_regd(&sc->ah->ah_regulatory)) + regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); + ath5k_init_leds(sc); return 0; -- cgit v1.2.3 From 1878f77e13b9d720b78c4f818b94bfd4a7f596e5 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 30 Mar 2009 22:30:32 -0400 Subject: Make ar9170 use common ath reg code Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ar9170/Kconfig | 1 + drivers/net/wireless/ar9170/ar9170.h | 3 +++ drivers/net/wireless/ar9170/main.c | 18 ++++++++++++++++++ drivers/net/wireless/ath/Kconfig | 2 +- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ar9170/Kconfig b/drivers/net/wireless/ar9170/Kconfig index de4281fda129..b99e3263ee6d 100644 --- a/drivers/net/wireless/ar9170/Kconfig +++ b/drivers/net/wireless/ar9170/Kconfig @@ -2,6 +2,7 @@ config AR9170_USB tristate "Atheros AR9170 802.11n USB support" depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER + select ATH_COMMON help This is a driver for the Atheros "otus" 802.11n USB devices. diff --git a/drivers/net/wireless/ar9170/ar9170.h b/drivers/net/wireless/ar9170/ar9170.h index f4fb2e94aea0..87c19859ba70 100644 --- a/drivers/net/wireless/ar9170/ar9170.h +++ b/drivers/net/wireless/ar9170/ar9170.h @@ -48,6 +48,8 @@ #include "eeprom.h" #include "hw.h" +#include "../ath/regd.h" + #define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) enum ar9170_bw { @@ -151,6 +153,7 @@ struct ar9170 { /* EEPROM */ struct ar9170_eeprom eeprom; + struct ath_regulatory regulatory; /* global tx status for unregistered Stations. */ struct sk_buff_head global_tx_status; diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ar9170/main.c index 5f55754d968f..8de0ff9f580b 100644 --- a/drivers/net/wireless/ar9170/main.c +++ b/drivers/net/wireless/ar9170/main.c @@ -1620,12 +1620,24 @@ static int ar9170_read_eeprom(struct ar9170 *ar) else ar->hw->channel_change_time = 80 * 1000; + ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); + ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); + /* second part of wiphy init */ SET_IEEE80211_PERM_ADDR(ar->hw, addr); return bands ? 0 : -EINVAL; } +static int ar9170_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ar9170 *ar = hw->priv; + + return ath_reg_notifier_apply(wiphy, request, &ar->regulatory); +} + int ar9170_register(struct ar9170 *ar, struct device *pdev) { int err; @@ -1635,10 +1647,16 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) if (err) goto err_out; + err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, + ar9170_reg_notifier); + err = ieee80211_register_hw(ar->hw); if (err) goto err_out; + if (!ath_is_world_regd(&ar->regulatory)) + regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); + err = ar9170_init_leds(ar); if (err) goto err_unreg; diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index c2873a24baae..76517a45a212 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -1,4 +1,4 @@ config ATH_COMMON tristate "Atheros Wireless Cards Shared Support" - depends on ATH5K || ATH9K + depends on ATH5K || ATH9K || AR9170_USB -- cgit v1.2.3 From 203c4805e91786f9a010bc7945a0fde70c9da28e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Mar 2009 22:30:33 -0400 Subject: atheros: put atheros wireless drivers into ath/ Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 3 - drivers/net/wireless/Makefile | 3 - drivers/net/wireless/ar9170/Kconfig | 18 - drivers/net/wireless/ar9170/Makefile | 3 - drivers/net/wireless/ar9170/ar9170.h | 212 -- drivers/net/wireless/ar9170/cmd.c | 129 - drivers/net/wireless/ar9170/cmd.h | 91 - drivers/net/wireless/ar9170/eeprom.h | 179 -- drivers/net/wireless/ar9170/hw.h | 417 --- drivers/net/wireless/ar9170/led.c | 171 - drivers/net/wireless/ar9170/mac.c | 452 --- drivers/net/wireless/ar9170/main.c | 1690 ---------- drivers/net/wireless/ar9170/phy.c | 1240 -------- drivers/net/wireless/ar9170/usb.c | 822 ----- drivers/net/wireless/ar9170/usb.h | 74 - drivers/net/wireless/ath/Kconfig | 6 +- drivers/net/wireless/ath/Makefile | 4 + drivers/net/wireless/ath/ar9170/Kconfig | 18 + drivers/net/wireless/ath/ar9170/Makefile | 3 + drivers/net/wireless/ath/ar9170/ar9170.h | 212 ++ drivers/net/wireless/ath/ar9170/cmd.c | 129 + drivers/net/wireless/ath/ar9170/cmd.h | 91 + drivers/net/wireless/ath/ar9170/eeprom.h | 179 ++ drivers/net/wireless/ath/ar9170/hw.h | 417 +++ drivers/net/wireless/ath/ar9170/led.c | 171 + drivers/net/wireless/ath/ar9170/mac.c | 452 +++ drivers/net/wireless/ath/ar9170/main.c | 1690 ++++++++++ drivers/net/wireless/ath/ar9170/phy.c | 1240 ++++++++ drivers/net/wireless/ath/ar9170/usb.c | 822 +++++ drivers/net/wireless/ath/ar9170/usb.h | 74 + drivers/net/wireless/ath/ath5k/Kconfig | 41 + drivers/net/wireless/ath/ath5k/Makefile | 15 + drivers/net/wireless/ath/ath5k/ath5k.h | 1354 ++++++++ drivers/net/wireless/ath/ath5k/attach.c | 348 +++ drivers/net/wireless/ath/ath5k/base.c | 3110 ++++++++++++++++++ drivers/net/wireless/ath/ath5k/base.h | 190 ++ drivers/net/wireless/ath/ath5k/caps.c | 195 ++ drivers/net/wireless/ath/ath5k/debug.c | 538 ++++ drivers/net/wireless/ath/ath5k/debug.h | 203 ++ drivers/net/wireless/ath/ath5k/desc.c | 696 +++++ drivers/net/wireless/ath/ath5k/desc.h | 332 ++ drivers/net/wireless/ath/ath5k/dma.c | 705 +++++ drivers/net/wireless/ath/ath5k/eeprom.c | 1769 +++++++++++ drivers/net/wireless/ath/ath5k/eeprom.h | 441 +++ drivers/net/wireless/ath/ath5k/gpio.c | 176 ++ drivers/net/wireless/ath/ath5k/initvals.c | 1557 +++++++++ drivers/net/wireless/ath/ath5k/led.c | 176 ++ drivers/net/wireless/ath/ath5k/pcu.c | 1174 +++++++ drivers/net/wireless/ath/ath5k/phy.c | 2599 ++++++++++++++++ drivers/net/wireless/ath/ath5k/qcu.c | 546 ++++ drivers/net/wireless/ath/ath5k/reg.h | 2589 +++++++++++++++ drivers/net/wireless/ath/ath5k/reset.c | 1346 ++++++++ drivers/net/wireless/ath/ath5k/rfbuffer.h | 1181 +++++++ drivers/net/wireless/ath/ath5k/rfgain.h | 516 +++ drivers/net/wireless/ath/ath9k/Kconfig | 24 + drivers/net/wireless/ath/ath9k/Makefile | 18 + drivers/net/wireless/ath/ath9k/ahb.c | 192 ++ drivers/net/wireless/ath/ath9k/ani.c | 822 +++++ drivers/net/wireless/ath/ath9k/ani.h | 138 + drivers/net/wireless/ath/ath9k/ath9k.h | 730 +++++ drivers/net/wireless/ath/ath9k/beacon.c | 743 +++++ drivers/net/wireless/ath/ath9k/calib.c | 1060 +++++++ drivers/net/wireless/ath/ath9k/calib.h | 124 + drivers/net/wireless/ath/ath9k/debug.c | 562 ++++ drivers/net/wireless/ath/ath9k/debug.h | 161 + drivers/net/wireless/ath/ath9k/eeprom.c | 2813 +++++++++++++++++ drivers/net/wireless/ath/ath9k/eeprom.h | 509 +++ drivers/net/wireless/ath/ath9k/hw.c | 3861 +++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 631 ++++ drivers/net/wireless/ath/ath9k/initvals.h | 4848 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/mac.c | 976 ++++++ drivers/net/wireless/ath/ath9k/mac.h | 680 ++++ drivers/net/wireless/ath/ath9k/main.c | 2890 +++++++++++++++++ drivers/net/wireless/ath/ath9k/pci.c | 295 ++ drivers/net/wireless/ath/ath9k/phy.c | 424 +++ drivers/net/wireless/ath/ath9k/phy.h | 576 ++++ drivers/net/wireless/ath/ath9k/rc.c | 1752 +++++++++++ drivers/net/wireless/ath/ath9k/rc.h | 216 ++ drivers/net/wireless/ath/ath9k/recv.c | 704 +++++ drivers/net/wireless/ath/ath9k/reg.h | 1511 +++++++++ drivers/net/wireless/ath/ath9k/virtual.c | 662 ++++ drivers/net/wireless/ath/ath9k/xmit.c | 2171 +++++++++++++ drivers/net/wireless/ath5k/Kconfig | 41 - drivers/net/wireless/ath5k/Makefile | 15 - drivers/net/wireless/ath5k/ath5k.h | 1354 -------- drivers/net/wireless/ath5k/attach.c | 348 --- drivers/net/wireless/ath5k/base.c | 3110 ------------------ drivers/net/wireless/ath5k/base.h | 190 -- drivers/net/wireless/ath5k/caps.c | 195 -- drivers/net/wireless/ath5k/debug.c | 538 ---- drivers/net/wireless/ath5k/debug.h | 203 -- drivers/net/wireless/ath5k/desc.c | 696 ----- drivers/net/wireless/ath5k/desc.h | 332 -- drivers/net/wireless/ath5k/dma.c | 705 ----- drivers/net/wireless/ath5k/eeprom.c | 1769 ----------- drivers/net/wireless/ath5k/eeprom.h | 441 --- drivers/net/wireless/ath5k/gpio.c | 176 -- drivers/net/wireless/ath5k/initvals.c | 1557 --------- drivers/net/wireless/ath5k/led.c | 176 -- drivers/net/wireless/ath5k/pcu.c | 1174 ------- drivers/net/wireless/ath5k/phy.c | 2599 ---------------- drivers/net/wireless/ath5k/qcu.c | 546 ---- drivers/net/wireless/ath5k/reg.h | 2589 --------------- drivers/net/wireless/ath5k/reset.c | 1346 -------- drivers/net/wireless/ath5k/rfbuffer.h | 1181 ------- drivers/net/wireless/ath5k/rfgain.h | 516 --- drivers/net/wireless/ath9k/Kconfig | 24 - drivers/net/wireless/ath9k/Makefile | 18 - drivers/net/wireless/ath9k/ahb.c | 192 -- drivers/net/wireless/ath9k/ani.c | 822 ----- drivers/net/wireless/ath9k/ani.h | 138 - drivers/net/wireless/ath9k/ath9k.h | 730 ----- drivers/net/wireless/ath9k/beacon.c | 743 ----- drivers/net/wireless/ath9k/calib.c | 1060 ------- drivers/net/wireless/ath9k/calib.h | 124 - drivers/net/wireless/ath9k/debug.c | 562 ---- drivers/net/wireless/ath9k/debug.h | 161 - drivers/net/wireless/ath9k/eeprom.c | 2813 ----------------- drivers/net/wireless/ath9k/eeprom.h | 509 --- drivers/net/wireless/ath9k/hw.c | 3861 ----------------------- drivers/net/wireless/ath9k/hw.h | 631 ---- drivers/net/wireless/ath9k/initvals.h | 4848 ----------------------------- drivers/net/wireless/ath9k/mac.c | 976 ------ drivers/net/wireless/ath9k/mac.h | 680 ---- drivers/net/wireless/ath9k/main.c | 2890 ----------------- drivers/net/wireless/ath9k/pci.c | 295 -- drivers/net/wireless/ath9k/phy.c | 424 --- drivers/net/wireless/ath9k/phy.h | 576 ---- drivers/net/wireless/ath9k/rc.c | 1752 ----------- drivers/net/wireless/ath9k/rc.h | 216 -- drivers/net/wireless/ath9k/recv.c | 704 ----- drivers/net/wireless/ath9k/reg.h | 1511 --------- drivers/net/wireless/ath9k/virtual.c | 662 ---- drivers/net/wireless/ath9k/xmit.c | 2171 ------------- 134 files changed, 57397 insertions(+), 57395 deletions(-) delete mode 100644 drivers/net/wireless/ar9170/Kconfig delete mode 100644 drivers/net/wireless/ar9170/Makefile delete mode 100644 drivers/net/wireless/ar9170/ar9170.h delete mode 100644 drivers/net/wireless/ar9170/cmd.c delete mode 100644 drivers/net/wireless/ar9170/cmd.h delete mode 100644 drivers/net/wireless/ar9170/eeprom.h delete mode 100644 drivers/net/wireless/ar9170/hw.h delete mode 100644 drivers/net/wireless/ar9170/led.c delete mode 100644 drivers/net/wireless/ar9170/mac.c delete mode 100644 drivers/net/wireless/ar9170/main.c delete mode 100644 drivers/net/wireless/ar9170/phy.c delete mode 100644 drivers/net/wireless/ar9170/usb.c delete mode 100644 drivers/net/wireless/ar9170/usb.h create mode 100644 drivers/net/wireless/ath/ar9170/Kconfig create mode 100644 drivers/net/wireless/ath/ar9170/Makefile create mode 100644 drivers/net/wireless/ath/ar9170/ar9170.h create mode 100644 drivers/net/wireless/ath/ar9170/cmd.c create mode 100644 drivers/net/wireless/ath/ar9170/cmd.h create mode 100644 drivers/net/wireless/ath/ar9170/eeprom.h create mode 100644 drivers/net/wireless/ath/ar9170/hw.h create mode 100644 drivers/net/wireless/ath/ar9170/led.c create mode 100644 drivers/net/wireless/ath/ar9170/mac.c create mode 100644 drivers/net/wireless/ath/ar9170/main.c create mode 100644 drivers/net/wireless/ath/ar9170/phy.c create mode 100644 drivers/net/wireless/ath/ar9170/usb.c create mode 100644 drivers/net/wireless/ath/ar9170/usb.h create mode 100644 drivers/net/wireless/ath/ath5k/Kconfig create mode 100644 drivers/net/wireless/ath/ath5k/Makefile create mode 100644 drivers/net/wireless/ath/ath5k/ath5k.h create mode 100644 drivers/net/wireless/ath/ath5k/attach.c create mode 100644 drivers/net/wireless/ath/ath5k/base.c create mode 100644 drivers/net/wireless/ath/ath5k/base.h create mode 100644 drivers/net/wireless/ath/ath5k/caps.c create mode 100644 drivers/net/wireless/ath/ath5k/debug.c create mode 100644 drivers/net/wireless/ath/ath5k/debug.h create mode 100644 drivers/net/wireless/ath/ath5k/desc.c create mode 100644 drivers/net/wireless/ath/ath5k/desc.h create mode 100644 drivers/net/wireless/ath/ath5k/dma.c create mode 100644 drivers/net/wireless/ath/ath5k/eeprom.c create mode 100644 drivers/net/wireless/ath/ath5k/eeprom.h create mode 100644 drivers/net/wireless/ath/ath5k/gpio.c create mode 100644 drivers/net/wireless/ath/ath5k/initvals.c create mode 100644 drivers/net/wireless/ath/ath5k/led.c create mode 100644 drivers/net/wireless/ath/ath5k/pcu.c create mode 100644 drivers/net/wireless/ath/ath5k/phy.c create mode 100644 drivers/net/wireless/ath/ath5k/qcu.c create mode 100644 drivers/net/wireless/ath/ath5k/reg.h create mode 100644 drivers/net/wireless/ath/ath5k/reset.c create mode 100644 drivers/net/wireless/ath/ath5k/rfbuffer.h create mode 100644 drivers/net/wireless/ath/ath5k/rfgain.h create mode 100644 drivers/net/wireless/ath/ath9k/Kconfig create mode 100644 drivers/net/wireless/ath/ath9k/Makefile create mode 100644 drivers/net/wireless/ath/ath9k/ahb.c create mode 100644 drivers/net/wireless/ath/ath9k/ani.c create mode 100644 drivers/net/wireless/ath/ath9k/ani.h create mode 100644 drivers/net/wireless/ath/ath9k/ath9k.h create mode 100644 drivers/net/wireless/ath/ath9k/beacon.c create mode 100644 drivers/net/wireless/ath/ath9k/calib.c create mode 100644 drivers/net/wireless/ath/ath9k/calib.h create mode 100644 drivers/net/wireless/ath/ath9k/debug.c create mode 100644 drivers/net/wireless/ath/ath9k/debug.h create mode 100644 drivers/net/wireless/ath/ath9k/eeprom.c create mode 100644 drivers/net/wireless/ath/ath9k/eeprom.h create mode 100644 drivers/net/wireless/ath/ath9k/hw.c create mode 100644 drivers/net/wireless/ath/ath9k/hw.h create mode 100644 drivers/net/wireless/ath/ath9k/initvals.h create mode 100644 drivers/net/wireless/ath/ath9k/mac.c create mode 100644 drivers/net/wireless/ath/ath9k/mac.h create mode 100644 drivers/net/wireless/ath/ath9k/main.c create mode 100644 drivers/net/wireless/ath/ath9k/pci.c create mode 100644 drivers/net/wireless/ath/ath9k/phy.c create mode 100644 drivers/net/wireless/ath/ath9k/phy.h create mode 100644 drivers/net/wireless/ath/ath9k/rc.c create mode 100644 drivers/net/wireless/ath/ath9k/rc.h create mode 100644 drivers/net/wireless/ath/ath9k/recv.c create mode 100644 drivers/net/wireless/ath/ath9k/reg.h create mode 100644 drivers/net/wireless/ath/ath9k/virtual.c create mode 100644 drivers/net/wireless/ath/ath9k/xmit.c delete mode 100644 drivers/net/wireless/ath5k/Kconfig delete mode 100644 drivers/net/wireless/ath5k/Makefile delete mode 100644 drivers/net/wireless/ath5k/ath5k.h delete mode 100644 drivers/net/wireless/ath5k/attach.c delete mode 100644 drivers/net/wireless/ath5k/base.c delete mode 100644 drivers/net/wireless/ath5k/base.h delete mode 100644 drivers/net/wireless/ath5k/caps.c delete mode 100644 drivers/net/wireless/ath5k/debug.c delete mode 100644 drivers/net/wireless/ath5k/debug.h delete mode 100644 drivers/net/wireless/ath5k/desc.c delete mode 100644 drivers/net/wireless/ath5k/desc.h delete mode 100644 drivers/net/wireless/ath5k/dma.c delete mode 100644 drivers/net/wireless/ath5k/eeprom.c delete mode 100644 drivers/net/wireless/ath5k/eeprom.h delete mode 100644 drivers/net/wireless/ath5k/gpio.c delete mode 100644 drivers/net/wireless/ath5k/initvals.c delete mode 100644 drivers/net/wireless/ath5k/led.c delete mode 100644 drivers/net/wireless/ath5k/pcu.c delete mode 100644 drivers/net/wireless/ath5k/phy.c delete mode 100644 drivers/net/wireless/ath5k/qcu.c delete mode 100644 drivers/net/wireless/ath5k/reg.h delete mode 100644 drivers/net/wireless/ath5k/reset.c delete mode 100644 drivers/net/wireless/ath5k/rfbuffer.h delete mode 100644 drivers/net/wireless/ath5k/rfgain.h delete mode 100644 drivers/net/wireless/ath9k/Kconfig delete mode 100644 drivers/net/wireless/ath9k/Makefile delete mode 100644 drivers/net/wireless/ath9k/ahb.c delete mode 100644 drivers/net/wireless/ath9k/ani.c delete mode 100644 drivers/net/wireless/ath9k/ani.h delete mode 100644 drivers/net/wireless/ath9k/ath9k.h delete mode 100644 drivers/net/wireless/ath9k/beacon.c delete mode 100644 drivers/net/wireless/ath9k/calib.c delete mode 100644 drivers/net/wireless/ath9k/calib.h delete mode 100644 drivers/net/wireless/ath9k/debug.c delete mode 100644 drivers/net/wireless/ath9k/debug.h delete mode 100644 drivers/net/wireless/ath9k/eeprom.c delete mode 100644 drivers/net/wireless/ath9k/eeprom.h delete mode 100644 drivers/net/wireless/ath9k/hw.c delete mode 100644 drivers/net/wireless/ath9k/hw.h delete mode 100644 drivers/net/wireless/ath9k/initvals.h delete mode 100644 drivers/net/wireless/ath9k/mac.c delete mode 100644 drivers/net/wireless/ath9k/mac.h delete mode 100644 drivers/net/wireless/ath9k/main.c delete mode 100644 drivers/net/wireless/ath9k/pci.c delete mode 100644 drivers/net/wireless/ath9k/phy.c delete mode 100644 drivers/net/wireless/ath9k/phy.h delete mode 100644 drivers/net/wireless/ath9k/rc.c delete mode 100644 drivers/net/wireless/ath9k/rc.h delete mode 100644 drivers/net/wireless/ath9k/recv.c delete mode 100644 drivers/net/wireless/ath9k/reg.h delete mode 100644 drivers/net/wireless/ath9k/virtual.c delete mode 100644 drivers/net/wireless/ath9k/xmit.c diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 9e2c7e26fcbf..8f279e7bd049 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -484,9 +484,6 @@ config MWL8K source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/ath/Kconfig" -source "drivers/net/wireless/ath5k/Kconfig" -source "drivers/net/wireless/ath9k/Kconfig" -source "drivers/net/wireless/ar9170/Kconfig" source "drivers/net/wireless/ipw2x00/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 104639e2783d..0625e91b5995 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -56,8 +56,5 @@ obj-$(CONFIG_RT2X00) += rt2x00/ obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_ATH_COMMON) += ath/ -obj-$(CONFIG_ATH5K) += ath5k/ -obj-$(CONFIG_ATH9K) += ath9k/ -obj-$(CONFIG_AR9170_USB) += ar9170/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o diff --git a/drivers/net/wireless/ar9170/Kconfig b/drivers/net/wireless/ar9170/Kconfig deleted file mode 100644 index b99e3263ee6d..000000000000 --- a/drivers/net/wireless/ar9170/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -config AR9170_USB - tristate "Atheros AR9170 802.11n USB support" - depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL - select FW_LOADER - select ATH_COMMON - help - This is a driver for the Atheros "otus" 802.11n USB devices. - - These devices require additional firmware (2 files). - For now, these files can be downloaded from here: - http://wireless.kernel.org/en/users/Drivers/ar9170 - - If you choose to build a module, it'll be called ar9170usb. - -config AR9170_LEDS - bool - depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) - default y diff --git a/drivers/net/wireless/ar9170/Makefile b/drivers/net/wireless/ar9170/Makefile deleted file mode 100644 index 8d91c7ee3215..000000000000 --- a/drivers/net/wireless/ar9170/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o - -obj-$(CONFIG_AR9170_USB) += ar9170usb.o diff --git a/drivers/net/wireless/ar9170/ar9170.h b/drivers/net/wireless/ar9170/ar9170.h deleted file mode 100644 index 87c19859ba70..000000000000 --- a/drivers/net/wireless/ar9170/ar9170.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Driver specific definitions - * - * Copyright 2008, Johannes Berg - * - * 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 __AR9170_H -#define __AR9170_H - -#include -#include -#include -#include -#ifdef CONFIG_AR9170_LEDS -#include -#endif /* CONFIG_AR9170_LEDS */ -#include "eeprom.h" -#include "hw.h" - -#include "../ath/regd.h" - -#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) - -enum ar9170_bw { - AR9170_BW_20, - AR9170_BW_40_BELOW, - AR9170_BW_40_ABOVE, - - __AR9170_NUM_BW, -}; - -enum ar9170_rf_init_mode { - AR9170_RFI_NONE, - AR9170_RFI_WARM, - AR9170_RFI_COLD, -}; - -#define AR9170_MAX_RX_BUFFER_SIZE 8192 - -#ifdef CONFIG_AR9170_LEDS -struct ar9170; - -struct ar9170_led { - struct ar9170 *ar; - struct led_classdev l; - char name[32]; - unsigned int toggled; - bool registered; -}; - -#endif /* CONFIG_AR9170_LEDS */ - -enum ar9170_device_state { - AR9170_UNKNOWN_STATE, - AR9170_STOPPED, - AR9170_IDLE, - AR9170_STARTED, - AR9170_ASSOCIATED, -}; - -struct ar9170 { - struct ieee80211_hw *hw; - struct mutex mutex; - enum ar9170_device_state state; - - int (*open)(struct ar9170 *); - void (*stop)(struct ar9170 *); - int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int); - int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , - void *, u32 , void *); - void (*callback_cmd)(struct ar9170 *, u32 , void *); - - /* interface mode settings */ - struct ieee80211_vif *vif; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - - /* beaconing */ - struct sk_buff *beacon; - struct work_struct beacon_work; - - /* cryptographic engine */ - u64 usedkeys; - bool rx_software_decryption; - bool disable_offload; - - /* filter settings */ - struct work_struct filter_config_work; - u64 cur_mc_hash, want_mc_hash; - u32 cur_filter, want_filter; - unsigned int filter_changed; - bool sniffer_enabled; - - /* PHY */ - struct ieee80211_channel *channel; - int noise[4]; - - /* 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_AR9170_LEDS - struct delayed_work led_work; - struct ar9170_led leds[AR9170_NUM_LEDS]; -#endif /* CONFIG_AR9170_LEDS */ - - /* qos queue settings */ - spinlock_t tx_stats_lock; - struct ieee80211_tx_queue_stats tx_stats[5]; - struct ieee80211_tx_queue_params edcf[5]; - - spinlock_t cmdlock; - __le32 cmdbuf[PAYLOAD_MAX + 1]; - - /* MAC statistics */ - struct ieee80211_low_level_stats stats; - - /* EEPROM */ - struct ar9170_eeprom eeprom; - struct ath_regulatory regulatory; - - /* global tx status for unregistered Stations. */ - struct sk_buff_head global_tx_status; - struct sk_buff_head global_tx_status_waste; - struct delayed_work tx_status_janitor; -}; - -struct ar9170_sta_info { - struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; -}; - -#define IS_STARTED(a) (a->state >= AR9170_STARTED) -#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE) - -#define AR9170_FILTER_CHANGED_PROMISC BIT(0) -#define AR9170_FILTER_CHANGED_MULTICAST BIT(1) -#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2) - -/* exported interface */ -void *ar9170_alloc(size_t priv_size); -int ar9170_register(struct ar9170 *ar, struct device *pdev); -void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); -void ar9170_unregister(struct ar9170 *ar); -void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, - bool update_statistics, u16 tx_status); - -/* MAC */ -int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -int ar9170_init_mac(struct ar9170 *ar); -int ar9170_set_qos(struct ar9170 *ar); -int ar9170_update_multicast(struct ar9170 *ar); -int ar9170_update_frame_filter(struct ar9170 *ar); -int ar9170_set_operating_mode(struct ar9170 *ar); -int ar9170_set_beacon_timers(struct ar9170 *ar); -int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); -int ar9170_update_beacon(struct ar9170 *ar); -void ar9170_new_beacon(struct work_struct *work); -int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, - u8 keyidx, u8 *keydata, int keylen); -int ar9170_disable_key(struct ar9170 *ar, u8 id); - -/* LEDs */ -#ifdef CONFIG_AR9170_LEDS -int ar9170_register_leds(struct ar9170 *ar); -void ar9170_unregister_leds(struct ar9170 *ar); -#endif /* CONFIG_AR9170_LEDS */ -int ar9170_init_leds(struct ar9170 *ar); -int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); - -/* PHY / RF */ -int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); -int ar9170_init_rf(struct ar9170 *ar); -int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); - -#endif /* __AR9170_H */ diff --git a/drivers/net/wireless/ar9170/cmd.c b/drivers/net/wireless/ar9170/cmd.c deleted file mode 100644 index f57a6200167b..000000000000 --- a/drivers/net/wireless/ar9170/cmd.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Basic HW register/memory/command access functions - * - * Copyright 2008, Johannes Berg - * - * 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 "ar9170.h" -#include "cmd.h" - -int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) -{ - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); - if (err) - printk(KERN_DEBUG "%s: writing memory failed\n", - wiphy_name(ar->hw->wiphy)); - return err; -} - -int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) -{ - __le32 buf[2] = { - cpu_to_le32(reg), - cpu_to_le32(val), - }; - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), - (u8 *) buf, 0, NULL); - if (err) - printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n", - wiphy_name(ar->hw->wiphy), reg, val); - return err; -} - -static int ar9170_read_mreg(struct ar9170 *ar, int nregs, - const u32 *regs, u32 *out) -{ - int i, err; - __le32 *offs, *res; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - /* 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 = ar->exec_cmd(ar, AR9170_CMD_RREG, - 4 * nregs, (u8 *)offs, - 4 * nregs, (u8 *)res); - if (err) - return err; - - /* convert result to cpu endian */ - for (i = 0; i < nregs; i++) - out[i] = le32_to_cpu(res[i]); - - return 0; -} - -int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) -{ - return ar9170_read_mreg(ar, 1, ®, val); -} - -int ar9170_echo_test(struct ar9170 *ar, u32 v) -{ - __le32 echobuf = cpu_to_le32(v); - __le32 echores; - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return -ENODEV; - - err = ar->exec_cmd(ar, AR9170_CMD_ECHO, - 4, (u8 *)&echobuf, - 4, (u8 *)&echores); - if (err) - return err; - - if (echobuf != echores) - return -EINVAL; - - return 0; -} diff --git a/drivers/net/wireless/ar9170/cmd.h b/drivers/net/wireless/ar9170/cmd.h deleted file mode 100644 index a4f0e50e52b4..000000000000 --- a/drivers/net/wireless/ar9170/cmd.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Basic HW register/memory/command access functions - * - * Copyright 2008, Johannes Berg - * - * 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 "ar9170.h" - -/* basic HW access */ -int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); -int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); -int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); -int ar9170_echo_test(struct ar9170 *ar, u32 v); - -/* - * 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 ar9170_regwrite_begin(ar) \ -do { \ - int __nreg = 0, __err = 0; \ - struct ar9170 *__ar = ar; - -#define ar9170_regwrite(r, v) do { \ - __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ - __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ - __nreg++; \ - if ((__nreg >= PAYLOAD_MAX/2)) { \ - if (IS_ACCEPTING_CMD(__ar)) \ - __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ - (u8 *) &__ar->cmdbuf[1], \ - 0, NULL); \ - __nreg = 0; \ - if (__err) \ - goto __regwrite_out; \ - } \ -} while (0) - -#define ar9170_regwrite_finish() \ -__regwrite_out : \ - if (__nreg) { \ - if (IS_ACCEPTING_CMD(__ar)) \ - __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ - (u8 *) &__ar->cmdbuf[1], \ - 0, NULL); \ - __nreg = 0; \ - } - -#define ar9170_regwrite_result() \ - __err; \ -} while (0); - -#endif /* __CMD_H */ diff --git a/drivers/net/wireless/ar9170/eeprom.h b/drivers/net/wireless/ar9170/eeprom.h deleted file mode 100644 index d2c8cc83f1dd..000000000000 --- a/drivers/net/wireless/ar9170/eeprom.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Atheros AR9170 driver - * - * EEPROM layout - * - * Copyright 2008, Johannes Berg - * - * 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 __AR9170_EEPROM_H -#define __AR9170_EEPROM_H - -#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; - -#endif /* __AR9170_EEPROM_H */ diff --git a/drivers/net/wireless/ar9170/hw.h b/drivers/net/wireless/ar9170/hw.h deleted file mode 100644 index 53e250a4278f..000000000000 --- a/drivers/net/wireless/ar9170/hw.h +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Hardware-specific definitions - * - * Copyright 2008, Johannes Berg - * - * 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 __AR9170_HW_H -#define __AR9170_HW_H - -#define AR9170_MAX_CMD_LEN 64 - -enum ar9170_cmd { - AR9170_CMD_RREG = 0x00, - AR9170_CMD_WREG = 0x01, - AR9170_CMD_RMEM = 0x02, - AR9170_CMD_WMEM = 0x03, - AR9170_CMD_BITAND = 0x04, - AR9170_CMD_BITOR = 0x05, - AR9170_CMD_EKEY = 0x28, - AR9170_CMD_DKEY = 0x29, - AR9170_CMD_FREQUENCY = 0x30, - AR9170_CMD_RF_INIT = 0x31, - AR9170_CMD_SYNTH = 0x32, - AR9170_CMD_FREQ_START = 0x33, - AR9170_CMD_ECHO = 0x80, - AR9170_CMD_TALLY = 0x81, - AR9170_CMD_TALLY_APD = 0x82, - AR9170_CMD_CONFIG = 0x83, - AR9170_CMD_RESET = 0x90, - AR9170_CMD_DKRESET = 0x91, - AR9170_CMD_DKTX_STATUS = 0x92, - AR9170_CMD_FDC = 0xA0, - AR9170_CMD_WREEPROM = 0xB0, - AR9170_CMD_WFLASH = 0xB0, - AR9170_CMD_FLASH_ERASE = 0xB1, - AR9170_CMD_FLASH_PROG = 0xB2, - AR9170_CMD_FLASH_CHKSUM = 0xB3, - AR9170_CMD_FLASH_READ = 0xB4, - AR9170_CMD_FW_DL_INIT = 0xB5, - AR9170_CMD_MEM_WREEPROM = 0xBB, -}; - -/* endpoints */ -#define AR9170_EP_TX 1 -#define AR9170_EP_RX 2 -#define AR9170_EP_IRQ 3 -#define AR9170_EP_CMD 4 - -#define AR9170_EEPROM_START 0x1600 - -#define AR9170_GPIO_REG_BASE 0x1d0100 -#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE -#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) -#define AR9170_NUM_LEDS 2 - - -#define AR9170_USB_REG_BASE 0x1e1000 -#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) -#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 -#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 -#define AR9170_DMA_CTL_HIGH_SPEED 0x4 -#define AR9170_DMA_CTL_PACKET_MODE 0x8 - -#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_MAC_REG_BASE 0x1c3000 - -#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_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) -#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) - -#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_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_REG_SNIFFER_ENABLE_PROMISC BIT(0) -#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 -#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) -#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) -#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 - -#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) -#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_REG_FTF_ASSOC_REQ BIT(0) -#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) -#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) -#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) -#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) -#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) -#define AR9170_MAC_REG_FTF_BIT6 BIT(6) -#define AR9170_MAC_REG_FTF_BIT7 BIT(7) -#define AR9170_MAC_REG_FTF_BEACON BIT(8) -#define AR9170_MAC_REG_FTF_ATIM BIT(9) -#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) -#define AR9170_MAC_REG_FTF_AUTH BIT(11) -#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) -#define AR9170_MAC_REG_FTF_BIT13 BIT(13) -#define AR9170_MAC_REG_FTF_BIT14 BIT(14) -#define AR9170_MAC_REG_FTF_BIT15 BIT(15) -#define AR9170_MAC_REG_FTF_BAR BIT(24) -#define AR9170_MAC_REG_FTF_BIT25 BIT(25) -#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) -#define AR9170_MAC_REG_FTF_RTS BIT(27) -#define AR9170_MAC_REG_FTF_CTS BIT(28) -#define AR9170_MAC_REG_FTF_ACK BIT(29) -#define AR9170_MAC_REG_FTF_CFE BIT(30) -#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) -#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff -#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff - -#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_RETRY (AR9170_MAC_REG_BASE + 0x6CC) -#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) - - -#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) -#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) - -#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) - -#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) -#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 -#define AR9170_MAC_REG_POWERMGT_AP 0xa1 -#define AR9170_MAC_REG_POWERMGT_STA 0x2 -#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 -#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) - -#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) -#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) - -#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_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) -#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) - -#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) - -#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_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) - -#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_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) -#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) - -#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_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) -#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) -#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) -#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) - - -#define AR9170_PWR_REG_BASE 0x1D4000 - -#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 - - -/* put beacon here in memory */ -#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 - - -struct ar9170_tx_control { - __le16 length; - __le16 mac_control; - __le32 phy_control; - u8 frame_data[0]; -} __packed; - -/* these are either-or */ -#define AR9170_TX_MAC_PROT_RTS 0x0001 -#define AR9170_TX_MAC_PROT_CTS 0x0002 - -#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_SHIFT 10 -#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) -#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 -#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 -#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 -#define AR9170_TX_MAC_TXOP_RIFS 0x2000 -#define AR9170_TX_MAC_IMM_AMPDU 0x4000 -#define AR9170_TX_MAC_RATE_PROBE 0x8000 - -/* 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_SHIFT 3 -#define AR9170_TX_PHY_BW_MASK (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_SHIFT 6 -#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) - -#define AR9170_TX_PHY_TX_PWR_SHIFT 9 -#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) - -/* not part of the hw-spec */ -#define AR9170_TX_PHY_QOS_SHIFT 25 -#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) - -#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 -#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) -#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_SHIFT 18 -#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) - -#define AR9170_TX_PHY_SHORT_GI 0x80000000 - -struct ar9170_rx_head { - u8 plcp[12]; -} __packed; - -struct ar9170_rx_tail { - 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; - u8 SAidx, DAidx; - u8 error; - u8 status; -} __packed; - -#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 - -static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) -{ - return (t->SAidx & 0xc0) >> 4 | - (t->DAidx & 0xc0) >> 6; -} - -#define AR9170_RX_STATUS_MODULATION_MASK 0x03 -#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_MASK 0x30 -#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 -#define AR9170_RX_STATUS_MPDU_FIRST 0x10 -#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20 -#define AR9170_RX_STATUS_MPDU_LAST 0x30 - - -#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 - -struct ar9170_cmd_tx_status { - __le16 unkn; - u8 dst[ETH_ALEN]; - __le32 rate; - __le16 status; -} __packed; - -#define AR9170_TX_STATUS_COMPLETE 0x00 -#define AR9170_TX_STATUS_RETRY 0x01 -#define AR9170_TX_STATUS_FAILED 0x02 - -struct ar9170_cmd_ba_failed_count { - __le16 failed; - __le16 rate; -} __packed; - -struct ar9170_cmd_response { - u8 flag; - u8 type; - - union { - struct ar9170_cmd_tx_status tx_status; - struct ar9170_cmd_ba_failed_count ba_fail_cnt; - u8 data[0]; - }; -} __packed; - -/* QoS */ - -/* mac80211 queue to HW/FW map */ -static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; - -/* HW/FW queue to mac80211 map */ -static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; - -enum ar9170_txq { - AR9170_TXQ_BE, - AR9170_TXQ_BK, - AR9170_TXQ_VI, - AR9170_TXQ_VO, - - __AR9170_NUM_TXQ, -}; - -#endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ar9170/led.c b/drivers/net/wireless/ar9170/led.c deleted file mode 100644 index 341cead7f606..000000000000 --- a/drivers/net/wireless/ar9170/led.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Atheros AR9170 driver - * - * LED handling - * - * Copyright 2008, Johannes Berg - * - * 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 "ar9170.h" -#include "cmd.h" - -int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) -{ - return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); -} - -int ar9170_init_leds(struct ar9170 *ar) -{ - int err; - - /* disable LEDs */ - /* GPIO [0/1 mode: output, 2/3: input] */ - err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); - if (err) - goto out; - - /* GPIO 0/1 value: off */ - err = ar9170_set_leds_state(ar, 0); - -out: - return err; -} - -#ifdef CONFIG_AR9170_LEDS -static void ar9170_update_leds(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); - int i, tmp, blink_delay = 1000; - u32 led_val = 0; - bool rerun = false; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return ; - - mutex_lock(&ar->mutex); - for (i = 0; i < AR9170_NUM_LEDS; i++) - if (ar->leds[i].toggled) { - led_val |= 1 << i; - - tmp = 70 + 200 / (ar->leds[i].toggled); - if (tmp < blink_delay) - blink_delay = tmp; - - if (ar->leds[i].toggled > 1) - ar->leds[i].toggled = 0; - - rerun = true; - } - - ar9170_set_leds_state(ar, led_val); - mutex_unlock(&ar->mutex); - - if (rerun) - queue_delayed_work(ar->hw->workqueue, &ar->led_work, - msecs_to_jiffies(blink_delay)); -} - -static void ar9170_led_brightness_set(struct led_classdev *led, - enum led_brightness brightness) -{ - struct ar9170_led *arl = container_of(led, struct ar9170_led, l); - struct ar9170 *ar = arl->ar; - - arl->toggled++; - - if (likely(IS_ACCEPTING_CMD(ar) && brightness)) - queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10); -} - -static int ar9170_register_led(struct ar9170 *ar, int i, char *name, - char *trigger) -{ - int err; - - snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), - "ar9170-%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 = ar9170_led_brightness_set; - 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) - printk(KERN_ERR "%s: failed to register %s LED (%d).\n", - wiphy_name(ar->hw->wiphy), ar->leds[i].name, err); - else - ar->leds[i].registered = true; - - return err; -} - -void ar9170_unregister_leds(struct ar9170 *ar) -{ - int i; - - cancel_delayed_work_sync(&ar->led_work); - - 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; - } -} - -int ar9170_register_leds(struct ar9170 *ar) -{ - int err; - - INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); - - err = ar9170_register_led(ar, 0, "tx", - ieee80211_get_tx_led_name(ar->hw)); - if (err) - goto fail; - - err = ar9170_register_led(ar, 1, "assoc", - ieee80211_get_assoc_led_name(ar->hw)); - if (err) - goto fail; - - return 0; - -fail: - ar9170_unregister_leds(ar); - return err; -} - -#endif /* CONFIG_AR9170_LEDS */ diff --git a/drivers/net/wireless/ar9170/mac.c b/drivers/net/wireless/ar9170/mac.c deleted file mode 100644 index c8fa3073169f..000000000000 --- a/drivers/net/wireless/ar9170/mac.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Atheros AR9170 driver - * - * MAC programming - * - * Copyright 2008, Johannes Berg - * - * 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 "ar9170.h" -#include "cmd.h" - -int ar9170_set_qos(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | - (ar->edcf[0].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | - (ar->edcf[1].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | - (ar->edcf[2].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | - (ar->edcf[3].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | - (ar->edcf[4].cw_max << 16)); - - ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, - ((ar->edcf[0].aifs * 9 + 10)) | - ((ar->edcf[1].aifs * 9 + 10) << 12) | - ((ar->edcf[2].aifs * 9 + 10) << 24)); - ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, - ((ar->edcf[2].aifs * 9 + 10) >> 8) | - ((ar->edcf[3].aifs * 9 + 10) << 4) | - ((ar->edcf[4].aifs * 9 + 10) << 16)); - - ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, - ar->edcf[0].txop | ar->edcf[1].txop << 16); - ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, - ar->edcf[1].txop | ar->edcf[3].txop << 16); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_init_mac(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); - - ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); - - /* enable MMIC */ - ar9170_regwrite(AR9170_MAC_REG_SNIFFER, - AR9170_MAC_REG_SNIFFER_DEFAULTS); - - ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); - - ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); - ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); - ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); - - /* CF-END mode */ - ar9170_regwrite(0x1c3b2c, 0x19000000); - - /* NAV protects ACK only (in TXOP) */ - ar9170_regwrite(0x1c3b38, 0x201); - - /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ - /* OTUS set AM to 0x1 */ - ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); - - ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); - - /* AGG test code*/ - /* Aggregation MAX number and timeout */ - ar9170_regwrite(0x1c3b9c, 0x10000a); - - ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, - AR9170_MAC_REG_FTF_DEFAULTS); - - /* Enable deaggregator, response in sniffer mode */ - ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); - - /* rate sets */ - ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); - ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); - ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); - - /* MIMO response control */ - ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ - - /* switch MAC to OTUS interface */ - ar9170_regwrite(0x1c3600, 0x3); - - ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); - - /* set PHY register read timeout (??) */ - ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); - - /* Disable Rx TimeOut, workaround for BB. */ - ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); - - /* Set CPU clock frequency to 88/80MHz */ - ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, - AR9170_PWR_CLK_AHB_80_88MHZ | - AR9170_PWR_CLK_DAC_160_INV_DLY); - - /* Set WLAN DMA interrupt mode: generate int per packet */ - ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); - - ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, - AR9170_MAC_FCS_FIFO_PROT); - - /* Disables the CF_END frame, undocumented register */ - ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, - 0x141E0F48); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) -{ - static const u8 zero[ETH_ALEN] = { 0 }; - - if (!mac) - mac = zero; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(reg, - (mac[3] << 24) | (mac[2] << 16) | - (mac[1] << 8) | mac[0]); - - ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_update_multicast(struct ar9170 *ar) -{ - int err; - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, - ar->want_mc_hash >> 32); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, - ar->want_mc_hash); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - - if (err) - return err; - - ar->cur_mc_hash = ar->want_mc_hash; - - return 0; -} - -int ar9170_update_frame_filter(struct ar9170 *ar) -{ - int err; - - err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, - ar->want_filter); - - if (err) - return err; - - ar->cur_filter = ar->want_filter; - - return 0; -} - -static int ar9170_set_promiscouous(struct ar9170 *ar) -{ - u32 encr_mode, sniffer; - int err; - - err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); - if (err) - return err; - - err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); - if (err) - return err; - - if (ar->sniffer_enabled) { - sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; - - /* - * Rx decryption works in place. - * - * If we don't disable it, the hardware will render all - * encrypted frames which are encrypted with an unknown - * key useless. - */ - - encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - ar->sniffer_enabled = true; - } else { - sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; - - if (ar->rx_software_decryption) - encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - else - encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); - ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_set_operating_mode(struct ar9170 *ar) -{ - u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; - u8 *mac_addr, *bssid; - int err; - - if (ar->vif) { - mac_addr = ar->mac_addr; - bssid = ar->bssid; - - switch (ar->vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; - break; -/* case NL80211_IFTYPE_AP: - pm_mode |= AR9170_MAC_REG_POWERMGT_AP; - break;*/ - case NL80211_IFTYPE_WDS: - pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; - break; - case NL80211_IFTYPE_MONITOR: - ar->sniffer_enabled = true; - ar->rx_software_decryption = true; - break; - default: - pm_mode |= AR9170_MAC_REG_POWERMGT_STA; - break; - } - } else { - mac_addr = NULL; - bssid = NULL; - } - - err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); - if (err) - return err; - - err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); - if (err) - return err; - - err = ar9170_set_promiscouous(ar); - if (err) - return err; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) -{ - u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); - - return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); -} - -int ar9170_set_beacon_timers(struct ar9170 *ar) -{ - u32 v = 0; - u32 pretbtt = 0; - - v |= ar->hw->conf.beacon_int; - - if (ar->vif) { - switch (ar->vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - v |= BIT(25); - break; - case NL80211_IFTYPE_AP: - v |= BIT(24); - pretbtt = (ar->hw->conf.beacon_int - 6) << 16; - break; - default: - break; - } - - v |= ar->vif->bss_conf.dtim_period << 16; - } - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); - ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -int ar9170_update_beacon(struct ar9170 *ar) -{ - struct sk_buff *skb; - __le32 *data, *old = NULL; - u32 word; - int i; - - skb = ieee80211_beacon_get(ar->hw, ar->vif); - if (!skb) - return -ENOMEM; - - data = (__le32 *)skb->data; - if (ar->beacon) - old = (__le32 *)ar->beacon->data; - - ar9170_regwrite_begin(ar); - for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { - /* - * XXX: This accesses beyond skb data for up - * to the last 3 bytes!! - */ - - if (old && (data[i] == old[i])) - continue; - - word = le32_to_cpu(data[i]); - ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); - } - - /* XXX: use skb->cb info */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) - ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << (3+16)) + 0x0400); - else - ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << (3+16)) + 0x0400); - - ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); - ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); - ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); - - ar9170_regwrite_finish(); - - dev_kfree_skb(ar->beacon); - ar->beacon = skb; - - return ar9170_regwrite_result(); -} - -void ar9170_new_beacon(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - beacon_work); - struct sk_buff *skb; - - if (unlikely(!IS_STARTED(ar))) - return ; - - mutex_lock(&ar->mutex); - - if (!ar->vif) - goto out; - - ar9170_update_beacon(ar); - - rcu_read_lock(); - while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) - ar9170_op_tx(ar->hw, skb); - - rcu_read_unlock(); - - out: - mutex_unlock(&ar->mutex); -} - -int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, - u8 keyidx, u8 *keydata, int keylen) -{ - __le32 vals[7]; - static const u8 bcast[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - u8 dummy; - - mac = mac ? : bcast; - - vals[0] = cpu_to_le32((keyidx << 16) + id); - vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); - vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | - mac[3] << 8 | mac[2]); - memset(&vals[3], 0, 16); - if (keydata) - memcpy(&vals[3], keydata, keylen); - - return ar->exec_cmd(ar, AR9170_CMD_EKEY, - sizeof(vals), (u8 *)vals, - 1, &dummy); -} - -int ar9170_disable_key(struct ar9170 *ar, u8 id) -{ - __le32 val = cpu_to_le32(id); - u8 dummy; - - return ar->exec_cmd(ar, AR9170_CMD_EKEY, - sizeof(val), (u8 *)&val, - 1, &dummy); -} diff --git a/drivers/net/wireless/ar9170/main.c b/drivers/net/wireless/ar9170/main.c deleted file mode 100644 index 8de0ff9f580b..000000000000 --- a/drivers/net/wireless/ar9170/main.c +++ /dev/null @@ -1,1690 +0,0 @@ -/* - * Atheros AR9170 driver - * - * mac80211 interaction code - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * 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 -#include -#include -#include -#include "ar9170.h" -#include "hw.h" -#include "cmd.h" - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ - .bitrate = (_bitrate), \ - .flags = (_flags), \ - .hw_value = (_hw_rate) | (_txpidx) << 4, \ -} - -static struct ieee80211_rate __ar9170_ratetable[] = { - RATE(10, 0, 0, 0), - RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(60, 0xb, 0, 0), - RATE(90, 0xf, 0, 0), - RATE(120, 0xa, 0, 0), - RATE(180, 0xe, 0, 0), - RATE(240, 0x9, 0, 0), - RATE(360, 0xd, 1, 0), - RATE(480, 0x8, 2, 0), - RATE(540, 0xc, 3, 0), -}; -#undef RATE - -#define ar9170_g_ratetable (__ar9170_ratetable + 0) -#define ar9170_g_ratetable_size 12 -#define ar9170_a_ratetable (__ar9170_ratetable + 4) -#define ar9170_a_ratetable_size 8 - -/* - * NB: The hw_value is used as an index into the ar9170_phy_freq_params - * array in phy.c so that we don't have to do frequency lookups! - */ -#define CHAN(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 18, /* XXX */ \ -} - -static struct ieee80211_channel ar9170_2ghz_chantable[] = { - CHAN(2412, 0), - CHAN(2417, 1), - CHAN(2422, 2), - CHAN(2427, 3), - CHAN(2432, 4), - CHAN(2437, 5), - CHAN(2442, 6), - CHAN(2447, 7), - CHAN(2452, 8), - CHAN(2457, 9), - CHAN(2462, 10), - CHAN(2467, 11), - CHAN(2472, 12), - CHAN(2484, 13), -}; - -static struct ieee80211_channel ar9170_5ghz_chantable[] = { - CHAN(4920, 14), - CHAN(4940, 15), - CHAN(4960, 16), - CHAN(4980, 17), - CHAN(5040, 18), - CHAN(5060, 19), - CHAN(5080, 20), - CHAN(5180, 21), - CHAN(5200, 22), - CHAN(5220, 23), - CHAN(5240, 24), - CHAN(5260, 25), - CHAN(5280, 26), - CHAN(5300, 27), - CHAN(5320, 28), - CHAN(5500, 29), - CHAN(5520, 30), - CHAN(5540, 31), - CHAN(5560, 32), - CHAN(5580, 33), - CHAN(5600, 34), - CHAN(5620, 35), - CHAN(5640, 36), - CHAN(5660, 37), - CHAN(5680, 38), - CHAN(5700, 39), - CHAN(5745, 40), - CHAN(5765, 41), - CHAN(5785, 42), - CHAN(5805, 43), - CHAN(5825, 44), - CHAN(5170, 45), - CHAN(5190, 46), - CHAN(5210, 47), - CHAN(5230, 48), -}; -#undef CHAN - -static struct ieee80211_supported_band ar9170_band_2GHz = { - .channels = ar9170_2ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), - .bitrates = ar9170_g_ratetable, - .n_bitrates = ar9170_g_ratetable_size, -}; - -#ifdef AR9170_QUEUE_DEBUG -/* - * In case some wants works with AR9170's crazy tx_status queueing techniques. - * He might need this rather useful probing function. - * - * NOTE: caller must hold the queue's spinlock! - */ - -static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *)txc->frame_data; - - printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] " - "mac_control:%04x, phy_control:%08x]\n", - wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control), - le32_to_cpu(txc->phy_control)); -} - -static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar, - struct sk_buff_head *queue) -{ - struct sk_buff *skb; - int i = 0; - - printk(KERN_DEBUG "---[ cut here ]---\n"); - printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n", - wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); - - skb_queue_walk(queue, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *)txc->frame_data; - - printk(KERN_DEBUG "index:%d => \n", i); - ar9170_print_txheader(ar, skb); - } - printk(KERN_DEBUG "---[ end ]---\n"); -} -#endif /* AR9170_QUEUE_DEBUG */ - -static struct ieee80211_supported_band ar9170_band_5GHz = { - .channels = ar9170_5ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), - .bitrates = ar9170_a_ratetable, - .n_bitrates = ar9170_a_ratetable_size, -}; - -void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, - bool valid_status, u16 tx_status) -{ - struct ieee80211_tx_info *txinfo; - unsigned int retries = 0, queue = skb_get_queue_mapping(skb); - unsigned long flags; - - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[queue].len--; - if (ieee80211_queue_stopped(ar->hw, queue)) - ieee80211_wake_queue(ar->hw, queue); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - switch (tx_status) { - case AR9170_TX_STATUS_RETRY: - retries = 2; - case AR9170_TX_STATUS_COMPLETE: - txinfo->flags |= IEEE80211_TX_STAT_ACK; - break; - - case AR9170_TX_STATUS_FAILED: - retries = ar->hw->conf.long_frame_max_tx_count; - break; - - default: - printk(KERN_ERR "%s: invalid tx_status response (%x).\n", - wiphy_name(ar->hw->wiphy), tx_status); - break; - } - - if (valid_status) - txinfo->status.rates[0].count = retries + 1; - - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); -} - -static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar, - const u8 *mac, - const u32 queue, - struct sk_buff_head *q) -{ - unsigned long flags; - struct sk_buff *skb; - - spin_lock_irqsave(&q->lock, flags); - skb_queue_walk(q, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - u32 txc_queue = (le32_to_cpu(txc->phy_control) & - AR9170_TX_PHY_QOS_MASK) >> - AR9170_TX_PHY_QOS_SHIFT; - - if ((queue != txc_queue) || - (compare_ether_addr(ieee80211_get_DA(hdr), mac))) - continue; - - __skb_unlink(skb, q); - spin_unlock_irqrestore(&q->lock, flags); - return skb; - } - spin_unlock_irqrestore(&q->lock, flags); - return NULL; -} - -static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, - const u32 queue) -{ - struct ieee80211_sta *sta; - struct sk_buff *skb; - - /* - * Unfortunately, the firmware does not tell to which (queued) frame - * this transmission status report belongs to. - * - * So we have to make risky guesses - with the scarce information - * the firmware provided (-> destination MAC, and phy_control) - - * and hope that we picked the right one... - */ - rcu_read_lock(); - sta = ieee80211_find_sta(ar->hw, mac); - - if (likely(sta)) { - struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv; - skb = skb_dequeue(&sta_priv->tx_status[queue]); - rcu_read_unlock(); - if (likely(skb)) - return skb; - } else - rcu_read_unlock(); - - /* scan the waste queue for candidates */ - skb = ar9170_find_skb_in_queue(ar, mac, queue, - &ar->global_tx_status_waste); - if (!skb) { - /* so it still _must_ be in the global list. */ - skb = ar9170_find_skb_in_queue(ar, mac, queue, - &ar->global_tx_status); - } - -#ifdef AR9170_QUEUE_DEBUG - if (unlikely((!skb) && net_ratelimit())) { - printk(KERN_ERR "%s: ESS:[%pM] does not have any " - "outstanding frames in this queue (%d).\n", - wiphy_name(ar->hw->wiphy), mac, queue); - } -#endif /* AR9170_QUEUE_DEBUG */ - return skb; -} - -/* - * This worker tries to keep the global tx_status queue empty. - * So we can guarantee that incoming tx_status reports for - * unregistered stations are always synced with the actual - * frame - which we think - belongs to. - */ - -static void ar9170_tx_status_janitor(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - tx_status_janitor.work); - struct sk_buff *skb; - - if (unlikely(!IS_STARTED(ar))) - return ; - - mutex_lock(&ar->mutex); - /* recycle the garbage back to mac80211... one by one. */ - while ((skb = skb_dequeue(&ar->global_tx_status_waste))) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: dispose queued frame =>\n", - wiphy_name(ar->hw->wiphy)); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - ar9170_handle_tx_status(ar, skb, false, - AR9170_TX_STATUS_FAILED); - } - - while ((skb = skb_dequeue(&ar->global_tx_status))) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: moving frame into waste queue =>\n", - wiphy_name(ar->hw->wiphy)); - - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - skb_queue_tail(&ar->global_tx_status_waste, skb); - } - - /* recall the janitor in 100ms - if there's garbage in the can. */ - if (skb_queue_len(&ar->global_tx_status_waste) > 0) - queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, - msecs_to_jiffies(100)); - - mutex_unlock(&ar->mutex); -} - -static void ar9170_handle_command_response(struct ar9170 *ar, - void *buf, u32 len) -{ - struct ar9170_cmd_response *cmd = (void *) buf; - - if ((cmd->type & 0xc0) != 0xc0) { - ar->callback_cmd(ar, len, buf); - return; - } - - /* hardware event handlers */ - switch (cmd->type) { - case 0xc1: { - /* - * TX status notification: - * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 - * - * XX always 81 - * YY always 00 - * M1-M6 is the MAC address - * R1-R4 is the transmit rate - * S1-S2 is the transmit status - */ - - struct sk_buff *skb; - u32 queue = (le32_to_cpu(cmd->tx_status.rate) & - AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT; - - skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue); - if (unlikely(!skb)) - return ; - - ar9170_handle_tx_status(ar, skb, true, - le16_to_cpu(cmd->tx_status.status)); - break; - } - - case 0xc0: - /* - * pre-TBTT event - */ - if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) - queue_work(ar->hw->workqueue, &ar->beacon_work); - break; - - case 0xc2: - /* - * (IBSS) beacon send notification - * bytes: 04 c2 XX YY B4 B3 B2 B1 - * - * XX always 80 - * YY always 00 - * B1-B4 "should" be the number of send out beacons. - */ - break; - - case 0xc3: - /* End of Atim Window */ - break; - - case 0xc4: - case 0xc5: - /* BlockACK events */ - break; - - case 0xc6: - /* Watchdog Interrupt */ - break; - - case 0xc9: - /* retransmission issue / SIFS/EIFS collision ?! */ - break; - - default: - printk(KERN_INFO "received unhandled event %x\n", cmd->type); - print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); - break; - } -} - -/* - * If the frame alignment is right (or the kernel has - * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there - * is only a single MPDU in the USB frame, then we can - * submit to mac80211 the SKB directly. However, since - * there may be multiple packets in one SKB in stream - * mode, and we need to observe the proper ordering, - * this is non-trivial. - */ -static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) -{ - struct sk_buff *skb; - struct ar9170_rx_head *head = (void *)buf; - struct ar9170_rx_tail *tail; - struct ieee80211_rx_status status; - int mpdu_len, i; - u8 error, antennas = 0, decrypt; - __le16 fc; - int reserved; - - if (unlikely(!IS_STARTED(ar))) - return ; - - /* Received MPDU */ - mpdu_len = len; - mpdu_len -= sizeof(struct ar9170_rx_head); - mpdu_len -= sizeof(struct ar9170_rx_tail); - BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); - BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24); - - if (mpdu_len <= FCS_LEN) - return; - - tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len); - - for (i = 0; i < 3; i++) - if (tail->rssi[i] != 0x80) - antennas |= BIT(i); - - /* post-process RSSI */ - for (i = 0; i < 7; i++) - if (tail->rssi[i] & 0x80) - tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f; - - memset(&status, 0, sizeof(status)); - - status.band = ar->channel->band; - status.freq = ar->channel->center_freq; - status.signal = ar->noise[0] + tail->rssi_combined; - status.noise = ar->noise[0]; - status.antenna = antennas; - - switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) { - case AR9170_RX_STATUS_MODULATION_CCK: - if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE) - status.flag |= RX_FLAG_SHORTPRE; - switch (head->plcp[0]) { - case 0x0a: - status.rate_idx = 0; - break; - case 0x14: - status.rate_idx = 1; - break; - case 0x37: - status.rate_idx = 2; - break; - case 0x6e: - status.rate_idx = 3; - break; - default: - if ((!ar->sniffer_enabled) && (net_ratelimit())) - printk(KERN_ERR "%s: invalid plcp cck rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); - return; - } - break; - case AR9170_RX_STATUS_MODULATION_OFDM: - switch (head->plcp[0] & 0xF) { - case 0xB: - status.rate_idx = 0; - break; - case 0xF: - status.rate_idx = 1; - break; - case 0xA: - status.rate_idx = 2; - break; - case 0xE: - status.rate_idx = 3; - break; - case 0x9: - status.rate_idx = 4; - break; - case 0xD: - status.rate_idx = 5; - break; - case 0x8: - status.rate_idx = 6; - break; - case 0xC: - status.rate_idx = 7; - break; - default: - if ((!ar->sniffer_enabled) && (net_ratelimit())) - printk(KERN_ERR "%s: invalid plcp ofdm rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); - return; - } - if (status.band == IEEE80211_BAND_2GHZ) - status.rate_idx += 4; - break; - case AR9170_RX_STATUS_MODULATION_HT: - case AR9170_RX_STATUS_MODULATION_DUPOFDM: - /* XXX */ - - if (net_ratelimit()) - printk(KERN_ERR "%s: invalid modulation\n", - wiphy_name(ar->hw->wiphy)); - return; - } - - error = tail->error; - - if (error & AR9170_RX_ERROR_MMIC) { - status.flag |= RX_FLAG_MMIC_ERROR; - error &= ~AR9170_RX_ERROR_MMIC; - } - - if (error & AR9170_RX_ERROR_PLCP) { - status.flag |= RX_FLAG_FAILED_PLCP_CRC; - error &= ~AR9170_RX_ERROR_PLCP; - } - - if (error & AR9170_RX_ERROR_FCS) { - status.flag |= RX_FLAG_FAILED_FCS_CRC; - error &= ~AR9170_RX_ERROR_FCS; - } - - decrypt = ar9170_get_decrypt_type(tail); - if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && - decrypt != AR9170_ENC_ALG_NONE) - status.flag |= RX_FLAG_DECRYPTED; - - /* ignore wrong RA errors */ - error &= ~AR9170_RX_ERROR_WRONG_RA; - - if (error & AR9170_RX_ERROR_DECRYPT) { - error &= ~AR9170_RX_ERROR_DECRYPT; - - /* - * Rx decryption is done in place, - * the original data is lost anyway. - */ - return ; - } - - /* drop any other error frames */ - if ((error) && (net_ratelimit())) { - printk(KERN_DEBUG "%s: errors: %#x\n", - wiphy_name(ar->hw->wiphy), error); - return; - } - - buf += sizeof(struct ar9170_rx_head); - fc = *(__le16 *)buf; - - if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc)) - reserved = 32 + 2; - else - reserved = 32; - - skb = dev_alloc_skb(mpdu_len + reserved); - if (!skb) - return; - - skb_reserve(skb, reserved); - memcpy(skb_put(skb, mpdu_len), buf, mpdu_len); - ieee80211_rx_irqsafe(ar->hw, skb, &status); -} - -void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) -{ - unsigned int i, tlen, resplen; - u8 *tbuf, *respbuf; - - tbuf = skb->data; - tlen = skb->len; - - while (tlen >= 4) { - int clen = tbuf[1] << 8 | tbuf[0]; - int wlen = (clen + 3) & ~3; - - /* - * parse stream (if any) - */ - if (tbuf[2] != 0 || tbuf[3] != 0x4e) { - printk(KERN_ERR "%s: missing tag!\n", - wiphy_name(ar->hw->wiphy)); - return ; - } - if (wlen > tlen - 4) { - printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n", - wiphy_name(ar->hw->wiphy), clen, wlen, tlen); - print_hex_dump(KERN_DEBUG, "data: ", - DUMP_PREFIX_OFFSET, - 16, 1, tbuf, tlen, true); - return ; - } - resplen = clen; - respbuf = tbuf + 4; - tbuf += wlen + 4; - tlen -= wlen + 4; - - i = 0; - - /* weird thing, but this is the same in the original driver */ - while (resplen > 2 && i < 12 && - respbuf[0] == 0xff && respbuf[1] == 0xff) { - i += 2; - resplen -= 2; - respbuf += 2; - } - - if (resplen < 4) - continue; - - /* found the 6 * 0xffff marker? */ - if (i == 12) - ar9170_handle_command_response(ar, respbuf, resplen); - else - ar9170_handle_mpdu(ar, respbuf, resplen); - } - - if (tlen) - printk(KERN_ERR "%s: buffer remains!\n", - wiphy_name(ar->hw->wiphy)); -} - -#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ -do { \ - queue.aifs = ai_fs; \ - queue.cw_min = cwmin; \ - queue.cw_max = cwmax; \ - queue.txop = _txop; \ -} while (0) - -static int ar9170_op_start(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - int err, i; - - mutex_lock(&ar->mutex); - - /* reinitialize queues statistics */ - memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); - for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++) - ar->tx_stats[i].limit = 8; - - /* reset QoS defaults */ - AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ - AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ - AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ - AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ - AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ - - err = ar->open(ar); - if (err) - goto out; - - err = ar9170_init_mac(ar); - if (err) - goto out; - - err = ar9170_set_qos(ar); - if (err) - goto out; - - err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); - if (err) - goto out; - - err = ar9170_init_rf(ar); - if (err) - goto out; - - /* start DMA */ - err = ar9170_write_reg(ar, 0x1c3d30, 0x100); - if (err) - goto out; - - ar->state = AR9170_STARTED; - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_op_stop(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - - if (IS_STARTED(ar)) - ar->state = AR9170_IDLE; - - flush_workqueue(ar->hw->workqueue); - - mutex_lock(&ar->mutex); - cancel_delayed_work_sync(&ar->tx_status_janitor); - cancel_work_sync(&ar->filter_config_work); - cancel_work_sync(&ar->beacon_work); - skb_queue_purge(&ar->global_tx_status_waste); - skb_queue_purge(&ar->global_tx_status); - - if (IS_ACCEPTING_CMD(ar)) { - ar9170_set_leds_state(ar, 0); - - /* stop DMA */ - ar9170_write_reg(ar, 0x1c3d30, 0); - ar->stop(ar); - } - - mutex_unlock(&ar->mutex); -} - -int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ar9170 *ar = hw->priv; - struct ieee80211_hdr *hdr; - struct ar9170_tx_control *txc; - struct ieee80211_tx_info *info; - struct ieee80211_rate *rate = NULL; - struct ieee80211_tx_rate *txrate; - unsigned int queue = skb_get_queue_mapping(skb); - unsigned long flags = 0; - struct ar9170_sta_info *sta_info = NULL; - u32 power, chains; - u16 keytype = 0; - u16 len, icv = 0; - int err; - bool tx_status; - - if (unlikely(!IS_STARTED(ar))) - goto err_free; - - hdr = (void *)skb->data; - info = IEEE80211_SKB_CB(skb); - len = skb->len; - - spin_lock_irqsave(&ar->tx_stats_lock, flags); - if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) { - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - return NETDEV_TX_OK; - } - - ar->tx_stats[queue].len++; - ar->tx_stats[queue].count++; - if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len) - ieee80211_stop_queue(hw, queue); - - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - - txc = (void *)skb_push(skb, sizeof(*txc)); - - tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) || - ((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0)); - - if (info->control.hw_key) { - icv = info->control.hw_key->icv_len; - - switch (info->control.hw_key->alg) { - case ALG_WEP: - keytype = AR9170_TX_MAC_ENCR_RC4; - break; - case ALG_TKIP: - keytype = AR9170_TX_MAC_ENCR_RC4; - break; - case ALG_CCMP: - keytype = AR9170_TX_MAC_ENCR_AES; - break; - default: - WARN_ON(1); - goto err_dequeue; - } - } - - /* Length */ - txc->length = cpu_to_le16(len + icv + 4); - - txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | - AR9170_TX_MAC_BACKOFF); - txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << - AR9170_TX_MAC_QOS_SHIFT); - txc->mac_control |= cpu_to_le16(keytype); - txc->phy_control = cpu_to_le32(0); - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - - txrate = &info->control.rates[0]; - - if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - - if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); - - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); - - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); - /* this works because 40 MHz is 2 and dup is 3 */ - if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); - - if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); - - if (txrate->flags & IEEE80211_TX_RC_MCS) { - u32 r = txrate->idx; - u8 *txpower; - - r <<= AR9170_TX_PHY_MCS_SHIFT; - if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK)) - goto err_dequeue; - txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); - - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht40; - else - txpower = ar->power_2G_ht40; - } else { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht20; - else - txpower = ar->power_2G_ht20; - } - - power = txpower[(txrate->idx) & 7]; - } else { - u8 *txpower; - u32 mod; - u32 phyrate; - u8 idx = txrate->idx; - - if (info->band != IEEE80211_BAND_2GHZ) { - idx += 4; - txpower = ar->power_5G_leg; - mod = AR9170_TX_PHY_MOD_OFDM; - } else { - if (idx < 4) { - txpower = ar->power_2G_cck; - mod = AR9170_TX_PHY_MOD_CCK; - } else { - mod = AR9170_TX_PHY_MOD_OFDM; - txpower = ar->power_2G_ofdm; - } - } - - rate = &__ar9170_ratetable[idx]; - - phyrate = rate->hw_value & 0xF; - power = txpower[(rate->hw_value & 0x30) >> 4]; - phyrate <<= AR9170_TX_PHY_MCS_SHIFT; - - txc->phy_control |= cpu_to_le32(mod); - txc->phy_control |= cpu_to_le32(phyrate); - } - - power <<= AR9170_TX_PHY_TX_PWR_SHIFT; - power &= AR9170_TX_PHY_TX_PWR_MASK; - txc->phy_control |= cpu_to_le32(power); - - /* set TX chains */ - if (ar->eeprom.tx_mask == 1) { - chains = AR9170_TX_PHY_TXCHAIN_1; - } else { - chains = AR9170_TX_PHY_TXCHAIN_2; - - /* >= 36M legacy OFDM - use only one chain */ - if (rate && rate->bitrate >= 360) - chains = AR9170_TX_PHY_TXCHAIN_1; - } - txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); - - if (tx_status) { - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); - /* - * WARNING: - * Putting the QoS queue bits into an unexplored territory is - * certainly not elegant. - * - * In my defense: This idea provides a reasonable way to - * smuggle valuable information to the tx_status callback. - * Also, the idea behind this bit-abuse came straight from - * the original driver code. - */ - - txc->phy_control |= - cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); - - if (info->control.sta) { - sta_info = (void *) info->control.sta->drv_priv; - skb_queue_tail(&sta_info->tx_status[queue], skb); - } else { - skb_queue_tail(&ar->global_tx_status, skb); - - queue_delayed_work(ar->hw->workqueue, - &ar->tx_status_janitor, - msecs_to_jiffies(100)); - } - } - - err = ar->tx(ar, skb, tx_status, 0); - if (unlikely(tx_status && err)) { - if (info->control.sta) - skb_unlink(skb, &sta_info->tx_status[queue]); - else - skb_unlink(skb, &ar->global_tx_status); - } - - return NETDEV_TX_OK; - -err_dequeue: - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[queue].len--; - ar->tx_stats[queue].count--; - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - -err_free: - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -static int ar9170_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (ar->vif) { - err = -EBUSY; - goto unlock; - } - - ar->vif = conf->vif; - memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); - - if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { - ar->rx_software_decryption = true; - ar->disable_offload = true; - } - - ar->cur_filter = 0; - ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS; - err = ar9170_update_frame_filter(ar); - if (err) - goto unlock; - - err = ar9170_set_operating_mode(ar); - -unlock: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ar9170 *ar = hw->priv; - - mutex_lock(&ar->mutex); - ar->vif = NULL; - ar->want_filter = 0; - ar9170_update_frame_filter(ar); - ar9170_set_beacon_timers(ar); - dev_kfree_skb(ar->beacon); - ar->beacon = NULL; - ar->sniffer_enabled = false; - ar->rx_software_decryption = false; - ar9170_set_operating_mode(ar); - mutex_unlock(&ar->mutex); -} - -static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { - /* - * is it long_frame_max_tx_count or short_frame_max_tx_count? - */ - - err = ar9170_set_hwretry_limit(ar, - ar->hw->conf.long_frame_max_tx_count); - if (err) - goto out; - } - - if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) { - err = ar9170_set_beacon_timers(ar); - if (err) - goto out; - } - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - err = ar9170_set_channel(ar, hw->conf.channel, - AR9170_RFI_NONE, AR9170_BW_20); - if (err) - goto out; - /* adjust slot time for 5 GHz */ - if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) - err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, - 9 << 10); - } - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static int ar9170_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (conf->changed & IEEE80211_IFCC_BSSID) { - memcpy(ar->bssid, conf->bssid, ETH_ALEN); - err = ar9170_set_operating_mode(ar); - } - - if (conf->changed & IEEE80211_IFCC_BEACON) { - err = ar9170_update_beacon(ar); - - if (err) - goto out; - err = ar9170_set_beacon_timers(ar); - } - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_set_filters(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - filter_config_work); - int err; - - if (unlikely(!IS_STARTED(ar))) - return ; - - mutex_lock(&ar->mutex); - if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) { - err = ar9170_set_operating_mode(ar); - if (err) - goto unlock; - } - - if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) { - err = ar9170_update_multicast(ar); - if (err) - goto unlock; - } - - if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER) - err = ar9170_update_frame_filter(ar); - -unlock: - mutex_unlock(&ar->mutex); -} - -static void ar9170_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) -{ - struct ar9170 *ar = hw->priv; - - /* mask supported flags */ - *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | - FIF_PROMISC_IN_BSS; - - /* - * We can support more by setting the sniffer bit and - * then checking the error flags, later. - */ - - if (changed_flags & FIF_ALLMULTI) { - if (*new_flags & FIF_ALLMULTI) { - ar->want_mc_hash = ~0ULL; - } else { - u64 mchash; - int i; - - /* always get broadcast frames */ - mchash = 1ULL << (0xff>>2); - - for (i = 0; i < mc_count; i++) { - if (WARN_ON(!mclist)) - break; - mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); - mclist = mclist->next; - } - ar->want_mc_hash = mchash; - } - ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST; - } - - if (changed_flags & FIF_CONTROL) { - u32 filter = AR9170_MAC_REG_FTF_PSPOLL | - AR9170_MAC_REG_FTF_RTS | - AR9170_MAC_REG_FTF_CTS | - AR9170_MAC_REG_FTF_ACK | - AR9170_MAC_REG_FTF_CFE | - AR9170_MAC_REG_FTF_CFE_ACK; - - if (*new_flags & FIF_CONTROL) - ar->want_filter = ar->cur_filter | filter; - else - ar->want_filter = ar->cur_filter & ~filter; - - ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER; - } - - if (changed_flags & FIF_PROMISC_IN_BSS) { - ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; - ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC; - } - - if (likely(IS_STARTED(ar))) - queue_work(ar->hw->workqueue, &ar->filter_config_work); -} - -static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - ar9170_regwrite_begin(ar); - - if (changed & BSS_CHANGED_ASSOC) { - ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state; - -#ifndef CONFIG_AR9170_LEDS - /* enable assoc LED. */ - err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); -#endif /* CONFIG_AR9170_LEDS */ - } - - if (changed & BSS_CHANGED_HT) { - /* TODO */ - err = 0; - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - u32 slottime = 20; - - if (bss_conf->use_short_slot) - slottime = 9; - - ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10); - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - u32 cck, ofdm; - - if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) { - ofdm = bss_conf->basic_rates; - cck = 0; - } else { - /* four cck rates */ - cck = bss_conf->basic_rates & 0xf; - ofdm = bss_conf->basic_rates >> 4; - } - ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, - ofdm << 8 | cck); - } - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - mutex_unlock(&ar->mutex); -} - -static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - int err; - u32 tsf_low; - u32 tsf_high; - u64 tsf; - - mutex_lock(&ar->mutex); - err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); - if (!err) - err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); - mutex_unlock(&ar->mutex); - - if (WARN_ON(err)) - return 0; - - tsf = tsf_high; - tsf = (tsf << 32) | tsf_low; - return tsf; -} - -static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ar9170 *ar = hw->priv; - int err = 0, i; - u8 ktype; - - if ((!ar->vif) || (ar->disable_offload)) - return -EOPNOTSUPP; - - switch (key->alg) { - case ALG_WEP: - if (key->keylen == LEN_WEP40) - ktype = AR9170_ENC_ALG_WEP64; - else - ktype = AR9170_ENC_ALG_WEP128; - break; - case ALG_TKIP: - ktype = AR9170_ENC_ALG_TKIP; - break; - case ALG_CCMP: - ktype = AR9170_ENC_ALG_AESCCMP; - break; - default: - return -EOPNOTSUPP; - } - - mutex_lock(&ar->mutex); - if (cmd == SET_KEY) { - if (unlikely(!IS_STARTED(ar))) { - err = -EOPNOTSUPP; - goto out; - } - - /* group keys need all-zeroes address */ - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) - sta = NULL; - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { - for (i = 0; i < 64; i++) - if (!(ar->usedkeys & BIT(i))) - break; - if (i == 64) { - ar->rx_software_decryption = true; - ar9170_set_operating_mode(ar); - err = -ENOSPC; - goto out; - } - } else { - i = 64 + key->keyidx; - } - - key->hw_key_idx = i; - - err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, - key->key, min_t(u8, 16, key->keylen)); - if (err) - goto out; - - if (key->alg == ALG_TKIP) { - err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, - ktype, 1, key->key + 16, 16); - if (err) - goto out; - - /* - * hardware is not capable generating the MMIC - * for fragmented frames! - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - } - - if (i < 64) - ar->usedkeys |= BIT(i); - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } else { - if (unlikely(!IS_STARTED(ar))) { - /* The device is gone... together with the key ;-) */ - err = 0; - goto out; - } - - err = ar9170_disable_key(ar, key->hw_key_idx); - if (err) - goto out; - - if (key->hw_key_idx < 64) { - ar->usedkeys &= ~BIT(key->hw_key_idx); - } else { - err = ar9170_upload_key(ar, key->hw_key_idx, NULL, - AR9170_ENC_ALG_NONE, 0, - NULL, 0); - if (err) - goto out; - - if (key->alg == ALG_TKIP) { - err = ar9170_upload_key(ar, key->hw_key_idx, - NULL, - AR9170_ENC_ALG_NONE, 1, - NULL, 0); - if (err) - goto out; - } - - } - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); - ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - -out: - mutex_unlock(&ar->mutex); - - return err; -} - -static void ar9170_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct ar9170 *ar = hw->priv; - struct ar9170_sta_info *info = (void *) sta->drv_priv; - struct sk_buff *skb; - unsigned int i; - - switch (cmd) { - case STA_NOTIFY_ADD: - for (i = 0; i < ar->hw->queues; i++) - skb_queue_head_init(&info->tx_status[i]); - break; - - case STA_NOTIFY_REMOVE: - - /* - * transfer all outstanding frames that need a tx_status - * reports to the global tx_status queue - */ - - for (i = 0; i < ar->hw->queues; i++) { - while ((skb = skb_dequeue(&info->tx_status[i]))) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: queueing frame in " - "global tx_status queue =>\n", - wiphy_name(ar->hw->wiphy)); - - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - skb_queue_tail(&ar->global_tx_status, skb); - } - } - queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, - msecs_to_jiffies(100)); - break; - - default: - break; - } -} - -static int ar9170_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ar9170 *ar = hw->priv; - u32 val; - int err; - - mutex_lock(&ar->mutex); - err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); - ar->stats.dot11ACKFailureCount += val; - - memcpy(stats, &ar->stats, sizeof(*stats)); - mutex_unlock(&ar->mutex); - - return 0; -} - -static int ar9170_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *tx_stats) -{ - struct ar9170 *ar = hw->priv; - - spin_lock_bh(&ar->tx_stats_lock); - memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); - spin_unlock_bh(&ar->tx_stats_lock); - - return 0; -} - -static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *param) -{ - struct ar9170 *ar = hw->priv; - int ret; - - mutex_lock(&ar->mutex); - if ((param) && !(queue > ar->hw->queues)) { - memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], - param, sizeof(*param)); - - ret = ar9170_set_qos(ar); - } else - ret = -EINVAL; - - mutex_unlock(&ar->mutex); - return ret; -} - -static const struct ieee80211_ops ar9170_ops = { - .start = ar9170_op_start, - .stop = ar9170_op_stop, - .tx = ar9170_op_tx, - .add_interface = ar9170_op_add_interface, - .remove_interface = ar9170_op_remove_interface, - .config = ar9170_op_config, - .config_interface = ar9170_op_config_interface, - .configure_filter = ar9170_op_configure_filter, - .conf_tx = ar9170_conf_tx, - .bss_info_changed = ar9170_op_bss_info_changed, - .get_tsf = ar9170_op_get_tsf, - .set_key = ar9170_set_key, - .sta_notify = ar9170_sta_notify, - .get_stats = ar9170_get_stats, - .get_tx_stats = ar9170_get_tx_stats, -}; - -void *ar9170_alloc(size_t priv_size) -{ - struct ieee80211_hw *hw; - struct ar9170 *ar; - int i; - - hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); - if (!hw) - return ERR_PTR(-ENOMEM); - - ar = hw->priv; - ar->hw = hw; - - mutex_init(&ar->mutex); - spin_lock_init(&ar->cmdlock); - spin_lock_init(&ar->tx_stats_lock); - skb_queue_head_init(&ar->global_tx_status); - skb_queue_head_init(&ar->global_tx_status_waste); - INIT_WORK(&ar->filter_config_work, ar9170_set_filters); - INIT_WORK(&ar->beacon_work, ar9170_new_beacon); - INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor); - - /* all hw supports 2.4 GHz, so set channel to 1 by default */ - ar->channel = &ar9170_2ghz_chantable[0]; - - /* first part of wiphy init */ - ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_WDS) | - BIT(NL80211_IFTYPE_ADHOC); - ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - ar->hw->queues = __AR9170_NUM_TXQ; - ar->hw->extra_tx_headroom = 8; - ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); - - ar->hw->max_rates = 1; - ar->hw->max_rate_tries = 3; - - for (i = 0; i < ARRAY_SIZE(ar->noise); i++) - ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ - - return ar; -} - -static int ar9170_read_eeprom(struct ar9170 *ar) -{ -#define RW 8 /* number of words to read at once */ -#define RB (sizeof(u32) * RW) - DECLARE_MAC_BUF(mbuf); - u8 *eeprom = (void *)&ar->eeprom; - u8 *addr = ar->eeprom.mac_address; - __le32 offsets[RW]; - int i, j, err, bands = 0; - - BUILD_BUG_ON(sizeof(ar->eeprom) & 3); - - BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); -#ifndef __CHECKER__ - /* don't want to handle trailing remains */ - BUILD_BUG_ON(sizeof(ar->eeprom) % RB); -#endif - - for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { - for (j = 0; j < RW; j++) - offsets[j] = cpu_to_le32(AR9170_EEPROM_START + - RB * i + 4 * j); - - err = ar->exec_cmd(ar, AR9170_CMD_RREG, - RB, (u8 *) &offsets, - RB, eeprom + RB * i); - if (err) - return err; - } - -#undef RW -#undef RB - - if (ar->eeprom.length == cpu_to_le16(0xFFFF)) - return -ENODATA; - - if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; - bands++; - } - if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; - bands++; - } - /* - * I measured this, a bandswitch takes roughly - * 135 ms and a frequency switch about 80. - * - * FIXME: measure these values again once EEPROM settings - * are used, that will influence them! - */ - if (bands == 2) - ar->hw->channel_change_time = 135 * 1000; - else - ar->hw->channel_change_time = 80 * 1000; - - ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); - ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); - - /* second part of wiphy init */ - SET_IEEE80211_PERM_ADDR(ar->hw, addr); - - return bands ? 0 : -EINVAL; -} - -static int ar9170_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ar9170 *ar = hw->priv; - - return ath_reg_notifier_apply(wiphy, request, &ar->regulatory); -} - -int ar9170_register(struct ar9170 *ar, struct device *pdev) -{ - int err; - - /* try to read EEPROM, init MAC addr */ - err = ar9170_read_eeprom(ar); - if (err) - goto err_out; - - err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, - ar9170_reg_notifier); - - err = ieee80211_register_hw(ar->hw); - if (err) - goto err_out; - - if (!ath_is_world_regd(&ar->regulatory)) - regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); - - err = ar9170_init_leds(ar); - if (err) - goto err_unreg; - -#ifdef CONFIG_AR9170_LEDS - err = ar9170_register_leds(ar); - if (err) - goto err_unreg; -#endif /* CONFIG_AR9170_LEDS */ - - dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", - wiphy_name(ar->hw->wiphy)); - - return err; - -err_unreg: - ieee80211_unregister_hw(ar->hw); - -err_out: - return err; -} - -void ar9170_unregister(struct ar9170 *ar) -{ -#ifdef CONFIG_AR9170_LEDS - ar9170_unregister_leds(ar); -#endif /* CONFIG_AR9170_LEDS */ - - ieee80211_unregister_hw(ar->hw); - mutex_destroy(&ar->mutex); -} diff --git a/drivers/net/wireless/ar9170/phy.c b/drivers/net/wireless/ar9170/phy.c deleted file mode 100644 index 6ce20754b8e7..000000000000 --- a/drivers/net/wireless/ar9170/phy.c +++ /dev/null @@ -1,1240 +0,0 @@ -/* - * Atheros AR9170 driver - * - * PHY and RF code - * - * Copyright 2008, Johannes Berg - * - * 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 -#include "ar9170.h" -#include "cmd.h" - -static int ar9170_init_power_cal(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); - ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -struct ar9170_phy_init { - u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; -}; - -static struct ar9170_phy_init ar5416_phy_init[] = { - { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, - { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, - { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, - { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, - { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, - { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, - { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, - { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, - { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, - { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, - { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, - { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, - { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, - { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, - { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, - { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, - { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, - { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, - { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, - { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, - { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, - { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, - { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, - { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, - { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, - { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, - { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, - { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, - { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, - { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, - { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, - { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, - { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, - { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, - { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, - { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, - { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, - { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, - { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, - { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, - { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, - { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, - { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, - { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, - { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, - { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, - { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, - { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, - { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, - { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, - { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, - { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, - { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, - { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, - { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, - { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, - { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, - { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, - { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, - { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, - { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, - { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, - { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, - { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, - { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, - { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, - { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, - { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, - { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, - { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, - { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, - { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, - { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, - { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, - { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, - { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, - { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, - { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, - { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, - { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, - { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, - { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, - { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, - { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, - { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, - { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, - { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, - { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, - { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, - { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, - { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, - { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, - { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, - { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, - { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, - { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, - { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, - { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, - { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, - { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, - { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, - { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, - { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, - { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, - { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, - { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, - { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, - { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, - { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, - { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, - { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, - { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, - { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, - { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, - { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, - { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, - { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, - { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, - { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, - { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, - { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, - { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, - { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, - { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, - { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, - { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, - { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, - { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, - { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, - { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, - { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, - { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, - { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, - { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, - { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, - { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, - { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, - { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, - { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, - { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, - { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, - { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, - { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, - { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, - { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, - { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, - { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, - { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, - { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, - { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, - { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, - { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, - { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, - { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, - { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, - { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, - { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, - { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, - { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, - { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, - { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, - { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, - { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, - { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, - { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, - { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, - { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, - { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, - { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, - { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, - { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, - { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, - { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, - { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, - { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, -/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ - { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, - { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, - { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, - { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, - { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, - { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, - { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, - { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, - { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, - { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, - { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, - { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, - { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, - { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, - { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, - { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } -}; - -int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) -{ - int i, err; - u32 val; - bool is_2ghz = band == IEEE80211_BAND_2GHZ; - bool is_40mhz = false; /* XXX: for now */ - - ar9170_regwrite_begin(ar); - - for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { - if (is_40mhz) { - if (is_2ghz) - val = ar5416_phy_init[i]._2ghz_40; - else - val = ar5416_phy_init[i]._5ghz_40; - } else { - if (is_2ghz) - val = ar5416_phy_init[i]._2ghz_20; - else - val = ar5416_phy_init[i]._5ghz_20; - } - - ar9170_regwrite(ar5416_phy_init[i].reg, val); - } - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - /* XXX: use EEPROM data here! */ - - err = ar9170_init_power_cal(ar); - if (err) - return err; - - /* XXX: remove magic! */ - if (is_2ghz) - err = ar9170_write_reg(ar, 0x1d4014, 0x5163); - else - err = ar9170_write_reg(ar, 0x1d4014, 0x5143); - - return err; -} - -struct ar9170_rf_init { - u32 reg, _5ghz, _2ghz; -}; - -static struct ar9170_rf_init ar9170_rf_init[] = { - /* bank 0 */ - { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, - { 0x1c58e0, 0x02008020, 0x02008020}, - /* bank 1 */ - { 0x1c58b0, 0x02108421, 0x02108421}, - { 0x1c58ec, 0x00000008, 0x00000008}, - /* bank 2 */ - { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, - { 0x1c58e0, 0x00000420, 0x00000420}, - /* bank 3 */ - { 0x1c58f0, 0x01400018, 0x01c00018}, - /* bank 4 */ - { 0x1c58b0, 0x000001a1, 0x000001a1}, - { 0x1c58e8, 0x00000001, 0x00000001}, - /* bank 5 */ - { 0x1c58b0, 0x00000013, 0x00000013}, - { 0x1c58e4, 0x00000002, 0x00000002}, - /* bank 6 */ - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00002c00, 0x00002c00}, - { 0x1c58b0, 0x00004800, 0x00004800}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00006000, 0x00006000}, - { 0x1c58b0, 0x00001000, 0x00001000}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00087c00, 0x00087c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00005400, 0x00005400}, - { 0x1c58b0, 0x00000c00, 0x00000c00}, - { 0x1c58b0, 0x00001800, 0x00001800}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00002c00, 0x00002c00}, - { 0x1c58b0, 0x00003c00, 0x00003c00}, - { 0x1c58b0, 0x00003800, 0x00003800}, - { 0x1c58b0, 0x00001c00, 0x00001c00}, - { 0x1c58b0, 0x00000800, 0x00000800}, - { 0x1c58b0, 0x00000408, 0x00000408}, - { 0x1c58b0, 0x00004c15, 0x00004c15}, - { 0x1c58b0, 0x00004188, 0x00004188}, - { 0x1c58b0, 0x0000201e, 0x0000201e}, - { 0x1c58b0, 0x00010408, 0x00010408}, - { 0x1c58b0, 0x00000801, 0x00000801}, - { 0x1c58b0, 0x00000c08, 0x00000c08}, - { 0x1c58b0, 0x0000181e, 0x0000181e}, - { 0x1c58b0, 0x00001016, 0x00001016}, - { 0x1c58b0, 0x00002800, 0x00002800}, - { 0x1c58b0, 0x00004010, 0x00004010}, - { 0x1c58b0, 0x0000081c, 0x0000081c}, - { 0x1c58b0, 0x00000115, 0x00000115}, - { 0x1c58b0, 0x00000015, 0x00000015}, - { 0x1c58b0, 0x00000066, 0x00000066}, - { 0x1c58b0, 0x0000001c, 0x0000001c}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000004, 0x00000004}, - { 0x1c58b0, 0x00000015, 0x00000015}, - { 0x1c58b0, 0x0000001f, 0x0000001f}, - { 0x1c58e0, 0x00000000, 0x00000400}, - /* bank 7 */ - { 0x1c58b0, 0x000000a0, 0x000000a0}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000040, 0x00000040}, - { 0x1c58f0, 0x0000001c, 0x0000001c}, -}; - -static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) -{ - int err, i; - - ar9170_regwrite_begin(ar); - - for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) - ar9170_regwrite(ar9170_rf_init[i].reg, - band5ghz ? ar9170_rf_init[i]._5ghz - : ar9170_rf_init[i]._2ghz); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - printk(KERN_ERR "%s: rf init failed\n", - wiphy_name(ar->hw->wiphy)); - return err; -} - -static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, - u32 freq, enum ar9170_bw bw) -{ - int err; - u32 d0, d1, td0, td1, fd0, fd1; - u8 chansel; - u8 refsel0 = 1, refsel1 = 0; - u8 lf_synth = 0; - - switch (bw) { - case AR9170_BW_40_ABOVE: - freq += 10; - break; - case AR9170_BW_40_BELOW: - freq -= 10; - break; - case AR9170_BW_20: - break; - case __AR9170_NUM_BW: - BUG(); - } - - if (band5ghz) { - if (freq % 10) { - chansel = (freq - 4800) / 5; - } else { - chansel = ((freq - 4800) / 10) * 2; - refsel0 = 0; - refsel1 = 1; - } - chansel = byte_rev_table[chansel]; - } else { - if (freq == 2484) { - chansel = 10 + (freq - 2274) / 5; - lf_synth = 1; - } else - chansel = 16 + (freq - 2272) / 5; - chansel *= 4; - chansel = byte_rev_table[chansel]; - } - - d1 = chansel; - d0 = 0x21 | - refsel0 << 3 | - refsel1 << 2 | - lf_synth << 1; - td0 = d0 & 0x1f; - td1 = d1 & 0x1f; - fd0 = td1 << 5 | td0; - - td0 = (d0 >> 5) & 0x7; - td1 = (d1 >> 5) & 0x7; - fd1 = td1 << 5 | td0; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(0x1c58b0, fd0); - ar9170_regwrite(0x1c58e8, fd1); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - msleep(10); - - return 0; -} - -struct ar9170_phy_freq_params { - u8 coeff_exp; - u16 coeff_man; - u8 coeff_exp_shgi; - u16 coeff_man_shgi; -}; - -struct ar9170_phy_freq_entry { - u16 freq; - struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; -}; - -/* NB: must be in sync with channel tables in main! */ -static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { -/* - * freq, - * 20MHz, - * 40MHz (below), - * 40Mhz (above), - */ - { 2412, { - { 3, 21737, 3, 19563, }, - { 3, 21827, 3, 19644, }, - { 3, 21647, 3, 19482, }, - } }, - { 2417, { - { 3, 21692, 3, 19523, }, - { 3, 21782, 3, 19604, }, - { 3, 21602, 3, 19442, }, - } }, - { 2422, { - { 3, 21647, 3, 19482, }, - { 3, 21737, 3, 19563, }, - { 3, 21558, 3, 19402, }, - } }, - { 2427, { - { 3, 21602, 3, 19442, }, - { 3, 21692, 3, 19523, }, - { 3, 21514, 3, 19362, }, - } }, - { 2432, { - { 3, 21558, 3, 19402, }, - { 3, 21647, 3, 19482, }, - { 3, 21470, 3, 19323, }, - } }, - { 2437, { - { 3, 21514, 3, 19362, }, - { 3, 21602, 3, 19442, }, - { 3, 21426, 3, 19283, }, - } }, - { 2442, { - { 3, 21470, 3, 19323, }, - { 3, 21558, 3, 19402, }, - { 3, 21382, 3, 19244, }, - } }, - { 2447, { - { 3, 21426, 3, 19283, }, - { 3, 21514, 3, 19362, }, - { 3, 21339, 3, 19205, }, - } }, - { 2452, { - { 3, 21382, 3, 19244, }, - { 3, 21470, 3, 19323, }, - { 3, 21295, 3, 19166, }, - } }, - { 2457, { - { 3, 21339, 3, 19205, }, - { 3, 21426, 3, 19283, }, - { 3, 21252, 3, 19127, }, - } }, - { 2462, { - { 3, 21295, 3, 19166, }, - { 3, 21382, 3, 19244, }, - { 3, 21209, 3, 19088, }, - } }, - { 2467, { - { 3, 21252, 3, 19127, }, - { 3, 21339, 3, 19205, }, - { 3, 21166, 3, 19050, }, - } }, - { 2472, { - { 3, 21209, 3, 19088, }, - { 3, 21295, 3, 19166, }, - { 3, 21124, 3, 19011, }, - } }, - { 2484, { - { 3, 21107, 3, 18996, }, - { 3, 21192, 3, 19073, }, - { 3, 21022, 3, 18920, }, - } }, - { 4920, { - { 4, 21313, 4, 19181, }, - { 4, 21356, 4, 19220, }, - { 4, 21269, 4, 19142, }, - } }, - { 4940, { - { 4, 21226, 4, 19104, }, - { 4, 21269, 4, 19142, }, - { 4, 21183, 4, 19065, }, - } }, - { 4960, { - { 4, 21141, 4, 19027, }, - { 4, 21183, 4, 19065, }, - { 4, 21098, 4, 18988, }, - } }, - { 4980, { - { 4, 21056, 4, 18950, }, - { 4, 21098, 4, 18988, }, - { 4, 21014, 4, 18912, }, - } }, - { 5040, { - { 4, 20805, 4, 18725, }, - { 4, 20846, 4, 18762, }, - { 4, 20764, 4, 18687, }, - } }, - { 5060, { - { 4, 20723, 4, 18651, }, - { 4, 20764, 4, 18687, }, - { 4, 20682, 4, 18614, }, - } }, - { 5080, { - { 4, 20641, 4, 18577, }, - { 4, 20682, 4, 18614, }, - { 4, 20601, 4, 18541, }, - } }, - { 5180, { - { 4, 20243, 4, 18219, }, - { 4, 20282, 4, 18254, }, - { 4, 20204, 4, 18183, }, - } }, - { 5200, { - { 4, 20165, 4, 18148, }, - { 4, 20204, 4, 18183, }, - { 4, 20126, 4, 18114, }, - } }, - { 5220, { - { 4, 20088, 4, 18079, }, - { 4, 20126, 4, 18114, }, - { 4, 20049, 4, 18044, }, - } }, - { 5240, { - { 4, 20011, 4, 18010, }, - { 4, 20049, 4, 18044, }, - { 4, 19973, 4, 17976, }, - } }, - { 5260, { - { 4, 19935, 4, 17941, }, - { 4, 19973, 4, 17976, }, - { 4, 19897, 4, 17907, }, - } }, - { 5280, { - { 4, 19859, 4, 17873, }, - { 4, 19897, 4, 17907, }, - { 4, 19822, 4, 17840, }, - } }, - { 5300, { - { 4, 19784, 4, 17806, }, - { 4, 19822, 4, 17840, }, - { 4, 19747, 4, 17772, }, - } }, - { 5320, { - { 4, 19710, 4, 17739, }, - { 4, 19747, 4, 17772, }, - { 4, 19673, 4, 17706, }, - } }, - { 5500, { - { 4, 19065, 4, 17159, }, - { 4, 19100, 4, 17190, }, - { 4, 19030, 4, 17127, }, - } }, - { 5520, { - { 4, 18996, 4, 17096, }, - { 4, 19030, 4, 17127, }, - { 4, 18962, 4, 17065, }, - } }, - { 5540, { - { 4, 18927, 4, 17035, }, - { 4, 18962, 4, 17065, }, - { 4, 18893, 4, 17004, }, - } }, - { 5560, { - { 4, 18859, 4, 16973, }, - { 4, 18893, 4, 17004, }, - { 4, 18825, 4, 16943, }, - } }, - { 5580, { - { 4, 18792, 4, 16913, }, - { 4, 18825, 4, 16943, }, - { 4, 18758, 4, 16882, }, - } }, - { 5600, { - { 4, 18725, 4, 16852, }, - { 4, 18758, 4, 16882, }, - { 4, 18691, 4, 16822, }, - } }, - { 5620, { - { 4, 18658, 4, 16792, }, - { 4, 18691, 4, 16822, }, - { 4, 18625, 4, 16762, }, - } }, - { 5640, { - { 4, 18592, 4, 16733, }, - { 4, 18625, 4, 16762, }, - { 4, 18559, 4, 16703, }, - } }, - { 5660, { - { 4, 18526, 4, 16673, }, - { 4, 18559, 4, 16703, }, - { 4, 18493, 4, 16644, }, - } }, - { 5680, { - { 4, 18461, 4, 16615, }, - { 4, 18493, 4, 16644, }, - { 4, 18428, 4, 16586, }, - } }, - { 5700, { - { 4, 18396, 4, 16556, }, - { 4, 18428, 4, 16586, }, - { 4, 18364, 4, 16527, }, - } }, - { 5745, { - { 4, 18252, 4, 16427, }, - { 4, 18284, 4, 16455, }, - { 4, 18220, 4, 16398, }, - } }, - { 5765, { - { 4, 18189, 5, 32740, }, - { 4, 18220, 4, 16398, }, - { 4, 18157, 5, 32683, }, - } }, - { 5785, { - { 4, 18126, 5, 32626, }, - { 4, 18157, 5, 32683, }, - { 4, 18094, 5, 32570, }, - } }, - { 5805, { - { 4, 18063, 5, 32514, }, - { 4, 18094, 5, 32570, }, - { 4, 18032, 5, 32458, }, - } }, - { 5825, { - { 4, 18001, 5, 32402, }, - { 4, 18032, 5, 32458, }, - { 4, 17970, 5, 32347, }, - } }, - { 5170, { - { 4, 20282, 4, 18254, }, - { 4, 20321, 4, 18289, }, - { 4, 20243, 4, 18219, }, - } }, - { 5190, { - { 4, 20204, 4, 18183, }, - { 4, 20243, 4, 18219, }, - { 4, 20165, 4, 18148, }, - } }, - { 5210, { - { 4, 20126, 4, 18114, }, - { 4, 20165, 4, 18148, }, - { 4, 20088, 4, 18079, }, - } }, - { 5230, { - { 4, 20049, 4, 18044, }, - { 4, 20088, 4, 18079, }, - { 4, 20011, 4, 18010, }, - } }, -}; - -static const struct ar9170_phy_freq_params * -ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, - enum ar9170_bw bw) -{ - unsigned int chanidx = 0; - u16 freq = 2412; - - if (channel) { - chanidx = channel->hw_value; - freq = channel->center_freq; - } - - BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); - - BUILD_BUG_ON(__AR9170_NUM_BW != 3); - - WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); - - return &ar9170_phy_freq_params[chanidx].params[bw]; -} - - -int ar9170_init_rf(struct ar9170 *ar) -{ - const struct ar9170_phy_freq_params *freqpar; - __le32 cmd[7]; - int err; - - err = ar9170_init_rf_banks_0_7(ar, false); - if (err) - return err; - - err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); - if (err) - return err; - - freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); - - cmd[0] = cpu_to_le32(2412 * 1000); - cmd[1] = cpu_to_le32(0); - cmd[2] = cpu_to_le32(1); - cmd[3] = cpu_to_le32(freqpar->coeff_exp); - cmd[4] = cpu_to_le32(freqpar->coeff_man); - cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); - cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); - - /* RF_INIT echoes the command back to us */ - err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, - sizeof(cmd), (u8 *)cmd, - sizeof(cmd), (u8 *)cmd); - if (err) - return err; - - msleep(1000); - - return ar9170_echo_test(ar, 0xaabbccdd); -} - -static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) -{ - int idx = nfreqs - 2; - - while (idx >= 0) { - if (f >= freqs[idx]) - return idx; - idx--; - } - - return 0; -} - -static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) -{ - /* nothing to interpolate, it's horizontal */ - if (y2 == y1) - return y1; - - /* check if we hit one of the edges */ - if (x == x1) - return y1; - if (x == x2) - return y2; - - /* x1 == x2 is bad, hopefully == x */ - if (x2 == x1) - return y1; - - return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); -} - -static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) -{ -#define SHIFT 8 - s32 y; - - y = ar9170_interpolate_s32(x << SHIFT, - x1 << SHIFT, y1 << SHIFT, - x2 << SHIFT, y2 << SHIFT); - - /* - * XXX: unwrap this expression - * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); -#undef SHIFT -} - -static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) -{ - struct ar9170_calibration_target_power_legacy *ctpl; - struct ar9170_calibration_target_power_ht *ctph; - u8 *ctpres; - int ntargets; - int idx, i, n; - u8 ackpower, ackchains, f; - u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; - - if (freq < 3000) - f = freq - 2300; - else - f = (freq - 4800)/5; - - /* - * cycle through the various modes - * - * legacy modes first: 5G, 2G CCK, 2G OFDM - */ - for (i = 0; i < 3; i++) { - switch (i) { - case 0: /* 5 GHz legacy */ - ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_leg; - break; - case 1: /* 2.4 GHz CCK */ - ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; - ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; - ctpres = ar->power_2G_cck; - break; - case 2: /* 2.4 GHz OFDM */ - ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ofdm; - break; - default: - BUG(); - } - - for (n = 0; n < ntargets; n++) { - if (ctpl[n].freq == 0xff) - break; - pwr_freqs[n] = ctpl[n].freq; - } - ntargets = n; - idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); - for (n = 0; n < 4; n++) - ctpres[n] = ar9170_interpolate_u8( - f, - ctpl[idx + 0].freq, - ctpl[idx + 0].power[n], - ctpl[idx + 1].freq, - ctpl[idx + 1].power[n]); - } - - /* - * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 - */ - for (i = 0; i < 4; i++) { - switch (i) { - case 0: /* 5 GHz HT 20 */ - ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_ht20; - break; - case 1: /* 5 GHz HT 40 */ - ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_ht40; - break; - case 2: /* 2.4 GHz HT 20 */ - ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ht20; - break; - case 3: /* 2.4 GHz HT 40 */ - ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ht40; - break; - default: - BUG(); - } - - for (n = 0; n < ntargets; n++) { - if (ctph[n].freq == 0xff) - break; - pwr_freqs[n] = ctph[n].freq; - } - ntargets = n; - idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); - for (n = 0; n < 8; n++) - ctpres[n] = ar9170_interpolate_u8( - f, - ctph[idx + 0].freq, - ctph[idx + 0].power[n], - ctph[idx + 1].freq, - ctph[idx + 1].power[n]); - } - - /* set ACK/CTS TX power */ - ar9170_regwrite_begin(ar); - - if (ar->eeprom.tx_mask != 1) - ackchains = AR9170_TX_PHY_TXCHAIN_2; - else - ackchains = AR9170_TX_PHY_TXCHAIN_1; - - if (freq < 3000) - ackpower = ar->power_2G_ofdm[0] & 0x3f; - else - ackpower = ar->power_5G_leg[0] & 0x3f; - - ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); - ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | - ackpower << 21 | ackchains << 27); - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -static int ar9170_calc_noise_dbm(u32 raw_noise) -{ - if (raw_noise & 0x100) - return ~((raw_noise & 0x0ff) >> 1); - else - return (raw_noise & 0xff) >> 1; -} - -int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) -{ - const struct ar9170_phy_freq_params *freqpar; - u32 cmd, tmp, offs; - __le32 vals[8]; - int i, err; - bool bandswitch; - - /* clear BB heavy clip enable */ - err = ar9170_write_reg(ar, 0x1c59e0, 0x200); - if (err) - return err; - - /* may be NULL at first setup */ - if (ar->channel) - bandswitch = ar->channel->band != channel->band; - else - bandswitch = true; - - /* HW workaround */ - if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && - channel->center_freq <= 2417) - bandswitch = true; - - err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); - if (err) - return err; - - if (rfi != AR9170_RFI_NONE || bandswitch) { - u32 val = 0x400; - - if (rfi == AR9170_RFI_COLD) - val = 0x800; - - /* warm/cold reset BB/ADDA */ - err = ar9170_write_reg(ar, 0x1d4004, val); - if (err) - return err; - - err = ar9170_write_reg(ar, 0x1d4004, 0x0); - if (err) - return err; - - err = ar9170_init_phy(ar, channel->band); - if (err) - return err; - - err = ar9170_init_rf_banks_0_7(ar, - channel->band == IEEE80211_BAND_5GHZ); - if (err) - return err; - - cmd = AR9170_CMD_RF_INIT; - } else { - cmd = AR9170_CMD_FREQUENCY; - } - - err = ar9170_init_rf_bank4_pwr(ar, - channel->band == IEEE80211_BAND_5GHZ, - channel->center_freq, bw); - if (err) - return err; - - switch (bw) { - case AR9170_BW_20: - tmp = 0x240; - offs = 0; - break; - case AR9170_BW_40_BELOW: - tmp = 0x2c4; - offs = 3; - break; - case AR9170_BW_40_ABOVE: - tmp = 0x2d4; - offs = 1; - break; - default: - BUG(); - return -ENOSYS; - } - - if (0 /* 2 streams capable */) - tmp |= 0x100; - - err = ar9170_write_reg(ar, 0x1c5804, tmp); - if (err) - return err; - - err = ar9170_set_power_cal(ar, channel->center_freq, bw); - if (err) - return err; - - freqpar = ar9170_get_hw_dyn_params(channel, bw); - - vals[0] = cpu_to_le32(channel->center_freq * 1000); - vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1); - vals[2] = cpu_to_le32(offs << 2 | 1); - vals[3] = cpu_to_le32(freqpar->coeff_exp); - vals[4] = cpu_to_le32(freqpar->coeff_man); - vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); - vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); - vals[7] = cpu_to_le32(1000); - - err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, - sizeof(vals), (u8 *)vals); - if (err) - return err; - - for (i = 0; i < 2; i++) { - ar->noise[i] = ar9170_calc_noise_dbm( - (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); - - ar->noise[i + 2] = ar9170_calc_noise_dbm( - (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); - } - - ar->channel = channel; - return 0; -} diff --git a/drivers/net/wireless/ar9170/usb.c b/drivers/net/wireless/ar9170/usb.c deleted file mode 100644 index fddda477095c..000000000000 --- a/drivers/net/wireless/ar9170/usb.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Atheros AR9170 driver - * - * USB - frontend - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * 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 -#include -#include -#include -#include -#include "ar9170.h" -#include "cmd.h" -#include "hw.h" -#include "usb.h" - -MODULE_AUTHOR("Johannes Berg "); -MODULE_AUTHOR("Christian Lamparter "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); -MODULE_FIRMWARE("ar9170-1.fw"); -MODULE_FIRMWARE("ar9170-2.fw"); - -static struct usb_device_id ar9170_usb_ids[] = { - /* Atheros 9170 */ - { USB_DEVICE(0x0cf3, 0x9170) }, - /* Atheros TG121N */ - { USB_DEVICE(0x0cf3, 0x1001) }, - /* Cace Airpcap NX */ - { USB_DEVICE(0xcace, 0x0300) }, - /* D-Link DWA 160A */ - { USB_DEVICE(0x07d1, 0x3c10) }, - /* Netgear WNDA3100 */ - { USB_DEVICE(0x0846, 0x9010) }, - /* Netgear WN111 v2 */ - { USB_DEVICE(0x0846, 0x9001) }, - /* Zydas ZD1221 */ - { USB_DEVICE(0x0ace, 0x1221) }, - /* ZyXEL NWD271N */ - { USB_DEVICE(0x0586, 0x3417) }, - /* Z-Com UB81 BG */ - { USB_DEVICE(0x0cde, 0x0023) }, - /* Z-Com UB82 ABG */ - { USB_DEVICE(0x0cde, 0x0026) }, - /* Arcadyan WN7512 */ - { USB_DEVICE(0x083a, 0xf522) }, - /* Planex GWUS300 */ - { USB_DEVICE(0x2019, 0x5304) }, - /* IO-Data WNGDNUS2 */ - { USB_DEVICE(0x04bb, 0x093f) }, - - /* terminate */ - {} -}; -MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); - -static void ar9170_usb_tx_urb_complete_free(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - - if (!aru) { - dev_kfree_skb_irq(skb); - return ; - } - - ar9170_handle_tx_status(&aru->common, skb, false, - AR9170_TX_STATUS_COMPLETE); -} - -static void ar9170_usb_tx_urb_complete(struct urb *urb) -{ -} - -static void ar9170_usb_irq_completed(struct urb *urb) -{ - struct ar9170_usb *aru = urb->context; - - switch (urb->status) { - /* everything is fine */ - case 0: - break; - - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - - default: - goto resubmit; - } - - print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET, - urb->transfer_buffer, urb->actual_length); - -resubmit: - usb_anchor_urb(urb, &aru->rx_submitted); - if (usb_submit_urb(urb, GFP_ATOMIC)) { - usb_unanchor_urb(urb); - goto free; - } - - return; - -free: - usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); -} - -static void ar9170_usb_rx_completed(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - int err; - - if (!aru) - goto free; - - switch (urb->status) { - /* everything is fine */ - case 0: - break; - - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - - default: - goto resubmit; - } - - skb_put(skb, urb->actual_length); - ar9170_rx(&aru->common, skb); - -resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) { - usb_unanchor_urb(urb); - dev_kfree_skb_irq(skb); - } - - return ; - -free: - dev_kfree_skb_irq(skb); - return; -} - -static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, - struct urb *urb, gfp_t gfp) -{ - struct sk_buff *skb; - - skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); - if (!skb) - return -ENOMEM; - - /* reserve some space for mac80211's radiotap */ - skb_reserve(skb, 32); - - usb_fill_bulk_urb(urb, aru->udev, - usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), - skb->data, min(skb_tailroom(skb), - AR9170_MAX_RX_BUFFER_SIZE), - ar9170_usb_rx_completed, skb); - - return 0; -} - -static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) -{ - struct urb *urb = NULL; - void *ibuf; - int err = -ENOMEM; - - /* initialize interrupt endpoint */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto out; - - ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); - if (!ibuf) - goto out; - - usb_fill_int_urb(urb, aru->udev, - usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, - 64, ar9170_usb_irq_completed, aru, 1); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - usb_unanchor_urb(urb); - usb_buffer_free(aru->udev, 64, urb->transfer_buffer, - urb->transfer_dma); - } - -out: - usb_free_urb(urb); - return err; -} - -static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) -{ - struct urb *urb; - int i; - int err = -EINVAL; - - for (i = 0; i < AR9170_NUM_RX_URBS; i++) { - err = -ENOMEM; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto err_out; - - err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); - if (err) { - usb_free_urb(urb); - goto err_out; - } - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - usb_unanchor_urb(urb); - dev_kfree_skb_any((void *) urb->transfer_buffer); - usb_free_urb(urb); - goto err_out; - } - usb_free_urb(urb); - } - - /* the device now waiting for a firmware. */ - aru->common.state = AR9170_IDLE; - return 0; - -err_out: - - usb_kill_anchored_urbs(&aru->rx_submitted); - return err; -} - -static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) -{ - int ret; - - aru->common.state = AR9170_UNKNOWN_STATE; - - usb_unlink_anchored_urbs(&aru->tx_submitted); - - /* give the LED OFF command and the deauth frame a chance to air. */ - ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, - msecs_to_jiffies(100)); - if (ret == 0) - dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); - usb_poison_anchored_urbs(&aru->tx_submitted); - - usb_poison_anchored_urbs(&aru->rx_submitted); -} - -static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, - unsigned int plen, void *payload, - unsigned int outlen, void *out) -{ - struct ar9170_usb *aru = (void *) ar; - struct urb *urb = NULL; - unsigned long flags; - int err = -ENOMEM; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return -EPERM; - - if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) - return -EINVAL; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (unlikely(!urb)) - goto err_free; - - ar->cmdbuf[0] = cpu_to_le32(plen); - ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); - /* writing multiple regs fills this buffer already */ - if (plen && payload != (u8 *)(&ar->cmdbuf[1])) - memcpy(&ar->cmdbuf[1], payload, plen); - - spin_lock_irqsave(&aru->common.cmdlock, flags); - aru->readbuf = (u8 *)out; - aru->readlen = outlen; - spin_unlock_irqrestore(&aru->common.cmdlock, flags); - - usb_fill_int_urb(urb, aru->udev, - usb_sndbulkpipe(aru->udev, AR9170_EP_CMD), - aru->common.cmdbuf, plen + 4, - ar9170_usb_tx_urb_complete, NULL, 1); - - usb_anchor_urb(urb, &aru->tx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) { - usb_unanchor_urb(urb); - usb_free_urb(urb); - goto err_unbuf; - } - usb_free_urb(urb); - - err = wait_for_completion_timeout(&aru->cmd_wait, HZ); - if (err == 0) { - err = -ETIMEDOUT; - goto err_unbuf; - } - - if (outlen >= 0 && aru->readlen != outlen) { - err = -EMSGSIZE; - goto err_unbuf; - } - - return 0; - -err_unbuf: - /* Maybe the device was removed in the second we were waiting? */ - if (IS_STARTED(ar)) { - dev_err(&aru->udev->dev, "no command feedback " - "received (%d).\n", err); - - /* provide some maybe useful debug information */ - print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, - aru->common.cmdbuf, plen + 4); - dump_stack(); - } - - /* invalidate to avoid completing the next prematurely */ - spin_lock_irqsave(&aru->common.cmdlock, flags); - aru->readbuf = NULL; - aru->readlen = 0; - spin_unlock_irqrestore(&aru->common.cmdlock, flags); - -err_free: - - return err; -} - -static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, - bool txstatus_needed, unsigned int extra_len) -{ - struct ar9170_usb *aru = (struct ar9170_usb *) ar; - struct urb *urb; - int err; - - if (unlikely(!IS_STARTED(ar))) { - /* Seriously, what were you drink... err... thinking!? */ - return -EPERM; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (unlikely(!urb)) - return -ENOMEM; - - usb_fill_bulk_urb(urb, aru->udev, - usb_sndbulkpipe(aru->udev, AR9170_EP_TX), - skb->data, skb->len + extra_len, (txstatus_needed ? - ar9170_usb_tx_urb_complete : - ar9170_usb_tx_urb_complete_free), skb); - urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(urb, &aru->tx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) - usb_unanchor_urb(urb); - - usb_free_urb(urb); - return err; -} - -static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) -{ - struct ar9170_usb *aru = (void *) ar; - unsigned long flags; - u32 in, out; - - if (!buffer) - return ; - - in = le32_to_cpup((__le32 *)buffer); - out = le32_to_cpu(ar->cmdbuf[0]); - - /* mask off length byte */ - out &= ~0xFF; - - if (aru->readlen >= 0) { - /* add expected length */ - out |= aru->readlen; - } else { - /* add obtained length */ - out |= in & 0xFF; - } - - /* - * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response - * length and we cannot predict the correct length in advance. - * So we only check if we provided enough space for the data. - */ - if (unlikely(out < in)) { - dev_warn(&aru->udev->dev, "received invalid command response " - "got %d bytes, instead of %d bytes " - "and the resp length is %d bytes\n", - in, out, len); - print_hex_dump_bytes("ar9170 invalid resp: ", - DUMP_PREFIX_OFFSET, buffer, len); - /* - * Do not complete, then the command times out, - * and we get a stack trace from there. - */ - return ; - } - - spin_lock_irqsave(&aru->common.cmdlock, flags); - if (aru->readbuf && len > 0) { - memcpy(aru->readbuf, buffer + 4, len - 4); - aru->readbuf = NULL; - } - complete(&aru->cmd_wait); - spin_unlock_irqrestore(&aru->common.cmdlock, flags); -} - -static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, - size_t len, u32 addr, bool complete) -{ - int transfer, err; - u8 *buf = kmalloc(4096, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - while (len) { - transfer = min_t(int, len, 4096); - memcpy(buf, data, transfer); - - err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), - 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, - addr >> 8, 0, buf, transfer, 1000); - - if (err < 0) { - kfree(buf); - return err; - } - - len -= transfer; - data += transfer; - addr += transfer; - } - kfree(buf); - - if (complete) { - err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), - 0x31 /* FW DL COMPLETE */, - 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); - } - - return 0; -} - -static int ar9170_usb_request_firmware(struct ar9170_usb *aru) -{ - int err = 0; - - err = request_firmware(&aru->init_values, "ar9170-1.fw", - &aru->udev->dev); - if (err) { - dev_err(&aru->udev->dev, "file with init values not found.\n"); - return err; - } - - err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); - if (err) { - release_firmware(aru->init_values); - dev_err(&aru->udev->dev, "firmware file not found.\n"); - return err; - } - - return err; -} - -static int ar9170_usb_reset(struct ar9170_usb *aru) -{ - int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); - - if (lock) { - ret = usb_lock_device_for_reset(aru->udev, aru->intf); - if (ret < 0) { - dev_err(&aru->udev->dev, "unable to lock device " - "for reset (%d).\n", ret); - return ret; - } - } - - ret = usb_reset_device(aru->udev); - if (lock) - usb_unlock_device(aru->udev); - - /* let it rest - for a second - */ - msleep(1000); - - return ret; -} - -static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) -{ - int err; - - /* First, upload initial values to device RAM */ - err = ar9170_usb_upload(aru, aru->init_values->data, - aru->init_values->size, 0x102800, false); - if (err) { - dev_err(&aru->udev->dev, "firmware part 1 " - "upload failed (%d).\n", err); - return err; - } - - /* Then, upload the firmware itself and start it */ - return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, - 0x200000, true); -} - -static int ar9170_usb_init_transport(struct ar9170_usb *aru) -{ - struct ar9170 *ar = (void *) &aru->common; - int err; - - ar9170_regwrite_begin(ar); - - /* Set USB Rx stream mode MAX packet number to 2 */ - ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); - - /* Set USB Rx stream mode timeout to 10us */ - ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); - - ar9170_regwrite_finish(); - - err = ar9170_regwrite_result(); - if (err) - dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); - - return err; -} - -static void ar9170_usb_stop(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - int ret; - - if (IS_ACCEPTING_CMD(ar)) - aru->common.state = AR9170_STOPPED; - - /* lets wait a while until the tx - queues are dried out */ - ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, - msecs_to_jiffies(1000)); - if (ret == 0) - dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); - - usb_poison_anchored_urbs(&aru->tx_submitted); - - /* - * Note: - * So far we freed all tx urbs, but we won't dare to touch any rx urbs. - * Else we would end up with a unresponsive device... - */ -} - -static int ar9170_usb_open(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - int err; - - usb_unpoison_anchored_urbs(&aru->tx_submitted); - err = ar9170_usb_init_transport(aru); - if (err) { - usb_poison_anchored_urbs(&aru->tx_submitted); - return err; - } - - aru->common.state = AR9170_IDLE; - return 0; -} - -static int ar9170_usb_init_device(struct ar9170_usb *aru) -{ - int err; - - err = ar9170_usb_alloc_rx_irq_urb(aru); - if (err) - goto err_out; - - err = ar9170_usb_alloc_rx_bulk_urbs(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_upload_firmware(aru); - if (err) { - err = ar9170_echo_test(&aru->common, 0x60d43110); - if (err) { - /* force user invention, by disabling the device */ - err = usb_driver_set_configuration(aru->udev, -1); - dev_err(&aru->udev->dev, "device is in a bad state. " - "please reconnect it!\n"); - goto err_unrx; - } - } - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_out: - return err; -} - -static int ar9170_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct ar9170_usb *aru; - struct ar9170 *ar; - struct usb_device *udev; - int err; - - aru = ar9170_alloc(sizeof(*aru)); - if (IS_ERR(aru)) { - err = PTR_ERR(aru); - goto out; - } - - udev = interface_to_usbdev(intf); - usb_get_dev(udev); - aru->udev = udev; - aru->intf = intf; - ar = &aru->common; - - usb_set_intfdata(intf, aru); - SET_IEEE80211_DEV(ar->hw, &udev->dev); - - init_usb_anchor(&aru->rx_submitted); - init_usb_anchor(&aru->tx_submitted); - init_completion(&aru->cmd_wait); - - aru->common.stop = ar9170_usb_stop; - aru->common.open = ar9170_usb_open; - aru->common.tx = ar9170_usb_tx; - aru->common.exec_cmd = ar9170_usb_exec_cmd; - aru->common.callback_cmd = ar9170_usb_callback_cmd; - - err = ar9170_usb_reset(aru); - if (err) - goto err_freehw; - - err = ar9170_usb_request_firmware(aru); - if (err) - goto err_freehw; - - err = ar9170_usb_init_device(aru); - if (err) - goto err_freefw; - - err = ar9170_usb_open(ar); - if (err) - goto err_unrx; - - err = ar9170_register(ar, &udev->dev); - - ar9170_usb_stop(ar); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_freefw: - release_firmware(aru->init_values); - release_firmware(aru->firmware); - -err_freehw: - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - ieee80211_free_hw(ar->hw); -out: - return err; -} - -static void ar9170_usb_disconnect(struct usb_interface *intf) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - - if (!aru) - return; - - aru->common.state = AR9170_IDLE; - ar9170_unregister(&aru->common); - ar9170_usb_cancel_urbs(aru); - - release_firmware(aru->init_values); - release_firmware(aru->firmware); - - usb_put_dev(aru->udev); - usb_set_intfdata(intf, NULL); - ieee80211_free_hw(aru->common.hw); -} - -#ifdef CONFIG_PM -static int ar9170_suspend(struct usb_interface *intf, - pm_message_t message) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - - if (!aru) - return -ENODEV; - - aru->common.state = AR9170_IDLE; - ar9170_usb_cancel_urbs(aru); - - return 0; -} - -static int ar9170_resume(struct usb_interface *intf) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - int err; - - if (!aru) - return -ENODEV; - - usb_unpoison_anchored_urbs(&aru->rx_submitted); - usb_unpoison_anchored_urbs(&aru->tx_submitted); - - /* - * FIXME: firmware upload will fail on resume. - * but this is better than a hang! - */ - - err = ar9170_usb_init_device(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_open(&aru->common); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - aru->common.state = AR9170_IDLE; - ar9170_usb_cancel_urbs(aru); - - return err; -} -#endif /* CONFIG_PM */ - -static struct usb_driver ar9170_driver = { - .name = "ar9170usb", - .probe = ar9170_usb_probe, - .disconnect = ar9170_usb_disconnect, - .id_table = ar9170_usb_ids, - .soft_unbind = 1, -#ifdef CONFIG_PM - .suspend = ar9170_suspend, - .resume = ar9170_resume, -#endif /* CONFIG_PM */ -}; - -static int __init ar9170_init(void) -{ - return usb_register(&ar9170_driver); -} - -static void __exit ar9170_exit(void) -{ - usb_deregister(&ar9170_driver); -} - -module_init(ar9170_init); -module_exit(ar9170_exit); diff --git a/drivers/net/wireless/ar9170/usb.h b/drivers/net/wireless/ar9170/usb.h deleted file mode 100644 index f5852924cd64..000000000000 --- a/drivers/net/wireless/ar9170/usb.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Atheros AR9170 USB driver - * - * Driver specific definitions - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * 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 __USB_H -#define __USB_H - -#include -#include -#include -#include -#include -#include -#include -#include "eeprom.h" -#include "hw.h" -#include "ar9170.h" - -#define AR9170_NUM_RX_URBS 16 - -struct firmware; - -struct ar9170_usb { - struct ar9170 common; - struct usb_device *udev; - struct usb_interface *intf; - - struct usb_anchor rx_submitted; - struct usb_anchor tx_submitted; - - spinlock_t cmdlock; - struct completion cmd_wait; - int readlen; - u8 *readbuf; - - const struct firmware *init_values; - const struct firmware *firmware; -}; - -#endif /* __USB_H */ diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 76517a45a212..d26e7b485315 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -1,4 +1,8 @@ config ATH_COMMON - tristate "Atheros Wireless Cards Shared Support" + tristate "Atheros Wireless Cards" depends on ATH5K || ATH9K || AR9170_USB +source "drivers/net/wireless/ath/ath5k/Kconfig" +source "drivers/net/wireless/ath/ath9k/Kconfig" +source "drivers/net/wireless/ath/ar9170/Kconfig" + diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index bc77646f90ad..a005b919233f 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -1,3 +1,7 @@ +obj-$(CONFIG_ATH5K) += ath5k/ +obj-$(CONFIG_ATH9K) += ath9k/ +obj-$(CONFIG_AR9170_USB) += ar9170/ + obj-$(CONFIG_ATH_COMMON) += ath.o ath-objs := regd.o diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig new file mode 100644 index 000000000000..b99e3263ee6d --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/Kconfig @@ -0,0 +1,18 @@ +config AR9170_USB + tristate "Atheros AR9170 802.11n USB support" + depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL + select FW_LOADER + select ATH_COMMON + help + This is a driver for the Atheros "otus" 802.11n USB devices. + + These devices require additional firmware (2 files). + For now, these files can be downloaded from here: + http://wireless.kernel.org/en/users/Drivers/ar9170 + + If you choose to build a module, it'll be called ar9170usb. + +config AR9170_LEDS + bool + depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) + default y diff --git a/drivers/net/wireless/ath/ar9170/Makefile b/drivers/net/wireless/ath/ar9170/Makefile new file mode 100644 index 000000000000..8d91c7ee3215 --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/Makefile @@ -0,0 +1,3 @@ +ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o + +obj-$(CONFIG_AR9170_USB) += ar9170usb.o diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h new file mode 100644 index 000000000000..f797495faa56 --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -0,0 +1,212 @@ +/* + * Atheros AR9170 driver + * + * Driver specific definitions + * + * Copyright 2008, Johannes Berg + * + * 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 __AR9170_H +#define __AR9170_H + +#include +#include +#include +#include +#ifdef CONFIG_AR9170_LEDS +#include +#endif /* CONFIG_AR9170_LEDS */ +#include "eeprom.h" +#include "hw.h" + +#include "../regd.h" + +#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) + +enum ar9170_bw { + AR9170_BW_20, + AR9170_BW_40_BELOW, + AR9170_BW_40_ABOVE, + + __AR9170_NUM_BW, +}; + +enum ar9170_rf_init_mode { + AR9170_RFI_NONE, + AR9170_RFI_WARM, + AR9170_RFI_COLD, +}; + +#define AR9170_MAX_RX_BUFFER_SIZE 8192 + +#ifdef CONFIG_AR9170_LEDS +struct ar9170; + +struct ar9170_led { + struct ar9170 *ar; + struct led_classdev l; + char name[32]; + unsigned int toggled; + bool registered; +}; + +#endif /* CONFIG_AR9170_LEDS */ + +enum ar9170_device_state { + AR9170_UNKNOWN_STATE, + AR9170_STOPPED, + AR9170_IDLE, + AR9170_STARTED, + AR9170_ASSOCIATED, +}; + +struct ar9170 { + struct ieee80211_hw *hw; + struct mutex mutex; + enum ar9170_device_state state; + + int (*open)(struct ar9170 *); + void (*stop)(struct ar9170 *); + int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int); + int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , + void *, u32 , void *); + void (*callback_cmd)(struct ar9170 *, u32 , void *); + + /* interface mode settings */ + struct ieee80211_vif *vif; + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + + /* beaconing */ + struct sk_buff *beacon; + struct work_struct beacon_work; + + /* cryptographic engine */ + u64 usedkeys; + bool rx_software_decryption; + bool disable_offload; + + /* filter settings */ + struct work_struct filter_config_work; + u64 cur_mc_hash, want_mc_hash; + u32 cur_filter, want_filter; + unsigned int filter_changed; + bool sniffer_enabled; + + /* PHY */ + struct ieee80211_channel *channel; + int noise[4]; + + /* 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_AR9170_LEDS + struct delayed_work led_work; + struct ar9170_led leds[AR9170_NUM_LEDS]; +#endif /* CONFIG_AR9170_LEDS */ + + /* qos queue settings */ + spinlock_t tx_stats_lock; + struct ieee80211_tx_queue_stats tx_stats[5]; + struct ieee80211_tx_queue_params edcf[5]; + + spinlock_t cmdlock; + __le32 cmdbuf[PAYLOAD_MAX + 1]; + + /* MAC statistics */ + struct ieee80211_low_level_stats stats; + + /* EEPROM */ + struct ar9170_eeprom eeprom; + struct ath_regulatory regulatory; + + /* global tx status for unregistered Stations. */ + struct sk_buff_head global_tx_status; + struct sk_buff_head global_tx_status_waste; + struct delayed_work tx_status_janitor; +}; + +struct ar9170_sta_info { + struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; +}; + +#define IS_STARTED(a) (a->state >= AR9170_STARTED) +#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE) + +#define AR9170_FILTER_CHANGED_PROMISC BIT(0) +#define AR9170_FILTER_CHANGED_MULTICAST BIT(1) +#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2) + +/* exported interface */ +void *ar9170_alloc(size_t priv_size); +int ar9170_register(struct ar9170 *ar, struct device *pdev); +void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); +void ar9170_unregister(struct ar9170 *ar); +void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, + bool update_statistics, u16 tx_status); + +/* MAC */ +int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +int ar9170_init_mac(struct ar9170 *ar); +int ar9170_set_qos(struct ar9170 *ar); +int ar9170_update_multicast(struct ar9170 *ar); +int ar9170_update_frame_filter(struct ar9170 *ar); +int ar9170_set_operating_mode(struct ar9170 *ar); +int ar9170_set_beacon_timers(struct ar9170 *ar); +int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); +int ar9170_update_beacon(struct ar9170 *ar); +void ar9170_new_beacon(struct work_struct *work); +int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, + u8 keyidx, u8 *keydata, int keylen); +int ar9170_disable_key(struct ar9170 *ar, u8 id); + +/* LEDs */ +#ifdef CONFIG_AR9170_LEDS +int ar9170_register_leds(struct ar9170 *ar); +void ar9170_unregister_leds(struct ar9170 *ar); +#endif /* CONFIG_AR9170_LEDS */ +int ar9170_init_leds(struct ar9170 *ar); +int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); + +/* PHY / RF */ +int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); +int ar9170_init_rf(struct ar9170 *ar); +int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, + enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); + +#endif /* __AR9170_H */ diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c new file mode 100644 index 000000000000..f57a6200167b --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/cmd.c @@ -0,0 +1,129 @@ +/* + * Atheros AR9170 driver + * + * Basic HW register/memory/command access functions + * + * Copyright 2008, Johannes Berg + * + * 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 "ar9170.h" +#include "cmd.h" + +int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) +{ + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); + if (err) + printk(KERN_DEBUG "%s: writing memory failed\n", + wiphy_name(ar->hw->wiphy)); + return err; +} + +int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) +{ + __le32 buf[2] = { + cpu_to_le32(reg), + cpu_to_le32(val), + }; + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), + (u8 *) buf, 0, NULL); + if (err) + printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n", + wiphy_name(ar->hw->wiphy), reg, val); + return err; +} + +static int ar9170_read_mreg(struct ar9170 *ar, int nregs, + const u32 *regs, u32 *out) +{ + int i, err; + __le32 *offs, *res; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return 0; + + /* 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 = ar->exec_cmd(ar, AR9170_CMD_RREG, + 4 * nregs, (u8 *)offs, + 4 * nregs, (u8 *)res); + if (err) + return err; + + /* convert result to cpu endian */ + for (i = 0; i < nregs; i++) + out[i] = le32_to_cpu(res[i]); + + return 0; +} + +int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) +{ + return ar9170_read_mreg(ar, 1, ®, val); +} + +int ar9170_echo_test(struct ar9170 *ar, u32 v) +{ + __le32 echobuf = cpu_to_le32(v); + __le32 echores; + int err; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return -ENODEV; + + err = ar->exec_cmd(ar, AR9170_CMD_ECHO, + 4, (u8 *)&echobuf, + 4, (u8 *)&echores); + if (err) + return err; + + if (echobuf != echores) + return -EINVAL; + + return 0; +} diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h new file mode 100644 index 000000000000..a4f0e50e52b4 --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/cmd.h @@ -0,0 +1,91 @@ +/* + * Atheros AR9170 driver + * + * Basic HW register/memory/command access functions + * + * Copyright 2008, Johannes Berg + * + * 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 "ar9170.h" + +/* basic HW access */ +int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); +int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); +int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); +int ar9170_echo_test(struct ar9170 *ar, u32 v); + +/* + * 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 ar9170_regwrite_begin(ar) \ +do { \ + int __nreg = 0, __err = 0; \ + struct ar9170 *__ar = ar; + +#define ar9170_regwrite(r, v) do { \ + __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ + __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ + __nreg++; \ + if ((__nreg >= PAYLOAD_MAX/2)) { \ + if (IS_ACCEPTING_CMD(__ar)) \ + __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ + 8 * __nreg, \ + (u8 *) &__ar->cmdbuf[1], \ + 0, NULL); \ + __nreg = 0; \ + if (__err) \ + goto __regwrite_out; \ + } \ +} while (0) + +#define ar9170_regwrite_finish() \ +__regwrite_out : \ + if (__nreg) { \ + if (IS_ACCEPTING_CMD(__ar)) \ + __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ + 8 * __nreg, \ + (u8 *) &__ar->cmdbuf[1], \ + 0, NULL); \ + __nreg = 0; \ + } + +#define ar9170_regwrite_result() \ + __err; \ +} while (0); + +#endif /* __CMD_H */ diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h new file mode 100644 index 000000000000..d2c8cc83f1dd --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/eeprom.h @@ -0,0 +1,179 @@ +/* + * Atheros AR9170 driver + * + * EEPROM layout + * + * Copyright 2008, Johannes Berg + * + * 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 __AR9170_EEPROM_H +#define __AR9170_EEPROM_H + +#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; + +#endif /* __AR9170_EEPROM_H */ diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h new file mode 100644 index 000000000000..53e250a4278f --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -0,0 +1,417 @@ +/* + * Atheros AR9170 driver + * + * Hardware-specific definitions + * + * Copyright 2008, Johannes Berg + * + * 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 __AR9170_HW_H +#define __AR9170_HW_H + +#define AR9170_MAX_CMD_LEN 64 + +enum ar9170_cmd { + AR9170_CMD_RREG = 0x00, + AR9170_CMD_WREG = 0x01, + AR9170_CMD_RMEM = 0x02, + AR9170_CMD_WMEM = 0x03, + AR9170_CMD_BITAND = 0x04, + AR9170_CMD_BITOR = 0x05, + AR9170_CMD_EKEY = 0x28, + AR9170_CMD_DKEY = 0x29, + AR9170_CMD_FREQUENCY = 0x30, + AR9170_CMD_RF_INIT = 0x31, + AR9170_CMD_SYNTH = 0x32, + AR9170_CMD_FREQ_START = 0x33, + AR9170_CMD_ECHO = 0x80, + AR9170_CMD_TALLY = 0x81, + AR9170_CMD_TALLY_APD = 0x82, + AR9170_CMD_CONFIG = 0x83, + AR9170_CMD_RESET = 0x90, + AR9170_CMD_DKRESET = 0x91, + AR9170_CMD_DKTX_STATUS = 0x92, + AR9170_CMD_FDC = 0xA0, + AR9170_CMD_WREEPROM = 0xB0, + AR9170_CMD_WFLASH = 0xB0, + AR9170_CMD_FLASH_ERASE = 0xB1, + AR9170_CMD_FLASH_PROG = 0xB2, + AR9170_CMD_FLASH_CHKSUM = 0xB3, + AR9170_CMD_FLASH_READ = 0xB4, + AR9170_CMD_FW_DL_INIT = 0xB5, + AR9170_CMD_MEM_WREEPROM = 0xBB, +}; + +/* endpoints */ +#define AR9170_EP_TX 1 +#define AR9170_EP_RX 2 +#define AR9170_EP_IRQ 3 +#define AR9170_EP_CMD 4 + +#define AR9170_EEPROM_START 0x1600 + +#define AR9170_GPIO_REG_BASE 0x1d0100 +#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE +#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) +#define AR9170_NUM_LEDS 2 + + +#define AR9170_USB_REG_BASE 0x1e1000 +#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) +#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 +#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 +#define AR9170_DMA_CTL_HIGH_SPEED 0x4 +#define AR9170_DMA_CTL_PACKET_MODE 0x8 + +#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_MAC_REG_BASE 0x1c3000 + +#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_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) +#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) + +#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_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_REG_SNIFFER_ENABLE_PROMISC BIT(0) +#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 +#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) +#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) +#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 + +#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) +#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_REG_FTF_ASSOC_REQ BIT(0) +#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) +#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) +#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) +#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) +#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) +#define AR9170_MAC_REG_FTF_BIT6 BIT(6) +#define AR9170_MAC_REG_FTF_BIT7 BIT(7) +#define AR9170_MAC_REG_FTF_BEACON BIT(8) +#define AR9170_MAC_REG_FTF_ATIM BIT(9) +#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) +#define AR9170_MAC_REG_FTF_AUTH BIT(11) +#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) +#define AR9170_MAC_REG_FTF_BIT13 BIT(13) +#define AR9170_MAC_REG_FTF_BIT14 BIT(14) +#define AR9170_MAC_REG_FTF_BIT15 BIT(15) +#define AR9170_MAC_REG_FTF_BAR BIT(24) +#define AR9170_MAC_REG_FTF_BIT25 BIT(25) +#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) +#define AR9170_MAC_REG_FTF_RTS BIT(27) +#define AR9170_MAC_REG_FTF_CTS BIT(28) +#define AR9170_MAC_REG_FTF_ACK BIT(29) +#define AR9170_MAC_REG_FTF_CFE BIT(30) +#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) +#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff +#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff + +#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_RETRY (AR9170_MAC_REG_BASE + 0x6CC) +#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) + + +#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) +#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) + +#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) + +#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) +#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 +#define AR9170_MAC_REG_POWERMGT_AP 0xa1 +#define AR9170_MAC_REG_POWERMGT_STA 0x2 +#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 +#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) + +#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) +#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) + +#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_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) +#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) + +#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) + +#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_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) + +#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_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) +#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) + +#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_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) +#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) +#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) +#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) + + +#define AR9170_PWR_REG_BASE 0x1D4000 + +#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 + + +/* put beacon here in memory */ +#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 + + +struct ar9170_tx_control { + __le16 length; + __le16 mac_control; + __le32 phy_control; + u8 frame_data[0]; +} __packed; + +/* these are either-or */ +#define AR9170_TX_MAC_PROT_RTS 0x0001 +#define AR9170_TX_MAC_PROT_CTS 0x0002 + +#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_SHIFT 10 +#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) +#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 +#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 +#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 +#define AR9170_TX_MAC_TXOP_RIFS 0x2000 +#define AR9170_TX_MAC_IMM_AMPDU 0x4000 +#define AR9170_TX_MAC_RATE_PROBE 0x8000 + +/* 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_SHIFT 3 +#define AR9170_TX_PHY_BW_MASK (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_SHIFT 6 +#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) + +#define AR9170_TX_PHY_TX_PWR_SHIFT 9 +#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) + +/* not part of the hw-spec */ +#define AR9170_TX_PHY_QOS_SHIFT 25 +#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) + +#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 +#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) +#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_SHIFT 18 +#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) + +#define AR9170_TX_PHY_SHORT_GI 0x80000000 + +struct ar9170_rx_head { + u8 plcp[12]; +} __packed; + +struct ar9170_rx_tail { + 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; + u8 SAidx, DAidx; + u8 error; + u8 status; +} __packed; + +#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 + +static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) +{ + return (t->SAidx & 0xc0) >> 4 | + (t->DAidx & 0xc0) >> 6; +} + +#define AR9170_RX_STATUS_MODULATION_MASK 0x03 +#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_MASK 0x30 +#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 +#define AR9170_RX_STATUS_MPDU_FIRST 0x10 +#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20 +#define AR9170_RX_STATUS_MPDU_LAST 0x30 + + +#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 + +struct ar9170_cmd_tx_status { + __le16 unkn; + u8 dst[ETH_ALEN]; + __le32 rate; + __le16 status; +} __packed; + +#define AR9170_TX_STATUS_COMPLETE 0x00 +#define AR9170_TX_STATUS_RETRY 0x01 +#define AR9170_TX_STATUS_FAILED 0x02 + +struct ar9170_cmd_ba_failed_count { + __le16 failed; + __le16 rate; +} __packed; + +struct ar9170_cmd_response { + u8 flag; + u8 type; + + union { + struct ar9170_cmd_tx_status tx_status; + struct ar9170_cmd_ba_failed_count ba_fail_cnt; + u8 data[0]; + }; +} __packed; + +/* QoS */ + +/* mac80211 queue to HW/FW map */ +static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; + +/* HW/FW queue to mac80211 map */ +static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; + +enum ar9170_txq { + AR9170_TXQ_BE, + AR9170_TXQ_BK, + AR9170_TXQ_VI, + AR9170_TXQ_VO, + + __AR9170_NUM_TXQ, +}; + +#endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c new file mode 100644 index 000000000000..341cead7f606 --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/led.c @@ -0,0 +1,171 @@ +/* + * Atheros AR9170 driver + * + * LED handling + * + * Copyright 2008, Johannes Berg + * + * 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 "ar9170.h" +#include "cmd.h" + +int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) +{ + return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); +} + +int ar9170_init_leds(struct ar9170 *ar) +{ + int err; + + /* disable LEDs */ + /* GPIO [0/1 mode: output, 2/3: input] */ + err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); + if (err) + goto out; + + /* GPIO 0/1 value: off */ + err = ar9170_set_leds_state(ar, 0); + +out: + return err; +} + +#ifdef CONFIG_AR9170_LEDS +static void ar9170_update_leds(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); + int i, tmp, blink_delay = 1000; + u32 led_val = 0; + bool rerun = false; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return ; + + mutex_lock(&ar->mutex); + for (i = 0; i < AR9170_NUM_LEDS; i++) + if (ar->leds[i].toggled) { + led_val |= 1 << i; + + tmp = 70 + 200 / (ar->leds[i].toggled); + if (tmp < blink_delay) + blink_delay = tmp; + + if (ar->leds[i].toggled > 1) + ar->leds[i].toggled = 0; + + rerun = true; + } + + ar9170_set_leds_state(ar, led_val); + mutex_unlock(&ar->mutex); + + if (rerun) + queue_delayed_work(ar->hw->workqueue, &ar->led_work, + msecs_to_jiffies(blink_delay)); +} + +static void ar9170_led_brightness_set(struct led_classdev *led, + enum led_brightness brightness) +{ + struct ar9170_led *arl = container_of(led, struct ar9170_led, l); + struct ar9170 *ar = arl->ar; + + arl->toggled++; + + if (likely(IS_ACCEPTING_CMD(ar) && brightness)) + queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10); +} + +static int ar9170_register_led(struct ar9170 *ar, int i, char *name, + char *trigger) +{ + int err; + + snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), + "ar9170-%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 = ar9170_led_brightness_set; + 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) + printk(KERN_ERR "%s: failed to register %s LED (%d).\n", + wiphy_name(ar->hw->wiphy), ar->leds[i].name, err); + else + ar->leds[i].registered = true; + + return err; +} + +void ar9170_unregister_leds(struct ar9170 *ar) +{ + int i; + + cancel_delayed_work_sync(&ar->led_work); + + 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; + } +} + +int ar9170_register_leds(struct ar9170 *ar) +{ + int err; + + INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); + + err = ar9170_register_led(ar, 0, "tx", + ieee80211_get_tx_led_name(ar->hw)); + if (err) + goto fail; + + err = ar9170_register_led(ar, 1, "assoc", + ieee80211_get_assoc_led_name(ar->hw)); + if (err) + goto fail; + + return 0; + +fail: + ar9170_unregister_leds(ar); + return err; +} + +#endif /* CONFIG_AR9170_LEDS */ diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c new file mode 100644 index 000000000000..c8fa3073169f --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -0,0 +1,452 @@ +/* + * Atheros AR9170 driver + * + * MAC programming + * + * Copyright 2008, Johannes Berg + * + * 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 "ar9170.h" +#include "cmd.h" + +int ar9170_set_qos(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | + (ar->edcf[0].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | + (ar->edcf[1].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | + (ar->edcf[2].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | + (ar->edcf[3].cw_max << 16)); + ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | + (ar->edcf[4].cw_max << 16)); + + ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, + ((ar->edcf[0].aifs * 9 + 10)) | + ((ar->edcf[1].aifs * 9 + 10) << 12) | + ((ar->edcf[2].aifs * 9 + 10) << 24)); + ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, + ((ar->edcf[2].aifs * 9 + 10) >> 8) | + ((ar->edcf[3].aifs * 9 + 10) << 4) | + ((ar->edcf[4].aifs * 9 + 10) << 16)); + + ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, + ar->edcf[0].txop | ar->edcf[1].txop << 16); + ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, + ar->edcf[1].txop | ar->edcf[3].txop << 16); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_init_mac(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); + + ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); + + /* enable MMIC */ + ar9170_regwrite(AR9170_MAC_REG_SNIFFER, + AR9170_MAC_REG_SNIFFER_DEFAULTS); + + ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); + + ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); + ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); + ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); + + /* CF-END mode */ + ar9170_regwrite(0x1c3b2c, 0x19000000); + + /* NAV protects ACK only (in TXOP) */ + ar9170_regwrite(0x1c3b38, 0x201); + + /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ + /* OTUS set AM to 0x1 */ + ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); + + ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); + + /* AGG test code*/ + /* Aggregation MAX number and timeout */ + ar9170_regwrite(0x1c3b9c, 0x10000a); + + ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, + AR9170_MAC_REG_FTF_DEFAULTS); + + /* Enable deaggregator, response in sniffer mode */ + ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); + + /* rate sets */ + ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); + ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); + ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); + + /* MIMO response control */ + ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ + + /* switch MAC to OTUS interface */ + ar9170_regwrite(0x1c3600, 0x3); + + ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); + + /* set PHY register read timeout (??) */ + ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); + + /* Disable Rx TimeOut, workaround for BB. */ + ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); + + /* Set CPU clock frequency to 88/80MHz */ + ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, + AR9170_PWR_CLK_AHB_80_88MHZ | + AR9170_PWR_CLK_DAC_160_INV_DLY); + + /* Set WLAN DMA interrupt mode: generate int per packet */ + ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); + + ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, + AR9170_MAC_FCS_FIFO_PROT); + + /* Disables the CF_END frame, undocumented register */ + ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, + 0x141E0F48); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) +{ + static const u8 zero[ETH_ALEN] = { 0 }; + + if (!mac) + mac = zero; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(reg, + (mac[3] << 24) | (mac[2] << 16) | + (mac[1] << 8) | mac[0]); + + ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]); + + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_update_multicast(struct ar9170 *ar) +{ + int err; + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, + ar->want_mc_hash >> 32); + ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, + ar->want_mc_hash); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + + if (err) + return err; + + ar->cur_mc_hash = ar->want_mc_hash; + + return 0; +} + +int ar9170_update_frame_filter(struct ar9170 *ar) +{ + int err; + + err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, + ar->want_filter); + + if (err) + return err; + + ar->cur_filter = ar->want_filter; + + return 0; +} + +static int ar9170_set_promiscouous(struct ar9170 *ar) +{ + u32 encr_mode, sniffer; + int err; + + err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); + if (err) + return err; + + err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); + if (err) + return err; + + if (ar->sniffer_enabled) { + sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; + + /* + * Rx decryption works in place. + * + * If we don't disable it, the hardware will render all + * encrypted frames which are encrypted with an unknown + * key useless. + */ + + encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + ar->sniffer_enabled = true; + } else { + sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; + + if (ar->rx_software_decryption) + encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + else + encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); + ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_set_operating_mode(struct ar9170 *ar) +{ + u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; + u8 *mac_addr, *bssid; + int err; + + if (ar->vif) { + mac_addr = ar->mac_addr; + bssid = ar->bssid; + + switch (ar->vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; + break; +/* case NL80211_IFTYPE_AP: + pm_mode |= AR9170_MAC_REG_POWERMGT_AP; + break;*/ + case NL80211_IFTYPE_WDS: + pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; + break; + case NL80211_IFTYPE_MONITOR: + ar->sniffer_enabled = true; + ar->rx_software_decryption = true; + break; + default: + pm_mode |= AR9170_MAC_REG_POWERMGT_STA; + break; + } + } else { + mac_addr = NULL; + bssid = NULL; + } + + err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); + if (err) + return err; + + err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); + if (err) + return err; + + err = ar9170_set_promiscouous(ar); + if (err) + return err; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + +int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) +{ + u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); + + return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); +} + +int ar9170_set_beacon_timers(struct ar9170 *ar) +{ + u32 v = 0; + u32 pretbtt = 0; + + v |= ar->hw->conf.beacon_int; + + if (ar->vif) { + switch (ar->vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + v |= BIT(25); + break; + case NL80211_IFTYPE_AP: + v |= BIT(24); + pretbtt = (ar->hw->conf.beacon_int - 6) << 16; + break; + default: + break; + } + + v |= ar->vif->bss_conf.dtim_period << 16; + } + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); + ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +int ar9170_update_beacon(struct ar9170 *ar) +{ + struct sk_buff *skb; + __le32 *data, *old = NULL; + u32 word; + int i; + + skb = ieee80211_beacon_get(ar->hw, ar->vif); + if (!skb) + return -ENOMEM; + + data = (__le32 *)skb->data; + if (ar->beacon) + old = (__le32 *)ar->beacon->data; + + ar9170_regwrite_begin(ar); + for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { + /* + * XXX: This accesses beyond skb data for up + * to the last 3 bytes!! + */ + + if (old && (data[i] == old[i])) + continue; + + word = le32_to_cpu(data[i]); + ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); + } + + /* XXX: use skb->cb info */ + if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) + ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, + ((skb->len + 4) << (3+16)) + 0x0400); + else + ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, + ((skb->len + 4) << (3+16)) + 0x0400); + + ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); + ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); + ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); + + ar9170_regwrite_finish(); + + dev_kfree_skb(ar->beacon); + ar->beacon = skb; + + return ar9170_regwrite_result(); +} + +void ar9170_new_beacon(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + beacon_work); + struct sk_buff *skb; + + if (unlikely(!IS_STARTED(ar))) + return ; + + mutex_lock(&ar->mutex); + + if (!ar->vif) + goto out; + + ar9170_update_beacon(ar); + + rcu_read_lock(); + while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) + ar9170_op_tx(ar->hw, skb); + + rcu_read_unlock(); + + out: + mutex_unlock(&ar->mutex); +} + +int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, + u8 keyidx, u8 *keydata, int keylen) +{ + __le32 vals[7]; + static const u8 bcast[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + u8 dummy; + + mac = mac ? : bcast; + + vals[0] = cpu_to_le32((keyidx << 16) + id); + vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); + vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | + mac[3] << 8 | mac[2]); + memset(&vals[3], 0, 16); + if (keydata) + memcpy(&vals[3], keydata, keylen); + + return ar->exec_cmd(ar, AR9170_CMD_EKEY, + sizeof(vals), (u8 *)vals, + 1, &dummy); +} + +int ar9170_disable_key(struct ar9170 *ar, u8 id) +{ + __le32 val = cpu_to_le32(id); + u8 dummy; + + return ar->exec_cmd(ar, AR9170_CMD_EKEY, + sizeof(val), (u8 *)&val, + 1, &dummy); +} diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c new file mode 100644 index 000000000000..8de0ff9f580b --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -0,0 +1,1690 @@ +/* + * Atheros AR9170 driver + * + * mac80211 interaction code + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * 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 +#include +#include +#include +#include "ar9170.h" +#include "hw.h" +#include "cmd.h" + +static int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ + .bitrate = (_bitrate), \ + .flags = (_flags), \ + .hw_value = (_hw_rate) | (_txpidx) << 4, \ +} + +static struct ieee80211_rate __ar9170_ratetable[] = { + RATE(10, 0, 0, 0), + RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(60, 0xb, 0, 0), + RATE(90, 0xf, 0, 0), + RATE(120, 0xa, 0, 0), + RATE(180, 0xe, 0, 0), + RATE(240, 0x9, 0, 0), + RATE(360, 0xd, 1, 0), + RATE(480, 0x8, 2, 0), + RATE(540, 0xc, 3, 0), +}; +#undef RATE + +#define ar9170_g_ratetable (__ar9170_ratetable + 0) +#define ar9170_g_ratetable_size 12 +#define ar9170_a_ratetable (__ar9170_ratetable + 4) +#define ar9170_a_ratetable_size 8 + +/* + * NB: The hw_value is used as an index into the ar9170_phy_freq_params + * array in phy.c so that we don't have to do frequency lookups! + */ +#define CHAN(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 18, /* XXX */ \ +} + +static struct ieee80211_channel ar9170_2ghz_chantable[] = { + CHAN(2412, 0), + CHAN(2417, 1), + CHAN(2422, 2), + CHAN(2427, 3), + CHAN(2432, 4), + CHAN(2437, 5), + CHAN(2442, 6), + CHAN(2447, 7), + CHAN(2452, 8), + CHAN(2457, 9), + CHAN(2462, 10), + CHAN(2467, 11), + CHAN(2472, 12), + CHAN(2484, 13), +}; + +static struct ieee80211_channel ar9170_5ghz_chantable[] = { + CHAN(4920, 14), + CHAN(4940, 15), + CHAN(4960, 16), + CHAN(4980, 17), + CHAN(5040, 18), + CHAN(5060, 19), + CHAN(5080, 20), + CHAN(5180, 21), + CHAN(5200, 22), + CHAN(5220, 23), + CHAN(5240, 24), + CHAN(5260, 25), + CHAN(5280, 26), + CHAN(5300, 27), + CHAN(5320, 28), + CHAN(5500, 29), + CHAN(5520, 30), + CHAN(5540, 31), + CHAN(5560, 32), + CHAN(5580, 33), + CHAN(5600, 34), + CHAN(5620, 35), + CHAN(5640, 36), + CHAN(5660, 37), + CHAN(5680, 38), + CHAN(5700, 39), + CHAN(5745, 40), + CHAN(5765, 41), + CHAN(5785, 42), + CHAN(5805, 43), + CHAN(5825, 44), + CHAN(5170, 45), + CHAN(5190, 46), + CHAN(5210, 47), + CHAN(5230, 48), +}; +#undef CHAN + +static struct ieee80211_supported_band ar9170_band_2GHz = { + .channels = ar9170_2ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), + .bitrates = ar9170_g_ratetable, + .n_bitrates = ar9170_g_ratetable_size, +}; + +#ifdef AR9170_QUEUE_DEBUG +/* + * In case some wants works with AR9170's crazy tx_status queueing techniques. + * He might need this rather useful probing function. + * + * NOTE: caller must hold the queue's spinlock! + */ + +static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) +{ + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *)txc->frame_data; + + printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] " + "mac_control:%04x, phy_control:%08x]\n", + wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), + ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control), + le32_to_cpu(txc->phy_control)); +} + +static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar, + struct sk_buff_head *queue) +{ + struct sk_buff *skb; + int i = 0; + + printk(KERN_DEBUG "---[ cut here ]---\n"); + printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n", + wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); + + skb_queue_walk(queue, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *)txc->frame_data; + + printk(KERN_DEBUG "index:%d => \n", i); + ar9170_print_txheader(ar, skb); + } + printk(KERN_DEBUG "---[ end ]---\n"); +} +#endif /* AR9170_QUEUE_DEBUG */ + +static struct ieee80211_supported_band ar9170_band_5GHz = { + .channels = ar9170_5ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), + .bitrates = ar9170_a_ratetable, + .n_bitrates = ar9170_a_ratetable_size, +}; + +void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, + bool valid_status, u16 tx_status) +{ + struct ieee80211_tx_info *txinfo; + unsigned int retries = 0, queue = skb_get_queue_mapping(skb); + unsigned long flags; + + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[queue].len--; + if (ieee80211_queue_stopped(ar->hw, queue)) + ieee80211_wake_queue(ar->hw, queue); + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + txinfo = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(txinfo); + + switch (tx_status) { + case AR9170_TX_STATUS_RETRY: + retries = 2; + case AR9170_TX_STATUS_COMPLETE: + txinfo->flags |= IEEE80211_TX_STAT_ACK; + break; + + case AR9170_TX_STATUS_FAILED: + retries = ar->hw->conf.long_frame_max_tx_count; + break; + + default: + printk(KERN_ERR "%s: invalid tx_status response (%x).\n", + wiphy_name(ar->hw->wiphy), tx_status); + break; + } + + if (valid_status) + txinfo->status.rates[0].count = retries + 1; + + skb_pull(skb, sizeof(struct ar9170_tx_control)); + ieee80211_tx_status_irqsafe(ar->hw, skb); +} + +static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar, + const u8 *mac, + const u32 queue, + struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb_queue_walk(q, skb) { + struct ar9170_tx_control *txc = (void *) skb->data; + struct ieee80211_hdr *hdr = (void *) txc->frame_data; + u32 txc_queue = (le32_to_cpu(txc->phy_control) & + AR9170_TX_PHY_QOS_MASK) >> + AR9170_TX_PHY_QOS_SHIFT; + + if ((queue != txc_queue) || + (compare_ether_addr(ieee80211_get_DA(hdr), mac))) + continue; + + __skb_unlink(skb, q); + spin_unlock_irqrestore(&q->lock, flags); + return skb; + } + spin_unlock_irqrestore(&q->lock, flags); + return NULL; +} + +static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac, + const u32 queue) +{ + struct ieee80211_sta *sta; + struct sk_buff *skb; + + /* + * Unfortunately, the firmware does not tell to which (queued) frame + * this transmission status report belongs to. + * + * So we have to make risky guesses - with the scarce information + * the firmware provided (-> destination MAC, and phy_control) - + * and hope that we picked the right one... + */ + rcu_read_lock(); + sta = ieee80211_find_sta(ar->hw, mac); + + if (likely(sta)) { + struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv; + skb = skb_dequeue(&sta_priv->tx_status[queue]); + rcu_read_unlock(); + if (likely(skb)) + return skb; + } else + rcu_read_unlock(); + + /* scan the waste queue for candidates */ + skb = ar9170_find_skb_in_queue(ar, mac, queue, + &ar->global_tx_status_waste); + if (!skb) { + /* so it still _must_ be in the global list. */ + skb = ar9170_find_skb_in_queue(ar, mac, queue, + &ar->global_tx_status); + } + +#ifdef AR9170_QUEUE_DEBUG + if (unlikely((!skb) && net_ratelimit())) { + printk(KERN_ERR "%s: ESS:[%pM] does not have any " + "outstanding frames in this queue (%d).\n", + wiphy_name(ar->hw->wiphy), mac, queue); + } +#endif /* AR9170_QUEUE_DEBUG */ + return skb; +} + +/* + * This worker tries to keep the global tx_status queue empty. + * So we can guarantee that incoming tx_status reports for + * unregistered stations are always synced with the actual + * frame - which we think - belongs to. + */ + +static void ar9170_tx_status_janitor(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + tx_status_janitor.work); + struct sk_buff *skb; + + if (unlikely(!IS_STARTED(ar))) + return ; + + mutex_lock(&ar->mutex); + /* recycle the garbage back to mac80211... one by one. */ + while ((skb = skb_dequeue(&ar->global_tx_status_waste))) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: dispose queued frame =>\n", + wiphy_name(ar->hw->wiphy)); + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + ar9170_handle_tx_status(ar, skb, false, + AR9170_TX_STATUS_FAILED); + } + + while ((skb = skb_dequeue(&ar->global_tx_status))) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: moving frame into waste queue =>\n", + wiphy_name(ar->hw->wiphy)); + + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + skb_queue_tail(&ar->global_tx_status_waste, skb); + } + + /* recall the janitor in 100ms - if there's garbage in the can. */ + if (skb_queue_len(&ar->global_tx_status_waste) > 0) + queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, + msecs_to_jiffies(100)); + + mutex_unlock(&ar->mutex); +} + +static void ar9170_handle_command_response(struct ar9170 *ar, + void *buf, u32 len) +{ + struct ar9170_cmd_response *cmd = (void *) buf; + + if ((cmd->type & 0xc0) != 0xc0) { + ar->callback_cmd(ar, len, buf); + return; + } + + /* hardware event handlers */ + switch (cmd->type) { + case 0xc1: { + /* + * TX status notification: + * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 + * + * XX always 81 + * YY always 00 + * M1-M6 is the MAC address + * R1-R4 is the transmit rate + * S1-S2 is the transmit status + */ + + struct sk_buff *skb; + u32 queue = (le32_to_cpu(cmd->tx_status.rate) & + AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT; + + skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue); + if (unlikely(!skb)) + return ; + + ar9170_handle_tx_status(ar, skb, true, + le16_to_cpu(cmd->tx_status.status)); + break; + } + + case 0xc0: + /* + * pre-TBTT event + */ + if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) + queue_work(ar->hw->workqueue, &ar->beacon_work); + break; + + case 0xc2: + /* + * (IBSS) beacon send notification + * bytes: 04 c2 XX YY B4 B3 B2 B1 + * + * XX always 80 + * YY always 00 + * B1-B4 "should" be the number of send out beacons. + */ + break; + + case 0xc3: + /* End of Atim Window */ + break; + + case 0xc4: + case 0xc5: + /* BlockACK events */ + break; + + case 0xc6: + /* Watchdog Interrupt */ + break; + + case 0xc9: + /* retransmission issue / SIFS/EIFS collision ?! */ + break; + + default: + printk(KERN_INFO "received unhandled event %x\n", cmd->type); + print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); + break; + } +} + +/* + * If the frame alignment is right (or the kernel has + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there + * is only a single MPDU in the USB frame, then we can + * submit to mac80211 the SKB directly. However, since + * there may be multiple packets in one SKB in stream + * mode, and we need to observe the proper ordering, + * this is non-trivial. + */ +static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +{ + struct sk_buff *skb; + struct ar9170_rx_head *head = (void *)buf; + struct ar9170_rx_tail *tail; + struct ieee80211_rx_status status; + int mpdu_len, i; + u8 error, antennas = 0, decrypt; + __le16 fc; + int reserved; + + if (unlikely(!IS_STARTED(ar))) + return ; + + /* Received MPDU */ + mpdu_len = len; + mpdu_len -= sizeof(struct ar9170_rx_head); + mpdu_len -= sizeof(struct ar9170_rx_tail); + BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); + BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24); + + if (mpdu_len <= FCS_LEN) + return; + + tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len); + + for (i = 0; i < 3; i++) + if (tail->rssi[i] != 0x80) + antennas |= BIT(i); + + /* post-process RSSI */ + for (i = 0; i < 7; i++) + if (tail->rssi[i] & 0x80) + tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f; + + memset(&status, 0, sizeof(status)); + + status.band = ar->channel->band; + status.freq = ar->channel->center_freq; + status.signal = ar->noise[0] + tail->rssi_combined; + status.noise = ar->noise[0]; + status.antenna = antennas; + + switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) { + case AR9170_RX_STATUS_MODULATION_CCK: + if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE) + status.flag |= RX_FLAG_SHORTPRE; + switch (head->plcp[0]) { + case 0x0a: + status.rate_idx = 0; + break; + case 0x14: + status.rate_idx = 1; + break; + case 0x37: + status.rate_idx = 2; + break; + case 0x6e: + status.rate_idx = 3; + break; + default: + if ((!ar->sniffer_enabled) && (net_ratelimit())) + printk(KERN_ERR "%s: invalid plcp cck rate " + "(%x).\n", wiphy_name(ar->hw->wiphy), + head->plcp[0]); + return; + } + break; + case AR9170_RX_STATUS_MODULATION_OFDM: + switch (head->plcp[0] & 0xF) { + case 0xB: + status.rate_idx = 0; + break; + case 0xF: + status.rate_idx = 1; + break; + case 0xA: + status.rate_idx = 2; + break; + case 0xE: + status.rate_idx = 3; + break; + case 0x9: + status.rate_idx = 4; + break; + case 0xD: + status.rate_idx = 5; + break; + case 0x8: + status.rate_idx = 6; + break; + case 0xC: + status.rate_idx = 7; + break; + default: + if ((!ar->sniffer_enabled) && (net_ratelimit())) + printk(KERN_ERR "%s: invalid plcp ofdm rate " + "(%x).\n", wiphy_name(ar->hw->wiphy), + head->plcp[0]); + return; + } + if (status.band == IEEE80211_BAND_2GHZ) + status.rate_idx += 4; + break; + case AR9170_RX_STATUS_MODULATION_HT: + case AR9170_RX_STATUS_MODULATION_DUPOFDM: + /* XXX */ + + if (net_ratelimit()) + printk(KERN_ERR "%s: invalid modulation\n", + wiphy_name(ar->hw->wiphy)); + return; + } + + error = tail->error; + + if (error & AR9170_RX_ERROR_MMIC) { + status.flag |= RX_FLAG_MMIC_ERROR; + error &= ~AR9170_RX_ERROR_MMIC; + } + + if (error & AR9170_RX_ERROR_PLCP) { + status.flag |= RX_FLAG_FAILED_PLCP_CRC; + error &= ~AR9170_RX_ERROR_PLCP; + } + + if (error & AR9170_RX_ERROR_FCS) { + status.flag |= RX_FLAG_FAILED_FCS_CRC; + error &= ~AR9170_RX_ERROR_FCS; + } + + decrypt = ar9170_get_decrypt_type(tail); + if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && + decrypt != AR9170_ENC_ALG_NONE) + status.flag |= RX_FLAG_DECRYPTED; + + /* ignore wrong RA errors */ + error &= ~AR9170_RX_ERROR_WRONG_RA; + + if (error & AR9170_RX_ERROR_DECRYPT) { + error &= ~AR9170_RX_ERROR_DECRYPT; + + /* + * Rx decryption is done in place, + * the original data is lost anyway. + */ + return ; + } + + /* drop any other error frames */ + if ((error) && (net_ratelimit())) { + printk(KERN_DEBUG "%s: errors: %#x\n", + wiphy_name(ar->hw->wiphy), error); + return; + } + + buf += sizeof(struct ar9170_rx_head); + fc = *(__le16 *)buf; + + if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc)) + reserved = 32 + 2; + else + reserved = 32; + + skb = dev_alloc_skb(mpdu_len + reserved); + if (!skb) + return; + + skb_reserve(skb, reserved); + memcpy(skb_put(skb, mpdu_len), buf, mpdu_len); + ieee80211_rx_irqsafe(ar->hw, skb, &status); +} + +void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) +{ + unsigned int i, tlen, resplen; + u8 *tbuf, *respbuf; + + tbuf = skb->data; + tlen = skb->len; + + while (tlen >= 4) { + int clen = tbuf[1] << 8 | tbuf[0]; + int wlen = (clen + 3) & ~3; + + /* + * parse stream (if any) + */ + if (tbuf[2] != 0 || tbuf[3] != 0x4e) { + printk(KERN_ERR "%s: missing tag!\n", + wiphy_name(ar->hw->wiphy)); + return ; + } + if (wlen > tlen - 4) { + printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n", + wiphy_name(ar->hw->wiphy), clen, wlen, tlen); + print_hex_dump(KERN_DEBUG, "data: ", + DUMP_PREFIX_OFFSET, + 16, 1, tbuf, tlen, true); + return ; + } + resplen = clen; + respbuf = tbuf + 4; + tbuf += wlen + 4; + tlen -= wlen + 4; + + i = 0; + + /* weird thing, but this is the same in the original driver */ + while (resplen > 2 && i < 12 && + respbuf[0] == 0xff && respbuf[1] == 0xff) { + i += 2; + resplen -= 2; + respbuf += 2; + } + + if (resplen < 4) + continue; + + /* found the 6 * 0xffff marker? */ + if (i == 12) + ar9170_handle_command_response(ar, respbuf, resplen); + else + ar9170_handle_mpdu(ar, respbuf, resplen); + } + + if (tlen) + printk(KERN_ERR "%s: buffer remains!\n", + wiphy_name(ar->hw->wiphy)); +} + +#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ +do { \ + queue.aifs = ai_fs; \ + queue.cw_min = cwmin; \ + queue.cw_max = cwmax; \ + queue.txop = _txop; \ +} while (0) + +static int ar9170_op_start(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + int err, i; + + mutex_lock(&ar->mutex); + + /* reinitialize queues statistics */ + memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); + for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++) + ar->tx_stats[i].limit = 8; + + /* reset QoS defaults */ + AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ + AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ + AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ + AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ + AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ + + err = ar->open(ar); + if (err) + goto out; + + err = ar9170_init_mac(ar); + if (err) + goto out; + + err = ar9170_set_qos(ar); + if (err) + goto out; + + err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); + if (err) + goto out; + + err = ar9170_init_rf(ar); + if (err) + goto out; + + /* start DMA */ + err = ar9170_write_reg(ar, 0x1c3d30, 0x100); + if (err) + goto out; + + ar->state = AR9170_STARTED; + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_op_stop(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + + if (IS_STARTED(ar)) + ar->state = AR9170_IDLE; + + flush_workqueue(ar->hw->workqueue); + + mutex_lock(&ar->mutex); + cancel_delayed_work_sync(&ar->tx_status_janitor); + cancel_work_sync(&ar->filter_config_work); + cancel_work_sync(&ar->beacon_work); + skb_queue_purge(&ar->global_tx_status_waste); + skb_queue_purge(&ar->global_tx_status); + + if (IS_ACCEPTING_CMD(ar)) { + ar9170_set_leds_state(ar, 0); + + /* stop DMA */ + ar9170_write_reg(ar, 0x1c3d30, 0); + ar->stop(ar); + } + + mutex_unlock(&ar->mutex); +} + +int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ar9170 *ar = hw->priv; + struct ieee80211_hdr *hdr; + struct ar9170_tx_control *txc; + struct ieee80211_tx_info *info; + struct ieee80211_rate *rate = NULL; + struct ieee80211_tx_rate *txrate; + unsigned int queue = skb_get_queue_mapping(skb); + unsigned long flags = 0; + struct ar9170_sta_info *sta_info = NULL; + u32 power, chains; + u16 keytype = 0; + u16 len, icv = 0; + int err; + bool tx_status; + + if (unlikely(!IS_STARTED(ar))) + goto err_free; + + hdr = (void *)skb->data; + info = IEEE80211_SKB_CB(skb); + len = skb->len; + + spin_lock_irqsave(&ar->tx_stats_lock, flags); + if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) { + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + return NETDEV_TX_OK; + } + + ar->tx_stats[queue].len++; + ar->tx_stats[queue].count++; + if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len) + ieee80211_stop_queue(hw, queue); + + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + + txc = (void *)skb_push(skb, sizeof(*txc)); + + tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) || + ((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0)); + + if (info->control.hw_key) { + icv = info->control.hw_key->icv_len; + + switch (info->control.hw_key->alg) { + case ALG_WEP: + keytype = AR9170_TX_MAC_ENCR_RC4; + break; + case ALG_TKIP: + keytype = AR9170_TX_MAC_ENCR_RC4; + break; + case ALG_CCMP: + keytype = AR9170_TX_MAC_ENCR_AES; + break; + default: + WARN_ON(1); + goto err_dequeue; + } + } + + /* Length */ + txc->length = cpu_to_le16(len + icv + 4); + + txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | + AR9170_TX_MAC_BACKOFF); + txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << + AR9170_TX_MAC_QOS_SHIFT); + txc->mac_control |= cpu_to_le16(keytype); + txc->phy_control = cpu_to_le32(0); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); + + txrate = &info->control.rates[0]; + + if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); + + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); + + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); + /* this works because 40 MHz is 2 and dup is 3 */ + if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); + + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); + + if (txrate->flags & IEEE80211_TX_RC_MCS) { + u32 r = txrate->idx; + u8 *txpower; + + r <<= AR9170_TX_PHY_MCS_SHIFT; + if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK)) + goto err_dequeue; + txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); + txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); + + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { + if (info->band == IEEE80211_BAND_5GHZ) + txpower = ar->power_5G_ht40; + else + txpower = ar->power_2G_ht40; + } else { + if (info->band == IEEE80211_BAND_5GHZ) + txpower = ar->power_5G_ht20; + else + txpower = ar->power_2G_ht20; + } + + power = txpower[(txrate->idx) & 7]; + } else { + u8 *txpower; + u32 mod; + u32 phyrate; + u8 idx = txrate->idx; + + if (info->band != IEEE80211_BAND_2GHZ) { + idx += 4; + txpower = ar->power_5G_leg; + mod = AR9170_TX_PHY_MOD_OFDM; + } else { + if (idx < 4) { + txpower = ar->power_2G_cck; + mod = AR9170_TX_PHY_MOD_CCK; + } else { + mod = AR9170_TX_PHY_MOD_OFDM; + txpower = ar->power_2G_ofdm; + } + } + + rate = &__ar9170_ratetable[idx]; + + phyrate = rate->hw_value & 0xF; + power = txpower[(rate->hw_value & 0x30) >> 4]; + phyrate <<= AR9170_TX_PHY_MCS_SHIFT; + + txc->phy_control |= cpu_to_le32(mod); + txc->phy_control |= cpu_to_le32(phyrate); + } + + power <<= AR9170_TX_PHY_TX_PWR_SHIFT; + power &= AR9170_TX_PHY_TX_PWR_MASK; + txc->phy_control |= cpu_to_le32(power); + + /* set TX chains */ + if (ar->eeprom.tx_mask == 1) { + chains = AR9170_TX_PHY_TXCHAIN_1; + } else { + chains = AR9170_TX_PHY_TXCHAIN_2; + + /* >= 36M legacy OFDM - use only one chain */ + if (rate && rate->bitrate >= 360) + chains = AR9170_TX_PHY_TXCHAIN_1; + } + txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); + + if (tx_status) { + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); + /* + * WARNING: + * Putting the QoS queue bits into an unexplored territory is + * certainly not elegant. + * + * In my defense: This idea provides a reasonable way to + * smuggle valuable information to the tx_status callback. + * Also, the idea behind this bit-abuse came straight from + * the original driver code. + */ + + txc->phy_control |= + cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); + + if (info->control.sta) { + sta_info = (void *) info->control.sta->drv_priv; + skb_queue_tail(&sta_info->tx_status[queue], skb); + } else { + skb_queue_tail(&ar->global_tx_status, skb); + + queue_delayed_work(ar->hw->workqueue, + &ar->tx_status_janitor, + msecs_to_jiffies(100)); + } + } + + err = ar->tx(ar, skb, tx_status, 0); + if (unlikely(tx_status && err)) { + if (info->control.sta) + skb_unlink(skb, &sta_info->tx_status[queue]); + else + skb_unlink(skb, &ar->global_tx_status); + } + + return NETDEV_TX_OK; + +err_dequeue: + spin_lock_irqsave(&ar->tx_stats_lock, flags); + ar->tx_stats[queue].len--; + ar->tx_stats[queue].count--; + spin_unlock_irqrestore(&ar->tx_stats_lock, flags); + +err_free: + dev_kfree_skb(skb); + return NETDEV_TX_OK; +} + +static int ar9170_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (ar->vif) { + err = -EBUSY; + goto unlock; + } + + ar->vif = conf->vif; + memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); + + if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { + ar->rx_software_decryption = true; + ar->disable_offload = true; + } + + ar->cur_filter = 0; + ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS; + err = ar9170_update_frame_filter(ar); + if (err) + goto unlock; + + err = ar9170_set_operating_mode(ar); + +unlock: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ar9170 *ar = hw->priv; + + mutex_lock(&ar->mutex); + ar->vif = NULL; + ar->want_filter = 0; + ar9170_update_frame_filter(ar); + ar9170_set_beacon_timers(ar); + dev_kfree_skb(ar->beacon); + ar->beacon = NULL; + ar->sniffer_enabled = false; + ar->rx_software_decryption = false; + ar9170_set_operating_mode(ar); + mutex_unlock(&ar->mutex); +} + +static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_PS) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + /* TODO */ + err = 0; + } + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + /* + * is it long_frame_max_tx_count or short_frame_max_tx_count? + */ + + err = ar9170_set_hwretry_limit(ar, + ar->hw->conf.long_frame_max_tx_count); + if (err) + goto out; + } + + if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) { + err = ar9170_set_beacon_timers(ar); + if (err) + goto out; + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + err = ar9170_set_channel(ar, hw->conf.channel, + AR9170_RFI_NONE, AR9170_BW_20); + if (err) + goto out; + /* adjust slot time for 5 GHz */ + if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) + err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, + 9 << 10); + } + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static int ar9170_op_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + if (conf->changed & IEEE80211_IFCC_BSSID) { + memcpy(ar->bssid, conf->bssid, ETH_ALEN); + err = ar9170_set_operating_mode(ar); + } + + if (conf->changed & IEEE80211_IFCC_BEACON) { + err = ar9170_update_beacon(ar); + + if (err) + goto out; + err = ar9170_set_beacon_timers(ar); + } + +out: + mutex_unlock(&ar->mutex); + return err; +} + +static void ar9170_set_filters(struct work_struct *work) +{ + struct ar9170 *ar = container_of(work, struct ar9170, + filter_config_work); + int err; + + if (unlikely(!IS_STARTED(ar))) + return ; + + mutex_lock(&ar->mutex); + if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) { + err = ar9170_set_operating_mode(ar); + if (err) + goto unlock; + } + + if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) { + err = ar9170_update_multicast(ar); + if (err) + goto unlock; + } + + if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER) + err = ar9170_update_frame_filter(ar); + +unlock: + mutex_unlock(&ar->mutex); +} + +static void ar9170_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + int mc_count, struct dev_mc_list *mclist) +{ + struct ar9170 *ar = hw->priv; + + /* mask supported flags */ + *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | + FIF_PROMISC_IN_BSS; + + /* + * We can support more by setting the sniffer bit and + * then checking the error flags, later. + */ + + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) { + ar->want_mc_hash = ~0ULL; + } else { + u64 mchash; + int i; + + /* always get broadcast frames */ + mchash = 1ULL << (0xff>>2); + + for (i = 0; i < mc_count; i++) { + if (WARN_ON(!mclist)) + break; + mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); + mclist = mclist->next; + } + ar->want_mc_hash = mchash; + } + ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST; + } + + if (changed_flags & FIF_CONTROL) { + u32 filter = AR9170_MAC_REG_FTF_PSPOLL | + AR9170_MAC_REG_FTF_RTS | + AR9170_MAC_REG_FTF_CTS | + AR9170_MAC_REG_FTF_ACK | + AR9170_MAC_REG_FTF_CFE | + AR9170_MAC_REG_FTF_CFE_ACK; + + if (*new_flags & FIF_CONTROL) + ar->want_filter = ar->cur_filter | filter; + else + ar->want_filter = ar->cur_filter & ~filter; + + ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER; + } + + if (changed_flags & FIF_PROMISC_IN_BSS) { + ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; + ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC; + } + + if (likely(IS_STARTED(ar))) + queue_work(ar->hw->workqueue, &ar->filter_config_work); +} + +static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct ar9170 *ar = hw->priv; + int err = 0; + + mutex_lock(&ar->mutex); + + ar9170_regwrite_begin(ar); + + if (changed & BSS_CHANGED_ASSOC) { + ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state; + +#ifndef CONFIG_AR9170_LEDS + /* enable assoc LED. */ + err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); +#endif /* CONFIG_AR9170_LEDS */ + } + + if (changed & BSS_CHANGED_HT) { + /* TODO */ + err = 0; + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + u32 slottime = 20; + + if (bss_conf->use_short_slot) + slottime = 9; + + ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + u32 cck, ofdm; + + if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) { + ofdm = bss_conf->basic_rates; + cck = 0; + } else { + /* four cck rates */ + cck = bss_conf->basic_rates & 0xf; + ofdm = bss_conf->basic_rates >> 4; + } + ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, + ofdm << 8 | cck); + } + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + mutex_unlock(&ar->mutex); +} + +static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) +{ + struct ar9170 *ar = hw->priv; + int err; + u32 tsf_low; + u32 tsf_high; + u64 tsf; + + mutex_lock(&ar->mutex); + err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); + if (!err) + err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); + mutex_unlock(&ar->mutex); + + if (WARN_ON(err)) + return 0; + + tsf = tsf_high; + tsf = (tsf << 32) | tsf_low; + return tsf; +} + +static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ar9170 *ar = hw->priv; + int err = 0, i; + u8 ktype; + + if ((!ar->vif) || (ar->disable_offload)) + return -EOPNOTSUPP; + + switch (key->alg) { + case ALG_WEP: + if (key->keylen == LEN_WEP40) + ktype = AR9170_ENC_ALG_WEP64; + else + ktype = AR9170_ENC_ALG_WEP128; + break; + case ALG_TKIP: + ktype = AR9170_ENC_ALG_TKIP; + break; + case ALG_CCMP: + ktype = AR9170_ENC_ALG_AESCCMP; + break; + default: + return -EOPNOTSUPP; + } + + mutex_lock(&ar->mutex); + if (cmd == SET_KEY) { + if (unlikely(!IS_STARTED(ar))) { + err = -EOPNOTSUPP; + goto out; + } + + /* group keys need all-zeroes address */ + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + sta = NULL; + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + for (i = 0; i < 64; i++) + if (!(ar->usedkeys & BIT(i))) + break; + if (i == 64) { + ar->rx_software_decryption = true; + ar9170_set_operating_mode(ar); + err = -ENOSPC; + goto out; + } + } else { + i = 64 + key->keyidx; + } + + key->hw_key_idx = i; + + err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, + key->key, min_t(u8, 16, key->keylen)); + if (err) + goto out; + + if (key->alg == ALG_TKIP) { + err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, + ktype, 1, key->key + 16, 16); + if (err) + goto out; + + /* + * hardware is not capable generating the MMIC + * for fragmented frames! + */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + } + + if (i < 64) + ar->usedkeys |= BIT(i); + + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + } else { + if (unlikely(!IS_STARTED(ar))) { + /* The device is gone... together with the key ;-) */ + err = 0; + goto out; + } + + err = ar9170_disable_key(ar, key->hw_key_idx); + if (err) + goto out; + + if (key->hw_key_idx < 64) { + ar->usedkeys &= ~BIT(key->hw_key_idx); + } else { + err = ar9170_upload_key(ar, key->hw_key_idx, NULL, + AR9170_ENC_ALG_NONE, 0, + NULL, 0); + if (err) + goto out; + + if (key->alg == ALG_TKIP) { + err = ar9170_upload_key(ar, key->hw_key_idx, + NULL, + AR9170_ENC_ALG_NONE, 1, + NULL, 0); + if (err) + goto out; + } + + } + } + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); + ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + +out: + mutex_unlock(&ar->mutex); + + return err; +} + +static void ar9170_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct ar9170 *ar = hw->priv; + struct ar9170_sta_info *info = (void *) sta->drv_priv; + struct sk_buff *skb; + unsigned int i; + + switch (cmd) { + case STA_NOTIFY_ADD: + for (i = 0; i < ar->hw->queues; i++) + skb_queue_head_init(&info->tx_status[i]); + break; + + case STA_NOTIFY_REMOVE: + + /* + * transfer all outstanding frames that need a tx_status + * reports to the global tx_status queue + */ + + for (i = 0; i < ar->hw->queues; i++) { + while ((skb = skb_dequeue(&info->tx_status[i]))) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: queueing frame in " + "global tx_status queue =>\n", + wiphy_name(ar->hw->wiphy)); + + ar9170_print_txheader(ar, skb); +#endif /* AR9170_QUEUE_DEBUG */ + skb_queue_tail(&ar->global_tx_status, skb); + } + } + queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor, + msecs_to_jiffies(100)); + break; + + default: + break; + } +} + +static int ar9170_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ar9170 *ar = hw->priv; + u32 val; + int err; + + mutex_lock(&ar->mutex); + err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); + ar->stats.dot11ACKFailureCount += val; + + memcpy(stats, &ar->stats, sizeof(*stats)); + mutex_unlock(&ar->mutex); + + return 0; +} + +static int ar9170_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *tx_stats) +{ + struct ar9170 *ar = hw->priv; + + spin_lock_bh(&ar->tx_stats_lock); + memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); + spin_unlock_bh(&ar->tx_stats_lock); + + return 0; +} + +static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct ar9170 *ar = hw->priv; + int ret; + + mutex_lock(&ar->mutex); + if ((param) && !(queue > ar->hw->queues)) { + memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], + param, sizeof(*param)); + + ret = ar9170_set_qos(ar); + } else + ret = -EINVAL; + + mutex_unlock(&ar->mutex); + return ret; +} + +static const struct ieee80211_ops ar9170_ops = { + .start = ar9170_op_start, + .stop = ar9170_op_stop, + .tx = ar9170_op_tx, + .add_interface = ar9170_op_add_interface, + .remove_interface = ar9170_op_remove_interface, + .config = ar9170_op_config, + .config_interface = ar9170_op_config_interface, + .configure_filter = ar9170_op_configure_filter, + .conf_tx = ar9170_conf_tx, + .bss_info_changed = ar9170_op_bss_info_changed, + .get_tsf = ar9170_op_get_tsf, + .set_key = ar9170_set_key, + .sta_notify = ar9170_sta_notify, + .get_stats = ar9170_get_stats, + .get_tx_stats = ar9170_get_tx_stats, +}; + +void *ar9170_alloc(size_t priv_size) +{ + struct ieee80211_hw *hw; + struct ar9170 *ar; + int i; + + hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); + if (!hw) + return ERR_PTR(-ENOMEM); + + ar = hw->priv; + ar->hw = hw; + + mutex_init(&ar->mutex); + spin_lock_init(&ar->cmdlock); + spin_lock_init(&ar->tx_stats_lock); + skb_queue_head_init(&ar->global_tx_status); + skb_queue_head_init(&ar->global_tx_status_waste); + INIT_WORK(&ar->filter_config_work, ar9170_set_filters); + INIT_WORK(&ar->beacon_work, ar9170_new_beacon); + INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor); + + /* all hw supports 2.4 GHz, so set channel to 1 by default */ + ar->channel = &ar9170_2ghz_chantable[0]; + + /* first part of wiphy init */ + ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); + ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + + ar->hw->queues = __AR9170_NUM_TXQ; + ar->hw->extra_tx_headroom = 8; + ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); + + ar->hw->max_rates = 1; + ar->hw->max_rate_tries = 3; + + for (i = 0; i < ARRAY_SIZE(ar->noise); i++) + ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ + + return ar; +} + +static int ar9170_read_eeprom(struct ar9170 *ar) +{ +#define RW 8 /* number of words to read at once */ +#define RB (sizeof(u32) * RW) + DECLARE_MAC_BUF(mbuf); + u8 *eeprom = (void *)&ar->eeprom; + u8 *addr = ar->eeprom.mac_address; + __le32 offsets[RW]; + int i, j, err, bands = 0; + + BUILD_BUG_ON(sizeof(ar->eeprom) & 3); + + BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); +#ifndef __CHECKER__ + /* don't want to handle trailing remains */ + BUILD_BUG_ON(sizeof(ar->eeprom) % RB); +#endif + + for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { + for (j = 0; j < RW; j++) + offsets[j] = cpu_to_le32(AR9170_EEPROM_START + + RB * i + 4 * j); + + err = ar->exec_cmd(ar, AR9170_CMD_RREG, + RB, (u8 *) &offsets, + RB, eeprom + RB * i); + if (err) + return err; + } + +#undef RW +#undef RB + + if (ar->eeprom.length == cpu_to_le16(0xFFFF)) + return -ENODATA; + + if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; + bands++; + } + if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { + ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; + bands++; + } + /* + * I measured this, a bandswitch takes roughly + * 135 ms and a frequency switch about 80. + * + * FIXME: measure these values again once EEPROM settings + * are used, that will influence them! + */ + if (bands == 2) + ar->hw->channel_change_time = 135 * 1000; + else + ar->hw->channel_change_time = 80 * 1000; + + ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); + ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); + + /* second part of wiphy init */ + SET_IEEE80211_PERM_ADDR(ar->hw, addr); + + return bands ? 0 : -EINVAL; +} + +static int ar9170_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ar9170 *ar = hw->priv; + + return ath_reg_notifier_apply(wiphy, request, &ar->regulatory); +} + +int ar9170_register(struct ar9170 *ar, struct device *pdev) +{ + int err; + + /* try to read EEPROM, init MAC addr */ + err = ar9170_read_eeprom(ar); + if (err) + goto err_out; + + err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, + ar9170_reg_notifier); + + err = ieee80211_register_hw(ar->hw); + if (err) + goto err_out; + + if (!ath_is_world_regd(&ar->regulatory)) + regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); + + err = ar9170_init_leds(ar); + if (err) + goto err_unreg; + +#ifdef CONFIG_AR9170_LEDS + err = ar9170_register_leds(ar); + if (err) + goto err_unreg; +#endif /* CONFIG_AR9170_LEDS */ + + dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", + wiphy_name(ar->hw->wiphy)); + + return err; + +err_unreg: + ieee80211_unregister_hw(ar->hw); + +err_out: + return err; +} + +void ar9170_unregister(struct ar9170 *ar) +{ +#ifdef CONFIG_AR9170_LEDS + ar9170_unregister_leds(ar); +#endif /* CONFIG_AR9170_LEDS */ + + ieee80211_unregister_hw(ar->hw); + mutex_destroy(&ar->mutex); +} diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c new file mode 100644 index 000000000000..6ce20754b8e7 --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -0,0 +1,1240 @@ +/* + * Atheros AR9170 driver + * + * PHY and RF code + * + * Copyright 2008, Johannes Berg + * + * 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 +#include "ar9170.h" +#include "cmd.h" + +static int ar9170_init_power_cal(struct ar9170 *ar) +{ + ar9170_regwrite_begin(ar); + + ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); + ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); + ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +struct ar9170_phy_init { + u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; +}; + +static struct ar9170_phy_init ar5416_phy_init[] = { + { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, + { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, + { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, + { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, + { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, + { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, + { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, + { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, + { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, + { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, + { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, + { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, + { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, + { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, + { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, + { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, + { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, + { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, + { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, + { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, + { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, + { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, + { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, + { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, + { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, + { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, + { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, + { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, + { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, + { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, + { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, + { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, + { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, + { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, + { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, + { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, + { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, + { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, + { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, + { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, + { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, + { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, + { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, + { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, + { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, + { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, + { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, + { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, + { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, + { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, + { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, + { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, + { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, + { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, + { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, + { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, + { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, + { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, + { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, + { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, + { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, + { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, + { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, + { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, + { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, + { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, + { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, + { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, + { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, + { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, + { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, + { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, + { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, + { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, + { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, + { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, + { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, + { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, + { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, + { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, + { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, + { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, + { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, + { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, + { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, + { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, + { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, + { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, + { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, + { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, + { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, + { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, + { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, + { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, + { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, + { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, + { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, + { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, + { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, + { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, + { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, + { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, + { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, + { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, + { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, + { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, + { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, + { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, + { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, + { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, + { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, + { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, + { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, + { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, + { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, + { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, + { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, + { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, + { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, + { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, + { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, + { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, + { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, + { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, + { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, + { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, + { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, + { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, + { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, + { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, + { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, + { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, + { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, + { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, + { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, + { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, + { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, + { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, + { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, + { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, + { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, + { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, + { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, + { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, + { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, + { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, + { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, + { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, + { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, + { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, + { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, + { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, + { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, + { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, + { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, + { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, + { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, + { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, + { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, + { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, + { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, + { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, + { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, + { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, + { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, + { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, + { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, + { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, + { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, + { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, + { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, + { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, + { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, + { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, + { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, + { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, + { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, + { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, + { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, + { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, + { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, + { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, + { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, + { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, + { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, +/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ + { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, + { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, + { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, + { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, + { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, + { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, + { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, + { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, + { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, + { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, + { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, + { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, + { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, + { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, + { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, + { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } +}; + +int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) +{ + int i, err; + u32 val; + bool is_2ghz = band == IEEE80211_BAND_2GHZ; + bool is_40mhz = false; /* XXX: for now */ + + ar9170_regwrite_begin(ar); + + for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { + if (is_40mhz) { + if (is_2ghz) + val = ar5416_phy_init[i]._2ghz_40; + else + val = ar5416_phy_init[i]._5ghz_40; + } else { + if (is_2ghz) + val = ar5416_phy_init[i]._2ghz_20; + else + val = ar5416_phy_init[i]._5ghz_20; + } + + ar9170_regwrite(ar5416_phy_init[i].reg, val); + } + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + /* XXX: use EEPROM data here! */ + + err = ar9170_init_power_cal(ar); + if (err) + return err; + + /* XXX: remove magic! */ + if (is_2ghz) + err = ar9170_write_reg(ar, 0x1d4014, 0x5163); + else + err = ar9170_write_reg(ar, 0x1d4014, 0x5143); + + return err; +} + +struct ar9170_rf_init { + u32 reg, _5ghz, _2ghz; +}; + +static struct ar9170_rf_init ar9170_rf_init[] = { + /* bank 0 */ + { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, + { 0x1c58e0, 0x02008020, 0x02008020}, + /* bank 1 */ + { 0x1c58b0, 0x02108421, 0x02108421}, + { 0x1c58ec, 0x00000008, 0x00000008}, + /* bank 2 */ + { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, + { 0x1c58e0, 0x00000420, 0x00000420}, + /* bank 3 */ + { 0x1c58f0, 0x01400018, 0x01c00018}, + /* bank 4 */ + { 0x1c58b0, 0x000001a1, 0x000001a1}, + { 0x1c58e8, 0x00000001, 0x00000001}, + /* bank 5 */ + { 0x1c58b0, 0x00000013, 0x00000013}, + { 0x1c58e4, 0x00000002, 0x00000002}, + /* bank 6 */ + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00002c00, 0x00002c00}, + { 0x1c58b0, 0x00004800, 0x00004800}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00006000, 0x00006000}, + { 0x1c58b0, 0x00001000, 0x00001000}, + { 0x1c58b0, 0x00004000, 0x00004000}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00087c00, 0x00087c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00005400, 0x00005400}, + { 0x1c58b0, 0x00000c00, 0x00000c00}, + { 0x1c58b0, 0x00001800, 0x00001800}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00006c00, 0x00006c00}, + { 0x1c58b0, 0x00007c00, 0x00007c00}, + { 0x1c58b0, 0x00002c00, 0x00002c00}, + { 0x1c58b0, 0x00003c00, 0x00003c00}, + { 0x1c58b0, 0x00003800, 0x00003800}, + { 0x1c58b0, 0x00001c00, 0x00001c00}, + { 0x1c58b0, 0x00000800, 0x00000800}, + { 0x1c58b0, 0x00000408, 0x00000408}, + { 0x1c58b0, 0x00004c15, 0x00004c15}, + { 0x1c58b0, 0x00004188, 0x00004188}, + { 0x1c58b0, 0x0000201e, 0x0000201e}, + { 0x1c58b0, 0x00010408, 0x00010408}, + { 0x1c58b0, 0x00000801, 0x00000801}, + { 0x1c58b0, 0x00000c08, 0x00000c08}, + { 0x1c58b0, 0x0000181e, 0x0000181e}, + { 0x1c58b0, 0x00001016, 0x00001016}, + { 0x1c58b0, 0x00002800, 0x00002800}, + { 0x1c58b0, 0x00004010, 0x00004010}, + { 0x1c58b0, 0x0000081c, 0x0000081c}, + { 0x1c58b0, 0x00000115, 0x00000115}, + { 0x1c58b0, 0x00000015, 0x00000015}, + { 0x1c58b0, 0x00000066, 0x00000066}, + { 0x1c58b0, 0x0000001c, 0x0000001c}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000004, 0x00000004}, + { 0x1c58b0, 0x00000015, 0x00000015}, + { 0x1c58b0, 0x0000001f, 0x0000001f}, + { 0x1c58e0, 0x00000000, 0x00000400}, + /* bank 7 */ + { 0x1c58b0, 0x000000a0, 0x000000a0}, + { 0x1c58b0, 0x00000000, 0x00000000}, + { 0x1c58b0, 0x00000040, 0x00000040}, + { 0x1c58f0, 0x0000001c, 0x0000001c}, +}; + +static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) +{ + int err, i; + + ar9170_regwrite_begin(ar); + + for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) + ar9170_regwrite(ar9170_rf_init[i].reg, + band5ghz ? ar9170_rf_init[i]._5ghz + : ar9170_rf_init[i]._2ghz); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + printk(KERN_ERR "%s: rf init failed\n", + wiphy_name(ar->hw->wiphy)); + return err; +} + +static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, + u32 freq, enum ar9170_bw bw) +{ + int err; + u32 d0, d1, td0, td1, fd0, fd1; + u8 chansel; + u8 refsel0 = 1, refsel1 = 0; + u8 lf_synth = 0; + + switch (bw) { + case AR9170_BW_40_ABOVE: + freq += 10; + break; + case AR9170_BW_40_BELOW: + freq -= 10; + break; + case AR9170_BW_20: + break; + case __AR9170_NUM_BW: + BUG(); + } + + if (band5ghz) { + if (freq % 10) { + chansel = (freq - 4800) / 5; + } else { + chansel = ((freq - 4800) / 10) * 2; + refsel0 = 0; + refsel1 = 1; + } + chansel = byte_rev_table[chansel]; + } else { + if (freq == 2484) { + chansel = 10 + (freq - 2274) / 5; + lf_synth = 1; + } else + chansel = 16 + (freq - 2272) / 5; + chansel *= 4; + chansel = byte_rev_table[chansel]; + } + + d1 = chansel; + d0 = 0x21 | + refsel0 << 3 | + refsel1 << 2 | + lf_synth << 1; + td0 = d0 & 0x1f; + td1 = d1 & 0x1f; + fd0 = td1 << 5 | td0; + + td0 = (d0 >> 5) & 0x7; + td1 = (d1 >> 5) & 0x7; + fd1 = td1 << 5 | td0; + + ar9170_regwrite_begin(ar); + + ar9170_regwrite(0x1c58b0, fd0); + ar9170_regwrite(0x1c58e8, fd1); + + ar9170_regwrite_finish(); + err = ar9170_regwrite_result(); + if (err) + return err; + + msleep(10); + + return 0; +} + +struct ar9170_phy_freq_params { + u8 coeff_exp; + u16 coeff_man; + u8 coeff_exp_shgi; + u16 coeff_man_shgi; +}; + +struct ar9170_phy_freq_entry { + u16 freq; + struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; +}; + +/* NB: must be in sync with channel tables in main! */ +static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { +/* + * freq, + * 20MHz, + * 40MHz (below), + * 40Mhz (above), + */ + { 2412, { + { 3, 21737, 3, 19563, }, + { 3, 21827, 3, 19644, }, + { 3, 21647, 3, 19482, }, + } }, + { 2417, { + { 3, 21692, 3, 19523, }, + { 3, 21782, 3, 19604, }, + { 3, 21602, 3, 19442, }, + } }, + { 2422, { + { 3, 21647, 3, 19482, }, + { 3, 21737, 3, 19563, }, + { 3, 21558, 3, 19402, }, + } }, + { 2427, { + { 3, 21602, 3, 19442, }, + { 3, 21692, 3, 19523, }, + { 3, 21514, 3, 19362, }, + } }, + { 2432, { + { 3, 21558, 3, 19402, }, + { 3, 21647, 3, 19482, }, + { 3, 21470, 3, 19323, }, + } }, + { 2437, { + { 3, 21514, 3, 19362, }, + { 3, 21602, 3, 19442, }, + { 3, 21426, 3, 19283, }, + } }, + { 2442, { + { 3, 21470, 3, 19323, }, + { 3, 21558, 3, 19402, }, + { 3, 21382, 3, 19244, }, + } }, + { 2447, { + { 3, 21426, 3, 19283, }, + { 3, 21514, 3, 19362, }, + { 3, 21339, 3, 19205, }, + } }, + { 2452, { + { 3, 21382, 3, 19244, }, + { 3, 21470, 3, 19323, }, + { 3, 21295, 3, 19166, }, + } }, + { 2457, { + { 3, 21339, 3, 19205, }, + { 3, 21426, 3, 19283, }, + { 3, 21252, 3, 19127, }, + } }, + { 2462, { + { 3, 21295, 3, 19166, }, + { 3, 21382, 3, 19244, }, + { 3, 21209, 3, 19088, }, + } }, + { 2467, { + { 3, 21252, 3, 19127, }, + { 3, 21339, 3, 19205, }, + { 3, 21166, 3, 19050, }, + } }, + { 2472, { + { 3, 21209, 3, 19088, }, + { 3, 21295, 3, 19166, }, + { 3, 21124, 3, 19011, }, + } }, + { 2484, { + { 3, 21107, 3, 18996, }, + { 3, 21192, 3, 19073, }, + { 3, 21022, 3, 18920, }, + } }, + { 4920, { + { 4, 21313, 4, 19181, }, + { 4, 21356, 4, 19220, }, + { 4, 21269, 4, 19142, }, + } }, + { 4940, { + { 4, 21226, 4, 19104, }, + { 4, 21269, 4, 19142, }, + { 4, 21183, 4, 19065, }, + } }, + { 4960, { + { 4, 21141, 4, 19027, }, + { 4, 21183, 4, 19065, }, + { 4, 21098, 4, 18988, }, + } }, + { 4980, { + { 4, 21056, 4, 18950, }, + { 4, 21098, 4, 18988, }, + { 4, 21014, 4, 18912, }, + } }, + { 5040, { + { 4, 20805, 4, 18725, }, + { 4, 20846, 4, 18762, }, + { 4, 20764, 4, 18687, }, + } }, + { 5060, { + { 4, 20723, 4, 18651, }, + { 4, 20764, 4, 18687, }, + { 4, 20682, 4, 18614, }, + } }, + { 5080, { + { 4, 20641, 4, 18577, }, + { 4, 20682, 4, 18614, }, + { 4, 20601, 4, 18541, }, + } }, + { 5180, { + { 4, 20243, 4, 18219, }, + { 4, 20282, 4, 18254, }, + { 4, 20204, 4, 18183, }, + } }, + { 5200, { + { 4, 20165, 4, 18148, }, + { 4, 20204, 4, 18183, }, + { 4, 20126, 4, 18114, }, + } }, + { 5220, { + { 4, 20088, 4, 18079, }, + { 4, 20126, 4, 18114, }, + { 4, 20049, 4, 18044, }, + } }, + { 5240, { + { 4, 20011, 4, 18010, }, + { 4, 20049, 4, 18044, }, + { 4, 19973, 4, 17976, }, + } }, + { 5260, { + { 4, 19935, 4, 17941, }, + { 4, 19973, 4, 17976, }, + { 4, 19897, 4, 17907, }, + } }, + { 5280, { + { 4, 19859, 4, 17873, }, + { 4, 19897, 4, 17907, }, + { 4, 19822, 4, 17840, }, + } }, + { 5300, { + { 4, 19784, 4, 17806, }, + { 4, 19822, 4, 17840, }, + { 4, 19747, 4, 17772, }, + } }, + { 5320, { + { 4, 19710, 4, 17739, }, + { 4, 19747, 4, 17772, }, + { 4, 19673, 4, 17706, }, + } }, + { 5500, { + { 4, 19065, 4, 17159, }, + { 4, 19100, 4, 17190, }, + { 4, 19030, 4, 17127, }, + } }, + { 5520, { + { 4, 18996, 4, 17096, }, + { 4, 19030, 4, 17127, }, + { 4, 18962, 4, 17065, }, + } }, + { 5540, { + { 4, 18927, 4, 17035, }, + { 4, 18962, 4, 17065, }, + { 4, 18893, 4, 17004, }, + } }, + { 5560, { + { 4, 18859, 4, 16973, }, + { 4, 18893, 4, 17004, }, + { 4, 18825, 4, 16943, }, + } }, + { 5580, { + { 4, 18792, 4, 16913, }, + { 4, 18825, 4, 16943, }, + { 4, 18758, 4, 16882, }, + } }, + { 5600, { + { 4, 18725, 4, 16852, }, + { 4, 18758, 4, 16882, }, + { 4, 18691, 4, 16822, }, + } }, + { 5620, { + { 4, 18658, 4, 16792, }, + { 4, 18691, 4, 16822, }, + { 4, 18625, 4, 16762, }, + } }, + { 5640, { + { 4, 18592, 4, 16733, }, + { 4, 18625, 4, 16762, }, + { 4, 18559, 4, 16703, }, + } }, + { 5660, { + { 4, 18526, 4, 16673, }, + { 4, 18559, 4, 16703, }, + { 4, 18493, 4, 16644, }, + } }, + { 5680, { + { 4, 18461, 4, 16615, }, + { 4, 18493, 4, 16644, }, + { 4, 18428, 4, 16586, }, + } }, + { 5700, { + { 4, 18396, 4, 16556, }, + { 4, 18428, 4, 16586, }, + { 4, 18364, 4, 16527, }, + } }, + { 5745, { + { 4, 18252, 4, 16427, }, + { 4, 18284, 4, 16455, }, + { 4, 18220, 4, 16398, }, + } }, + { 5765, { + { 4, 18189, 5, 32740, }, + { 4, 18220, 4, 16398, }, + { 4, 18157, 5, 32683, }, + } }, + { 5785, { + { 4, 18126, 5, 32626, }, + { 4, 18157, 5, 32683, }, + { 4, 18094, 5, 32570, }, + } }, + { 5805, { + { 4, 18063, 5, 32514, }, + { 4, 18094, 5, 32570, }, + { 4, 18032, 5, 32458, }, + } }, + { 5825, { + { 4, 18001, 5, 32402, }, + { 4, 18032, 5, 32458, }, + { 4, 17970, 5, 32347, }, + } }, + { 5170, { + { 4, 20282, 4, 18254, }, + { 4, 20321, 4, 18289, }, + { 4, 20243, 4, 18219, }, + } }, + { 5190, { + { 4, 20204, 4, 18183, }, + { 4, 20243, 4, 18219, }, + { 4, 20165, 4, 18148, }, + } }, + { 5210, { + { 4, 20126, 4, 18114, }, + { 4, 20165, 4, 18148, }, + { 4, 20088, 4, 18079, }, + } }, + { 5230, { + { 4, 20049, 4, 18044, }, + { 4, 20088, 4, 18079, }, + { 4, 20011, 4, 18010, }, + } }, +}; + +static const struct ar9170_phy_freq_params * +ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, + enum ar9170_bw bw) +{ + unsigned int chanidx = 0; + u16 freq = 2412; + + if (channel) { + chanidx = channel->hw_value; + freq = channel->center_freq; + } + + BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); + + BUILD_BUG_ON(__AR9170_NUM_BW != 3); + + WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); + + return &ar9170_phy_freq_params[chanidx].params[bw]; +} + + +int ar9170_init_rf(struct ar9170 *ar) +{ + const struct ar9170_phy_freq_params *freqpar; + __le32 cmd[7]; + int err; + + err = ar9170_init_rf_banks_0_7(ar, false); + if (err) + return err; + + err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); + if (err) + return err; + + freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); + + cmd[0] = cpu_to_le32(2412 * 1000); + cmd[1] = cpu_to_le32(0); + cmd[2] = cpu_to_le32(1); + cmd[3] = cpu_to_le32(freqpar->coeff_exp); + cmd[4] = cpu_to_le32(freqpar->coeff_man); + cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); + cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); + + /* RF_INIT echoes the command back to us */ + err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, + sizeof(cmd), (u8 *)cmd, + sizeof(cmd), (u8 *)cmd); + if (err) + return err; + + msleep(1000); + + return ar9170_echo_test(ar, 0xaabbccdd); +} + +static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) +{ + int idx = nfreqs - 2; + + while (idx >= 0) { + if (f >= freqs[idx]) + return idx; + idx--; + } + + return 0; +} + +static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) +{ + /* nothing to interpolate, it's horizontal */ + if (y2 == y1) + return y1; + + /* check if we hit one of the edges */ + if (x == x1) + return y1; + if (x == x2) + return y2; + + /* x1 == x2 is bad, hopefully == x */ + if (x2 == x1) + return y1; + + return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); +} + +static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) +{ +#define SHIFT 8 + s32 y; + + y = ar9170_interpolate_s32(x << SHIFT, + x1 << SHIFT, y1 << SHIFT, + x2 << SHIFT, y2 << SHIFT); + + /* + * XXX: unwrap this expression + * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); +#undef SHIFT +} + +static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) +{ + struct ar9170_calibration_target_power_legacy *ctpl; + struct ar9170_calibration_target_power_ht *ctph; + u8 *ctpres; + int ntargets; + int idx, i, n; + u8 ackpower, ackchains, f; + u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; + + if (freq < 3000) + f = freq - 2300; + else + f = (freq - 4800)/5; + + /* + * cycle through the various modes + * + * legacy modes first: 5G, 2G CCK, 2G OFDM + */ + for (i = 0; i < 3; i++) { + switch (i) { + case 0: /* 5 GHz legacy */ + ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_leg; + break; + case 1: /* 2.4 GHz CCK */ + ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; + ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; + ctpres = ar->power_2G_cck; + break; + case 2: /* 2.4 GHz OFDM */ + ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ofdm; + break; + default: + BUG(); + } + + for (n = 0; n < ntargets; n++) { + if (ctpl[n].freq == 0xff) + break; + pwr_freqs[n] = ctpl[n].freq; + } + ntargets = n; + idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); + for (n = 0; n < 4; n++) + ctpres[n] = ar9170_interpolate_u8( + f, + ctpl[idx + 0].freq, + ctpl[idx + 0].power[n], + ctpl[idx + 1].freq, + ctpl[idx + 1].power[n]); + } + + /* + * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 + */ + for (i = 0; i < 4; i++) { + switch (i) { + case 0: /* 5 GHz HT 20 */ + ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_ht20; + break; + case 1: /* 5 GHz HT 40 */ + ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; + ntargets = AR5416_NUM_5G_TARGET_PWRS; + ctpres = ar->power_5G_ht40; + break; + case 2: /* 2.4 GHz HT 20 */ + ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ht20; + break; + case 3: /* 2.4 GHz HT 40 */ + ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; + ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; + ctpres = ar->power_2G_ht40; + break; + default: + BUG(); + } + + for (n = 0; n < ntargets; n++) { + if (ctph[n].freq == 0xff) + break; + pwr_freqs[n] = ctph[n].freq; + } + ntargets = n; + idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); + for (n = 0; n < 8; n++) + ctpres[n] = ar9170_interpolate_u8( + f, + ctph[idx + 0].freq, + ctph[idx + 0].power[n], + ctph[idx + 1].freq, + ctph[idx + 1].power[n]); + } + + /* set ACK/CTS TX power */ + ar9170_regwrite_begin(ar); + + if (ar->eeprom.tx_mask != 1) + ackchains = AR9170_TX_PHY_TXCHAIN_2; + else + ackchains = AR9170_TX_PHY_TXCHAIN_1; + + if (freq < 3000) + ackpower = ar->power_2G_ofdm[0] & 0x3f; + else + ackpower = ar->power_5G_leg[0] & 0x3f; + + ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); + ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | + ackpower << 21 | ackchains << 27); + + ar9170_regwrite_finish(); + return ar9170_regwrite_result(); +} + +static int ar9170_calc_noise_dbm(u32 raw_noise) +{ + if (raw_noise & 0x100) + return ~((raw_noise & 0x0ff) >> 1); + else + return (raw_noise & 0xff) >> 1; +} + +int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, + enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) +{ + const struct ar9170_phy_freq_params *freqpar; + u32 cmd, tmp, offs; + __le32 vals[8]; + int i, err; + bool bandswitch; + + /* clear BB heavy clip enable */ + err = ar9170_write_reg(ar, 0x1c59e0, 0x200); + if (err) + return err; + + /* may be NULL at first setup */ + if (ar->channel) + bandswitch = ar->channel->band != channel->band; + else + bandswitch = true; + + /* HW workaround */ + if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && + channel->center_freq <= 2417) + bandswitch = true; + + err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); + if (err) + return err; + + if (rfi != AR9170_RFI_NONE || bandswitch) { + u32 val = 0x400; + + if (rfi == AR9170_RFI_COLD) + val = 0x800; + + /* warm/cold reset BB/ADDA */ + err = ar9170_write_reg(ar, 0x1d4004, val); + if (err) + return err; + + err = ar9170_write_reg(ar, 0x1d4004, 0x0); + if (err) + return err; + + err = ar9170_init_phy(ar, channel->band); + if (err) + return err; + + err = ar9170_init_rf_banks_0_7(ar, + channel->band == IEEE80211_BAND_5GHZ); + if (err) + return err; + + cmd = AR9170_CMD_RF_INIT; + } else { + cmd = AR9170_CMD_FREQUENCY; + } + + err = ar9170_init_rf_bank4_pwr(ar, + channel->band == IEEE80211_BAND_5GHZ, + channel->center_freq, bw); + if (err) + return err; + + switch (bw) { + case AR9170_BW_20: + tmp = 0x240; + offs = 0; + break; + case AR9170_BW_40_BELOW: + tmp = 0x2c4; + offs = 3; + break; + case AR9170_BW_40_ABOVE: + tmp = 0x2d4; + offs = 1; + break; + default: + BUG(); + return -ENOSYS; + } + + if (0 /* 2 streams capable */) + tmp |= 0x100; + + err = ar9170_write_reg(ar, 0x1c5804, tmp); + if (err) + return err; + + err = ar9170_set_power_cal(ar, channel->center_freq, bw); + if (err) + return err; + + freqpar = ar9170_get_hw_dyn_params(channel, bw); + + vals[0] = cpu_to_le32(channel->center_freq * 1000); + vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1); + vals[2] = cpu_to_le32(offs << 2 | 1); + vals[3] = cpu_to_le32(freqpar->coeff_exp); + vals[4] = cpu_to_le32(freqpar->coeff_man); + vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); + vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); + vals[7] = cpu_to_le32(1000); + + err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, + sizeof(vals), (u8 *)vals); + if (err) + return err; + + for (i = 0; i < 2; i++) { + ar->noise[i] = ar9170_calc_noise_dbm( + (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); + + ar->noise[i + 2] = ar9170_calc_noise_dbm( + (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); + } + + ar->channel = channel; + return 0; +} diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c new file mode 100644 index 000000000000..fddda477095c --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -0,0 +1,822 @@ +/* + * Atheros AR9170 driver + * + * USB - frontend + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * 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 +#include +#include +#include +#include +#include "ar9170.h" +#include "cmd.h" +#include "hw.h" +#include "usb.h" + +MODULE_AUTHOR("Johannes Berg "); +MODULE_AUTHOR("Christian Lamparter "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); +MODULE_FIRMWARE("ar9170-1.fw"); +MODULE_FIRMWARE("ar9170-2.fw"); + +static struct usb_device_id ar9170_usb_ids[] = { + /* Atheros 9170 */ + { USB_DEVICE(0x0cf3, 0x9170) }, + /* Atheros TG121N */ + { USB_DEVICE(0x0cf3, 0x1001) }, + /* Cace Airpcap NX */ + { USB_DEVICE(0xcace, 0x0300) }, + /* D-Link DWA 160A */ + { USB_DEVICE(0x07d1, 0x3c10) }, + /* Netgear WNDA3100 */ + { USB_DEVICE(0x0846, 0x9010) }, + /* Netgear WN111 v2 */ + { USB_DEVICE(0x0846, 0x9001) }, + /* Zydas ZD1221 */ + { USB_DEVICE(0x0ace, 0x1221) }, + /* ZyXEL NWD271N */ + { USB_DEVICE(0x0586, 0x3417) }, + /* Z-Com UB81 BG */ + { USB_DEVICE(0x0cde, 0x0023) }, + /* Z-Com UB82 ABG */ + { USB_DEVICE(0x0cde, 0x0026) }, + /* Arcadyan WN7512 */ + { USB_DEVICE(0x083a, 0xf522) }, + /* Planex GWUS300 */ + { USB_DEVICE(0x2019, 0x5304) }, + /* IO-Data WNGDNUS2 */ + { USB_DEVICE(0x04bb, 0x093f) }, + + /* terminate */ + {} +}; +MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); + +static void ar9170_usb_tx_urb_complete_free(struct urb *urb) +{ + struct sk_buff *skb = urb->context; + struct ar9170_usb *aru = (struct ar9170_usb *) + usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + + if (!aru) { + dev_kfree_skb_irq(skb); + return ; + } + + ar9170_handle_tx_status(&aru->common, skb, false, + AR9170_TX_STATUS_COMPLETE); +} + +static void ar9170_usb_tx_urb_complete(struct urb *urb) +{ +} + +static void ar9170_usb_irq_completed(struct urb *urb) +{ + struct ar9170_usb *aru = urb->context; + + switch (urb->status) { + /* everything is fine */ + case 0: + break; + + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + + default: + goto resubmit; + } + + print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET, + urb->transfer_buffer, urb->actual_length); + +resubmit: + usb_anchor_urb(urb, &aru->rx_submitted); + if (usb_submit_urb(urb, GFP_ATOMIC)) { + usb_unanchor_urb(urb); + goto free; + } + + return; + +free: + usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); +} + +static void ar9170_usb_rx_completed(struct urb *urb) +{ + struct sk_buff *skb = urb->context; + struct ar9170_usb *aru = (struct ar9170_usb *) + usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); + int err; + + if (!aru) + goto free; + + switch (urb->status) { + /* everything is fine */ + case 0: + break; + + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + + default: + goto resubmit; + } + + skb_put(skb, urb->actual_length); + ar9170_rx(&aru->common, skb); + +resubmit: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + usb_unanchor_urb(urb); + dev_kfree_skb_irq(skb); + } + + return ; + +free: + dev_kfree_skb_irq(skb); + return; +} + +static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, + struct urb *urb, gfp_t gfp) +{ + struct sk_buff *skb; + + skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); + if (!skb) + return -ENOMEM; + + /* reserve some space for mac80211's radiotap */ + skb_reserve(skb, 32); + + usb_fill_bulk_urb(urb, aru->udev, + usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), + skb->data, min(skb_tailroom(skb), + AR9170_MAX_RX_BUFFER_SIZE), + ar9170_usb_rx_completed, skb); + + return 0; +} + +static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) +{ + struct urb *urb = NULL; + void *ibuf; + int err = -ENOMEM; + + /* initialize interrupt endpoint */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto out; + + ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); + if (!ibuf) + goto out; + + usb_fill_int_urb(urb, aru->udev, + usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, + 64, ar9170_usb_irq_completed, aru, 1); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + usb_unanchor_urb(urb); + usb_buffer_free(aru->udev, 64, urb->transfer_buffer, + urb->transfer_dma); + } + +out: + usb_free_urb(urb); + return err; +} + +static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) +{ + struct urb *urb; + int i; + int err = -EINVAL; + + for (i = 0; i < AR9170_NUM_RX_URBS; i++) { + err = -ENOMEM; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + goto err_out; + + err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); + if (err) { + usb_free_urb(urb); + goto err_out; + } + + usb_anchor_urb(urb, &aru->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + usb_unanchor_urb(urb); + dev_kfree_skb_any((void *) urb->transfer_buffer); + usb_free_urb(urb); + goto err_out; + } + usb_free_urb(urb); + } + + /* the device now waiting for a firmware. */ + aru->common.state = AR9170_IDLE; + return 0; + +err_out: + + usb_kill_anchored_urbs(&aru->rx_submitted); + return err; +} + +static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) +{ + int ret; + + aru->common.state = AR9170_UNKNOWN_STATE; + + usb_unlink_anchored_urbs(&aru->tx_submitted); + + /* give the LED OFF command and the deauth frame a chance to air. */ + ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, + msecs_to_jiffies(100)); + if (ret == 0) + dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); + usb_poison_anchored_urbs(&aru->tx_submitted); + + usb_poison_anchored_urbs(&aru->rx_submitted); +} + +static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, + unsigned int plen, void *payload, + unsigned int outlen, void *out) +{ + struct ar9170_usb *aru = (void *) ar; + struct urb *urb = NULL; + unsigned long flags; + int err = -ENOMEM; + + if (unlikely(!IS_ACCEPTING_CMD(ar))) + return -EPERM; + + if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) + return -EINVAL; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (unlikely(!urb)) + goto err_free; + + ar->cmdbuf[0] = cpu_to_le32(plen); + ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); + /* writing multiple regs fills this buffer already */ + if (plen && payload != (u8 *)(&ar->cmdbuf[1])) + memcpy(&ar->cmdbuf[1], payload, plen); + + spin_lock_irqsave(&aru->common.cmdlock, flags); + aru->readbuf = (u8 *)out; + aru->readlen = outlen; + spin_unlock_irqrestore(&aru->common.cmdlock, flags); + + usb_fill_int_urb(urb, aru->udev, + usb_sndbulkpipe(aru->udev, AR9170_EP_CMD), + aru->common.cmdbuf, plen + 4, + ar9170_usb_tx_urb_complete, NULL, 1); + + usb_anchor_urb(urb, &aru->tx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + usb_unanchor_urb(urb); + usb_free_urb(urb); + goto err_unbuf; + } + usb_free_urb(urb); + + err = wait_for_completion_timeout(&aru->cmd_wait, HZ); + if (err == 0) { + err = -ETIMEDOUT; + goto err_unbuf; + } + + if (outlen >= 0 && aru->readlen != outlen) { + err = -EMSGSIZE; + goto err_unbuf; + } + + return 0; + +err_unbuf: + /* Maybe the device was removed in the second we were waiting? */ + if (IS_STARTED(ar)) { + dev_err(&aru->udev->dev, "no command feedback " + "received (%d).\n", err); + + /* provide some maybe useful debug information */ + print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, + aru->common.cmdbuf, plen + 4); + dump_stack(); + } + + /* invalidate to avoid completing the next prematurely */ + spin_lock_irqsave(&aru->common.cmdlock, flags); + aru->readbuf = NULL; + aru->readlen = 0; + spin_unlock_irqrestore(&aru->common.cmdlock, flags); + +err_free: + + return err; +} + +static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb, + bool txstatus_needed, unsigned int extra_len) +{ + struct ar9170_usb *aru = (struct ar9170_usb *) ar; + struct urb *urb; + int err; + + if (unlikely(!IS_STARTED(ar))) { + /* Seriously, what were you drink... err... thinking!? */ + return -EPERM; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (unlikely(!urb)) + return -ENOMEM; + + usb_fill_bulk_urb(urb, aru->udev, + usb_sndbulkpipe(aru->udev, AR9170_EP_TX), + skb->data, skb->len + extra_len, (txstatus_needed ? + ar9170_usb_tx_urb_complete : + ar9170_usb_tx_urb_complete_free), skb); + urb->transfer_flags |= URB_ZERO_PACKET; + + usb_anchor_urb(urb, &aru->tx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (unlikely(err)) + usb_unanchor_urb(urb); + + usb_free_urb(urb); + return err; +} + +static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) +{ + struct ar9170_usb *aru = (void *) ar; + unsigned long flags; + u32 in, out; + + if (!buffer) + return ; + + in = le32_to_cpup((__le32 *)buffer); + out = le32_to_cpu(ar->cmdbuf[0]); + + /* mask off length byte */ + out &= ~0xFF; + + if (aru->readlen >= 0) { + /* add expected length */ + out |= aru->readlen; + } else { + /* add obtained length */ + out |= in & 0xFF; + } + + /* + * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response + * length and we cannot predict the correct length in advance. + * So we only check if we provided enough space for the data. + */ + if (unlikely(out < in)) { + dev_warn(&aru->udev->dev, "received invalid command response " + "got %d bytes, instead of %d bytes " + "and the resp length is %d bytes\n", + in, out, len); + print_hex_dump_bytes("ar9170 invalid resp: ", + DUMP_PREFIX_OFFSET, buffer, len); + /* + * Do not complete, then the command times out, + * and we get a stack trace from there. + */ + return ; + } + + spin_lock_irqsave(&aru->common.cmdlock, flags); + if (aru->readbuf && len > 0) { + memcpy(aru->readbuf, buffer + 4, len - 4); + aru->readbuf = NULL; + } + complete(&aru->cmd_wait); + spin_unlock_irqrestore(&aru->common.cmdlock, flags); +} + +static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, + size_t len, u32 addr, bool complete) +{ + int transfer, err; + u8 *buf = kmalloc(4096, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + while (len) { + transfer = min_t(int, len, 4096); + memcpy(buf, data, transfer); + + err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), + 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, + addr >> 8, 0, buf, transfer, 1000); + + if (err < 0) { + kfree(buf); + return err; + } + + len -= transfer; + data += transfer; + addr += transfer; + } + kfree(buf); + + if (complete) { + err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), + 0x31 /* FW DL COMPLETE */, + 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); + } + + return 0; +} + +static int ar9170_usb_request_firmware(struct ar9170_usb *aru) +{ + int err = 0; + + err = request_firmware(&aru->init_values, "ar9170-1.fw", + &aru->udev->dev); + if (err) { + dev_err(&aru->udev->dev, "file with init values not found.\n"); + return err; + } + + err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); + if (err) { + release_firmware(aru->init_values); + dev_err(&aru->udev->dev, "firmware file not found.\n"); + return err; + } + + return err; +} + +static int ar9170_usb_reset(struct ar9170_usb *aru) +{ + int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); + + if (lock) { + ret = usb_lock_device_for_reset(aru->udev, aru->intf); + if (ret < 0) { + dev_err(&aru->udev->dev, "unable to lock device " + "for reset (%d).\n", ret); + return ret; + } + } + + ret = usb_reset_device(aru->udev); + if (lock) + usb_unlock_device(aru->udev); + + /* let it rest - for a second - */ + msleep(1000); + + return ret; +} + +static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) +{ + int err; + + /* First, upload initial values to device RAM */ + err = ar9170_usb_upload(aru, aru->init_values->data, + aru->init_values->size, 0x102800, false); + if (err) { + dev_err(&aru->udev->dev, "firmware part 1 " + "upload failed (%d).\n", err); + return err; + } + + /* Then, upload the firmware itself and start it */ + return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, + 0x200000, true); +} + +static int ar9170_usb_init_transport(struct ar9170_usb *aru) +{ + struct ar9170 *ar = (void *) &aru->common; + int err; + + ar9170_regwrite_begin(ar); + + /* Set USB Rx stream mode MAX packet number to 2 */ + ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); + + /* Set USB Rx stream mode timeout to 10us */ + ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); + + ar9170_regwrite_finish(); + + err = ar9170_regwrite_result(); + if (err) + dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); + + return err; +} + +static void ar9170_usb_stop(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + int ret; + + if (IS_ACCEPTING_CMD(ar)) + aru->common.state = AR9170_STOPPED; + + /* lets wait a while until the tx - queues are dried out */ + ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, + msecs_to_jiffies(1000)); + if (ret == 0) + dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); + + usb_poison_anchored_urbs(&aru->tx_submitted); + + /* + * Note: + * So far we freed all tx urbs, but we won't dare to touch any rx urbs. + * Else we would end up with a unresponsive device... + */ +} + +static int ar9170_usb_open(struct ar9170 *ar) +{ + struct ar9170_usb *aru = (void *) ar; + int err; + + usb_unpoison_anchored_urbs(&aru->tx_submitted); + err = ar9170_usb_init_transport(aru); + if (err) { + usb_poison_anchored_urbs(&aru->tx_submitted); + return err; + } + + aru->common.state = AR9170_IDLE; + return 0; +} + +static int ar9170_usb_init_device(struct ar9170_usb *aru) +{ + int err; + + err = ar9170_usb_alloc_rx_irq_urb(aru); + if (err) + goto err_out; + + err = ar9170_usb_alloc_rx_bulk_urbs(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_upload_firmware(aru); + if (err) { + err = ar9170_echo_test(&aru->common, 0x60d43110); + if (err) { + /* force user invention, by disabling the device */ + err = usb_driver_set_configuration(aru->udev, -1); + dev_err(&aru->udev->dev, "device is in a bad state. " + "please reconnect it!\n"); + goto err_unrx; + } + } + + return 0; + +err_unrx: + ar9170_usb_cancel_urbs(aru); + +err_out: + return err; +} + +static int ar9170_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct ar9170_usb *aru; + struct ar9170 *ar; + struct usb_device *udev; + int err; + + aru = ar9170_alloc(sizeof(*aru)); + if (IS_ERR(aru)) { + err = PTR_ERR(aru); + goto out; + } + + udev = interface_to_usbdev(intf); + usb_get_dev(udev); + aru->udev = udev; + aru->intf = intf; + ar = &aru->common; + + usb_set_intfdata(intf, aru); + SET_IEEE80211_DEV(ar->hw, &udev->dev); + + init_usb_anchor(&aru->rx_submitted); + init_usb_anchor(&aru->tx_submitted); + init_completion(&aru->cmd_wait); + + aru->common.stop = ar9170_usb_stop; + aru->common.open = ar9170_usb_open; + aru->common.tx = ar9170_usb_tx; + aru->common.exec_cmd = ar9170_usb_exec_cmd; + aru->common.callback_cmd = ar9170_usb_callback_cmd; + + err = ar9170_usb_reset(aru); + if (err) + goto err_freehw; + + err = ar9170_usb_request_firmware(aru); + if (err) + goto err_freehw; + + err = ar9170_usb_init_device(aru); + if (err) + goto err_freefw; + + err = ar9170_usb_open(ar); + if (err) + goto err_unrx; + + err = ar9170_register(ar, &udev->dev); + + ar9170_usb_stop(ar); + if (err) + goto err_unrx; + + return 0; + +err_unrx: + ar9170_usb_cancel_urbs(aru); + +err_freefw: + release_firmware(aru->init_values); + release_firmware(aru->firmware); + +err_freehw: + usb_set_intfdata(intf, NULL); + usb_put_dev(udev); + ieee80211_free_hw(ar->hw); +out: + return err; +} + +static void ar9170_usb_disconnect(struct usb_interface *intf) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + + if (!aru) + return; + + aru->common.state = AR9170_IDLE; + ar9170_unregister(&aru->common); + ar9170_usb_cancel_urbs(aru); + + release_firmware(aru->init_values); + release_firmware(aru->firmware); + + usb_put_dev(aru->udev); + usb_set_intfdata(intf, NULL); + ieee80211_free_hw(aru->common.hw); +} + +#ifdef CONFIG_PM +static int ar9170_suspend(struct usb_interface *intf, + pm_message_t message) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + + if (!aru) + return -ENODEV; + + aru->common.state = AR9170_IDLE; + ar9170_usb_cancel_urbs(aru); + + return 0; +} + +static int ar9170_resume(struct usb_interface *intf) +{ + struct ar9170_usb *aru = usb_get_intfdata(intf); + int err; + + if (!aru) + return -ENODEV; + + usb_unpoison_anchored_urbs(&aru->rx_submitted); + usb_unpoison_anchored_urbs(&aru->tx_submitted); + + /* + * FIXME: firmware upload will fail on resume. + * but this is better than a hang! + */ + + err = ar9170_usb_init_device(aru); + if (err) + goto err_unrx; + + err = ar9170_usb_open(&aru->common); + if (err) + goto err_unrx; + + return 0; + +err_unrx: + aru->common.state = AR9170_IDLE; + ar9170_usb_cancel_urbs(aru); + + return err; +} +#endif /* CONFIG_PM */ + +static struct usb_driver ar9170_driver = { + .name = "ar9170usb", + .probe = ar9170_usb_probe, + .disconnect = ar9170_usb_disconnect, + .id_table = ar9170_usb_ids, + .soft_unbind = 1, +#ifdef CONFIG_PM + .suspend = ar9170_suspend, + .resume = ar9170_resume, +#endif /* CONFIG_PM */ +}; + +static int __init ar9170_init(void) +{ + return usb_register(&ar9170_driver); +} + +static void __exit ar9170_exit(void) +{ + usb_deregister(&ar9170_driver); +} + +module_init(ar9170_init); +module_exit(ar9170_exit); diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h new file mode 100644 index 000000000000..f5852924cd64 --- /dev/null +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -0,0 +1,74 @@ +/* + * Atheros AR9170 USB driver + * + * Driver specific definitions + * + * Copyright 2008, Johannes Berg + * Copyright 2009, Christian Lamparter + * + * 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 __USB_H +#define __USB_H + +#include +#include +#include +#include +#include +#include +#include +#include "eeprom.h" +#include "hw.h" +#include "ar9170.h" + +#define AR9170_NUM_RX_URBS 16 + +struct firmware; + +struct ar9170_usb { + struct ar9170 common; + struct usb_device *udev; + struct usb_interface *intf; + + struct usb_anchor rx_submitted; + struct usb_anchor tx_submitted; + + spinlock_t cmdlock; + struct completion cmd_wait; + int readlen; + u8 *readbuf; + + const struct firmware *init_values; + const struct firmware *firmware; +}; + +#endif /* __USB_H */ diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig new file mode 100644 index 000000000000..509b6f94f73b --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/Kconfig @@ -0,0 +1,41 @@ +config ATH5K + tristate "Atheros 5xxx wireless cards support" + depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + select ATH_COMMON + select MAC80211_LEDS + select LEDS_CLASS + select NEW_LEDS + ---help--- + This module adds support for wireless adapters based on + Atheros 5xxx chipset. + + Currently the following chip versions are supported: + + MAC: AR5211 AR5212 + PHY: RF5111/2111 RF5112/2112 RF5413/2413 + + This driver uses the kernel's mac80211 subsystem. + + If you choose to build a module, it'll be called ath5k. Say M if + unsure. + +config ATH5K_DEBUG + bool "Atheros 5xxx debugging" + depends on ATH5K + ---help--- + Atheros 5xxx debugging messages. + + Say Y, if and you will get debug options for ath5k. + To use this, you need to mount debugfs: + + mkdir /debug/ + mount -t debugfs debug /debug/ + + You will get access to files under: + /debug/ath5k/phy0/ + + To enable debug, pass the debug level to the debug module + parameter. For example: + + modprobe ath5k debug=0x00000400 + diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile new file mode 100644 index 000000000000..84a74c5248e5 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/Makefile @@ -0,0 +1,15 @@ +ath5k-y += caps.o +ath5k-y += initvals.o +ath5k-y += eeprom.o +ath5k-y += gpio.o +ath5k-y += desc.o +ath5k-y += dma.o +ath5k-y += qcu.o +ath5k-y += pcu.o +ath5k-y += phy.o +ath5k-y += reset.o +ath5k-y += attach.o +ath5k-y += base.o +ath5k-y += led.o +ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o +obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h new file mode 100644 index 000000000000..60c6d2edc4b9 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -0,0 +1,1354 @@ +/* + * Copyright (c) 2004-2007 Reyk Floeter + * Copyright (c) 2006-2007 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ATH5K_H +#define _ATH5K_H + +/* TODO: Clean up channel debuging -doesn't work anyway- and start + * working on reg. control code using all available eeprom information + * -rev. engineering needed- */ +#define CHAN_DEBUG 0 + +#include +#include +#include + +#include "../regd.h" + +/* RX/TX descriptor hw structs + * TODO: Driver part should only see sw structs */ +#include "desc.h" + +/* EEPROM structs/offsets + * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) + * and clean up common bits, then introduce set/get functions in eeprom.c */ +#include "eeprom.h" + +/* PCI IDs */ +#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ +#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */ +#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */ +#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */ +#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */ +#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */ +#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */ +#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */ +#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */ +#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */ +#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */ +#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ +#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ +#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */ +#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */ +#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */ +#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */ +#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */ + +/****************************\ + GENERIC DRIVER DEFINITIONS +\****************************/ + +#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__) + +#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \ + printk(_level "ath5k %s: " _fmt, \ + ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \ + ##__VA_ARGS__) + +#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \ + if (net_ratelimit()) \ + ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \ + } while (0) + +#define ATH5K_INFO(_sc, _fmt, ...) \ + ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__) + +#define ATH5K_WARN(_sc, _fmt, ...) \ + ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__) + +#define ATH5K_ERR(_sc, _fmt, ...) \ + ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) + +/* + * AR5K REGISTER ACCESS + */ + +/* Some macros to read/write fields */ + +/* First shift, then mask */ +#define AR5K_REG_SM(_val, _flags) \ + (((_val) << _flags##_S) & (_flags)) + +/* First mask, then shift */ +#define AR5K_REG_MS(_val, _flags) \ + (((_val) & (_flags)) >> _flags##_S) + +/* Some registers can hold multiple values of interest. For this + * reason when we want to write to these registers we must first + * retrieve the values which we do not want to clear (lets call this + * old_data) and then set the register with this and our new_value: + * ( old_data | new_value) */ +#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \ + ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \ + (((_val) << _flags##_S) & (_flags)), _reg) + +#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \ + ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \ + (_mask)) | (_flags), _reg) + +#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \ + ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg) + +#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ + ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) + +/* Access to PHY registers */ +#define AR5K_PHY_READ(ah, _reg) \ + ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2)) + +#define AR5K_PHY_WRITE(ah, _reg, _val) \ + ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2)) + +/* Access QCU registers per queue */ +#define AR5K_REG_READ_Q(ah, _reg, _queue) \ + (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ + +#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \ + ath5k_hw_reg_write(ah, (1 << _queue), _reg) + +#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \ + _reg |= 1 << _queue; \ +} while (0) + +#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \ + _reg &= ~(1 << _queue); \ +} while (0) + +/* Used while writing initvals */ +#define AR5K_REG_WAIT(_i) do { \ + if (_i % 64) \ + udelay(1); \ +} while (0) + +/* Register dumps are done per operation mode */ +#define AR5K_INI_RFGAIN_5GHZ 0 +#define AR5K_INI_RFGAIN_2GHZ 1 + +/* TODO: Clean this up */ +#define AR5K_INI_VAL_11A 0 +#define AR5K_INI_VAL_11A_TURBO 1 +#define AR5K_INI_VAL_11B 2 +#define AR5K_INI_VAL_11G 3 +#define AR5K_INI_VAL_11G_TURBO 4 +#define AR5K_INI_VAL_XR 0 +#define AR5K_INI_VAL_MAX 5 + +/* Used for BSSID etc manipulation */ +#define AR5K_LOW_ID(_a)( \ +(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ +) + +#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) + +/* + * Some tuneable values (these should be changeable by the user) + * TODO: Make use of them and add more options OR use debug/configfs + */ +#define AR5K_TUNE_DMA_BEACON_RESP 2 +#define AR5K_TUNE_SW_BEACON_RESP 10 +#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 +#define AR5K_TUNE_RADAR_ALERT false +#define AR5K_TUNE_MIN_TX_FIFO_THRES 1 +#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) +#define AR5K_TUNE_REGISTER_TIMEOUT 20000 +/* Register for RSSI threshold has a mask of 0xff, so 255 seems to + * be the max value. */ +#define AR5K_TUNE_RSSI_THRES 129 +/* This must be set when setting the RSSI threshold otherwise it can + * prevent a reset. If AR5K_RSSI_THR is read after writing to it + * the BMISS_THRES will be seen as 0, seems harware doesn't keep + * track of it. Max value depends on harware. For AR5210 this is just 7. + * For AR5211+ this seems to be up to 255. */ +#define AR5K_TUNE_BMISS_THRES 7 +#define AR5K_TUNE_REGISTER_DWELL_TIME 20000 +#define AR5K_TUNE_BEACON_INTERVAL 100 +#define AR5K_TUNE_AIFS 2 +#define AR5K_TUNE_AIFS_11B 2 +#define AR5K_TUNE_AIFS_XR 0 +#define AR5K_TUNE_CWMIN 15 +#define AR5K_TUNE_CWMIN_11B 31 +#define AR5K_TUNE_CWMIN_XR 3 +#define AR5K_TUNE_CWMAX 1023 +#define AR5K_TUNE_CWMAX_11B 1023 +#define AR5K_TUNE_CWMAX_XR 7 +#define AR5K_TUNE_NOISE_FLOOR -72 +#define AR5K_TUNE_MAX_TXPOWER 63 +#define AR5K_TUNE_DEFAULT_TXPOWER 25 +#define AR5K_TUNE_TPC_TXPOWER false +#define AR5K_TUNE_ANT_DIVERSITY true +#define AR5K_TUNE_HWTXTRIES 4 + +#define AR5K_INIT_CARR_SENSE_EN 1 + +/*Swap RX/TX Descriptor for big endian archs*/ +#if defined(__BIG_ENDIAN) +#define AR5K_INIT_CFG ( \ + AR5K_CFG_SWTD | AR5K_CFG_SWRD \ +) +#else +#define AR5K_INIT_CFG 0x00000000 +#endif + +/* Initial values */ +#define AR5K_INIT_CYCRSSI_THR1 2 +#define AR5K_INIT_TX_LATENCY 502 +#define AR5K_INIT_USEC 39 +#define AR5K_INIT_USEC_TURBO 79 +#define AR5K_INIT_USEC_32 31 +#define AR5K_INIT_SLOT_TIME 396 +#define AR5K_INIT_SLOT_TIME_TURBO 480 +#define AR5K_INIT_ACK_CTS_TIMEOUT 1024 +#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 +#define AR5K_INIT_PROG_IFS 920 +#define AR5K_INIT_PROG_IFS_TURBO 960 +#define AR5K_INIT_EIFS 3440 +#define AR5K_INIT_EIFS_TURBO 6880 +#define AR5K_INIT_SIFS 560 +#define AR5K_INIT_SIFS_TURBO 480 +#define AR5K_INIT_SH_RETRY 10 +#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY +#define AR5K_INIT_SSH_RETRY 32 +#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY +#define AR5K_INIT_TX_RETRY 10 + +#define AR5K_INIT_TRANSMIT_LATENCY ( \ + (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ + (AR5K_INIT_USEC) \ +) +#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ + (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ + (AR5K_INIT_USEC_TURBO) \ +) +#define AR5K_INIT_PROTO_TIME_CNTRL ( \ + (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ + (AR5K_INIT_PROG_IFS) \ +) +#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ + (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ + (AR5K_INIT_PROG_IFS_TURBO) \ +) + +/* token to use for aifs, cwmin, cwmax in MadWiFi */ +#define AR5K_TXQ_USEDEFAULT ((u32) -1) + +/* GENERIC CHIPSET DEFINITIONS */ + +/* MAC Chips */ +enum ath5k_version { + AR5K_AR5210 = 0, + AR5K_AR5211 = 1, + AR5K_AR5212 = 2, +}; + +/* PHY Chips */ +enum ath5k_radio { + AR5K_RF5110 = 0, + AR5K_RF5111 = 1, + AR5K_RF5112 = 2, + AR5K_RF2413 = 3, + AR5K_RF5413 = 4, + AR5K_RF2316 = 5, + AR5K_RF2317 = 6, + AR5K_RF2425 = 7, +}; + +/* + * Common silicon revision/version values + */ + +enum ath5k_srev_type { + AR5K_VERSION_MAC, + AR5K_VERSION_RAD, +}; + +struct ath5k_srev_name { + const char *sr_name; + enum ath5k_srev_type sr_type; + u_int sr_val; +}; + +#define AR5K_SREV_UNKNOWN 0xffff + +#define AR5K_SREV_AR5210 0x00 /* Crete */ +#define AR5K_SREV_AR5311 0x10 /* Maui 1 */ +#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */ +#define AR5K_SREV_AR5311B 0x30 /* Spirit */ +#define AR5K_SREV_AR5211 0x40 /* Oahu */ +#define AR5K_SREV_AR5212 0x50 /* Venice */ +#define AR5K_SREV_AR5213 0x55 /* ??? */ +#define AR5K_SREV_AR5213A 0x59 /* Hainan */ +#define AR5K_SREV_AR2413 0x78 /* Griffin lite */ +#define AR5K_SREV_AR2414 0x70 /* Griffin */ +#define AR5K_SREV_AR5424 0x90 /* Condor */ +#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ +#define AR5K_SREV_AR5414 0xa0 /* Eagle */ +#define AR5K_SREV_AR2415 0xb0 /* Talon */ +#define AR5K_SREV_AR5416 0xc0 /* PCI-E */ +#define AR5K_SREV_AR5418 0xca /* PCI-E */ +#define AR5K_SREV_AR2425 0xe0 /* Swan */ +#define AR5K_SREV_AR2417 0xf0 /* Nala */ + +#define AR5K_SREV_RAD_5110 0x00 +#define AR5K_SREV_RAD_5111 0x10 +#define AR5K_SREV_RAD_5111A 0x15 +#define AR5K_SREV_RAD_2111 0x20 +#define AR5K_SREV_RAD_5112 0x30 +#define AR5K_SREV_RAD_5112A 0x35 +#define AR5K_SREV_RAD_5112B 0x36 +#define AR5K_SREV_RAD_2112 0x40 +#define AR5K_SREV_RAD_2112A 0x45 +#define AR5K_SREV_RAD_2112B 0x46 +#define AR5K_SREV_RAD_2413 0x50 +#define AR5K_SREV_RAD_5413 0x60 +#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */ +#define AR5K_SREV_RAD_2317 0x80 +#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */ +#define AR5K_SREV_RAD_2425 0xa2 +#define AR5K_SREV_RAD_5133 0xc0 + +#define AR5K_SREV_PHY_5211 0x30 +#define AR5K_SREV_PHY_5212 0x41 +#define AR5K_SREV_PHY_5212A 0x42 +#define AR5K_SREV_PHY_5212B 0x43 +#define AR5K_SREV_PHY_2413 0x45 +#define AR5K_SREV_PHY_5413 0x61 +#define AR5K_SREV_PHY_2425 0x70 + +/* IEEE defs */ +#define IEEE80211_MAX_LEN 2500 + +/* TODO add support to mac80211 for vendor-specific rates and modes */ + +/* + * Some of this information is based on Documentation from: + * + * http://madwifi.org/wiki/ChipsetFeatures/SuperAG + * + * Modulation for Atheros' eXtended Range - range enhancing extension that is + * supposed to double the distance an Atheros client device can keep a + * connection with an Atheros access point. This is achieved by increasing + * the receiver sensitivity up to, -105dBm, which is about 20dB above what + * the 802.11 specifications demand. In addition, new (proprietary) data rates + * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. + * + * Please note that can you either use XR or TURBO but you cannot use both, + * they are exclusive. + * + */ +#define MODULATION_XR 0x00000200 +/* + * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a + * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s + * signaling rate achieved through the bonding of two 54Mbit/s 802.11g + * channels. To use this feature your Access Point must also suport it. + * There is also a distinction between "static" and "dynamic" turbo modes: + * + * - Static: is the dumb version: devices set to this mode stick to it until + * the mode is turned off. + * - Dynamic: is the intelligent version, the network decides itself if it + * is ok to use turbo. As soon as traffic is detected on adjacent channels + * (which would get used in turbo mode), or when a non-turbo station joins + * the network, turbo mode won't be used until the situation changes again. + * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which + * monitors the used radio band in order to decide whether turbo mode may + * be used or not. + * + * This article claims Super G sticks to bonding of channels 5 and 6 for + * USA: + * + * http://www.pcworld.com/article/id,113428-page,1/article.html + * + * The channel bonding seems to be driver specific though. In addition to + * deciding what channels will be used, these "Turbo" modes are accomplished + * by also enabling the following features: + * + * - Bursting: allows multiple frames to be sent at once, rather than pausing + * after each frame. Bursting is a standards-compliant feature that can be + * used with any Access Point. + * - Fast frames: increases the amount of information that can be sent per + * frame, also resulting in a reduction of transmission overhead. It is a + * proprietary feature that needs to be supported by the Access Point. + * - Compression: data frames are compressed in real time using a Lempel Ziv + * algorithm. This is done transparently. Once this feature is enabled, + * compression and decompression takes place inside the chipset, without + * putting additional load on the host CPU. + * + */ +#define MODULATION_TURBO 0x00000080 + +enum ath5k_driver_mode { + AR5K_MODE_11A = 0, + AR5K_MODE_11A_TURBO = 1, + AR5K_MODE_11B = 2, + AR5K_MODE_11G = 3, + AR5K_MODE_11G_TURBO = 4, + AR5K_MODE_XR = 0, + AR5K_MODE_MAX = 5 +}; + + +/****************\ + TX DEFINITIONS +\****************/ + +/* + * TX Status descriptor + */ +struct ath5k_tx_status { + u16 ts_seqnum; + u16 ts_tstamp; + u8 ts_status; + u8 ts_rate[4]; + u8 ts_retry[4]; + u8 ts_final_idx; + s8 ts_rssi; + u8 ts_shortretry; + u8 ts_longretry; + u8 ts_virtcol; + u8 ts_antenna; +}; + +#define AR5K_TXSTAT_ALTRATE 0x80 +#define AR5K_TXERR_XRETRY 0x01 +#define AR5K_TXERR_FILT 0x02 +#define AR5K_TXERR_FIFO 0x04 + +/** + * enum ath5k_tx_queue - Queue types used to classify tx queues. + * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue + * @AR5K_TX_QUEUE_DATA: A normal data queue + * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue + * @AR5K_TX_QUEUE_BEACON: The beacon queue + * @AR5K_TX_QUEUE_CAB: The after-beacon queue + * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue + */ +enum ath5k_tx_queue { + AR5K_TX_QUEUE_INACTIVE = 0, + AR5K_TX_QUEUE_DATA, + AR5K_TX_QUEUE_XR_DATA, + AR5K_TX_QUEUE_BEACON, + AR5K_TX_QUEUE_CAB, + AR5K_TX_QUEUE_UAPSD, +}; + +#define AR5K_NUM_TX_QUEUES 10 +#define AR5K_NUM_TX_QUEUES_NOQCU 2 + +/* + * Queue syb-types to classify normal data queues. + * These are the 4 Access Categories as defined in + * WME spec. 0 is the lowest priority and 4 is the + * highest. Normal data that hasn't been classified + * goes to the Best Effort AC. + */ +enum ath5k_tx_queue_subtype { + AR5K_WME_AC_BK = 0, /*Background traffic*/ + AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/ + AR5K_WME_AC_VI, /*Video traffic*/ + AR5K_WME_AC_VO, /*Voice traffic*/ +}; + +/* + * Queue ID numbers as returned by the hw functions, each number + * represents a hw queue. If hw does not support hw queues + * (eg 5210) all data goes in one queue. These match + * d80211 definitions (net80211/MadWiFi don't use them). + */ +enum ath5k_tx_queue_id { + AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, + AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, + AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ + AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/ + AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ + AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ + AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ + AR5K_TX_QUEUE_ID_UAPSD = 8, + AR5K_TX_QUEUE_ID_XR_DATA = 9, +}; + +/* + * Flags to set hw queue's parameters... + */ +#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */ +#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */ +#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */ +#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */ +#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */ +#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */ +#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */ +#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */ +#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */ +#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */ +#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/ +#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */ +#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ +#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ + +/* + * A struct to hold tx queue's parameters + */ +struct ath5k_txq_info { + enum ath5k_tx_queue tqi_type; + enum ath5k_tx_queue_subtype tqi_subtype; + u16 tqi_flags; /* Tx queue flags (see above) */ + u32 tqi_aifs; /* Arbitrated Interframe Space */ + s32 tqi_cw_min; /* Minimum Contention Window */ + s32 tqi_cw_max; /* Maximum Contention Window */ + u32 tqi_cbr_period; /* Constant bit rate period */ + u32 tqi_cbr_overflow_limit; + u32 tqi_burst_time; + u32 tqi_ready_time; /* Not used */ +}; + +/* + * Transmit packet types. + * used on tx control descriptor + * TODO: Use them inside base.c corectly + */ +enum ath5k_pkt_type { + AR5K_PKT_TYPE_NORMAL = 0, + AR5K_PKT_TYPE_ATIM = 1, + AR5K_PKT_TYPE_PSPOLL = 2, + AR5K_PKT_TYPE_BEACON = 3, + AR5K_PKT_TYPE_PROBE_RESP = 4, + AR5K_PKT_TYPE_PIFS = 5, +}; + +/* + * TX power and TPC settings + */ +#define AR5K_TXPOWER_OFDM(_r, _v) ( \ + ((0 & 1) << ((_v) + 6)) | \ + (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \ +) + +#define AR5K_TXPOWER_CCK(_r, _v) ( \ + (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ +) + +/* + * DMA size definitions (2^n+2) + */ +enum ath5k_dmasize { + AR5K_DMASIZE_4B = 0, + AR5K_DMASIZE_8B, + AR5K_DMASIZE_16B, + AR5K_DMASIZE_32B, + AR5K_DMASIZE_64B, + AR5K_DMASIZE_128B, + AR5K_DMASIZE_256B, + AR5K_DMASIZE_512B +}; + + +/****************\ + RX DEFINITIONS +\****************/ + +/* + * RX Status descriptor + */ +struct ath5k_rx_status { + u16 rs_datalen; + u16 rs_tstamp; + u8 rs_status; + u8 rs_phyerr; + s8 rs_rssi; + u8 rs_keyix; + u8 rs_rate; + u8 rs_antenna; + u8 rs_more; +}; + +#define AR5K_RXERR_CRC 0x01 +#define AR5K_RXERR_PHY 0x02 +#define AR5K_RXERR_FIFO 0x04 +#define AR5K_RXERR_DECRYPT 0x08 +#define AR5K_RXERR_MIC 0x10 +#define AR5K_RXKEYIX_INVALID ((u8) - 1) +#define AR5K_TXKEYIX_INVALID ((u32) - 1) + + +/**************************\ + BEACON TIMERS DEFINITIONS +\**************************/ + +#define AR5K_BEACON_PERIOD 0x0000ffff +#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ +#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ + +#if 0 +/** + * struct ath5k_beacon_state - Per-station beacon timer state. + * @bs_interval: in TU's, can also include the above flags + * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a + * Point Coordination Function capable AP + */ +struct ath5k_beacon_state { + u32 bs_next_beacon; + u32 bs_next_dtim; + u32 bs_interval; + u8 bs_dtim_period; + u8 bs_cfp_period; + u16 bs_cfp_max_duration; + u16 bs_cfp_du_remain; + u16 bs_tim_offset; + u16 bs_sleep_duration; + u16 bs_bmiss_threshold; + u32 bs_cfp_next; +}; +#endif + + +/* + * TSF to TU conversion: + * + * TSF is a 64bit value in usec (microseconds). + * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of + * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024). + */ +#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) + + +/*******************************\ + GAIN OPTIMIZATION DEFINITIONS +\*******************************/ + +enum ath5k_rfgain { + AR5K_RFGAIN_INACTIVE = 0, + AR5K_RFGAIN_ACTIVE, + AR5K_RFGAIN_READ_REQUESTED, + AR5K_RFGAIN_NEED_CHANGE, +}; + +struct ath5k_gain { + u8 g_step_idx; + u8 g_current; + u8 g_target; + u8 g_low; + u8 g_high; + u8 g_f_corr; + u8 g_state; +}; + +/********************\ + COMMON DEFINITIONS +\********************/ + +#define AR5K_SLOT_TIME_9 396 +#define AR5K_SLOT_TIME_20 880 +#define AR5K_SLOT_TIME_MAX 0xffff + +/* channel_flags */ +#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ +#define CHANNEL_TURBO 0x0010 /* Turbo Channel */ +#define CHANNEL_CCK 0x0020 /* CCK channel */ +#define CHANNEL_OFDM 0x0040 /* OFDM channel */ +#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ +#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */ +#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */ +#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */ +#define CHANNEL_XR 0x0800 /* XR channel */ + +#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) +#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) +#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) +#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) +#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) +#define CHANNEL_108A CHANNEL_T +#define CHANNEL_108G CHANNEL_TG +#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) + +#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ + CHANNEL_TURBO) + +#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) +#define CHANNEL_MODES CHANNEL_ALL + +/* + * Used internaly for reset_tx_queue). + * Also see struct struct ieee80211_channel. + */ +#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0) +#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0) + +/* + * The following structure is used to map 2GHz channels to + * 5GHz Atheros channels. + * TODO: Clean up + */ +struct ath5k_athchan_2ghz { + u32 a2_flags; + u16 a2_athchan; +}; + + +/******************\ + RATE DEFINITIONS +\******************/ + +/** + * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32. + * + * The rate code is used to get the RX rate or set the TX rate on the + * hardware descriptors. It is also used for internal modulation control + * and settings. + * + * This is the hardware rate map we are aware of: + * + * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 + * rate_kbps 3000 1000 ? ? ? 2000 500 48000 + * + * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 + * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? + * + * rate_code 17 18 19 20 21 22 23 24 + * rate_kbps ? ? ? ? ? ? ? 11000 + * + * rate_code 25 26 27 28 29 30 31 32 + * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ? + * + * "S" indicates CCK rates with short preamble. + * + * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the + * lowest 4 bits, so they are the same as below with a 0xF mask. + * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). + * We handle this in ath5k_setup_bands(). + */ +#define AR5K_MAX_RATES 32 + +/* B */ +#define ATH5K_RATE_CODE_1M 0x1B +#define ATH5K_RATE_CODE_2M 0x1A +#define ATH5K_RATE_CODE_5_5M 0x19 +#define ATH5K_RATE_CODE_11M 0x18 +/* A and G */ +#define ATH5K_RATE_CODE_6M 0x0B +#define ATH5K_RATE_CODE_9M 0x0F +#define ATH5K_RATE_CODE_12M 0x0A +#define ATH5K_RATE_CODE_18M 0x0E +#define ATH5K_RATE_CODE_24M 0x09 +#define ATH5K_RATE_CODE_36M 0x0D +#define ATH5K_RATE_CODE_48M 0x08 +#define ATH5K_RATE_CODE_54M 0x0C +/* XR */ +#define ATH5K_RATE_CODE_XR_500K 0x07 +#define ATH5K_RATE_CODE_XR_1M 0x02 +#define ATH5K_RATE_CODE_XR_2M 0x06 +#define ATH5K_RATE_CODE_XR_3M 0x01 + +/* adding this flag to rate_code enables short preamble */ +#define AR5K_SET_SHORT_PREAMBLE 0x04 + +/* + * Crypto definitions + */ + +#define AR5K_KEYCACHE_SIZE 8 + +/***********************\ + HW RELATED DEFINITIONS +\***********************/ + +/* + * Misc definitions + */ +#define AR5K_RSSI_EP_MULTIPLIER (1<<7) + +#define AR5K_ASSERT_ENTRY(_e, _s) do { \ + if (_e >= _s) \ + return (false); \ +} while (0) + +/* + * Hardware interrupt abstraction + */ + +/** + * enum ath5k_int - Hardware interrupt masks helpers + * + * @AR5K_INT_RX: mask to identify received frame interrupts, of type + * AR5K_ISR_RXOK or AR5K_ISR_RXERR + * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?) + * @AR5K_INT_RXNOFRM: No frame received (?) + * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The + * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's + * LinkPtr is NULL. For more details, refer to: + * http://www.freepatentsonline.com/20030225739.html + * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). + * Note that Rx overrun is not always fatal, on some chips we can continue + * operation without reseting the card, that's why int_fatal is not + * common for all chips. + * @AR5K_INT_TX: mask to identify received frame interrupts, of type + * AR5K_ISR_TXOK or AR5K_ISR_TXERR + * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?) + * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold + * We currently do increments on interrupt by + * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 + * @AR5K_INT_MIB: Indicates the Management Information Base counters should be + * checked. We should do this with ath5k_hw_update_mib_counters() but + * it seems we should also then do some noise immunity work. + * @AR5K_INT_RXPHY: RX PHY Error + * @AR5K_INT_RXKCM: RX Key cache miss + * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a + * beacon that must be handled in software. The alternative is if you + * have VEOL support, in that case you let the hardware deal with things. + * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing + * beacons from the AP have associated with, we should probably try to + * reassociate. When in IBSS mode this might mean we have not received + * any beacons from any local stations. Note that every station in an + * IBSS schedules to send beacons at the Target Beacon Transmission Time + * (TBTT) with a random backoff. + * @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? + * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now + * until properly handled + * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA + * errors. These types of errors we can enable seem to be of type + * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. + * @AR5K_INT_GLOBAL: Used to clear and set the IER + * @AR5K_INT_NOCARD: signals the card has been removed + * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same + * bit value + * + * These are mapped to take advantage of some common bits + * between the MACs, to be able to set intr properties + * easier. Some of them are not used yet inside hw.c. Most map + * to the respective hw interrupt value as they are common amogst different + * MACs. + */ +enum ath5k_int { + AR5K_INT_RXOK = 0x00000001, + AR5K_INT_RXDESC = 0x00000002, + AR5K_INT_RXERR = 0x00000004, + AR5K_INT_RXNOFRM = 0x00000008, + AR5K_INT_RXEOL = 0x00000010, + AR5K_INT_RXORN = 0x00000020, + AR5K_INT_TXOK = 0x00000040, + AR5K_INT_TXDESC = 0x00000080, + AR5K_INT_TXERR = 0x00000100, + AR5K_INT_TXNOFRM = 0x00000200, + AR5K_INT_TXEOL = 0x00000400, + AR5K_INT_TXURN = 0x00000800, + AR5K_INT_MIB = 0x00001000, + AR5K_INT_SWI = 0x00002000, + AR5K_INT_RXPHY = 0x00004000, + AR5K_INT_RXKCM = 0x00008000, + AR5K_INT_SWBA = 0x00010000, + AR5K_INT_BRSSI = 0x00020000, + AR5K_INT_BMISS = 0x00040000, + AR5K_INT_FATAL = 0x00080000, /* Non common */ + AR5K_INT_BNR = 0x00100000, /* Non common */ + AR5K_INT_TIM = 0x00200000, /* Non common */ + AR5K_INT_DTIM = 0x00400000, /* Non common */ + AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */ + AR5K_INT_GPIO = 0x01000000, + AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ + AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ + AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */ + AR5K_INT_QCBRORN = 0x10000000, /* Non common */ + AR5K_INT_QCBRURN = 0x20000000, /* Non common */ + AR5K_INT_QTRIG = 0x40000000, /* Non common */ + AR5K_INT_GLOBAL = 0x80000000, + + AR5K_INT_COMMON = AR5K_INT_RXOK + | AR5K_INT_RXDESC + | AR5K_INT_RXERR + | AR5K_INT_RXNOFRM + | AR5K_INT_RXEOL + | AR5K_INT_RXORN + | AR5K_INT_TXOK + | AR5K_INT_TXDESC + | AR5K_INT_TXERR + | AR5K_INT_TXNOFRM + | AR5K_INT_TXEOL + | AR5K_INT_TXURN + | AR5K_INT_MIB + | AR5K_INT_SWI + | AR5K_INT_RXPHY + | AR5K_INT_RXKCM + | AR5K_INT_SWBA + | AR5K_INT_BRSSI + | AR5K_INT_BMISS + | AR5K_INT_GPIO + | AR5K_INT_GLOBAL, + + AR5K_INT_NOCARD = 0xffffffff +}; + +/* + * Power management + */ +enum ath5k_power_mode { + AR5K_PM_UNDEFINED = 0, + AR5K_PM_AUTO, + AR5K_PM_AWAKE, + AR5K_PM_FULL_SLEEP, + AR5K_PM_NETWORK_SLEEP, +}; + +/* + * These match net80211 definitions (not used in + * mac80211). + * TODO: Clean this up + */ +#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/ +#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/ +#define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/ +#define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/ +#define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/ + +/* GPIO-controlled software LED */ +#define AR5K_SOFTLED_PIN 0 +#define AR5K_SOFTLED_ON 0 +#define AR5K_SOFTLED_OFF 1 + +/* + * Chipset capabilities -see ath5k_hw_get_capability- + * get_capability function is not yet fully implemented + * in ath5k so most of these don't work yet... + * TODO: Implement these & merge with _TUNE_ stuff above + */ +enum ath5k_capability_type { + AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ + AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */ + AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */ + AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */ + AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */ + AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */ + AR5K_CAP_VEOL = 7, /* Supports virtual EOL */ + AR5K_CAP_COMPRESSION = 8, /* Supports compression */ + AR5K_CAP_BURST = 9, /* Supports packet bursting */ + AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */ + AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */ + AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */ + AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */ + AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */ + AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */ + AR5K_CAP_XR = 16, /* Supports XR mode */ + AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */ + AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */ + AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */ + AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */ +}; + + +/* XXX: we *may* move cap_range stuff to struct wiphy */ +struct ath5k_capabilities { + /* + * Supported PHY modes + * (ie. CHANNEL_A, CHANNEL_B, ...) + */ + DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX); + + /* + * Frequency range (without regulation restrictions) + */ + struct { + u16 range_2ghz_min; + u16 range_2ghz_max; + u16 range_5ghz_min; + u16 range_5ghz_max; + } cap_range; + + /* + * Values stored in the EEPROM (some of them...) + */ + struct ath5k_eeprom_info cap_eeprom; + + /* + * Queue information + */ + struct { + u8 q_tx_num; + } cap_queues; +}; + + +/***************************************\ + HARDWARE ABSTRACTION LAYER STRUCTURE +\***************************************/ + +/* + * Misc defines + */ + +#define AR5K_MAX_GPIO 10 +#define AR5K_MAX_RF_BANKS 8 + +/* TODO: Clean up and merge with ath5k_softc */ +struct ath5k_hw { + u32 ah_magic; + + struct ath5k_softc *ah_sc; + void __iomem *ah_iobase; + + enum ath5k_int ah_imr; + + enum nl80211_iftype ah_op_mode; + enum ath5k_power_mode ah_power_mode; + struct ieee80211_channel ah_current_channel; + bool ah_turbo; + bool ah_calibration; + bool ah_running; + bool ah_single_chip; + bool ah_combined_mic; + + u32 ah_mac_srev; + u16 ah_mac_version; + u16 ah_mac_revision; + u16 ah_phy_revision; + u16 ah_radio_5ghz_revision; + u16 ah_radio_2ghz_revision; + + enum ath5k_version ah_version; + enum ath5k_radio ah_radio; + u32 ah_phy; + + bool ah_5ghz; + bool ah_2ghz; + +#define ah_modes ah_capabilities.cap_mode +#define ah_ee_version ah_capabilities.cap_eeprom.ee_version + + u32 ah_atim_window; + u32 ah_aifs; + u32 ah_cw_min; + u32 ah_cw_max; + bool ah_software_retry; + u32 ah_limit_tx_retries; + + u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; + bool ah_ant_diversity; + + u8 ah_sta_id[ETH_ALEN]; + + /* Current BSSID we are trying to assoc to / create. + * This is passed by mac80211 on config_interface() and cached here for + * use in resets */ + u8 ah_bssid[ETH_ALEN]; + u8 ah_bssid_mask[ETH_ALEN]; + + u32 ah_gpio[AR5K_MAX_GPIO]; + int ah_gpio_npins; + + struct ath_regulatory ah_regulatory; + struct ath5k_capabilities ah_capabilities; + + struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; + u32 ah_txq_status; + u32 ah_txq_imr_txok; + u32 ah_txq_imr_txerr; + u32 ah_txq_imr_txurn; + u32 ah_txq_imr_txdesc; + u32 ah_txq_imr_txeol; + u32 ah_txq_imr_cbrorn; + u32 ah_txq_imr_cbrurn; + u32 ah_txq_imr_qtrig; + u32 ah_txq_imr_nofrm; + u32 ah_txq_isr; + u32 *ah_rf_banks; + size_t ah_rf_banks_size; + size_t ah_rf_regs_count; + struct ath5k_gain ah_gain; + u8 ah_offset[AR5K_MAX_RF_BANKS]; + + + struct { + /* Temporary tables used for interpolation */ + u8 tmpL[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_POWER_TABLE_SIZE]; + u8 tmpR[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_POWER_TABLE_SIZE]; + u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2]; + u16 txp_rates_power_table[AR5K_MAX_RATES]; + u8 txp_min_idx; + bool txp_tpc; + /* Values in 0.25dB units */ + s16 txp_min_pwr; + s16 txp_max_pwr; + s16 txp_offset; + s16 txp_ofdm; + /* Values in dB units */ + s16 txp_cck_ofdm_pwr_delta; + s16 txp_cck_ofdm_gainf_delta; + } ah_txpower; + + struct { + bool r_enabled; + int r_last_alert; + struct ieee80211_channel r_last_channel; + } ah_radar; + + /* noise floor from last periodic calibration */ + s32 ah_noise_floor; + + /* + * Function pointers + */ + int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, + u32 size, unsigned int flags); + int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, + unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, + unsigned int, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int); + int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, + unsigned int, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int); + int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_tx_status *); + int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_rx_status *); +}; + +/* + * Prototypes + */ + +/* Attach/Detach Functions */ +extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); +extern void ath5k_hw_detach(struct ath5k_hw *ah); + +/* LED functions */ +extern int ath5k_init_leds(struct ath5k_softc *sc); +extern void ath5k_led_enable(struct ath5k_softc *sc); +extern void ath5k_led_off(struct ath5k_softc *sc); +extern void ath5k_unregister_leds(struct ath5k_softc *sc); + +/* Reset Functions */ +extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); +extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); +/* Power management functions */ +extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); + +/* DMA Related Functions */ +extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); +extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); +extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); +extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); +extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); +extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); +extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); +extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, + u32 phys_addr); +extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); +/* Interrupt handling */ +extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); +extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); +extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum +ath5k_int new_mask); +extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); + +/* EEPROM access functions */ +extern int ath5k_eeprom_init(struct ath5k_hw *ah); +extern void ath5k_eeprom_detach(struct ath5k_hw *ah); +extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); +extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); + +/* Protocol Control Unit Functions */ +extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); +/* BSSID Functions */ +extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac); +extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); +extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id); +extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); +/* Receive start/stop functions */ +extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); +extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); +/* RX Filter functions */ +extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); +extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); +extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); +extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); +extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); +/* Beacon control functions */ +extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); +extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); +extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); +extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); +extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); +#if 0 +extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); +extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); +extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); +#endif +/* ACK bit rate */ +void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); +/* ACK/CTS Timeouts */ +extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); +extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); +extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); +extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); +/* Key table (WEP) functions */ +extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); +extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); +extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); +extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); + +/* Queue Control Unit, DFS Control Unit Functions */ +extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); +extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, + const struct ath5k_txq_info *queue_info); +extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, + enum ath5k_tx_queue queue_type, + struct ath5k_txq_info *queue_info); +extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); +extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); +extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); +extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); +extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); + +/* Hardware Descriptor Functions */ +extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); + +/* GPIO Functions */ +extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); +extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); +extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); +extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); +extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); +extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); + +/* Misc functions */ +int ath5k_hw_set_capabilities(struct ath5k_hw *ah); +extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); +extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); +extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); + +/* Initial register settings functions */ +extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); + +/* Initialize RF */ +extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + unsigned int mode); +extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); +extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); +extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); +/* PHY/RF channel functions */ +extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); +extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); +/* PHY calibration */ +extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); +extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); +/* Misc PHY functions */ +extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); +extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); +extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); +extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); +/* TX power setup */ +extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); +extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); + +/* + * Functions used internaly + */ + +/* + * Translate usec to hw clock units + * TODO: Half/quarter rate + */ +static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) +{ + return turbo ? (usec * 80) : (usec * 40); +} + +/* + * Translate hw clock units to usec + * TODO: Half/quarter rate + */ +static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) +{ + return turbo ? (clock / 80) : (clock / 40); +} + +/* + * Read from a register + */ +static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) +{ + return ioread32(ah->ah_iobase + reg); +} + +/* + * Write to a register + */ +static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) +{ + iowrite32(val, ah->ah_iobase + reg); +} + +#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) +/* + * Check if a register write has been completed + */ +static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, + u32 val, bool is_set) +{ + int i; + u32 data; + + for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { + data = ath5k_hw_reg_read(ah, reg); + if (is_set && (data & flag)) + break; + else if ((data & flag) == val) + break; + udelay(15); + } + + return (i <= 0) ? -EAGAIN : 0; +} +#endif + +static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) +{ + u32 retval = 0, bit, i; + + for (i = 0; i < bits; i++) { + bit = (val >> i) & 1; + retval = (retval << 1) | bit; + } + + return retval; +} + +static inline int ath5k_pad_size(int hdrlen) +{ + return (hdrlen < 24) ? 0 : hdrlen & 3; +} + +#endif diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c new file mode 100644 index 000000000000..70d376c63aac --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/*************************************\ +* Attach/Detach Functions and helpers * +\*************************************/ + +#include +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/** + * ath5k_hw_post - Power On Self Test helper function + * + * @ah: The &struct ath5k_hw + */ +static int ath5k_hw_post(struct ath5k_hw *ah) +{ + + static const u32 static_pattern[4] = { + 0x55555555, 0xaaaaaaaa, + 0x66666666, 0x99999999 + }; + static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) }; + int i, c; + u16 cur_reg; + u32 var_pattern; + u32 init_val; + u32 cur_val; + + for (c = 0; c < 2; c++) { + + cur_reg = regs[c]; + + /* Save previous value */ + init_val = ath5k_hw_reg_read(ah, cur_reg); + + for (i = 0; i < 256; i++) { + var_pattern = i << 16 | i; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + cur_val = ath5k_hw_reg_read(ah, cur_reg); + + if (cur_val != var_pattern) { + ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); + return -EAGAIN; + } + + /* Found on ndiswrapper dumps */ + var_pattern = 0x0039080f; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + } + + for (i = 0; i < 4; i++) { + var_pattern = static_pattern[i]; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + cur_val = ath5k_hw_reg_read(ah, cur_reg); + + if (cur_val != var_pattern) { + ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); + return -EAGAIN; + } + + /* Found on ndiswrapper dumps */ + var_pattern = 0x003b080f; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + } + + /* Restore previous value */ + ath5k_hw_reg_write(ah, init_val, cur_reg); + + } + + return 0; + +} + +/** + * ath5k_hw_attach - Check if hw is supported and init the needed structs + * + * @sc: The &struct ath5k_softc we got from the driver's attach function + * @mac_version: The mac version id (check out ath5k.h) based on pci id + * + * Check if the device is supported, perform a POST and initialize the needed + * structs. Returns -ENOMEM if we don't have memory for the needed structs, + * -ENODEV if the device is not supported or prints an error msg if something + * else went wrong. + */ +struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) +{ + struct ath5k_hw *ah; + struct pci_dev *pdev = sc->pdev; + int ret; + u32 srev; + + /*If we passed the test malloc a ath5k_hw struct*/ + ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); + if (ah == NULL) { + ret = -ENOMEM; + ATH5K_ERR(sc, "out of memory\n"); + goto err; + } + + ah->ah_sc = sc; + ah->ah_iobase = sc->iobase; + + /* + * HW information + */ + ah->ah_op_mode = NL80211_IFTYPE_STATION; + ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; + ah->ah_turbo = false; + ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; + ah->ah_imr = 0; + ah->ah_atim_window = 0; + ah->ah_aifs = AR5K_TUNE_AIFS; + ah->ah_cw_min = AR5K_TUNE_CWMIN; + ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; + ah->ah_software_retry = false; + ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; + + /* + * Set the mac version based on the pci id + */ + ah->ah_version = mac_version; + + /*Fill the ath5k_hw struct with the needed functions*/ + ret = ath5k_hw_init_desc_functions(ah); + if (ret) + goto err_free; + + /* Bring device out of sleep and reset it's units */ + ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true); + if (ret) + goto err_free; + + /* Get MAC, PHY and RADIO revisions */ + srev = ath5k_hw_reg_read(ah, AR5K_SREV); + ah->ah_mac_srev = srev; + ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); + ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); + ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & + 0xffffffff; + ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_5GHZ); + ah->ah_phy = AR5K_PHY(0); + + /* Try to identify radio chip based on it's srev */ + switch (ah->ah_radio_5ghz_revision & 0xf0) { + case AR5K_SREV_RAD_5111: + ah->ah_radio = AR5K_RF5111; + ah->ah_single_chip = false; + ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_2GHZ); + break; + case AR5K_SREV_RAD_5112: + case AR5K_SREV_RAD_2112: + ah->ah_radio = AR5K_RF5112; + ah->ah_single_chip = false; + ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_2GHZ); + break; + case AR5K_SREV_RAD_2413: + ah->ah_radio = AR5K_RF2413; + ah->ah_single_chip = true; + break; + case AR5K_SREV_RAD_5413: + ah->ah_radio = AR5K_RF5413; + ah->ah_single_chip = true; + break; + case AR5K_SREV_RAD_2316: + ah->ah_radio = AR5K_RF2316; + ah->ah_single_chip = true; + break; + case AR5K_SREV_RAD_2317: + ah->ah_radio = AR5K_RF2317; + ah->ah_single_chip = true; + break; + case AR5K_SREV_RAD_5424: + if (ah->ah_mac_version == AR5K_SREV_AR2425 || + ah->ah_mac_version == AR5K_SREV_AR2417){ + ah->ah_radio = AR5K_RF2425; + ah->ah_single_chip = true; + } else { + ah->ah_radio = AR5K_RF5413; + ah->ah_single_chip = true; + } + break; + default: + /* Identify radio based on mac/phy srev */ + if (ah->ah_version == AR5K_AR5210) { + ah->ah_radio = AR5K_RF5110; + ah->ah_single_chip = false; + } else if (ah->ah_version == AR5K_AR5211) { + ah->ah_radio = AR5K_RF5111; + ah->ah_single_chip = false; + ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, + CHANNEL_2GHZ); + } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || + ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || + ah->ah_phy_revision == AR5K_SREV_PHY_2425) { + ah->ah_radio = AR5K_RF2425; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425; + } else if (srev == AR5K_SREV_AR5213A && + ah->ah_phy_revision == AR5K_SREV_PHY_5212B) { + ah->ah_radio = AR5K_RF5112; + ah->ah_single_chip = false; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B; + } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) { + ah->ah_radio = AR5K_RF2316; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; + } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) || + ah->ah_phy_revision == AR5K_SREV_PHY_5413) { + ah->ah_radio = AR5K_RF5413; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413; + } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) || + ah->ah_phy_revision == AR5K_SREV_PHY_2413) { + ah->ah_radio = AR5K_RF2413; + ah->ah_single_chip = true; + ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; + } else { + ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); + ret = -ENODEV; + goto err_free; + } + } + + + /* Return on unsuported chips (unsupported eeprom etc) */ + if ((srev >= AR5K_SREV_AR5416) && + (srev < AR5K_SREV_AR2425)) { + ATH5K_ERR(sc, "Device not yet supported.\n"); + ret = -ENODEV; + goto err_free; + } + + /* + * Write PCI-E power save settings + */ + if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { + ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); + /* Shut off RX when elecidle is asserted */ + ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); + /* TODO: EEPROM work */ + ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); + /* Shut off PLL and CLKREQ active in L1 */ + ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); + /* Preserce other settings */ + ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); + ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); + /* Reset SERDES to load new settings */ + ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); + mdelay(1); + } + + /* + * POST + */ + ret = ath5k_hw_post(ah); + if (ret) + goto err_free; + + /* Enable pci core retry fix on Hainan (5213A) and later chips */ + if (srev >= AR5K_SREV_AR5213A) + ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG); + + /* + * Get card capabilities, calibration values etc + * TODO: EEPROM work + */ + ret = ath5k_eeprom_init(ah); + if (ret) { + ATH5K_ERR(sc, "unable to init EEPROM\n"); + goto err_free; + } + + /* Get misc capabilities */ + ret = ath5k_hw_set_capabilities(ah); + if (ret) { + ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", + sc->pdev->device); + goto err_free; + } + + if (srev >= AR5K_SREV_AR2414) { + ah->ah_combined_mic = true; + AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, + AR5K_MISC_MODE_COMBINED_MIC); + } + + /* MAC address is cleared until add_interface */ + ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); + + /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ + memset(ah->ah_bssid, 0xff, ETH_ALEN); + ath5k_hw_set_associd(ah, ah->ah_bssid, 0); + ath5k_hw_set_opmode(ah); + + ath5k_hw_rfgain_opt_init(ah); + + return ah; +err_free: + kfree(ah); +err: + return ERR_PTR(ret); +} + +/** + * ath5k_hw_detach - Free the ath5k_hw struct + * + * @ah: The &struct ath5k_hw + */ +void ath5k_hw_detach(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + + __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); + + if (ah->ah_rf_banks != NULL) + kfree(ah->ah_rf_banks); + + ath5k_eeprom_detach(ah); + + /* assume interrupts are down */ + kfree(ah); +} diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c new file mode 100644 index 000000000000..ff6d4f839734 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -0,0 +1,3110 @@ +/*- + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2004-2005 Atheros Communications, Inc. + * Copyright (c) 2006 Devicescape Software, Inc. + * Copyright (c) 2007 Jiri Slaby + * Copyright (c) 2007 Luis R. Rodriguez + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "base.h" +#include "reg.h" +#include "debug.h" + +static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ +static int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +static int modparam_all_channels; +module_param_named(all_channels, modparam_all_channels, int, 0444); +MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); + + +/******************\ +* Internal defines * +\******************/ + +/* Module info */ +MODULE_AUTHOR("Jiri Slaby"); +MODULE_AUTHOR("Nick Kossifidis"); +MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); +MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); + + +/* Known PCI ids */ +static const struct pci_device_id ath5k_pci_id_table[] = { + { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ + { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ + { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ + { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */ + { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */ + { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */ + { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */ + { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */ + { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ + { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ + { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */ + { 0 } +}; +MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); + +/* Known SREVs */ +static const struct ath5k_srev_name srev_names[] = { + { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, + { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, + { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, + { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B }, + { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 }, + { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 }, + { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 }, + { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A }, + { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 }, + { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 }, + { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 }, + { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 }, + { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 }, + { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 }, + { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 }, + { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, + { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, + { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, + { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, + { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, + { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, + { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A }, + { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, + { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, + { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, + { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B }, + { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, + { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, + { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, + { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, + { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, + { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, + { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, + { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, + { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, + { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, +}; + +static const struct ieee80211_rate ath5k_rates[] = { + { .bitrate = 10, + .hw_value = ATH5K_RATE_CODE_1M, }, + { .bitrate = 20, + .hw_value = ATH5K_RATE_CODE_2M, + .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, + .hw_value = ATH5K_RATE_CODE_5_5M, + .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, + .hw_value = ATH5K_RATE_CODE_11M, + .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, + .hw_value = ATH5K_RATE_CODE_6M, + .flags = 0 }, + { .bitrate = 90, + .hw_value = ATH5K_RATE_CODE_9M, + .flags = 0 }, + { .bitrate = 120, + .hw_value = ATH5K_RATE_CODE_12M, + .flags = 0 }, + { .bitrate = 180, + .hw_value = ATH5K_RATE_CODE_18M, + .flags = 0 }, + { .bitrate = 240, + .hw_value = ATH5K_RATE_CODE_24M, + .flags = 0 }, + { .bitrate = 360, + .hw_value = ATH5K_RATE_CODE_36M, + .flags = 0 }, + { .bitrate = 480, + .hw_value = ATH5K_RATE_CODE_48M, + .flags = 0 }, + { .bitrate = 540, + .hw_value = ATH5K_RATE_CODE_54M, + .flags = 0 }, + /* XR missing */ +}; + +/* + * Prototypes - PCI stack related functions + */ +static int __devinit ath5k_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id); +static void __devexit ath5k_pci_remove(struct pci_dev *pdev); +#ifdef CONFIG_PM +static int ath5k_pci_suspend(struct pci_dev *pdev, + pm_message_t state); +static int ath5k_pci_resume(struct pci_dev *pdev); +#else +#define ath5k_pci_suspend NULL +#define ath5k_pci_resume NULL +#endif /* CONFIG_PM */ + +static struct pci_driver ath5k_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = ath5k_pci_id_table, + .probe = ath5k_pci_probe, + .remove = __devexit_p(ath5k_pci_remove), + .suspend = ath5k_pci_suspend, + .resume = ath5k_pci_resume, +}; + + + +/* + * Prototypes - MAC 802.11 stack related functions + */ +static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +static int ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel); +static int ath5k_reset_wake(struct ath5k_softc *sc); +static int ath5k_start(struct ieee80211_hw *hw); +static void ath5k_stop(struct ieee80211_hw *hw); +static int ath5k_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf); +static void ath5k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf); +static int ath5k_config(struct ieee80211_hw *hw, u32 changed); +static int ath5k_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf); +static void ath5k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + int mc_count, struct dev_mc_list *mclist); +static int ath5k_set_key(struct ieee80211_hw *hw, + enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +static int ath5k_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats); +static int ath5k_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats); +static u64 ath5k_get_tsf(struct ieee80211_hw *hw); +static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); +static void ath5k_reset_tsf(struct ieee80211_hw *hw); +static int ath5k_beacon_update(struct ath5k_softc *sc, + struct sk_buff *skb); +static void ath5k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); + +static const struct ieee80211_ops ath5k_hw_ops = { + .tx = ath5k_tx, + .start = ath5k_start, + .stop = ath5k_stop, + .add_interface = ath5k_add_interface, + .remove_interface = ath5k_remove_interface, + .config = ath5k_config, + .config_interface = ath5k_config_interface, + .configure_filter = ath5k_configure_filter, + .set_key = ath5k_set_key, + .get_stats = ath5k_get_stats, + .conf_tx = NULL, + .get_tx_stats = ath5k_get_tx_stats, + .get_tsf = ath5k_get_tsf, + .set_tsf = ath5k_set_tsf, + .reset_tsf = ath5k_reset_tsf, + .bss_info_changed = ath5k_bss_info_changed, +}; + +/* + * Prototypes - Internal functions + */ +/* Attach detach */ +static int ath5k_attach(struct pci_dev *pdev, + struct ieee80211_hw *hw); +static void ath5k_detach(struct pci_dev *pdev, + struct ieee80211_hw *hw); +/* Channel/mode setup */ +static inline short ath5k_ieee2mhz(short chan); +static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, + struct ieee80211_channel *channels, + unsigned int mode, + unsigned int max); +static int ath5k_setup_bands(struct ieee80211_hw *hw); +static int ath5k_chan_set(struct ath5k_softc *sc, + struct ieee80211_channel *chan); +static void ath5k_setcurmode(struct ath5k_softc *sc, + unsigned int mode); +static void ath5k_mode_setup(struct ath5k_softc *sc); + +/* Descriptor setup */ +static int ath5k_desc_alloc(struct ath5k_softc *sc, + struct pci_dev *pdev); +static void ath5k_desc_free(struct ath5k_softc *sc, + struct pci_dev *pdev); +/* Buffers setup */ +static int ath5k_rxbuf_setup(struct ath5k_softc *sc, + struct ath5k_buf *bf); +static int ath5k_txbuf_setup(struct ath5k_softc *sc, + struct ath5k_buf *bf); +static inline void ath5k_txbuf_free(struct ath5k_softc *sc, + struct ath5k_buf *bf) +{ + BUG_ON(!bf); + if (!bf->skb) + return; + pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_any(bf->skb); + bf->skb = NULL; +} + +static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, + struct ath5k_buf *bf) +{ + BUG_ON(!bf); + if (!bf->skb) + return; + pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, + PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(bf->skb); + bf->skb = NULL; +} + + +/* Queues setup */ +static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, + int qtype, int subtype); +static int ath5k_beaconq_setup(struct ath5k_hw *ah); +static int ath5k_beaconq_config(struct ath5k_softc *sc); +static void ath5k_txq_drainq(struct ath5k_softc *sc, + struct ath5k_txq *txq); +static void ath5k_txq_cleanup(struct ath5k_softc *sc); +static void ath5k_txq_release(struct ath5k_softc *sc); +/* Rx handling */ +static int ath5k_rx_start(struct ath5k_softc *sc); +static void ath5k_rx_stop(struct ath5k_softc *sc); +static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, + struct ath5k_desc *ds, + struct sk_buff *skb, + struct ath5k_rx_status *rs); +static void ath5k_tasklet_rx(unsigned long data); +/* Tx handling */ +static void ath5k_tx_processq(struct ath5k_softc *sc, + struct ath5k_txq *txq); +static void ath5k_tasklet_tx(unsigned long data); +/* Beacon handling */ +static int ath5k_beacon_setup(struct ath5k_softc *sc, + struct ath5k_buf *bf); +static void ath5k_beacon_send(struct ath5k_softc *sc); +static void ath5k_beacon_config(struct ath5k_softc *sc); +static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); +static void ath5k_tasklet_beacon(unsigned long data); + +static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) +{ + u64 tsf = ath5k_hw_get_tsf64(ah); + + if ((tsf & 0x7fff) < rstamp) + tsf -= 0x8000; + + return (tsf & ~0x7fff) | rstamp; +} + +/* Interrupt handling */ +static int ath5k_init(struct ath5k_softc *sc); +static int ath5k_stop_locked(struct ath5k_softc *sc); +static int ath5k_stop_hw(struct ath5k_softc *sc); +static irqreturn_t ath5k_intr(int irq, void *dev_id); +static void ath5k_tasklet_reset(unsigned long data); + +static void ath5k_calibrate(unsigned long data); + +/* + * Module init/exit functions + */ +static int __init +init_ath5k_pci(void) +{ + int ret; + + ath5k_debug_init(); + + ret = pci_register_driver(&ath5k_pci_driver); + if (ret) { + printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); + return ret; + } + + return 0; +} + +static void __exit +exit_ath5k_pci(void) +{ + pci_unregister_driver(&ath5k_pci_driver); + + ath5k_debug_finish(); +} + +module_init(init_ath5k_pci); +module_exit(exit_ath5k_pci); + + +/********************\ +* PCI Initialization * +\********************/ + +static const char * +ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) +{ + const char *name = "xxxxx"; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(srev_names); i++) { + if (srev_names[i].sr_type != type) + continue; + + if ((val & 0xf0) == srev_names[i].sr_val) + name = srev_names[i].sr_name; + + if ((val & 0xff) == srev_names[i].sr_val) { + name = srev_names[i].sr_name; + break; + } + } + + return name; +} + +static int __devinit +ath5k_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + void __iomem *mem; + struct ath5k_softc *sc; + struct ieee80211_hw *hw; + int ret; + u8 csz; + + ret = pci_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "can't enable device\n"); + goto err; + } + + /* XXX 32-bit addressing only */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "32-bit DMA not available\n"); + goto err_dis; + } + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); + if (csz == 0) { + /* + * Linux 2.4.18 (at least) writes the cache line size + * register as a 16-bit wide register which is wrong. + * We must have this setup properly for rx buffer + * DMA to work so force a reasonable value here if it + * comes up zero. + */ + csz = L1_CACHE_BYTES / sizeof(u32); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); + } + /* + * The default setting of latency timer yields poor results, + * set it to the value used by other systems. It may be worth + * tweaking this setting more. + */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* + * Disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state. + */ + pci_write_config_byte(pdev, 0x41, 0); + + ret = pci_request_region(pdev, 0, "ath5k"); + if (ret) { + dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); + goto err_dis; + } + + mem = pci_iomap(pdev, 0, 0); + if (!mem) { + dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; + ret = -EIO; + goto err_reg; + } + + /* + * Allocate hw (mac80211 main struct) + * and hw->priv (driver private data) + */ + hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); + ret = -ENOMEM; + goto err_map; + } + + dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); + + /* Initialize driver private data */ + SET_IEEE80211_DEV(hw, &pdev->dev); + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->extra_tx_headroom = 2; + hw->channel_change_time = 5000; + sc = hw->priv; + sc->hw = hw; + sc->pdev = pdev; + + ath5k_debug_init_device(sc); + + /* + * Mark the device as detached to avoid processing + * interrupts until setup is complete. + */ + __set_bit(ATH_STAT_INVALID, sc->status); + + sc->iobase = mem; /* So we can unmap it on detach */ + sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ + sc->opmode = NL80211_IFTYPE_STATION; + mutex_init(&sc->lock); + spin_lock_init(&sc->rxbuflock); + spin_lock_init(&sc->txbuflock); + spin_lock_init(&sc->block); + + /* Set private data */ + pci_set_drvdata(pdev, hw); + + /* Setup interrupt handler */ + ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); + if (ret) { + ATH5K_ERR(sc, "request_irq failed\n"); + goto err_free; + } + + /* Initialize device */ + sc->ah = ath5k_hw_attach(sc, id->driver_data); + if (IS_ERR(sc->ah)) { + ret = PTR_ERR(sc->ah); + goto err_irq; + } + + /* set up multi-rate retry capabilities */ + if (sc->ah->ah_version == AR5K_AR5212) { + hw->max_rates = 4; + hw->max_rate_tries = 11; + } + + /* Finish private driver data initialization */ + ret = ath5k_attach(pdev, hw); + if (ret) + goto err_ah; + + ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", + ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), + sc->ah->ah_mac_srev, + sc->ah->ah_phy_revision); + + if (!sc->ah->ah_single_chip) { + /* Single chip radio (!RF5111) */ + if (sc->ah->ah_radio_5ghz_revision && + !sc->ah->ah_radio_2ghz_revision) { + /* No 5GHz support -> report 2GHz radio */ + if (!test_bit(AR5K_MODE_11A, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* No 2GHz support (5110 and some + * 5Ghz only cards) -> report 5Ghz radio */ + } else if (!test_bit(AR5K_MODE_11B, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* Multiband radio */ + } else { + ATH5K_INFO(sc, "RF%s multiband radio found" + " (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + } + } + /* Multi chip radio (RF5111 - RF2111) -> + * report both 2GHz/5GHz radios */ + else if (sc->ah->ah_radio_5ghz_revision && + sc->ah->ah_radio_2ghz_revision){ + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_2ghz_revision), + sc->ah->ah_radio_2ghz_revision); + } + } + + + /* ready to process interrupts */ + __clear_bit(ATH_STAT_INVALID, sc->status); + + return 0; +err_ah: + ath5k_hw_detach(sc->ah); +err_irq: + free_irq(pdev->irq, sc); +err_free: + ieee80211_free_hw(hw); +err_map: + pci_iounmap(pdev, mem); +err_reg: + pci_release_region(pdev, 0); +err_dis: + pci_disable_device(pdev); +err: + return ret; +} + +static void __devexit +ath5k_pci_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath5k_softc *sc = hw->priv; + + ath5k_debug_finish_device(sc); + ath5k_detach(pdev, hw); + ath5k_hw_detach(sc->ah); + free_irq(pdev->irq, sc); + pci_iounmap(pdev, sc->iobase); + pci_release_region(pdev, 0); + pci_disable_device(pdev); + ieee80211_free_hw(hw); +} + +#ifdef CONFIG_PM +static int +ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath5k_softc *sc = hw->priv; + + ath5k_led_off(sc); + + free_irq(pdev->irq, sc); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int +ath5k_pci_resume(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath5k_softc *sc = hw->priv; + int err; + + pci_restore_state(pdev); + + err = pci_enable_device(pdev); + if (err) + return err; + + err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); + if (err) { + ATH5K_ERR(sc, "request_irq failed\n"); + goto err_no_irq; + } + + ath5k_led_enable(sc); + return 0; + +err_no_irq: + pci_disable_device(pdev); + return err; +} +#endif /* CONFIG_PM */ + + +/***********************\ +* Driver Initialization * +\***********************/ + +static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath5k_softc *sc = hw->priv; + struct ath_regulatory *reg = &sc->ah->ah_regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + +static int +ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + u8 mac[ETH_ALEN] = {}; + int ret; + + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); + + /* + * Check if the MAC has multi-rate retry support. + * We do this by trying to setup a fake extended + * descriptor. MAC's that don't have support will + * return false w/o doing anything. MAC's that do + * support it will return true w/o doing anything. + */ + ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); + if (ret < 0) + goto err; + if (ret > 0) + __set_bit(ATH_STAT_MRRETRY, sc->status); + + /* + * Collect the channel list. The 802.11 layer + * is resposible for filtering this list based + * on settings like the phy mode and regulatory + * domain restrictions. + */ + ret = ath5k_setup_bands(hw); + if (ret) { + ATH5K_ERR(sc, "can't get channels\n"); + goto err; + } + + /* NB: setup here so ath5k_rate_update is happy */ + if (test_bit(AR5K_MODE_11A, ah->ah_modes)) + ath5k_setcurmode(sc, AR5K_MODE_11A); + else + ath5k_setcurmode(sc, AR5K_MODE_11B); + + /* + * Allocate tx+rx descriptors and populate the lists. + */ + ret = ath5k_desc_alloc(sc, pdev); + if (ret) { + ATH5K_ERR(sc, "can't allocate descriptors\n"); + goto err; + } + + /* + * Allocate hardware transmit queues: one queue for + * beacon frames and one data queue for each QoS + * priority. Note that hw functions handle reseting + * these queues at the needed time. + */ + ret = ath5k_beaconq_setup(ah); + if (ret < 0) { + ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); + goto err_desc; + } + sc->bhalq = ret; + + sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); + if (IS_ERR(sc->txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(sc->txq); + goto err_bhal; + } + + tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); + tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); + tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); + tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); + setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); + + ret = ath5k_eeprom_read_mac(ah, mac); + if (ret) { + ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", + sc->pdev->device); + goto err_queues; + } + + SET_IEEE80211_PERM_ADDR(hw, mac); + /* All MAC address bits matter for ACKs */ + memset(sc->bssidmask, 0xff, ETH_ALEN); + ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); + + ah->ah_regulatory.current_rd = + ah->ah_capabilities.cap_eeprom.ee_regdomain; + ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); + if (ret) { + ATH5K_ERR(sc, "can't initialize regulatory system\n"); + goto err_queues; + } + + ret = ieee80211_register_hw(hw); + if (ret) { + ATH5K_ERR(sc, "can't register ieee80211 hw\n"); + goto err_queues; + } + + if (!ath_is_world_regd(&sc->ah->ah_regulatory)) + regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); + + ath5k_init_leds(sc); + + return 0; +err_queues: + ath5k_txq_release(sc); +err_bhal: + ath5k_hw_release_tx_queue(ah, sc->bhalq); +err_desc: + ath5k_desc_free(sc, pdev); +err: + return ret; +} + +static void +ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + + /* + * NB: the order of these is important: + * o call the 802.11 layer before detaching ath5k_hw to + * insure callbacks into the driver to delete global + * key cache entries can be handled + * o reclaim the tx queue data structures after calling + * the 802.11 layer as we'll get called back to reclaim + * node state and potentially want to use them + * o to cleanup the tx queues the hal is called, so detach + * it last + * XXX: ??? detach ath5k_hw ??? + * Other than that, it's straightforward... + */ + ieee80211_unregister_hw(hw); + ath5k_desc_free(sc, pdev); + ath5k_txq_release(sc); + ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); + ath5k_unregister_leds(sc); + + /* + * NB: can't reclaim these until after ieee80211_ifdetach + * returns because we'll get called back to reclaim node + * state and potentially want to use them. + */ +} + + + + +/********************\ +* Channel/mode setup * +\********************/ + +/* + * Convert IEEE channel number to MHz frequency. + */ +static inline short +ath5k_ieee2mhz(short chan) +{ + if (chan <= 14 || chan >= 27) + return ieee80211chan2mhz(chan); + else + return 2212 + chan * 20; +} + +/* + * Returns true for the channel numbers used without all_channels modparam. + */ +static bool ath5k_is_standard_channel(short chan) +{ + return ((chan <= 14) || + /* UNII 1,2 */ + ((chan & 3) == 0 && chan >= 36 && chan <= 64) || + /* midband */ + ((chan & 3) == 0 && chan >= 100 && chan <= 140) || + /* UNII-3 */ + ((chan & 3) == 1 && chan >= 149 && chan <= 165)); +} + +static unsigned int +ath5k_copy_channels(struct ath5k_hw *ah, + struct ieee80211_channel *channels, + unsigned int mode, + unsigned int max) +{ + unsigned int i, count, size, chfreq, freq, ch; + + if (!test_bit(mode, ah->ah_modes)) + return 0; + + switch (mode) { + case AR5K_MODE_11A: + case AR5K_MODE_11A_TURBO: + /* 1..220, but 2GHz frequencies are filtered by check_channel */ + size = 220 ; + chfreq = CHANNEL_5GHZ; + break; + case AR5K_MODE_11B: + case AR5K_MODE_11G: + case AR5K_MODE_11G_TURBO: + size = 26; + chfreq = CHANNEL_2GHZ; + break; + default: + ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); + return 0; + } + + for (i = 0, count = 0; i < size && max > 0; i++) { + ch = i + 1 ; + freq = ath5k_ieee2mhz(ch); + + /* Check if channel is supported by the chipset */ + if (!ath5k_channel_ok(ah, freq, chfreq)) + continue; + + if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) + continue; + + /* Write channel info and increment counter */ + channels[count].center_freq = freq; + channels[count].band = (chfreq == CHANNEL_2GHZ) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + switch (mode) { + case AR5K_MODE_11A: + case AR5K_MODE_11G: + channels[count].hw_value = chfreq | CHANNEL_OFDM; + break; + case AR5K_MODE_11A_TURBO: + case AR5K_MODE_11G_TURBO: + channels[count].hw_value = chfreq | + CHANNEL_OFDM | CHANNEL_TURBO; + break; + case AR5K_MODE_11B: + channels[count].hw_value = CHANNEL_B; + } + + count++; + max--; + } + + return count; +} + +static void +ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b) +{ + u8 i; + + for (i = 0; i < AR5K_MAX_RATES; i++) + sc->rate_idx[b->band][i] = -1; + + for (i = 0; i < b->n_bitrates; i++) { + sc->rate_idx[b->band][b->bitrates[i].hw_value] = i; + if (b->bitrates[i].hw_value_short) + sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i; + } +} + +static int +ath5k_setup_bands(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + struct ieee80211_supported_band *sband; + int max_c, count_c = 0; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS); + max_c = ARRAY_SIZE(sc->channels); + + /* 2GHz band */ + sband = &sc->sbands[IEEE80211_BAND_2GHZ]; + sband->band = IEEE80211_BAND_2GHZ; + sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0]; + + if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) { + /* G mode */ + memcpy(sband->bitrates, &ath5k_rates[0], + sizeof(struct ieee80211_rate) * 12); + sband->n_bitrates = 12; + + sband->channels = sc->channels; + sband->n_channels = ath5k_copy_channels(ah, sband->channels, + AR5K_MODE_11G, max_c); + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + count_c = sband->n_channels; + max_c -= count_c; + } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) { + /* B mode */ + memcpy(sband->bitrates, &ath5k_rates[0], + sizeof(struct ieee80211_rate) * 4); + sband->n_bitrates = 4; + + /* 5211 only supports B rates and uses 4bit rate codes + * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B) + * fix them up here: + */ + if (ah->ah_version == AR5K_AR5211) { + for (i = 0; i < 4; i++) { + sband->bitrates[i].hw_value = + sband->bitrates[i].hw_value & 0xF; + sband->bitrates[i].hw_value_short = + sband->bitrates[i].hw_value_short & 0xF; + } + } + + sband->channels = sc->channels; + sband->n_channels = ath5k_copy_channels(ah, sband->channels, + AR5K_MODE_11B, max_c); + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + count_c = sband->n_channels; + max_c -= count_c; + } + ath5k_setup_rate_idx(sc, sband); + + /* 5GHz band, A mode */ + if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) { + sband = &sc->sbands[IEEE80211_BAND_5GHZ]; + sband->band = IEEE80211_BAND_5GHZ; + sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0]; + + memcpy(sband->bitrates, &ath5k_rates[4], + sizeof(struct ieee80211_rate) * 8); + sband->n_bitrates = 8; + + sband->channels = &sc->channels[count_c]; + sband->n_channels = ath5k_copy_channels(ah, sband->channels, + AR5K_MODE_11A, max_c); + + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } + ath5k_setup_rate_idx(sc, sband); + + ath5k_debug_dump_bands(sc); + + return 0; +} + +/* + * Set/change channels. If the channel is really being changed, + * it's done by reseting the chip. To accomplish this we must + * first cleanup any pending DMA, then restart stuff after a la + * ath5k_init. + * + * Called with sc->lock. + */ +static int +ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) +{ + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", + sc->curchan->center_freq, chan->center_freq); + + if (chan->center_freq != sc->curchan->center_freq || + chan->hw_value != sc->curchan->hw_value) { + + sc->curchan = chan; + sc->curband = &sc->sbands[chan->band]; + + /* + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the + * hardware at the new frequency, and then re-enable + * the relevant bits of the h/w. + */ + return ath5k_reset(sc, true, true); + } + + return 0; +} + +static void +ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) +{ + sc->curmode = mode; + + if (mode == AR5K_MODE_11A) { + sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; + } else { + sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; + } +} + +static void +ath5k_mode_setup(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + u32 rfilt; + + /* configure rx filter */ + rfilt = sc->filter_flags; + ath5k_hw_set_rx_filter(ah, rfilt); + + if (ath5k_hw_hasbssidmask(ah)) + ath5k_hw_set_bssid_mask(ah, sc->bssidmask); + + /* configure operational mode */ + ath5k_hw_set_opmode(ah); + + ath5k_hw_set_mcast_filter(ah, 0, 0); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); +} + +static inline int +ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) +{ + int rix; + + /* return base rate on errors */ + if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES, + "hw_rix out of bounds: %x\n", hw_rix)) + return 0; + + rix = sc->rate_idx[sc->curband->band][hw_rix]; + if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) + rix = 0; + + return rix; +} + +/***************\ +* Buffers setup * +\***************/ + +static +struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) +{ + struct sk_buff *skb; + unsigned int off; + + /* + * Allocate buffer with headroom_needed space for the + * fake physical layer header at the start. + */ + skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); + + if (!skb) { + ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", + sc->rxbufsize + sc->cachelsz - 1); + return NULL; + } + /* + * Cache-line-align. This is important (for the + * 5210 at least) as not doing so causes bogus data + * in rx'd frames. + */ + off = ((unsigned long)skb->data) % sc->cachelsz; + if (off != 0) + skb_reserve(skb, sc->cachelsz - off); + + *skb_addr = pci_map_single(sc->pdev, + skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { + ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); + dev_kfree_skb(skb); + return NULL; + } + return skb; +} + +static int +ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) +{ + struct ath5k_hw *ah = sc->ah; + struct sk_buff *skb = bf->skb; + struct ath5k_desc *ds; + + if (!skb) { + skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); + if (!skb) + return -ENOMEM; + bf->skb = skb; + } + + /* + * Setup descriptors. For receive we always terminate + * the descriptor list with a self-linked entry so we'll + * not get overrun under high load (as can happen with a + * 5212 when ANI processing enables PHY error frames). + * + * To insure the last descriptor is self-linked we create + * each descriptor as self-linked and add it to the end. As + * each additional descriptor is added the previous self-linked + * entry is ``fixed'' naturally. This should be safe even + * if DMA is happening. When processing RX interrupts we + * never remove/process the last, self-linked, entry on the + * descriptor list. This insures the hardware always has + * someplace to write a new frame. + */ + ds = bf->desc; + ds->ds_link = bf->daddr; /* link to self */ + ds->ds_data = bf->skbaddr; + ah->ah_setup_rx_desc(ah, ds, + skb_tailroom(skb), /* buffer size */ + 0); + + if (sc->rxlink != NULL) + *sc->rxlink = bf->daddr; + sc->rxlink = &ds->ds_link; + return 0; +} + +static int +ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) +{ + struct ath5k_hw *ah = sc->ah; + struct ath5k_txq *txq = sc->txq; + struct ath5k_desc *ds = bf->desc; + struct sk_buff *skb = bf->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; + struct ieee80211_rate *rate; + unsigned int mrr_rate[3], mrr_tries[3]; + int i, ret; + u16 hw_rate; + u16 cts_rate = 0; + u16 duration = 0; + u8 rc_flags; + + flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; + + /* XXX endianness */ + bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + + rate = ieee80211_get_tx_rate(sc->hw, info); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + flags |= AR5K_TXDESC_NOACK; + + rc_flags = info->control.rates[0].flags; + hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? + rate->hw_value_short : rate->hw_value; + + pktlen = skb->len; + + /* FIXME: If we are in g mode and rate is a CCK rate + * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta + * from tx power (value is in dB units already) */ + if (info->control.hw_key) { + keyidx = info->control.hw_key->hw_key_idx; + pktlen += info->control.hw_key->icv_len; + } + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { + flags |= AR5K_TXDESC_RTSENA; + cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; + duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, + sc->vif, pktlen, info)); + } + if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + flags |= AR5K_TXDESC_CTSENA; + cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; + duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, + sc->vif, pktlen, info)); + } + ret = ah->ah_setup_tx_desc(ah, ds, pktlen, + ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, + (sc->power_level * 2), + hw_rate, + info->control.rates[0].count, keyidx, 0, flags, + cts_rate, duration); + if (ret) + goto err_unmap; + + memset(mrr_rate, 0, sizeof(mrr_rate)); + memset(mrr_tries, 0, sizeof(mrr_tries)); + for (i = 0; i < 3; i++) { + rate = ieee80211_get_alt_retry_rate(sc->hw, info, i); + if (!rate) + break; + + mrr_rate[i] = rate->hw_value; + mrr_tries[i] = info->control.rates[i + 1].count; + } + + ah->ah_setup_mrr_tx_desc(ah, ds, + mrr_rate[0], mrr_tries[0], + mrr_rate[1], mrr_tries[1], + mrr_rate[2], mrr_tries[2]); + + ds->ds_link = 0; + ds->ds_data = bf->skbaddr; + + spin_lock_bh(&txq->lock); + list_add_tail(&bf->list, &txq->q); + sc->tx_stats[txq->qnum].len++; + if (txq->link == NULL) /* is this first packet? */ + ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); + else /* no, so only link it */ + *txq->link = bf->daddr; + + txq->link = &ds->ds_link; + ath5k_hw_start_tx_dma(ah, txq->qnum); + mmiowb(); + spin_unlock_bh(&txq->lock); + + return 0; +err_unmap: + pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + return ret; +} + +/*******************\ +* Descriptors setup * +\*******************/ + +static int +ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) +{ + struct ath5k_desc *ds; + struct ath5k_buf *bf; + dma_addr_t da; + unsigned int i; + int ret; + + /* allocate descriptors */ + sc->desc_len = sizeof(struct ath5k_desc) * + (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); + sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); + if (sc->desc == NULL) { + ATH5K_ERR(sc, "can't allocate descriptors\n"); + ret = -ENOMEM; + goto err; + } + ds = sc->desc; + da = sc->desc_daddr; + ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n", + ds, sc->desc_len, (unsigned long long)sc->desc_daddr); + + bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF, + sizeof(struct ath5k_buf), GFP_KERNEL); + if (bf == NULL) { + ATH5K_ERR(sc, "can't allocate bufptr\n"); + ret = -ENOMEM; + goto err_free; + } + sc->bufptr = bf; + + INIT_LIST_HEAD(&sc->rxbuf); + for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) { + bf->desc = ds; + bf->daddr = da; + list_add_tail(&bf->list, &sc->rxbuf); + } + + INIT_LIST_HEAD(&sc->txbuf); + sc->txbuf_len = ATH_TXBUF; + for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, + da += sizeof(*ds)) { + bf->desc = ds; + bf->daddr = da; + list_add_tail(&bf->list, &sc->txbuf); + } + + /* beacon buffer */ + bf->desc = ds; + bf->daddr = da; + sc->bbuf = bf; + + return 0; +err_free: + pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); +err: + sc->desc = NULL; + return ret; +} + +static void +ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) +{ + struct ath5k_buf *bf; + + ath5k_txbuf_free(sc, sc->bbuf); + list_for_each_entry(bf, &sc->txbuf, list) + ath5k_txbuf_free(sc, bf); + list_for_each_entry(bf, &sc->rxbuf, list) + ath5k_rxbuf_free(sc, bf); + + /* Free memory associated with all descriptors */ + pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + + kfree(sc->bufptr); + sc->bufptr = NULL; +} + + + + + +/**************\ +* Queues setup * +\**************/ + +static struct ath5k_txq * +ath5k_txq_setup(struct ath5k_softc *sc, + int qtype, int subtype) +{ + struct ath5k_hw *ah = sc->ah; + struct ath5k_txq *txq; + struct ath5k_txq_info qi = { + .tqi_subtype = subtype, + .tqi_aifs = AR5K_TXQ_USEDEFAULT, + .tqi_cw_min = AR5K_TXQ_USEDEFAULT, + .tqi_cw_max = AR5K_TXQ_USEDEFAULT + }; + int qnum; + + /* + * Enable interrupts only for EOL and DESC conditions. + * We mark tx descriptors to receive a DESC interrupt + * when a tx queue gets deep; otherwise waiting for the + * EOL to reap descriptors. Note that this is done to + * reduce interrupt load and this only defers reaping + * descriptors, never transmitting frames. Aside from + * reducing interrupts this also permits more concurrency. + * The only potential downside is if the tx queue backs + * up in which case the top half of the kernel may backup + * due to a lack of tx descriptors. + */ + qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE | + AR5K_TXQ_FLAG_TXDESCINT_ENABLE; + qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi); + if (qnum < 0) { + /* + * NB: don't print a message, this happens + * normally on parts with too few tx queues + */ + return ERR_PTR(qnum); + } + if (qnum >= ARRAY_SIZE(sc->txqs)) { + ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n", + qnum, ARRAY_SIZE(sc->txqs)); + ath5k_hw_release_tx_queue(ah, qnum); + return ERR_PTR(-EINVAL); + } + txq = &sc->txqs[qnum]; + if (!txq->setup) { + txq->qnum = qnum; + txq->link = NULL; + INIT_LIST_HEAD(&txq->q); + spin_lock_init(&txq->lock); + txq->setup = true; + } + return &sc->txqs[qnum]; +} + +static int +ath5k_beaconq_setup(struct ath5k_hw *ah) +{ + struct ath5k_txq_info qi = { + .tqi_aifs = AR5K_TXQ_USEDEFAULT, + .tqi_cw_min = AR5K_TXQ_USEDEFAULT, + .tqi_cw_max = AR5K_TXQ_USEDEFAULT, + /* NB: for dynamic turbo, don't enable any other interrupts */ + .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE + }; + + return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi); +} + +static int +ath5k_beaconq_config(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + struct ath5k_txq_info qi; + int ret; + + ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); + if (ret) + return ret; + if (sc->opmode == NL80211_IFTYPE_AP || + sc->opmode == NL80211_IFTYPE_MESH_POINT) { + /* + * Always burst out beacon and CAB traffic + * (aifs = cwmin = cwmax = 0) + */ + qi.tqi_aifs = 0; + qi.tqi_cw_min = 0; + qi.tqi_cw_max = 0; + } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { + /* + * Adhoc mode; backoff between 0 and (2 * cw_min). + */ + qi.tqi_aifs = 0; + qi.tqi_cw_min = 0; + qi.tqi_cw_max = 2 * ah->ah_cw_min; + } + + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n", + qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max); + + ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi); + if (ret) { + ATH5K_ERR(sc, "%s: unable to update parameters for beacon " + "hardware queue!\n", __func__); + return ret; + } + + return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; +} + +static void +ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) +{ + struct ath5k_buf *bf, *bf0; + + /* + * NB: this assumes output has been stopped and + * we do not need to block ath5k_tx_tasklet + */ + spin_lock_bh(&txq->lock); + list_for_each_entry_safe(bf, bf0, &txq->q, list) { + ath5k_debug_printtxbuf(sc, bf); + + ath5k_txbuf_free(sc, bf); + + spin_lock_bh(&sc->txbuflock); + sc->tx_stats[txq->qnum].len--; + list_move_tail(&bf->list, &sc->txbuf); + sc->txbuf_len++; + spin_unlock_bh(&sc->txbuflock); + } + txq->link = NULL; + spin_unlock_bh(&txq->lock); +} + +/* + * Drain the transmit queues and reclaim resources. + */ +static void +ath5k_txq_cleanup(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + unsigned int i; + + /* XXX return value */ + if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { + /* don't touch the hardware if marked invalid */ + ath5k_hw_stop_tx_dma(ah, sc->bhalq); + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", + ath5k_hw_get_txdp(ah, sc->bhalq)); + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) + if (sc->txqs[i].setup) { + ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " + "link %p\n", + sc->txqs[i].qnum, + ath5k_hw_get_txdp(ah, + sc->txqs[i].qnum), + sc->txqs[i].link); + } + } + ieee80211_wake_queues(sc->hw); /* XXX move to callers */ + + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) + if (sc->txqs[i].setup) + ath5k_txq_drainq(sc, &sc->txqs[i]); +} + +static void +ath5k_txq_release(struct ath5k_softc *sc) +{ + struct ath5k_txq *txq = sc->txqs; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++) + if (txq->setup) { + ath5k_hw_release_tx_queue(sc->ah, txq->qnum); + txq->setup = false; + } +} + + + + +/*************\ +* RX Handling * +\*************/ + +/* + * Enable the receive h/w following a reset. + */ +static int +ath5k_rx_start(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + struct ath5k_buf *bf; + int ret; + + sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz); + + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", + sc->cachelsz, sc->rxbufsize); + + sc->rxlink = NULL; + + spin_lock_bh(&sc->rxbuflock); + list_for_each_entry(bf, &sc->rxbuf, list) { + ret = ath5k_rxbuf_setup(sc, bf); + if (ret != 0) { + spin_unlock_bh(&sc->rxbuflock); + goto err; + } + } + bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); + spin_unlock_bh(&sc->rxbuflock); + + ath5k_hw_set_rxdp(ah, bf->daddr); + ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ + ath5k_mode_setup(sc); /* set filters, etc. */ + ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ + + return 0; +err: + return ret; +} + +/* + * Disable the receive h/w in preparation for a reset. + */ +static void +ath5k_rx_stop(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + + ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ + ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ + ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ + + ath5k_debug_printrxbuffs(sc, ah); + + sc->rxlink = NULL; /* just in case */ +} + +static unsigned int +ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, + struct sk_buff *skb, struct ath5k_rx_status *rs) +{ + struct ieee80211_hdr *hdr = (void *)skb->data; + unsigned int keyix, hlen; + + if (!(rs->rs_status & AR5K_RXERR_DECRYPT) && + rs->rs_keyix != AR5K_RXKEYIX_INVALID) + return RX_FLAG_DECRYPTED; + + /* Apparently when a default key is used to decrypt the packet + the hw does not set the index used to decrypt. In such cases + get the index from the packet. */ + hlen = ieee80211_hdrlen(hdr->frame_control); + if (ieee80211_has_protected(hdr->frame_control) && + !(rs->rs_status & AR5K_RXERR_DECRYPT) && + skb->len >= hlen + 4) { + keyix = skb->data[hlen + 3] >> 6; + + if (test_bit(keyix, sc->keymap)) + return RX_FLAG_DECRYPTED; + } + + return 0; +} + + +static void +ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, + struct ieee80211_rx_status *rxs) +{ + u64 tsf, bc_tstamp; + u32 hw_tu; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + + if (ieee80211_is_beacon(mgmt->frame_control) && + le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && + memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { + /* + * Received an IBSS beacon with the same BSSID. Hardware *must* + * have updated the local TSF. We have to work around various + * hardware bugs, though... + */ + tsf = ath5k_hw_get_tsf64(sc->ah); + bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp); + hw_tu = TSF_TO_TU(tsf); + + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", + (unsigned long long)bc_tstamp, + (unsigned long long)rxs->mactime, + (unsigned long long)(rxs->mactime - bc_tstamp), + (unsigned long long)tsf); + + /* + * Sometimes the HW will give us a wrong tstamp in the rx + * status, causing the timestamp extension to go wrong. + * (This seems to happen especially with beacon frames bigger + * than 78 byte (incl. FCS)) + * But we know that the receive timestamp must be later than the + * timestamp of the beacon since HW must have synced to that. + * + * NOTE: here we assume mactime to be after the frame was + * received, not like mac80211 which defines it at the start. + */ + if (bc_tstamp > rxs->mactime) { + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "fixing mactime from %llx to %llx\n", + (unsigned long long)rxs->mactime, + (unsigned long long)tsf); + rxs->mactime = tsf; + } + + /* + * Local TSF might have moved higher than our beacon timers, + * in that case we have to update them to continue sending + * beacons. This also takes care of synchronizing beacon sending + * times with other stations. + */ + if (hw_tu >= sc->nexttbtt) + ath5k_beacon_update_timers(sc, bc_tstamp); + } +} + +static void ath5k_tasklet_beacon(unsigned long data) +{ + struct ath5k_softc *sc = (struct ath5k_softc *) data; + + /* + * Software beacon alert--time to send a beacon. + * + * In IBSS mode we use this interrupt just to + * keep track of the next TBTT (target beacon + * transmission time) in order to detect wether + * automatic TSF updates happened. + */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) { + /* XXX: only if VEOL suppported */ + u64 tsf = ath5k_hw_get_tsf64(sc->ah); + sc->nexttbtt += sc->bintval; + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "SWBA nexttbtt: %x hw_tu: %x " + "TSF: %llx\n", + sc->nexttbtt, + TSF_TO_TU(tsf), + (unsigned long long) tsf); + } else { + spin_lock(&sc->block); + ath5k_beacon_send(sc); + spin_unlock(&sc->block); + } +} + +static void +ath5k_tasklet_rx(unsigned long data) +{ + struct ieee80211_rx_status rxs = {}; + struct ath5k_rx_status rs = {}; + struct sk_buff *skb, *next_skb; + dma_addr_t next_skb_addr; + struct ath5k_softc *sc = (void *)data; + struct ath5k_buf *bf, *bf_last; + struct ath5k_desc *ds; + int ret; + int hdrlen; + int padsize; + + spin_lock(&sc->rxbuflock); + if (list_empty(&sc->rxbuf)) { + ATH5K_WARN(sc, "empty rx buf pool\n"); + goto unlock; + } + bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); + do { + rxs.flag = 0; + + bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); + BUG_ON(bf->skb == NULL); + skb = bf->skb; + ds = bf->desc; + + /* + * last buffer must not be freed to ensure proper hardware + * function. When the hardware finishes also a packet next to + * it, we are sure, it doesn't use it anymore and we can go on. + */ + if (bf_last == bf) + bf->flags |= 1; + if (bf->flags) { + struct ath5k_buf *bf_next = list_entry(bf->list.next, + struct ath5k_buf, list); + ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, + &rs); + if (ret) + break; + bf->flags &= ~1; + /* skip the overwritten one (even status is martian) */ + goto next; + } + + ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); + if (unlikely(ret == -EINPROGRESS)) + break; + else if (unlikely(ret)) { + ATH5K_ERR(sc, "error in processing rx descriptor\n"); + spin_unlock(&sc->rxbuflock); + return; + } + + if (unlikely(rs.rs_more)) { + ATH5K_WARN(sc, "unsupported jumbo\n"); + goto next; + } + + if (unlikely(rs.rs_status)) { + if (rs.rs_status & AR5K_RXERR_PHY) + goto next; + if (rs.rs_status & AR5K_RXERR_DECRYPT) { + /* + * Decrypt error. If the error occurred + * because there was no hardware key, then + * let the frame through so the upper layers + * can process it. This is necessary for 5210 + * parts which have no way to setup a ``clear'' + * key cache entry. + * + * XXX do key cache faulting + */ + if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && + !(rs.rs_status & AR5K_RXERR_CRC)) + goto accept; + } + if (rs.rs_status & AR5K_RXERR_MIC) { + rxs.flag |= RX_FLAG_MMIC_ERROR; + goto accept; + } + + /* let crypto-error packets fall through in MNTR */ + if ((rs.rs_status & + ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || + sc->opmode != NL80211_IFTYPE_MONITOR) + goto next; + } +accept: + next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); + + /* + * If we can't replace bf->skb with a new skb under memory + * pressure, just skip this packet + */ + if (!next_skb) + goto next; + + pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, + PCI_DMA_FROMDEVICE); + skb_put(skb, rs.rs_datalen); + + /* The MAC header is padded to have 32-bit boundary if the + * packet payload is non-zero. The general calculation for + * padsize would take into account odd header lengths: + * padsize = (4 - hdrlen % 4) % 4; However, since only + * even-length headers are used, padding can only be 0 or 2 + * bytes and we can optimize this a bit. In addition, we must + * not try to remove padding from short control frames that do + * not have payload. */ + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + padsize = ath5k_pad_size(hdrlen); + if (padsize) { + memmove(skb->data + padsize, skb->data, hdrlen); + skb_pull(skb, padsize); + } + + /* + * always extend the mac timestamp, since this information is + * also needed for proper IBSS merging. + * + * XXX: it might be too late to do it here, since rs_tstamp is + * 15bit only. that means TSF extension has to be done within + * 32768usec (about 32ms). it might be necessary to move this to + * the interrupt handler, like it is done in madwifi. + * + * Unfortunately we don't know when the hardware takes the rx + * timestamp (beginning of phy frame, data frame, end of rx?). + * The only thing we know is that it is hardware specific... + * On AR5213 it seems the rx timestamp is at the end of the + * frame, but i'm not sure. + * + * NOTE: mac80211 defines mactime at the beginning of the first + * data symbol. Since we don't have any time references it's + * impossible to comply to that. This affects IBSS merge only + * right now, so it's not too bad... + */ + rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); + rxs.flag |= RX_FLAG_TSFT; + + rxs.freq = sc->curchan->center_freq; + rxs.band = sc->curband->band; + + rxs.noise = sc->ah->ah_noise_floor; + rxs.signal = rxs.noise + rs.rs_rssi; + + /* An rssi of 35 indicates you should be able use + * 54 Mbps reliably. A more elaborate scheme can be used + * here but it requires a map of SNR/throughput for each + * possible mode used */ + rxs.qual = rs.rs_rssi * 100 / 35; + + /* rssi can be more than 35 though, anything above that + * should be considered at 100% */ + if (rxs.qual > 100) + rxs.qual = 100; + + rxs.antenna = rs.rs_antenna; + rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); + rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); + + if (rxs.rate_idx >= 0 && rs.rs_rate == + sc->curband->bitrates[rxs.rate_idx].hw_value_short) + rxs.flag |= RX_FLAG_SHORTPRE; + + ath5k_debug_dump_skb(sc, skb, "RX ", 0); + + /* check beacons in IBSS mode */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) + ath5k_check_ibss_tsf(sc, skb, &rxs); + + __ieee80211_rx(sc->hw, skb, &rxs); + + bf->skb = next_skb; + bf->skbaddr = next_skb_addr; +next: + list_move_tail(&bf->list, &sc->rxbuf); + } while (ath5k_rxbuf_setup(sc, bf) == 0); +unlock: + spin_unlock(&sc->rxbuflock); +} + + + + +/*************\ +* TX Handling * +\*************/ + +static void +ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) +{ + struct ath5k_tx_status ts = {}; + struct ath5k_buf *bf, *bf0; + struct ath5k_desc *ds; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + int i, ret; + + spin_lock(&txq->lock); + list_for_each_entry_safe(bf, bf0, &txq->q, list) { + ds = bf->desc; + + ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); + if (unlikely(ret == -EINPROGRESS)) + break; + else if (unlikely(ret)) { + ATH5K_ERR(sc, "error %d while processing queue %u\n", + ret, txq->qnum); + break; + } + + skb = bf->skb; + info = IEEE80211_SKB_CB(skb); + bf->skb = NULL; + + pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, + PCI_DMA_TODEVICE); + + ieee80211_tx_info_clear_status(info); + for (i = 0; i < 4; i++) { + struct ieee80211_tx_rate *r = + &info->status.rates[i]; + + if (ts.ts_rate[i]) { + r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); + r->count = ts.ts_retry[i]; + } else { + r->idx = -1; + r->count = 0; + } + } + + /* count the successful attempt as well */ + info->status.rates[ts.ts_final_idx].count++; + + if (unlikely(ts.ts_status)) { + sc->ll_stats.dot11ACKFailureCount++; + if (ts.ts_status & AR5K_TXERR_FILT) + info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + } else { + info->flags |= IEEE80211_TX_STAT_ACK; + info->status.ack_signal = ts.ts_rssi; + } + + ieee80211_tx_status(sc->hw, skb); + sc->tx_stats[txq->qnum].count++; + + spin_lock(&sc->txbuflock); + sc->tx_stats[txq->qnum].len--; + list_move_tail(&bf->list, &sc->txbuf); + sc->txbuf_len++; + spin_unlock(&sc->txbuflock); + } + if (likely(list_empty(&txq->q))) + txq->link = NULL; + spin_unlock(&txq->lock); + if (sc->txbuf_len > ATH_TXBUF / 5) + ieee80211_wake_queues(sc->hw); +} + +static void +ath5k_tasklet_tx(unsigned long data) +{ + struct ath5k_softc *sc = (void *)data; + + ath5k_tx_processq(sc, sc->txq); +} + + +/*****************\ +* Beacon handling * +\*****************/ + +/* + * Setup the beacon frame for transmit. + */ +static int +ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) +{ + struct sk_buff *skb = bf->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath5k_hw *ah = sc->ah; + struct ath5k_desc *ds; + int ret, antenna = 0; + u32 flags; + + bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " + "skbaddr %llx\n", skb, skb->data, skb->len, + (unsigned long long)bf->skbaddr); + if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { + ATH5K_ERR(sc, "beacon DMA mapping failed\n"); + return -EIO; + } + + ds = bf->desc; + + flags = AR5K_TXDESC_NOACK; + if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { + ds->ds_link = bf->daddr; /* self-linked */ + flags |= AR5K_TXDESC_VEOL; + /* + * Let hardware handle antenna switching if txantenna is not set + */ + } else { + ds->ds_link = 0; + /* + * Switch antenna every 4 beacons if txantenna is not set + * XXX assumes two antennas + */ + if (antenna == 0) + antenna = sc->bsent & 4 ? 2 : 1; + } + + /* FIXME: If we are in g mode and rate is a CCK rate + * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta + * from tx power (value is in dB units already) */ + ds->ds_data = bf->skbaddr; + ret = ah->ah_setup_tx_desc(ah, ds, skb->len, + ieee80211_get_hdrlen_from_skb(skb), + AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), + ieee80211_get_tx_rate(sc->hw, info)->hw_value, + 1, AR5K_TXKEYIX_INVALID, + antenna, flags, 0, 0); + if (ret) + goto err_unmap; + + return 0; +err_unmap: + pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + return ret; +} + +/* + * Transmit a beacon frame at SWBA. Dynamic updates to the + * frame contents are done as needed and the slot time is + * also adjusted based on current state. + * + * This is called from software irq context (beacontq or restq + * tasklets) or user context from ath5k_beacon_config. + */ +static void +ath5k_beacon_send(struct ath5k_softc *sc) +{ + struct ath5k_buf *bf = sc->bbuf; + struct ath5k_hw *ah = sc->ah; + + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); + + if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || + sc->opmode == NL80211_IFTYPE_MONITOR)) { + ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); + return; + } + /* + * Check if the previous beacon has gone out. If + * not don't don't try to post another, skip this + * period and wait for the next. Missed beacons + * indicate a problem and should not occur. If we + * miss too many consecutive beacons reset the device. + */ + if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { + sc->bmisscount++; + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "missed %u consecutive beacons\n", sc->bmisscount); + if (sc->bmisscount > 3) { /* NB: 3 is a guess */ + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "stuck beacon time (%u missed)\n", + sc->bmisscount); + tasklet_schedule(&sc->restq); + } + return; + } + if (unlikely(sc->bmisscount != 0)) { + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "resume beacon xmit after %u misses\n", + sc->bmisscount); + sc->bmisscount = 0; + } + + /* + * Stop any current dma and put the new frame on the queue. + * This should never fail since we check above that no frames + * are still pending on the queue. + */ + if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { + ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); + /* NB: hw still stops DMA, so proceed */ + } + + ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); + ath5k_hw_start_tx_dma(ah, sc->bhalq); + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", + sc->bhalq, (unsigned long long)bf->daddr, bf->desc); + + sc->bsent++; +} + + +/** + * ath5k_beacon_update_timers - update beacon timers + * + * @sc: struct ath5k_softc pointer we are operating on + * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a + * beacon timer update based on the current HW TSF. + * + * Calculate the next target beacon transmit time (TBTT) based on the timestamp + * of a received beacon or the current local hardware TSF and write it to the + * beacon timer registers. + * + * This is called in a variety of situations, e.g. when a beacon is received, + * when a TSF update has been detected, but also when an new IBSS is created or + * when we otherwise know we have to update the timers, but we keep it in this + * function to have it all together in one place. + */ +static void +ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) +{ + struct ath5k_hw *ah = sc->ah; + u32 nexttbtt, intval, hw_tu, bc_tu; + u64 hw_tsf; + + intval = sc->bintval & AR5K_BEACON_PERIOD; + if (WARN_ON(!intval)) + return; + + /* beacon TSF converted to TU */ + bc_tu = TSF_TO_TU(bc_tsf); + + /* current TSF converted to TU */ + hw_tsf = ath5k_hw_get_tsf64(ah); + hw_tu = TSF_TO_TU(hw_tsf); + +#define FUDGE 3 + /* we use FUDGE to make sure the next TBTT is ahead of the current TU */ + if (bc_tsf == -1) { + /* + * no beacons received, called internally. + * just need to refresh timers based on HW TSF. + */ + nexttbtt = roundup(hw_tu + FUDGE, intval); + } else if (bc_tsf == 0) { + /* + * no beacon received, probably called by ath5k_reset_tsf(). + * reset TSF to start with 0. + */ + nexttbtt = intval; + intval |= AR5K_BEACON_RESET_TSF; + } else if (bc_tsf > hw_tsf) { + /* + * beacon received, SW merge happend but HW TSF not yet updated. + * not possible to reconfigure timers yet, but next time we + * receive a beacon with the same BSSID, the hardware will + * automatically update the TSF and then we need to reconfigure + * the timers. + */ + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "need to wait for HW TSF sync\n"); + return; + } else { + /* + * most important case for beacon synchronization between STA. + * + * beacon received and HW TSF has been already updated by HW. + * update next TBTT based on the TSF of the beacon, but make + * sure it is ahead of our local TSF timer. + */ + nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval); + } +#undef FUDGE + + sc->nexttbtt = nexttbtt; + + intval |= AR5K_BEACON_ENA; + ath5k_hw_init_beacon(ah, nexttbtt, intval); + + /* + * debugging output last in order to preserve the time critical aspect + * of this function + */ + if (bc_tsf == -1) + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "reconfigured timers based on HW TSF\n"); + else if (bc_tsf == 0) + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "reset HW TSF and timers\n"); + else + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "updated timers based on beacon TSF\n"); + + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", + (unsigned long long) bc_tsf, + (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt); + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", + intval & AR5K_BEACON_PERIOD, + intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", + intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); +} + + +/** + * ath5k_beacon_config - Configure the beacon queues and interrupts + * + * @sc: struct ath5k_softc pointer we are operating on + * + * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA + * interrupts to detect TSF updates only. + */ +static void +ath5k_beacon_config(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + unsigned long flags; + + ath5k_hw_set_imr(ah, 0); + sc->bmisscount = 0; + sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); + + if (sc->opmode == NL80211_IFTYPE_ADHOC || + sc->opmode == NL80211_IFTYPE_MESH_POINT || + sc->opmode == NL80211_IFTYPE_AP) { + /* + * In IBSS mode we use a self-linked tx descriptor and let the + * hardware send the beacons automatically. We have to load it + * only once here. + * We use the SWBA interrupt only to keep track of the beacon + * timers in order to detect automatic TSF updates. + */ + ath5k_beaconq_config(sc); + + sc->imask |= AR5K_INT_SWBA; + + if (sc->opmode == NL80211_IFTYPE_ADHOC) { + if (ath5k_hw_hasveol(ah)) { + spin_lock_irqsave(&sc->block, flags); + ath5k_beacon_send(sc); + spin_unlock_irqrestore(&sc->block, flags); + } + } else + ath5k_beacon_update_timers(sc, -1); + } + + ath5k_hw_set_imr(ah, sc->imask); +} + + +/********************\ +* Interrupt handling * +\********************/ + +static int +ath5k_init(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + int ret, i; + + mutex_lock(&sc->lock); + + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); + + /* + * Stop anything previously setup. This is safe + * no matter this is the first time through or not. + */ + ath5k_stop_locked(sc); + + /* + * The basic interface to setting the hardware in a good + * state is ``reset''. On return the hardware is known to + * be powered up and with interrupts disabled. This must + * be followed by initialization of the appropriate bits + * and then setup of the interrupt mask. + */ + sc->curchan = sc->hw->conf.channel; + sc->curband = &sc->sbands[sc->curchan->band]; + sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | + AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | + AR5K_INT_FATAL | AR5K_INT_GLOBAL; + ret = ath5k_reset(sc, false, false); + if (ret) + goto done; + + /* + * Reset the key cache since some parts do not reset the + * contents on initial power up or resume from suspend. + */ + for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) + ath5k_hw_reset_key(ah, i); + + /* Set ack to be sent at low bit-rates */ + ath5k_hw_set_ack_bitrate_high(ah, false); + + mod_timer(&sc->calib_tim, round_jiffies(jiffies + + msecs_to_jiffies(ath5k_calinterval * 1000))); + + ret = 0; +done: + mmiowb(); + mutex_unlock(&sc->lock); + return ret; +} + +static int +ath5k_stop_locked(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", + test_bit(ATH_STAT_INVALID, sc->status)); + + /* + * Shutdown the hardware and driver: + * stop output from above + * disable interrupts + * turn off timers + * turn off the radio + * clear transmit machinery + * clear receive machinery + * drain and release tx queues + * reclaim beacon resources + * power down hardware + * + * Note that some of this work is not possible if the + * hardware is gone (invalid). + */ + ieee80211_stop_queues(sc->hw); + + if (!test_bit(ATH_STAT_INVALID, sc->status)) { + ath5k_led_off(sc); + ath5k_hw_set_imr(ah, 0); + synchronize_irq(sc->pdev->irq); + } + ath5k_txq_cleanup(sc); + if (!test_bit(ATH_STAT_INVALID, sc->status)) { + ath5k_rx_stop(sc); + ath5k_hw_phy_disable(ah); + } else + sc->rxlink = NULL; + + return 0; +} + +/* + * Stop the device, grabbing the top-level lock to protect + * against concurrent entry through ath5k_init (which can happen + * if another thread does a system call and the thread doing the + * stop is preempted). + */ +static int +ath5k_stop_hw(struct ath5k_softc *sc) +{ + int ret; + + mutex_lock(&sc->lock); + ret = ath5k_stop_locked(sc); + if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { + /* + * Set the chip in full sleep mode. Note that we are + * careful to do this only when bringing the interface + * completely to a stop. When the chip is in this state + * it must be carefully woken up or references to + * registers in the PCI clock domain may freeze the bus + * (and system). This varies by chip and is mostly an + * issue with newer parts that go to sleep more quickly. + */ + if (sc->ah->ah_mac_srev >= 0x78) { + /* + * XXX + * don't put newer MAC revisions > 7.8 to sleep because + * of the above mentioned problems + */ + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, " + "not putting device to sleep\n"); + } else { + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, + "putting device to full sleep\n"); + ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0); + } + } + ath5k_txbuf_free(sc, sc->bbuf); + + mmiowb(); + mutex_unlock(&sc->lock); + + del_timer_sync(&sc->calib_tim); + tasklet_kill(&sc->rxtq); + tasklet_kill(&sc->txtq); + tasklet_kill(&sc->restq); + tasklet_kill(&sc->beacontq); + + return ret; +} + +static irqreturn_t +ath5k_intr(int irq, void *dev_id) +{ + struct ath5k_softc *sc = dev_id; + struct ath5k_hw *ah = sc->ah; + enum ath5k_int status; + unsigned int counter = 1000; + + if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || + !ath5k_hw_is_intr_pending(ah))) + return IRQ_NONE; + + do { + ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ + ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", + status, sc->imask); + if (unlikely(status & AR5K_INT_FATAL)) { + /* + * Fatal errors are unrecoverable. + * Typically these are caused by DMA errors. + */ + tasklet_schedule(&sc->restq); + } else if (unlikely(status & AR5K_INT_RXORN)) { + tasklet_schedule(&sc->restq); + } else { + if (status & AR5K_INT_SWBA) { + tasklet_schedule(&sc->beacontq); + } + if (status & AR5K_INT_RXEOL) { + /* + * NB: the hardware should re-read the link when + * RXE bit is written, but it doesn't work at + * least on older hardware revs. + */ + sc->rxlink = NULL; + } + if (status & AR5K_INT_TXURN) { + /* bump tx trigger level */ + ath5k_hw_update_tx_triglevel(ah, true); + } + if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) + tasklet_schedule(&sc->rxtq); + if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC + | AR5K_INT_TXERR | AR5K_INT_TXEOL)) + tasklet_schedule(&sc->txtq); + if (status & AR5K_INT_BMISS) { + /* TODO */ + } + if (status & AR5K_INT_MIB) { + /* + * These stats are also used for ANI i think + * so how about updating them more often ? + */ + ath5k_hw_update_mib_counters(ah, &sc->ll_stats); + } + } + } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); + + if (unlikely(!counter)) + ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); + + return IRQ_HANDLED; +} + +static void +ath5k_tasklet_reset(unsigned long data) +{ + struct ath5k_softc *sc = (void *)data; + + ath5k_reset_wake(sc); +} + +/* + * Periodically recalibrate the PHY to account + * for temperature/environment changes. + */ +static void +ath5k_calibrate(unsigned long data) +{ + struct ath5k_softc *sc = (void *)data; + struct ath5k_hw *ah = sc->ah; + + ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", + ieee80211_frequency_to_channel(sc->curchan->center_freq), + sc->curchan->hw_value); + + if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { + /* + * Rfgain is out of bounds, reset the chip + * to load new gain values. + */ + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); + ath5k_reset_wake(sc); + } + if (ath5k_hw_phy_calibrate(ah, sc->curchan)) + ATH5K_ERR(sc, "calibration of channel %u failed\n", + ieee80211_frequency_to_channel( + sc->curchan->center_freq)); + + mod_timer(&sc->calib_tim, round_jiffies(jiffies + + msecs_to_jiffies(ath5k_calinterval * 1000))); +} + + +/********************\ +* Mac80211 functions * +\********************/ + +static int +ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_buf *bf; + unsigned long flags; + int hdrlen; + int padsize; + + ath5k_debug_dump_skb(sc, skb, "TX ", 1); + + if (sc->opmode == NL80211_IFTYPE_MONITOR) + ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); + + /* + * the hardware expects the header padded to 4 byte boundaries + * if this is not the case we add the padding after the header + */ + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + padsize = ath5k_pad_size(hdrlen); + if (padsize) { + + if (skb_headroom(skb) < padsize) { + ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" + " headroom to pad %d\n", hdrlen, padsize); + goto drop_packet; + } + skb_push(skb, padsize); + memmove(skb->data, skb->data+padsize, hdrlen); + } + + spin_lock_irqsave(&sc->txbuflock, flags); + if (list_empty(&sc->txbuf)) { + ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); + spin_unlock_irqrestore(&sc->txbuflock, flags); + ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); + goto drop_packet; + } + bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); + list_del(&bf->list); + sc->txbuf_len--; + if (list_empty(&sc->txbuf)) + ieee80211_stop_queues(hw); + spin_unlock_irqrestore(&sc->txbuflock, flags); + + bf->skb = skb; + + if (ath5k_txbuf_setup(sc, bf)) { + bf->skb = NULL; + spin_lock_irqsave(&sc->txbuflock, flags); + list_add_tail(&bf->list, &sc->txbuf); + sc->txbuf_len++; + spin_unlock_irqrestore(&sc->txbuflock, flags); + goto drop_packet; + } + return NETDEV_TX_OK; + +drop_packet: + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static int +ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel) +{ + struct ath5k_hw *ah = sc->ah; + int ret; + + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); + + if (stop) { + ath5k_hw_set_imr(ah, 0); + ath5k_txq_cleanup(sc); + ath5k_rx_stop(sc); + } + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true); + if (ret) { + ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); + goto err; + } + + ret = ath5k_rx_start(sc); + if (ret) { + ATH5K_ERR(sc, "can't start recv logic\n"); + goto err; + } + + /* + * Change channels and update the h/w rate map if we're switching; + * e.g. 11a to 11b/g. + * + * We may be doing a reset in response to an ioctl that changes the + * channel so update any state that might change as a result. + * + * XXX needed? + */ +/* ath5k_chan_change(sc, c); */ + + ath5k_beacon_config(sc); + /* intrs are enabled by ath5k_beacon_config */ + + return 0; +err: + return ret; +} + +static int +ath5k_reset_wake(struct ath5k_softc *sc) +{ + int ret; + + ret = ath5k_reset(sc, true, true); + if (!ret) + ieee80211_wake_queues(sc->hw); + + return ret; +} + +static int ath5k_start(struct ieee80211_hw *hw) +{ + return ath5k_init(hw->priv); +} + +static void ath5k_stop(struct ieee80211_hw *hw) +{ + ath5k_stop_hw(hw->priv); +} + +static int ath5k_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ath5k_softc *sc = hw->priv; + int ret; + + mutex_lock(&sc->lock); + if (sc->vif) { + ret = 0; + goto end; + } + + sc->vif = conf->vif; + + switch (conf->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_MONITOR: + sc->opmode = conf->type; + break; + default: + ret = -EOPNOTSUPP; + goto end; + } + + /* Set to a reasonable value. Note that this will + * be set to mac80211's value at ath5k_config(). */ + sc->bintval = 1000; + ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); + + ret = 0; +end: + mutex_unlock(&sc->lock); + return ret; +} + +static void +ath5k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ath5k_softc *sc = hw->priv; + u8 mac[ETH_ALEN] = {}; + + mutex_lock(&sc->lock); + if (sc->vif != conf->vif) + goto end; + + ath5k_hw_set_lladdr(sc->ah, mac); + sc->vif = NULL; +end: + mutex_unlock(&sc->lock); +} + +/* + * TODO: Phy disable/diversity etc + */ +static int +ath5k_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ath5k_softc *sc = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + int ret; + + mutex_lock(&sc->lock); + + sc->bintval = conf->beacon_int; + sc->power_level = conf->power_level; + + ret = ath5k_chan_set(sc, conf->channel); + + mutex_unlock(&sc->lock); + return ret; +} + +static int +ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + int ret = 0; + + mutex_lock(&sc->lock); + if (sc->vif != vif) { + ret = -EIO; + goto unlock; + } + if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { + /* Cache for later use during resets */ + memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); + /* XXX: assoc id is set to 0 for now, mac80211 doesn't have + * a clean way of letting us retrieve this yet. */ + ath5k_hw_set_associd(ah, ah->ah_bssid, 0); + mmiowb(); + } + if (conf->changed & IEEE80211_IFCC_BEACON && + (vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_AP)) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) { + ret = -ENOMEM; + goto unlock; + } + ath5k_beacon_update(sc, beacon); + } + +unlock: + mutex_unlock(&sc->lock); + return ret; +} + +#define SUPPORTED_FIF_FLAGS \ + FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ + FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ + FIF_BCN_PRBRESP_PROMISC +/* + * o always accept unicast, broadcast, and multicast traffic + * o multicast traffic for all BSSIDs will be enabled if mac80211 + * says it should be + * o maintain current state of phy ofdm or phy cck error reception. + * If the hardware detects any of these type of errors then + * ath5k_hw_get_rx_filter() will pass to us the respective + * hardware filters to be able to receive these type of frames. + * o probe request frames are accepted only when operating in + * hostap, adhoc, or monitor modes + * o enable promiscuous mode according to the interface state + * o accept beacons: + * - when operating in adhoc mode so the 802.11 layer creates + * node table entries for peers, + * - when operating in station mode for collecting rssi data when + * the station is otherwise quiet, or + * - when scanning + */ +static void ath5k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, + int mc_count, struct dev_mc_list *mclist) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + u32 mfilt[2], val, rfilt; + u8 pos; + int i; + + mfilt[0] = 0; + mfilt[1] = 0; + + /* Only deal with supported flags */ + changed_flags &= SUPPORTED_FIF_FLAGS; + *new_flags &= SUPPORTED_FIF_FLAGS; + + /* If HW detects any phy or radar errors, leave those filters on. + * Also, always enable Unicast, Broadcasts and Multicast + * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ + rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | + (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | + AR5K_RX_FILTER_MCAST); + + if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { + if (*new_flags & FIF_PROMISC_IN_BSS) { + rfilt |= AR5K_RX_FILTER_PROM; + __set_bit(ATH_STAT_PROMISC, sc->status); + } else { + __clear_bit(ATH_STAT_PROMISC, sc->status); + } + } + + /* Note, AR5K_RX_FILTER_MCAST is already enabled */ + if (*new_flags & FIF_ALLMULTI) { + mfilt[0] = ~0; + mfilt[1] = ~0; + } else { + for (i = 0; i < mc_count; i++) { + if (!mclist) + break; + /* calculate XOR of eight 6-bit values */ + val = get_unaligned_le32(mclist->dmi_addr + 0); + pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + val = get_unaligned_le32(mclist->dmi_addr + 3); + pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; + pos &= 0x3f; + mfilt[pos / 32] |= (1 << (pos % 32)); + /* XXX: we might be able to just do this instead, + * but not sure, needs testing, if we do use this we'd + * neet to inform below to not reset the mcast */ + /* ath5k_hw_set_mcast_filterindex(ah, + * mclist->dmi_addr[5]); */ + mclist = mclist->next; + } + } + + /* This is the best we can do */ + if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) + rfilt |= AR5K_RX_FILTER_PHYERR; + + /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons + * and probes for any BSSID, this needs testing */ + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) + rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; + + /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not + * set we should only pass on control frames for this + * station. This needs testing. I believe right now this + * enables *all* control frames, which is OK.. but + * but we should see if we can improve on granularity */ + if (*new_flags & FIF_CONTROL) + rfilt |= AR5K_RX_FILTER_CONTROL; + + /* Additional settings per mode -- this is per ath5k */ + + /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ + + if (sc->opmode == NL80211_IFTYPE_MONITOR) + rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | + AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; + if (sc->opmode != NL80211_IFTYPE_STATION) + rfilt |= AR5K_RX_FILTER_PROBEREQ; + if (sc->opmode != NL80211_IFTYPE_AP && + sc->opmode != NL80211_IFTYPE_MESH_POINT && + test_bit(ATH_STAT_PROMISC, sc->status)) + rfilt |= AR5K_RX_FILTER_PROM; + if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) || + sc->opmode == NL80211_IFTYPE_ADHOC || + sc->opmode == NL80211_IFTYPE_AP) + rfilt |= AR5K_RX_FILTER_BEACON; + if (sc->opmode == NL80211_IFTYPE_MESH_POINT) + rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | + AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; + + /* Set filters */ + ath5k_hw_set_rx_filter(ah, rfilt); + + /* Set multicast bits */ + ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); + /* Set the cached hw filter flags, this will alter actually + * be set in HW */ + sc->filter_flags = rfilt; +} + +static int +ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath5k_softc *sc = hw->priv; + int ret = 0; + + if (modparam_nohwcrypt) + return -EOPNOTSUPP; + + switch (key->alg) { + case ALG_WEP: + case ALG_TKIP: + break; + case ALG_CCMP: + return -EOPNOTSUPP; + default: + WARN_ON(1); + return -EINVAL; + } + + mutex_lock(&sc->lock); + + switch (cmd) { + case SET_KEY: + ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, + sta ? sta->addr : NULL); + if (ret) { + ATH5K_ERR(sc, "can't set the key\n"); + goto unlock; + } + __set_bit(key->keyidx, sc->keymap); + key->hw_key_idx = key->keyidx; + key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | + IEEE80211_KEY_FLAG_GENERATE_MMIC); + break; + case DISABLE_KEY: + ath5k_hw_reset_key(sc->ah, key->keyidx); + __clear_bit(key->keyidx, sc->keymap); + break; + default: + ret = -EINVAL; + goto unlock; + } + +unlock: + mmiowb(); + mutex_unlock(&sc->lock); + return ret; +} + +static int +ath5k_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + + /* Force update */ + ath5k_hw_update_mib_counters(ah, &sc->ll_stats); + + memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); + + return 0; +} + +static int +ath5k_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats) +{ + struct ath5k_softc *sc = hw->priv; + + memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); + + return 0; +} + +static u64 +ath5k_get_tsf(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + + return ath5k_hw_get_tsf64(sc->ah); +} + +static void +ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct ath5k_softc *sc = hw->priv; + + ath5k_hw_set_tsf64(sc->ah, tsf); +} + +static void +ath5k_reset_tsf(struct ieee80211_hw *hw) +{ + struct ath5k_softc *sc = hw->priv; + + /* + * in IBSS mode we need to update the beacon timers too. + * this will also reset the TSF if we call it with 0 + */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) + ath5k_beacon_update_timers(sc, 0); + else + ath5k_hw_reset_tsf(sc->ah); +} + +static int +ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) +{ + unsigned long flags; + int ret; + + ath5k_debug_dump_skb(sc, skb, "BC ", 1); + + spin_lock_irqsave(&sc->block, flags); + ath5k_txbuf_free(sc, sc->bbuf); + sc->bbuf->skb = skb; + ret = ath5k_beacon_setup(sc, sc->bbuf); + if (ret) + sc->bbuf->skb = NULL; + spin_unlock_irqrestore(&sc->block, flags); + if (!ret) { + ath5k_beacon_config(sc); + mmiowb(); + } + + return ret; +} +static void +set_beacon_filter(struct ieee80211_hw *hw, bool enable) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + u32 rfilt; + rfilt = ath5k_hw_get_rx_filter(ah); + if (enable) + rfilt |= AR5K_RX_FILTER_BEACON; + else + rfilt &= ~AR5K_RX_FILTER_BEACON; + ath5k_hw_set_rx_filter(ah, rfilt); + sc->filter_flags = rfilt; +} + +static void ath5k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct ath5k_softc *sc = hw->priv; + if (changes & BSS_CHANGED_ASSOC) { + mutex_lock(&sc->lock); + sc->assoc = bss_conf->assoc; + if (sc->opmode == NL80211_IFTYPE_STATION) + set_beacon_filter(hw, sc->assoc); + mutex_unlock(&sc->lock); + } +} diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h new file mode 100644 index 000000000000..822956114cd7 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +/* + * Defintions for the Atheros Wireless LAN controller driver. + */ +#ifndef _DEV_ATH_ATHVAR_H +#define _DEV_ATH_ATHVAR_H + +#include +#include +#include +#include +#include + +#include "ath5k.h" +#include "debug.h" + +#define ATH_RXBUF 40 /* number of RX buffers */ +#define ATH_TXBUF 200 /* number of TX buffers */ +#define ATH_BCBUF 1 /* number of beacon buffers */ + +struct ath5k_buf { + struct list_head list; + unsigned int flags; /* rx descriptor flags */ + struct ath5k_desc *desc; /* virtual addr of desc */ + dma_addr_t daddr; /* physical addr of desc */ + struct sk_buff *skb; /* skbuff for buf */ + dma_addr_t skbaddr;/* physical addr of skb data */ +}; + +/* + * Data transmit queue state. One of these exists for each + * hardware transmit queue. Packets sent to us from above + * are assigned to queues based on their priority. Not all + * devices support a complete set of hardware transmit queues. + * For those devices the array sc_ac2q will map multiple + * priorities to fewer hardware queues (typically all to one + * hardware queue). + */ +struct ath5k_txq { + unsigned int qnum; /* hardware q number */ + u32 *link; /* link ptr in last TX desc */ + struct list_head q; /* transmit queue */ + spinlock_t lock; /* lock on q and link */ + bool setup; +}; + +#define ATH5K_LED_MAX_NAME_LEN 31 + +/* + * State for LED triggers + */ +struct ath5k_led +{ + char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ + struct ath5k_softc *sc; /* driver state */ + struct led_classdev led_dev; /* led classdev */ +}; + + +#if CHAN_DEBUG +#define ATH_CHAN_MAX (26+26+26+200+200) +#else +#define ATH_CHAN_MAX (14+14+14+252+20) +#endif + +/* Software Carrier, keeps track of the driver state + * associated with an instance of a device */ +struct ath5k_softc { + struct pci_dev *pdev; /* for dma mapping */ + void __iomem *iobase; /* address of the device */ + struct mutex lock; /* dev-level lock */ + /* FIXME: how many does it really need? */ + struct ieee80211_tx_queue_stats tx_stats[16]; + struct ieee80211_low_level_stats ll_stats; + struct ieee80211_hw *hw; /* IEEE 802.11 common */ + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + struct ieee80211_channel channels[ATH_CHAN_MAX]; + struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; + s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; + enum nl80211_iftype opmode; + struct ath5k_hw *ah; /* Atheros HW */ + + struct ieee80211_supported_band *curband; + +#ifdef CONFIG_ATH5K_DEBUG + struct ath5k_dbg_info debug; /* debug info */ +#endif /* CONFIG_ATH5K_DEBUG */ + + struct ath5k_buf *bufptr; /* allocated buffer ptr */ + struct ath5k_desc *desc; /* TX/RX descriptors */ + dma_addr_t desc_daddr; /* DMA (physical) address */ + size_t desc_len; /* size of TX/RX descriptors */ + u16 cachelsz; /* cache line size */ + + DECLARE_BITMAP(status, 5); +#define ATH_STAT_INVALID 0 /* disable hardware accesses */ +#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ +#define ATH_STAT_PROMISC 2 +#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ +#define ATH_STAT_STARTED 4 /* opened & irqs enabled */ + + unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ + unsigned int curmode; /* current phy mode */ + struct ieee80211_channel *curchan; /* current h/w channel */ + + struct ieee80211_vif *vif; + + enum ath5k_int imask; /* interrupt mask copy */ + + DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ + + u8 bssidmask[ETH_ALEN]; + + unsigned int led_pin, /* GPIO pin for driving LED */ + led_on; /* pin setting for LED on */ + + struct tasklet_struct restq; /* reset tasklet */ + + unsigned int rxbufsize; /* rx size based on mtu */ + struct list_head rxbuf; /* receive buffer */ + spinlock_t rxbuflock; + u32 *rxlink; /* link ptr in last RX desc */ + struct tasklet_struct rxtq; /* rx intr tasklet */ + struct ath5k_led rx_led; /* rx led */ + + struct list_head txbuf; /* transmit buffer */ + spinlock_t txbuflock; + unsigned int txbuf_len; /* buf count in txbuf list */ + struct ath5k_txq txqs[2]; /* beacon and tx */ + + struct ath5k_txq *txq; /* beacon and tx*/ + struct tasklet_struct txtq; /* tx intr tasklet */ + struct ath5k_led tx_led; /* tx led */ + + spinlock_t block; /* protects beacon */ + struct tasklet_struct beacontq; /* beacon intr tasklet */ + struct ath5k_buf *bbuf; /* beacon buffer */ + unsigned int bhalq, /* SW q for outgoing beacons */ + bmisscount, /* missed beacon transmits */ + bintval, /* beacon interval in TU */ + bsent; + unsigned int nexttbtt; /* next beacon time in TU */ + + struct timer_list calib_tim; /* calibration timer */ + int power_level; /* Requested tx power in dbm */ + bool assoc; /* assocate state */ +}; + +#define ath5k_hw_hasbssidmask(_ah) \ + (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) +#define ath5k_hw_hasveol(_ah) \ + (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) + +#endif diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c new file mode 100644 index 000000000000..367a6c7d3cc7 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Jiri Slaby + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/**************\ +* Capabilities * +\**************/ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/* + * Fill the capabilities struct + * TODO: Merge this with EEPROM code when we are done with it + */ +int ath5k_hw_set_capabilities(struct ath5k_hw *ah) +{ + u16 ee_header; + + ATH5K_TRACE(ah->ah_sc); + /* Capabilities stored in the EEPROM */ + ee_header = ah->ah_capabilities.cap_eeprom.ee_header; + + if (ah->ah_version == AR5K_AR5210) { + /* + * Set radio capabilities + * (The AR5110 only supports the middle 5GHz band) + */ + ah->ah_capabilities.cap_range.range_5ghz_min = 5120; + ah->ah_capabilities.cap_range.range_5ghz_max = 5430; + ah->ah_capabilities.cap_range.range_2ghz_min = 0; + ah->ah_capabilities.cap_range.range_2ghz_max = 0; + + /* Set supported modes */ + __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); + __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); + } else { + /* + * XXX The tranceiver supports frequencies from 4920 to 6100GHz + * XXX and from 2312 to 2732GHz. There are problems with the + * XXX current ieee80211 implementation because the IEEE + * XXX channel mapping does not support negative channel + * XXX numbers (2312MHz is channel -19). Of course, this + * XXX doesn't matter because these channels are out of range + * XXX but some regulation domains like MKK (Japan) will + * XXX support frequencies somewhere around 4.8GHz. + */ + + /* + * Set radio capabilities + */ + + if (AR5K_EEPROM_HDR_11A(ee_header)) { + /* 4920 */ + ah->ah_capabilities.cap_range.range_5ghz_min = 5005; + ah->ah_capabilities.cap_range.range_5ghz_max = 6100; + + /* Set supported modes */ + __set_bit(AR5K_MODE_11A, + ah->ah_capabilities.cap_mode); + __set_bit(AR5K_MODE_11A_TURBO, + ah->ah_capabilities.cap_mode); + if (ah->ah_version == AR5K_AR5212) + __set_bit(AR5K_MODE_11G_TURBO, + ah->ah_capabilities.cap_mode); + } + + /* Enable 802.11b if a 2GHz capable radio (2111/5112) is + * connected */ + if (AR5K_EEPROM_HDR_11B(ee_header) || + (AR5K_EEPROM_HDR_11G(ee_header) && + ah->ah_version != AR5K_AR5211)) { + /* 2312 */ + ah->ah_capabilities.cap_range.range_2ghz_min = 2412; + ah->ah_capabilities.cap_range.range_2ghz_max = 2732; + + if (AR5K_EEPROM_HDR_11B(ee_header)) + __set_bit(AR5K_MODE_11B, + ah->ah_capabilities.cap_mode); + + if (AR5K_EEPROM_HDR_11G(ee_header) && + ah->ah_version != AR5K_AR5211) + __set_bit(AR5K_MODE_11G, + ah->ah_capabilities.cap_mode); + } + } + + /* GPIO */ + ah->ah_gpio_npins = AR5K_NUM_GPIO; + + /* Set number of supported TX queues */ + if (ah->ah_version == AR5K_AR5210) + ah->ah_capabilities.cap_queues.q_tx_num = + AR5K_NUM_TX_QUEUES_NOQCU; + else + ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; + + return 0; +} + +/* Main function used by the driver part to check caps */ +int ath5k_hw_get_capability(struct ath5k_hw *ah, + enum ath5k_capability_type cap_type, + u32 capability, u32 *result) +{ + ATH5K_TRACE(ah->ah_sc); + + switch (cap_type) { + case AR5K_CAP_NUM_TXQUEUES: + if (result) { + if (ah->ah_version == AR5K_AR5210) + *result = AR5K_NUM_TX_QUEUES_NOQCU; + else + *result = AR5K_NUM_TX_QUEUES; + goto yes; + } + case AR5K_CAP_VEOL: + goto yes; + case AR5K_CAP_COMPRESSION: + if (ah->ah_version == AR5K_AR5212) + goto yes; + else + goto no; + case AR5K_CAP_BURST: + goto yes; + case AR5K_CAP_TPC: + goto yes; + case AR5K_CAP_BSSIDMASK: + if (ah->ah_version == AR5K_AR5212) + goto yes; + else + goto no; + case AR5K_CAP_XR: + if (ah->ah_version == AR5K_AR5212) + goto yes; + else + goto no; + default: + goto no; + } + +no: + return -EINVAL; +yes: + return 0; +} + +/* + * TODO: Following functions should be part of a new function + * set_capability + */ + +int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, + u16 assoc_id) +{ + ATH5K_TRACE(ah->ah_sc); + + if (ah->ah_version == AR5K_AR5210) { + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, + AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); + return 0; + } + + return -EIO; +} + +int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + + if (ah->ah_version == AR5K_AR5210) { + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, + AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); + return 0; + } + + return -EIO; +} diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c new file mode 100644 index 000000000000..9770bb3d40f9 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2007-2008 Bruno Randolf + * + * This file is free software: you may copy, redistribute 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 file 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. If not, see . + * + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2004-2005 Atheros Communications, Inc. + * Copyright (c) 2006 Devicescape Software, Inc. + * Copyright (c) 2007 Jiri Slaby + * Copyright (c) 2007 Luis R. Rodriguez + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include "base.h" +#include "debug.h" + +static unsigned int ath5k_debug; +module_param_named(debug, ath5k_debug, uint, 0); + + +#ifdef CONFIG_ATH5K_DEBUG + +#include +#include "reg.h" + +static struct dentry *ath5k_global_debugfs; + +static int ath5k_debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + + +/* debugfs: registers */ + +struct reg { + const char *name; + int addr; +}; + +#define REG_STRUCT_INIT(r) { #r, r } + +/* just a few random registers, might want to add more */ +static const struct reg regs[] = { + REG_STRUCT_INIT(AR5K_CR), + REG_STRUCT_INIT(AR5K_RXDP), + REG_STRUCT_INIT(AR5K_CFG), + REG_STRUCT_INIT(AR5K_IER), + REG_STRUCT_INIT(AR5K_BCR), + REG_STRUCT_INIT(AR5K_RTSD0), + REG_STRUCT_INIT(AR5K_RTSD1), + REG_STRUCT_INIT(AR5K_TXCFG), + REG_STRUCT_INIT(AR5K_RXCFG), + REG_STRUCT_INIT(AR5K_RXJLA), + REG_STRUCT_INIT(AR5K_MIBC), + REG_STRUCT_INIT(AR5K_TOPS), + REG_STRUCT_INIT(AR5K_RXNOFRM), + REG_STRUCT_INIT(AR5K_TXNOFRM), + REG_STRUCT_INIT(AR5K_RPGTO), + REG_STRUCT_INIT(AR5K_RFCNT), + REG_STRUCT_INIT(AR5K_MISC), + REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT), + REG_STRUCT_INIT(AR5K_ISR), + REG_STRUCT_INIT(AR5K_PISR), + REG_STRUCT_INIT(AR5K_SISR0), + REG_STRUCT_INIT(AR5K_SISR1), + REG_STRUCT_INIT(AR5K_SISR2), + REG_STRUCT_INIT(AR5K_SISR3), + REG_STRUCT_INIT(AR5K_SISR4), + REG_STRUCT_INIT(AR5K_IMR), + REG_STRUCT_INIT(AR5K_PIMR), + REG_STRUCT_INIT(AR5K_SIMR0), + REG_STRUCT_INIT(AR5K_SIMR1), + REG_STRUCT_INIT(AR5K_SIMR2), + REG_STRUCT_INIT(AR5K_SIMR3), + REG_STRUCT_INIT(AR5K_SIMR4), + REG_STRUCT_INIT(AR5K_DCM_ADDR), + REG_STRUCT_INIT(AR5K_DCCFG), + REG_STRUCT_INIT(AR5K_CCFG), + REG_STRUCT_INIT(AR5K_CPC0), + REG_STRUCT_INIT(AR5K_CPC1), + REG_STRUCT_INIT(AR5K_CPC2), + REG_STRUCT_INIT(AR5K_CPC3), + REG_STRUCT_INIT(AR5K_CPCOVF), + REG_STRUCT_INIT(AR5K_RESET_CTL), + REG_STRUCT_INIT(AR5K_SLEEP_CTL), + REG_STRUCT_INIT(AR5K_INTPEND), + REG_STRUCT_INIT(AR5K_SFR), + REG_STRUCT_INIT(AR5K_PCICFG), + REG_STRUCT_INIT(AR5K_GPIOCR), + REG_STRUCT_INIT(AR5K_GPIODO), + REG_STRUCT_INIT(AR5K_SREV), +}; + +static void *reg_start(struct seq_file *seq, loff_t *pos) +{ + return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; +} + +static void reg_stop(struct seq_file *seq, void *p) +{ + /* nothing to do */ +} + +static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) +{ + ++*pos; + return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; +} + +static int reg_show(struct seq_file *seq, void *p) +{ + struct ath5k_softc *sc = seq->private; + struct reg *r = p; + seq_printf(seq, "%-25s0x%08x\n", r->name, + ath5k_hw_reg_read(sc->ah, r->addr)); + return 0; +} + +static const struct seq_operations register_seq_ops = { + .start = reg_start, + .next = reg_next, + .stop = reg_stop, + .show = reg_show +}; + +static int open_file_registers(struct inode *inode, struct file *file) +{ + struct seq_file *s; + int res; + res = seq_open(file, ®ister_seq_ops); + if (res == 0) { + s = file->private_data; + s->private = inode->i_private; + } + return res; +} + +static const struct file_operations fops_registers = { + .open = open_file_registers, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, + .owner = THIS_MODULE, +}; + + +/* debugfs: beacons */ + +static ssize_t read_file_beacon(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = sc->ah; + char buf[500]; + unsigned int len = 0; + unsigned int v; + u64 tsf; + + v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); + len += snprintf(buf+len, sizeof(buf)-len, + "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", + "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, + (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); + + len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n", + "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); + + len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n", + "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT)); + + v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); + len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", + "AR5K_TIMER0 (TBTT)", v, v); + + v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); + len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", + "AR5K_TIMER1 (DMA)", v, v >> 3); + + v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); + len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", + "AR5K_TIMER2 (SWBA)", v, v >> 3); + + v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); + len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", + "AR5K_TIMER3 (ATIM)", v, v); + + tsf = ath5k_hw_get_tsf64(sc->ah); + len += snprintf(buf+len, sizeof(buf)-len, + "TSF\t\t0x%016llx\tTU: %08x\n", + (unsigned long long)tsf, TSF_TO_TU(tsf)); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_beacon(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + struct ath5k_hw *ah = sc->ah; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "disable", 7) == 0) { + AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); + printk(KERN_INFO "debugfs disable beacons\n"); + } else if (strncmp(buf, "enable", 6) == 0) { + AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); + printk(KERN_INFO "debugfs enable beacons\n"); + } + return count; +} + +static const struct file_operations fops_beacon = { + .read = read_file_beacon, + .write = write_file_beacon, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + +/* debugfs: reset */ + +static ssize_t write_file_reset(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + tasklet_schedule(&sc->restq); + return count; +} + +static const struct file_operations fops_reset = { + .write = write_file_reset, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + +/* debugfs: debug level */ + +static const struct { + enum ath5k_debug_level level; + const char *name; + const char *desc; +} dbg_info[] = { + { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, + { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, + { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, + { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, + { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, + { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, + { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, + { ATH5K_DEBUG_LED, "led", "LED management" }, + { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, + { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, + { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, + { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, + { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, +}; + +static ssize_t read_file_debug(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + unsigned int i; + + len += snprintf(buf+len, sizeof(buf)-len, + "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); + + for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level & dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + } + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level == dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + unsigned int i; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { + if (strncmp(buf, dbg_info[i].name, + strlen(dbg_info[i].name)) == 0) { + sc->debug.level ^= dbg_info[i].level; /* toggle bit */ + break; + } + } + return count; +} + +static const struct file_operations fops_debug = { + .read = read_file_debug, + .write = write_file_debug, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + +/* init */ + +void +ath5k_debug_init(void) +{ + ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); +} + +void +ath5k_debug_init_device(struct ath5k_softc *sc) +{ + sc->debug.level = ath5k_debug; + + sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), + ath5k_global_debugfs); + + sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO, + sc->debug.debugfs_phydir, sc, &fops_debug); + + sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, + sc->debug.debugfs_phydir, sc, &fops_registers); + + sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, + sc->debug.debugfs_phydir, sc, &fops_beacon); + + sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, + sc->debug.debugfs_phydir, sc, &fops_reset); +} + +void +ath5k_debug_finish(void) +{ + debugfs_remove(ath5k_global_debugfs); +} + +void +ath5k_debug_finish_device(struct ath5k_softc *sc) +{ + debugfs_remove(sc->debug.debugfs_debug); + debugfs_remove(sc->debug.debugfs_registers); + debugfs_remove(sc->debug.debugfs_beacon); + debugfs_remove(sc->debug.debugfs_reset); + debugfs_remove(sc->debug.debugfs_phydir); +} + + +/* functions used in other places */ + +void +ath5k_debug_dump_bands(struct ath5k_softc *sc) +{ + unsigned int b, i; + + if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS))) + return; + + BUG_ON(!sc->sbands); + + for (b = 0; b < IEEE80211_NUM_BANDS; b++) { + struct ieee80211_supported_band *band = &sc->sbands[b]; + char bname[5]; + switch (band->band) { + case IEEE80211_BAND_2GHZ: + strcpy(bname, "2 GHz"); + break; + case IEEE80211_BAND_5GHZ: + strcpy(bname, "5 GHz"); + break; + default: + printk(KERN_DEBUG "Band not supported: %d\n", + band->band); + return; + } + printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname, + band->n_channels, band->n_bitrates); + printk(KERN_DEBUG " channels:\n"); + for (i = 0; i < band->n_channels; i++) + printk(KERN_DEBUG " %3d %d %.4x %.4x\n", + ieee80211_frequency_to_channel( + band->channels[i].center_freq), + band->channels[i].center_freq, + band->channels[i].hw_value, + band->channels[i].flags); + printk(KERN_DEBUG " rates:\n"); + for (i = 0; i < band->n_bitrates; i++) + printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", + band->bitrates[i].bitrate, + band->bitrates[i].hw_value, + band->bitrates[i].flags, + band->bitrates[i].hw_value_short); + } +} + +static inline void +ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, + struct ath5k_rx_status *rs) +{ + struct ath5k_desc *ds = bf->desc; + struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; + + printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", + ds, (unsigned long long)bf->daddr, + ds->ds_link, ds->ds_data, + rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, + rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, + !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); +} + +void +ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) +{ + struct ath5k_desc *ds; + struct ath5k_buf *bf; + struct ath5k_rx_status rs = {}; + int status; + + if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) + return; + + printk(KERN_DEBUG "rx queue %x, link %p\n", + ath5k_hw_get_rxdp(ah), sc->rxlink); + + spin_lock_bh(&sc->rxbuflock); + list_for_each_entry(bf, &sc->rxbuf, list) { + ds = bf->desc; + status = ah->ah_proc_rx_desc(ah, ds, &rs); + if (!status) + ath5k_debug_printrxbuf(bf, status == 0, &rs); + } + spin_unlock_bh(&sc->rxbuflock); +} + +void +ath5k_debug_dump_skb(struct ath5k_softc *sc, + struct sk_buff *skb, const char *prefix, int tx) +{ + char buf[16]; + + if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || + (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) + return; + + snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); + + print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, + min(200U, skb->len)); + + printk(KERN_DEBUG "\n"); +} + +void +ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) +{ + struct ath5k_desc *ds = bf->desc; + struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; + struct ath5k_tx_status ts = {}; + int done; + + if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) + return; + + done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); + + printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " + "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, + ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, + td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, + td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, + done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); +} + +#endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h new file mode 100644 index 000000000000..66f69f04e55e --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2007 Bruno Randolf + * + * This file is free software: you may copy, redistribute 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 file 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. If not, see . + * + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2004-2005 Atheros Communications, Inc. + * Copyright (c) 2006 Devicescape Software, Inc. + * Copyright (c) 2007 Jiri Slaby + * Copyright (c) 2007 Luis R. Rodriguez + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ATH5K_DEBUG_H +#define _ATH5K_DEBUG_H + +struct ath5k_softc; +struct ath5k_hw; +struct sk_buff; +struct ath5k_buf; + +struct ath5k_dbg_info { + unsigned int level; /* debug level */ + /* debugfs entries */ + struct dentry *debugfs_phydir; + struct dentry *debugfs_debug; + struct dentry *debugfs_registers; + struct dentry *debugfs_beacon; + struct dentry *debugfs_reset; +}; + +/** + * enum ath5k_debug_level - ath5k debug level + * + * @ATH5K_DEBUG_RESET: reset processing + * @ATH5K_DEBUG_INTR: interrupt handling + * @ATH5K_DEBUG_MODE: mode init/setup + * @ATH5K_DEBUG_XMIT: basic xmit operation + * @ATH5K_DEBUG_BEACON: beacon handling + * @ATH5K_DEBUG_CALIBRATE: periodic calibration + * @ATH5K_DEBUG_TXPOWER: transmit power setting + * @ATH5K_DEBUG_LED: led management + * @ATH5K_DEBUG_DUMP_RX: print received skb content + * @ATH5K_DEBUG_DUMP_TX: print transmit skb content + * @ATH5K_DEBUG_DUMPBANDS: dump bands + * @ATH5K_DEBUG_TRACE: trace function calls + * @ATH5K_DEBUG_ANY: show at any debug level + * + * The debug level is used to control the amount and type of debugging output + * we want to see. The debug level is given in calls to ATH5K_DBG to specify + * where the message should appear, and the user can control the debugging + * messages he wants to see, either by the module parameter 'debug' on module + * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can + * be combined together by bitwise OR. + */ +enum ath5k_debug_level { + ATH5K_DEBUG_RESET = 0x00000001, + ATH5K_DEBUG_INTR = 0x00000002, + ATH5K_DEBUG_MODE = 0x00000004, + ATH5K_DEBUG_XMIT = 0x00000008, + ATH5K_DEBUG_BEACON = 0x00000010, + ATH5K_DEBUG_CALIBRATE = 0x00000020, + ATH5K_DEBUG_TXPOWER = 0x00000040, + ATH5K_DEBUG_LED = 0x00000080, + ATH5K_DEBUG_DUMP_RX = 0x00000100, + ATH5K_DEBUG_DUMP_TX = 0x00000200, + ATH5K_DEBUG_DUMPBANDS = 0x00000400, + ATH5K_DEBUG_TRACE = 0x00001000, + ATH5K_DEBUG_ANY = 0xffffffff +}; + +#ifdef CONFIG_ATH5K_DEBUG + +#define ATH5K_TRACE(_sc) do { \ + if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ + printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \ + } while (0) + +#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ + if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ + ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ + __func__, __LINE__, ##__VA_ARGS__); \ + } while (0) + +#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \ + if (unlikely((_sc)->debug.level & (_m))) \ + ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ + __func__, __LINE__, ##__VA_ARGS__); \ + } while (0) + +void +ath5k_debug_init(void); + +void +ath5k_debug_init_device(struct ath5k_softc *sc); + +void +ath5k_debug_finish(void); + +void +ath5k_debug_finish_device(struct ath5k_softc *sc); + +void +ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); + +void +ath5k_debug_dump_bands(struct ath5k_softc *sc); + +void +ath5k_debug_dump_skb(struct ath5k_softc *sc, + struct sk_buff *skb, const char *prefix, int tx); + +void +ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); + +#else /* no debugging */ + +#include + +#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc)) + +static inline void __attribute__ ((format (printf, 3, 4))) +ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} + +static inline void __attribute__ ((format (printf, 3, 4))) +ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) +{} + +static inline void +ath5k_debug_init(void) {} + +static inline void +ath5k_debug_init_device(struct ath5k_softc *sc) {} + +static inline void +ath5k_debug_finish(void) {} + +static inline void +ath5k_debug_finish_device(struct ath5k_softc *sc) {} + +static inline void +ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} + +static inline void +ath5k_debug_dump_bands(struct ath5k_softc *sc) {} + +static inline void +ath5k_debug_dump_skb(struct ath5k_softc *sc, + struct sk_buff *skb, const char *prefix, int tx) {} + +static inline void +ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} + +#endif /* ifdef CONFIG_ATH5K_DEBUG */ + +#endif /* ifndef _ATH5K_DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c new file mode 100644 index 000000000000..dc30a2b70a6b --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -0,0 +1,696 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Pavel Roskin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/******************************\ + Hardware Descriptor Functions +\******************************/ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/* + * TX Descriptors + */ + +/* + * Initialize the 2-word tx control descriptor on 5210/5211 + */ +static int +ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, + unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, + unsigned int key_index, unsigned int antenna_mode, unsigned int flags, + unsigned int rtscts_rate, unsigned int rtscts_duration) +{ + u32 frame_type; + struct ath5k_hw_2w_tx_ctl *tx_ctl; + unsigned int frame_len; + + tx_ctl = &desc->ud.ds_tx5210.tx_ctl; + + /* + * Validate input + * - Zero retries don't make sense. + * - A zero rate will put the HW into a mode where it continously sends + * noise on the channel, so it is important to avoid this. + */ + if (unlikely(tx_tries0 == 0)) { + ATH5K_ERR(ah->ah_sc, "zero retries\n"); + WARN_ON(1); + return -EINVAL; + } + if (unlikely(tx_rate0 == 0)) { + ATH5K_ERR(ah->ah_sc, "zero rate\n"); + WARN_ON(1); + return -EINVAL; + } + + /* Clear descriptor */ + memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); + + /* Setup control descriptor */ + + /* Verify and set frame length */ + + /* remove padding we might have added before */ + frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; + + if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) + return -EINVAL; + + tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; + + /* Verify and set buffer length */ + + /* NB: beacon's BufLen must be a multiple of 4 bytes */ + if (type == AR5K_PKT_TYPE_BEACON) + pkt_len = roundup(pkt_len, 4); + + if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) + return -EINVAL; + + tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; + + /* + * Verify and set header length + * XXX: I only found that on 5210 code, does it work on 5211 ? + */ + if (ah->ah_version == AR5K_AR5210) { + if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) + return -EINVAL; + tx_ctl->tx_control_0 |= + AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); + } + + /*Diferences between 5210-5211*/ + if (ah->ah_version == AR5K_AR5210) { + switch (type) { + case AR5K_PKT_TYPE_BEACON: + case AR5K_PKT_TYPE_PROBE_RESP: + frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; + case AR5K_PKT_TYPE_PIFS: + frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; + default: + frame_type = type /*<< 2 ?*/; + } + + tx_ctl->tx_control_0 |= + AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | + AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); + + } else { + tx_ctl->tx_control_0 |= + AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | + AR5K_REG_SM(antenna_mode, + AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); + tx_ctl->tx_control_1 |= + AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); + } +#define _TX_FLAGS(_c, _flag) \ + if (flags & AR5K_TXDESC_##_flag) { \ + tx_ctl->tx_control_##_c |= \ + AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ + } + + _TX_FLAGS(0, CLRDMASK); + _TX_FLAGS(0, VEOL); + _TX_FLAGS(0, INTREQ); + _TX_FLAGS(0, RTSENA); + _TX_FLAGS(1, NOACK); + +#undef _TX_FLAGS + + /* + * WEP crap + */ + if (key_index != AR5K_TXKEYIX_INVALID) { + tx_ctl->tx_control_0 |= + AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; + tx_ctl->tx_control_1 |= + AR5K_REG_SM(key_index, + AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); + } + + /* + * RTS/CTS Duration [5210 ?] + */ + if ((ah->ah_version == AR5K_AR5210) && + (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) + tx_ctl->tx_control_1 |= rtscts_duration & + AR5K_2W_TX_DESC_CTL1_RTS_DURATION; + + return 0; +} + +/* + * Initialize the 4-word tx control descriptor on 5212 + */ +static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, + struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, + enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, + unsigned int tx_tries0, unsigned int key_index, + unsigned int antenna_mode, unsigned int flags, + unsigned int rtscts_rate, + unsigned int rtscts_duration) +{ + struct ath5k_hw_4w_tx_ctl *tx_ctl; + unsigned int frame_len; + + ATH5K_TRACE(ah->ah_sc); + tx_ctl = &desc->ud.ds_tx5212.tx_ctl; + + /* + * Validate input + * - Zero retries don't make sense. + * - A zero rate will put the HW into a mode where it continously sends + * noise on the channel, so it is important to avoid this. + */ + if (unlikely(tx_tries0 == 0)) { + ATH5K_ERR(ah->ah_sc, "zero retries\n"); + WARN_ON(1); + return -EINVAL; + } + if (unlikely(tx_rate0 == 0)) { + ATH5K_ERR(ah->ah_sc, "zero rate\n"); + WARN_ON(1); + return -EINVAL; + } + + tx_power += ah->ah_txpower.txp_offset; + if (tx_power > AR5K_TUNE_MAX_TXPOWER) + tx_power = AR5K_TUNE_MAX_TXPOWER; + + /* Clear descriptor */ + memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); + + /* Setup control descriptor */ + + /* Verify and set frame length */ + + /* remove padding we might have added before */ + frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; + + if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) + return -EINVAL; + + tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; + + /* Verify and set buffer length */ + + /* NB: beacon's BufLen must be a multiple of 4 bytes */ + if (type == AR5K_PKT_TYPE_BEACON) + pkt_len = roundup(pkt_len, 4); + + if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) + return -EINVAL; + + tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; + + tx_ctl->tx_control_0 |= + AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | + AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); + tx_ctl->tx_control_1 |= AR5K_REG_SM(type, + AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); + tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); + tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + +#define _TX_FLAGS(_c, _flag) \ + if (flags & AR5K_TXDESC_##_flag) { \ + tx_ctl->tx_control_##_c |= \ + AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ + } + + _TX_FLAGS(0, CLRDMASK); + _TX_FLAGS(0, VEOL); + _TX_FLAGS(0, INTREQ); + _TX_FLAGS(0, RTSENA); + _TX_FLAGS(0, CTSENA); + _TX_FLAGS(1, NOACK); + +#undef _TX_FLAGS + + /* + * WEP crap + */ + if (key_index != AR5K_TXKEYIX_INVALID) { + tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; + tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, + AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); + } + + /* + * RTS/CTS + */ + if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) { + if ((flags & AR5K_TXDESC_RTSENA) && + (flags & AR5K_TXDESC_CTSENA)) + return -EINVAL; + tx_ctl->tx_control_2 |= rtscts_duration & + AR5K_4W_TX_DESC_CTL2_RTS_DURATION; + tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, + AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); + } + + return 0; +} + +/* + * Initialize a 4-word multi rate retry tx control descriptor on 5212 + */ +static int +ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, + u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) +{ + struct ath5k_hw_4w_tx_ctl *tx_ctl; + + /* + * Rates can be 0 as long as the retry count is 0 too. + * A zero rate and nonzero retry count will put the HW into a mode where + * it continously sends noise on the channel, so it is important to + * avoid this. + */ + if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || + (tx_rate2 == 0 && tx_tries2 != 0) || + (tx_rate3 == 0 && tx_tries3 != 0))) { + ATH5K_ERR(ah->ah_sc, "zero rate\n"); + WARN_ON(1); + return -EINVAL; + } + + if (ah->ah_version == AR5K_AR5212) { + tx_ctl = &desc->ud.ds_tx5212.tx_ctl; + +#define _XTX_TRIES(_n) \ + if (tx_tries##_n) { \ + tx_ctl->tx_control_2 |= \ + AR5K_REG_SM(tx_tries##_n, \ + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ + tx_ctl->tx_control_3 |= \ + AR5K_REG_SM(tx_rate##_n, \ + AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ + } + + _XTX_TRIES(1); + _XTX_TRIES(2); + _XTX_TRIES(3); + +#undef _XTX_TRIES + + return 1; + } + + return 0; +} + +/* no mrr support for cards older than 5212 */ +static int +ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, + unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, + u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) +{ + return 0; +} + +/* + * Proccess the tx status descriptor on 5210/5211 + */ +static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_tx_status *ts) +{ + struct ath5k_hw_2w_tx_ctl *tx_ctl; + struct ath5k_hw_tx_status *tx_status; + + ATH5K_TRACE(ah->ah_sc); + + tx_ctl = &desc->ud.ds_tx5210.tx_ctl; + tx_status = &desc->ud.ds_tx5210.tx_stat; + + /* No frame has been send or error */ + if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) + return -EINPROGRESS; + + /* + * Get descriptor status + */ + ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, + AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); + ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, + AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); + ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, + AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); + /*TODO: ts->ts_virtcol + test*/ + ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, + AR5K_DESC_TX_STATUS1_SEQ_NUM); + ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, + AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); + ts->ts_antenna = 1; + ts->ts_status = 0; + ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, + AR5K_2W_TX_DESC_CTL0_XMIT_RATE); + ts->ts_retry[0] = ts->ts_longretry; + ts->ts_final_idx = 0; + + if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { + if (tx_status->tx_status_0 & + AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) + ts->ts_status |= AR5K_TXERR_XRETRY; + + if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) + ts->ts_status |= AR5K_TXERR_FIFO; + + if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) + ts->ts_status |= AR5K_TXERR_FILT; + } + + return 0; +} + +/* + * Proccess a tx status descriptor on 5212 + */ +static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_tx_status *ts) +{ + struct ath5k_hw_4w_tx_ctl *tx_ctl; + struct ath5k_hw_tx_status *tx_status; + + ATH5K_TRACE(ah->ah_sc); + + tx_ctl = &desc->ud.ds_tx5212.tx_ctl; + tx_status = &desc->ud.ds_tx5212.tx_stat; + + /* No frame has been send or error */ + if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) + return -EINPROGRESS; + + /* + * Get descriptor status + */ + ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, + AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); + ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, + AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); + ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, + AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); + ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, + AR5K_DESC_TX_STATUS1_SEQ_NUM); + ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, + AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); + ts->ts_antenna = (tx_status->tx_status_1 & + AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; + ts->ts_status = 0; + + ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, + AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); + + /* The longretry counter has the number of un-acked retries + * for the final rate. To get the total number of retries + * we have to add the retry counters for the other rates + * as well + */ + ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; + switch (ts->ts_final_idx) { + case 3: + ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); + + ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); + ts->ts_longretry += ts->ts_retry[2]; + /* fall through */ + case 2: + ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); + + ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); + ts->ts_longretry += ts->ts_retry[1]; + /* fall through */ + case 1: + ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); + + ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); + ts->ts_longretry += ts->ts_retry[0]; + /* fall through */ + case 0: + ts->ts_rate[0] = tx_ctl->tx_control_3 & + AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + break; + } + + /* TX error */ + if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { + if (tx_status->tx_status_0 & + AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) + ts->ts_status |= AR5K_TXERR_XRETRY; + + if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) + ts->ts_status |= AR5K_TXERR_FIFO; + + if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) + ts->ts_status |= AR5K_TXERR_FILT; + } + + return 0; +} + +/* + * RX Descriptors + */ + +/* + * Initialize an rx control descriptor + */ +static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + u32 size, unsigned int flags) +{ + struct ath5k_hw_rx_ctl *rx_ctl; + + ATH5K_TRACE(ah->ah_sc); + rx_ctl = &desc->ud.ds_rx.rx_ctl; + + /* + * Clear the descriptor + * If we don't clean the status descriptor, + * while scanning we get too many results, + * most of them virtual, after some secs + * of scanning system hangs. M.F. + */ + memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); + + /* Setup descriptor */ + rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; + if (unlikely(rx_ctl->rx_control_1 != size)) + return -EINVAL; + + if (flags & AR5K_RXDESC_INTREQ) + rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; + + return 0; +} + +/* + * Proccess the rx status descriptor on 5210/5211 + */ +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_rx_status *rs) +{ + struct ath5k_hw_rx_status *rx_status; + + rx_status = &desc->ud.ds_rx.u.rx_stat; + + /* No frame received / not ready */ + if (unlikely(!(rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_DONE))) + return -EINPROGRESS; + + /* + * Frame receive status + */ + rs->rs_datalen = rx_status->rx_status_0 & + AR5K_5210_RX_DESC_STATUS0_DATA_LEN; + rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); + rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); + rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); + rs->rs_more = !!(rx_status->rx_status_0 & + AR5K_5210_RX_DESC_STATUS0_MORE); + /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ + rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); + rs->rs_status = 0; + rs->rs_phyerr = 0; + + /* + * Key table status + */ + if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) + rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); + else + rs->rs_keyix = AR5K_RXKEYIX_INVALID; + + /* + * Receive/descriptor errors + */ + if (!(rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { + if (rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) + rs->rs_status |= AR5K_RXERR_CRC; + + if (rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) + rs->rs_status |= AR5K_RXERR_FIFO; + + if (rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { + rs->rs_status |= AR5K_RXERR_PHY; + rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); + } + + if (rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) + rs->rs_status |= AR5K_RXERR_DECRYPT; + } + + return 0; +} + +/* + * Proccess the rx status descriptor on 5212 + */ +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_rx_status *rs) +{ + struct ath5k_hw_rx_status *rx_status; + struct ath5k_hw_rx_error *rx_err; + + ATH5K_TRACE(ah->ah_sc); + rx_status = &desc->ud.ds_rx.u.rx_stat; + + /* Overlay on error */ + rx_err = &desc->ud.ds_rx.u.rx_err; + + /* No frame received / not ready */ + if (unlikely(!(rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_DONE))) + return -EINPROGRESS; + + /* + * Frame receive status + */ + rs->rs_datalen = rx_status->rx_status_0 & + AR5K_5212_RX_DESC_STATUS0_DATA_LEN; + rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); + rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); + rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); + rs->rs_more = !!(rx_status->rx_status_0 & + AR5K_5212_RX_DESC_STATUS0_MORE); + rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); + rs->rs_status = 0; + rs->rs_phyerr = 0; + + /* + * Key table status + */ + if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) + rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); + else + rs->rs_keyix = AR5K_RXKEYIX_INVALID; + + /* + * Receive/descriptor errors + */ + if (!(rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) + rs->rs_status |= AR5K_RXERR_CRC; + + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { + rs->rs_status |= AR5K_RXERR_PHY; + rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, + AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); + } + + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) + rs->rs_status |= AR5K_RXERR_DECRYPT; + + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) + rs->rs_status |= AR5K_RXERR_MIC; + } + + return 0; +} + +/* + * Init function pointers inside ath5k_hw struct + */ +int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) +{ + + if (ah->ah_version != AR5K_AR5210 && + ah->ah_version != AR5K_AR5211 && + ah->ah_version != AR5K_AR5212) + return -ENOTSUPP; + + /* XXX: What is this magic value and where is it used ? */ + if (ah->ah_version == AR5K_AR5212) + ah->ah_magic = AR5K_EEPROM_MAGIC_5212; + else if (ah->ah_version == AR5K_AR5211) + ah->ah_magic = AR5K_EEPROM_MAGIC_5211; + + if (ah->ah_version == AR5K_AR5212) { + ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; + ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; + ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; + ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; + } else { + ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; + ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; + ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; + ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; + } + + if (ah->ah_version == AR5K_AR5212) + ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; + else if (ah->ah_version <= AR5K_AR5211) + ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; + + return 0; +} + diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h new file mode 100644 index 000000000000..56158c804e3e --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/desc.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * Internal RX/TX descriptor structures + * (rX: reserved fields possibily used by future versions of the ar5k chipset) + */ + +/* + * common hardware RX control descriptor + */ +struct ath5k_hw_rx_ctl { + u32 rx_control_0; /* RX control word 0 */ + u32 rx_control_1; /* RX control word 1 */ +} __packed; + +/* RX control word 0 field/sflags */ +#define AR5K_DESC_RX_CTL0 0x00000000 + +/* RX control word 1 fields/flags */ +#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff +#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 + +/* + * common hardware RX status descriptor + * 5210/11 and 5212 differ only in the flags defined below + */ +struct ath5k_hw_rx_status { + u32 rx_status_0; /* RX status word 0 */ + u32 rx_status_1; /* RX status word 1 */ +} __packed; + +/* 5210/5211 */ +/* RX status word 0 fields/flags */ +#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff +#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 + +/* RX status word 1 fields/flags */ +#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 +#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 +#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 +#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 +#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 +#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 +#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 +#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 +#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 +#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 + +/* 5212 */ +/* RX status word 0 fields/flags */ +#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff +#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 +#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 + +/* RX status word 1 fields/flags */ +#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 +#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 +#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 +#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 +#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 +#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 +#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 +#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 +#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 + +/* + * common hardware RX error descriptor + */ +struct ath5k_hw_rx_error { + u32 rx_error_0; /* RX status word 0 */ + u32 rx_error_1; /* RX status word 1 */ +} __packed; + +/* RX error word 0 fields/flags */ +#define AR5K_RX_DESC_ERROR0 0x00000000 + +/* RX error word 1 fields/flags */ +#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 +#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 + +/* PHY Error codes */ +#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 +#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 +#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 +#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 +#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 +#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 +#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 +#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 + +/* + * 5210/5211 hardware 2-word TX control descriptor + */ +struct ath5k_hw_2w_tx_ctl { + u32 tx_control_0; /* TX control word 0 */ + u32 tx_control_1; /* TX control word 1 */ +} __packed; + +/* TX control word 0 fields/flags */ +#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff +#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ +#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 +#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 +#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 +#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 +#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 +#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ +#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ +#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ +#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 +#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 +#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 + +#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ + (ah->ah_version == AR5K_AR5210 ? \ + AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ + AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) + +#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 +#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 +#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 + +/* TX control word 1 fields/flags */ +#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff +#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 +#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 +#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 + +#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ + (ah->ah_version == AR5K_AR5210 ? \ + AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ + AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) + +#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 +#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ +#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 +#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ +#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ + +/* Frame types */ +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c +#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 + +/* + * 5212 hardware 4-word TX control descriptor + */ +struct ath5k_hw_4w_tx_ctl { + u32 tx_control_0; /* TX control word 0 */ + +#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff +#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 +#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 +#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 +#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 +#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 +#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 +#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 +#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 +#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 +#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 + + u32 tx_control_1; /* TX control word 1 */ + +#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff +#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 +#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 +#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 +#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 +#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 +#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 +#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 +#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 +#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 +#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 +#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 +#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 + + u32 tx_control_2; /* TX control word 2 */ + +#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff +#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 +#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 + + u32 tx_control_3; /* TX control word 3 */ + +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 +#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 +#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 +#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 +} __packed; + +/* + * Common TX status descriptor + */ +struct ath5k_hw_tx_status { + u32 tx_status_0; /* TX status word 0 */ + u32 tx_status_1; /* TX status word 1 */ +} __packed; + +/* TX status word 0 fields/flags */ +#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 +#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 +#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 +#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 +/*??? +#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 +#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 +*/ +#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 +#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 +/*??? +#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 +#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 +*/ +#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 +#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 +#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 +#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 +#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 +#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 + +/* TX status word 1 fields/flags */ +#define AR5K_DESC_TX_STATUS1_DONE 0x00000001 +#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe +#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 +#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 +#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 +#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 +#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 +#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 +#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 + +/* + * 5210/5211 hardware TX descriptor + */ +struct ath5k_hw_5210_tx_desc { + struct ath5k_hw_2w_tx_ctl tx_ctl; + struct ath5k_hw_tx_status tx_stat; +} __packed; + +/* + * 5212 hardware TX descriptor + */ +struct ath5k_hw_5212_tx_desc { + struct ath5k_hw_4w_tx_ctl tx_ctl; + struct ath5k_hw_tx_status tx_stat; +} __packed; + +/* + * common hardware RX descriptor + */ +struct ath5k_hw_all_rx_desc { + struct ath5k_hw_rx_ctl rx_ctl; + union { + struct ath5k_hw_rx_status rx_stat; + struct ath5k_hw_rx_error rx_err; + } u; +} __packed; + +/* + * Atheros hardware descriptor + * This is read and written to by the hardware + */ +struct ath5k_desc { + u32 ds_link; /* physical address of the next descriptor */ + u32 ds_data; /* physical address of data buffer (skb) */ + + union { + struct ath5k_hw_5210_tx_desc ds_tx5210; + struct ath5k_hw_5212_tx_desc ds_tx5212; + struct ath5k_hw_all_rx_desc ds_rx; + } ud; +} __packed; + +#define AR5K_RXDESC_INTREQ 0x0020 + +#define AR5K_TXDESC_CLRDMASK 0x0001 +#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/ +#define AR5K_TXDESC_RTSENA 0x0004 +#define AR5K_TXDESC_CTSENA 0x0008 +#define AR5K_TXDESC_INTREQ 0x0010 +#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ + diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c new file mode 100644 index 000000000000..b65b4feb2d28 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -0,0 +1,705 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/*************************************\ +* DMA and interrupt masking functions * +\*************************************/ + +/* + * dma.c - DMA and interrupt masking functions + * + * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and + * handle queue setup for 5210 chipset (rest are handled on qcu.c). + * Also we setup interrupt mask register (IMR) and read the various iterrupt + * status registers (ISR). + * + * TODO: Handle SISR on 5211+ and introduce a function to return the queue + * number that resulted the interrupt. + */ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/*********\ +* Receive * +\*********/ + +/** + * ath5k_hw_start_rx_dma - Start DMA receive + * + * @ah: The &struct ath5k_hw + */ +void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); +} + +/** + * ath5k_hw_stop_rx_dma - Stop DMA receive + * + * @ah: The &struct ath5k_hw + */ +int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) +{ + unsigned int i; + + ATH5K_TRACE(ah->ah_sc); + ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); + + /* + * It may take some time to disable the DMA receive unit + */ + for (i = 1000; i > 0 && + (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; + i--) + udelay(10); + + return i ? 0 : -EBUSY; +} + +/** + * ath5k_hw_get_rxdp - Get RX Descriptor's address + * + * @ah: The &struct ath5k_hw + * + * XXX: Is RXDP read and clear ? + */ +u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) +{ + return ath5k_hw_reg_read(ah, AR5K_RXDP); +} + +/** + * ath5k_hw_set_rxdp - Set RX Descriptor's address + * + * @ah: The &struct ath5k_hw + * @phys_addr: RX descriptor address + * + * XXX: Should we check if rx is enabled before setting rxdp ? + */ +void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) +{ + ATH5K_TRACE(ah->ah_sc); + + ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); +} + + +/**********\ +* Transmit * +\**********/ + +/** + * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue + * + * @ah: The &struct ath5k_hw + * @queue: The hw queue number + * + * Start DMA transmit for a specific queue and since 5210 doesn't have + * QCU/DCU, set up queue parameters for 5210 here based on queue type (one + * queue for normal data and one queue for beacons). For queue setup + * on newer chips check out qcu.c. Returns -EINVAL if queue number is out + * of range or if queue is already disabled. + * + * NOTE: Must be called after setting up tx control descriptor for that + * queue (see below). + */ +int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) +{ + u32 tx_queue; + + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* Return if queue is declared inactive */ + if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) + return -EIO; + + if (ah->ah_version == AR5K_AR5210) { + tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); + + /* + * Set the queue by type on 5210 + */ + switch (ah->ah_txq[queue].tqi_type) { + case AR5K_TX_QUEUE_DATA: + tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; + break; + case AR5K_TX_QUEUE_BEACON: + tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; + ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, + AR5K_BSR); + break; + case AR5K_TX_QUEUE_CAB: + tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; + ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | + AR5K_BCR_BDMAE, AR5K_BSR); + break; + default: + return -EINVAL; + } + /* Start queue */ + ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); + } else { + /* Return if queue is disabled */ + if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) + return -EIO; + + /* Start queue */ + AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); + } + + return 0; +} + +/** + * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue + * + * @ah: The &struct ath5k_hw + * @queue: The hw queue number + * + * Stop DMA transmit on a specific hw queue and drain queue so we don't + * have any pending frames. Returns -EBUSY if we still have pending frames, + * -EINVAL if queue number is out of range. + * + */ +int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) +{ + unsigned int i = 40; + u32 tx_queue, pending; + + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* Return if queue is declared inactive */ + if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) + return -EIO; + + if (ah->ah_version == AR5K_AR5210) { + tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); + + /* + * Set by queue type + */ + switch (ah->ah_txq[queue].tqi_type) { + case AR5K_TX_QUEUE_DATA: + tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; + break; + case AR5K_TX_QUEUE_BEACON: + case AR5K_TX_QUEUE_CAB: + /* XXX Fix me... */ + tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; + ath5k_hw_reg_write(ah, 0, AR5K_BSR); + break; + default: + return -EINVAL; + } + + /* Stop queue */ + ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); + } else { + /* + * Schedule TX disable and wait until queue is empty + */ + AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); + + /*Check for pending frames*/ + do { + pending = ath5k_hw_reg_read(ah, + AR5K_QUEUE_STATUS(queue)) & + AR5K_QCU_STS_FRMPENDCNT; + udelay(100); + } while (--i && pending); + + /* For 2413+ order PCU to drop packets using + * QUIET mechanism */ + if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && + pending){ + /* Set periodicity and duration */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| + AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), + AR5K_QUIET_CTL2); + + /* Enable quiet period for current TSF */ + ath5k_hw_reg_write(ah, + AR5K_QUIET_CTL1_QT_EN | + AR5K_REG_SM(ath5k_hw_reg_read(ah, + AR5K_TSF_L32_5211) >> 10, + AR5K_QUIET_CTL1_NEXT_QT_TSF), + AR5K_QUIET_CTL1); + + /* Force channel idle high */ + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, + AR5K_DIAG_SW_CHANEL_IDLE_HIGH); + + /* Wait a while and disable mechanism */ + udelay(200); + AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, + AR5K_QUIET_CTL1_QT_EN); + + /* Re-check for pending frames */ + i = 40; + do { + pending = ath5k_hw_reg_read(ah, + AR5K_QUEUE_STATUS(queue)) & + AR5K_QCU_STS_FRMPENDCNT; + udelay(100); + } while (--i && pending); + + AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, + AR5K_DIAG_SW_CHANEL_IDLE_HIGH); + } + + /* Clear register */ + ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); + if (pending) + return -EBUSY; + } + + /* TODO: Check for success on 5210 else return error */ + return 0; +} + +/** + * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue + * + * @ah: The &struct ath5k_hw + * @queue: The hw queue number + * + * Get TX descriptor's address for a specific queue. For 5210 we ignore + * the queue number and use tx queue type since we only have 2 queues. + * We use TXDP0 for normal data queue and TXDP1 for beacon queue. + * For newer chips with QCU/DCU we just read the corresponding TXDP register. + * + * XXX: Is TXDP read and clear ? + */ +u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) +{ + u16 tx_reg; + + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* + * Get the transmit queue descriptor pointer from the selected queue + */ + /*5210 doesn't have QCU*/ + if (ah->ah_version == AR5K_AR5210) { + switch (ah->ah_txq[queue].tqi_type) { + case AR5K_TX_QUEUE_DATA: + tx_reg = AR5K_NOQCU_TXDP0; + break; + case AR5K_TX_QUEUE_BEACON: + case AR5K_TX_QUEUE_CAB: + tx_reg = AR5K_NOQCU_TXDP1; + break; + default: + return 0xffffffff; + } + } else { + tx_reg = AR5K_QUEUE_TXDP(queue); + } + + return ath5k_hw_reg_read(ah, tx_reg); +} + +/** + * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue + * + * @ah: The &struct ath5k_hw + * @queue: The hw queue number + * + * Set TX descriptor's address for a specific queue. For 5210 we ignore + * the queue number and we use tx queue type since we only have 2 queues + * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue. + * For newer chips with QCU/DCU we just set the corresponding TXDP register. + * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still + * active. + */ +int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) +{ + u16 tx_reg; + + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* + * Set the transmit queue descriptor pointer register by type + * on 5210 + */ + if (ah->ah_version == AR5K_AR5210) { + switch (ah->ah_txq[queue].tqi_type) { + case AR5K_TX_QUEUE_DATA: + tx_reg = AR5K_NOQCU_TXDP0; + break; + case AR5K_TX_QUEUE_BEACON: + case AR5K_TX_QUEUE_CAB: + tx_reg = AR5K_NOQCU_TXDP1; + break; + default: + return -EINVAL; + } + } else { + /* + * Set the transmit queue descriptor pointer for + * the selected queue on QCU for 5211+ + * (this won't work if the queue is still active) + */ + if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + return -EIO; + + tx_reg = AR5K_QUEUE_TXDP(queue); + } + + /* Set descriptor pointer */ + ath5k_hw_reg_write(ah, phys_addr, tx_reg); + + return 0; +} + +/** + * ath5k_hw_update_tx_triglevel - Update tx trigger level + * + * @ah: The &struct ath5k_hw + * @increase: Flag to force increase of trigger level + * + * This function increases/decreases the tx trigger level for the tx fifo + * buffer (aka FIFO threshold) that is used to indicate when PCU flushes + * the buffer and transmits it's data. Lowering this results sending small + * frames more quickly but can lead to tx underruns, raising it a lot can + * result other problems (i think bmiss is related). Right now we start with + * the lowest possible (64Bytes) and if we get tx underrun we increase it using + * the increase flag. Returns -EIO if we have have reached maximum/minimum. + * + * XXX: Link this with tx DMA size ? + * XXX: Use it to save interrupts ? + * TODO: Needs testing, i think it's related to bmiss... + */ +int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) +{ + u32 trigger_level, imr; + int ret = -EIO; + + ATH5K_TRACE(ah->ah_sc); + + /* + * Disable interrupts by setting the mask + */ + imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); + + trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), + AR5K_TXCFG_TXFULL); + + if (!increase) { + if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) + goto done; + } else + trigger_level += + ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); + + /* + * Update trigger level on success + */ + if (ah->ah_version == AR5K_AR5210) + ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); + else + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_TXFULL, trigger_level); + + ret = 0; + +done: + /* + * Restore interrupt mask + */ + ath5k_hw_set_imr(ah, imr); + + return ret; +} + +/*******************\ +* Interrupt masking * +\*******************/ + +/** + * ath5k_hw_is_intr_pending - Check if we have pending interrupts + * + * @ah: The &struct ath5k_hw + * + * Check if we have pending interrupts to process. Returns 1 if we + * have pending interrupts and 0 if we haven't. + */ +bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; +} + +/** + * ath5k_hw_get_isr - Get interrupt status + * + * @ah: The @struct ath5k_hw + * @interrupt_mask: Driver's interrupt mask used to filter out + * interrupts in sw. + * + * This function is used inside our interrupt handler to determine the reason + * for the interrupt by reading Primary Interrupt Status Register. Returns an + * abstract interrupt status mask which is mostly ISR with some uncommon bits + * being mapped on some standard non hw-specific positions + * (check out &ath5k_int). + * + * NOTE: We use read-and-clear register, so after this function is called ISR + * is zeroed. + */ +int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) +{ + u32 data; + + ATH5K_TRACE(ah->ah_sc); + + /* + * Read interrupt status from the Interrupt Status register + * on 5210 + */ + if (ah->ah_version == AR5K_AR5210) { + data = ath5k_hw_reg_read(ah, AR5K_ISR); + if (unlikely(data == AR5K_INT_NOCARD)) { + *interrupt_mask = data; + return -ENODEV; + } + } else { + /* + * Read interrupt status from Interrupt + * Status Register shadow copy (Read And Clear) + * + * Note: PISR/SISR Not available on 5210 + */ + data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); + if (unlikely(data == AR5K_INT_NOCARD)) { + *interrupt_mask = data; + return -ENODEV; + } + } + + /* + * Get abstract interrupt mask (driver-compatible) + */ + *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; + + if (ah->ah_version != AR5K_AR5210) { + u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2); + + /*HIU = Host Interface Unit (PCI etc)*/ + if (unlikely(data & (AR5K_ISR_HIUERR))) + *interrupt_mask |= AR5K_INT_FATAL; + + /*Beacon Not Ready*/ + if (unlikely(data & (AR5K_ISR_BNR))) + *interrupt_mask |= AR5K_INT_BNR; + + if (unlikely(sisr2 & (AR5K_SISR2_SSERR | + AR5K_SISR2_DPERR | + AR5K_SISR2_MCABT))) + *interrupt_mask |= AR5K_INT_FATAL; + + if (data & AR5K_ISR_TIM) + *interrupt_mask |= AR5K_INT_TIM; + + if (data & AR5K_ISR_BCNMISC) { + if (sisr2 & AR5K_SISR2_TIM) + *interrupt_mask |= AR5K_INT_TIM; + if (sisr2 & AR5K_SISR2_DTIM) + *interrupt_mask |= AR5K_INT_DTIM; + if (sisr2 & AR5K_SISR2_DTIM_SYNC) + *interrupt_mask |= AR5K_INT_DTIM_SYNC; + if (sisr2 & AR5K_SISR2_BCN_TIMEOUT) + *interrupt_mask |= AR5K_INT_BCN_TIMEOUT; + if (sisr2 & AR5K_SISR2_CAB_TIMEOUT) + *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; + } + + if (data & AR5K_ISR_RXDOPPLER) + *interrupt_mask |= AR5K_INT_RX_DOPPLER; + if (data & AR5K_ISR_QCBRORN) { + *interrupt_mask |= AR5K_INT_QCBRORN; + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), + AR5K_SISR3_QCBRORN); + } + if (data & AR5K_ISR_QCBRURN) { + *interrupt_mask |= AR5K_INT_QCBRURN; + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), + AR5K_SISR3_QCBRURN); + } + if (data & AR5K_ISR_QTRIG) { + *interrupt_mask |= AR5K_INT_QTRIG; + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR4), + AR5K_SISR4_QTRIG); + } + + if (data & AR5K_ISR_TXOK) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), + AR5K_SISR0_QCU_TXOK); + + if (data & AR5K_ISR_TXDESC) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), + AR5K_SISR0_QCU_TXDESC); + + if (data & AR5K_ISR_TXERR) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), + AR5K_SISR1_QCU_TXERR); + + if (data & AR5K_ISR_TXEOL) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), + AR5K_SISR1_QCU_TXEOL); + + if (data & AR5K_ISR_TXURN) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR2), + AR5K_SISR2_QCU_TXURN); + } else { + if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT + | AR5K_ISR_HIUERR | AR5K_ISR_DPERR))) + *interrupt_mask |= AR5K_INT_FATAL; + + /* + * XXX: BMISS interrupts may occur after association. + * I found this on 5210 code but it needs testing. If this is + * true we should disable them before assoc and re-enable them + * after a successful assoc + some jiffies. + interrupt_mask &= ~AR5K_INT_BMISS; + */ + } + + /* + * In case we didn't handle anything, + * print the register value. + */ + if (unlikely(*interrupt_mask == 0 && net_ratelimit())) + ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr); + + return 0; +} + +/** + * ath5k_hw_set_imr - Set interrupt mask + * + * @ah: The &struct ath5k_hw + * @new_mask: The new interrupt mask to be set + * + * Set the interrupt mask in hw to save interrupts. We do that by mapping + * ath5k_int bits to hw-specific bits to remove abstraction and writing + * Interrupt Mask Register. + */ +enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) +{ + enum ath5k_int old_mask, int_mask; + + old_mask = ah->ah_imr; + + /* + * Disable card interrupts to prevent any race conditions + * (they will be re-enabled afterwards if AR5K_INT GLOBAL + * is set again on the new mask). + */ + if (old_mask & AR5K_INT_GLOBAL) { + ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); + ath5k_hw_reg_read(ah, AR5K_IER); + } + + /* + * Add additional, chipset-dependent interrupt mask flags + * and write them to the IMR (interrupt mask register). + */ + int_mask = new_mask & AR5K_INT_COMMON; + + if (ah->ah_version != AR5K_AR5210) { + /* Preserve per queue TXURN interrupt mask */ + u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) + & AR5K_SIMR2_QCU_TXURN; + + if (new_mask & AR5K_INT_FATAL) { + int_mask |= AR5K_IMR_HIUERR; + simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR + | AR5K_SIMR2_DPERR); + } + + /*Beacon Not Ready*/ + if (new_mask & AR5K_INT_BNR) + int_mask |= AR5K_INT_BNR; + + if (new_mask & AR5K_INT_TIM) + int_mask |= AR5K_IMR_TIM; + + if (new_mask & AR5K_INT_TIM) + simr2 |= AR5K_SISR2_TIM; + if (new_mask & AR5K_INT_DTIM) + simr2 |= AR5K_SISR2_DTIM; + if (new_mask & AR5K_INT_DTIM_SYNC) + simr2 |= AR5K_SISR2_DTIM_SYNC; + if (new_mask & AR5K_INT_BCN_TIMEOUT) + simr2 |= AR5K_SISR2_BCN_TIMEOUT; + if (new_mask & AR5K_INT_CAB_TIMEOUT) + simr2 |= AR5K_SISR2_CAB_TIMEOUT; + + if (new_mask & AR5K_INT_RX_DOPPLER) + int_mask |= AR5K_IMR_RXDOPPLER; + + /* Note: Per queue interrupt masks + * are set via reset_tx_queue (qcu.c) */ + ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); + ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); + + } else { + if (new_mask & AR5K_INT_FATAL) + int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT + | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); + + ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); + } + + /* If RXNOFRM interrupt is masked disable it + * by setting AR5K_RXNOFRM to zero */ + if (!(new_mask & AR5K_INT_RXNOFRM)) + ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM); + + /* Store new interrupt mask */ + ah->ah_imr = new_mask; + + /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */ + if (new_mask & AR5K_INT_GLOBAL) { + ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); + ath5k_hw_reg_read(ah, AR5K_IER); + } + + return old_mask; +} + diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c new file mode 100644 index 000000000000..c0fb3b09ba45 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -0,0 +1,1769 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2008-2009 Felix Fietkau + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/*************************************\ +* EEPROM access functions and helpers * +\*************************************/ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/* + * Read from eeprom + */ +static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) +{ + u32 status, timeout; + + ATH5K_TRACE(ah->ah_sc); + /* + * Initialize EEPROM access + */ + if (ah->ah_version == AR5K_AR5210) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); + (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); + } else { + ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); + AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, + AR5K_EEPROM_CMD_READ); + } + + for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { + status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); + if (status & AR5K_EEPROM_STAT_RDDONE) { + if (status & AR5K_EEPROM_STAT_RDERR) + return -EIO; + *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & + 0xffff); + return 0; + } + udelay(15); + } + + return -ETIMEDOUT; +} + +/* + * Translate binary channel representation in EEPROM to frequency + */ +static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, + unsigned int mode) +{ + u16 val; + + if (bin == AR5K_EEPROM_CHANNEL_DIS) + return bin; + + if (mode == AR5K_EEPROM_MODE_11A) { + if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) + val = (5 * bin) + 4800; + else + val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : + (bin * 10) + 5100; + } else { + if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) + val = bin + 2300; + else + val = bin + 2400; + } + + return val; +} + +/* + * Initialize eeprom & capabilities structs + */ +static int +ath5k_eeprom_init_header(struct ath5k_hw *ah) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + int ret; + u16 val; + + /* + * Read values from EEPROM and store them in the capability structure + */ + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); + + /* Return if we have an old EEPROM */ + if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) + return 0; + +#ifdef notyet + /* + * Validate the checksum of the EEPROM date. There are some + * devices with invalid EEPROMs. + */ + for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { + AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); + cksum ^= val; + } + if (cksum != AR5K_EEPROM_INFO_CKSUM) { + ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); + return -EIO; + } +#endif + + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), + ee_ant_gain); + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); + + /* XXX: Don't know which versions include these two */ + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2); + + if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3); + + if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) { + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5); + AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6); + } + } + + if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { + AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); + ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; + ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; + + AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); + ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; + ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; + } + + return 0; +} + + +/* + * Read antenna infos from eeprom + */ +static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, + unsigned int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 o = *offset; + u16 val; + int ret, i = 0; + + AR5K_EEPROM_READ(o++, val); + ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; + ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f; + ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; + + AR5K_EEPROM_READ(o++, val); + ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; + ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; + ee->ee_ant_control[mode][i++] = val & 0x3f; + + AR5K_EEPROM_READ(o++, val); + ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; + ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; + ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; + + AR5K_EEPROM_READ(o++, val); + ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; + ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; + ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; + ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; + + AR5K_EEPROM_READ(o++, val); + ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; + ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; + ee->ee_ant_control[mode][i++] = val & 0x3f; + + /* Get antenna modes */ + ah->ah_antenna[mode][0] = + (ee->ee_ant_control[mode][0] << 4); + ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = + ee->ee_ant_control[mode][1] | + (ee->ee_ant_control[mode][2] << 6) | + (ee->ee_ant_control[mode][3] << 12) | + (ee->ee_ant_control[mode][4] << 18) | + (ee->ee_ant_control[mode][5] << 24); + ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = + ee->ee_ant_control[mode][6] | + (ee->ee_ant_control[mode][7] << 6) | + (ee->ee_ant_control[mode][8] << 12) | + (ee->ee_ant_control[mode][9] << 18) | + (ee->ee_ant_control[mode][10] << 24); + + /* return new offset */ + *offset = o; + + return 0; +} + +/* + * Read supported modes and some mode-specific calibration data + * from eeprom + */ +static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, + unsigned int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 o = *offset; + u16 val; + int ret; + + ee->ee_n_piers[mode] = 0; + AR5K_EEPROM_READ(o++, val); + ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); + switch(mode) { + case AR5K_EEPROM_MODE_11A: + ee->ee_ob[mode][3] = (val >> 5) & 0x7; + ee->ee_db[mode][3] = (val >> 2) & 0x7; + ee->ee_ob[mode][2] = (val << 1) & 0x7; + + AR5K_EEPROM_READ(o++, val); + ee->ee_ob[mode][2] |= (val >> 15) & 0x1; + ee->ee_db[mode][2] = (val >> 12) & 0x7; + ee->ee_ob[mode][1] = (val >> 9) & 0x7; + ee->ee_db[mode][1] = (val >> 6) & 0x7; + ee->ee_ob[mode][0] = (val >> 3) & 0x7; + ee->ee_db[mode][0] = val & 0x7; + break; + case AR5K_EEPROM_MODE_11G: + case AR5K_EEPROM_MODE_11B: + ee->ee_ob[mode][1] = (val >> 4) & 0x7; + ee->ee_db[mode][1] = val & 0x7; + break; + } + + AR5K_EEPROM_READ(o++, val); + ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; + ee->ee_thr_62[mode] = val & 0xff; + + if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) + ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; + + AR5K_EEPROM_READ(o++, val); + ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; + ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; + + AR5K_EEPROM_READ(o++, val); + ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; + + if ((val & 0xff) & 0x80) + ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); + else + ee->ee_noise_floor_thr[mode] = val & 0xff; + + if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) + ee->ee_noise_floor_thr[mode] = + mode == AR5K_EEPROM_MODE_11A ? -54 : -1; + + AR5K_EEPROM_READ(o++, val); + ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; + ee->ee_x_gain[mode] = (val >> 1) & 0xf; + ee->ee_xpd[mode] = val & 0x1; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) + ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { + AR5K_EEPROM_READ(o++, val); + ee->ee_false_detect[mode] = (val >> 6) & 0x7f; + + if (mode == AR5K_EEPROM_MODE_11A) + ee->ee_xr_power[mode] = val & 0x3f; + else { + ee->ee_ob[mode][0] = val & 0x7; + ee->ee_db[mode][0] = (val >> 3) & 0x7; + } + } + + if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { + ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; + ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; + } else { + ee->ee_i_gain[mode] = (val >> 13) & 0x7; + + AR5K_EEPROM_READ(o++, val); + ee->ee_i_gain[mode] |= (val << 3) & 0x38; + + if (mode == AR5K_EEPROM_MODE_11G) { + ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6) + ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; + } + } + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && + mode == AR5K_EEPROM_MODE_11A) { + ee->ee_i_cal[mode] = (val >> 8) & 0x3f; + ee->ee_q_cal[mode] = (val >> 3) & 0x1f; + } + + if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) + goto done; + + /* Note: >= v5 have bg freq piers on another location + * so these freq piers are ignored for >= v5 (should be 0xff + * anyway) */ + switch(mode) { + case AR5K_EEPROM_MODE_11A: + if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) + break; + + AR5K_EEPROM_READ(o++, val); + ee->ee_margin_tx_rx[mode] = val & 0x3f; + break; + case AR5K_EEPROM_MODE_11B: + AR5K_EEPROM_READ(o++, val); + + ee->ee_pwr_cal_b[0].freq = + ath5k_eeprom_bin2freq(ee, val & 0xff, mode); + if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS) + ee->ee_n_piers[mode]++; + + ee->ee_pwr_cal_b[1].freq = + ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); + if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS) + ee->ee_n_piers[mode]++; + + AR5K_EEPROM_READ(o++, val); + ee->ee_pwr_cal_b[2].freq = + ath5k_eeprom_bin2freq(ee, val & 0xff, mode); + if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS) + ee->ee_n_piers[mode]++; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) + ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; + break; + case AR5K_EEPROM_MODE_11G: + AR5K_EEPROM_READ(o++, val); + + ee->ee_pwr_cal_g[0].freq = + ath5k_eeprom_bin2freq(ee, val & 0xff, mode); + if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS) + ee->ee_n_piers[mode]++; + + ee->ee_pwr_cal_g[1].freq = + ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); + if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS) + ee->ee_n_piers[mode]++; + + AR5K_EEPROM_READ(o++, val); + ee->ee_turbo_max_power[mode] = val & 0x7f; + ee->ee_xr_power[mode] = (val >> 7) & 0x3f; + + AR5K_EEPROM_READ(o++, val); + ee->ee_pwr_cal_g[2].freq = + ath5k_eeprom_bin2freq(ee, val & 0xff, mode); + if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS) + ee->ee_n_piers[mode]++; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) + ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; + + AR5K_EEPROM_READ(o++, val); + ee->ee_i_cal[mode] = (val >> 8) & 0x3f; + ee->ee_q_cal[mode] = (val >> 3) & 0x1f; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { + AR5K_EEPROM_READ(o++, val); + ee->ee_cck_ofdm_gain_delta = val & 0xff; + } + break; + } + +done: + /* return new offset */ + *offset = o; + + return 0; +} + +/* + * Read turbo mode information on newer EEPROM versions + */ +static int +ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, + u32 *offset, unsigned int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 o = *offset; + u16 val; + int ret; + + if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) + return 0; + + switch (mode){ + case AR5K_EEPROM_MODE_11A: + ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f; + + ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7; + AR5K_EEPROM_READ(o++, val); + ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3; + ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f; + + ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f; + AR5K_EEPROM_READ(o++, val); + ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7; + ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff; + + if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2) + ee->ee_pd_gain_overlap = (val >> 9) & 0xf; + break; + case AR5K_EEPROM_MODE_11G: + ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f; + + ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7; + AR5K_EEPROM_READ(o++, val); + ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1; + ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f; + + ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f; + AR5K_EEPROM_READ(o++, val); + ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5; + ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff; + break; + } + + /* return new offset */ + *offset = o; + + return 0; +} + +/* Read mode-specific data (except power calibration data) */ +static int +ath5k_eeprom_init_modes(struct ath5k_hw *ah) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 mode_offset[3]; + unsigned int mode; + u32 offset; + int ret; + + /* + * Get values for all modes + */ + mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); + mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); + mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); + + ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] = + AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); + + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { + offset = mode_offset[mode]; + + ret = ath5k_eeprom_read_ants(ah, &offset, mode); + if (ret) + return ret; + + ret = ath5k_eeprom_read_modes(ah, &offset, mode); + if (ret) + return ret; + + ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode); + if (ret) + return ret; + } + + /* override for older eeprom versions for better performance */ + if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) { + ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15; + ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28; + ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28; + } + + return 0; +} + +/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff + * frequency mask) */ +static inline int +ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, + struct ath5k_chan_pcal_info *pc, unsigned int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + int o = *offset; + int i = 0; + u8 freq1, freq2; + int ret; + u16 val; + + ee->ee_n_piers[mode] = 0; + while(i < max) { + AR5K_EEPROM_READ(o++, val); + + freq1 = val & 0xff; + if (!freq1) + break; + + pc[i++].freq = ath5k_eeprom_bin2freq(ee, + freq1, mode); + ee->ee_n_piers[mode]++; + + freq2 = (val >> 8) & 0xff; + if (!freq2) + break; + + pc[i++].freq = ath5k_eeprom_bin2freq(ee, + freq2, mode); + ee->ee_n_piers[mode]++; + } + + /* return new offset */ + *offset = o; + + return 0; +} + +/* Read frequency piers for 802.11a */ +static int +ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; + int i, ret; + u16 val; + u8 mask; + + if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { + ath5k_eeprom_read_freq_list(ah, &offset, + AR5K_EEPROM_N_5GHZ_CHAN, pcal, + AR5K_EEPROM_MODE_11A); + } else { + mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); + + AR5K_EEPROM_READ(offset++, val); + pcal[0].freq = (val >> 9) & mask; + pcal[1].freq = (val >> 2) & mask; + pcal[2].freq = (val << 5) & mask; + + AR5K_EEPROM_READ(offset++, val); + pcal[2].freq |= (val >> 11) & 0x1f; + pcal[3].freq = (val >> 4) & mask; + pcal[4].freq = (val << 3) & mask; + + AR5K_EEPROM_READ(offset++, val); + pcal[4].freq |= (val >> 13) & 0x7; + pcal[5].freq = (val >> 6) & mask; + pcal[6].freq = (val << 1) & mask; + + AR5K_EEPROM_READ(offset++, val); + pcal[6].freq |= (val >> 15) & 0x1; + pcal[7].freq = (val >> 8) & mask; + pcal[8].freq = (val >> 1) & mask; + pcal[9].freq = (val << 6) & mask; + + AR5K_EEPROM_READ(offset++, val); + pcal[9].freq |= (val >> 10) & 0x3f; + + /* Fixed number of piers */ + ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; + + for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { + pcal[i].freq = ath5k_eeprom_bin2freq(ee, + pcal[i].freq, AR5K_EEPROM_MODE_11A); + } + } + + return 0; +} + +/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ +static inline int +ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *pcal; + + switch(mode) { + case AR5K_EEPROM_MODE_11B: + pcal = ee->ee_pwr_cal_b; + break; + case AR5K_EEPROM_MODE_11G: + pcal = ee->ee_pwr_cal_g; + break; + default: + return -EINVAL; + } + + ath5k_eeprom_read_freq_list(ah, &offset, + AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, + mode); + + return 0; +} + +/* + * Read power calibration for RF5111 chips + * + * For RF5111 we have an XPD -eXternal Power Detector- curve + * for each calibrated channel. Each curve has 0,5dB Power steps + * on x axis and PCDAC steps (offsets) on y axis and looks like an + * exponential function. To recreate the curve we read 11 points + * here and interpolate later. + */ + +/* Used to match PCDAC steps with power values on RF5111 chips + * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC + * steps that match with the power values we read from eeprom. On + * older eeprom versions (< 3.2) these steps are equaly spaced at + * 10% of the pcdac curve -until the curve reaches it's maximum- + * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) + * these 11 steps are spaced in a different way. This function returns + * the pcdac steps based on eeprom version and curve min/max so that we + * can have pcdac/pwr points. + */ +static inline void +ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) +{ + const static u16 intercepts3[] = + { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; + const static u16 intercepts3_2[] = + { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; + const u16 *ip; + int i; + + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) + ip = intercepts3_2; + else + ip = intercepts3; + + for (i = 0; i < ARRAY_SIZE(intercepts3); i++) + vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; +} + +/* Convert RF5111 specific data to generic raw data + * used by interpolation code */ +static int +ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, + struct ath5k_chan_pcal_info *chinfo) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf5111 *pcinfo; + struct ath5k_pdgain_info *pd; + u8 pier, point, idx; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + + /* Fill raw data for each calibration pier */ + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + + pcinfo = &chinfo[pier].rf5111_info; + + /* Allocate pd_curves for this cal pier */ + chinfo[pier].pd_curves = + kcalloc(AR5K_EEPROM_N_PD_CURVES, + sizeof(struct ath5k_pdgain_info), + GFP_KERNEL); + + if (!chinfo[pier].pd_curves) + return -ENOMEM; + + /* Only one curve for RF5111 + * find out which one and place + * in in pd_curves. + * Note: ee_x_gain is reversed here */ + for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { + + if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) { + pdgain_idx[0] = idx; + break; + } + } + + ee->ee_pd_gains[mode] = 1; + + pd = &chinfo[pier].pd_curves[idx]; + + pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, + sizeof(u8), GFP_KERNEL); + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, + sizeof(s16), GFP_KERNEL); + if (!pd->pd_pwr) + return -ENOMEM; + + /* Fill raw dataset + * (convert power to 0.25dB units + * for RF5112 combatibility) */ + for (point = 0; point < pd->pd_points; point++) { + + /* Absolute values */ + pd->pd_pwr[point] = 2 * pcinfo->pwr[point]; + + /* Already sorted */ + pd->pd_step[point] = pcinfo->pcdac[point]; + } + + /* Set min/max pwr */ + chinfo[pier].min_pwr = pd->pd_pwr[0]; + chinfo[pier].max_pwr = pd->pd_pwr[10]; + + } + + return 0; +} + +/* Parse EEPROM data */ +static int +ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *pcal; + int offset, ret; + int i; + u16 val; + + offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); + switch(mode) { + case AR5K_EEPROM_MODE_11A: + if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) + return 0; + + ret = ath5k_eeprom_init_11a_pcal_freq(ah, + offset + AR5K_EEPROM_GROUP1_OFFSET); + if (ret < 0) + return ret; + + offset += AR5K_EEPROM_GROUP2_OFFSET; + pcal = ee->ee_pwr_cal_a; + break; + case AR5K_EEPROM_MODE_11B: + if (!AR5K_EEPROM_HDR_11B(ee->ee_header) && + !AR5K_EEPROM_HDR_11G(ee->ee_header)) + return 0; + + pcal = ee->ee_pwr_cal_b; + offset += AR5K_EEPROM_GROUP3_OFFSET; + + /* fixed piers */ + pcal[0].freq = 2412; + pcal[1].freq = 2447; + pcal[2].freq = 2484; + ee->ee_n_piers[mode] = 3; + break; + case AR5K_EEPROM_MODE_11G: + if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) + return 0; + + pcal = ee->ee_pwr_cal_g; + offset += AR5K_EEPROM_GROUP4_OFFSET; + + /* fixed piers */ + pcal[0].freq = 2312; + pcal[1].freq = 2412; + pcal[2].freq = 2484; + ee->ee_n_piers[mode] = 3; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ee->ee_n_piers[mode]; i++) { + struct ath5k_chan_pcal_info_rf5111 *cdata = + &pcal[i].rf5111_info; + + AR5K_EEPROM_READ(offset++, val); + cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M); + cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M); + cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M); + + AR5K_EEPROM_READ(offset++, val); + cdata->pwr[0] |= ((val >> 14) & 0x3); + cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M); + cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M); + cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M); + + AR5K_EEPROM_READ(offset++, val); + cdata->pwr[3] |= ((val >> 12) & 0xf); + cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M); + cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M); + + AR5K_EEPROM_READ(offset++, val); + cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M); + cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M); + cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M); + + AR5K_EEPROM_READ(offset++, val); + cdata->pwr[8] |= ((val >> 14) & 0x3); + cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M); + cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M); + + ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, + cdata->pcdac_max, cdata->pcdac); + } + + return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal); +} + + +/* + * Read power calibration for RF5112 chips + * + * For RF5112 we have 4 XPD -eXternal Power Detector- curves + * for each calibrated channel on 0, -6, -12 and -18dbm but we only + * use the higher (3) and the lower (0) curves. Each curve has 0.5dB + * power steps on x axis and PCDAC steps on y axis and looks like a + * linear function. To recreate the curve and pass the power values + * on hw, we read 4 points for xpd 0 (lower gain -> max power) + * and 3 points for xpd 3 (higher gain -> lower power) here and + * interpolate later. + * + * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. + */ + +/* Convert RF5112 specific data to generic raw data + * used by interpolation code */ +static int +ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, + struct ath5k_chan_pcal_info *chinfo) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf5112 *pcinfo; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + unsigned int pier, pdg, point; + + /* Fill raw data for each calibration pier */ + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + + pcinfo = &chinfo[pier].rf5112_info; + + /* Allocate pd_curves for this cal pier */ + chinfo[pier].pd_curves = + kcalloc(AR5K_EEPROM_N_PD_CURVES, + sizeof(struct ath5k_pdgain_info), + GFP_KERNEL); + + if (!chinfo[pier].pd_curves) + return -ENOMEM; + + /* Fill pd_curves */ + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + + u8 idx = pdgain_idx[pdg]; + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[idx]; + + /* Lowest gain curve (max power) */ + if (pdg == 0) { + /* One more point for better accuracy */ + pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(pd->pd_points, + sizeof(u8), GFP_KERNEL); + + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(pd->pd_points, + sizeof(s16), GFP_KERNEL); + + if (!pd->pd_pwr) + return -ENOMEM; + + + /* Fill raw dataset + * (all power levels are in 0.25dB units) */ + pd->pd_step[0] = pcinfo->pcdac_x0[0]; + pd->pd_pwr[0] = pcinfo->pwr_x0[0]; + + for (point = 1; point < pd->pd_points; + point++) { + /* Absolute values */ + pd->pd_pwr[point] = + pcinfo->pwr_x0[point]; + + /* Deltas */ + pd->pd_step[point] = + pd->pd_step[point - 1] + + pcinfo->pcdac_x0[point]; + } + + /* Set min power for this frequency */ + chinfo[pier].min_pwr = pd->pd_pwr[0]; + + /* Highest gain curve (min power) */ + } else if (pdg == 1) { + + pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(pd->pd_points, + sizeof(u8), GFP_KERNEL); + + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(pd->pd_points, + sizeof(s16), GFP_KERNEL); + + if (!pd->pd_pwr) + return -ENOMEM; + + /* Fill raw dataset + * (all power levels are in 0.25dB units) */ + for (point = 0; point < pd->pd_points; + point++) { + /* Absolute values */ + pd->pd_pwr[point] = + pcinfo->pwr_x3[point]; + + /* Fixed points */ + pd->pd_step[point] = + pcinfo->pcdac_x3[point]; + } + + /* Since we have a higher gain curve + * override min power */ + chinfo[pier].min_pwr = pd->pd_pwr[0]; + } + } + } + + return 0; +} + +/* Parse EEPROM data */ +static int +ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; + struct ath5k_chan_pcal_info *gen_chan_info; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + u32 offset; + u8 i, c; + u16 val; + int ret; + u8 pd_gains = 0; + + /* Count how many curves we have and + * identify them (which one of the 4 + * available curves we have on each count). + * Curves are stored from lower (x0) to + * higher (x3) gain */ + for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) { + /* ee_x_gain[mode] is x gain mask */ + if ((ee->ee_x_gain[mode] >> i) & 0x1) + pdgain_idx[pd_gains++] = i; + } + ee->ee_pd_gains[mode] = pd_gains; + + if (pd_gains == 0 || pd_gains > 2) + return -EINVAL; + + switch (mode) { + case AR5K_EEPROM_MODE_11A: + /* + * Read 5GHz EEPROM channels + */ + offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); + ath5k_eeprom_init_11a_pcal_freq(ah, offset); + + offset += AR5K_EEPROM_GROUP2_OFFSET; + gen_chan_info = ee->ee_pwr_cal_a; + break; + case AR5K_EEPROM_MODE_11B: + offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); + if (AR5K_EEPROM_HDR_11A(ee->ee_header)) + offset += AR5K_EEPROM_GROUP3_OFFSET; + + /* NB: frequency piers parsed during mode init */ + gen_chan_info = ee->ee_pwr_cal_b; + break; + case AR5K_EEPROM_MODE_11G: + offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); + if (AR5K_EEPROM_HDR_11A(ee->ee_header)) + offset += AR5K_EEPROM_GROUP4_OFFSET; + else if (AR5K_EEPROM_HDR_11B(ee->ee_header)) + offset += AR5K_EEPROM_GROUP2_OFFSET; + + /* NB: frequency piers parsed during mode init */ + gen_chan_info = ee->ee_pwr_cal_g; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ee->ee_n_piers[mode]; i++) { + chan_pcal_info = &gen_chan_info[i].rf5112_info; + + /* Power values in quarter dB + * for the lower xpd gain curve + * (0 dBm -> higher output power) */ + for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { + AR5K_EEPROM_READ(offset++, val); + chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff); + chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff); + } + + /* PCDAC steps + * corresponding to the above power + * measurements */ + AR5K_EEPROM_READ(offset++, val); + chan_pcal_info->pcdac_x0[1] = (val & 0x1f); + chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); + chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); + + /* Power values in quarter dB + * for the higher xpd gain curve + * (18 dBm -> lower output power) */ + AR5K_EEPROM_READ(offset++, val); + chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff); + chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff); + + AR5K_EEPROM_READ(offset++, val); + chan_pcal_info->pwr_x3[2] = (val & 0xff); + + /* PCDAC steps + * corresponding to the above power + * measurements (fixed) */ + chan_pcal_info->pcdac_x3[0] = 20; + chan_pcal_info->pcdac_x3[1] = 35; + chan_pcal_info->pcdac_x3[2] = 63; + + if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { + chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f); + + /* Last xpd0 power level is also channel maximum */ + gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; + } else { + chan_pcal_info->pcdac_x0[0] = 1; + gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff); + } + + } + + return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info); +} + + +/* + * Read power calibration for RF2413 chips + * + * For RF2413 we have a Power to PDDAC table (Power Detector) + * instead of a PCDAC and 4 pd gain curves for each calibrated channel. + * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y + * axis and looks like an exponential function like the RF5111 curve. + * + * To recreate the curves we read here the points and interpolate + * later. Note that in most cases only 2 (higher and lower) curves are + * used (like RF5112) but vendors have the oportunity to include all + * 4 curves on eeprom. The final curve (higher power) has an extra + * point for better accuracy like RF5112. + */ + +/* For RF2413 power calibration data doesn't start on a fixed location and + * if a mode is not supported, it's section is missing -not zeroed-. + * So we need to calculate the starting offset for each section by using + * these two functions */ + +/* Return the size of each section based on the mode and the number of pd + * gains available (maximum 4). */ +static inline unsigned int +ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) +{ + static const unsigned int pdgains_size[] = { 4, 6, 9, 12 }; + unsigned int sz; + + sz = pdgains_size[ee->ee_pd_gains[mode] - 1]; + sz *= ee->ee_n_piers[mode]; + + return sz; +} + +/* Return the starting offset for a section based on the modes supported + * and each section's size. */ +static unsigned int +ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) +{ + u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4); + + switch(mode) { + case AR5K_EEPROM_MODE_11G: + if (AR5K_EEPROM_HDR_11B(ee->ee_header)) + offset += ath5k_pdgains_size_2413(ee, + AR5K_EEPROM_MODE_11B) + + AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; + /* fall through */ + case AR5K_EEPROM_MODE_11B: + if (AR5K_EEPROM_HDR_11A(ee->ee_header)) + offset += ath5k_pdgains_size_2413(ee, + AR5K_EEPROM_MODE_11A) + + AR5K_EEPROM_N_5GHZ_CHAN / 2; + /* fall through */ + case AR5K_EEPROM_MODE_11A: + break; + default: + break; + } + + return offset; +} + +/* Convert RF2413 specific data to generic raw data + * used by interpolation code */ +static int +ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, + struct ath5k_chan_pcal_info *chinfo) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf2413 *pcinfo; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + unsigned int pier, pdg, point; + + /* Fill raw data for each calibration pier */ + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + + pcinfo = &chinfo[pier].rf2413_info; + + /* Allocate pd_curves for this cal pier */ + chinfo[pier].pd_curves = + kcalloc(AR5K_EEPROM_N_PD_CURVES, + sizeof(struct ath5k_pdgain_info), + GFP_KERNEL); + + if (!chinfo[pier].pd_curves) + return -ENOMEM; + + /* Fill pd_curves */ + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + + u8 idx = pdgain_idx[pdg]; + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[idx]; + + /* One more point for the highest power + * curve (lowest gain) */ + if (pdg == ee->ee_pd_gains[mode] - 1) + pd->pd_points = AR5K_EEPROM_N_PD_POINTS; + else + pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1; + + /* Allocate pd points for this curve */ + pd->pd_step = kcalloc(pd->pd_points, + sizeof(u8), GFP_KERNEL); + + if (!pd->pd_step) + return -ENOMEM; + + pd->pd_pwr = kcalloc(pd->pd_points, + sizeof(s16), GFP_KERNEL); + + if (!pd->pd_pwr) + return -ENOMEM; + + /* Fill raw dataset + * convert all pwr levels to + * quarter dB for RF5112 combatibility */ + pd->pd_step[0] = pcinfo->pddac_i[pdg]; + pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg]; + + for (point = 1; point < pd->pd_points; point++) { + + pd->pd_pwr[point] = pd->pd_pwr[point - 1] + + 2 * pcinfo->pwr[pdg][point - 1]; + + pd->pd_step[point] = pd->pd_step[point - 1] + + pcinfo->pddac[pdg][point - 1]; + + } + + /* Highest gain curve -> min power */ + if (pdg == 0) + chinfo[pier].min_pwr = pd->pd_pwr[0]; + + /* Lowest gain curve -> max power */ + if (pdg == ee->ee_pd_gains[mode] - 1) + chinfo[pier].max_pwr = + pd->pd_pwr[pd->pd_points - 1]; + } + } + + return 0; +} + +/* Parse EEPROM data */ +static int +ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info_rf2413 *pcinfo; + struct ath5k_chan_pcal_info *chinfo; + u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; + u32 offset; + int idx, i, ret; + u16 val; + u8 pd_gains = 0; + + /* Count how many curves we have and + * identify them (which one of the 4 + * available curves we have on each count). + * Curves are stored from higher to + * lower gain so we go backwards */ + for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) { + /* ee_x_gain[mode] is x gain mask */ + if ((ee->ee_x_gain[mode] >> idx) & 0x1) + pdgain_idx[pd_gains++] = idx; + + } + ee->ee_pd_gains[mode] = pd_gains; + + if (pd_gains == 0) + return -EINVAL; + + offset = ath5k_cal_data_offset_2413(ee, mode); + switch (mode) { + case AR5K_EEPROM_MODE_11A: + if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) + return 0; + + ath5k_eeprom_init_11a_pcal_freq(ah, offset); + offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; + chinfo = ee->ee_pwr_cal_a; + break; + case AR5K_EEPROM_MODE_11B: + if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) + return 0; + + ath5k_eeprom_init_11bg_2413(ah, mode, offset); + offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; + chinfo = ee->ee_pwr_cal_b; + break; + case AR5K_EEPROM_MODE_11G: + if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) + return 0; + + ath5k_eeprom_init_11bg_2413(ah, mode, offset); + offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; + chinfo = ee->ee_pwr_cal_g; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ee->ee_n_piers[mode]; i++) { + pcinfo = &chinfo[i].rf2413_info; + + /* + * Read pwr_i, pddac_i and the first + * 2 pd points (pwr, pddac) + */ + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr_i[0] = val & 0x1f; + pcinfo->pddac_i[0] = (val >> 5) & 0x7f; + pcinfo->pwr[0][0] = (val >> 12) & 0xf; + + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac[0][0] = val & 0x3f; + pcinfo->pwr[0][1] = (val >> 6) & 0xf; + pcinfo->pddac[0][1] = (val >> 10) & 0x3f; + + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr[0][2] = val & 0xf; + pcinfo->pddac[0][2] = (val >> 4) & 0x3f; + + pcinfo->pwr[0][3] = 0; + pcinfo->pddac[0][3] = 0; + + if (pd_gains > 1) { + /* + * Pd gain 0 is not the last pd gain + * so it only has 2 pd points. + * Continue wih pd gain 1. + */ + pcinfo->pwr_i[1] = (val >> 10) & 0x1f; + + pcinfo->pddac_i[1] = (val >> 15) & 0x1; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac_i[1] |= (val & 0x3F) << 1; + + pcinfo->pwr[1][0] = (val >> 6) & 0xf; + pcinfo->pddac[1][0] = (val >> 10) & 0x3f; + + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr[1][1] = val & 0xf; + pcinfo->pddac[1][1] = (val >> 4) & 0x3f; + pcinfo->pwr[1][2] = (val >> 10) & 0xf; + + pcinfo->pddac[1][2] = (val >> 14) & 0x3; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac[1][2] |= (val & 0xF) << 2; + + pcinfo->pwr[1][3] = 0; + pcinfo->pddac[1][3] = 0; + } else if (pd_gains == 1) { + /* + * Pd gain 0 is the last one so + * read the extra point. + */ + pcinfo->pwr[0][3] = (val >> 10) & 0xf; + + pcinfo->pddac[0][3] = (val >> 14) & 0x3; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac[0][3] |= (val & 0xF) << 2; + } + + /* + * Proceed with the other pd_gains + * as above. + */ + if (pd_gains > 2) { + pcinfo->pwr_i[2] = (val >> 4) & 0x1f; + pcinfo->pddac_i[2] = (val >> 9) & 0x7f; + + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr[2][0] = (val >> 0) & 0xf; + pcinfo->pddac[2][0] = (val >> 4) & 0x3f; + pcinfo->pwr[2][1] = (val >> 10) & 0xf; + + pcinfo->pddac[2][1] = (val >> 14) & 0x3; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac[2][1] |= (val & 0xF) << 2; + + pcinfo->pwr[2][2] = (val >> 4) & 0xf; + pcinfo->pddac[2][2] = (val >> 8) & 0x3f; + + pcinfo->pwr[2][3] = 0; + pcinfo->pddac[2][3] = 0; + } else if (pd_gains == 2) { + pcinfo->pwr[1][3] = (val >> 4) & 0xf; + pcinfo->pddac[1][3] = (val >> 8) & 0x3f; + } + + if (pd_gains > 3) { + pcinfo->pwr_i[3] = (val >> 14) & 0x3; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2; + + pcinfo->pddac_i[3] = (val >> 3) & 0x7f; + pcinfo->pwr[3][0] = (val >> 10) & 0xf; + pcinfo->pddac[3][0] = (val >> 14) & 0x3; + + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac[3][0] |= (val & 0xF) << 2; + pcinfo->pwr[3][1] = (val >> 4) & 0xf; + pcinfo->pddac[3][1] = (val >> 8) & 0x3f; + + pcinfo->pwr[3][2] = (val >> 14) & 0x3; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2; + + pcinfo->pddac[3][2] = (val >> 2) & 0x3f; + pcinfo->pwr[3][3] = (val >> 8) & 0xf; + + pcinfo->pddac[3][3] = (val >> 12) & 0xF; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4; + } else if (pd_gains == 3) { + pcinfo->pwr[2][3] = (val >> 14) & 0x3; + AR5K_EEPROM_READ(offset++, val); + pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2; + + pcinfo->pddac[2][3] = (val >> 2) & 0x3f; + } + } + + return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo); +} + + +/* + * Read per rate target power (this is the maximum tx power + * supported by the card). This info is used when setting + * tx power, no matter the channel. + * + * This also works for v5 EEPROMs. + */ +static int +ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_rate_pcal_info *rate_pcal_info; + u8 *rate_target_pwr_num; + u32 offset; + u16 val; + int ret, i; + + offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); + rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; + switch (mode) { + case AR5K_EEPROM_MODE_11A: + offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); + rate_pcal_info = ee->ee_rate_tpwr_a; + ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; + break; + case AR5K_EEPROM_MODE_11B: + offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); + rate_pcal_info = ee->ee_rate_tpwr_b; + ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */ + break; + case AR5K_EEPROM_MODE_11G: + offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version); + rate_pcal_info = ee->ee_rate_tpwr_g; + ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN; + break; + default: + return -EINVAL; + } + + /* Different freq mask for older eeproms (<= v3.2) */ + if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) { + for (i = 0; i < (*rate_target_pwr_num); i++) { + AR5K_EEPROM_READ(offset++, val); + rate_pcal_info[i].freq = + ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode); + + rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f); + rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f; + + AR5K_EEPROM_READ(offset++, val); + + if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || + val == 0) { + (*rate_target_pwr_num) = i; + break; + } + + rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7); + rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f); + rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f); + } + } else { + for (i = 0; i < (*rate_target_pwr_num); i++) { + AR5K_EEPROM_READ(offset++, val); + rate_pcal_info[i].freq = + ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); + + rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f); + rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f; + + AR5K_EEPROM_READ(offset++, val); + + if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || + val == 0) { + (*rate_target_pwr_num) = i; + break; + } + + rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf; + rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f); + rate_pcal_info[i].target_power_54 = (val & 0x3f); + } + } + + return 0; +} + +/* + * Read per channel calibration info from EEPROM + * + * This info is used to calibrate the baseband power table. Imagine + * that for each channel there is a power curve that's hw specific + * (depends on amplifier etc) and we try to "correct" this curve using + * offests we pass on to phy chip (baseband -> before amplifier) so that + * it can use accurate power values when setting tx power (takes amplifier's + * performance on each channel into account). + * + * EEPROM provides us with the offsets for some pre-calibrated channels + * and we have to interpolate to create the full table for these channels and + * also the table for any channel. + */ +static int +ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + int (*read_pcal)(struct ath5k_hw *hw, int mode); + int mode; + int err; + + if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) && + (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1)) + read_pcal = ath5k_eeprom_read_pcal_info_5112; + else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) && + (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2)) + read_pcal = ath5k_eeprom_read_pcal_info_2413; + else + read_pcal = ath5k_eeprom_read_pcal_info_5111; + + + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; + mode++) { + err = read_pcal(ah, mode); + if (err) + return err; + + err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode); + if (err < 0) + return err; + } + + return 0; +} + +static int +ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *chinfo; + u8 pier, pdg; + + switch (mode) { + case AR5K_EEPROM_MODE_11A: + if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_a; + break; + case AR5K_EEPROM_MODE_11B: + if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_b; + break; + case AR5K_EEPROM_MODE_11G: + if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) + return 0; + chinfo = ee->ee_pwr_cal_g; + break; + default: + return -EINVAL; + } + + for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { + if (!chinfo[pier].pd_curves) + continue; + + for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[pdg]; + + if (pd != NULL) { + kfree(pd->pd_step); + kfree(pd->pd_pwr); + } + } + + kfree(chinfo[pier].pd_curves); + } + + return 0; +} + +void +ath5k_eeprom_detach(struct ath5k_hw *ah) +{ + u8 mode; + + for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) + ath5k_eeprom_free_pcal_info(ah, mode); +} + +/* Read conformance test limits used for regulatory control */ +static int +ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_edge_power *rep; + unsigned int fmask, pmask; + unsigned int ctl_mode; + int ret, i, j; + u32 offset; + u16 val; + + pmask = AR5K_EEPROM_POWER_M; + fmask = AR5K_EEPROM_FREQ_M(ee->ee_version); + offset = AR5K_EEPROM_CTL(ee->ee_version); + ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version); + for (i = 0; i < ee->ee_ctls; i += 2) { + AR5K_EEPROM_READ(offset++, val); + ee->ee_ctl[i] = (val >> 8) & 0xff; + ee->ee_ctl[i + 1] = val & 0xff; + } + + offset = AR5K_EEPROM_GROUP8_OFFSET; + if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) + offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) - + AR5K_EEPROM_GROUP5_OFFSET; + else + offset += AR5K_EEPROM_GROUPS_START(ee->ee_version); + + rep = ee->ee_ctl_pwr; + for(i = 0; i < ee->ee_ctls; i++) { + switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) { + case AR5K_CTL_11A: + case AR5K_CTL_TURBO: + ctl_mode = AR5K_EEPROM_MODE_11A; + break; + default: + ctl_mode = AR5K_EEPROM_MODE_11G; + break; + } + if (ee->ee_ctl[i] == 0) { + if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) + offset += 8; + else + offset += 7; + rep += AR5K_EEPROM_N_EDGES; + continue; + } + if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { + for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { + AR5K_EEPROM_READ(offset++, val); + rep[j].freq = (val >> 8) & fmask; + rep[j + 1].freq = val & fmask; + } + for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { + AR5K_EEPROM_READ(offset++, val); + rep[j].edge = (val >> 8) & pmask; + rep[j].flag = (val >> 14) & 1; + rep[j + 1].edge = val & pmask; + rep[j + 1].flag = (val >> 6) & 1; + } + } else { + AR5K_EEPROM_READ(offset++, val); + rep[0].freq = (val >> 9) & fmask; + rep[1].freq = (val >> 2) & fmask; + rep[2].freq = (val << 5) & fmask; + + AR5K_EEPROM_READ(offset++, val); + rep[2].freq |= (val >> 11) & 0x1f; + rep[3].freq = (val >> 4) & fmask; + rep[4].freq = (val << 3) & fmask; + + AR5K_EEPROM_READ(offset++, val); + rep[4].freq |= (val >> 13) & 0x7; + rep[5].freq = (val >> 6) & fmask; + rep[6].freq = (val << 1) & fmask; + + AR5K_EEPROM_READ(offset++, val); + rep[6].freq |= (val >> 15) & 0x1; + rep[7].freq = (val >> 8) & fmask; + + rep[0].edge = (val >> 2) & pmask; + rep[1].edge = (val << 4) & pmask; + + AR5K_EEPROM_READ(offset++, val); + rep[1].edge |= (val >> 12) & 0xf; + rep[2].edge = (val >> 6) & pmask; + rep[3].edge = val & pmask; + + AR5K_EEPROM_READ(offset++, val); + rep[4].edge = (val >> 10) & pmask; + rep[5].edge = (val >> 4) & pmask; + rep[6].edge = (val << 2) & pmask; + + AR5K_EEPROM_READ(offset++, val); + rep[6].edge |= (val >> 14) & 0x3; + rep[7].edge = (val >> 8) & pmask; + } + for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) { + rep[j].freq = ath5k_eeprom_bin2freq(ee, + rep[j].freq, ctl_mode); + } + rep += AR5K_EEPROM_N_EDGES; + } + + return 0; +} + + +/* + * Initialize eeprom power tables + */ +int +ath5k_eeprom_init(struct ath5k_hw *ah) +{ + int err; + + err = ath5k_eeprom_init_header(ah); + if (err < 0) + return err; + + err = ath5k_eeprom_init_modes(ah); + if (err < 0) + return err; + + err = ath5k_eeprom_read_pcal_info(ah); + if (err < 0) + return err; + + err = ath5k_eeprom_read_ctl_info(ah); + if (err < 0) + return err; + + return 0; +} + +/* + * Read the MAC address from eeprom + */ +int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ + u8 mac_d[ETH_ALEN] = {}; + u32 total, offset; + u16 data; + int octet, ret; + + ret = ath5k_hw_eeprom_read(ah, 0x20, &data); + if (ret) + return ret; + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { + ret = ath5k_hw_eeprom_read(ah, offset, &data); + if (ret) + return ret; + + total += data; + mac_d[octet + 1] = data & 0xff; + mac_d[octet] = data >> 8; + octet += 2; + } + + if (!total || total == 3 * 0xffff) + return -EINVAL; + + memcpy(mac, mac_d, ETH_ALEN); + + return 0; +} + +bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah) +{ + u16 data; + + ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data); + + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data) + return true; + else + return false; +} + diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h new file mode 100644 index 000000000000..b0c0606dea0b --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) + */ +#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ +#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ +#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ +#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ +#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ + +#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ +#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ +#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ +#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ +#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) +#define AR5K_EEPROM_INFO_CKSUM 0xffff +#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) + +#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ +#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ +#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ +#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ +#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ +#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */ +#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ +#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ +#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ +#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */ +#define AR5K_EEPROM_VERSION_4_4 0x4004 +#define AR5K_EEPROM_VERSION_4_5 0x4005 +#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ +#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */ +#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */ +#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */ +#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */ +#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */ + +#define AR5K_EEPROM_MODE_11A 0 +#define AR5K_EEPROM_MODE_11B 1 +#define AR5K_EEPROM_MODE_11G 2 + +#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ +#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) +#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) +#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) +#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ +#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ +#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) +#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ +#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ + +#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c +#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 +#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 +#define AR5K_EEPROM_RFKILL_POLARITY_S 1 + +/* Newer EEPROMs are using a different offset */ +#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ + (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) + +#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) +#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff)) +#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff)) + +/* Misc values available since EEPROM 4.0 */ +#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4) +#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) +#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1) +#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1) +#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) + +#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) +#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) +#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) +#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) + +#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) +#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff) +#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff) + +#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7) +#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f) +#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff) + +#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) +#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) +#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) +#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) + +#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) +#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) +#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) +#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) +#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) +#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) +#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) +#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) + +#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) +#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) +#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) +#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) +#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) +#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) +#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) +#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) + +/* calibration settings */ +#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) +#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) +#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) +#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ +#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */ +#define AR5K_EEPROM_GROUP1_OFFSET 0x0 +#define AR5K_EEPROM_GROUP2_OFFSET 0x5 +#define AR5K_EEPROM_GROUP3_OFFSET 0x37 +#define AR5K_EEPROM_GROUP4_OFFSET 0x46 +#define AR5K_EEPROM_GROUP5_OFFSET 0x55 +#define AR5K_EEPROM_GROUP6_OFFSET 0x65 +#define AR5K_EEPROM_GROUP7_OFFSET 0x69 +#define AR5K_EEPROM_GROUP8_OFFSET 0x6f + +#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ + AR5K_EEPROM_GROUP5_OFFSET, 0x0000) +#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ + AR5K_EEPROM_GROUP6_OFFSET, 0x0010) +#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ + AR5K_EEPROM_GROUP7_OFFSET, 0x0014) + +/* [3.1 - 3.3] */ +#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec +#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed + +#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ +#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ +#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ +#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ +#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 +#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ +#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 +#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ +#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 +#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ +#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 +#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ +#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 +#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ +#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 +#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ +#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 + +/* Some EEPROM defines */ +#define AR5K_EEPROM_EEP_SCALE 100 +#define AR5K_EEPROM_EEP_DELTA 10 +#define AR5K_EEPROM_N_MODES 3 +#define AR5K_EEPROM_N_5GHZ_CHAN 10 +#define AR5K_EEPROM_N_2GHZ_CHAN 3 +#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 +#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 +#define AR5K_EEPROM_MAX_CHAN 10 +#define AR5K_EEPROM_N_PWR_POINTS_5111 11 +#define AR5K_EEPROM_N_PCDAC 11 +#define AR5K_EEPROM_N_PHASE_CAL 5 +#define AR5K_EEPROM_N_TEST_FREQ 8 +#define AR5K_EEPROM_N_EDGES 8 +#define AR5K_EEPROM_N_INTERCEPTS 11 +#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) +#define AR5K_EEPROM_PCDAC_M 0x3f +#define AR5K_EEPROM_PCDAC_START 1 +#define AR5K_EEPROM_PCDAC_STOP 63 +#define AR5K_EEPROM_PCDAC_STEP 1 +#define AR5K_EEPROM_NON_EDGE_M 0x40 +#define AR5K_EEPROM_CHANNEL_POWER 8 +#define AR5K_EEPROM_N_OBDB 4 +#define AR5K_EEPROM_OBDB_DIS 0xffff +#define AR5K_EEPROM_CHANNEL_DIS 0xff +#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) +#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) +#define AR5K_EEPROM_MAX_CTLS 32 +#define AR5K_EEPROM_N_PD_CURVES 4 +#define AR5K_EEPROM_N_XPD0_POINTS 4 +#define AR5K_EEPROM_N_XPD3_POINTS 3 +#define AR5K_EEPROM_N_PD_GAINS 4 +#define AR5K_EEPROM_N_PD_POINTS 5 +#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 +#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 +#define AR5K_EEPROM_POWER_M 0x3f +#define AR5K_EEPROM_POWER_MIN 0 +#define AR5K_EEPROM_POWER_MAX 3150 +#define AR5K_EEPROM_POWER_STEP 50 +#define AR5K_EEPROM_POWER_TABLE_SIZE 64 +#define AR5K_EEPROM_N_POWER_LOC_11B 4 +#define AR5K_EEPROM_N_POWER_LOC_11G 6 +#define AR5K_EEPROM_I_GAIN 10 +#define AR5K_EEPROM_CCK_OFDM_DELTA 15 +#define AR5K_EEPROM_N_IQ_CAL 2 + +#define AR5K_EEPROM_READ(_o, _v) do { \ + ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ + if (ret) \ + return ret; \ +} while (0) + +#define AR5K_EEPROM_READ_HDR(_o, _v) \ + AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ + +enum ath5k_ant_setting { + AR5K_ANT_VARIABLE = 0, /* variable by programming */ + AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ + AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ + AR5K_ANT_MAX = 3, +}; + +enum ath5k_ctl_mode { + AR5K_CTL_11A = 0, + AR5K_CTL_11B = 1, + AR5K_CTL_11G = 2, + AR5K_CTL_TURBO = 3, + AR5K_CTL_TURBOG = 4, + AR5K_CTL_2GHT20 = 5, + AR5K_CTL_5GHT20 = 6, + AR5K_CTL_2GHT40 = 7, + AR5K_CTL_5GHT40 = 8, + AR5K_CTL_MODE_M = 15, +}; + +/* Default CTL ids for the 3 main reg domains. + * Atheros only uses these by default but vendors + * can have up to 32 different CTLs for different + * scenarios. Note that theese values are ORed with + * the mode id (above) so we can have up to 24 CTL + * datasets out of these 3 main regdomains. That leaves + * 8 ids that can be used by vendors and since 0x20 is + * missing from HAL sources i guess this is the set of + * custom CTLs vendors can use. */ +#define AR5K_CTL_FCC 0x10 +#define AR5K_CTL_CUSTOM 0x20 +#define AR5K_CTL_ETSI 0x30 +#define AR5K_CTL_MKK 0x40 + +/* Indicates a CTL with only mode set and + * no reg domain mapping, such CTLs are used + * for world roaming domains or simply when + * a reg domain is not set */ +#define AR5K_CTL_NO_REGDOMAIN 0xf0 + +/* Indicates an empty (invalid) CTL */ +#define AR5K_CTL_NO_CTL 0xff + +/* Per channel calibration data, used for power table setup */ +struct ath5k_chan_pcal_info_rf5111 { + /* Power levels in half dbm units + * for one power curve. */ + u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111]; + /* PCDAC table steps + * for the above values */ + u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111]; + /* Starting PCDAC step */ + u8 pcdac_min; + /* Final PCDAC step */ + u8 pcdac_max; +}; + +struct ath5k_chan_pcal_info_rf5112 { + /* Power levels in quarter dBm units + * for lower (0) and higher (3) + * level curves in 0.25dB units */ + s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; + s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; + /* PCDAC table steps + * for the above values */ + u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; + u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; +}; + +struct ath5k_chan_pcal_info_rf2413 { + /* Starting pwr/pddac values */ + s8 pwr_i[AR5K_EEPROM_N_PD_GAINS]; + u8 pddac_i[AR5K_EEPROM_N_PD_GAINS]; + /* (pwr,pddac) points + * power levels in 0.5dB units */ + s8 pwr[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_N_PD_POINTS]; + u8 pddac[AR5K_EEPROM_N_PD_GAINS] + [AR5K_EEPROM_N_PD_POINTS]; +}; + +enum ath5k_powertable_type { + AR5K_PWRTABLE_PWR_TO_PCDAC = 0, + AR5K_PWRTABLE_LINEAR_PCDAC = 1, + AR5K_PWRTABLE_PWR_TO_PDADC = 2, +}; + +struct ath5k_pdgain_info { + u8 pd_points; + u8 *pd_step; + /* Power values are in + * 0.25dB units */ + s16 *pd_pwr; +}; + +struct ath5k_chan_pcal_info { + /* Frequency */ + u16 freq; + /* Tx power boundaries */ + s16 max_pwr; + s16 min_pwr; + union { + struct ath5k_chan_pcal_info_rf5111 rf5111_info; + struct ath5k_chan_pcal_info_rf5112 rf5112_info; + struct ath5k_chan_pcal_info_rf2413 rf2413_info; + }; + /* Raw values used by phy code + * Curves are stored in order from lower + * gain to higher gain (max txpower -> min txpower) */ + struct ath5k_pdgain_info *pd_curves; +}; + +/* Per rate calibration data for each mode, + * used for rate power table setup. + * Note: Values in 0.5dB units */ +struct ath5k_rate_pcal_info { + u16 freq; /* Frequency */ + /* Power level for 6-24Mbit/s rates or + * 1Mb rate */ + u16 target_power_6to24; + /* Power level for 36Mbit rate or + * 2Mb rate */ + u16 target_power_36; + /* Power level for 48Mbit rate or + * 5.5Mbit rate */ + u16 target_power_48; + /* Power level for 54Mbit rate or + * 11Mbit rate */ + u16 target_power_54; +}; + +/* Power edges for conformance test limits */ +struct ath5k_edge_power { + u16 freq; + u16 edge; /* in half dBm */ + bool flag; +}; + +/* EEPROM calibration data */ +struct ath5k_eeprom_info { + + /* Header information */ + u16 ee_magic; + u16 ee_protect; + u16 ee_regdomain; + u16 ee_version; + u16 ee_header; + u16 ee_ant_gain; + u16 ee_misc0; + u16 ee_misc1; + u16 ee_misc2; + u16 ee_misc3; + u16 ee_misc4; + u16 ee_misc5; + u16 ee_misc6; + u16 ee_cck_ofdm_gain_delta; + u16 ee_cck_ofdm_power_delta; + u16 ee_scaled_cck_delta; + + /* RF Calibration settings (reset, rfregs) */ + u16 ee_i_cal[AR5K_EEPROM_N_MODES]; + u16 ee_q_cal[AR5K_EEPROM_N_MODES]; + u16 ee_fixed_bias[AR5K_EEPROM_N_MODES]; + u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; + u16 ee_xr_power[AR5K_EEPROM_N_MODES]; + u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; + u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES]; + u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; + u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; + u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; + u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; + u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; + u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; + u16 ee_thr_62[AR5K_EEPROM_N_MODES]; + u16 ee_xlna_gain[AR5K_EEPROM_N_MODES]; + u16 ee_xpd[AR5K_EEPROM_N_MODES]; + u16 ee_x_gain[AR5K_EEPROM_N_MODES]; + u16 ee_i_gain[AR5K_EEPROM_N_MODES]; + u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; + u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES]; + u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES]; + u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES]; + + /* Power calibration data */ + u16 ee_false_detect[AR5K_EEPROM_N_MODES]; + + /* Number of pd gain curves per mode */ + u8 ee_pd_gains[AR5K_EEPROM_N_MODES]; + /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */ + u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS]; + + u8 ee_n_piers[AR5K_EEPROM_N_MODES]; + struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]; + struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; + struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; + + /* Per rate target power levels */ + u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]; + struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]; + struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; + struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; + + /* Conformance test limits (Unused) */ + u8 ee_ctls; + u8 ee_ctl[AR5K_EEPROM_MAX_CTLS]; + struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS]; + + /* Noise Floor Calibration settings */ + s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; + s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; + s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; + s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES]; + s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES]; + s8 ee_pd_gain_overlap; + + u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; +}; + diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c new file mode 100644 index 000000000000..64a27e73d02e --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/gpio.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/****************\ + GPIO Functions +\****************/ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/* + * Set led state + */ +void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) +{ + u32 led; + /*5210 has different led mode handling*/ + u32 led_5210; + + ATH5K_TRACE(ah->ah_sc); + + /*Reset led status*/ + if (ah->ah_version != AR5K_AR5210) + AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); + + /* + * Some blinking values, define at your wish + */ + switch (state) { + case AR5K_LED_SCAN: + case AR5K_LED_AUTH: + led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; + led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; + break; + + case AR5K_LED_INIT: + led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; + led_5210 = AR5K_PCICFG_LED_PEND; + break; + + case AR5K_LED_ASSOC: + case AR5K_LED_RUN: + led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; + led_5210 = AR5K_PCICFG_LED_ASSOC; + break; + + default: + led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; + led_5210 = AR5K_PCICFG_LED_PEND; + break; + } + + /*Write new status to the register*/ + if (ah->ah_version != AR5K_AR5210) + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); +} + +/* + * Set GPIO inputs + */ +int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) +{ + ATH5K_TRACE(ah->ah_sc); + if (gpio >= AR5K_NUM_GPIO) + return -EINVAL; + + ath5k_hw_reg_write(ah, + (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) + | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); + + return 0; +} + +/* + * Set GPIO outputs + */ +int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) +{ + ATH5K_TRACE(ah->ah_sc); + if (gpio >= AR5K_NUM_GPIO) + return -EINVAL; + + ath5k_hw_reg_write(ah, + (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) + | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); + + return 0; +} + +/* + * Get GPIO state + */ +u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) +{ + ATH5K_TRACE(ah->ah_sc); + if (gpio >= AR5K_NUM_GPIO) + return 0xffffffff; + + /* GPIO input magic */ + return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & + 0x1; +} + +/* + * Set GPIO state + */ +int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) +{ + u32 data; + ATH5K_TRACE(ah->ah_sc); + + if (gpio >= AR5K_NUM_GPIO) + return -EINVAL; + + /* GPIO output magic */ + data = ath5k_hw_reg_read(ah, AR5K_GPIODO); + + data &= ~(1 << gpio); + data |= (val & 1) << gpio; + + ath5k_hw_reg_write(ah, data, AR5K_GPIODO); + + return 0; +} + +/* + * Initialize the GPIO interrupt (RFKill switch) + */ +void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, + u32 interrupt_level) +{ + u32 data; + + ATH5K_TRACE(ah->ah_sc); + if (gpio >= AR5K_NUM_GPIO) + return; + + /* + * Set the GPIO interrupt + */ + data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & + ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | + AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | + (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); + + ath5k_hw_reg_write(ah, interrupt_level ? data : + (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); + + ah->ah_imr |= AR5K_IMR_GPIO; + + /* Enable GPIO interrupts */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); +} + diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c new file mode 100644 index 000000000000..61fb621ed20d --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -0,0 +1,1557 @@ +/* + * Initial register settings functions + * + * Copyright (c) 2004-2007 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2007-2008 Jiri Slaby + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/* + * Mode-independent initial register writes + */ + +struct ath5k_ini { + u16 ini_register; + u32 ini_value; + + enum { + AR5K_INI_WRITE = 0, /* Default */ + AR5K_INI_READ = 1, /* Cleared on read */ + } ini_mode; +}; + +/* + * Mode specific initial register values + */ + +struct ath5k_ini_mode { + u16 mode_register; + u32 mode_value[5]; +}; + +/* Initial register settings for AR5210 */ +static const struct ath5k_ini ar5210_ini[] = { + /* PCU and MAC registers */ + { AR5K_NOQCU_TXDP0, 0 }, + { AR5K_NOQCU_TXDP1, 0 }, + { AR5K_RXDP, 0 }, + { AR5K_CR, 0 }, + { AR5K_ISR, 0, AR5K_INI_READ }, + { AR5K_IMR, 0 }, + { AR5K_IER, AR5K_IER_DISABLE }, + { AR5K_BSR, 0, AR5K_INI_READ }, + { AR5K_TXCFG, AR5K_DMASIZE_128B }, + { AR5K_RXCFG, AR5K_DMASIZE_128B }, + { AR5K_CFG, AR5K_INIT_CFG }, + { AR5K_TOPS, 8 }, + { AR5K_RXNOFRM, 8 }, + { AR5K_RPGTO, 0 }, + { AR5K_TXNOFRM, 0 }, + { AR5K_SFR, 0 }, + { AR5K_MIBC, 0 }, + { AR5K_MISC, 0 }, + { AR5K_RX_FILTER_5210, 0 }, + { AR5K_MCAST_FILTER0_5210, 0 }, + { AR5K_MCAST_FILTER1_5210, 0 }, + { AR5K_TX_MASK0, 0 }, + { AR5K_TX_MASK1, 0 }, + { AR5K_CLR_TMASK, 0 }, + { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES }, + { AR5K_DIAG_SW_5210, 0 }, + { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES }, + { AR5K_TSF_L32_5210, 0 }, + { AR5K_TIMER0_5210, 0 }, + { AR5K_TIMER1_5210, 0xffffffff }, + { AR5K_TIMER2_5210, 0xffffffff }, + { AR5K_TIMER3_5210, 1 }, + { AR5K_CFP_DUR_5210, 0 }, + { AR5K_CFP_PERIOD_5210, 0 }, + /* PHY registers */ + { AR5K_PHY(0), 0x00000047 }, + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY(3), 0x09848ea6 }, + { AR5K_PHY(4), 0x3d32e000 }, + { AR5K_PHY(5), 0x0000076b }, + { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE }, + { AR5K_PHY(8), 0x02020200 }, + { AR5K_PHY(9), 0x00000e0e }, + { AR5K_PHY(10), 0x0a020201 }, + { AR5K_PHY(11), 0x00036ffc }, + { AR5K_PHY(12), 0x00000000 }, + { AR5K_PHY(13), 0x00000e0e }, + { AR5K_PHY(14), 0x00000007 }, + { AR5K_PHY(15), 0x00020100 }, + { AR5K_PHY(16), 0x89630000 }, + { AR5K_PHY(17), 0x1372169c }, + { AR5K_PHY(18), 0x0018b633 }, + { AR5K_PHY(19), 0x1284613c }, + { AR5K_PHY(20), 0x0de8b8e0 }, + { AR5K_PHY(21), 0x00074859 }, + { AR5K_PHY(22), 0x7e80beba }, + { AR5K_PHY(23), 0x313a665e }, + { AR5K_PHY_AGCCTL, 0x00001d08 }, + { AR5K_PHY(25), 0x0001ce00 }, + { AR5K_PHY(26), 0x409a4190 }, + { AR5K_PHY(28), 0x0000000f }, + { AR5K_PHY(29), 0x00000080 }, + { AR5K_PHY(30), 0x00000004 }, + { AR5K_PHY(31), 0x00000018 }, /* 0x987c */ + { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */ + { AR5K_PHY(65), 0x00000000 }, + { AR5K_PHY(66), 0x00000000 }, + { AR5K_PHY(67), 0x00800000 }, + { AR5K_PHY(68), 0x00000003 }, + /* BB gain table (64bytes) */ + { AR5K_BB_GAIN(0), 0x00000000 }, + { AR5K_BB_GAIN(1), 0x00000020 }, + { AR5K_BB_GAIN(2), 0x00000010 }, + { AR5K_BB_GAIN(3), 0x00000030 }, + { AR5K_BB_GAIN(4), 0x00000008 }, + { AR5K_BB_GAIN(5), 0x00000028 }, + { AR5K_BB_GAIN(6), 0x00000028 }, + { AR5K_BB_GAIN(7), 0x00000004 }, + { AR5K_BB_GAIN(8), 0x00000024 }, + { AR5K_BB_GAIN(9), 0x00000014 }, + { AR5K_BB_GAIN(10), 0x00000034 }, + { AR5K_BB_GAIN(11), 0x0000000c }, + { AR5K_BB_GAIN(12), 0x0000002c }, + { AR5K_BB_GAIN(13), 0x00000002 }, + { AR5K_BB_GAIN(14), 0x00000022 }, + { AR5K_BB_GAIN(15), 0x00000012 }, + { AR5K_BB_GAIN(16), 0x00000032 }, + { AR5K_BB_GAIN(17), 0x0000000a }, + { AR5K_BB_GAIN(18), 0x0000002a }, + { AR5K_BB_GAIN(19), 0x00000001 }, + { AR5K_BB_GAIN(20), 0x00000021 }, + { AR5K_BB_GAIN(21), 0x00000011 }, + { AR5K_BB_GAIN(22), 0x00000031 }, + { AR5K_BB_GAIN(23), 0x00000009 }, + { AR5K_BB_GAIN(24), 0x00000029 }, + { AR5K_BB_GAIN(25), 0x00000005 }, + { AR5K_BB_GAIN(26), 0x00000025 }, + { AR5K_BB_GAIN(27), 0x00000015 }, + { AR5K_BB_GAIN(28), 0x00000035 }, + { AR5K_BB_GAIN(29), 0x0000000d }, + { AR5K_BB_GAIN(30), 0x0000002d }, + { AR5K_BB_GAIN(31), 0x00000003 }, + { AR5K_BB_GAIN(32), 0x00000023 }, + { AR5K_BB_GAIN(33), 0x00000013 }, + { AR5K_BB_GAIN(34), 0x00000033 }, + { AR5K_BB_GAIN(35), 0x0000000b }, + { AR5K_BB_GAIN(36), 0x0000002b }, + { AR5K_BB_GAIN(37), 0x00000007 }, + { AR5K_BB_GAIN(38), 0x00000027 }, + { AR5K_BB_GAIN(39), 0x00000017 }, + { AR5K_BB_GAIN(40), 0x00000037 }, + { AR5K_BB_GAIN(41), 0x0000000f }, + { AR5K_BB_GAIN(42), 0x0000002f }, + { AR5K_BB_GAIN(43), 0x0000002f }, + { AR5K_BB_GAIN(44), 0x0000002f }, + { AR5K_BB_GAIN(45), 0x0000002f }, + { AR5K_BB_GAIN(46), 0x0000002f }, + { AR5K_BB_GAIN(47), 0x0000002f }, + { AR5K_BB_GAIN(48), 0x0000002f }, + { AR5K_BB_GAIN(49), 0x0000002f }, + { AR5K_BB_GAIN(50), 0x0000002f }, + { AR5K_BB_GAIN(51), 0x0000002f }, + { AR5K_BB_GAIN(52), 0x0000002f }, + { AR5K_BB_GAIN(53), 0x0000002f }, + { AR5K_BB_GAIN(54), 0x0000002f }, + { AR5K_BB_GAIN(55), 0x0000002f }, + { AR5K_BB_GAIN(56), 0x0000002f }, + { AR5K_BB_GAIN(57), 0x0000002f }, + { AR5K_BB_GAIN(58), 0x0000002f }, + { AR5K_BB_GAIN(59), 0x0000002f }, + { AR5K_BB_GAIN(60), 0x0000002f }, + { AR5K_BB_GAIN(61), 0x0000002f }, + { AR5K_BB_GAIN(62), 0x0000002f }, + { AR5K_BB_GAIN(63), 0x0000002f }, + /* 5110 RF gain table (64btes) */ + { AR5K_RF_GAIN(0), 0x0000001d }, + { AR5K_RF_GAIN(1), 0x0000005d }, + { AR5K_RF_GAIN(2), 0x0000009d }, + { AR5K_RF_GAIN(3), 0x000000dd }, + { AR5K_RF_GAIN(4), 0x0000011d }, + { AR5K_RF_GAIN(5), 0x00000021 }, + { AR5K_RF_GAIN(6), 0x00000061 }, + { AR5K_RF_GAIN(7), 0x000000a1 }, + { AR5K_RF_GAIN(8), 0x000000e1 }, + { AR5K_RF_GAIN(9), 0x00000031 }, + { AR5K_RF_GAIN(10), 0x00000071 }, + { AR5K_RF_GAIN(11), 0x000000b1 }, + { AR5K_RF_GAIN(12), 0x0000001c }, + { AR5K_RF_GAIN(13), 0x0000005c }, + { AR5K_RF_GAIN(14), 0x00000029 }, + { AR5K_RF_GAIN(15), 0x00000069 }, + { AR5K_RF_GAIN(16), 0x000000a9 }, + { AR5K_RF_GAIN(17), 0x00000020 }, + { AR5K_RF_GAIN(18), 0x00000019 }, + { AR5K_RF_GAIN(19), 0x00000059 }, + { AR5K_RF_GAIN(20), 0x00000099 }, + { AR5K_RF_GAIN(21), 0x00000030 }, + { AR5K_RF_GAIN(22), 0x00000005 }, + { AR5K_RF_GAIN(23), 0x00000025 }, + { AR5K_RF_GAIN(24), 0x00000065 }, + { AR5K_RF_GAIN(25), 0x000000a5 }, + { AR5K_RF_GAIN(26), 0x00000028 }, + { AR5K_RF_GAIN(27), 0x00000068 }, + { AR5K_RF_GAIN(28), 0x0000001f }, + { AR5K_RF_GAIN(29), 0x0000001e }, + { AR5K_RF_GAIN(30), 0x00000018 }, + { AR5K_RF_GAIN(31), 0x00000058 }, + { AR5K_RF_GAIN(32), 0x00000098 }, + { AR5K_RF_GAIN(33), 0x00000003 }, + { AR5K_RF_GAIN(34), 0x00000004 }, + { AR5K_RF_GAIN(35), 0x00000044 }, + { AR5K_RF_GAIN(36), 0x00000084 }, + { AR5K_RF_GAIN(37), 0x00000013 }, + { AR5K_RF_GAIN(38), 0x00000012 }, + { AR5K_RF_GAIN(39), 0x00000052 }, + { AR5K_RF_GAIN(40), 0x00000092 }, + { AR5K_RF_GAIN(41), 0x000000d2 }, + { AR5K_RF_GAIN(42), 0x0000002b }, + { AR5K_RF_GAIN(43), 0x0000002a }, + { AR5K_RF_GAIN(44), 0x0000006a }, + { AR5K_RF_GAIN(45), 0x000000aa }, + { AR5K_RF_GAIN(46), 0x0000001b }, + { AR5K_RF_GAIN(47), 0x0000001a }, + { AR5K_RF_GAIN(48), 0x0000005a }, + { AR5K_RF_GAIN(49), 0x0000009a }, + { AR5K_RF_GAIN(50), 0x000000da }, + { AR5K_RF_GAIN(51), 0x00000006 }, + { AR5K_RF_GAIN(52), 0x00000006 }, + { AR5K_RF_GAIN(53), 0x00000006 }, + { AR5K_RF_GAIN(54), 0x00000006 }, + { AR5K_RF_GAIN(55), 0x00000006 }, + { AR5K_RF_GAIN(56), 0x00000006 }, + { AR5K_RF_GAIN(57), 0x00000006 }, + { AR5K_RF_GAIN(58), 0x00000006 }, + { AR5K_RF_GAIN(59), 0x00000006 }, + { AR5K_RF_GAIN(60), 0x00000006 }, + { AR5K_RF_GAIN(61), 0x00000006 }, + { AR5K_RF_GAIN(62), 0x00000006 }, + { AR5K_RF_GAIN(63), 0x00000006 }, + /* PHY activation */ + { AR5K_PHY(53), 0x00000020 }, + { AR5K_PHY(51), 0x00000004 }, + { AR5K_PHY(50), 0x00060106 }, + { AR5K_PHY(39), 0x0000006d }, + { AR5K_PHY(48), 0x00000000 }, + { AR5K_PHY(52), 0x00000014 }, + { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE }, +}; + +/* Initial register settings for AR5211 */ +static const struct ath5k_ini ar5211_ini[] = { + { AR5K_RXDP, 0x00000000 }, + { AR5K_RTSD0, 0x84849c9c }, + { AR5K_RTSD1, 0x7c7c7c7c }, + { AR5K_RXCFG, 0x00000005 }, + { AR5K_MIBC, 0x00000000 }, + { AR5K_TOPS, 0x00000008 }, + { AR5K_RXNOFRM, 0x00000008 }, + { AR5K_TXNOFRM, 0x00000010 }, + { AR5K_RPGTO, 0x00000000 }, + { AR5K_RFCNT, 0x0000001f }, + { AR5K_QUEUE_TXDP(0), 0x00000000 }, + { AR5K_QUEUE_TXDP(1), 0x00000000 }, + { AR5K_QUEUE_TXDP(2), 0x00000000 }, + { AR5K_QUEUE_TXDP(3), 0x00000000 }, + { AR5K_QUEUE_TXDP(4), 0x00000000 }, + { AR5K_QUEUE_TXDP(5), 0x00000000 }, + { AR5K_QUEUE_TXDP(6), 0x00000000 }, + { AR5K_QUEUE_TXDP(7), 0x00000000 }, + { AR5K_QUEUE_TXDP(8), 0x00000000 }, + { AR5K_QUEUE_TXDP(9), 0x00000000 }, + { AR5K_DCU_FP, 0x00000000 }, + { AR5K_STA_ID1, 0x00000000 }, + { AR5K_BSS_ID0, 0x00000000 }, + { AR5K_BSS_ID1, 0x00000000 }, + { AR5K_RSSI_THR, 0x00000000 }, + { AR5K_CFP_PERIOD_5211, 0x00000000 }, + { AR5K_TIMER0_5211, 0x00000030 }, + { AR5K_TIMER1_5211, 0x0007ffff }, + { AR5K_TIMER2_5211, 0x01ffffff }, + { AR5K_TIMER3_5211, 0x00000031 }, + { AR5K_CFP_DUR_5211, 0x00000000 }, + { AR5K_RX_FILTER_5211, 0x00000000 }, + { AR5K_MCAST_FILTER0_5211, 0x00000000 }, + { AR5K_MCAST_FILTER1_5211, 0x00000002 }, + { AR5K_DIAG_SW_5211, 0x00000000 }, + { AR5K_ADDAC_TEST, 0x00000000 }, + { AR5K_DEFAULT_ANTENNA, 0x00000000 }, + /* PHY registers */ + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY(3), 0x2d849093 }, + { AR5K_PHY(4), 0x7d32e000 }, + { AR5K_PHY(5), 0x00000f6b }, + { AR5K_PHY_ACT, 0x00000000 }, + { AR5K_PHY(11), 0x00026ffe }, + { AR5K_PHY(12), 0x00000000 }, + { AR5K_PHY(15), 0x00020100 }, + { AR5K_PHY(16), 0x206a017a }, + { AR5K_PHY(19), 0x1284613c }, + { AR5K_PHY(21), 0x00000859 }, + { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */ + { AR5K_PHY(27), 0x050cb081 }, + { AR5K_PHY(28), 0x0000000f }, + { AR5K_PHY(29), 0x00000080 }, + { AR5K_PHY(30), 0x0000000c }, + { AR5K_PHY(64), 0x00000000 }, + { AR5K_PHY(65), 0x00000000 }, + { AR5K_PHY(66), 0x00000000 }, + { AR5K_PHY(67), 0x00800000 }, + { AR5K_PHY(68), 0x00000001 }, + { AR5K_PHY(71), 0x0000092a }, + { AR5K_PHY_IQ, 0x00000000 }, + { AR5K_PHY(73), 0x00058a05 }, + { AR5K_PHY(74), 0x00000001 }, + { AR5K_PHY(75), 0x00000000 }, + { AR5K_PHY_PAPD_PROBE, 0x00000000 }, + { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */ + { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */ + { AR5K_PHY(79), 0x0000003f }, /* 0x993c */ + { AR5K_PHY(80), 0x00000004 }, + { AR5K_PHY(82), 0x00000000 }, + { AR5K_PHY(83), 0x00000000 }, + { AR5K_PHY(84), 0x00000000 }, + { AR5K_PHY_RADAR, 0x5d50f14c }, + { AR5K_PHY(86), 0x00000018 }, + { AR5K_PHY(87), 0x004b6a8e }, + /* Initial Power table (32bytes) + * common on all cards/modes. + * Note: Table is rewritten during + * txpower setup later using calibration + * data etc. so next write is non-common */ + { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff }, + { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff }, + { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff }, + { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff }, + { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff }, + { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff }, + { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff }, + { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff }, + { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff }, + { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff }, + { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff }, + { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff }, + { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff }, + { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff }, + { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff }, + { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff }, + { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff }, + { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff }, + { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff }, + { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff }, + { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff }, + { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff }, + { AR5K_PHY_CCKTXCTL, 0x00000000 }, + { AR5K_PHY(642), 0x503e4646 }, + { AR5K_PHY_GAIN_2GHZ, 0x6480416c }, + { AR5K_PHY(644), 0x0199a003 }, + { AR5K_PHY(645), 0x044cd610 }, + { AR5K_PHY(646), 0x13800040 }, + { AR5K_PHY(647), 0x1be00060 }, + { AR5K_PHY(648), 0x0c53800a }, + { AR5K_PHY(649), 0x0014df3b }, + { AR5K_PHY(650), 0x000001b5 }, + { AR5K_PHY(651), 0x00000020 }, +}; + +/* Initial mode-specific settings for AR5211 + * 5211 supports OFDM-only g (draft g) but we + * need to test it ! + */ +static const struct ath5k_ini_mode ar5211_ini_mode[] = { + { AR5K_TXCFG, + /* a aTurbo b g (OFDM) */ + { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(0), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(1), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(2), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(3), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(4), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(5), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(6), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(7), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(8), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(9), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, + { AR5K_DCU_GBL_IFS_SLOT, + { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, + { AR5K_DCU_GBL_IFS_SIFS, + { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, + { AR5K_DCU_GBL_IFS_EIFS, + { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, + { AR5K_DCU_GBL_IFS_MISC, + { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, + { AR5K_TIME_OUT, + { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, + { AR5K_USEC_5211, + { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, + { AR5K_PHY_TURBO, + { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, + { AR5K_PHY(8), + { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, + { AR5K_PHY(9), + { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, + { AR5K_PHY(10), + { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, + { AR5K_PHY(13), + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY(14), + { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, + { AR5K_PHY(17), + { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, + { AR5K_PHY(18), + { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, + { AR5K_PHY(20), + { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, + { AR5K_PHY_SIG, + { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, + { AR5K_PHY_AGCCTL, + { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, + { AR5K_PHY_NF, + { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, + { AR5K_PHY_RX_DELAY, + { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, + { AR5K_PHY(70), + { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, + { AR5K_PHY_PCDAC_TXPOWER_BASE, + { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, + { AR5K_RF_BUFFER_CONTROL_4, + { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, +}; + +/* Initial register settings for AR5212 */ +static const struct ath5k_ini ar5212_ini_common_start[] = { + { AR5K_RXDP, 0x00000000 }, + { AR5K_RXCFG, 0x00000005 }, + { AR5K_MIBC, 0x00000000 }, + { AR5K_TOPS, 0x00000008 }, + { AR5K_RXNOFRM, 0x00000008 }, + { AR5K_TXNOFRM, 0x00000010 }, + { AR5K_RPGTO, 0x00000000 }, + { AR5K_RFCNT, 0x0000001f }, + { AR5K_QUEUE_TXDP(0), 0x00000000 }, + { AR5K_QUEUE_TXDP(1), 0x00000000 }, + { AR5K_QUEUE_TXDP(2), 0x00000000 }, + { AR5K_QUEUE_TXDP(3), 0x00000000 }, + { AR5K_QUEUE_TXDP(4), 0x00000000 }, + { AR5K_QUEUE_TXDP(5), 0x00000000 }, + { AR5K_QUEUE_TXDP(6), 0x00000000 }, + { AR5K_QUEUE_TXDP(7), 0x00000000 }, + { AR5K_QUEUE_TXDP(8), 0x00000000 }, + { AR5K_QUEUE_TXDP(9), 0x00000000 }, + { AR5K_DCU_FP, 0x00000000 }, + { AR5K_DCU_TXP, 0x00000000 }, + /* Tx filter table 0 (32 entries) */ + { AR5K_DCU_TX_FILTER_0(0), 0x00000000 }, /* DCU 0 */ + { AR5K_DCU_TX_FILTER_0(1), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(2), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(3), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(4), 0x00000000 }, /* DCU 1 */ + { AR5K_DCU_TX_FILTER_0(5), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(6), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(7), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(8), 0x00000000 }, /* DCU 2 */ + { AR5K_DCU_TX_FILTER_0(9), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(10), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(11), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(12), 0x00000000 }, /* DCU 3 */ + { AR5K_DCU_TX_FILTER_0(13), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(14), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(15), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(16), 0x00000000 }, /* DCU 4 */ + { AR5K_DCU_TX_FILTER_0(17), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(18), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(19), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(20), 0x00000000 }, /* DCU 5 */ + { AR5K_DCU_TX_FILTER_0(21), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(22), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(23), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(24), 0x00000000 }, /* DCU 6 */ + { AR5K_DCU_TX_FILTER_0(25), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(26), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(27), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(28), 0x00000000 }, /* DCU 7 */ + { AR5K_DCU_TX_FILTER_0(29), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(30), 0x00000000 }, + { AR5K_DCU_TX_FILTER_0(31), 0x00000000 }, + /* Tx filter table 1 (16 entries) */ + { AR5K_DCU_TX_FILTER_1(0), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(1), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(2), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(3), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(4), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(5), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(6), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(7), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(8), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(9), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(10), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(11), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(12), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(13), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(14), 0x00000000 }, + { AR5K_DCU_TX_FILTER_1(15), 0x00000000 }, + { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, + { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, + { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, + { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, + { AR5K_STA_ID1, 0x00000000 }, + { AR5K_BSS_ID0, 0x00000000 }, + { AR5K_BSS_ID1, 0x00000000 }, + { AR5K_BEACON_5211, 0x00000000 }, + { AR5K_CFP_PERIOD_5211, 0x00000000 }, + { AR5K_TIMER0_5211, 0x00000030 }, + { AR5K_TIMER1_5211, 0x0007ffff }, + { AR5K_TIMER2_5211, 0x01ffffff }, + { AR5K_TIMER3_5211, 0x00000031 }, + { AR5K_CFP_DUR_5211, 0x00000000 }, + { AR5K_RX_FILTER_5211, 0x00000000 }, + { AR5K_DIAG_SW_5211, 0x00000000 }, + { AR5K_ADDAC_TEST, 0x00000000 }, + { AR5K_DEFAULT_ANTENNA, 0x00000000 }, + { AR5K_FRAME_CTL_QOSM, 0x000fc78f }, + { AR5K_XRMODE, 0x2a82301a }, + { AR5K_XRDELAY, 0x05dc01e0 }, + { AR5K_XRTIMEOUT, 0x1f402710 }, + { AR5K_XRCHIRP, 0x01f40000 }, + { AR5K_XRSTOMP, 0x00001e1c }, + { AR5K_SLEEP0, 0x0002aaaa }, + { AR5K_SLEEP1, 0x02005555 }, + { AR5K_SLEEP2, 0x00000000 }, + { AR5K_BSS_IDM0, 0xffffffff }, + { AR5K_BSS_IDM1, 0x0000ffff }, + { AR5K_TXPC, 0x00000000 }, + { AR5K_PROFCNT_TX, 0x00000000 }, + { AR5K_PROFCNT_RX, 0x00000000 }, + { AR5K_PROFCNT_RXCLR, 0x00000000 }, + { AR5K_PROFCNT_CYCLE, 0x00000000 }, + { AR5K_QUIET_CTL1, 0x00000088 }, + /* Initial rate duration table (32 entries )*/ + { AR5K_RATE_DUR(0), 0x00000000 }, + { AR5K_RATE_DUR(1), 0x0000008c }, + { AR5K_RATE_DUR(2), 0x000000e4 }, + { AR5K_RATE_DUR(3), 0x000002d5 }, + { AR5K_RATE_DUR(4), 0x00000000 }, + { AR5K_RATE_DUR(5), 0x00000000 }, + { AR5K_RATE_DUR(6), 0x000000a0 }, + { AR5K_RATE_DUR(7), 0x000001c9 }, + { AR5K_RATE_DUR(8), 0x0000002c }, + { AR5K_RATE_DUR(9), 0x0000002c }, + { AR5K_RATE_DUR(10), 0x00000030 }, + { AR5K_RATE_DUR(11), 0x0000003c }, + { AR5K_RATE_DUR(12), 0x0000002c }, + { AR5K_RATE_DUR(13), 0x0000002c }, + { AR5K_RATE_DUR(14), 0x00000030 }, + { AR5K_RATE_DUR(15), 0x0000003c }, + { AR5K_RATE_DUR(16), 0x00000000 }, + { AR5K_RATE_DUR(17), 0x00000000 }, + { AR5K_RATE_DUR(18), 0x00000000 }, + { AR5K_RATE_DUR(19), 0x00000000 }, + { AR5K_RATE_DUR(20), 0x00000000 }, + { AR5K_RATE_DUR(21), 0x00000000 }, + { AR5K_RATE_DUR(22), 0x00000000 }, + { AR5K_RATE_DUR(23), 0x00000000 }, + { AR5K_RATE_DUR(24), 0x000000d5 }, + { AR5K_RATE_DUR(25), 0x000000df }, + { AR5K_RATE_DUR(26), 0x00000102 }, + { AR5K_RATE_DUR(27), 0x0000013a }, + { AR5K_RATE_DUR(28), 0x00000075 }, + { AR5K_RATE_DUR(29), 0x0000007f }, + { AR5K_RATE_DUR(30), 0x000000a2 }, + { AR5K_RATE_DUR(31), 0x00000000 }, + { AR5K_QUIET_CTL2, 0x00010002 }, + { AR5K_TSF_PARM, 0x00000001 }, + { AR5K_QOS_NOACK, 0x000000c0 }, + { AR5K_PHY_ERR_FIL, 0x00000000 }, + { AR5K_XRLAT_TX, 0x00000168 }, + { AR5K_ACKSIFS, 0x00000000 }, + /* Rate -> db table + * notice ...03<-02<-01<-00 ! */ + { AR5K_RATE2DB(0), 0x03020100 }, + { AR5K_RATE2DB(1), 0x07060504 }, + { AR5K_RATE2DB(2), 0x0b0a0908 }, + { AR5K_RATE2DB(3), 0x0f0e0d0c }, + { AR5K_RATE2DB(4), 0x13121110 }, + { AR5K_RATE2DB(5), 0x17161514 }, + { AR5K_RATE2DB(6), 0x1b1a1918 }, + { AR5K_RATE2DB(7), 0x1f1e1d1c }, + /* Db -> Rate table */ + { AR5K_DB2RATE(0), 0x03020100 }, + { AR5K_DB2RATE(1), 0x07060504 }, + { AR5K_DB2RATE(2), 0x0b0a0908 }, + { AR5K_DB2RATE(3), 0x0f0e0d0c }, + { AR5K_DB2RATE(4), 0x13121110 }, + { AR5K_DB2RATE(5), 0x17161514 }, + { AR5K_DB2RATE(6), 0x1b1a1918 }, + { AR5K_DB2RATE(7), 0x1f1e1d1c }, + /* PHY registers (Common settings + * for all chips/modes) */ + { AR5K_PHY(3), 0xad848e19 }, + { AR5K_PHY(4), 0x7d28e000 }, + { AR5K_PHY_TIMING_3, 0x9c0a9f6b }, + { AR5K_PHY_ACT, 0x00000000 }, + { AR5K_PHY(16), 0x206a017a }, + { AR5K_PHY(21), 0x00000859 }, + { AR5K_PHY_BIN_MASK_1, 0x00000000 }, + { AR5K_PHY_BIN_MASK_2, 0x00000000 }, + { AR5K_PHY_BIN_MASK_3, 0x00000000 }, + { AR5K_PHY_BIN_MASK_CTL, 0x00800000 }, + { AR5K_PHY_ANT_CTL, 0x00000001 }, + /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */ + { AR5K_PHY_MAX_RX_LEN, 0x00000c80 }, + { AR5K_PHY_IQ, 0x05100000 }, + { AR5K_PHY_WARM_RESET, 0x00000001 }, + { AR5K_PHY_CTL, 0x00000004 }, + { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 }, + { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d }, + { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f }, + { AR5K_PHY(82), 0x9280b212 }, + { AR5K_PHY_RADAR, 0x5d50e188 }, + /*{ AR5K_PHY(86), 0x000000ff },*/ + { AR5K_PHY(87), 0x004b6a8e }, + { AR5K_PHY_NFTHRES, 0x000003ce }, + { AR5K_PHY_RESTART, 0x192fb515 }, + { AR5K_PHY(94), 0x00000001 }, + { AR5K_PHY_RFBUS_REQ, 0x00000000 }, + /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */ + /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */ + { AR5K_PHY(644), 0x00806333 }, + { AR5K_PHY(645), 0x00106c10 }, + { AR5K_PHY(646), 0x009c4060 }, + /* { AR5K_PHY(647), 0x1483800a }, */ + /* { AR5K_PHY(648), 0x01831061 }, */ /* Old value */ + { AR5K_PHY(648), 0x018830c6 }, + { AR5K_PHY(649), 0x00000400 }, + /*{ AR5K_PHY(650), 0x000001b5 },*/ + { AR5K_PHY(651), 0x00000000 }, + { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, + { AR5K_PHY_TXPOWER_RATE2, 0x20202020 }, + /*{ AR5K_PHY(655), 0x13c889af },*/ + { AR5K_PHY(656), 0x38490a20 }, + { AR5K_PHY(657), 0x00007bb6 }, + { AR5K_PHY(658), 0x0fff3ffc }, +}; + +/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ +static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { + { AR5K_QUEUE_DFS_LOCAL_IFS(0), + /* a/XR aTurbo b g (DYN) gTurbo */ + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(1), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(2), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(3), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(4), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(5), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(6), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(7), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(8), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_QUEUE_DFS_LOCAL_IFS(9), + { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, + { AR5K_DCU_GBL_IFS_SIFS, + { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, + { AR5K_DCU_GBL_IFS_SLOT, + { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, + { AR5K_DCU_GBL_IFS_EIFS, + { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, + { AR5K_DCU_GBL_IFS_MISC, + { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, + { AR5K_TIME_OUT, + { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, + { AR5K_PHY_TURBO, + { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, + { AR5K_PHY(8), + { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, + { AR5K_PHY_RF_CTL2, + { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_SETTLING, + { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, + { AR5K_PHY_AGCCTL, + { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } }, + { AR5K_PHY_NF, + { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, + { AR5K_PHY_WEAK_OFDM_HIGH_THR, + { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, + { AR5K_PHY(70), + { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, + { AR5K_PHY_OFDM_SELFCORR, + { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, + { 0xa230, + { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, +}; + +/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ +static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { + { AR5K_TXCFG, + /* a/XR aTurbo b g (DYN) gTurbo */ + { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, + { AR5K_USEC_5211, + { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_PA_CTL, + { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { AR5K_PHY_GAIN, + { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, + { AR5K_PHY_SIG, + { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, + { AR5K_PHY_WEAK_OFDM_LOW_THR, + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, + { AR5K_PHY_RX_DELAY, + { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, + { AR5K_PHY_CCK_RX_CTL_4, + { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, +}; + +static const struct ath5k_ini rf5111_ini_common_end[] = { + { AR5K_DCU_FP, 0x00000000 }, + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY_ADC_CTL, 0x00022ffe }, + { 0x983c, 0x00020100 }, + { AR5K_PHY_GAIN_OFFSET, 0x1284613c }, + { AR5K_PHY_PAPD_PROBE, 0x00004883 }, + { 0x9940, 0x00000004 }, + { 0x9958, 0x000000ff }, + { 0x9974, 0x00000000 }, + { AR5K_PHY_SPENDING, 0x00000018 }, + { AR5K_PHY_CCKTXCTL, 0x00000000 }, + { AR5K_PHY_CCK_CROSSCORR, 0xd03e6788 }, + { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 }, + { 0xa23c, 0x13c889af }, +}; + +/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ +static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { + { AR5K_TXCFG, + /* a/XR aTurbo b g (DYN) gTurbo */ + { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, + { AR5K_USEC_5211, + { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_PA_CTL, + { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { AR5K_PHY_GAIN, + { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, + { AR5K_PHY_SIG, + { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, + { AR5K_PHY_WEAK_OFDM_LOW_THR, + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { AR5K_PHY_RX_DELAY, + { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, + { AR5K_PHY_CCKTXCTL, + { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, + { AR5K_PHY_CCK_CROSSCORR, + { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, + { AR5K_PHY_CCK_RX_CTL_4, + { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, +}; + +static const struct ath5k_ini rf5112_ini_common_end[] = { + { AR5K_DCU_FP, 0x00000000 }, + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY_ADC_CTL, 0x00022ffe }, + { 0x983c, 0x00020100 }, + { AR5K_PHY_GAIN_OFFSET, 0x1284613c }, + { AR5K_PHY_PAPD_PROBE, 0x00004882 }, + { 0x9940, 0x00000004 }, + { 0x9958, 0x000000ff }, + { 0x9974, 0x00000000 }, + { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 }, + { 0xa23c, 0x13c889af }, +}; + +/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ +static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { + { AR5K_TXCFG, + /* a/XR aTurbo b g (DYN) gTurbo */ + { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + { AR5K_USEC_5211, + { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_PA_CTL, + { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, + { AR5K_PHY_GAIN, + { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, + { AR5K_PHY_SIG, + { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, + { AR5K_PHY_WEAK_OFDM_LOW_THR, + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { AR5K_PHY_RX_DELAY, + { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { AR5K_PHY_CCKTXCTL, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY_CCK_CROSSCORR, + { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, + { AR5K_PHY_CCK_RX_CTL_4, + { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0xa300, + { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, + { 0xa304, + { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, + { 0xa308, + { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, + { 0xa30c, + { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, + { 0xa310, + { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, + { 0xa314, + { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, + { 0xa318, + { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, + { 0xa31c, + { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, + { 0xa320, + { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, + { 0xa324, + { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, + { 0xa328, + { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, + { 0xa32c, + { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, + { 0xa330, + { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, + { 0xa334, + { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, +}; + +static const struct ath5k_ini rf5413_ini_common_end[] = { + { AR5K_DCU_FP, 0x000003e0 }, + { AR5K_5414_CBCFG, 0x00000010 }, + { AR5K_SEQ_MASK, 0x0000000f }, + { 0x809c, 0x00000000 }, + { 0x80a0, 0x00000000 }, + { AR5K_MIC_QOS_CTL, 0x00000000 }, + { AR5K_MIC_QOS_SEL, 0x00000000 }, + { AR5K_MISC_MODE, 0x00000000 }, + { AR5K_OFDM_FIL_CNT, 0x00000000 }, + { AR5K_CCK_FIL_CNT, 0x00000000 }, + { AR5K_PHYERR_CNT1, 0x00000000 }, + { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, + { AR5K_PHYERR_CNT2, 0x00000000 }, + { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, + { AR5K_TSF_THRES, 0x00000000 }, + { 0x8140, 0x800003f9 }, + { 0x8144, 0x00000000 }, + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY_ADC_CTL, 0x0000a000 }, + { 0x983c, 0x00200400 }, + { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, + { AR5K_PHY_SCR, 0x0000001f }, + { AR5K_PHY_SLMT, 0x00000080 }, + { AR5K_PHY_SCAL, 0x0000000e }, + { 0x9958, 0x00081fff }, + { AR5K_PHY_TIMING_7, 0x00000000 }, + { AR5K_PHY_TIMING_8, 0x02800000 }, + { AR5K_PHY_TIMING_11, 0x00000000 }, + { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, + { 0x99e4, 0xaaaaaaaa }, + { 0x99e8, 0x3c466478 }, + { 0x99ec, 0x000000aa }, + { AR5K_PHY_SCLOCK, 0x0000000c }, + { AR5K_PHY_SDELAY, 0x000000ff }, + { AR5K_PHY_SPENDING, 0x00000014 }, + { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, + { 0xa23c, 0x93c889af }, + { AR5K_PHY_FAST_ADC, 0x00000001 }, + { 0xa250, 0x0000a000 }, + { AR5K_PHY_BLUETOOTH, 0x00000000 }, + { AR5K_PHY_TPC_RG1, 0x0cc75380 }, + { 0xa25c, 0x0f0f0f01 }, + { 0xa260, 0x5f690f01 }, + { 0xa264, 0x00418a11 }, + { 0xa268, 0x00000000 }, + { AR5K_PHY_TPC_RG5, 0x0c30c16a }, + { 0xa270, 0x00820820 }, + { 0xa274, 0x081b7caa }, + { 0xa278, 0x1ce739ce }, + { 0xa27c, 0x051701ce }, + { 0xa338, 0x00000000 }, + { 0xa33c, 0x00000000 }, + { 0xa340, 0x00000000 }, + { 0xa344, 0x00000000 }, + { 0xa348, 0x3fffffff }, + { 0xa34c, 0x3fffffff }, + { 0xa350, 0x3fffffff }, + { 0xa354, 0x0003ffff }, + { 0xa358, 0x79a8aa1f }, + { 0xa35c, 0x066c420f }, + { 0xa360, 0x0f282207 }, + { 0xa364, 0x17601685 }, + { 0xa368, 0x1f801104 }, + { 0xa36c, 0x37a00c03 }, + { 0xa370, 0x3fc40883 }, + { 0xa374, 0x57c00803 }, + { 0xa378, 0x5fd80682 }, + { 0xa37c, 0x7fe00482 }, + { 0xa380, 0x7f3c7bba }, + { 0xa384, 0xf3307ff0 }, +}; + +/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ +/* XXX: a mode ? */ +static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { + { AR5K_TXCFG, + /* a/XR aTurbo b g (DYN) gTurbo */ + { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + { AR5K_USEC_5211, + { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } }, + { AR5K_PHY_PA_CTL, + { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } }, + { AR5K_PHY_GAIN, + { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } }, + { AR5K_PHY_SIG, + { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } }, + { AR5K_PHY_WEAK_OFDM_LOW_THR, + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { AR5K_PHY_RX_DELAY, + { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { AR5K_PHY_CCKTXCTL, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY_CCK_CROSSCORR, + { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } }, + { AR5K_PHY_CCK_RX_CTL_4, + { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, +}; + +static const struct ath5k_ini rf2413_ini_common_end[] = { + { AR5K_DCU_FP, 0x000003e0 }, + { AR5K_SEQ_MASK, 0x0000000f }, + { AR5K_MIC_QOS_CTL, 0x00000000 }, + { AR5K_MIC_QOS_SEL, 0x00000000 }, + { AR5K_MISC_MODE, 0x00000000 }, + { AR5K_OFDM_FIL_CNT, 0x00000000 }, + { AR5K_CCK_FIL_CNT, 0x00000000 }, + { AR5K_PHYERR_CNT1, 0x00000000 }, + { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, + { AR5K_PHYERR_CNT2, 0x00000000 }, + { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, + { AR5K_TSF_THRES, 0x00000000 }, + { 0x8140, 0x800000a8 }, + { 0x8144, 0x00000000 }, + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY_ADC_CTL, 0x0000a000 }, + { 0x983c, 0x00200400 }, + { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, + { AR5K_PHY_SCR, 0x0000001f }, + { AR5K_PHY_SLMT, 0x00000080 }, + { AR5K_PHY_SCAL, 0x0000000e }, + { 0x9958, 0x000000ff }, + { AR5K_PHY_TIMING_7, 0x00000000 }, + { AR5K_PHY_TIMING_8, 0x02800000 }, + { AR5K_PHY_TIMING_11, 0x00000000 }, + { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, + { 0x99e4, 0xaaaaaaaa }, + { 0x99e8, 0x3c466478 }, + { 0x99ec, 0x000000aa }, + { AR5K_PHY_SCLOCK, 0x0000000c }, + { AR5K_PHY_SDELAY, 0x000000ff }, + { AR5K_PHY_SPENDING, 0x00000014 }, + { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, + { 0xa23c, 0x93c889af }, + { AR5K_PHY_FAST_ADC, 0x00000001 }, + { 0xa250, 0x0000a000 }, + { AR5K_PHY_BLUETOOTH, 0x00000000 }, + { AR5K_PHY_TPC_RG1, 0x0cc75380 }, + { 0xa25c, 0x0f0f0f01 }, + { 0xa260, 0x5f690f01 }, + { 0xa264, 0x00418a11 }, + { 0xa268, 0x00000000 }, + { AR5K_PHY_TPC_RG5, 0x0c30c16a }, + { 0xa270, 0x00820820 }, + { 0xa274, 0x001b7caa }, + { 0xa278, 0x1ce739ce }, + { 0xa27c, 0x051701ce }, + { 0xa300, 0x18010000 }, + { 0xa304, 0x30032602 }, + { 0xa308, 0x48073e06 }, + { 0xa30c, 0x560b4c0a }, + { 0xa310, 0x641a600f }, + { 0xa314, 0x784f6e1b }, + { 0xa318, 0x868f7c5a }, + { 0xa31c, 0x8ecf865b }, + { 0xa320, 0x9d4f970f }, + { 0xa324, 0xa5cfa18f }, + { 0xa328, 0xb55faf1f }, + { 0xa32c, 0xbddfb99f }, + { 0xa330, 0xcd7fc73f }, + { 0xa334, 0xd5ffd1bf }, + { 0xa338, 0x00000000 }, + { 0xa33c, 0x00000000 }, + { 0xa340, 0x00000000 }, + { 0xa344, 0x00000000 }, + { 0xa348, 0x3fffffff }, + { 0xa34c, 0x3fffffff }, + { 0xa350, 0x3fffffff }, + { 0xa354, 0x0003ffff }, + { 0xa358, 0x79a8aa1f }, + { 0xa35c, 0x066c420f }, + { 0xa360, 0x0f282207 }, + { 0xa364, 0x17601685 }, + { 0xa368, 0x1f801104 }, + { 0xa36c, 0x37a00c03 }, + { 0xa370, 0x3fc40883 }, + { 0xa374, 0x57c00803 }, + { 0xa378, 0x5fd80682 }, + { 0xa37c, 0x7fe00482 }, + { 0xa380, 0x7f3c7bba }, + { 0xa384, 0xf3307ff0 }, +}; + +/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ +/* XXX: a mode ? */ +static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { + { AR5K_TXCFG, + /* a/XR aTurbo b g (DYN) gTurbo */ + { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, + { AR5K_USEC_5211, + { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, + { AR5K_PHY_TURBO, + { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } }, + { AR5K_PHY_RF_CTL3, + { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, + { AR5K_PHY_RF_CTL4, + { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY_PA_CTL, + { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } }, + { AR5K_PHY_SETTLING, + { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } }, + { AR5K_PHY_GAIN, + { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } }, + { AR5K_PHY_DESIRED_SIZE, + { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, + { AR5K_PHY_SIG, + { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, + { AR5K_PHY_WEAK_OFDM_LOW_THR, + { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, + { AR5K_PHY_RX_DELAY, + { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { AR5K_PHY_CCKTXCTL, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY_CCK_CROSSCORR, + { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } }, + { AR5K_PHY_CCK_RX_CTL_4, + { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, + { 0xa324, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa328, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa32c, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa330, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa334, + { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, +}; + +static const struct ath5k_ini rf2425_ini_common_end[] = { + { AR5K_DCU_FP, 0x000003e0 }, + { AR5K_SEQ_MASK, 0x0000000f }, + { 0x809c, 0x00000000 }, + { 0x80a0, 0x00000000 }, + { AR5K_MIC_QOS_CTL, 0x00000000 }, + { AR5K_MIC_QOS_SEL, 0x00000000 }, + { AR5K_MISC_MODE, 0x00000000 }, + { AR5K_OFDM_FIL_CNT, 0x00000000 }, + { AR5K_CCK_FIL_CNT, 0x00000000 }, + { AR5K_PHYERR_CNT1, 0x00000000 }, + { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, + { AR5K_PHYERR_CNT2, 0x00000000 }, + { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, + { AR5K_TSF_THRES, 0x00000000 }, + { 0x8140, 0x800003f9 }, + { 0x8144, 0x00000000 }, + { AR5K_PHY_AGC, 0x00000000 }, + { AR5K_PHY_ADC_CTL, 0x0000a000 }, + { 0x983c, 0x00200400 }, + { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, + { AR5K_PHY_SCR, 0x0000001f }, + { AR5K_PHY_SLMT, 0x00000080 }, + { AR5K_PHY_SCAL, 0x0000000e }, + { 0x9958, 0x00081fff }, + { AR5K_PHY_TIMING_7, 0x00000000 }, + { AR5K_PHY_TIMING_8, 0x02800000 }, + { AR5K_PHY_TIMING_11, 0x00000000 }, + { 0x99dc, 0xfebadbe8 }, + { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, + { 0x99e4, 0xaaaaaaaa }, + { 0x99e8, 0x3c466478 }, + { 0x99ec, 0x000000aa }, + { AR5K_PHY_SCLOCK, 0x0000000c }, + { AR5K_PHY_SDELAY, 0x000000ff }, + { AR5K_PHY_SPENDING, 0x00000014 }, + { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, + { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, + { AR5K_PHY_TXPOWER_RATE4, 0x20202020 }, + { 0xa23c, 0x93c889af }, + { AR5K_PHY_FAST_ADC, 0x00000001 }, + { 0xa250, 0x0000a000 }, + { AR5K_PHY_BLUETOOTH, 0x00000000 }, + { AR5K_PHY_TPC_RG1, 0x0cc75380 }, + { 0xa25c, 0x0f0f0f01 }, + { 0xa260, 0x5f690f01 }, + { 0xa264, 0x00418a11 }, + { 0xa268, 0x00000000 }, + { AR5K_PHY_TPC_RG5, 0x0c30c166 }, + { 0xa270, 0x00820820 }, + { 0xa274, 0x081a3caa }, + { 0xa278, 0x1ce739ce }, + { 0xa27c, 0x051701ce }, + { 0xa300, 0x16010000 }, + { 0xa304, 0x2c032402 }, + { 0xa308, 0x48433e42 }, + { 0xa30c, 0x5a0f500b }, + { 0xa310, 0x6c4b624a }, + { 0xa314, 0x7e8b748a }, + { 0xa318, 0x96cf8ccb }, + { 0xa31c, 0xa34f9d0f }, + { 0xa320, 0xa7cfa58f }, + { 0xa348, 0x3fffffff }, + { 0xa34c, 0x3fffffff }, + { 0xa350, 0x3fffffff }, + { 0xa354, 0x0003ffff }, + { 0xa358, 0x79a8aa1f }, + { 0xa35c, 0x066c420f }, + { 0xa360, 0x0f282207 }, + { 0xa364, 0x17601685 }, + { 0xa368, 0x1f801104 }, + { 0xa36c, 0x37a00c03 }, + { 0xa370, 0x3fc40883 }, + { 0xa374, 0x57c00803 }, + { 0xa378, 0x5fd80682 }, + { 0xa37c, 0x7fe00482 }, + { 0xa380, 0x7f3c7bba }, + { 0xa384, 0xf3307ff0 }, +}; + +/* + * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with + * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) + */ + +/* RF5111 Initial BaseBand Gain settings */ +static const struct ath5k_ini rf5111_ini_bbgain[] = { + { AR5K_BB_GAIN(0), 0x00000000 }, + { AR5K_BB_GAIN(1), 0x00000020 }, + { AR5K_BB_GAIN(2), 0x00000010 }, + { AR5K_BB_GAIN(3), 0x00000030 }, + { AR5K_BB_GAIN(4), 0x00000008 }, + { AR5K_BB_GAIN(5), 0x00000028 }, + { AR5K_BB_GAIN(6), 0x00000004 }, + { AR5K_BB_GAIN(7), 0x00000024 }, + { AR5K_BB_GAIN(8), 0x00000014 }, + { AR5K_BB_GAIN(9), 0x00000034 }, + { AR5K_BB_GAIN(10), 0x0000000c }, + { AR5K_BB_GAIN(11), 0x0000002c }, + { AR5K_BB_GAIN(12), 0x00000002 }, + { AR5K_BB_GAIN(13), 0x00000022 }, + { AR5K_BB_GAIN(14), 0x00000012 }, + { AR5K_BB_GAIN(15), 0x00000032 }, + { AR5K_BB_GAIN(16), 0x0000000a }, + { AR5K_BB_GAIN(17), 0x0000002a }, + { AR5K_BB_GAIN(18), 0x00000006 }, + { AR5K_BB_GAIN(19), 0x00000026 }, + { AR5K_BB_GAIN(20), 0x00000016 }, + { AR5K_BB_GAIN(21), 0x00000036 }, + { AR5K_BB_GAIN(22), 0x0000000e }, + { AR5K_BB_GAIN(23), 0x0000002e }, + { AR5K_BB_GAIN(24), 0x00000001 }, + { AR5K_BB_GAIN(25), 0x00000021 }, + { AR5K_BB_GAIN(26), 0x00000011 }, + { AR5K_BB_GAIN(27), 0x00000031 }, + { AR5K_BB_GAIN(28), 0x00000009 }, + { AR5K_BB_GAIN(29), 0x00000029 }, + { AR5K_BB_GAIN(30), 0x00000005 }, + { AR5K_BB_GAIN(31), 0x00000025 }, + { AR5K_BB_GAIN(32), 0x00000015 }, + { AR5K_BB_GAIN(33), 0x00000035 }, + { AR5K_BB_GAIN(34), 0x0000000d }, + { AR5K_BB_GAIN(35), 0x0000002d }, + { AR5K_BB_GAIN(36), 0x00000003 }, + { AR5K_BB_GAIN(37), 0x00000023 }, + { AR5K_BB_GAIN(38), 0x00000013 }, + { AR5K_BB_GAIN(39), 0x00000033 }, + { AR5K_BB_GAIN(40), 0x0000000b }, + { AR5K_BB_GAIN(41), 0x0000002b }, + { AR5K_BB_GAIN(42), 0x0000002b }, + { AR5K_BB_GAIN(43), 0x0000002b }, + { AR5K_BB_GAIN(44), 0x0000002b }, + { AR5K_BB_GAIN(45), 0x0000002b }, + { AR5K_BB_GAIN(46), 0x0000002b }, + { AR5K_BB_GAIN(47), 0x0000002b }, + { AR5K_BB_GAIN(48), 0x0000002b }, + { AR5K_BB_GAIN(49), 0x0000002b }, + { AR5K_BB_GAIN(50), 0x0000002b }, + { AR5K_BB_GAIN(51), 0x0000002b }, + { AR5K_BB_GAIN(52), 0x0000002b }, + { AR5K_BB_GAIN(53), 0x0000002b }, + { AR5K_BB_GAIN(54), 0x0000002b }, + { AR5K_BB_GAIN(55), 0x0000002b }, + { AR5K_BB_GAIN(56), 0x0000002b }, + { AR5K_BB_GAIN(57), 0x0000002b }, + { AR5K_BB_GAIN(58), 0x0000002b }, + { AR5K_BB_GAIN(59), 0x0000002b }, + { AR5K_BB_GAIN(60), 0x0000002b }, + { AR5K_BB_GAIN(61), 0x0000002b }, + { AR5K_BB_GAIN(62), 0x00000002 }, + { AR5K_BB_GAIN(63), 0x00000016 }, +}; + +/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */ +static const struct ath5k_ini rf5112_ini_bbgain[] = { + { AR5K_BB_GAIN(0), 0x00000000 }, + { AR5K_BB_GAIN(1), 0x00000001 }, + { AR5K_BB_GAIN(2), 0x00000002 }, + { AR5K_BB_GAIN(3), 0x00000003 }, + { AR5K_BB_GAIN(4), 0x00000004 }, + { AR5K_BB_GAIN(5), 0x00000005 }, + { AR5K_BB_GAIN(6), 0x00000008 }, + { AR5K_BB_GAIN(7), 0x00000009 }, + { AR5K_BB_GAIN(8), 0x0000000a }, + { AR5K_BB_GAIN(9), 0x0000000b }, + { AR5K_BB_GAIN(10), 0x0000000c }, + { AR5K_BB_GAIN(11), 0x0000000d }, + { AR5K_BB_GAIN(12), 0x00000010 }, + { AR5K_BB_GAIN(13), 0x00000011 }, + { AR5K_BB_GAIN(14), 0x00000012 }, + { AR5K_BB_GAIN(15), 0x00000013 }, + { AR5K_BB_GAIN(16), 0x00000014 }, + { AR5K_BB_GAIN(17), 0x00000015 }, + { AR5K_BB_GAIN(18), 0x00000018 }, + { AR5K_BB_GAIN(19), 0x00000019 }, + { AR5K_BB_GAIN(20), 0x0000001a }, + { AR5K_BB_GAIN(21), 0x0000001b }, + { AR5K_BB_GAIN(22), 0x0000001c }, + { AR5K_BB_GAIN(23), 0x0000001d }, + { AR5K_BB_GAIN(24), 0x00000020 }, + { AR5K_BB_GAIN(25), 0x00000021 }, + { AR5K_BB_GAIN(26), 0x00000022 }, + { AR5K_BB_GAIN(27), 0x00000023 }, + { AR5K_BB_GAIN(28), 0x00000024 }, + { AR5K_BB_GAIN(29), 0x00000025 }, + { AR5K_BB_GAIN(30), 0x00000028 }, + { AR5K_BB_GAIN(31), 0x00000029 }, + { AR5K_BB_GAIN(32), 0x0000002a }, + { AR5K_BB_GAIN(33), 0x0000002b }, + { AR5K_BB_GAIN(34), 0x0000002c }, + { AR5K_BB_GAIN(35), 0x0000002d }, + { AR5K_BB_GAIN(36), 0x00000030 }, + { AR5K_BB_GAIN(37), 0x00000031 }, + { AR5K_BB_GAIN(38), 0x00000032 }, + { AR5K_BB_GAIN(39), 0x00000033 }, + { AR5K_BB_GAIN(40), 0x00000034 }, + { AR5K_BB_GAIN(41), 0x00000035 }, + { AR5K_BB_GAIN(42), 0x00000035 }, + { AR5K_BB_GAIN(43), 0x00000035 }, + { AR5K_BB_GAIN(44), 0x00000035 }, + { AR5K_BB_GAIN(45), 0x00000035 }, + { AR5K_BB_GAIN(46), 0x00000035 }, + { AR5K_BB_GAIN(47), 0x00000035 }, + { AR5K_BB_GAIN(48), 0x00000035 }, + { AR5K_BB_GAIN(49), 0x00000035 }, + { AR5K_BB_GAIN(50), 0x00000035 }, + { AR5K_BB_GAIN(51), 0x00000035 }, + { AR5K_BB_GAIN(52), 0x00000035 }, + { AR5K_BB_GAIN(53), 0x00000035 }, + { AR5K_BB_GAIN(54), 0x00000035 }, + { AR5K_BB_GAIN(55), 0x00000035 }, + { AR5K_BB_GAIN(56), 0x00000035 }, + { AR5K_BB_GAIN(57), 0x00000035 }, + { AR5K_BB_GAIN(58), 0x00000035 }, + { AR5K_BB_GAIN(59), 0x00000035 }, + { AR5K_BB_GAIN(60), 0x00000035 }, + { AR5K_BB_GAIN(61), 0x00000035 }, + { AR5K_BB_GAIN(62), 0x00000010 }, + { AR5K_BB_GAIN(63), 0x0000001a }, +}; + + +/* + * Write initial register dump + */ +static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, + const struct ath5k_ini *ini_regs, bool change_channel) +{ + unsigned int i; + + /* Write initial registers */ + for (i = 0; i < size; i++) { + /* On channel change there is + * no need to mess with PCU */ + if (change_channel && + ini_regs[i].ini_register >= AR5K_PCU_MIN && + ini_regs[i].ini_register <= AR5K_PCU_MAX) + continue; + + switch (ini_regs[i].ini_mode) { + case AR5K_INI_READ: + /* Cleared on read */ + ath5k_hw_reg_read(ah, ini_regs[i].ini_register); + break; + case AR5K_INI_WRITE: + default: + AR5K_REG_WAIT(i); + ath5k_hw_reg_write(ah, ini_regs[i].ini_value, + ini_regs[i].ini_register); + } + } +} + +static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, + unsigned int size, const struct ath5k_ini_mode *ini_mode, + u8 mode) +{ + unsigned int i; + + for (i = 0; i < size; i++) { + AR5K_REG_WAIT(i); + ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode], + (u32)ini_mode[i].mode_register); + } + +} + +int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) +{ + /* + * Write initial register settings + */ + + /* For AR5212 and combatible */ + if (ah->ah_version == AR5K_AR5212) { + + /* First set of mode-specific settings */ + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(ar5212_ini_mode_start), + ar5212_ini_mode_start, mode); + + /* + * Write initial settings common for all modes + */ + ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), + ar5212_ini_common_start, change_channel); + + /* Second set of mode-specific settings */ + switch (ah->ah_radio) { + case AR5K_RF5111: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf5111_ini_mode_end), + rf5111_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5111_ini_common_end), + rf5111_ini_common_end, change_channel); + + /* Baseband gain table */ + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5111_ini_bbgain), + rf5111_ini_bbgain, change_channel); + + break; + case AR5K_RF5112: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf5112_ini_mode_end), + rf5112_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_common_end), + rf5112_ini_common_end, change_channel); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, change_channel); + + break; + case AR5K_RF5413: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf5413_ini_mode_end), + rf5413_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5413_ini_common_end), + rf5413_ini_common_end, change_channel); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, change_channel); + + break; + case AR5K_RF2316: + case AR5K_RF2413: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf2413_ini_mode_end), + rf2413_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf2413_ini_common_end), + rf2413_ini_common_end, change_channel); + + /* Override settings from rf2413_ini_common_end */ + if (ah->ah_radio == AR5K_RF2316) { + ath5k_hw_reg_write(ah, 0x00004000, + AR5K_PHY_AGC); + ath5k_hw_reg_write(ah, 0x081b7caa, + 0xa274); + } + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, change_channel); + break; + case AR5K_RF2317: + case AR5K_RF2425: + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf2425_ini_mode_end), + rf2425_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf2425_ini_common_end), + rf2425_ini_common_end, change_channel); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, change_channel); + break; + default: + return -EINVAL; + + } + + /* For AR5211 */ + } else if (ah->ah_version == AR5K_AR5211) { + + /* AR5K_MODE_11B */ + if (mode > 2) { + ATH5K_ERR(ah->ah_sc, + "unsupported channel mode: %d\n", mode); + return -EINVAL; + } + + /* Mode-specific settings */ + ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode), + ar5211_ini_mode, mode); + + /* + * Write initial settings common for all modes + */ + ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), + ar5211_ini, change_channel); + + /* AR5211 only comes with 5111 */ + + /* Baseband gain table */ + ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), + rf5111_ini_bbgain, change_channel); + /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ + } else if (ah->ah_version == AR5K_AR5210) { + ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), + ar5210_ini, change_channel); + } + + return 0; +} diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c new file mode 100644 index 000000000000..19555fb79c9b --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * Copyright (c) 2004-2005 Atheros Communications, Inc. + * Copyright (c) 2007 Jiri Slaby + * Copyright (c) 2009 Bob Copeland + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include "ath5k.h" +#include "base.h" + +#define ATH_SDEVICE(subv,subd) \ + .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ + .subvendor = (subv), .subdevice = (subd) + +#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity)) +#define ATH_PIN(data) ((data) >> 8) +#define ATH_POLARITY(data) ((data) & 0xff) + +/* Devices we match on for LED config info (typically laptops) */ +static const struct pci_device_id ath5k_led_devices[] = { + /* IBM-specific AR5212 */ + { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, + /* AR5211 */ + { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, + /* HP Compaq nc6xx, nc4000, nx6000 */ + { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, + /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, + /* Acer Ferrari 5000 (russ.dill@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, + /* E-machines E510 (tuliom@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, + /* Acer Extensa 5620z (nekoreeve@gmail.com) */ + { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, + { } +}; + +void ath5k_led_enable(struct ath5k_softc *sc) +{ + if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { + ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); + ath5k_led_off(sc); + } +} + +void ath5k_led_on(struct ath5k_softc *sc) +{ + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + return; + ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); +} + +void ath5k_led_off(struct ath5k_softc *sc) +{ + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + return; + ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); +} + +static void +ath5k_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct ath5k_led *led = container_of(led_dev, struct ath5k_led, + led_dev); + + if (brightness == LED_OFF) + ath5k_led_off(led->sc); + else + ath5k_led_on(led->sc); +} + +static int +ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, + const char *name, char *trigger) +{ + int err; + + led->sc = sc; + strncpy(led->name, name, sizeof(led->name)); + led->led_dev.name = led->name; + led->led_dev.default_trigger = trigger; + led->led_dev.brightness_set = ath5k_led_brightness_set; + + err = led_classdev_register(&sc->pdev->dev, &led->led_dev); + if (err) { + ATH5K_WARN(sc, "could not register LED %s\n", name); + led->sc = NULL; + } + return err; +} + +static void +ath5k_unregister_led(struct ath5k_led *led) +{ + if (!led->sc) + return; + led_classdev_unregister(&led->led_dev); + ath5k_led_off(led->sc); + led->sc = NULL; +} + +void ath5k_unregister_leds(struct ath5k_softc *sc) +{ + ath5k_unregister_led(&sc->rx_led); + ath5k_unregister_led(&sc->tx_led); +} + +int ath5k_init_leds(struct ath5k_softc *sc) +{ + int ret = 0; + struct ieee80211_hw *hw = sc->hw; + struct pci_dev *pdev = sc->pdev; + char name[ATH5K_LED_MAX_NAME_LEN + 1]; + const struct pci_device_id *match; + + match = pci_match_id(&ath5k_led_devices[0], pdev); + if (match) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = ATH_PIN(match->driver_data); + sc->led_on = ATH_POLARITY(match->driver_data); + } + + if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + goto out; + + ath5k_led_enable(sc); + + snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); + ret = ath5k_register_led(sc, &sc->rx_led, name, + ieee80211_get_rx_led_name(hw)); + if (ret) + goto out; + + snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); + ret = ath5k_register_led(sc, &sc->tx_led, name, + ieee80211_get_tx_led_name(hw)); +out: + return ret; +} + diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c new file mode 100644 index 000000000000..55122f1e1986 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -0,0 +1,1174 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Matthew W. S. Bell + * Copyright (c) 2007-2008 Luis Rodriguez + * Copyright (c) 2007-2008 Pavel Roskin + * Copyright (c) 2007-2008 Jiri Slaby + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/*********************************\ +* Protocol Control Unit Functions * +\*********************************/ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/*******************\ +* Generic functions * +\*******************/ + +/** + * ath5k_hw_set_opmode - Set PCU operating mode + * + * @ah: The &struct ath5k_hw + * + * Initialize PCU for the various operating modes (AP/STA etc) + * + * NOTE: ah->ah_op_mode must be set before calling this. + */ +int ath5k_hw_set_opmode(struct ath5k_hw *ah) +{ + u32 pcu_reg, beacon_reg, low_id, high_id; + + + /* Preserve rest settings */ + pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; + pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP + | AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); + + beacon_reg = 0; + + ATH5K_TRACE(ah->ah_sc); + + switch (ah->ah_op_mode) { + case NL80211_IFTYPE_ADHOC: + pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; + beacon_reg |= AR5K_BCR_ADHOC; + if (ah->ah_version == AR5K_AR5210) + pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; + else + AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; + beacon_reg |= AR5K_BCR_AP; + if (ah->ah_version == AR5K_AR5210) + pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; + else + AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); + break; + + case NL80211_IFTYPE_STATION: + pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + AR5K_STA_ID1_PWR_SV : 0); + case NL80211_IFTYPE_MONITOR: + pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE + | (ah->ah_version == AR5K_AR5210 ? + AR5K_STA_ID1_NO_PSPOLL : 0); + break; + + default: + return -EINVAL; + } + + /* + * Set PCU registers + */ + low_id = AR5K_LOW_ID(ah->ah_sta_id); + high_id = AR5K_HIGH_ID(ah->ah_sta_id); + ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); + ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); + + /* + * Set Beacon Control Register on 5210 + */ + if (ah->ah_version == AR5K_AR5210) + ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); + + return 0; +} + +/** + * ath5k_hw_update - Update mib counters (mac layer statistics) + * + * @ah: The &struct ath5k_hw + * @stats: The &struct ieee80211_low_level_stats we use to track + * statistics on the driver + * + * Reads MIB counters from PCU and updates sw statistics. Must be + * called after a MIB interrupt. + */ +void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, + struct ieee80211_low_level_stats *stats) +{ + ATH5K_TRACE(ah->ah_sc); + + /* Read-And-Clear */ + stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); + stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); + stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); + stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); + + /* XXX: Should we use this to track beacon count ? + * -we read it anyway to clear the register */ + ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); + + /* Reset profile count registers on 5212*/ + if (ah->ah_version == AR5K_AR5212) { + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); + ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); + } + + /* TODO: Handle ANI stats */ +} + +/** + * ath5k_hw_set_ack_bitrate - set bitrate for ACKs + * + * @ah: The &struct ath5k_hw + * @high: Flag to determine if we want to use high transmition rate + * for ACKs or not + * + * If high flag is set, we tell hw to use a set of control rates based on + * the current transmition rate (check out control_rates array inside reset.c). + * If not hw just uses the lowest rate available for the current modulation + * scheme being used (1Mbit for CCK and 6Mbits for OFDM). + */ +void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) +{ + if (ah->ah_version != AR5K_AR5212) + return; + else { + u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; + if (high) + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); + } +} + + +/******************\ +* ACK/CTS Timeouts * +\******************/ + +/** + * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + + return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, + AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); +} + +/** + * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU + * + * @ah: The &struct ath5k_hw + * @timeout: Timeout in usec + */ +int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) +{ + ATH5K_TRACE(ah->ah_sc); + if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), + ah->ah_turbo) <= timeout) + return -EINVAL; + + AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, + ath5k_hw_htoclock(timeout, ah->ah_turbo)); + + return 0; +} + +/** + * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, + AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); +} + +/** + * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU + * + * @ah: The &struct ath5k_hw + * @timeout: Timeout in usec + */ +int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) +{ + ATH5K_TRACE(ah->ah_sc); + if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), + ah->ah_turbo) <= timeout) + return -EINVAL; + + AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, + ath5k_hw_htoclock(timeout, ah->ah_turbo)); + + return 0; +} + + +/****************\ +* BSSID handling * +\****************/ + +/** + * ath5k_hw_get_lladdr - Get station id + * + * @ah: The &struct ath5k_hw + * @mac: The card's mac address + * + * Initialize ah->ah_sta_id using the mac address provided + * (just a memcpy). + * + * TODO: Remove it once we merge ath5k_softc and ath5k_hw + */ +void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) +{ + ATH5K_TRACE(ah->ah_sc); + memcpy(mac, ah->ah_sta_id, ETH_ALEN); +} + +/** + * ath5k_hw_set_lladdr - Set station id + * + * @ah: The &struct ath5k_hw + * @mac: The card's mac address + * + * Set station id on hw using the provided mac address + */ +int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) +{ + u32 low_id, high_id; + u32 pcu_reg; + + ATH5K_TRACE(ah->ah_sc); + /* Set new station ID */ + memcpy(ah->ah_sta_id, mac, ETH_ALEN); + + pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; + + low_id = AR5K_LOW_ID(mac); + high_id = AR5K_HIGH_ID(mac); + + ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); + ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); + + return 0; +} + +/** + * ath5k_hw_set_associd - Set BSSID for association + * + * @ah: The &struct ath5k_hw + * @bssid: BSSID + * @assoc_id: Assoc id + * + * Sets the BSSID which trigers the "SME Join" operation + */ +void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) +{ + u32 low_id, high_id; + u16 tim_offset = 0; + + /* + * Set simple BSSID mask on 5212 + */ + if (ah->ah_version == AR5K_AR5212) { + ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), + AR5K_BSS_IDM0); + ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), + AR5K_BSS_IDM1); + } + + /* + * Set BSSID which triggers the "SME Join" operation + */ + low_id = AR5K_LOW_ID(bssid); + high_id = AR5K_HIGH_ID(bssid); + ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); + ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << + AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); + + if (assoc_id == 0) { + ath5k_hw_disable_pspoll(ah); + return; + } + + AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, + tim_offset ? tim_offset + 4 : 0); + + ath5k_hw_enable_pspoll(ah, NULL, 0); +} + +/** + * ath5k_hw_set_bssid_mask - filter out bssids we listen + * + * @ah: the &struct ath5k_hw + * @mask: the bssid_mask, a u8 array of size ETH_ALEN + * + * BSSID masking is a method used by AR5212 and newer hardware to inform PCU + * which bits of the interface's MAC address should be looked at when trying + * to decide which packets to ACK. In station mode and AP mode with a single + * BSS every bit matters since we lock to only one BSS. In AP mode with + * multiple BSSes (virtual interfaces) not every bit matters because hw must + * accept frames for all BSSes and so we tweak some bits of our mac address + * in order to have multiple BSSes. + * + * NOTE: This is a simple filter and does *not* filter out all + * relevant frames. Some frames that are not for us might get ACKed from us + * by PCU because they just match the mask. + * + * When handling multiple BSSes you can get the BSSID mask by computing the + * set of ~ ( MAC XOR BSSID ) for all bssids we handle. + * + * When you do this you are essentially computing the common bits of all your + * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with + * the MAC address to obtain the relevant bits and compare the result with + * (frame's BSSID & mask) to see if they match. + */ +/* + * Simple example: on your card you have have two BSSes you have created with + * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. + * There is another BSSID-03 but you are not part of it. For simplicity's sake, + * assuming only 4 bits for a mac address and for BSSIDs you can then have: + * + * \ + * MAC: 0001 | + * BSSID-01: 0100 | --> Belongs to us + * BSSID-02: 1001 | + * / + * ------------------- + * BSSID-03: 0110 | --> External + * ------------------- + * + * Our bssid_mask would then be: + * + * On loop iteration for BSSID-01: + * ~(0001 ^ 0100) -> ~(0101) + * -> 1010 + * bssid_mask = 1010 + * + * On loop iteration for BSSID-02: + * bssid_mask &= ~(0001 ^ 1001) + * bssid_mask = (1010) & ~(0001 ^ 1001) + * bssid_mask = (1010) & ~(1001) + * bssid_mask = (1010) & (0110) + * bssid_mask = 0010 + * + * A bssid_mask of 0010 means "only pay attention to the second least + * significant bit". This is because its the only bit common + * amongst the MAC and all BSSIDs we support. To findout what the real + * common bit is we can simply "&" the bssid_mask now with any BSSID we have + * or our MAC address (we assume the hardware uses the MAC address). + * + * Now, suppose there's an incoming frame for BSSID-03: + * + * IFRAME-01: 0110 + * + * An easy eye-inspeciton of this already should tell you that this frame + * will not pass our check. This is beacuse the bssid_mask tells the + * hardware to only look at the second least significant bit and the + * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB + * as 1, which does not match 0. + * + * So with IFRAME-01 we *assume* the hardware will do: + * + * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; + * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; + * --> allow = (0010) == 0000 ? 1 : 0; + * --> allow = 0 + * + * Lets now test a frame that should work: + * + * IFRAME-02: 0001 (we should allow) + * + * allow = (0001 & 1010) == 1010 + * + * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; + * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; + * --> allow = (0010) == (0010) + * --> allow = 1 + * + * Other examples: + * + * IFRAME-03: 0100 --> allowed + * IFRAME-04: 1001 --> allowed + * IFRAME-05: 1101 --> allowed but its not for us!!! + * + */ +int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) +{ + u32 low_id, high_id; + ATH5K_TRACE(ah->ah_sc); + + /* Cache bssid mask so that we can restore it + * on reset */ + memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); + if (ah->ah_version == AR5K_AR5212) { + low_id = AR5K_LOW_ID(mask); + high_id = AR5K_HIGH_ID(mask); + + ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); + ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); + + return 0; + } + + return -EIO; +} + + +/************\ +* RX Control * +\************/ + +/** + * ath5k_hw_start_rx_pcu - Start RX engine + * + * @ah: The &struct ath5k_hw + * + * Starts RX engine on PCU so that hw can process RXed frames + * (ACK etc). + * + * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma + * TODO: Init ANI here + */ +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); +} + +/** + * at5k_hw_stop_rx_pcu - Stop RX engine + * + * @ah: The &struct ath5k_hw + * + * Stops RX engine on PCU + * + * TODO: Detach ANI here + */ +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); +} + +/* + * Set multicast filter + */ +void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) +{ + ATH5K_TRACE(ah->ah_sc); + /* Set the multicat filter */ + ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); + ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); +} + +/* + * Set multicast filter by index + */ +int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) +{ + + ATH5K_TRACE(ah->ah_sc); + if (index >= 64) + return -EINVAL; + else if (index >= 32) + AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, + (1 << (index - 32))); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); + + return 0; +} + +/* + * Clear Multicast filter by index + */ +int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) +{ + + ATH5K_TRACE(ah->ah_sc); + if (index >= 64) + return -EINVAL; + else if (index >= 32) + AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, + (1 << (index - 32))); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); + + return 0; +} + +/** + * ath5k_hw_get_rx_filter - Get current rx filter + * + * @ah: The &struct ath5k_hw + * + * Returns the RX filter by reading rx filter and + * phy error filter registers. RX filter is used + * to set the allowed frame types that PCU will accept + * and pass to the driver. For a list of frame types + * check out reg.h. + */ +u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) +{ + u32 data, filter = 0; + + ATH5K_TRACE(ah->ah_sc); + filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); + + /*Radar detection for 5212*/ + if (ah->ah_version == AR5K_AR5212) { + data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); + + if (data & AR5K_PHY_ERR_FIL_RADAR) + filter |= AR5K_RX_FILTER_RADARERR; + if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) + filter |= AR5K_RX_FILTER_PHYERR; + } + + return filter; +} + +/** + * ath5k_hw_set_rx_filter - Set rx filter + * + * @ah: The &struct ath5k_hw + * @filter: RX filter mask (see reg.h) + * + * Sets RX filter register and also handles PHY error filter + * register on 5212 and newer chips so that we have proper PHY + * error reporting. + */ +void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) +{ + u32 data = 0; + + ATH5K_TRACE(ah->ah_sc); + + /* Set PHY error filter register on 5212*/ + if (ah->ah_version == AR5K_AR5212) { + if (filter & AR5K_RX_FILTER_RADARERR) + data |= AR5K_PHY_ERR_FIL_RADAR; + if (filter & AR5K_RX_FILTER_PHYERR) + data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; + } + + /* + * The AR5210 uses promiscous mode to detect radar activity + */ + if (ah->ah_version == AR5K_AR5210 && + (filter & AR5K_RX_FILTER_RADARERR)) { + filter &= ~AR5K_RX_FILTER_RADARERR; + filter |= AR5K_RX_FILTER_PROM; + } + + /*Zero length DMA (phy error reporting) */ + if (data) + AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); + + /*Write RX Filter register*/ + ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); + + /*Write PHY error filter register on 5212*/ + if (ah->ah_version == AR5K_AR5212) + ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); + +} + + +/****************\ +* Beacon control * +\****************/ + +/** + * ath5k_hw_get_tsf32 - Get a 32bit TSF + * + * @ah: The &struct ath5k_hw + * + * Returns lower 32 bits of current TSF + */ +u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + return ath5k_hw_reg_read(ah, AR5K_TSF_L32); +} + +/** + * ath5k_hw_get_tsf64 - Get the full 64bit TSF + * + * @ah: The &struct ath5k_hw + * + * Returns the current TSF + */ +u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) +{ + u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + ATH5K_TRACE(ah->ah_sc); + + return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); +} + +/** + * ath5k_hw_set_tsf64 - Set a new 64bit TSF + * + * @ah: The &struct ath5k_hw + * @tsf64: The new 64bit TSF + * + * Sets the new TSF + */ +void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) +{ + ATH5K_TRACE(ah->ah_sc); + + ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); + ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); +} + +/** + * ath5k_hw_reset_tsf - Force a TSF reset + * + * @ah: The &struct ath5k_hw + * + * Forces a TSF reset on PCU + */ +void ath5k_hw_reset_tsf(struct ath5k_hw *ah) +{ + u32 val; + + ATH5K_TRACE(ah->ah_sc); + + val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; + + /* + * Each write to the RESET_TSF bit toggles a hardware internal + * signal to reset TSF, but if left high it will cause a TSF reset + * on the next chip reset as well. Thus we always write the value + * twice to clear the signal. + */ + ath5k_hw_reg_write(ah, val, AR5K_BEACON); + ath5k_hw_reg_write(ah, val, AR5K_BEACON); +} + +/* + * Initialize beacon timers + */ +void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) +{ + u32 timer1, timer2, timer3; + + ATH5K_TRACE(ah->ah_sc); + /* + * Set the additional timers by mode + */ + switch (ah->ah_op_mode) { + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_STATION: + /* In STA mode timer1 is used as next wakeup + * timer and timer2 as next CFP duration start + * timer. Both in 1/8TUs. */ + /* TODO: PCF handling */ + if (ah->ah_version == AR5K_AR5210) { + timer1 = 0xffffffff; + timer2 = 0xffffffff; + } else { + timer1 = 0x0000ffff; + timer2 = 0x0007ffff; + } + /* Mark associated AP as PCF incapable for now */ + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); + break; + case NL80211_IFTYPE_ADHOC: + AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); + default: + /* On non-STA modes timer1 is used as next DMA + * beacon alert (DBA) timer and timer2 as next + * software beacon alert. Both in 1/8TUs. */ + timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; + timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; + break; + } + + /* Timer3 marks the end of our ATIM window + * a zero length window is not allowed because + * we 'll get no beacons */ + timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); + + /* + * Set the beacon register and enable all timers. + */ + /* When in AP mode zero timer0 to start TSF */ + if (ah->ah_op_mode == NL80211_IFTYPE_AP) + ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); + else + ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); + ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); + ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); + ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); + + /* Force a TSF reset if requested and enable beacons */ + if (interval & AR5K_BEACON_RESET_TSF) + ath5k_hw_reset_tsf(ah); + + ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | + AR5K_BEACON_ENABLE), + AR5K_BEACON); + + /* Flush any pending BMISS interrupts on ISR by + * performing a clear-on-write operation on PISR + * register for the BMISS bit (writing a bit on + * ISR togles a reset for that bit and leaves + * the rest bits intact) */ + if (ah->ah_version == AR5K_AR5210) + ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); + else + ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); + + /* TODO: Set enchanced sleep registers on AR5212 + * based on vif->bss_conf params, until then + * disable power save reporting.*/ + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); + +} + +#if 0 +/* + * Set beacon timers + */ +int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, + const struct ath5k_beacon_state *state) +{ + u32 cfp_period, next_cfp, dtim, interval, next_beacon; + + /* + * TODO: should be changed through *state + * review struct ath5k_beacon_state struct + * + * XXX: These are used for cfp period bellow, are they + * ok ? Is it O.K. for tsf here to be 0 or should we use + * get_tsf ? + */ + u32 dtim_count = 0; /* XXX */ + u32 cfp_count = 0; /* XXX */ + u32 tsf = 0; /* XXX */ + + ATH5K_TRACE(ah->ah_sc); + /* Return on an invalid beacon state */ + if (state->bs_interval < 1) + return -EINVAL; + + interval = state->bs_interval; + dtim = state->bs_dtim_period; + + /* + * PCF support? + */ + if (state->bs_cfp_period > 0) { + /* + * Enable PCF mode and set the CFP + * (Contention Free Period) and timer registers + */ + cfp_period = state->bs_cfp_period * state->bs_dtim_period * + state->bs_interval; + next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * + state->bs_interval; + + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, + AR5K_STA_ID1_DEFAULT_ANTENNA | + AR5K_STA_ID1_PCF); + ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); + ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, + AR5K_CFP_DUR); + ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : + next_cfp)) << 3, AR5K_TIMER2); + } else { + /* Disable PCF mode */ + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, + AR5K_STA_ID1_DEFAULT_ANTENNA | + AR5K_STA_ID1_PCF); + } + + /* + * Enable the beacon timer register + */ + ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); + + /* + * Start the beacon timers + */ + ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & + ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | + AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, + AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, + AR5K_BEACON_PERIOD), AR5K_BEACON); + + /* + * Write new beacon miss threshold, if it appears to be valid + * XXX: Figure out right values for min <= bs_bmiss_threshold <= max + * and return if its not in range. We can test this by reading value and + * setting value to a largest value and seeing which values register. + */ + + AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, + state->bs_bmiss_threshold); + + /* + * Set sleep control register + * XXX: Didn't find this in 5210 code but since this register + * exists also in ar5k's 5210 headers i leave it as common code. + */ + AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, + (state->bs_sleep_duration - 3) << 3); + + /* + * Set enhanced sleep registers on 5212 + */ + if (ah->ah_version == AR5K_AR5212) { + if (state->bs_sleep_duration > state->bs_interval && + roundup(state->bs_sleep_duration, interval) == + state->bs_sleep_duration) + interval = state->bs_sleep_duration; + + if (state->bs_sleep_duration > dtim && (dtim == 0 || + roundup(state->bs_sleep_duration, dtim) == + state->bs_sleep_duration)) + dtim = state->bs_sleep_duration; + + if (interval > dtim) + return -EINVAL; + + next_beacon = interval == dtim ? state->bs_next_dtim : + state->bs_next_beacon; + + ath5k_hw_reg_write(ah, + AR5K_REG_SM((state->bs_next_dtim - 3) << 3, + AR5K_SLEEP0_NEXT_DTIM) | + AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | + AR5K_SLEEP0_ENH_SLEEP_EN | + AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); + + ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, + AR5K_SLEEP1_NEXT_TIM) | + AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); + + ath5k_hw_reg_write(ah, + AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | + AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); + } + + return 0; +} + +/* + * Reset beacon timers + */ +void ath5k_hw_reset_beacon(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + /* + * Disable beacon timer + */ + ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); + + /* + * Disable some beacon register values + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, + AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); + ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); +} + +/* + * Wait for beacon queue to finish + */ +int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) +{ + unsigned int i; + int ret; + + ATH5K_TRACE(ah->ah_sc); + + /* 5210 doesn't have QCU*/ + if (ah->ah_version == AR5K_AR5210) { + /* + * Wait for beaconn queue to finish by checking + * Control Register and Beacon Status Register. + */ + for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { + if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) + || + !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) + break; + udelay(10); + } + + /* Timeout... */ + if (i <= 0) { + /* + * Re-schedule the beacon queue + */ + ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); + ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, + AR5K_BCR); + + return -EIO; + } + ret = 0; + } else { + /*5211/5212*/ + ret = ath5k_hw_register_timeout(ah, + AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), + AR5K_QCU_STS_FRMPENDCNT, 0, false); + + if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) + return -EIO; + } + + return ret; +} +#endif + + +/*********************\ +* Key table functions * +\*********************/ + +/* + * Reset a key entry on the table + */ +int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) +{ + unsigned int i, type; + u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; + + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); + + type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); + + for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) + ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); + + /* Reset associated MIC entry if TKIP + * is enabled located at offset (entry + 64) */ + if (type == AR5K_KEYTABLE_TYPE_TKIP) { + AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); + for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) + ath5k_hw_reg_write(ah, 0, + AR5K_KEYTABLE_OFF(micentry, i)); + } + + /* + * Set NULL encryption on AR5212+ + * + * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) + * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 + * + * Note2: Windows driver (ndiswrapper) sets this to + * 0x00000714 instead of 0x00000007 + */ + if (ah->ah_version > AR5K_AR5211) { + ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, + AR5K_KEYTABLE_TYPE(entry)); + + if (type == AR5K_KEYTABLE_TYPE_TKIP) { + ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, + AR5K_KEYTABLE_TYPE(micentry)); + } + } + + return 0; +} + +/* + * Check if a table entry is valid + */ +int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) +{ + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); + + /* Check the validation flag at the end of the entry */ + return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & + AR5K_KEYTABLE_VALID; +} + +static +int ath5k_keycache_type(const struct ieee80211_key_conf *key) +{ + switch (key->alg) { + case ALG_TKIP: + return AR5K_KEYTABLE_TYPE_TKIP; + case ALG_CCMP: + return AR5K_KEYTABLE_TYPE_CCM; + case ALG_WEP: + if (key->keylen == LEN_WEP40) + return AR5K_KEYTABLE_TYPE_40; + else if (key->keylen == LEN_WEP104) + return AR5K_KEYTABLE_TYPE_104; + return -EINVAL; + default: + return -EINVAL; + } + return -EINVAL; +} + +/* + * Set a key entry on the table + */ +int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, + const struct ieee80211_key_conf *key, const u8 *mac) +{ + unsigned int i; + int keylen; + __le32 key_v[5] = {}; + __le32 key0 = 0, key1 = 0; + __le32 *rxmic, *txmic; + int keytype; + u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; + bool is_tkip; + const u8 *key_ptr; + + ATH5K_TRACE(ah->ah_sc); + + is_tkip = (key->alg == ALG_TKIP); + + /* + * key->keylen comes in from mac80211 in bytes. + * TKIP is 128 bit + 128 bit mic + */ + keylen = (is_tkip) ? (128 / 8) : key->keylen; + + if (entry > AR5K_KEYTABLE_SIZE || + (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) + return -EOPNOTSUPP; + + if (unlikely(keylen > 16)) + return -EOPNOTSUPP; + + keytype = ath5k_keycache_type(key); + if (keytype < 0) + return keytype; + + /* + * each key block is 6 bytes wide, written as pairs of + * alternating 32 and 16 bit le values. + */ + key_ptr = key->key; + for (i = 0; keylen >= 6; keylen -= 6) { + memcpy(&key_v[i], key_ptr, 6); + i += 2; + key_ptr += 6; + } + if (keylen) + memcpy(&key_v[i], key_ptr, keylen); + + /* intentionally corrupt key until mic is installed */ + if (is_tkip) { + key0 = key_v[0] = ~key_v[0]; + key1 = key_v[1] = ~key_v[1]; + } + + for (i = 0; i < ARRAY_SIZE(key_v); i++) + ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), + AR5K_KEYTABLE_OFF(entry, i)); + + ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); + + if (is_tkip) { + /* Install rx/tx MIC */ + rxmic = (__le32 *) &key->key[16]; + txmic = (__le32 *) &key->key[24]; + + if (ah->ah_combined_mic) { + key_v[0] = rxmic[0]; + key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); + key_v[2] = rxmic[1]; + key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); + key_v[4] = txmic[1]; + } else { + key_v[0] = rxmic[0]; + key_v[1] = 0; + key_v[2] = rxmic[1]; + key_v[3] = 0; + key_v[4] = 0; + } + for (i = 0; i < ARRAY_SIZE(key_v); i++) + ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), + AR5K_KEYTABLE_OFF(micentry, i)); + + ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, + AR5K_KEYTABLE_TYPE(micentry)); + ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); + ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); + + /* restore first 2 words of key */ + ath5k_hw_reg_write(ah, le32_to_cpu(~key0), + AR5K_KEYTABLE_OFF(entry, 0)); + ath5k_hw_reg_write(ah, le32_to_cpu(~key1), + AR5K_KEYTABLE_OFF(entry, 1)); + } + + return ath5k_hw_set_key_lladdr(ah, entry, mac); +} + +int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) +{ + u32 low_id, high_id; + + ATH5K_TRACE(ah->ah_sc); + /* Invalid entry (key table overflow) */ + AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); + + /* MAC may be NULL if it's a broadcast key. In this case no need to + * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ + if (!mac) { + low_id = 0xffffffff; + high_id = 0xffff | AR5K_KEYTABLE_VALID; + } else { + low_id = AR5K_LOW_ID(mac); + high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; + } + + ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); + ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); + + return 0; +} + diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c new file mode 100644 index 000000000000..9e2faae5ae94 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -0,0 +1,2599 @@ +/* + * PHY functions + * + * Copyright (c) 2004-2007 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * Copyright (c) 2007-2008 Jiri Slaby + * Copyright (c) 2008-2009 Felix Fietkau + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#define _ATH5K_PHY + +#include + +#include "ath5k.h" +#include "reg.h" +#include "base.h" +#include "rfbuffer.h" +#include "rfgain.h" + +/* + * Used to modify RF Banks before writing them to AR5K_RF_BUFFER + */ +static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, + const struct ath5k_rf_reg *rf_regs, + u32 val, u8 reg_id, bool set) +{ + const struct ath5k_rf_reg *rfreg = NULL; + u8 offset, bank, num_bits, col, position; + u16 entry; + u32 mask, data, last_bit, bits_shifted, first_bit; + u32 *rfb; + s32 bits_left; + int i; + + data = 0; + rfb = ah->ah_rf_banks; + + for (i = 0; i < ah->ah_rf_regs_count; i++) { + if (rf_regs[i].index == reg_id) { + rfreg = &rf_regs[i]; + break; + } + } + + if (rfb == NULL || rfreg == NULL) { + ATH5K_PRINTF("Rf register not found!\n"); + /* should not happen */ + return 0; + } + + bank = rfreg->bank; + num_bits = rfreg->field.len; + first_bit = rfreg->field.pos; + col = rfreg->field.col; + + /* first_bit is an offset from bank's + * start. Since we have all banks on + * the same array, we use this offset + * to mark each bank's start */ + offset = ah->ah_offset[bank]; + + /* Boundary check */ + if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) { + ATH5K_PRINTF("invalid values at offset %u\n", offset); + return 0; + } + + entry = ((first_bit - 1) / 8) + offset; + position = (first_bit - 1) % 8; + + if (set) + data = ath5k_hw_bitswap(val, num_bits); + + for (bits_shifted = 0, bits_left = num_bits; bits_left > 0; + position = 0, entry++) { + + last_bit = (position + bits_left > 8) ? 8 : + position + bits_left; + + mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) << + (col * 8); + + if (set) { + rfb[entry] &= ~mask; + rfb[entry] |= ((data << position) << (col * 8)) & mask; + data >>= (8 - position); + } else { + data |= (((rfb[entry] & mask) >> (col * 8)) >> position) + << bits_shifted; + bits_shifted += last_bit - position; + } + + bits_left -= 8 - position; + } + + data = set ? 1 : ath5k_hw_bitswap(data, num_bits); + + return data; +} + +/**********************\ +* RF Gain optimization * +\**********************/ + +/* + * This code is used to optimize rf gain on different environments + * (temprature mostly) based on feedback from a power detector. + * + * It's only used on RF5111 and RF5112, later RF chips seem to have + * auto adjustment on hw -notice they have a much smaller BANK 7 and + * no gain optimization ladder-. + * + * For more infos check out this patent doc + * http://www.freepatentsonline.com/7400691.html + * + * This paper describes power drops as seen on the receiver due to + * probe packets + * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues + * %20of%20Power%20Control.pdf + * + * And this is the MadWiFi bug entry related to the above + * http://madwifi-project.org/ticket/1659 + * with various measurements and diagrams + * + * TODO: Deal with power drops due to probes by setting an apropriate + * tx power on the probe packets ! Make this part of the calibration process. + */ + +/* Initialize ah_gain durring attach */ +int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) +{ + /* Initialize the gain optimization values */ + switch (ah->ah_radio) { + case AR5K_RF5111: + ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default; + ah->ah_gain.g_low = 20; + ah->ah_gain.g_high = 35; + ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; + break; + case AR5K_RF5112: + ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; + ah->ah_gain.g_low = 20; + ah->ah_gain.g_high = 85; + ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; + break; + default: + return -EINVAL; + } + + return 0; +} + +/* Schedule a gain probe check on the next transmited packet. + * That means our next packet is going to be sent with lower + * tx power and a Peak to Average Power Detector (PAPD) will try + * to measure the gain. + * + * TODO: Use propper tx power setting for the probe packet so + * that we don't observe a serious power drop on the receiver + * + * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) + * just after we enable the probe so that we don't mess with + * standard traffic ? Maybe it's time to use sw interrupts and + * a probe tasklet !!! + */ +static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) +{ + + /* Skip if gain calibration is inactive or + * we already handle a probe request */ + if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE) + return; + + /* Send the packet with 2dB below max power as + * patent doc suggest */ + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, + AR5K_PHY_PAPD_PROBE_TXPOWER) | + AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); + + ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED; + +} + +/* Calculate gain_F measurement correction + * based on the current step for RF5112 rev. 2 */ +static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) +{ + u32 mix, step; + u32 *rf; + const struct ath5k_gain_opt *go; + const struct ath5k_gain_opt_step *g_step; + const struct ath5k_rf_reg *rf_regs; + + /* Only RF5112 Rev. 2 supports it */ + if ((ah->ah_radio != AR5K_RF5112) || + (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A)) + return 0; + + go = &rfgain_opt_5112; + rf_regs = rf_regs_5112a; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); + + g_step = &go->go_step[ah->ah_gain.g_step_idx]; + + if (ah->ah_rf_banks == NULL) + return 0; + + rf = ah->ah_rf_banks; + ah->ah_gain.g_f_corr = 0; + + /* No VGA (Variable Gain Amplifier) override, skip */ + if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1) + return 0; + + /* Mix gain stepping */ + step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false); + + /* Mix gain override */ + mix = g_step->gos_param[0]; + + switch (mix) { + case 3: + ah->ah_gain.g_f_corr = step * 2; + break; + case 2: + ah->ah_gain.g_f_corr = (step - 5) * 2; + break; + case 1: + ah->ah_gain.g_f_corr = step; + break; + default: + ah->ah_gain.g_f_corr = 0; + break; + } + + return ah->ah_gain.g_f_corr; +} + +/* Check if current gain_F measurement is in the range of our + * power detector windows. If we get a measurement outside range + * we know it's not accurate (detectors can't measure anything outside + * their detection window) so we must ignore it */ +static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) +{ + const struct ath5k_rf_reg *rf_regs; + u32 step, mix_ovr, level[4]; + u32 *rf; + + if (ah->ah_rf_banks == NULL) + return false; + + rf = ah->ah_rf_banks; + + if (ah->ah_radio == AR5K_RF5111) { + + rf_regs = rf_regs_5111; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); + + step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP, + false); + + level[0] = 0; + level[1] = (step == 63) ? 50 : step + 4; + level[2] = (step != 63) ? 64 : level[0]; + level[3] = level[2] + 50 ; + + ah->ah_gain.g_high = level[3] - + (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5); + ah->ah_gain.g_low = level[0] + + (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0); + } else { + + rf_regs = rf_regs_5112; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); + + mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, + false); + + level[0] = level[2] = 0; + + if (mix_ovr == 1) { + level[1] = level[3] = 83; + } else { + level[1] = level[3] = 107; + ah->ah_gain.g_high = 55; + } + } + + return (ah->ah_gain.g_current >= level[0] && + ah->ah_gain.g_current <= level[1]) || + (ah->ah_gain.g_current >= level[2] && + ah->ah_gain.g_current <= level[3]); +} + +/* Perform gain_F adjustment by choosing the right set + * of parameters from rf gain optimization ladder */ +static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) +{ + const struct ath5k_gain_opt *go; + const struct ath5k_gain_opt_step *g_step; + int ret = 0; + + switch (ah->ah_radio) { + case AR5K_RF5111: + go = &rfgain_opt_5111; + break; + case AR5K_RF5112: + go = &rfgain_opt_5112; + break; + default: + return 0; + } + + g_step = &go->go_step[ah->ah_gain.g_step_idx]; + + if (ah->ah_gain.g_current >= ah->ah_gain.g_high) { + + /* Reached maximum */ + if (ah->ah_gain.g_step_idx == 0) + return -1; + + for (ah->ah_gain.g_target = ah->ah_gain.g_current; + ah->ah_gain.g_target >= ah->ah_gain.g_high && + ah->ah_gain.g_step_idx > 0; + g_step = &go->go_step[ah->ah_gain.g_step_idx]) + ah->ah_gain.g_target -= 2 * + (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain - + g_step->gos_gain); + + ret = 1; + goto done; + } + + if (ah->ah_gain.g_current <= ah->ah_gain.g_low) { + + /* Reached minimum */ + if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1)) + return -2; + + for (ah->ah_gain.g_target = ah->ah_gain.g_current; + ah->ah_gain.g_target <= ah->ah_gain.g_low && + ah->ah_gain.g_step_idx < go->go_steps_count-1; + g_step = &go->go_step[ah->ah_gain.g_step_idx]) + ah->ah_gain.g_target -= 2 * + (go->go_step[++ah->ah_gain.g_step_idx].gos_gain - + g_step->gos_gain); + + ret = 2; + goto done; + } + +done: + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "ret %d, gain step %u, current gain %u, target gain %u\n", + ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current, + ah->ah_gain.g_target); + + return ret; +} + +/* Main callback for thermal rf gain calibration engine + * Check for a new gain reading and schedule an adjustment + * if needed. + * + * TODO: Use sw interrupt to schedule reset if gain_F needs + * adjustment */ +enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) +{ + u32 data, type; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + + ATH5K_TRACE(ah->ah_sc); + + if (ah->ah_rf_banks == NULL || + ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) + return AR5K_RFGAIN_INACTIVE; + + /* No check requested, either engine is inactive + * or an adjustment is already requested */ + if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED) + goto done; + + /* Read the PAPD (Peak to Average Power Detector) + * register */ + data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE); + + /* No probe is scheduled, read gain_F measurement */ + if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) { + ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S; + type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE); + + /* If tx packet is CCK correct the gain_F measurement + * by cck ofdm gain delta */ + if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) { + if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) + ah->ah_gain.g_current += + ee->ee_cck_ofdm_gain_delta; + else + ah->ah_gain.g_current += + AR5K_GAIN_CCK_PROBE_CORR; + } + + /* Further correct gain_F measurement for + * RF5112A radios */ + if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { + ath5k_hw_rf_gainf_corr(ah); + ah->ah_gain.g_current = + ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ? + (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) : + 0; + } + + /* Check if measurement is ok and if we need + * to adjust gain, schedule a gain adjustment, + * else switch back to the acive state */ + if (ath5k_hw_rf_check_gainf_readback(ah) && + AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) && + ath5k_hw_rf_gainf_adjust(ah)) { + ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE; + } else { + ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; + } + } + +done: + return ah->ah_gain.g_state; +} + +/* Write initial rf gain table to set the RF sensitivity + * this one works on all RF chips and has nothing to do + * with gain_F calibration */ +int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) +{ + const struct ath5k_ini_rfgain *ath5k_rfg; + unsigned int i, size; + + switch (ah->ah_radio) { + case AR5K_RF5111: + ath5k_rfg = rfgain_5111; + size = ARRAY_SIZE(rfgain_5111); + break; + case AR5K_RF5112: + ath5k_rfg = rfgain_5112; + size = ARRAY_SIZE(rfgain_5112); + break; + case AR5K_RF2413: + ath5k_rfg = rfgain_2413; + size = ARRAY_SIZE(rfgain_2413); + break; + case AR5K_RF2316: + ath5k_rfg = rfgain_2316; + size = ARRAY_SIZE(rfgain_2316); + break; + case AR5K_RF5413: + ath5k_rfg = rfgain_5413; + size = ARRAY_SIZE(rfgain_5413); + break; + case AR5K_RF2317: + case AR5K_RF2425: + ath5k_rfg = rfgain_2425; + size = ARRAY_SIZE(rfgain_2425); + break; + default: + return -EINVAL; + } + + switch (freq) { + case AR5K_INI_RFGAIN_2GHZ: + case AR5K_INI_RFGAIN_5GHZ: + break; + default: + return -EINVAL; + } + + for (i = 0; i < size; i++) { + AR5K_REG_WAIT(i); + ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], + (u32)ath5k_rfg[i].rfg_register); + } + + return 0; +} + + + +/********************\ +* RF Registers setup * +\********************/ + + +/* + * Setup RF registers by writing rf buffer on hw + */ +int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, + unsigned int mode) +{ + const struct ath5k_rf_reg *rf_regs; + const struct ath5k_ini_rfbuffer *ini_rfb; + const struct ath5k_gain_opt *go = NULL; + const struct ath5k_gain_opt_step *g_step; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u8 ee_mode = 0; + u32 *rfb; + int i, obdb = -1, bank = -1; + + switch (ah->ah_radio) { + case AR5K_RF5111: + rf_regs = rf_regs_5111; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); + ini_rfb = rfb_5111; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111); + go = &rfgain_opt_5111; + break; + case AR5K_RF5112: + if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { + rf_regs = rf_regs_5112a; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); + ini_rfb = rfb_5112a; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a); + } else { + rf_regs = rf_regs_5112; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); + ini_rfb = rfb_5112; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112); + } + go = &rfgain_opt_5112; + break; + case AR5K_RF2413: + rf_regs = rf_regs_2413; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413); + ini_rfb = rfb_2413; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413); + break; + case AR5K_RF2316: + rf_regs = rf_regs_2316; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316); + ini_rfb = rfb_2316; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316); + break; + case AR5K_RF5413: + rf_regs = rf_regs_5413; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413); + ini_rfb = rfb_5413; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413); + break; + case AR5K_RF2317: + rf_regs = rf_regs_2425; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); + ini_rfb = rfb_2317; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317); + break; + case AR5K_RF2425: + rf_regs = rf_regs_2425; + ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); + if (ah->ah_mac_srev < AR5K_SREV_AR2417) { + ini_rfb = rfb_2425; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425); + } else { + ini_rfb = rfb_2417; + ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417); + } + break; + default: + return -EINVAL; + } + + /* If it's the first time we set rf buffer, allocate + * ah->ah_rf_banks based on ah->ah_rf_banks_size + * we set above */ + if (ah->ah_rf_banks == NULL) { + ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size, + GFP_KERNEL); + if (ah->ah_rf_banks == NULL) { + ATH5K_ERR(ah->ah_sc, "out of memory\n"); + return -ENOMEM; + } + } + + /* Copy values to modify them */ + rfb = ah->ah_rf_banks; + + for (i = 0; i < ah->ah_rf_banks_size; i++) { + if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) { + ATH5K_ERR(ah->ah_sc, "invalid bank\n"); + return -EINVAL; + } + + /* Bank changed, write down the offset */ + if (bank != ini_rfb[i].rfb_bank) { + bank = ini_rfb[i].rfb_bank; + ah->ah_offset[bank] = i; + } + + rfb[i] = ini_rfb[i].rfb_mode_data[mode]; + } + + /* Set Output and Driver bias current (OB/DB) */ + if (channel->hw_value & CHANNEL_2GHZ) { + + if (channel->hw_value & CHANNEL_CCK) + ee_mode = AR5K_EEPROM_MODE_11B; + else + ee_mode = AR5K_EEPROM_MODE_11G; + + /* For RF511X/RF211X combination we + * use b_OB and b_DB parameters stored + * in eeprom on ee->ee_ob[ee_mode][0] + * + * For all other chips we use OB/DB for 2Ghz + * stored in the b/g modal section just like + * 802.11a on ee->ee_ob[ee_mode][1] */ + if ((ah->ah_radio == AR5K_RF5111) || + (ah->ah_radio == AR5K_RF5112)) + obdb = 0; + else + obdb = 1; + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], + AR5K_RF_OB_2GHZ, true); + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], + AR5K_RF_DB_2GHZ, true); + + /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */ + } else if ((channel->hw_value & CHANNEL_5GHZ) || + (ah->ah_radio == AR5K_RF5111)) { + + /* For 11a, Turbo and XR we need to choose + * OB/DB based on frequency range */ + ee_mode = AR5K_EEPROM_MODE_11A; + obdb = channel->center_freq >= 5725 ? 3 : + (channel->center_freq >= 5500 ? 2 : + (channel->center_freq >= 5260 ? 1 : + (channel->center_freq > 4000 ? 0 : -1))); + + if (obdb < 0) + return -EINVAL; + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], + AR5K_RF_OB_5GHZ, true); + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], + AR5K_RF_DB_5GHZ, true); + } + + g_step = &go->go_step[ah->ah_gain.g_step_idx]; + + /* Bank Modifications (chip-specific) */ + if (ah->ah_radio == AR5K_RF5111) { + + /* Set gain_F settings according to current step */ + if (channel->hw_value & CHANNEL_OFDM) { + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, + AR5K_PHY_FRAME_CTL_TX_CLIP, + g_step->gos_param[0]); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], + AR5K_RF_PWD_90, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], + AR5K_RF_PWD_84, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], + AR5K_RF_RFGAIN_SEL, true); + + /* We programmed gain_F parameters, switch back + * to active state */ + ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; + + } + + /* Bank 6/7 setup */ + + ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode], + AR5K_RF_PWD_XPD, true); + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode], + AR5K_RF_XPD_GAIN, true); + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], + AR5K_RF_GAIN_I, true); + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], + AR5K_RF_PLO_SEL, true); + + /* TODO: Half/quarter channel support */ + } + + if (ah->ah_radio == AR5K_RF5112) { + + /* Set gain_F settings according to current step */ + if (channel->hw_value & CHANNEL_OFDM) { + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0], + AR5K_RF_MIXGAIN_OVR, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], + AR5K_RF_PWD_138, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], + AR5K_RF_PWD_137, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], + AR5K_RF_PWD_136, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4], + AR5K_RF_PWD_132, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5], + AR5K_RF_PWD_131, true); + + ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6], + AR5K_RF_PWD_130, true); + + /* We programmed gain_F parameters, switch back + * to active state */ + ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; + } + + /* Bank 6/7 setup */ + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], + AR5K_RF_XPD_SEL, true); + + if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { + /* Rev. 1 supports only one xpd */ + ath5k_hw_rfb_op(ah, rf_regs, + ee->ee_x_gain[ee_mode], + AR5K_RF_XPD_GAIN, true); + + } else { + /* TODO: Set high and low gain bits */ + ath5k_hw_rfb_op(ah, rf_regs, + ee->ee_x_gain[ee_mode], + AR5K_RF_PD_GAIN_LO, true); + ath5k_hw_rfb_op(ah, rf_regs, + ee->ee_x_gain[ee_mode], + AR5K_RF_PD_GAIN_HI, true); + + /* Lower synth voltage on Rev 2 */ + ath5k_hw_rfb_op(ah, rf_regs, 2, + AR5K_RF_HIGH_VC_CP, true); + + ath5k_hw_rfb_op(ah, rf_regs, 2, + AR5K_RF_MID_VC_CP, true); + + ath5k_hw_rfb_op(ah, rf_regs, 2, + AR5K_RF_LOW_VC_CP, true); + + ath5k_hw_rfb_op(ah, rf_regs, 2, + AR5K_RF_PUSH_UP, true); + + /* Decrease power consumption on 5213+ BaseBand */ + if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { + ath5k_hw_rfb_op(ah, rf_regs, 1, + AR5K_RF_PAD2GND, true); + + ath5k_hw_rfb_op(ah, rf_regs, 1, + AR5K_RF_XB2_LVL, true); + + ath5k_hw_rfb_op(ah, rf_regs, 1, + AR5K_RF_XB5_LVL, true); + + ath5k_hw_rfb_op(ah, rf_regs, 1, + AR5K_RF_PWD_167, true); + + ath5k_hw_rfb_op(ah, rf_regs, 1, + AR5K_RF_PWD_166, true); + } + } + + ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], + AR5K_RF_GAIN_I, true); + + /* TODO: Half/quarter channel support */ + + } + + if (ah->ah_radio == AR5K_RF5413 && + channel->hw_value & CHANNEL_2GHZ) { + + ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE, + true); + + /* Set optimum value for early revisions (on pci-e chips) */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5424 && + ah->ah_mac_srev < AR5K_SREV_AR5413) + ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3), + AR5K_RF_PWD_ICLOBUF_2G, true); + + } + + /* Write RF banks on hw */ + for (i = 0; i < ah->ah_rf_banks_size; i++) { + AR5K_REG_WAIT(i); + ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register); + } + + return 0; +} + + +/**************************\ + PHY/RF channel functions +\**************************/ + +/* + * Check if a channel is supported + */ +bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) +{ + /* Check if the channel is in our supported range */ + if (flags & CHANNEL_2GHZ) { + if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && + (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) + return true; + } else if (flags & CHANNEL_5GHZ) + if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && + (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) + return true; + + return false; +} + +/* + * Convertion needed for RF5110 + */ +static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) +{ + u32 athchan; + + /* + * Convert IEEE channel/MHz to an internal channel value used + * by the AR5210 chipset. This has not been verified with + * newer chipsets like the AR5212A who have a completely + * different RF/PHY part. + */ + athchan = (ath5k_hw_bitswap( + (ieee80211_frequency_to_channel( + channel->center_freq) - 24) / 2, 5) + << 1) | (1 << 6) | 0x1; + return athchan; +} + +/* + * Set channel on RF5110 + */ +static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 data; + + /* + * Set the channel and wait + */ + data = ath5k_hw_rf5110_chan2athchan(channel); + ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); + ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); + mdelay(1); + + return 0; +} + +/* + * Convertion needed for 5111 + */ +static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, + struct ath5k_athchan_2ghz *athchan) +{ + int channel; + + /* Cast this value to catch negative channel numbers (>= -19) */ + channel = (int)ieee; + + /* + * Map 2GHz IEEE channel to 5GHz Atheros channel + */ + if (channel <= 13) { + athchan->a2_athchan = 115 + channel; + athchan->a2_flags = 0x46; + } else if (channel == 14) { + athchan->a2_athchan = 124; + athchan->a2_flags = 0x44; + } else if (channel >= 15 && channel <= 26) { + athchan->a2_athchan = ((channel - 14) * 4) + 132; + athchan->a2_flags = 0x46; + } else + return -EINVAL; + + return 0; +} + +/* + * Set channel on 5111 + */ +static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + struct ath5k_athchan_2ghz ath5k_channel_2ghz; + unsigned int ath5k_channel = + ieee80211_frequency_to_channel(channel->center_freq); + u32 data0, data1, clock; + int ret; + + /* + * Set the channel on the RF5111 radio + */ + data0 = data1 = 0; + + if (channel->hw_value & CHANNEL_2GHZ) { + /* Map 2GHz channel to 5GHz Atheros channel ID */ + ret = ath5k_hw_rf5111_chan2athchan( + ieee80211_frequency_to_channel(channel->center_freq), + &ath5k_channel_2ghz); + if (ret) + return ret; + + ath5k_channel = ath5k_channel_2ghz.a2_athchan; + data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff) + << 5) | (1 << 4); + } + + if (ath5k_channel < 145 || !(ath5k_channel & 1)) { + clock = 1; + data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) | + (clock << 1) | (1 << 10) | 1; + } else { + clock = 0; + data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff) + << 2) | (clock << 1) | (1 << 10) | 1; + } + + ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8), + AR5K_RF_BUFFER); + ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00), + AR5K_RF_BUFFER_CONTROL_3); + + return 0; +} + +/* + * Set channel on 5112 and newer + */ +static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 data, data0, data1, data2; + u16 c; + + data = data0 = data1 = data2 = 0; + c = channel->center_freq; + + if (c < 4800) { + if (!((c - 2224) % 5)) { + data0 = ((2 * (c - 704)) - 3040) / 10; + data1 = 1; + } else if (!((c - 2192) % 5)) { + data0 = ((2 * (c - 672)) - 3040) / 10; + data1 = 0; + } else + return -EINVAL; + + data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); + } else if ((c - (c % 5)) != 2 || c > 5435) { + if (!(c % 20) && c >= 5120) { + data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); + data2 = ath5k_hw_bitswap(3, 2); + } else if (!(c % 10)) { + data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); + data2 = ath5k_hw_bitswap(2, 2); + } else if (!(c % 5)) { + data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); + data2 = ath5k_hw_bitswap(1, 2); + } else + return -EINVAL; + } else { + data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data2 = ath5k_hw_bitswap(0, 2); + } + + data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; + + ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); + ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); + + return 0; +} + +/* + * Set the channel on the RF2425 + */ +static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 data, data0, data2; + u16 c; + + data = data0 = data2 = 0; + c = channel->center_freq; + + if (c < 4800) { + data0 = ath5k_hw_bitswap((c - 2272), 8); + data2 = 0; + /* ? 5GHz ? */ + } else if ((c - (c % 5)) != 2 || c > 5435) { + if (!(c % 20) && c < 5120) + data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); + else if (!(c % 10)) + data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); + else if (!(c % 5)) + data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); + else + return -EINVAL; + data2 = ath5k_hw_bitswap(1, 2); + } else { + data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data2 = ath5k_hw_bitswap(0, 2); + } + + data = (data0 << 4) | data2 << 2 | 0x1001; + + ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); + ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); + + return 0; +} + +/* + * Set a channel on the radio chip + */ +int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) +{ + int ret; + /* + * Check bounds supported by the PHY (we don't care about regultory + * restrictions at this point). Note: hw_value already has the band + * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok() + * of the band by that */ + if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) { + ATH5K_ERR(ah->ah_sc, + "channel frequency (%u MHz) out of supported " + "band range\n", + channel->center_freq); + return -EINVAL; + } + + /* + * Set the channel and wait + */ + switch (ah->ah_radio) { + case AR5K_RF5110: + ret = ath5k_hw_rf5110_channel(ah, channel); + break; + case AR5K_RF5111: + ret = ath5k_hw_rf5111_channel(ah, channel); + break; + case AR5K_RF2425: + ret = ath5k_hw_rf2425_channel(ah, channel); + break; + default: + ret = ath5k_hw_rf5112_channel(ah, channel); + break; + } + + if (ret) + return ret; + + /* Set JAPAN setting for channel 14 */ + if (channel->center_freq == 2484) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, + AR5K_PHY_CCKTXCTL_JAPAN); + } else { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, + AR5K_PHY_CCKTXCTL_WORLD); + } + + ah->ah_current_channel.center_freq = channel->center_freq; + ah->ah_current_channel.hw_value = channel->hw_value; + ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; + + return 0; +} + +/*****************\ + PHY calibration +\*****************/ + +/** + * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration + * + * @ah: struct ath5k_hw pointer we are operating on + * @freq: the channel frequency, just used for error logging + * + * This function performs a noise floor calibration of the PHY and waits for + * it to complete. Then the noise floor value is compared to some maximum + * noise floor we consider valid. + * + * Note that this is different from what the madwifi HAL does: it reads the + * noise floor and afterwards initiates the calibration. Since the noise floor + * calibration can take some time to finish, depending on the current channel + * use, that avoids the occasional timeout warnings we are seeing now. + * + * See the following link for an Atheros patent on noise floor calibration: + * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ + * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 + * + * XXX: Since during noise floor calibration antennas are detached according to + * the patent, we should stop tx queues here. + */ +int +ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) +{ + int ret; + unsigned int i; + s32 noise_floor; + + /* + * Enable noise floor calibration + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_NF); + + ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_NF, 0, false); + if (ret) { + ATH5K_ERR(ah->ah_sc, + "noise floor calibration timeout (%uMHz)\n", freq); + return -EAGAIN; + } + + /* Wait until the noise floor is calibrated and read the value */ + for (i = 20; i > 0; i--) { + mdelay(1); + noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); + noise_floor = AR5K_PHY_NF_RVAL(noise_floor); + if (noise_floor & AR5K_PHY_NF_ACTIVE) { + noise_floor = AR5K_PHY_NF_AVAL(noise_floor); + + if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) + break; + } + } + + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "noise floor %d\n", noise_floor); + + if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { + ATH5K_ERR(ah->ah_sc, + "noise floor calibration failed (%uMHz)\n", freq); + return -EAGAIN; + } + + ah->ah_noise_floor = noise_floor; + + return 0; +} + +/* + * Perform a PHY calibration on RF5110 + * -Fix BPSK/QAM Constellation (I/Q correction) + * -Calculate Noise Floor + */ +static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 phy_sig, phy_agc, phy_sat, beacon; + int ret; + + /* + * Disable beacons and RX/TX queues, wait + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, + AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); + beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); + ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); + + mdelay(2); + + /* + * Set the channel (with AGC turned off) + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); + udelay(10); + ret = ath5k_hw_channel(ah, channel); + + /* + * Activate PHY and wait + */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); + mdelay(1); + + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); + + if (ret) + return ret; + + /* + * Calibrate the radio chip + */ + + /* Remember normal state */ + phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG); + phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE); + phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT); + + /* Update radio registers */ + ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) | + AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG); + + ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI | + AR5K_PHY_AGCCOARSE_LO)) | + AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) | + AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE); + + ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT | + AR5K_PHY_ADCSAT_THR)) | + AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) | + AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT); + + udelay(20); + + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); + udelay(10); + ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); + + mdelay(1); + + /* + * Enable calibration and wait until completion + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL); + + ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL, 0, false); + + /* Reset to normal state */ + ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG); + ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE); + ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT); + + if (ret) { + ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", + channel->center_freq); + return ret; + } + + ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + + /* + * Re-enable RX/TX and beacons + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, + AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); + ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); + + return 0; +} + +/* + * Perform a PHY calibration on RF5111/5112 and newer chips + */ +static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 i_pwr, q_pwr; + s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; + int i; + ATH5K_TRACE(ah->ah_sc); + + if (!ah->ah_calibration || + ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) + goto done; + + /* Calibration has finished, get the results and re-run */ + for (i = 0; i <= 10; i++) { + iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); + i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); + q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); + } + + i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; + q_coffd = q_pwr >> 7; + + /* No correction */ + if (i_coffd == 0 || q_coffd == 0) + goto done; + + i_coff = ((-iq_corr) / i_coffd) & 0x3f; + + /* Boundary check */ + if (i_coff > 31) + i_coff = 31; + if (i_coff < -32) + i_coff = -32; + + q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; + + /* Boundary check */ + if (q_coff > 15) + q_coff = 15; + if (q_coff < -16) + q_coff = -16; + + /* Commit new I/Q value */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | + ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); + + /* Re-enable calibration -if we don't we'll commit + * the same values again and again */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); + +done: + + /* TODO: Separate noise floor calibration from I/Q calibration + * since noise floor calibration interrupts rx path while I/Q + * calibration doesn't. We don't need to run noise floor calibration + * as often as I/Q calibration.*/ + ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + + /* Initiate a gain_F calibration */ + ath5k_hw_request_rfgain_probe(ah); + + return 0; +} + +/* + * Perform a PHY calibration + */ +int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + int ret; + + if (ah->ah_radio == AR5K_RF5110) + ret = ath5k_hw_rf5110_calibrate(ah, channel); + else + ret = ath5k_hw_rf511x_calibrate(ah, channel); + + return ret; +} + +int ath5k_hw_phy_disable(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + /*Just a try M.F.*/ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); + + return 0; +} + +/********************\ + Misc PHY functions +\********************/ + +/* + * Get the PHY Chip revision + */ +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) +{ + unsigned int i; + u32 srev; + u16 ret; + + ATH5K_TRACE(ah->ah_sc); + + /* + * Set the radio chip access register + */ + switch (chan) { + case CHANNEL_2GHZ: + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); + break; + case CHANNEL_5GHZ: + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + break; + default: + return 0; + } + + mdelay(2); + + /* ...wait until PHY is ready and read the selected radio revision */ + ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); + + for (i = 0; i < 8; i++) + ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); + + if (ah->ah_version == AR5K_AR5210) { + srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; + ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; + } else { + srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; + ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | + ((srev & 0x0f) << 4), 8); + } + + /* Reset to the 5GHz mode */ + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + + return ret; +} + +void /*TODO:Boundary check*/ +ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) +{ + ATH5K_TRACE(ah->ah_sc); + /*Just a try M.F.*/ + if (ah->ah_version != AR5K_AR5210) + ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); +} + +unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + /*Just a try M.F.*/ + if (ah->ah_version != AR5K_AR5210) + return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); + + return false; /*XXX: What do we return for 5210 ?*/ +} + + +/****************\ +* TX power setup * +\****************/ + +/* + * Helper functions + */ + +/* + * Do linear interpolation between two given (x, y) points + */ +static s16 +ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, + s16 y_left, s16 y_right) +{ + s16 ratio, result; + + /* Avoid divide by zero and skip interpolation + * if we have the same point */ + if ((x_left == x_right) || (y_left == y_right)) + return y_left; + + /* + * Since we use ints and not fps, we need to scale up in + * order to get a sane ratio value (or else we 'll eg. get + * always 1 instead of 1.25, 1.75 etc). We scale up by 100 + * to have some accuracy both for 0.5 and 0.25 steps. + */ + ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left)); + + /* Now scale down to be in range */ + result = y_left + (ratio * (target - x_left) / 100); + + return result; +} + +/* + * Find vertical boundary (min pwr) for the linear PCDAC curve. + * + * Since we have the top of the curve and we draw the line below + * until we reach 1 (1 pcdac step) we need to know which point + * (x value) that is so that we don't go below y axis and have negative + * pcdac values when creating the curve, or fill the table with zeroes. + */ +static s16 +ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, + const s16 *pwrL, const s16 *pwrR) +{ + s8 tmp; + s16 min_pwrL, min_pwrR; + s16 pwr_i = pwrL[0]; + + do { + pwr_i--; + tmp = (s8) ath5k_get_interpolated_value(pwr_i, + pwrL[0], pwrL[1], + stepL[0], stepL[1]); + + } while (tmp > 1); + + min_pwrL = pwr_i; + + pwr_i = pwrR[0]; + do { + pwr_i--; + tmp = (s8) ath5k_get_interpolated_value(pwr_i, + pwrR[0], pwrR[1], + stepR[0], stepR[1]); + + } while (tmp > 1); + + min_pwrR = pwr_i; + + /* Keep the right boundary so that it works for both curves */ + return max(min_pwrL, min_pwrR); +} + +/* + * Interpolate (pwr,vpd) points to create a Power to PDADC or a + * Power to PCDAC curve. + * + * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC + * steps (offsets) on y axis. Power can go up to 31.5dB and max + * PCDAC/PDADC step for each curve is 64 but we can write more than + * one curves on hw so we can go up to 128 (which is the max step we + * can write on the final table). + * + * We write y values (PCDAC/PDADC steps) on hw. + */ +static void +ath5k_create_power_curve(s16 pmin, s16 pmax, + const s16 *pwr, const u8 *vpd, + u8 num_points, + u8 *vpd_table, u8 type) +{ + u8 idx[2] = { 0, 1 }; + s16 pwr_i = 2*pmin; + int i; + + if (num_points < 2) + return; + + /* We want the whole line, so adjust boundaries + * to cover the entire power range. Note that + * power values are already 0.25dB so no need + * to multiply pwr_i by 2 */ + if (type == AR5K_PWRTABLE_LINEAR_PCDAC) { + pwr_i = pmin; + pmin = 0; + pmax = 63; + } + + /* Find surrounding turning points (TPs) + * and interpolate between them */ + for (i = 0; (i <= (u16) (pmax - pmin)) && + (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { + + /* We passed the right TP, move to the next set of TPs + * if we pass the last TP, extrapolate above using the last + * two TPs for ratio */ + if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) { + idx[0]++; + idx[1]++; + } + + vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i, + pwr[idx[0]], pwr[idx[1]], + vpd[idx[0]], vpd[idx[1]]); + + /* Increase by 0.5dB + * (0.25 dB units) */ + pwr_i += 2; + } +} + +/* + * Get the surrounding per-channel power calibration piers + * for a given frequency so that we can interpolate between + * them and come up with an apropriate dataset for our current + * channel. + */ +static void +ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + struct ath5k_chan_pcal_info **pcinfo_l, + struct ath5k_chan_pcal_info **pcinfo_r) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_chan_pcal_info *pcinfo; + u8 idx_l, idx_r; + u8 mode, max, i; + u32 target = channel->center_freq; + + idx_l = 0; + idx_r = 0; + + if (!(channel->hw_value & CHANNEL_OFDM)) { + pcinfo = ee->ee_pwr_cal_b; + mode = AR5K_EEPROM_MODE_11B; + } else if (channel->hw_value & CHANNEL_2GHZ) { + pcinfo = ee->ee_pwr_cal_g; + mode = AR5K_EEPROM_MODE_11G; + } else { + pcinfo = ee->ee_pwr_cal_a; + mode = AR5K_EEPROM_MODE_11A; + } + max = ee->ee_n_piers[mode] - 1; + + /* Frequency is below our calibrated + * range. Use the lowest power curve + * we have */ + if (target < pcinfo[0].freq) { + idx_l = idx_r = 0; + goto done; + } + + /* Frequency is above our calibrated + * range. Use the highest power curve + * we have */ + if (target > pcinfo[max].freq) { + idx_l = idx_r = max; + goto done; + } + + /* Frequency is inside our calibrated + * channel range. Pick the surrounding + * calibration piers so that we can + * interpolate */ + for (i = 0; i <= max; i++) { + + /* Frequency matches one of our calibration + * piers, no need to interpolate, just use + * that calibration pier */ + if (pcinfo[i].freq == target) { + idx_l = idx_r = i; + goto done; + } + + /* We found a calibration pier that's above + * frequency, use this pier and the previous + * one to interpolate */ + if (target < pcinfo[i].freq) { + idx_r = i; + idx_l = idx_r - 1; + goto done; + } + } + +done: + *pcinfo_l = &pcinfo[idx_l]; + *pcinfo_r = &pcinfo[idx_r]; + + return; +} + +/* + * Get the surrounding per-rate power calibration data + * for a given frequency and interpolate between power + * values to set max target power supported by hw for + * each rate. + */ +static void +ath5k_get_rate_pcal_data(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + struct ath5k_rate_pcal_info *rates) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_rate_pcal_info *rpinfo; + u8 idx_l, idx_r; + u8 mode, max, i; + u32 target = channel->center_freq; + + idx_l = 0; + idx_r = 0; + + if (!(channel->hw_value & CHANNEL_OFDM)) { + rpinfo = ee->ee_rate_tpwr_b; + mode = AR5K_EEPROM_MODE_11B; + } else if (channel->hw_value & CHANNEL_2GHZ) { + rpinfo = ee->ee_rate_tpwr_g; + mode = AR5K_EEPROM_MODE_11G; + } else { + rpinfo = ee->ee_rate_tpwr_a; + mode = AR5K_EEPROM_MODE_11A; + } + max = ee->ee_rate_target_pwr_num[mode] - 1; + + /* Get the surrounding calibration + * piers - same as above */ + if (target < rpinfo[0].freq) { + idx_l = idx_r = 0; + goto done; + } + + if (target > rpinfo[max].freq) { + idx_l = idx_r = max; + goto done; + } + + for (i = 0; i <= max; i++) { + + if (rpinfo[i].freq == target) { + idx_l = idx_r = i; + goto done; + } + + if (target < rpinfo[i].freq) { + idx_r = i; + idx_l = idx_r - 1; + goto done; + } + } + +done: + /* Now interpolate power value, based on the frequency */ + rates->freq = target; + + rates->target_power_6to24 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_6to24, + rpinfo[idx_r].target_power_6to24); + + rates->target_power_36 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_36, + rpinfo[idx_r].target_power_36); + + rates->target_power_48 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_48, + rpinfo[idx_r].target_power_48); + + rates->target_power_54 = + ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, + rpinfo[idx_r].freq, + rpinfo[idx_l].target_power_54, + rpinfo[idx_r].target_power_54); +} + +/* + * Get the max edge power for this channel if + * we have such data from EEPROM's Conformance Test + * Limits (CTL), and limit max power if needed. + * + * FIXME: Only works for world regulatory domains + */ +static void +ath5k_get_max_ctl_power(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + struct ath5k_edge_power *rep = ee->ee_ctl_pwr; + u8 *ctl_val = ee->ee_ctl; + s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4; + s16 edge_pwr = 0; + u8 rep_idx; + u8 i, ctl_mode; + u8 ctl_idx = 0xFF; + u32 target = channel->center_freq; + + /* Find out a CTL for our mode that's not mapped + * on a specific reg domain. + * + * TODO: Map our current reg domain to one of the 3 available + * reg domain ids so that we can support more CTLs. */ + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_G: + ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_B: + ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_T: + ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_TG: + ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN; + break; + case CHANNEL_XR: + /* Fall through */ + default: + return; + } + + for (i = 0; i < ee->ee_ctls; i++) { + if (ctl_val[i] == ctl_mode) { + ctl_idx = i; + break; + } + } + + /* If we have a CTL dataset available grab it and find the + * edge power for our frequency */ + if (ctl_idx == 0xFF) + return; + + /* Edge powers are sorted by frequency from lower + * to higher. Each CTL corresponds to 8 edge power + * measurements. */ + rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES; + + /* Don't do boundaries check because we + * might have more that one bands defined + * for this mode */ + + /* Get the edge power that's closer to our + * frequency */ + for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) { + rep_idx += i; + if (target <= rep[rep_idx].freq) + edge_pwr = (s16) rep[rep_idx].edge; + } + + if (edge_pwr) + ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr); +} + + +/* + * Power to PCDAC table functions + */ + +/* + * Fill Power to PCDAC table on RF5111 + * + * No further processing is needed for RF5111, the only thing we have to + * do is fill the values below and above calibration range since eeprom data + * may not cover the entire PCDAC table. + */ +static void +ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min, + s16 *table_max) +{ + u8 *pcdac_out = ah->ah_txpower.txp_pd_table; + u8 *pcdac_tmp = ah->ah_txpower.tmpL[0]; + u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i; + s16 min_pwr, max_pwr; + + /* Get table boundaries */ + min_pwr = table_min[0]; + pcdac_0 = pcdac_tmp[0]; + + max_pwr = table_max[0]; + pcdac_n = pcdac_tmp[table_max[0] - table_min[0]]; + + /* Extrapolate below minimum using pcdac_0 */ + pcdac_i = 0; + for (i = 0; i < min_pwr; i++) + pcdac_out[pcdac_i++] = pcdac_0; + + /* Copy values from pcdac_tmp */ + pwr_idx = min_pwr; + for (i = 0 ; pwr_idx <= max_pwr && + pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) { + pcdac_out[pcdac_i++] = pcdac_tmp[i]; + pwr_idx++; + } + + /* Extrapolate above maximum */ + while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE) + pcdac_out[pcdac_i++] = pcdac_n; + +} + +/* + * Combine available XPD Curves and fill Linear Power to PCDAC table + * on RF5112 + * + * RFX112 can have up to 2 curves (one for low txpower range and one for + * higher txpower range). We need to put them both on pcdac_out and place + * them in the correct location. In case we only have one curve available + * just fit it on pcdac_out (it's supposed to cover the entire range of + * available pwr levels since it's always the higher power curve). Extrapolate + * below and above final table if needed. + */ +static void +ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, + s16 *table_max, u8 pdcurves) +{ + u8 *pcdac_out = ah->ah_txpower.txp_pd_table; + u8 *pcdac_low_pwr; + u8 *pcdac_high_pwr; + u8 *pcdac_tmp; + u8 pwr; + s16 max_pwr_idx; + s16 min_pwr_idx; + s16 mid_pwr_idx = 0; + /* Edge flag turs on the 7nth bit on the PCDAC + * to delcare the higher power curve (force values + * to be greater than 64). If we only have one curve + * we don't need to set this, if we have 2 curves and + * fill the table backwards this can also be used to + * switch from higher power curve to lower power curve */ + u8 edge_flag; + int i; + + /* When we have only one curve available + * that's the higher power curve. If we have + * two curves the first is the high power curve + * and the next is the low power curve. */ + if (pdcurves > 1) { + pcdac_low_pwr = ah->ah_txpower.tmpL[1]; + pcdac_high_pwr = ah->ah_txpower.tmpL[0]; + mid_pwr_idx = table_max[1] - table_min[1] - 1; + max_pwr_idx = (table_max[0] - table_min[0]) / 2; + + /* If table size goes beyond 31.5dB, keep the + * upper 31.5dB range when setting tx power. + * Note: 126 = 31.5 dB in quarter dB steps */ + if (table_max[0] - table_min[1] > 126) + min_pwr_idx = table_max[0] - 126; + else + min_pwr_idx = table_min[1]; + + /* Since we fill table backwards + * start from high power curve */ + pcdac_tmp = pcdac_high_pwr; + + edge_flag = 0x40; +#if 0 + /* If both min and max power limits are in lower + * power curve's range, only use the low power curve. + * TODO: min/max levels are related to target + * power values requested from driver/user + * XXX: Is this really needed ? */ + if (min_pwr < table_max[1] && + max_pwr < table_max[1]) { + edge_flag = 0; + pcdac_tmp = pcdac_low_pwr; + max_pwr_idx = (table_max[1] - table_min[1])/2; + } +#endif + } else { + pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ + pcdac_high_pwr = ah->ah_txpower.tmpL[0]; + min_pwr_idx = table_min[0]; + max_pwr_idx = (table_max[0] - table_min[0]) / 2; + pcdac_tmp = pcdac_high_pwr; + edge_flag = 0; + } + + /* This is used when setting tx power*/ + ah->ah_txpower.txp_min_idx = min_pwr_idx/2; + + /* Fill Power to PCDAC table backwards */ + pwr = max_pwr_idx; + for (i = 63; i >= 0; i--) { + /* Entering lower power range, reset + * edge flag and set pcdac_tmp to lower + * power curve.*/ + if (edge_flag == 0x40 && + (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) { + edge_flag = 0x00; + pcdac_tmp = pcdac_low_pwr; + pwr = mid_pwr_idx/2; + } + + /* Don't go below 1, extrapolate below if we have + * already swithced to the lower power curve -or + * we only have one curve and edge_flag is zero + * anyway */ + if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) { + while (i >= 0) { + pcdac_out[i] = pcdac_out[i + 1]; + i--; + } + break; + } + + pcdac_out[i] = pcdac_tmp[pwr] | edge_flag; + + /* Extrapolate above if pcdac is greater than + * 126 -this can happen because we OR pcdac_out + * value with edge_flag on high power curve */ + if (pcdac_out[i] > 126) + pcdac_out[i] = 126; + + /* Decrease by a 0.5dB step */ + pwr--; + } +} + +/* Write PCDAC values on hw */ +static void +ath5k_setup_pcdac_table(struct ath5k_hw *ah) +{ + u8 *pcdac_out = ah->ah_txpower.txp_pd_table; + int i; + + /* + * Write TX power values + */ + for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { + ath5k_hw_reg_write(ah, + (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) | + (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16), + AR5K_PHY_PCDAC_TXPOWER(i)); + } +} + + +/* + * Power to PDADC table functions + */ + +/* + * Set the gain boundaries and create final Power to PDADC table + * + * We can have up to 4 pd curves, we need to do a simmilar process + * as we do for RF5112. This time we don't have an edge_flag but we + * set the gain boundaries on a separate register. + */ +static void +ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, + s16 *pwr_min, s16 *pwr_max, u8 pdcurves) +{ + u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS]; + u8 *pdadc_out = ah->ah_txpower.txp_pd_table; + u8 *pdadc_tmp; + s16 pdadc_0; + u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size; + u8 pd_gain_overlap; + + /* Note: Register value is initialized on initvals + * there is no feedback from hw. + * XXX: What about pd_gain_overlap from EEPROM ? */ + pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) & + AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP; + + /* Create final PDADC table */ + for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) { + pdadc_tmp = ah->ah_txpower.tmpL[pdg]; + + if (pdg == pdcurves - 1) + /* 2 dB boundary stretch for last + * (higher power) curve */ + gain_boundaries[pdg] = pwr_max[pdg] + 4; + else + /* Set gain boundary in the middle + * between this curve and the next one */ + gain_boundaries[pdg] = + (pwr_max[pdg] + pwr_min[pdg + 1]) / 2; + + /* Sanity check in case our 2 db stretch got out of + * range. */ + if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER) + gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER; + + /* For the first curve (lower power) + * start from 0 dB */ + if (pdg == 0) + pdadc_0 = 0; + else + /* For the other curves use the gain overlap */ + pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) - + pd_gain_overlap; + + /* Force each power step to be at least 0.5 dB */ + if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1) + pwr_step = pdadc_tmp[1] - pdadc_tmp[0]; + else + pwr_step = 1; + + /* If pdadc_0 is negative, we need to extrapolate + * below this pdgain by a number of pwr_steps */ + while ((pdadc_0 < 0) && (pdadc_i < 128)) { + s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step; + pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp; + pdadc_0++; + } + + /* Set last pwr level, using gain boundaries */ + pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg]; + /* Limit it to be inside pwr range */ + table_size = pwr_max[pdg] - pwr_min[pdg]; + max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; + + /* Fill pdadc_out table */ + while (pdadc_0 < max_idx) + pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; + + /* Need to extrapolate above this pdgain? */ + if (pdadc_n <= max_idx) + continue; + + /* Force each power step to be at least 0.5 dB */ + if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1) + pwr_step = pdadc_tmp[table_size - 1] - + pdadc_tmp[table_size - 2]; + else + pwr_step = 1; + + /* Extrapolate above */ + while ((pdadc_0 < (s16) pdadc_n) && + (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) { + s16 tmp = pdadc_tmp[table_size - 1] + + (pdadc_0 - max_idx) * pwr_step; + pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp; + pdadc_0++; + } + } + + while (pdg < AR5K_EEPROM_N_PD_GAINS) { + gain_boundaries[pdg] = gain_boundaries[pdg - 1]; + pdg++; + } + + while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) { + pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1]; + pdadc_i++; + } + + /* Set gain boundaries */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(pd_gain_overlap, + AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) | + AR5K_REG_SM(gain_boundaries[0], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) | + AR5K_REG_SM(gain_boundaries[1], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) | + AR5K_REG_SM(gain_boundaries[2], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) | + AR5K_REG_SM(gain_boundaries[3], + AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4), + AR5K_PHY_TPC_RG5); + + /* Used for setting rate power table */ + ah->ah_txpower.txp_min_idx = pwr_min[0]; + +} + +/* Write PDADC values on hw */ +static void +ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, + u8 pdcurves, u8 *pdg_to_idx) +{ + u8 *pdadc_out = ah->ah_txpower.txp_pd_table; + u32 reg; + u8 i; + + /* Select the right pdgain curves */ + + /* Clear current settings */ + reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1); + reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 | + AR5K_PHY_TPC_RG1_PDGAIN_2 | + AR5K_PHY_TPC_RG1_PDGAIN_3 | + AR5K_PHY_TPC_RG1_NUM_PD_GAIN); + + /* + * Use pd_gains curve from eeprom + * + * This overrides the default setting from initvals + * in case some vendors (e.g. Zcomax) don't use the default + * curves. If we don't honor their settings we 'll get a + * 5dB (1 * gain overlap ?) drop. + */ + reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN); + + switch (pdcurves) { + case 3: + reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3); + /* Fall through */ + case 2: + reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2); + /* Fall through */ + case 1: + reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1); + break; + } + ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1); + + /* + * Write TX power values + */ + for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { + ath5k_hw_reg_write(ah, + ((pdadc_out[4*i + 0] & 0xff) << 0) | + ((pdadc_out[4*i + 1] & 0xff) << 8) | + ((pdadc_out[4*i + 2] & 0xff) << 16) | + ((pdadc_out[4*i + 3] & 0xff) << 24), + AR5K_PHY_PDADC_TXPOWER(i)); + } +} + + +/* + * Common code for PCDAC/PDADC tables + */ + +/* + * This is the main function that uses all of the above + * to set PCDAC/PDADC table on hw for the current channel. + * This table is used for tx power calibration on the basband, + * without it we get weird tx power levels and in some cases + * distorted spectral mask + */ +static int +ath5k_setup_channel_powertable(struct ath5k_hw *ah, + struct ieee80211_channel *channel, + u8 ee_mode, u8 type) +{ + struct ath5k_pdgain_info *pdg_L, *pdg_R; + struct ath5k_chan_pcal_info *pcinfo_L; + struct ath5k_chan_pcal_info *pcinfo_R; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode]; + s16 table_min[AR5K_EEPROM_N_PD_GAINS]; + s16 table_max[AR5K_EEPROM_N_PD_GAINS]; + u8 *tmpL; + u8 *tmpR; + u32 target = channel->center_freq; + int pdg, i; + + /* Get surounding freq piers for this channel */ + ath5k_get_chan_pcal_surrounding_piers(ah, channel, + &pcinfo_L, + &pcinfo_R); + + /* Loop over pd gain curves on + * surounding freq piers by index */ + for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { + + /* Fill curves in reverse order + * from lower power (max gain) + * to higher power. Use curve -> idx + * backmaping we did on eeprom init */ + u8 idx = pdg_curve_to_idx[pdg]; + + /* Grab the needed curves by index */ + pdg_L = &pcinfo_L->pd_curves[idx]; + pdg_R = &pcinfo_R->pd_curves[idx]; + + /* Initialize the temp tables */ + tmpL = ah->ah_txpower.tmpL[pdg]; + tmpR = ah->ah_txpower.tmpR[pdg]; + + /* Set curve's x boundaries and create + * curves so that they cover the same + * range (if we don't do that one table + * will have values on some range and the + * other one won't have any so interpolation + * will fail) */ + table_min[pdg] = min(pdg_L->pd_pwr[0], + pdg_R->pd_pwr[0]) / 2; + + table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1], + pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2; + + /* Now create the curves on surrounding channels + * and interpolate if needed to get the final + * curve for this gain on this channel */ + switch (type) { + case AR5K_PWRTABLE_LINEAR_PCDAC: + /* Override min/max so that we don't loose + * accuracy (don't divide by 2) */ + table_min[pdg] = min(pdg_L->pd_pwr[0], + pdg_R->pd_pwr[0]); + + table_max[pdg] = + max(pdg_L->pd_pwr[pdg_L->pd_points - 1], + pdg_R->pd_pwr[pdg_R->pd_points - 1]); + + /* Override minimum so that we don't get + * out of bounds while extrapolating + * below. Don't do this when we have 2 + * curves and we are on the high power curve + * because table_min is ok in this case */ + if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) { + + table_min[pdg] = + ath5k_get_linear_pcdac_min(pdg_L->pd_step, + pdg_R->pd_step, + pdg_L->pd_pwr, + pdg_R->pd_pwr); + + /* Don't go too low because we will + * miss the upper part of the curve. + * Note: 126 = 31.5dB (max power supported) + * in 0.25dB units */ + if (table_max[pdg] - table_min[pdg] > 126) + table_min[pdg] = table_max[pdg] - 126; + } + + /* Fall through */ + case AR5K_PWRTABLE_PWR_TO_PCDAC: + case AR5K_PWRTABLE_PWR_TO_PDADC: + + ath5k_create_power_curve(table_min[pdg], + table_max[pdg], + pdg_L->pd_pwr, + pdg_L->pd_step, + pdg_L->pd_points, tmpL, type); + + /* We are in a calibration + * pier, no need to interpolate + * between freq piers */ + if (pcinfo_L == pcinfo_R) + continue; + + ath5k_create_power_curve(table_min[pdg], + table_max[pdg], + pdg_R->pd_pwr, + pdg_R->pd_step, + pdg_R->pd_points, tmpR, type); + break; + default: + return -EINVAL; + } + + /* Interpolate between curves + * of surounding freq piers to + * get the final curve for this + * pd gain. Re-use tmpL for interpolation + * output */ + for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) && + (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { + tmpL[i] = (u8) ath5k_get_interpolated_value(target, + (s16) pcinfo_L->freq, + (s16) pcinfo_R->freq, + (s16) tmpL[i], + (s16) tmpR[i]); + } + } + + /* Now we have a set of curves for this + * channel on tmpL (x range is table_max - table_min + * and y values are tmpL[pdg][]) sorted in the same + * order as EEPROM (because we've used the backmaping). + * So for RF5112 it's from higher power to lower power + * and for RF2413 it's from lower power to higher power. + * For RF5111 we only have one curve. */ + + /* Fill min and max power levels for this + * channel by interpolating the values on + * surounding channels to complete the dataset */ + ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, + (s16) pcinfo_L->freq, + (s16) pcinfo_R->freq, + pcinfo_L->min_pwr, pcinfo_R->min_pwr); + + ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target, + (s16) pcinfo_L->freq, + (s16) pcinfo_R->freq, + pcinfo_L->max_pwr, pcinfo_R->max_pwr); + + /* We are ready to go, fill PCDAC/PDADC + * table and write settings on hardware */ + switch (type) { + case AR5K_PWRTABLE_LINEAR_PCDAC: + /* For RF5112 we can have one or two curves + * and each curve covers a certain power lvl + * range so we need to do some more processing */ + ath5k_combine_linear_pcdac_curves(ah, table_min, table_max, + ee->ee_pd_gains[ee_mode]); + + /* Set txp.offset so that we can + * match max power value with max + * table index */ + ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); + + /* Write settings on hw */ + ath5k_setup_pcdac_table(ah); + break; + case AR5K_PWRTABLE_PWR_TO_PCDAC: + /* We are done for RF5111 since it has only + * one curve, just fit the curve on the table */ + ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max); + + /* No rate powertable adjustment for RF5111 */ + ah->ah_txpower.txp_min_idx = 0; + ah->ah_txpower.txp_offset = 0; + + /* Write settings on hw */ + ath5k_setup_pcdac_table(ah); + break; + case AR5K_PWRTABLE_PWR_TO_PDADC: + /* Set PDADC boundaries and fill + * final PDADC table */ + ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, + ee->ee_pd_gains[ee_mode]); + + /* Write settings on hw */ + ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); + + /* Set txp.offset, note that table_min + * can be negative */ + ah->ah_txpower.txp_offset = table_min[0]; + break; + default: + return -EINVAL; + } + + return 0; +} + + +/* + * Per-rate tx power setting + * + * This is the code that sets the desired tx power (below + * maximum) on hw for each rate (we also have TPC that sets + * power per packet). We do that by providing an index on the + * PCDAC/PDADC table we set up. + */ + +/* + * Set rate power table + * + * For now we only limit txpower based on maximum tx power + * supported by hw (what's inside rate_info). We need to limit + * this even more, based on regulatory domain etc. + * + * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps) + * and is indexed as follows: + * rates[0] - rates[7] -> OFDM rates + * rates[8] - rates[14] -> CCK rates + * rates[15] -> XR rates (they all have the same power) + */ +static void +ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, + struct ath5k_rate_pcal_info *rate_info, + u8 ee_mode) +{ + unsigned int i; + u16 *rates; + + /* max_pwr is power level we got from driver/user in 0.5dB + * units, switch to 0.25dB units so we can compare */ + max_pwr *= 2; + max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2; + + /* apply rate limits */ + rates = ah->ah_txpower.txp_rates_power_table; + + /* OFDM rates 6 to 24Mb/s */ + for (i = 0; i < 5; i++) + rates[i] = min(max_pwr, rate_info->target_power_6to24); + + /* Rest OFDM rates */ + rates[5] = min(rates[0], rate_info->target_power_36); + rates[6] = min(rates[0], rate_info->target_power_48); + rates[7] = min(rates[0], rate_info->target_power_54); + + /* CCK rates */ + /* 1L */ + rates[8] = min(rates[0], rate_info->target_power_6to24); + /* 2L */ + rates[9] = min(rates[0], rate_info->target_power_36); + /* 2S */ + rates[10] = min(rates[0], rate_info->target_power_36); + /* 5L */ + rates[11] = min(rates[0], rate_info->target_power_48); + /* 5S */ + rates[12] = min(rates[0], rate_info->target_power_48); + /* 11L */ + rates[13] = min(rates[0], rate_info->target_power_54); + /* 11S */ + rates[14] = min(rates[0], rate_info->target_power_54); + + /* XR rates */ + rates[15] = min(rates[0], rate_info->target_power_6to24); + + /* CCK rates have different peak to average ratio + * so we have to tweak their power so that gainf + * correction works ok. For this we use OFDM to + * CCK delta from eeprom */ + if ((ee_mode == AR5K_EEPROM_MODE_11G) && + (ah->ah_phy_revision < AR5K_SREV_PHY_5212A)) + for (i = 8; i <= 15; i++) + rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; + + ah->ah_txpower.txp_min_pwr = rates[7]; + ah->ah_txpower.txp_max_pwr = rates[0]; + ah->ah_txpower.txp_ofdm = rates[7]; +} + + +/* + * Set transmition power + */ +int +ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, + u8 ee_mode, u8 txpower) +{ + struct ath5k_rate_pcal_info rate_info; + u8 type; + int ret; + + ATH5K_TRACE(ah->ah_sc); + if (txpower > AR5K_TUNE_MAX_TXPOWER) { + ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); + return -EINVAL; + } + if (txpower == 0) + txpower = AR5K_TUNE_DEFAULT_TXPOWER; + + /* Reset TX power values */ + memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); + ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; + ah->ah_txpower.txp_min_pwr = 0; + ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; + + /* Initialize TX power table */ + switch (ah->ah_radio) { + case AR5K_RF5111: + type = AR5K_PWRTABLE_PWR_TO_PCDAC; + break; + case AR5K_RF5112: + type = AR5K_PWRTABLE_LINEAR_PCDAC; + break; + case AR5K_RF2413: + case AR5K_RF5413: + case AR5K_RF2316: + case AR5K_RF2317: + case AR5K_RF2425: + type = AR5K_PWRTABLE_PWR_TO_PDADC; + break; + default: + return -EINVAL; + } + + /* FIXME: Only on channel/mode change */ + ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); + if (ret) + return ret; + + /* Limit max power if we have a CTL available */ + ath5k_get_max_ctl_power(ah, channel); + + /* FIXME: Tx power limit for this regdomain + * XXX: Mac80211/CRDA will do that anyway ? */ + + /* FIXME: Antenna reduction stuff */ + + /* FIXME: Limit power on turbo modes */ + + /* FIXME: TPC scale reduction */ + + /* Get surounding channels for per-rate power table + * calibration */ + ath5k_get_rate_pcal_data(ah, channel, &rate_info); + + /* Setup rate power table */ + ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode); + + /* Write rate power table on hw */ + ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) | + AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) | + AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1); + + ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) | + AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) | + AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2); + + ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) | + AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) | + AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3); + + ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) | + AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) | + AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4); + + /* FIXME: TPC support */ + if (ah->ah_txpower.txp_tpc) { + ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | + AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); + + ath5k_hw_reg_write(ah, + AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) | + AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) | + AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP), + AR5K_TPC); + } else { + ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX | + AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); + } + + return 0; +} + +int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) +{ + /*Just a try M.F.*/ + struct ieee80211_channel *channel = &ah->ah_current_channel; + + ATH5K_TRACE(ah->ah_sc); + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, + "changing txpower to %d\n", txpower); + + return ath5k_hw_txpower(ah, channel, mode, txpower); +} + +#undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c new file mode 100644 index 000000000000..5094c394a4b2 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/********************************************\ +Queue Control Unit, DFS Control Unit Functions +\********************************************/ + +#include "ath5k.h" +#include "reg.h" +#include "debug.h" +#include "base.h" + +/* + * Get properties for a transmit queue + */ +int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, + struct ath5k_txq_info *queue_info) +{ + ATH5K_TRACE(ah->ah_sc); + memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); + return 0; +} + +/* + * Set properties for a transmit queue + */ +int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, + const struct ath5k_txq_info *queue_info) +{ + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) + return -EIO; + + memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); + + /*XXX: Is this supported on 5210 ?*/ + if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && + ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || + (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || + queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) + ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; + + return 0; +} + +/* + * Initialize a transmit queue + */ +int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, + struct ath5k_txq_info *queue_info) +{ + unsigned int queue; + int ret; + + ATH5K_TRACE(ah->ah_sc); + + /* + * Get queue by type + */ + /*5210 only has 2 queues*/ + if (ah->ah_version == AR5K_AR5210) { + switch (queue_type) { + case AR5K_TX_QUEUE_DATA: + queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; + break; + case AR5K_TX_QUEUE_BEACON: + case AR5K_TX_QUEUE_CAB: + queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; + break; + default: + return -EINVAL; + } + } else { + switch (queue_type) { + case AR5K_TX_QUEUE_DATA: + for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; + ah->ah_txq[queue].tqi_type != + AR5K_TX_QUEUE_INACTIVE; queue++) { + + if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) + return -EINVAL; + } + break; + case AR5K_TX_QUEUE_UAPSD: + queue = AR5K_TX_QUEUE_ID_UAPSD; + break; + case AR5K_TX_QUEUE_BEACON: + queue = AR5K_TX_QUEUE_ID_BEACON; + break; + case AR5K_TX_QUEUE_CAB: + queue = AR5K_TX_QUEUE_ID_CAB; + break; + case AR5K_TX_QUEUE_XR_DATA: + if (ah->ah_version != AR5K_AR5212) + ATH5K_ERR(ah->ah_sc, + "XR data queues only supported in" + " 5212!\n"); + queue = AR5K_TX_QUEUE_ID_XR_DATA; + break; + default: + return -EINVAL; + } + } + + /* + * Setup internal queue structure + */ + memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); + ah->ah_txq[queue].tqi_type = queue_type; + + if (queue_info != NULL) { + queue_info->tqi_type = queue_type; + ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info); + if (ret) + return ret; + } + + /* + * We use ah_txq_status to hold a temp value for + * the Secondary interrupt mask registers on 5211+ + * check out ath5k_hw_reset_tx_queue + */ + AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); + + return queue; +} + +/* + * Get number of pending frames + * for a specific queue [5211+] + */ +u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) +{ + u32 pending; + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + /* Return if queue is declared inactive */ + if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) + return false; + + /* XXX: How about AR5K_CFG_TXCNT ? */ + if (ah->ah_version == AR5K_AR5210) + return false; + + pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); + + /* It's possible to have no frames pending even if TXE + * is set. To indicate that q has not stopped return + * true */ + if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) + return true; + + return pending; +} + +/* + * Set a transmit queue inactive + */ +void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) +{ + ATH5K_TRACE(ah->ah_sc); + if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) + return; + + /* This queue will be skipped in further operations */ + ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; + /*For SIMR setup*/ + AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); +} + +/* + * Set DFS properties for a transmit queue on DCU + */ +int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) +{ + u32 cw_min, cw_max, retry_lg, retry_sh; + struct ath5k_txq_info *tq = &ah->ah_txq[queue]; + + ATH5K_TRACE(ah->ah_sc); + AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); + + tq = &ah->ah_txq[queue]; + + if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) + return 0; + + if (ah->ah_version == AR5K_AR5210) { + /* Only handle data queues, others will be ignored */ + if (tq->tqi_type != AR5K_TX_QUEUE_DATA) + return 0; + + /* Set Slot time */ + ath5k_hw_reg_write(ah, ah->ah_turbo ? + AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, + AR5K_SLOT_TIME); + /* Set ACK_CTS timeout */ + ath5k_hw_reg_write(ah, ah->ah_turbo ? + AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : + AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); + /* Set Transmit Latency */ + ath5k_hw_reg_write(ah, ah->ah_turbo ? + AR5K_INIT_TRANSMIT_LATENCY_TURBO : + AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); + + /* Set IFS0 */ + if (ah->ah_turbo) { + ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + + (ah->ah_aifs + tq->tqi_aifs) * + AR5K_INIT_SLOT_TIME_TURBO) << + AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, + AR5K_IFS0); + } else { + ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + + (ah->ah_aifs + tq->tqi_aifs) * + AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | + AR5K_INIT_SIFS, AR5K_IFS0); + } + + /* Set IFS1 */ + ath5k_hw_reg_write(ah, ah->ah_turbo ? + AR5K_INIT_PROTO_TIME_CNTRL_TURBO : + AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); + /* Set AR5K_PHY_SETTLING */ + ath5k_hw_reg_write(ah, ah->ah_turbo ? + (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) + | 0x38 : + (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) + | 0x1C, + AR5K_PHY_SETTLING); + /* Set Frame Control Register */ + ath5k_hw_reg_write(ah, ah->ah_turbo ? + (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | + AR5K_PHY_TURBO_SHORT | 0x2020) : + (AR5K_PHY_FRAME_CTL_INI | 0x1020), + AR5K_PHY_FRAME_CTL_5210); + } + + /* + * Calculate cwmin/max by channel mode + */ + cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; + cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; + ah->ah_aifs = AR5K_TUNE_AIFS; + /*XR is only supported on 5212*/ + if (IS_CHAN_XR(ah->ah_current_channel) && + ah->ah_version == AR5K_AR5212) { + cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; + cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; + ah->ah_aifs = AR5K_TUNE_AIFS_XR; + /*B mode is not supported on 5210*/ + } else if (IS_CHAN_B(ah->ah_current_channel) && + ah->ah_version != AR5K_AR5210) { + cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; + cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; + ah->ah_aifs = AR5K_TUNE_AIFS_11B; + } + + cw_min = 1; + while (cw_min < ah->ah_cw_min) + cw_min = (cw_min << 1) | 1; + + cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : + ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); + cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : + ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); + + /* + * Calculate and set retry limits + */ + if (ah->ah_software_retry) { + /* XXX Need to test this */ + retry_lg = ah->ah_limit_tx_retries; + retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? + AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; + } else { + retry_lg = AR5K_INIT_LG_RETRY; + retry_sh = AR5K_INIT_SH_RETRY; + } + + /*No QCU/DCU [5210]*/ + if (ah->ah_version == AR5K_AR5210) { + ath5k_hw_reg_write(ah, + (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) + | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, + AR5K_NODCU_RETRY_LMT_SLG_RETRY) + | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, + AR5K_NODCU_RETRY_LMT_SSH_RETRY) + | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) + | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), + AR5K_NODCU_RETRY_LMT); + } else { + /*QCU/DCU [5211+]*/ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(AR5K_INIT_SLG_RETRY, + AR5K_DCU_RETRY_LMT_SLG_RETRY) | + AR5K_REG_SM(AR5K_INIT_SSH_RETRY, + AR5K_DCU_RETRY_LMT_SSH_RETRY) | + AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | + AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), + AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); + + /*===Rest is also for QCU/DCU only [5211+]===*/ + + /* + * Set initial content window (cw_min/cw_max) + * and arbitrated interframe space (aifs)... + */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | + AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | + AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, + AR5K_DCU_LCL_IFS_AIFS), + AR5K_QUEUE_DFS_LOCAL_IFS(queue)); + + /* + * Set misc registers + */ + /* Enable DCU early termination for this queue */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_DCU_EARLY); + + /* Enable DCU to wait for next fragment from QCU */ + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_DCU_MISC_FRAG_WAIT); + + /* On Maui and Spirit use the global seqnum on DCU */ + if (ah->ah_mac_version < AR5K_SREV_AR5211) + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + AR5K_DCU_MISC_SEQNUM_CTL); + + if (tq->tqi_cbr_period) { + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, + AR5K_QCU_CBRCFG_INTVAL) | + AR5K_REG_SM(tq->tqi_cbr_overflow_limit, + AR5K_QCU_CBRCFG_ORN_THRES), + AR5K_QUEUE_CBRCFG(queue)); + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_CBR); + if (tq->tqi_cbr_overflow_limit) + AR5K_REG_ENABLE_BITS(ah, + AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_CBR_THRES_ENABLE); + } + + if (tq->tqi_ready_time && + (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, + AR5K_QCU_RDYTIMECFG_INTVAL) | + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); + + if (tq->tqi_burst_time) { + ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, + AR5K_DCU_CHAN_TIME_DUR) | + AR5K_DCU_CHAN_TIME_ENABLE, + AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); + + if (tq->tqi_flags + & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) + AR5K_REG_ENABLE_BITS(ah, + AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_RDY_VEOL_POLICY); + } + + if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) + ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, + AR5K_QUEUE_DFS_MISC(queue)); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) + ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, + AR5K_QUEUE_DFS_MISC(queue)); + + /* + * Set registers by queue type + */ + switch (tq->tqi_type) { + case AR5K_TX_QUEUE_BEACON: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_DBA_GT | + AR5K_QCU_MISC_CBREXP_BCN_DIS | + AR5K_QCU_MISC_BCN_ENABLE); + + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_DCU_MISC_ARBLOCK_CTL_S) | + AR5K_DCU_MISC_POST_FR_BKOFF_DIS | + AR5K_DCU_MISC_BCN_ENABLE); + break; + + case AR5K_TX_QUEUE_CAB: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_FRSHED_DBA_GT | + AR5K_QCU_MISC_CBREXP_DIS | + AR5K_QCU_MISC_CBREXP_BCN_DIS); + + ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - + (AR5K_TUNE_SW_BEACON_RESP - + AR5K_TUNE_DMA_BEACON_RESP) - + AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | + AR5K_QCU_RDYTIMECFG_ENABLE, + AR5K_QUEUE_RDYTIMECFG(queue)); + + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), + (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << + AR5K_DCU_MISC_ARBLOCK_CTL_S)); + break; + + case AR5K_TX_QUEUE_UAPSD: + AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), + AR5K_QCU_MISC_CBREXP_DIS); + break; + + case AR5K_TX_QUEUE_DATA: + default: + break; + } + + /* TODO: Handle frame compression */ + + /* + * Enable interrupts for this tx queue + * in the secondary interrupt mask registers + */ + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); + + if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) + AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); + + /* Update secondary interrupt mask registers */ + + /* Filter out inactive queues */ + ah->ah_txq_imr_txok &= ah->ah_txq_status; + ah->ah_txq_imr_txerr &= ah->ah_txq_status; + ah->ah_txq_imr_txurn &= ah->ah_txq_status; + ah->ah_txq_imr_txdesc &= ah->ah_txq_status; + ah->ah_txq_imr_txeol &= ah->ah_txq_status; + ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; + ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; + ah->ah_txq_imr_qtrig &= ah->ah_txq_status; + ah->ah_txq_imr_nofrm &= ah->ah_txq_status; + + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, + AR5K_SIMR0_QCU_TXOK) | + AR5K_REG_SM(ah->ah_txq_imr_txdesc, + AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, + AR5K_SIMR1_QCU_TXERR) | + AR5K_REG_SM(ah->ah_txq_imr_txeol, + AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); + /* Update simr2 but don't overwrite rest simr2 settings */ + AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); + AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, + AR5K_REG_SM(ah->ah_txq_imr_txurn, + AR5K_SIMR2_QCU_TXURN)); + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, + AR5K_SIMR3_QCBRORN) | + AR5K_REG_SM(ah->ah_txq_imr_cbrurn, + AR5K_SIMR3_QCBRURN), AR5K_SIMR3); + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, + AR5K_SIMR4_QTRIG), AR5K_SIMR4); + /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, + AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); + /* No queue has TXNOFRM enabled, disable the interrupt + * by setting AR5K_TXNOFRM to zero */ + if (ah->ah_txq_imr_nofrm == 0) + ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); + + /* Set QCU mask for this DCU to save power */ + AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); + } + + return 0; +} + +/* + * Get slot time from DCU + */ +unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) +{ + ATH5K_TRACE(ah->ah_sc); + if (ah->ah_version == AR5K_AR5210) + return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, + AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); + else + return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; +} + +/* + * Set slot time on DCU + */ +int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) +{ + ATH5K_TRACE(ah->ah_sc); + if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) + return -EINVAL; + + if (ah->ah_version == AR5K_AR5210) + ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, + ah->ah_turbo), AR5K_SLOT_TIME); + else + ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); + + return 0; +} + diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h new file mode 100644 index 000000000000..7070d1543cdc --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -0,0 +1,2589 @@ +/* + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2007-2008 Michael Taylor + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k + * maintained by Reyk Floeter + * + * I tried to document those registers by looking at ar5k code, some + * 802.11 (802.11e mostly) papers and by reading various public available + * Atheros presentations and papers like these: + * + * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf + * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf + * + * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf + * + * This file also contains register values found on a memory dump of + * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal + * released by Atheros and on various debug messages found on the net. + */ + + + +/*====MAC DMA REGISTERS====*/ + +/* + * AR5210-Specific TXDP registers + * 5210 has only 2 transmit queues so no DCU/QCU, just + * 2 transmit descriptor pointers... + */ +#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */ +#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */ + +/* + * Mac Control Register + */ +#define AR5K_CR 0x0008 /* Register Address */ +#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */ +#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */ +#define AR5K_CR_RXE 0x00000004 /* RX Enable */ +#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */ +#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */ +#define AR5K_CR_RXD 0x00000020 /* RX Disable */ +#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */ + +/* + * RX Descriptor Pointer register + */ +#define AR5K_RXDP 0x000c + +/* + * Configuration and status register + */ +#define AR5K_CFG 0x0014 /* Register Address */ +#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */ +#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */ +#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ +#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */ +#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */ +#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */ +#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ +#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ +#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */ +#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */ +#define AR5K_CFG_TXCNT_S 11 +#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */ +#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */ +#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */ +#define AR5K_CFG_PCI_THRES_S 17 + +/* + * Interrupt enable register + */ +#define AR5K_IER 0x0024 /* Register Address */ +#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */ +#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */ + + +/* + * 0x0028 is Beacon Control Register on 5210 + * and first RTS duration register on 5211 + */ + +/* + * Beacon control register [5210] + */ +#define AR5K_BCR 0x0028 /* Register Address */ +#define AR5K_BCR_AP 0x00000000 /* AP mode */ +#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */ +#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */ +#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */ +#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */ +#define AR5K_BCR_BCGET 0x00000010 + +/* + * First RTS duration register [5211] + */ +#define AR5K_RTSD0 0x0028 /* Register Address */ +#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */ +#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */ +#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/ +#define AR5K_RTSD0_9_S 8 +#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/ +#define AR5K_RTSD0_12_S 16 +#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/ +#define AR5K_RTSD0_18_S 24 + + +/* + * 0x002c is Beacon Status Register on 5210 + * and second RTS duration register on 5211 + */ + +/* + * Beacon status register [5210] + * + * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR + * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning + * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). + * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i + * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what + * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. + */ +#define AR5K_BSR 0x002c /* Register Address */ +#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */ +#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */ +#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */ +#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */ +#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */ +#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */ +#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */ +#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */ +#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */ +#define AR5K_BSR_SWBA_CNT 0x00ff0000 + +/* + * Second RTS duration register [5211] + */ +#define AR5K_RTSD1 0x002c /* Register Address */ +#define AR5K_RTSD1_24 0x000000ff /* 24Mb */ +#define AR5K_RTSD1_24_S 0 +#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */ +#define AR5K_RTSD1_36_S 8 +#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */ +#define AR5K_RTSD1_48_S 16 +#define AR5K_RTSD1_54 0xff000000 /* 54Mb */ +#define AR5K_RTSD1_54_S 24 + + +/* + * Transmit configuration register + */ +#define AR5K_TXCFG 0x0030 /* Register Address */ +#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */ +#define AR5K_TXCFG_SDMAMR_S 0 +#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */ +#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */ +#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */ +#define AR5K_TXCFG_TXFULL_S 4 +#define AR5K_TXCFG_TXFULL_0B 0x00000000 +#define AR5K_TXCFG_TXFULL_64B 0x00000010 +#define AR5K_TXCFG_TXFULL_128B 0x00000020 +#define AR5K_TXCFG_TXFULL_192B 0x00000030 +#define AR5K_TXCFG_TXFULL_256B 0x00000040 +#define AR5K_TXCFG_TXCONT_EN 0x00000080 +#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */ +#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */ +#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */ +#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */ +#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */ +#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ +#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */ +#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */ +#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */ +#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */ + +/* + * Receive configuration register + */ +#define AR5K_RXCFG 0x0034 /* Register Address */ +#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */ +#define AR5K_RXCFG_SDMAMW_S 0 +#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */ +#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */ +#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */ +#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */ +#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */ + +/* + * Receive jumbo descriptor last address register + * Only found in 5211 (?) + */ +#define AR5K_RXJLA 0x0038 + +/* + * MIB control register + */ +#define AR5K_MIBC 0x0040 /* Register Address */ +#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ +#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ +#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ +#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ + +/* + * Timeout prescale register + */ +#define AR5K_TOPS 0x0044 +#define AR5K_TOPS_M 0x0000ffff + +/* + * Receive timeout register (no frame received) + */ +#define AR5K_RXNOFRM 0x0048 +#define AR5K_RXNOFRM_M 0x000003ff + +/* + * Transmit timeout register (no frame sent) + */ +#define AR5K_TXNOFRM 0x004c +#define AR5K_TXNOFRM_M 0x000003ff +#define AR5K_TXNOFRM_QCU 0x000ffc00 +#define AR5K_TXNOFRM_QCU_S 10 + +/* + * Receive frame gap timeout register + */ +#define AR5K_RPGTO 0x0050 +#define AR5K_RPGTO_M 0x000003ff + +/* + * Receive frame count limit register + */ +#define AR5K_RFCNT 0x0054 +#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */ +#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */ + +/* + * Misc settings register + * (reserved0-3) + */ +#define AR5K_MISC 0x0058 /* Register Address */ +#define AR5K_MISC_DMA_OBS_M 0x000001e0 +#define AR5K_MISC_DMA_OBS_S 5 +#define AR5K_MISC_MISC_OBS_M 0x00000e00 +#define AR5K_MISC_MISC_OBS_S 9 +#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000 +#define AR5K_MISC_MAC_OBS_LSB_S 12 +#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000 +#define AR5K_MISC_MAC_OBS_MSB_S 15 +#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */ +#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */ + +/* + * QCU/DCU clock gating register (5311) + * (reserved4-5) + */ +#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */ +#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */ +#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */ + +/* + * Interrupt Status Registers + * + * For 5210 there is only one status register but for + * 5211/5212 we have one primary and 4 secondary registers. + * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. + * Most of these bits are common for all chipsets. + */ +#define AR5K_ISR 0x001c /* Register Address [5210] */ +#define AR5K_PISR 0x0080 /* Register Address [5211+] */ +#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */ +#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ +#define AR5K_ISR_RXERR 0x00000004 /* Receive error */ +#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ +#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */ +#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */ +#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */ +#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ +#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ +#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */ +#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ +#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ +#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ +#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */ +#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */ +#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */ +#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ +#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ +#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ +#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ +#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ +#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ +#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ +#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ +#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ +#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ +#define AR5K_ISR_TIM 0x00800000 /* [5211+] */ +#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, + CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ +#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ +#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ +#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ +#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ + +/* + * Secondary status registers [5211+] (0 - 4) + * + * These give the status for each QCU, only QCUs 0-9 are + * represented. + */ +#define AR5K_SISR0 0x0084 /* Register Address [5211+] */ +#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ +#define AR5K_SISR0_QCU_TXOK_S 0 +#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ +#define AR5K_SISR0_QCU_TXDESC_S 16 + +#define AR5K_SISR1 0x0088 /* Register Address [5211+] */ +#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ +#define AR5K_SISR1_QCU_TXERR_S 0 +#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ +#define AR5K_SISR1_QCU_TXEOL_S 16 + +#define AR5K_SISR2 0x008c /* Register Address [5211+] */ +#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ +#define AR5K_SISR2_QCU_TXURN_S 0 +#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ +#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ +#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */ +#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ +#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ +#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ +#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ +#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ +#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ +#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */ + +#define AR5K_SISR3 0x0090 /* Register Address [5211+] */ +#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ +#define AR5K_SISR3_QCBRORN_S 0 +#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ +#define AR5K_SISR3_QCBRURN_S 16 + +#define AR5K_SISR4 0x0094 /* Register Address [5211+] */ +#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */ +#define AR5K_SISR4_QTRIG_S 0 + +/* + * Shadow read-and-clear interrupt status registers [5211+] + */ +#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */ +#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */ +#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */ +#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */ +#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */ +#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */ + +/* + * Interrupt Mask Registers + * + * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary + * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. + */ +#define AR5K_IMR 0x0020 /* Register Address [5210] */ +#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ +#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/ +#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ +#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ +#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ +#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/ +#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/ +#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/ +#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/ +#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/ +#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/ +#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/ +#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/ +#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/ +#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */ +#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/ +#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */ +#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/ +#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ +#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/ +#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ +#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */ +#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ +#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/ +#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */ +#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */ +#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ +#define AR5K_IMR_TIM 0x00800000 /* [5211+] */ +#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, + CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ +#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/ +#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */ +#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */ +#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ + +/* + * Secondary interrupt mask registers [5211+] (0 - 4) + */ +#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */ +#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ +#define AR5K_SIMR0_QCU_TXOK_S 0 +#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ +#define AR5K_SIMR0_QCU_TXDESC_S 16 + +#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */ +#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ +#define AR5K_SIMR1_QCU_TXERR_S 0 +#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ +#define AR5K_SIMR1_QCU_TXEOL_S 16 + +#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ +#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ +#define AR5K_SIMR2_QCU_TXURN_S 0 +#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ +#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ +#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */ +#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ +#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ +#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ +#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ +#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ +#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */ +#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */ + +#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */ +#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ +#define AR5K_SIMR3_QCBRORN_S 0 +#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ +#define AR5K_SIMR3_QCBRURN_S 16 + +#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */ +#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */ +#define AR5K_SIMR4_QTRIG_S 0 + +/* + * DMA Debug registers 0-7 + * 0xe0 - 0xfc + */ + +/* + * Decompression mask registers [5212+] + */ +#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */ +#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */ + +/* + * Wake On Wireless pattern control register [5212+] + */ +#define AR5K_WOW_PCFG 0x0410 /* Register Address */ +#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */ +#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */ +#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */ +#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */ +#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */ +#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */ +#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */ +#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */ +#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */ + +/* + * Wake On Wireless pattern index register (?) [5212+] + */ +#define AR5K_WOW_PAT_IDX 0x0414 + +/* + * Wake On Wireless pattern data register [5212+] + */ +#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */ +#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */ +#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */ +#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */ +#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */ +#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */ +#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */ + +/* + * Decompression configuration registers [5212+] + */ +#define AR5K_DCCFG 0x0420 /* Register Address */ +#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */ +#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */ +#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */ +#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */ + +/* + * Compression configuration registers [5212+] + */ +#define AR5K_CCFG 0x0600 /* Register Address */ +#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */ +#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */ + +#define AR5K_CCFG_CCU 0x0604 /* Register Address */ +#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */ +#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */ +#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */ +#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */ +#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */ + +/* + * Compression performance counter registers [5212+] + */ +#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */ +#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/ +#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */ +#define AR5K_CPC3 0x061c /* Compression performance counter 3 */ +#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */ + + +/* + * Queue control unit (QCU) registers [5211+] + * + * Card has 12 TX Queues but i see that only 0-9 are used (?) + * both in binary HAL (see ah.h) and ar5k. Each queue has it's own + * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate) + * configuration register (0x08c0 - 0x08ec), a ready time configuration + * register (0x0900 - 0x092c), a misc configuration register (0x09c0 - + * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some + * global registers, QCU transmit enable/disable and "one shot arm (?)" + * set/clear, which contain status for all queues (we shift by 1 for each + * queue). To access these registers easily we define some macros here + * that are used inside HAL. For more infos check out *_tx_queue functs. + */ + +/* + * Generic QCU Register access macros + */ +#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r) +#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q)) +#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q)) + +/* + * QCU Transmit descriptor pointer registers + */ +#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */ +#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q) + +/* + * QCU Transmit enable register + */ +#define AR5K_QCU_TXE 0x0840 +#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q) +#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q) + +/* + * QCU Transmit disable register + */ +#define AR5K_QCU_TXD 0x0880 +#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q) +#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q) + +/* + * QCU Constant Bit Rate configuration registers + */ +#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */ +#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */ +#define AR5K_QCU_CBRCFG_INTVAL_S 0 +#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */ +#define AR5K_QCU_CBRCFG_ORN_THRES_S 24 +#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q) + +/* + * QCU Ready time configuration registers + */ +#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */ +#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */ +#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0 +#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */ +#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q) + +/* + * QCU one shot arm set registers + */ +#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */ +#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff + +/* + * QCU one shot arm clear registers + */ +#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */ +#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff + +/* + * QCU misc registers + */ +#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */ +#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */ +#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ +#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ +#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */ +#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */ +#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */ +#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */ +#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */ +#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */ +#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */ +#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */ +#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */ +#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */ +#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */ +#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */ +#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q) + + +/* + * QCU status registers + */ +#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */ +#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */ +#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */ +#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q) + +/* + * QCU ready time shutdown register + */ +#define AR5K_QCU_RDYTIMESHDN 0x0a40 +#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff + +/* + * QCU compression buffer base registers [5212+] + */ +#define AR5K_QCU_CBB_SELECT 0x0b00 +#define AR5K_QCU_CBB_ADDR 0x0b04 +#define AR5K_QCU_CBB_ADDR_S 9 + +/* + * QCU compression buffer configuration register [5212+] + * (buffer size) + */ +#define AR5K_QCU_CBCFG 0x0b08 + + + +/* + * Distributed Coordination Function (DCF) control unit (DCU) + * registers [5211+] + * + * These registers control the various characteristics of each queue + * for 802.11e (WME) combatibility so they go together with + * QCU registers in pairs. For each queue we have a QCU mask register, + * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c), + * a retry limit register (0x1080 - 0x10ac), a channel time register + * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and + * a sequence number register (0x1140 - 0x116c). It seems that "global" + * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k). + * We use the same macros here for easier register access. + * + */ + +/* + * DCU QCU mask registers + */ +#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */ +#define AR5K_DCU_QCUMASK_M 0x000003ff +#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q) + +/* + * DCU local Inter Frame Space settings register + */ +#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */ +#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */ +#define AR5K_DCU_LCL_IFS_CW_MIN_S 0 +#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */ +#define AR5K_DCU_LCL_IFS_CW_MAX_S 10 +#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */ +#define AR5K_DCU_LCL_IFS_AIFS_S 20 +#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */ +#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q) + +/* + * DCU retry limit registers + */ +#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ +#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ +#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0 +#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */ +#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4 +#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */ +#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8 +#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */ +#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14 +#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) + +/* + * DCU channel time registers + */ +#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */ +#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */ +#define AR5K_DCU_CHAN_TIME_DUR_S 0 +#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */ +#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q) + +/* + * DCU misc registers [5211+] + * + * Note: Arbiter lockout control controls the + * behaviour on low priority queues when we have multiple queues + * with pending frames. Intra-frame lockout means we wait until + * the queue's current frame transmits (with post frame backoff and bursting) + * before we transmit anything else and global lockout means we + * wait for the whole queue to finish before higher priority queues + * can transmit (this is used on beacon and CAB queues). + * No lockout means there is no special handling. + */ +#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */ +#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */ +#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series + station RTS/data failure count + reset policy (?) */ +#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series + CW reset policy */ +#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */ +#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */ +#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */ +#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */ +#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */ +#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */ +#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 +#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1 +#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */ +#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */ +#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17 +#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */ +#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */ +#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */ +#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */ +#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */ +#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */ +#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */ +#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */ +#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */ +#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q) + +/* + * DCU frame sequence number registers + */ +#define AR5K_DCU_SEQNUM_BASE 0x1140 +#define AR5K_DCU_SEQNUM_M 0x00000fff +#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q) + +/* + * DCU global IFS SIFS register + */ +#define AR5K_DCU_GBL_IFS_SIFS 0x1030 +#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff + +/* + * DCU global IFS slot interval register + */ +#define AR5K_DCU_GBL_IFS_SLOT 0x1070 +#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff + +/* + * DCU global IFS EIFS register + */ +#define AR5K_DCU_GBL_IFS_EIFS 0x10b0 +#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff + +/* + * DCU global IFS misc register + * + * LFSR stands for Linear Feedback Shift Register + * and it's used for generating pseudo-random + * number sequences. + * + * (If i understand corectly, random numbers are + * used for idle sensing -multiplied with cwmin/max etc-) + */ +#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */ +#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ +#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 +#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */ +#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */ +#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */ + +/* + * DCU frame prefetch control register + */ +#define AR5K_DCU_FP 0x1230 /* Register Address */ +#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */ +#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */ +#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */ + +/* + * DCU transmit pause control/status register + */ +#define AR5K_DCU_TXP 0x1270 /* Register Address */ +#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */ +#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */ + +/* + * DCU transmit filter table 0 (32 entries) + * each entry contains a 32bit slice of the + * 128bit tx filter for each DCU (4 slices per DCU) + */ +#define AR5K_DCU_TX_FILTER_0_BASE 0x1038 +#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64)) + +/* + * DCU transmit filter table 1 (16 entries) + */ +#define AR5K_DCU_TX_FILTER_1_BASE 0x103c +#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + (_n * 64)) + +/* + * DCU clear transmit filter register + */ +#define AR5K_DCU_TX_FILTER_CLR 0x143c + +/* + * DCU set transmit filter register + */ +#define AR5K_DCU_TX_FILTER_SET 0x147c + +/* + * Reset control register + */ +#define AR5K_RESET_CTL 0x4000 /* Register Address */ +#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */ +#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */ +#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */ +#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ +#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ +#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ + +/* + * Sleep control register + */ +#define AR5K_SLEEP_CTL 0x4004 /* Register Address */ +#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */ +#define AR5K_SLEEP_CTL_SLDUR_S 0 +#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */ +#define AR5K_SLEEP_CTL_SLE_S 16 +#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */ +#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */ +#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */ +#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */ +#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */ +#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */ +#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */ + +/* + * Interrupt pending register + */ +#define AR5K_INTPEND 0x4008 +#define AR5K_INTPEND_M 0x00000001 + +/* + * Sleep force register + */ +#define AR5K_SFR 0x400c +#define AR5K_SFR_EN 0x00000001 + +/* + * PCI configuration register + * TODO: Fix LED stuff + */ +#define AR5K_PCICFG 0x4010 /* Register Address */ +#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ +#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */ +#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ +#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ +#define AR5K_PCICFG_EESIZE_S 3 +#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */ +#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */ +#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */ +#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */ +#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */ +#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */ +#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */ +#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */ +#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */ +#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */ +#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ +#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ +#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ +#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/ +#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ +#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ +#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ +#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */ +#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */ +#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */ +#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */ +#define AR5K_PCICFG_LEDBLINK_S 20 +#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */ +#define AR5K_PCICFG_LEDSTATE \ + (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \ + AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW) +#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */ +#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24 + +/* + * "General Purpose Input/Output" (GPIO) control register + * + * I'm not sure about this but after looking at the code + * for all chipsets here is what i got. + * + * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits) + * Mode 0 -> always input + * Mode 1 -> output when GPIODO for this GPIO is set to 0 + * Mode 2 -> output when GPIODO for this GPIO is set to 1 + * Mode 3 -> always output + * + * For more infos check out get_gpio/set_gpio and + * set_gpio_input/set_gpio_output functs. + * For more infos on gpio interrupt check out set_gpio_intr. + */ +#define AR5K_NUM_GPIO 6 + +#define AR5K_GPIOCR 0x4014 /* Register Address */ +#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ +#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */ +#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */ +#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */ +#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */ +#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */ +#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */ +#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */ + +/* + * "General Purpose Input/Output" (GPIO) data output register + */ +#define AR5K_GPIODO 0x4018 + +/* + * "General Purpose Input/Output" (GPIO) data input register + */ +#define AR5K_GPIODI 0x401c +#define AR5K_GPIODI_M 0x0000002f + +/* + * Silicon revision register + */ +#define AR5K_SREV 0x4020 /* Register Address */ +#define AR5K_SREV_REV 0x0000000f /* Mask for revision */ +#define AR5K_SREV_REV_S 0 +#define AR5K_SREV_VER 0x000000ff /* Mask for version */ +#define AR5K_SREV_VER_S 4 + +/* + * TXE write posting register + */ +#define AR5K_TXEPOST 0x4028 + +/* + * QCU sleep mask + */ +#define AR5K_QCU_SLEEP_MASK 0x402c + +/* 0x4068 is compression buffer configuration + * register on 5414 and pm configuration register + * on 5424 and newer pci-e chips. */ + +/* + * Compression buffer configuration + * register (enable/disable) [5414] + */ +#define AR5K_5414_CBCFG 0x4068 +#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */ + +/* + * PCI-E Power managment configuration + * and status register [5424+] + */ +#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */ +/* Only 5424 */ +#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1 + when d2_sleep_en is asserted */ +#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */ +#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */ +#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes + down */ +/* Wake On Wireless */ +#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */ +#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */ +#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */ +#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080 +#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100 +#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200 +#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400 + +/* + * PCI-E Workaround enable register + */ +#define AR5K_PCIE_WAEN 0x407c + +/* + * PCI-E Serializer/Desirializer + * registers + */ +#define AR5K_PCIE_SERDES 0x4080 +#define AR5K_PCIE_SERDES_RESET 0x4084 + +/*====EEPROM REGISTERS====*/ + +/* + * EEPROM access registers + * + * Here we got a difference between 5210/5211-12 + * read data register for 5210 is at 0x6800 and + * status register is at 0x6c00. There is also + * no eeprom command register on 5210 and the + * offsets are different. + * + * To read eeprom data for a specific offset: + * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) + * read AR5K_EEPROM_BASE +(4 * offset) + * check the eeprom status register + * and read eeprom data register. + * + * 5211 - write offset to AR5K_EEPROM_BASE + * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD + * check the eeprom status register + * and read eeprom data register. + * + * To write eeprom data for a specific offset: + * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) + * write data to AR5K_EEPROM_BASE +(4 * offset) + * check the eeprom status register + * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD + * 5212 write offset to AR5K_EEPROM_BASE + * write data to data register + * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD + * check the eeprom status register + * + * For more infos check eeprom_* functs and the ar5k.c + * file posted in madwifi-devel mailing list. + * http://sourceforge.net/mailarchive/message.php?msg_id=8966525 + * + */ +#define AR5K_EEPROM_BASE 0x6000 + +/* + * EEPROM data register + */ +#define AR5K_EEPROM_DATA_5211 0x6004 +#define AR5K_EEPROM_DATA_5210 0x6800 +#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \ + AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211) + +/* + * EEPROM command register + */ +#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ +#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ +#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ +#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ + +/* + * EEPROM status register + */ +#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */ +#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */ +#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \ + AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211) +#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */ +#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */ +#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */ +#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */ + +/* + * EEPROM config register + */ +#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ +#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ +#define AR5K_EEPROM_CFG_SIZE_AUTO 0 +#define AR5K_EEPROM_CFG_SIZE_4KBIT 1 +#define AR5K_EEPROM_CFG_SIZE_8KBIT 2 +#define AR5K_EEPROM_CFG_SIZE_16KBIT 3 +#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */ +#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */ +#define AR5K_EEPROM_CFG_CLK_RATE_S 3 +#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0 +#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1 +#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2 +#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */ +#define AR5K_EEPROM_CFG_PROT_KEY_S 8 +#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */ + + +/* + * TODO: Wake On Wireless registers + * Range 0x7000 - 0x7ce0 + */ + +/* + * Protocol Control Unit (PCU) registers + */ +/* + * Used for checking initial register writes + * during channel reset (see reset func) + */ +#define AR5K_PCU_MIN 0x8000 +#define AR5K_PCU_MAX 0x8fff + +/* + * First station id register (Lower 32 bits of MAC address) + */ +#define AR5K_STA_ID0 0x8000 +#define AR5K_STA_ID0_ARRD_L32 0xffffffff + +/* + * Second station id register (Upper 16 bits of MAC address + PCU settings) + */ +#define AR5K_STA_ID1 0x8004 /* Register Address */ +#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */ +#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ +#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ +#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ +#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */ +#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */ +#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */ +#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/ +#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \ + AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211) +#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ +#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ +#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ +#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ +#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */ +#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ +#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ +#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ +#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */ +#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ +#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ + +/* + * First BSSID register (MAC address, lower 32bits) + */ +#define AR5K_BSS_ID0 0x8008 + +/* + * Second BSSID register (MAC address in upper 16 bits) + * + * AID: Association ID + */ +#define AR5K_BSS_ID1 0x800c +#define AR5K_BSS_ID1_AID 0xffff0000 +#define AR5K_BSS_ID1_AID_S 16 + +/* + * Backoff slot time register + */ +#define AR5K_SLOT_TIME 0x8010 + +/* + * ACK/CTS timeout register + */ +#define AR5K_TIME_OUT 0x8014 /* Register Address */ +#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */ +#define AR5K_TIME_OUT_ACK_S 0 +#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */ +#define AR5K_TIME_OUT_CTS_S 16 + +/* + * RSSI threshold register + */ +#define AR5K_RSSI_THR 0x8018 /* Register Address */ +#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */ +#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */ +#define AR5K_RSSI_THR_BMISS_5210_S 8 +#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */ +#define AR5K_RSSI_THR_BMISS_5211_S 8 +#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \ + AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211) +#define AR5K_RSSI_THR_BMISS_S 8 + +/* + * 5210 has more PCU registers because there is no QCU/DCU + * so queue parameters are set here, this way a lot common + * registers have different address for 5210. To make things + * easier we define a macro based on ah->ah_version for common + * registers with different addresses and common flags. + */ + +/* + * Retry limit register + * + * Retry limit register for 5210 (no QCU/DCU so it's done in PCU) + */ +#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */ +#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ +#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0 +#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */ +#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4 +#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */ +#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8 +#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */ +#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14 +#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */ +#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20 + +/* + * Transmit latency register + */ +#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */ +#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */ +#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \ + AR5K_USEC_5210 : AR5K_USEC_5211) +#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */ +#define AR5K_USEC_1_S 0 +#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */ +#define AR5K_USEC_32_S 7 +#define AR5K_USEC_TX_LATENCY_5211 0x007fc000 +#define AR5K_USEC_TX_LATENCY_5211_S 14 +#define AR5K_USEC_RX_LATENCY_5211 0x1f800000 +#define AR5K_USEC_RX_LATENCY_5211_S 23 +#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */ +#define AR5K_USEC_TX_LATENCY_5210_S 14 +#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */ +#define AR5K_USEC_RX_LATENCY_5210_S 20 + +/* + * PCU beacon control register + */ +#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */ +#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */ +#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \ + AR5K_BEACON_5210 : AR5K_BEACON_5211) +#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */ +#define AR5K_BEACON_PERIOD_S 0 +#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */ +#define AR5K_BEACON_TIM_S 16 +#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */ +#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */ + +/* + * CFP period register + */ +#define AR5K_CFP_PERIOD_5210 0x8028 +#define AR5K_CFP_PERIOD_5211 0x8024 +#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \ + AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211) + +/* + * Next beacon time register + */ +#define AR5K_TIMER0_5210 0x802c +#define AR5K_TIMER0_5211 0x8028 +#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_TIMER0_5210 : AR5K_TIMER0_5211) + +/* + * Next DMA beacon alert register + */ +#define AR5K_TIMER1_5210 0x8030 +#define AR5K_TIMER1_5211 0x802c +#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_TIMER1_5210 : AR5K_TIMER1_5211) + +/* + * Next software beacon alert register + */ +#define AR5K_TIMER2_5210 0x8034 +#define AR5K_TIMER2_5211 0x8030 +#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_TIMER2_5210 : AR5K_TIMER2_5211) + +/* + * Next ATIM window time register + */ +#define AR5K_TIMER3_5210 0x8038 +#define AR5K_TIMER3_5211 0x8034 +#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_TIMER3_5210 : AR5K_TIMER3_5211) + + +/* + * 5210 First inter frame spacing register (IFS) + */ +#define AR5K_IFS0 0x8040 +#define AR5K_IFS0_SIFS 0x000007ff +#define AR5K_IFS0_SIFS_S 0 +#define AR5K_IFS0_DIFS 0x007ff800 +#define AR5K_IFS0_DIFS_S 11 + +/* + * 5210 Second inter frame spacing register (IFS) + */ +#define AR5K_IFS1 0x8044 +#define AR5K_IFS1_PIFS 0x00000fff +#define AR5K_IFS1_PIFS_S 0 +#define AR5K_IFS1_EIFS 0x03fff000 +#define AR5K_IFS1_EIFS_S 12 +#define AR5K_IFS1_CS_EN 0x04000000 + + +/* + * CFP duration register + */ +#define AR5K_CFP_DUR_5210 0x8048 +#define AR5K_CFP_DUR_5211 0x8038 +#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \ + AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211) + +/* + * Receive filter register + */ +#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */ +#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */ +#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \ + AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211) +#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */ +#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */ +#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */ +#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */ +#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */ +#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */ +#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */ +#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */ +#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */ +#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */ +#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */ +#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */ +#define AR5K_RX_FILTER_PHYERR \ + ((ah->ah_version == AR5K_AR5211 ? \ + AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212)) +#define AR5K_RX_FILTER_RADARERR \ + ((ah->ah_version == AR5K_AR5211 ? \ + AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212)) + +/* + * Multicast filter register (lower 32 bits) + */ +#define AR5K_MCAST_FILTER0_5210 0x8050 +#define AR5K_MCAST_FILTER0_5211 0x8040 +#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211) + +/* + * Multicast filter register (higher 16 bits) + */ +#define AR5K_MCAST_FILTER1_5210 0x8054 +#define AR5K_MCAST_FILTER1_5211 0x8044 +#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211) + + +/* + * Transmit mask register (lower 32 bits) [5210] + */ +#define AR5K_TX_MASK0 0x8058 + +/* + * Transmit mask register (higher 16 bits) [5210] + */ +#define AR5K_TX_MASK1 0x805c + +/* + * Clear transmit mask [5210] + */ +#define AR5K_CLR_TMASK 0x8060 + +/* + * Trigger level register (before transmission) [5210] + */ +#define AR5K_TRIG_LVL 0x8064 + + +/* + * PCU control register + * + * Only DIS_RX is used in the code, the rest i guess are + * for tweaking/diagnostics. + */ +#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ +#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ +#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211) +#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ +#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ +#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ +#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ +#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ +#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ +#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ +#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 +#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) +#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */ +#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 +#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) +#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */ +#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 +#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) +#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */ +#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 +#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) +#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */ +#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 +#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211) +#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */ +#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ +#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ +#define AR5K_DIAG_SW_SCRAM_SEED_S 10 +#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ +#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 +#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ +#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) +#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ +#define AR5K_DIAG_SW_OBSPT_S 18 +#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ +#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ +#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ +#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ + +/* + * TSF (clock) register (lower 32 bits) + */ +#define AR5K_TSF_L32_5210 0x806c +#define AR5K_TSF_L32_5211 0x804c +#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211) + +/* + * TSF (clock) register (higher 32 bits) + */ +#define AR5K_TSF_U32_5210 0x8070 +#define AR5K_TSF_U32_5211 0x8050 +#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \ + AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211) + +/* + * Last beacon timestamp register (Read Only) + */ +#define AR5K_LAST_TSTP 0x8080 + +/* + * ADDAC test register [5211+] + */ +#define AR5K_ADDAC_TEST 0x8054 /* Register Address */ +#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */ +#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */ +#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */ +#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */ +#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */ +#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */ +#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */ +#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */ +#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */ +#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */ +#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */ + +/* + * Default antenna register [5211+] + */ +#define AR5K_DEFAULT_ANTENNA 0x8058 + +/* + * Frame control QoS mask register (?) [5211+] + * (FC_QOS_MASK) + */ +#define AR5K_FRAME_CTL_QOSM 0x805c + +/* + * Seq mask register (?) [5211+] + */ +#define AR5K_SEQ_MASK 0x8060 + +/* + * Retry count register [5210] + */ +#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */ +#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */ +#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */ + +/* + * Back-off status register [5210] + */ +#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */ +#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */ +#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */ + + + +/* + * NAV register (current) + */ +#define AR5K_NAV_5210 0x808c +#define AR5K_NAV_5211 0x8084 +#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \ + AR5K_NAV_5210 : AR5K_NAV_5211) + +/* + * RTS success register + */ +#define AR5K_RTS_OK_5210 0x8090 +#define AR5K_RTS_OK_5211 0x8088 +#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \ + AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) + +/* + * RTS failure register + */ +#define AR5K_RTS_FAIL_5210 0x8094 +#define AR5K_RTS_FAIL_5211 0x808c +#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \ + AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) + +/* + * ACK failure register + */ +#define AR5K_ACK_FAIL_5210 0x8098 +#define AR5K_ACK_FAIL_5211 0x8090 +#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \ + AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) + +/* + * FCS failure register + */ +#define AR5K_FCS_FAIL_5210 0x809c +#define AR5K_FCS_FAIL_5211 0x8094 +#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \ + AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211) + +/* + * Beacon count register + */ +#define AR5K_BEACON_CNT_5210 0x80a0 +#define AR5K_BEACON_CNT_5211 0x8098 +#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \ + AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211) + + +/*===5212 Specific PCU registers===*/ + +/* + * Transmit power control register + */ +#define AR5K_TPC 0x80e8 +#define AR5K_TPC_ACK 0x0000003f /* ack frames */ +#define AR5K_TPC_ACK_S 0 +#define AR5K_TPC_CTS 0x00003f00 /* cts frames */ +#define AR5K_TPC_CTS_S 8 +#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */ +#define AR5K_TPC_CHIRP_S 16 +#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */ +#define AR5K_TPC_DOPPLER_S 24 + +/* + * XR (eXtended Range) mode register + */ +#define AR5K_XRMODE 0x80c0 /* Register Address */ +#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */ +#define AR5K_XRMODE_POLL_TYPE_S 0 +#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */ +#define AR5K_XRMODE_POLL_SUBTYPE_S 2 +#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */ +#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */ +#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */ +#define AR5K_XRMODE_FRAME_HOLD_S 20 + +/* + * XR delay register + */ +#define AR5K_XRDELAY 0x80c4 /* Register Address */ +#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */ +#define AR5K_XRDELAY_SLOT_DELAY_S 0 +#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */ +#define AR5K_XRDELAY_CHIRP_DELAY_S 16 + +/* + * XR timeout register + */ +#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */ +#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */ +#define AR5K_XRTIMEOUT_CHIRP_S 0 +#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */ +#define AR5K_XRTIMEOUT_POLL_S 16 + +/* + * XR chirp register + */ +#define AR5K_XRCHIRP 0x80cc /* Register Address */ +#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */ +#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */ + +/* + * XR stomp register + */ +#define AR5K_XRSTOMP 0x80d0 /* Register Address */ +#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */ +#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */ +#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */ +#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */ +#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/ +#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */ + +/* + * First enhanced sleep register + */ +#define AR5K_SLEEP0 0x80d4 /* Register Address */ +#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */ +#define AR5K_SLEEP0_NEXT_DTIM_S 0 +#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */ +#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */ +#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */ +#define AR5K_SLEEP0_CABTO_S 24 + +/* + * Second enhanced sleep register + */ +#define AR5K_SLEEP1 0x80d8 /* Register Address */ +#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */ +#define AR5K_SLEEP1_NEXT_TIM_S 0 +#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */ +#define AR5K_SLEEP1_BEACON_TO_S 24 + +/* + * Third enhanced sleep register + */ +#define AR5K_SLEEP2 0x80dc /* Register Address */ +#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */ +#define AR5K_SLEEP2_TIM_PER_S 0 +#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */ +#define AR5K_SLEEP2_DTIM_PER_S 16 + +/* + * BSSID mask registers + */ +#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */ +#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */ + +/* + * TX power control (TPC) register + * + * XXX: PCDAC steps (0.5dbm) or DBM ? + * + */ +#define AR5K_TXPC 0x80e8 /* Register Address */ +#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */ +#define AR5K_TXPC_ACK_S 0 +#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */ +#define AR5K_TXPC_CTS_S 8 +#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */ +#define AR5K_TXPC_CHIRP_S 16 +#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */ +#define AR5K_TXPC_DOPPLER_S 24 + +/* + * Profile count registers + */ +#define AR5K_PROFCNT_TX 0x80ec /* Tx count */ +#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ +#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ +#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ + +/* + * Quiet period control registers + */ +#define AR5K_QUIET_CTL1 0x80fc /* Register Address */ +#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ +#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0 +#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ +#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ + +#define AR5K_QUIET_CTL2 0x8100 /* Register Address */ +#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */ +#define AR5K_QUIET_CTL2_QT_PER_S 0 +#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */ +#define AR5K_QUIET_CTL2_QT_DUR_S 16 + +/* + * TSF parameter register + */ +#define AR5K_TSF_PARM 0x8104 /* Register Address */ +#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */ +#define AR5K_TSF_PARM_INC_S 0 + +/* + * QoS NOACK policy + */ +#define AR5K_QOS_NOACK 0x8108 /* Register Address */ +#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */ +#define AR5K_QOS_NOACK_2BIT_VALUES_S 0 +#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */ +#define AR5K_QOS_NOACK_BIT_OFFSET_S 4 +#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */ +#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7 + +/* + * PHY error filter register + */ +#define AR5K_PHY_ERR_FIL 0x810c +#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */ +#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */ +#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */ + +/* + * XR latency register + */ +#define AR5K_XRLAT_TX 0x8110 + +/* + * ACK SIFS register + */ +#define AR5K_ACKSIFS 0x8114 /* Register Address */ +#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */ + +/* + * MIC QoS control register (?) + */ +#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */ +#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2)) +#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */ + +/* + * MIC QoS select register (?) + */ +#define AR5K_MIC_QOS_SEL 0x811c +#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4)) + +/* + * Misc mode control register (?) + */ +#define AR5K_MISC_MODE 0x8120 /* Register Address */ +#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */ +#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */ +#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */ +/* more bits */ + +/* + * OFDM Filter counter + */ +#define AR5K_OFDM_FIL_CNT 0x8124 + +/* + * CCK Filter counter + */ +#define AR5K_CCK_FIL_CNT 0x8128 + +/* + * PHY Error Counters (?) + */ +#define AR5K_PHYERR_CNT1 0x812c +#define AR5K_PHYERR_CNT1_MASK 0x8130 + +#define AR5K_PHYERR_CNT2 0x8134 +#define AR5K_PHYERR_CNT2_MASK 0x8138 + +/* + * TSF Threshold register (?) + */ +#define AR5K_TSF_THRES 0x813c + +/* + * TODO: Wake On Wireless registers + * Range: 0x8147 - 0x818c + */ + +/* + * Rate -> ACK SIFS mapping table (32 entries) + */ +#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */ +#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2)) +#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */ +#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */ + +/* + * Rate -> duration mapping table (32 entries) + */ +#define AR5K_RATE_DUR_BASE 0x8700 +#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2)) + +/* + * Rate -> db mapping table + * (8 entries, each one has 4 8bit fields) + */ +#define AR5K_RATE2DB_BASE 0x87c0 +#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2)) + +/* + * db -> Rate mapping table + * (8 entries, each one has 4 8bit fields) + */ +#define AR5K_DB2RATE_BASE 0x87e0 +#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2)) + +/*===5212 end===*/ + +/* + * Key table (WEP) register + */ +#define AR5K_KEYTABLE_0_5210 0x9000 +#define AR5K_KEYTABLE_0_5211 0x8800 +#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5)) +#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) +#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \ + AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n)) +#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2)) +#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5) +#define AR5K_KEYTABLE_TYPE_40 0x00000000 +#define AR5K_KEYTABLE_TYPE_104 0x00000001 +#define AR5K_KEYTABLE_TYPE_128 0x00000003 +#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */ +#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */ +#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */ +#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */ +#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */ +#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6) +#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) +#define AR5K_KEYTABLE_VALID 0x00008000 + +/* If key type is TKIP and MIC is enabled + * MIC key goes in offset entry + 64 */ +#define AR5K_KEYTABLE_MIC_OFFSET 64 + +/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit + * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit + * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit + * + * Some vendors have introduced bigger WEP keys to address + * security vulnerabilities in WEP. This includes: + * + * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit + * + * We can expand this if we find ar5k Atheros cards with a larger + * key table size. + */ +#define AR5K_KEYTABLE_SIZE_5210 64 +#define AR5K_KEYTABLE_SIZE_5211 128 +#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \ + AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211) + + +/*===PHY REGISTERS===*/ + +/* + * PHY registers start + */ +#define AR5K_PHY_BASE 0x9800 +#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) + +/* + * TST_2 (Misc config parameters) + */ +#define AR5K_PHY_TST2 0x9800 /* Register Address */ +#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/ +#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */ +#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */ +#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */ +#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */ +#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */ +#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */ +#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */ +#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */ +#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */ +#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */ +#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */ +#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */ +#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */ +#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */ +#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */ +#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */ +#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */ + +/* + * PHY frame control register [5110] /turbo mode register [5111+] + * + * There is another frame control register for [5111+] + * at address 0x9944 (see below) but the 2 first flags + * are common here between 5110 frame control register + * and [5111+] turbo mode register, so this also works as + * a "turbo mode register" for 5110. We treat this one as + * a frame control register for 5110 below. + */ +#define AR5K_PHY_TURBO 0x9804 /* Register Address */ +#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ +#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ +#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ + +/* + * PHY agility command register + * (aka TST_1) + */ +#define AR5K_PHY_AGC 0x9808 /* Register Address */ +#define AR5K_PHY_TST1 0x9808 +#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/ +#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */ +#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */ +#define AR5K_PHY_TST1_TXSRC_SRC_S 1 +#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */ +#define AR5K_PHY_TST1_TXSRC_ALT_S 7 + + +/* + * PHY timing register 3 [5112+] + */ +#define AR5K_PHY_TIMING_3 0x9814 +#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000 +#define AR5K_PHY_TIMING_3_DSC_MAN_S 17 +#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000 +#define AR5K_PHY_TIMING_3_DSC_EXP_S 13 + +/* + * PHY chip revision register + */ +#define AR5K_PHY_CHIP_ID 0x9818 + +/* + * PHY activation register + */ +#define AR5K_PHY_ACT 0x981c /* Register Address */ +#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */ +#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */ + +/* + * PHY RF control registers + */ +#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */ +#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */ +#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0 + +#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */ +#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */ +#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8 + +#define AR5K_PHY_ADC_CTL 0x982c +#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003 +#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0 +#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000 +#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000 +#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000 +#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000 +#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16 + +#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */ +#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */ +#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */ +#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */ +#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */ + +/* + * Pre-Amplifier control register + * (XPA -> external pre-amplifier) + */ +#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */ +#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */ +#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */ +#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */ +#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */ + +/* + * PHY settling register + */ +#define AR5K_PHY_SETTLING 0x9844 /* Register Address */ +#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ +#define AR5K_PHY_SETTLING_AGC_S 0 +#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ +#define AR5K_PHY_SETTLING_SWITCH_S 7 + +/* + * PHY Gain registers + */ +#define AR5K_PHY_GAIN 0x9848 /* Register Address */ +#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */ +#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12 +#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000 +#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18 + +#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */ +#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ + +/* + * Desired ADC/PGA size register + * (for more infos read ANI patent) + */ +#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ +#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */ +#define AR5K_PHY_DESIRED_SIZE_ADC_S 0 +#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */ +#define AR5K_PHY_DESIRED_SIZE_PGA_S 8 +#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */ +#define AR5K_PHY_DESIRED_SIZE_TOT_S 20 + +/* + * PHY signal register + * (for more infos read ANI patent) + */ +#define AR5K_PHY_SIG 0x9858 /* Register Address */ +#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */ +#define AR5K_PHY_SIG_FIRSTEP_S 12 +#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */ +#define AR5K_PHY_SIG_FIRPWR_S 18 + +/* + * PHY coarse agility control register + * (for more infos read ANI patent) + */ +#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */ +#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */ +#define AR5K_PHY_AGCCOARSE_LO_S 7 +#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */ +#define AR5K_PHY_AGCCOARSE_HI_S 15 + +/* + * PHY agility control register + */ +#define AR5K_PHY_AGCCTL 0x9860 /* Register address */ +#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ +#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ +#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ +#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ + +/* + * PHY noise floor status register + */ +#define AR5K_PHY_NF 0x9864 /* Register address */ +#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ +#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ +#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) +#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) +#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) +#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ +#define AR5K_PHY_NF_THRESH62_S 12 +#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ +#define AR5K_PHY_NF_MINCCA_PWR_S 19 + +/* + * PHY ADC saturation register [5110] + */ +#define AR5K_PHY_ADCSAT 0x9868 +#define AR5K_PHY_ADCSAT_ICNT 0x0001f800 +#define AR5K_PHY_ADCSAT_ICNT_S 11 +#define AR5K_PHY_ADCSAT_THR 0x000007e0 +#define AR5K_PHY_ADCSAT_THR_S 5 + +/* + * PHY Weak ofdm signal detection threshold registers (ANI) [5212+] + */ + +/* High thresholds */ +#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24 + +/* Low thresholds */ +#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c +#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21 + + +/* + * PHY sleep registers [5112+] + */ +#define AR5K_PHY_SCR 0x9870 + +#define AR5K_PHY_SLMT 0x9874 +#define AR5K_PHY_SLMT_32MHZ 0x0000007f + +#define AR5K_PHY_SCAL 0x9878 +#define AR5K_PHY_SCAL_32MHZ 0x0000000e +#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a +#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 + +/* + * PHY PLL (Phase Locked Loop) control register + */ +#define AR5K_PHY_PLL 0x987c +#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */ +/* 40MHz -> 5GHz band */ +#define AR5K_PHY_PLL_40MHZ_5211 0x00000018 +#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa +#define AR5K_PHY_PLL_40MHZ_5413 0x00000004 +#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \ + AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212) +/* 44MHz -> 2.4GHz band */ +#define AR5K_PHY_PLL_44MHZ_5211 0x00000019 +#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab +#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \ + AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212) + +#define AR5K_PHY_PLL_RF5111 0x00000000 +#define AR5K_PHY_PLL_RF5112 0x00000040 +#define AR5K_PHY_PLL_HALF_RATE 0x00000100 +#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200 + +/* + * RF Buffer register + * + * It's obvious from the code that 0x989c is the buffer register but + * for the other special registers that we write to after sending each + * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers + * for now. It's interesting that they are also used for some other operations. + */ + +#define AR5K_RF_BUFFER 0x989c +#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */ +#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */ +#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */ + +#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */ + /* Channel set on 5111 */ + /* Used to read radio revision*/ + +#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */ + /* Bank 0,1,2,6 on 5111 */ + /* Bank 1 on 5112 */ + /* Used during activation on 5111 */ + +#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */ + /* Used during activation on 5111 */ + /* Channel on 5112 */ + /* Bank 6 on 5112 */ + +#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */ + +/* + * PHY RF stage register [5210] + */ +#define AR5K_PHY_RFSTG 0x98d4 +#define AR5K_PHY_RFSTG_DISABLE 0x00000021 + +/* + * BIN masks (?) + */ +#define AR5K_PHY_BIN_MASK_1 0x9900 +#define AR5K_PHY_BIN_MASK_2 0x9904 +#define AR5K_PHY_BIN_MASK_3 0x9908 + +#define AR5K_PHY_BIN_MASK_CTL 0x990c +#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff +#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0 +#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000 +#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24 + +/* + * PHY Antenna control register + */ +#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */ +#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */ +#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */ +#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */ +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */ +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4 + +/* + * PHY receiver delay register [5111+] + */ +#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */ +#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */ + +/* + * PHY max rx length register (?) [5111] + */ +#define AR5K_PHY_MAX_RX_LEN 0x991c + +/* + * PHY timing register 4 + * I(nphase)/Q(adrature) calibration register [5111+] + */ +#define AR5K_PHY_IQ 0x9920 /* Register Address */ +#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ +#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ +#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 +#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ +#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */ +#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12 +#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */ +#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */ +#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */ +#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */ +#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */ +#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */ +#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */ + +/* + * PHY timing register 5 + * OFDM Self-correlator Cyclic RSSI threshold params + * (Check out bb_cycpwr_thr1 on ANI patent) + */ +#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1 +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */ +#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */ +#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */ +#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */ + +/* + * PHY-only warm reset register + */ +#define AR5K_PHY_WARM_RESET 0x9928 + +/* + * PHY-only control register + */ +#define AR5K_PHY_CTL 0x992c /* Register Address */ +#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */ +#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */ +#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */ +#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */ +#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */ +#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */ +#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */ +#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */ + +/* + * PHY PAPD probe register [5111+] + */ +#define AR5K_PHY_PAPD_PROBE 0x9930 +#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001 +#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002 +#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040 +#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00 +#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9 +#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000 +#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000 +#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */ +#define AR5K_PHY_PAPD_PROBE_TYPE_S 23 +#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0 +#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1 +#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2 +#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000 +#define AR5K_PHY_PAPD_PROBE_GAINF_S 25 +#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */ +#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */ + +/* + * PHY TX rate power registers [5112+] + */ +#define AR5K_PHY_TXPOWER_RATE1 0x9934 +#define AR5K_PHY_TXPOWER_RATE2 0x9938 +#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c +#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040 +#define AR5K_PHY_TXPOWER_RATE3 0xa234 +#define AR5K_PHY_TXPOWER_RATE4 0xa238 + +/* + * PHY frame control register [5111+] + */ +#define AR5K_PHY_FRAME_CTL_5210 0x9804 +#define AR5K_PHY_FRAME_CTL_5211 0x9944 +#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ + AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) +/*---[5111+]---*/ +#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ +#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 +#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ +#define AR5K_PHY_FRAME_CTL_EMU 0x80000000 +#define AR5K_PHY_FRAME_CTL_EMU_S 31 +/*---[5110/5111]---*/ +#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */ +#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */ +#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */ +#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */ +#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000 +#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */ +#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ + AR5K_PHY_FRAME_CTL_TXURN_ERR | \ + AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ + AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \ + AR5K_PHY_FRAME_CTL_PARITY_ERR | \ + AR5K_PHY_FRAME_CTL_TIMING_ERR + +/* + * PHY Tx Power adjustment register [5212A+] + */ +#define AR5K_PHY_TX_PWR_ADJ 0x994c +#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0 +#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6 +#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000 +#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18 + +/* + * PHY radar detection register [5111+] + */ +#define AR5K_PHY_RADAR 0x9954 +#define AR5K_PHY_RADAR_ENABLE 0x00000001 +#define AR5K_PHY_RADAR_DISABLE 0x00000000 +#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold + 5-bits, units unknown {0..31} + (? MHz ?) */ +#define AR5K_PHY_RADAR_INBANDTHR_S 1 + +#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold + 6-bits, dBm range {0..63} + in dBm units. */ +#define AR5K_PHY_RADAR_PRSSI_THR_S 6 + +#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold + 6-bits, dBm range {0..63} + in dBm units. */ +#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12 + +#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold. + 6-bits, dBm range {0..63} + in dBm units. */ +#define AR5K_PHY_RADAR_RSSI_THR_S 18 + +#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response + filter power out threshold. + 7-bits, standard power range + {0..127} in 1/2 dBm units. */ +#define AR5K_PHY_RADAR_FIRPWR_THRS 24 + +/* + * PHY antenna switch table registers + */ +#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960 +#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964 + +/* + * PHY Noise floor threshold + */ +#define AR5K_PHY_NFTHRES 0x9968 + +/* + * Sigma Delta register (?) [5213] + */ +#define AR5K_PHY_SIGMA_DELTA 0x996C +#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 +#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0 +#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8 +#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3 +#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00 +#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8 +#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000 +#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +/* + * RF restart register [5112+] (?) + */ +#define AR5K_PHY_RESTART 0x9970 /* restart */ +#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */ +#define AR5K_PHY_RESTART_DIV_GC_S 18 + +/* + * RF Bus access request register (for synth-oly channel switching) + */ +#define AR5K_PHY_RFBUS_REQ 0x997C +#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001 + +/* + * Spur mitigation masks (?) + */ +#define AR5K_PHY_TIMING_7 0x9980 +#define AR5K_PHY_TIMING_8 0x9984 +#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff +#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0 + +#define AR5K_PHY_BIN_MASK2_1 0x9988 +#define AR5K_PHY_BIN_MASK2_2 0x998c +#define AR5K_PHY_BIN_MASK2_3 0x9990 + +#define AR5K_PHY_BIN_MASK2_4 0x9994 +#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff +#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0 + +#define AR5K_PHY_TIMING_9 0x9998 +#define AR5K_PHY_TIMING_10 0x999c +#define AR5K_PHY_TIMING_10_PILOT_MASK_2 0x000fffff +#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S 0 + +/* + * Spur mitigation control + */ +#define AR5K_PHY_TIMING_11 0x99a0 /* Register address */ +#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */ +#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0 +#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */ +#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S 20 +#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */ +#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */ + +/* + * Gain tables + */ +#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ +#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2)) +#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */ +#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2)) + +/* + * PHY timing IQ calibration result register [5111+] + */ +#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */ +#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */ +#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */ + +/* + * PHY current RSSI register [5111+] + */ +#define AR5K_PHY_CURRENT_RSSI 0x9c1c + +/* + * PHY RF Bus grant register + */ +#define AR5K_PHY_RFBUS_GRANT 0x9c20 +#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001 + +/* + * PHY ADC test register + */ +#define AR5K_PHY_ADC_TEST 0x9c24 +#define AR5K_PHY_ADC_TEST_I 0x00000001 +#define AR5K_PHY_ADC_TEST_Q 0x00000200 + +/* + * PHY DAC test register + */ +#define AR5K_PHY_DAC_TEST 0x9c28 +#define AR5K_PHY_DAC_TEST_I 0x00000001 +#define AR5K_PHY_DAC_TEST_Q 0x00000200 + +/* + * PHY PTAT register (?) + */ +#define AR5K_PHY_PTAT 0x9c2c + +/* + * PHY Illegal TX rate register [5112+] + */ +#define AR5K_PHY_BAD_TX_RATE 0x9c30 + +/* + * PHY SPUR Power register [5112+] + */ +#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */ +#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */ +#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */ +#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */ + +/* + * PHY Channel status register [5112+] (?) + */ +#define AR5K_PHY_CHAN_STATUS 0x9c38 +#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001 +#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002 +#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004 +#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008 + +/* + * Heavy clip enable register + */ +#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0 + +/* + * PHY clock sleep registers [5112+] + */ +#define AR5K_PHY_SCLOCK 0x99f0 +#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c +#define AR5K_PHY_SDELAY 0x99f4 +#define AR5K_PHY_SDELAY_32MHZ 0x000000ff +#define AR5K_PHY_SPENDING 0x99f8 + + +/* + * PHY PAPD I (power?) table (?) + * (92! entries) + */ +#define AR5K_PHY_PAPD_I_BASE 0xa000 +#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2)) + +/* + * PHY PCDAC TX power table + */ +#define AR5K_PHY_PCDAC_TXPOWER_BASE 0xa180 +#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2)) + +/* + * PHY mode register [5111+] + */ +#define AR5K_PHY_MODE 0x0a200 /* Register Address */ +#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */ +#define AR5K_PHY_MODE_MOD_OFDM 0 +#define AR5K_PHY_MODE_MOD_CCK 1 +#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */ +#define AR5K_PHY_MODE_FREQ_5GHZ 0 +#define AR5K_PHY_MODE_FREQ_2GHZ 2 +#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */ +#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */ +#define AR5K_PHY_MODE_RAD_RF5111 0 +#define AR5K_PHY_MODE_RAD_RF5112 8 +#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */ +#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */ +#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */ + +/* + * PHY CCK transmit control register [5111+ (?)] + */ +#define AR5K_PHY_CCKTXCTL 0xa204 +#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000 +#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010 +#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001 +#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004 + +/* + * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] + */ +#define AR5K_PHY_CCK_CROSSCORR 0xa208 +#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f +#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 + +/* Same address is used for antenna diversity activation */ +#define AR5K_PHY_FAST_ANT_DIV 0xa208 +#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000 + +/* + * PHY 2GHz gain register [5111+] + */ +#define AR5K_PHY_GAIN_2GHZ 0xa20c +#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 +#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18 +#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c + +#define AR5K_PHY_CCK_RX_CTL_4 0xa21c +#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000 +#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19 + +#define AR5K_PHY_DAG_CCK_CTL 0xa228 +#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200 +#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00 +#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10 + +#define AR5K_PHY_FAST_ADC 0xa24c + +#define AR5K_PHY_BLUETOOTH 0xa254 + +/* + * Transmit Power Control register + * [2413+] + */ +#define AR5K_PHY_TPC_RG1 0xa258 +#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000 +#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14 +#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000 +#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16 +#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000 +#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18 +#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000 +#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20 + +#define AR5K_PHY_TPC_RG5 0xa26C +#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F +#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22 + +/* + * PHY PDADC Tx power table + */ +#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 +#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c new file mode 100644 index 000000000000..775fdf78554b --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -0,0 +1,1346 @@ +/* + * Copyright (c) 2004-2008 Reyk Floeter + * Copyright (c) 2006-2008 Nick Kossifidis + * Copyright (c) 2007-2008 Luis Rodriguez + * Copyright (c) 2007-2008 Pavel Roskin + * Copyright (c) 2007-2008 Jiri Slaby + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#define _ATH5K_RESET + +/*****************************\ + Reset functions and helpers +\*****************************/ + +#include /* To determine if a card is pci-e */ +#include /* For get_bitmask_order */ +#include "ath5k.h" +#include "reg.h" +#include "base.h" +#include "debug.h" + +/** + * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 + * + * @ah: the &struct ath5k_hw + * @channel: the currently set channel upon reset + * + * Write the delta slope coefficient (used on pilot tracking ?) for OFDM + * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). + * + * Since delta slope is floating point we split it on its exponent and + * mantissa and provide these values on hw. + * + * For more infos i think this patent is related + * http://www.freepatentsonline.com/7184495.html + */ +static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + /* Get exponent and mantissa and set it */ + u32 coef_scaled, coef_exp, coef_man, + ds_coef_exp, ds_coef_man, clock; + + BUG_ON(!(ah->ah_version == AR5K_AR5212) || + !(channel->hw_value & CHANNEL_OFDM)); + + /* Get coefficient + * ALGO: coef = (5 * clock * carrier_freq) / 2) + * we scale coef by shifting clock value by 24 for + * better precision since we use integers */ + /* TODO: Half/quarter rate */ + clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); + + coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; + + /* Get exponent + * ALGO: coef_exp = 14 - highest set bit position */ + coef_exp = get_bitmask_order(coef_scaled); + + /* Doesn't make sense if it's zero*/ + if (!coef_exp) + return -EINVAL; + + /* Note: we've shifted coef_scaled by 24 */ + coef_exp = 14 - (coef_exp - 24); + + + /* Get mantissa (significant digits) + * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ + coef_man = coef_scaled + + (1 << (24 - coef_exp - 1)); + + /* Calculate delta slope coefficient exponent + * and mantissa (remove scaling) and set them on hw */ + ds_coef_man = coef_man >> (24 - coef_exp); + ds_coef_exp = coef_exp - 16; + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, + AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, + AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); + + return 0; +} + + +/* + * index into rates for control rates, we can set it up like this because + * this is only used for AR5212 and we know it supports G mode + */ +static const unsigned int control_rates[] = + { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; + +/** + * ath5k_hw_write_rate_duration - fill rate code to duration table + * + * @ah: the &struct ath5k_hw + * @mode: one of enum ath5k_driver_mode + * + * Write the rate code to duration table upon hw reset. This is a helper for + * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on + * the hardware, based on current mode, for each rate. The rates which are + * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have + * different rate code so we write their value twice (one for long preample + * and one for short). + * + * Note: Band doesn't matter here, if we set the values for OFDM it works + * on both a and g modes. So all we have to do is set values for all g rates + * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ + * quarter rate mode, we need to use another set of bitrates (that's why we + * need the mode parameter) but we don't handle these proprietary modes yet. + */ +static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, + unsigned int mode) +{ + struct ath5k_softc *sc = ah->ah_sc; + struct ieee80211_rate *rate; + unsigned int i; + + /* Write rate duration table */ + for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { + u32 reg; + u16 tx_time; + + rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; + + /* Set ACK timeout */ + reg = AR5K_RATE_DUR(rate->hw_value); + + /* An ACK frame consists of 10 bytes. If you add the FCS, + * which ieee80211_generic_frame_duration() adds, + * its 14 bytes. Note we use the control rate and not the + * actual rate for this rate. See mac80211 tx.c + * ieee80211_duration() for a brief description of + * what rate we should choose to TX ACKs. */ + tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, + sc->vif, 10, rate)); + + ath5k_hw_reg_write(ah, tx_time, reg); + + if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) + continue; + + /* + * We're not distinguishing short preamble here, + * This is true, all we'll get is a longer value here + * which is not necessarilly bad. We could use + * export ieee80211_frame_duration() but that needs to be + * fixed first to be properly used by mac802111 drivers: + * + * - remove erp stuff and let the routine figure ofdm + * erp rates + * - remove passing argument ieee80211_local as + * drivers don't have access to it + * - move drivers using ieee80211_generic_frame_duration() + * to this + */ + ath5k_hw_reg_write(ah, tx_time, + reg + (AR5K_SET_SHORT_PREAMBLE << 2)); + } +} + +/* + * Reset chipset + */ +static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) +{ + int ret; + u32 mask = val ? val : ~0U; + + ATH5K_TRACE(ah->ah_sc); + + /* Read-and-clear RX Descriptor Pointer*/ + ath5k_hw_reg_read(ah, AR5K_RXDP); + + /* + * Reset the device and wait until success + */ + ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); + + /* Wait at least 128 PCI clocks */ + udelay(15); + + if (ah->ah_version == AR5K_AR5210) { + val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA + | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; + mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA + | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; + } else { + val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; + mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; + } + + ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); + + /* + * Reset configuration register (for hw byte-swap). Note that this + * is only set for big endian. We do the necessary magic in + * AR5K_INIT_CFG. + */ + if ((val & AR5K_RESET_CTL_PCU) == 0) + ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); + + return ret; +} + +/* + * Sleep control + */ +int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, + bool set_chip, u16 sleep_duration) +{ + unsigned int i; + u32 staid, data; + + ATH5K_TRACE(ah->ah_sc); + staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); + + switch (mode) { + case AR5K_PM_AUTO: + staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; + /* fallthrough */ + case AR5K_PM_NETWORK_SLEEP: + if (set_chip) + ath5k_hw_reg_write(ah, + AR5K_SLEEP_CTL_SLE_ALLOW | + sleep_duration, + AR5K_SLEEP_CTL); + + staid |= AR5K_STA_ID1_PWR_SV; + break; + + case AR5K_PM_FULL_SLEEP: + if (set_chip) + ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, + AR5K_SLEEP_CTL); + + staid |= AR5K_STA_ID1_PWR_SV; + break; + + case AR5K_PM_AWAKE: + + staid &= ~AR5K_STA_ID1_PWR_SV; + + if (!set_chip) + goto commit; + + /* Preserve sleep duration */ + data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); + if (data & 0xffc00000) + data = 0; + else + data = data & 0xfffcffff; + + ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); + udelay(15); + + for (i = 50; i > 0; i--) { + /* Check if the chip did wake up */ + if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & + AR5K_PCICFG_SPWR_DN) == 0) + break; + + /* Wait a bit and retry */ + udelay(200); + ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); + } + + /* Fail if the chip didn't wake up */ + if (i <= 0) + return -EIO; + + break; + + default: + return -EINVAL; + } + +commit: + ah->ah_power_mode = mode; + ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); + + return 0; +} + +/* + * Bring up MAC + PHY Chips and program PLL + * TODO: Half/Quarter rate support + */ +int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) +{ + struct pci_dev *pdev = ah->ah_sc->pdev; + u32 turbo, mode, clock, bus_flags; + int ret; + + turbo = 0; + mode = 0; + clock = 0; + + ATH5K_TRACE(ah->ah_sc); + + /* Wakeup the device */ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); + return ret; + } + + if (ah->ah_version != AR5K_AR5210) { + /* + * Get channel mode flags + */ + + if (ah->ah_radio >= AR5K_RF5112) { + mode = AR5K_PHY_MODE_RAD_RF5112; + clock = AR5K_PHY_PLL_RF5112; + } else { + mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ + clock = AR5K_PHY_PLL_RF5111; /*Zero*/ + } + + if (flags & CHANNEL_2GHZ) { + mode |= AR5K_PHY_MODE_FREQ_2GHZ; + clock |= AR5K_PHY_PLL_44MHZ; + + if (flags & CHANNEL_CCK) { + mode |= AR5K_PHY_MODE_MOD_CCK; + } else if (flags & CHANNEL_OFDM) { + /* XXX Dynamic OFDM/CCK is not supported by the + * AR5211 so we set MOD_OFDM for plain g (no + * CCK headers) operation. We need to test + * this, 5211 might support ofdm-only g after + * all, there are also initial register values + * in the code for g mode (see initvals.c). */ + if (ah->ah_version == AR5K_AR5211) + mode |= AR5K_PHY_MODE_MOD_OFDM; + else + mode |= AR5K_PHY_MODE_MOD_DYN; + } else { + ATH5K_ERR(ah->ah_sc, + "invalid radio modulation mode\n"); + return -EINVAL; + } + } else if (flags & CHANNEL_5GHZ) { + mode |= AR5K_PHY_MODE_FREQ_5GHZ; + + if (ah->ah_radio == AR5K_RF5413) + clock = AR5K_PHY_PLL_40MHZ_5413; + else + clock |= AR5K_PHY_PLL_40MHZ; + + if (flags & CHANNEL_OFDM) + mode |= AR5K_PHY_MODE_MOD_OFDM; + else { + ATH5K_ERR(ah->ah_sc, + "invalid radio modulation mode\n"); + return -EINVAL; + } + } else { + ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); + return -EINVAL; + } + + if (flags & CHANNEL_TURBO) + turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; + } else { /* Reset the device */ + + /* ...enable Atheros turbo mode if requested */ + if (flags & CHANNEL_TURBO) + ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, + AR5K_PHY_TURBO); + } + + /* reseting PCI on PCI-E cards results card to hang + * and always return 0xffff... so we ingore that flag + * for PCI-E cards */ + bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + + /* Reset chipset */ + if (ah->ah_version == AR5K_AR5210) { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | + AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); + mdelay(2); + } else { + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); + } + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); + return -EIO; + } + + /* ...wakeup again!*/ + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); + if (ret) { + ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); + return ret; + } + + /* ...final warm reset */ + if (ath5k_hw_nic_reset(ah, 0)) { + ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); + return -EIO; + } + + if (ah->ah_version != AR5K_AR5210) { + + /* ...update PLL if needed */ + if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { + ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); + udelay(300); + } + + /* ...set the PHY operating mode */ + ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); + ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); + } + + return 0; +} + +/* + * If there is an external 32KHz crystal available, use it + * as ref. clock instead of 32/40MHz clock and baseband clocks + * to save power during sleep or restore normal 32/40MHz + * operation. + * + * XXX: When operating on 32KHz certain PHY registers (27 - 31, + * 123 - 127) require delay on access. + */ +static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 scal, spending, usec32; + + /* Only set 32KHz settings if we have an external + * 32KHz crystal present */ + if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || + AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && + enable) { + + /* 1 usec/cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); + /* Set up tsf increment on each cycle */ + AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); + + /* Set baseband sleep control registers + * and sleep control rate */ + ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + spending = 0x14; + else + spending = 0x18; + ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { + ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); + ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); + } else { + ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); + ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); + ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); + } + + /* Enable sleep clock operation */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_EN); + + } else { + + /* Disable sleep clock operation and + * restore default parameters */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_EN); + + AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, + AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); + + ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); + ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); + + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) + scal = AR5K_PHY_SCAL_32MHZ_2417; + else if (ath5k_eeprom_is_hb63(ah)) + scal = AR5K_PHY_SCAL_32MHZ_HB63; + else + scal = AR5K_PHY_SCAL_32MHZ; + ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); + + ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); + ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + spending = 0x14; + else + spending = 0x18; + ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413)) + usec32 = 39; + else + usec32 = 31; + AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); + + AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); + } + return; +} + +static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u8 refclk_freq; + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + refclk_freq = 40; + else + refclk_freq = 32; + + if ((channel->center_freq % refclk_freq != 0) && + ((channel->center_freq % refclk_freq < 10) || + (channel->center_freq % refclk_freq > 22))) + return true; + else + return false; +} + +/* TODO: Half/Quarter rate */ +static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + if (ah->ah_version == AR5K_AR5212 && + ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { + + /* Setup ADC control */ + ath5k_hw_reg_write(ah, + (AR5K_REG_SM(2, + AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) | + AR5K_REG_SM(2, + AR5K_PHY_ADC_CTL_INBUFGAIN_ON) | + AR5K_PHY_ADC_CTL_PWD_DAC_OFF | + AR5K_PHY_ADC_CTL_PWD_ADC_OFF), + AR5K_PHY_ADC_CTL); + + + + /* Disable barker RSSI threshold */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, + AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR); + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, + AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2); + + /* Set the mute mask */ + ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); + } + + /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */ + if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B) + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH); + + /* Enable DCU double buffering */ + if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B) + AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_DCU_DBL_BUF_DIS); + + /* Set DAC/ADC delays */ + if (ah->ah_version == AR5K_AR5212) { + u32 scal; + if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) + scal = AR5K_PHY_SCAL_32MHZ_2417; + else if (ath5k_eeprom_is_hb63(ah)) + scal = AR5K_PHY_SCAL_32MHZ_HB63; + else + scal = AR5K_PHY_SCAL_32MHZ; + ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); + } + + /* Set fast ADC */ + if ((ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { + u32 fast_adc = true; + + if (channel->center_freq == 2462 || + channel->center_freq == 2467) + fast_adc = 0; + + /* Only update if needed */ + if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc) + ath5k_hw_reg_write(ah, fast_adc, + AR5K_PHY_FAST_ADC); + } + + /* Fix for first revision of the RF5112 RF chipset */ + if (ah->ah_radio == AR5K_RF5112 && + ah->ah_radio_5ghz_revision < + AR5K_SREV_RAD_5112A) { + u32 data; + ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, + AR5K_PHY_CCKTXCTL); + if (channel->hw_value & CHANNEL_5GHZ) + data = 0xffb81020; + else + data = 0xffb80d20; + ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); + } + + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + u32 usec_reg; + /* 5311 has different tx/rx latency masks + * from 5211, since we deal 5311 the same + * as 5211 when setting initvals, shift + * values here to their proper locations */ + usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); + ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | + AR5K_USEC_32 | + AR5K_USEC_TX_LATENCY_5211 | + AR5K_REG_SM(29, + AR5K_USEC_RX_LATENCY_5210)), + AR5K_USEC_5211); + /* Clear QCU/DCU clock gating register */ + ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); + /* Set DAC/ADC delays */ + ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); + /* Enable PCU FIFO corruption ECO */ + AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, + AR5K_DIAG_SW_ECO_ENABLE); + } +} + +static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, + struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + s16 cck_ofdm_pwr_delta; + + /* Adjust power delta for channel 14 */ + if (channel->center_freq == 2484) + cck_ofdm_pwr_delta = + ((ee->ee_cck_ofdm_power_delta - + ee->ee_scaled_cck_delta) * 2) / 10; + else + cck_ofdm_pwr_delta = + (ee->ee_cck_ofdm_power_delta * 2) / 10; + + /* Set CCK to OFDM power delta on tx power + * adjustment register */ + if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { + if (channel->hw_value == CHANNEL_G) + ath5k_hw_reg_write(ah, + AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), + AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | + AR5K_REG_SM((cck_ofdm_pwr_delta * -1), + AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), + AR5K_PHY_TX_PWR_ADJ); + else + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); + } else { + /* For older revs we scale power on sw during tx power + * setup */ + ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta; + ah->ah_txpower.txp_cck_ofdm_gainf_delta = + ee->ee_cck_ofdm_gain_delta; + } + + /* Set antenna idle switch table */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, + AR5K_PHY_ANT_CTL_SWTABLE_IDLE, + (ah->ah_antenna[ee_mode][0] | + AR5K_PHY_ANT_CTL_TXRX_EN)); + + /* Set antenna switch table */ + ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], + AR5K_PHY_ANT_SWITCH_TABLE_0); + ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], + AR5K_PHY_ANT_SWITCH_TABLE_1); + + /* Noise floor threshold */ + ath5k_hw_reg_write(ah, + AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), + AR5K_PHY_NFTHRES); + + if ((channel->hw_value & CHANNEL_TURBO) && + (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { + /* Switch settling time (Turbo) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, + AR5K_PHY_SETTLING_SWITCH, + ee->ee_switch_settling_turbo[ee_mode]); + + /* Tx/Rx attenuation (Turbo) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, + AR5K_PHY_GAIN_TXRX_ATTEN, + ee->ee_atn_tx_rx_turbo[ee_mode]); + + /* ADC/PGA desired size (Turbo) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, + AR5K_PHY_DESIRED_SIZE_ADC, + ee->ee_adc_desired_size_turbo[ee_mode]); + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, + AR5K_PHY_DESIRED_SIZE_PGA, + ee->ee_pga_desired_size_turbo[ee_mode]); + + /* Tx/Rx margin (Turbo) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, + AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, + ee->ee_margin_tx_rx_turbo[ee_mode]); + + } else { + /* Switch settling time */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, + AR5K_PHY_SETTLING_SWITCH, + ee->ee_switch_settling[ee_mode]); + + /* Tx/Rx attenuation */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, + AR5K_PHY_GAIN_TXRX_ATTEN, + ee->ee_atn_tx_rx[ee_mode]); + + /* ADC/PGA desired size */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, + AR5K_PHY_DESIRED_SIZE_ADC, + ee->ee_adc_desired_size[ee_mode]); + + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, + AR5K_PHY_DESIRED_SIZE_PGA, + ee->ee_pga_desired_size[ee_mode]); + + /* Tx/Rx margin */ + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, + AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, + ee->ee_margin_tx_rx[ee_mode]); + } + + /* XPA delays */ + ath5k_hw_reg_write(ah, + (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | + (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | + (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | + (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); + + /* XLNA delay */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3, + AR5K_PHY_RF_CTL3_TXE2XLNA_ON, + ee->ee_tx_end2xlna_enable[ee_mode]); + + /* Thresh64 (ANI) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF, + AR5K_PHY_NF_THRESH62, + ee->ee_thr_62[ee_mode]); + + + /* False detect backoff for channels + * that have spur noise. Write the new + * cyclic power RSSI threshold. */ + if (ath5k_hw_chan_has_spur_noise(ah, channel)) + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, + AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, + AR5K_INIT_CYCRSSI_THR1 + + ee->ee_false_detect[ee_mode]); + else + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, + AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, + AR5K_INIT_CYCRSSI_THR1); + + /* I/Q correction + * TODO: Per channel i/q infos ? */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CORR_ENABLE | + (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | + ee->ee_q_cal[ee_mode]); + + /* Heavy clipping -disable for now */ + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) + ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); + + return; +} + +/* + * Main reset function + */ +int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + struct ieee80211_channel *channel, bool change_channel) +{ + u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; + u32 phy_tst1; + u8 mode, freq, ee_mode, ant[2]; + int i, ret; + + ATH5K_TRACE(ah->ah_sc); + + s_ant = 0; + ee_mode = 0; + staid1_flags = 0; + tsf_up = 0; + tsf_lo = 0; + freq = 0; + mode = 0; + + /* + * Save some registers before a reset + */ + /*DCU/Antenna selection not available on 5210*/ + if (ah->ah_version != AR5K_AR5210) { + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + mode = AR5K_MODE_11A; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + mode = AR5K_MODE_11G; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_B: + mode = AR5K_MODE_11B; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11B; + break; + case CHANNEL_T: + mode = AR5K_MODE_11A_TURBO; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_TG: + if (ah->ah_version == AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "TurboG mode not available on 5211"); + return -EINVAL; + } + mode = AR5K_MODE_11G_TURBO; + freq = AR5K_INI_RFGAIN_2GHZ; + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_XR: + if (ah->ah_version == AR5K_AR5211) { + ATH5K_ERR(ah->ah_sc, + "XR mode not available on 5211"); + return -EINVAL; + } + mode = AR5K_MODE_XR; + freq = AR5K_INI_RFGAIN_5GHZ; + ee_mode = AR5K_EEPROM_MODE_11A; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } + + if (change_channel) { + /* + * Save frame sequence count + * For revs. after Oahu, only save + * seq num for DCU 0 (Global seq num) + */ + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + + for (i = 0; i < 10; i++) + s_seq[i] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(i)); + + } else { + s_seq[0] = ath5k_hw_reg_read(ah, + AR5K_QUEUE_DCU_SEQNUM(0)); + } + + /* TSF accelerates on AR5211 durring reset + * As a workaround save it here and restore + * it later so that it's back in time after + * reset. This way it'll get re-synced on the + * next beacon without breaking ad-hoc. + * + * On AR5212 TSF is almost preserved across a + * reset so it stays back in time anyway and + * we don't have to save/restore it. + * + * XXX: Since this breaks power saving we have + * to disable power saving until we receive the + * next beacon, so we can resync beacon timers */ + if (ah->ah_version == AR5K_AR5211) { + tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); + tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); + } + } + + /* Save default antenna */ + s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); + + if (ah->ah_version == AR5K_AR5212) { + /* Restore normal 32/40MHz clock operation + * to avoid register access delay on certain + * PHY registers */ + ath5k_hw_set_sleep_clock(ah, false); + + /* Since we are going to write rf buffer + * check if we have any pending gain_F + * optimization settings */ + if (change_channel && ah->ah_rf_banks != NULL) + ath5k_hw_gainf_calibrate(ah); + } + } + + /*GPIOs*/ + s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & + AR5K_PCICFG_LEDSTATE; + s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); + s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); + + /* AR5K_STA_ID1 flags, only preserve antenna + * settings and ack/cts rate mode */ + staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & + (AR5K_STA_ID1_DEFAULT_ANTENNA | + AR5K_STA_ID1_DESC_ANTENNA | + AR5K_STA_ID1_RTS_DEF_ANTENNA | + AR5K_STA_ID1_ACKCTS_6MB | + AR5K_STA_ID1_BASE_RATE_11B | + AR5K_STA_ID1_SELFGEN_DEF_ANT); + + /* Wakeup the device */ + ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); + if (ret) + return ret; + + /* + * Initialize operating mode + */ + ah->ah_op_mode = op_mode; + + /* PHY access enable */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5211) + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); + else + ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40, + AR5K_PHY(0)); + + /* Write initial settings */ + ret = ath5k_hw_write_initvals(ah, mode, change_channel); + if (ret) + return ret; + + /* + * 5211/5212 Specific + */ + if (ah->ah_version != AR5K_AR5210) { + + /* + * Write initial RF gain settings + * This should work for both 5111/5112 + */ + ret = ath5k_hw_rfgain_init(ah, freq); + if (ret) + return ret; + + mdelay(1); + + /* + * Tweak initval settings for revised + * chipsets and add some more config + * bits + */ + ath5k_hw_tweak_initval_settings(ah, channel); + + /* + * Set TX power (FIXME) + */ + ret = ath5k_hw_txpower(ah, channel, ee_mode, + AR5K_TUNE_DEFAULT_TXPOWER); + if (ret) + return ret; + + /* Write rate duration table only on AR5212 and if + * virtual interface has already been brought up + * XXX: rethink this after new mode changes to + * mac80211 are integrated */ + if (ah->ah_version == AR5K_AR5212 && + ah->ah_sc->vif != NULL) + ath5k_hw_write_rate_duration(ah, mode); + + /* + * Write RF buffer + */ + ret = ath5k_hw_rfregs_init(ah, channel, mode); + if (ret) + return ret; + + + /* Write OFDM timings on 5212*/ + if (ah->ah_version == AR5K_AR5212 && + channel->hw_value & CHANNEL_OFDM) { + ret = ath5k_hw_write_ofdm_timings(ah, channel); + if (ret) + return ret; + } + + /*Enable/disable 802.11b mode on 5111 + (enable 2111 frequency converter + CCK)*/ + if (ah->ah_radio == AR5K_RF5111) { + if (mode == AR5K_MODE_11B) + AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_B_MODE); + else + AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_B_MODE); + } + + /* + * In case a fixed antenna was set as default + * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE + * registers. + */ + if (s_ant != 0) { + if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ + ant[0] = ant[1] = AR5K_ANT_FIXED_A; + else /* 2 - Aux */ + ant[0] = ant[1] = AR5K_ANT_FIXED_B; + } else { + ant[0] = AR5K_ANT_FIXED_A; + ant[1] = AR5K_ANT_FIXED_B; + } + + /* Commit values from EEPROM */ + ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode); + + } else { + /* + * For 5210 we do all initialization using + * initvals, so we don't have to modify + * any settings (5210 also only supports + * a/aturbo modes) + */ + mdelay(1); + /* Disable phy and wait */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); + mdelay(1); + } + + /* + * Restore saved values + */ + + /*DCU/Antenna selection not available on 5210*/ + if (ah->ah_version != AR5K_AR5210) { + + if (change_channel) { + if (ah->ah_mac_srev < AR5K_SREV_AR5211) { + for (i = 0; i < 10; i++) + ath5k_hw_reg_write(ah, s_seq[i], + AR5K_QUEUE_DCU_SEQNUM(i)); + } else { + ath5k_hw_reg_write(ah, s_seq[0], + AR5K_QUEUE_DCU_SEQNUM(0)); + } + + + if (ah->ah_version == AR5K_AR5211) { + ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); + ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); + } + } + + ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); + } + + /* Ledstate */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); + + /* Gpio settings */ + ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); + ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); + + /* Restore sta_id flags and preserve our mac address*/ + ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id), + AR5K_STA_ID0); + ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id), + AR5K_STA_ID1); + + + /* + * Configure PCU + */ + + /* Restore bssid and bssid mask */ + /* XXX: add ah->aid once mac80211 gives this to us */ + ath5k_hw_set_associd(ah, ah->ah_bssid, 0); + + /* Set PCU config */ + ath5k_hw_set_opmode(ah); + + /* Clear any pending interrupts + * PISR/SISR Not available on 5210 */ + if (ah->ah_version != AR5K_AR5210) + ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); + + /* Set RSSI/BRSSI thresholds + * + * Note: If we decide to set this value + * dynamicaly, have in mind that when AR5K_RSSI_THR + * register is read it might return 0x40 if we haven't + * wrote anything to it plus BMISS RSSI threshold is zeroed. + * So doing a save/restore procedure here isn't the right + * choice. Instead store it on ath5k_hw */ + ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | + AR5K_TUNE_BMISS_THRES << + AR5K_RSSI_THR_BMISS_S), + AR5K_RSSI_THR); + + /* MIC QoS support */ + if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { + ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); + ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); + } + + /* QoS NOACK Policy */ + if (ah->ah_version == AR5K_AR5212) { + ath5k_hw_reg_write(ah, + AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | + AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | + AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), + AR5K_QOS_NOACK); + } + + + /* + * Configure PHY + */ + + /* Set channel on PHY */ + ret = ath5k_hw_channel(ah, channel); + if (ret) + return ret; + + /* + * Enable the PHY and wait until completion + * This includes BaseBand and Synthesizer + * activation. + */ + ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); + + /* + * On 5211+ read activation -> rx delay + * and use it. + * + * TODO: Half/quarter rate support + */ + if (ah->ah_version != AR5K_AR5210) { + u32 delay; + delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & + AR5K_PHY_RX_DELAY_M; + delay = (channel->hw_value & CHANNEL_CCK) ? + ((delay << 2) / 22) : (delay / 10); + + udelay(100 + (2 * delay)); + } else { + mdelay(1); + } + + /* + * Perform ADC test to see if baseband is ready + * Set tx hold and check adc test register + */ + phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); + ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); + for (i = 0; i <= 20; i++) { + if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) + break; + udelay(200); + } + ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); + + /* + * Start automatic gain control calibration + * + * During AGC calibration RX path is re-routed to + * a power detector so we don't receive anything. + * + * This method is used to calibrate some static offsets + * used together with on-the fly I/Q calibration (the + * one performed via ath5k_hw_phy_calibrate), that doesn't + * interrupt rx path. + * + * While rx path is re-routed to the power detector we also + * start a noise floor calibration, to measure the + * card's noise floor (the noise we measure when we are not + * transmiting or receiving anything). + * + * If we are in a noisy environment AGC calibration may time + * out and/or noise floor calibration might timeout. + */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL); + + /* At the same time start I/Q calibration for QAM constellation + * -no need for CCK- */ + ah->ah_calibration = false; + if (!(mode == AR5K_MODE_11B)) { + ah->ah_calibration = true; + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_RUN); + } + + /* Wait for gain calibration to finish (we check for I/Q calibration + * during ath5k_phy_calibrate) */ + if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL, 0, false)) { + ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", + channel->center_freq); + } + + /* + * If we run NF calibration before AGC, it always times out. + * Binary HAL starts NF and AGC calibration at the same time + * and only waits for AGC to finish. Also if AGC or NF cal. + * times out, reset doesn't fail on binary HAL. I believe + * that's wrong because since rx path is routed to a detector, + * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211 + * enables noise floor calibration after offset calibration and if noise + * floor calibration fails, reset fails. I believe that's + * a better approach, we just need to find a polling interval + * that suits best, even if reset continues we need to make + * sure that rx path is ready. + */ + ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + + + /* + * Configure QCUs/DCUs + */ + + /* TODO: HW Compression support for data queues */ + /* TODO: Burst prefetch for data queues */ + + /* + * Reset queues and start beacon timers at the end of the reset routine + * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping + * Note: If we want we can assign multiple qcus on one dcu. + */ + for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { + ret = ath5k_hw_reset_tx_queue(ah, i); + if (ret) { + ATH5K_ERR(ah->ah_sc, + "failed to reset TX queue #%d\n", i); + return ret; + } + } + + + /* + * Configure DMA/Interrupts + */ + + /* + * Set Rx/Tx DMA Configuration + * + * Set standard DMA size (128). Note that + * a DMA size of 512 causes rx overruns and tx errors + * on pci-e cards (tested on 5424 but since rx overruns + * also occur on 5416/5418 with madwifi we set 128 + * for all PCI-E cards to be safe). + * + * XXX: need to check 5210 for this + * TODO: Check out tx triger level, it's always 64 on dumps but I + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); + } + + /* Pre-enable interrupts on 5211/5212*/ + if (ah->ah_version != AR5K_AR5210) + ath5k_hw_set_imr(ah, ah->ah_imr); + + /* + * Setup RFKill interrupt if rfkill flag is set on eeprom. + * TODO: Use gpio pin and polarity infos from eeprom + * TODO: Handle this in ath5k_intr because it'll result + * a nasty interrupt storm. + */ +#if 0 + if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { + ath5k_hw_set_gpio_input(ah, 0); + ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0); + if (ah->ah_gpio[0] == 0) + ath5k_hw_set_gpio_intr(ah, 0, 1); + else + ath5k_hw_set_gpio_intr(ah, 0, 0); + } +#endif + + /* Enable 32KHz clock function for AR5212+ chips + * Set clocks to 32KHz operation and use an + * external 32KHz crystal when sleeping if one + * exists */ + if (ah->ah_version == AR5K_AR5212) + ath5k_hw_set_sleep_clock(ah, true); + + /* + * Disable beacons and reset the register + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | + AR5K_BEACON_RESET_TSF); + + return 0; +} + +#undef _ATH5K_RESET diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h new file mode 100644 index 000000000000..e50baff66175 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h @@ -0,0 +1,1181 @@ +/* + * RF Buffer handling functions + * + * Copyright (c) 2009 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + + +/* + * There are some special registers on the RF chip + * that control various operation settings related mostly to + * the analog parts (channel, gain adjustment etc). + * + * We don't write on those registers directly but + * we send a data packet on the chip, using a special register, + * that holds all the settings we need. After we 've sent the + * data packet, we write on another special register to notify hw + * to apply the settings. This is done so that control registers + * can be dynamicaly programmed during operation and the settings + * are applied faster on the hw. + * + * We call each data packet an "RF Bank" and all the data we write + * (all RF Banks) "RF Buffer". This file holds initial RF Buffer + * data for the different RF chips, and various info to match RF + * Buffer offsets with specific RF registers so that we can access + * them. We tweak these settings on rfregs_init function. + * + * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer + * registers and control registers): + * + * http://www.google.com/patents?id=qNURAAAAEBAJ + */ + + +/* + * Struct to hold default mode specific RF + * register values (RF Banks) + */ +struct ath5k_ini_rfbuffer { + u8 rfb_bank; /* RF Bank number */ + u16 rfb_ctrl_register; /* RF Buffer control register */ + u32 rfb_mode_data[5]; /* RF Buffer data for each mode */ +}; + +/* + * Struct to hold RF Buffer field + * infos used to access certain RF + * analog registers + */ +struct ath5k_rfb_field { + u8 len; /* Field length */ + u16 pos; /* Offset on the raw packet */ + u8 col; /* Column -used for shifting */ +}; + +/* + * RF analog register definition + */ +struct ath5k_rf_reg { + u8 bank; /* RF Buffer Bank number */ + u8 index; /* Register's index on rf_regs_idx */ + struct ath5k_rfb_field field; /* RF Buffer field for this register */ +}; + +/* Map RF registers to indexes + * We do this to handle common bits and make our + * life easier by using an index for each register + * instead of a full rfb_field */ +enum ath5k_rf_regs_idx { + /* BANK 6 */ + AR5K_RF_OB_2GHZ = 0, + AR5K_RF_OB_5GHZ, + AR5K_RF_DB_2GHZ, + AR5K_RF_DB_5GHZ, + AR5K_RF_FIXED_BIAS_A, + AR5K_RF_FIXED_BIAS_B, + AR5K_RF_PWD_XPD, + AR5K_RF_XPD_SEL, + AR5K_RF_XPD_GAIN, + AR5K_RF_PD_GAIN_LO, + AR5K_RF_PD_GAIN_HI, + AR5K_RF_HIGH_VC_CP, + AR5K_RF_MID_VC_CP, + AR5K_RF_LOW_VC_CP, + AR5K_RF_PUSH_UP, + AR5K_RF_PAD2GND, + AR5K_RF_XB2_LVL, + AR5K_RF_XB5_LVL, + AR5K_RF_PWD_ICLOBUF_2G, + AR5K_RF_PWD_84, + AR5K_RF_PWD_90, + AR5K_RF_PWD_130, + AR5K_RF_PWD_131, + AR5K_RF_PWD_132, + AR5K_RF_PWD_136, + AR5K_RF_PWD_137, + AR5K_RF_PWD_138, + AR5K_RF_PWD_166, + AR5K_RF_PWD_167, + AR5K_RF_DERBY_CHAN_SEL_MODE, + /* BANK 7 */ + AR5K_RF_GAIN_I, + AR5K_RF_PLO_SEL, + AR5K_RF_RFGAIN_SEL, + AR5K_RF_RFGAIN_STEP, + AR5K_RF_WAIT_S, + AR5K_RF_WAIT_I, + AR5K_RF_MAX_TIME, + AR5K_RF_MIXVGA_OVR, + AR5K_RF_MIXGAIN_OVR, + AR5K_RF_MIXGAIN_STEP, + AR5K_RF_PD_DELAY_A, + AR5K_RF_PD_DELAY_B, + AR5K_RF_PD_DELAY_XR, + AR5K_RF_PD_PERIOD_A, + AR5K_RF_PD_PERIOD_B, + AR5K_RF_PD_PERIOD_XR, +}; + + +/*******************\ +* RF5111 (Sombrero) * +\*******************/ + +/* BANK 6 len pos col */ +#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } +#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } + +#define AR5K_RF5111_OB_5GHZ { 3, 104, 0 } +#define AR5K_RF5111_DB_5GHZ { 3, 107, 0 } + +#define AR5K_RF5111_PWD_XPD { 1, 95, 0 } +#define AR5K_RF5111_XPD_GAIN { 4, 96, 0 } + +/* Access to PWD registers */ +#define AR5K_RF5111_PWD(_n) { 1, (135 - _n), 3 } + +/* BANK 7 len pos col */ +#define AR5K_RF5111_GAIN_I { 6, 29, 0 } +#define AR5K_RF5111_PLO_SEL { 1, 4, 0 } +#define AR5K_RF5111_RFGAIN_SEL { 1, 36, 0 } +#define AR5K_RF5111_RFGAIN_STEP { 6, 37, 0 } +/* Only on AR5212 BaseBand and up */ +#define AR5K_RF5111_WAIT_S { 5, 19, 0 } +#define AR5K_RF5111_WAIT_I { 5, 24, 0 } +#define AR5K_RF5111_MAX_TIME { 2, 49, 0 } + +static const struct ath5k_rf_reg rf_regs_5111[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, + {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, + {6, AR5K_RF_DB_5GHZ, AR5K_RF5111_DB_5GHZ}, + {6, AR5K_RF_PWD_XPD, AR5K_RF5111_PWD_XPD}, + {6, AR5K_RF_XPD_GAIN, AR5K_RF5111_XPD_GAIN}, + {6, AR5K_RF_PWD_84, AR5K_RF5111_PWD(84)}, + {6, AR5K_RF_PWD_90, AR5K_RF5111_PWD(90)}, + {7, AR5K_RF_GAIN_I, AR5K_RF5111_GAIN_I}, + {7, AR5K_RF_PLO_SEL, AR5K_RF5111_PLO_SEL}, + {7, AR5K_RF_RFGAIN_SEL, AR5K_RF5111_RFGAIN_SEL}, + {7, AR5K_RF_RFGAIN_STEP, AR5K_RF5111_RFGAIN_STEP}, + {7, AR5K_RF_WAIT_S, AR5K_RF5111_WAIT_S}, + {7, AR5K_RF_WAIT_I, AR5K_RF5111_WAIT_I}, + {7, AR5K_RF_MAX_TIME, AR5K_RF5111_MAX_TIME} +}; + +/* Default mode specific settings */ +static const struct ath5k_ini_rfbuffer rfb_5111[] = { + { 0, 0x989c, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 0, 0x989c, + { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, + { 0, 0x989c, + { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, + { 0, 0x98d4, + { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, + { 1, 0x98d4, + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d4, + { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, + { 3, 0x98d8, + { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, + { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, + { 6, 0x989c, + { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, + { 6, 0x989c, + { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, + { 6, 0x989c, + { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, + { 6, 0x989c, + { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, + { 6, 0x98d4, + { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, + { 7, 0x989c, + { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, + { 7, 0x989c, + { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, + { 7, 0x989c, + { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, + { 7, 0x989c, + { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, + { 7, 0x989c, + { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, + { 7, 0x989c, + { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, + { 7, 0x989c, + { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, +}; + + + +/***********************\ +* RF5112/RF2112 (Derby) * +\***********************/ + +/* BANK 7 (Common) len pos col */ +#define AR5K_RF5112X_GAIN_I { 6, 14, 0 } +#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } +#define AR5K_RF5112X_MIXGAIN_OVR { 2, 37, 0 } +#define AR5K_RF5112X_MIXGAIN_STEP { 4, 32, 0 } +#define AR5K_RF5112X_PD_DELAY_A { 4, 58, 0 } +#define AR5K_RF5112X_PD_DELAY_B { 4, 62, 0 } +#define AR5K_RF5112X_PD_DELAY_XR { 4, 66, 0 } +#define AR5K_RF5112X_PD_PERIOD_A { 4, 70, 0 } +#define AR5K_RF5112X_PD_PERIOD_B { 4, 74, 0 } +#define AR5K_RF5112X_PD_PERIOD_XR { 4, 78, 0 } + +/* RFX112 (Derby 1) */ + +/* BANK 6 len pos col */ +#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 } +#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 } + +#define AR5K_RF5112_OB_5GHZ { 3, 261, 0 } +#define AR5K_RF5112_DB_5GHZ { 3, 264, 0 } + +#define AR5K_RF5112_FIXED_BIAS_A { 1, 260, 0 } +#define AR5K_RF5112_FIXED_BIAS_B { 1, 259, 0 } + +#define AR5K_RF5112_XPD_SEL { 1, 284, 0 } +#define AR5K_RF5112_XPD_GAIN { 2, 252, 0 } + +/* Access to PWD registers */ +#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } + +static const struct ath5k_rf_reg rf_regs_5112[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, + {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, + {6, AR5K_RF_DB_5GHZ, AR5K_RF5112_DB_5GHZ}, + {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112_FIXED_BIAS_A}, + {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112_FIXED_BIAS_B}, + {6, AR5K_RF_XPD_SEL, AR5K_RF5112_XPD_SEL}, + {6, AR5K_RF_XPD_GAIN, AR5K_RF5112_XPD_GAIN}, + {6, AR5K_RF_PWD_130, AR5K_RF5112_PWD(130)}, + {6, AR5K_RF_PWD_131, AR5K_RF5112_PWD(131)}, + {6, AR5K_RF_PWD_132, AR5K_RF5112_PWD(132)}, + {6, AR5K_RF_PWD_136, AR5K_RF5112_PWD(136)}, + {6, AR5K_RF_PWD_137, AR5K_RF5112_PWD(137)}, + {6, AR5K_RF_PWD_138, AR5K_RF5112_PWD(138)}, + {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I}, + {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR}, + {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR}, + {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP}, + {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A}, + {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B}, + {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR}, + {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A}, + {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B}, + {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR}, +}; + +/* Default mode specific settings */ +static const struct ath5k_ini_rfbuffer rfb_5112[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, + { 3, 0x98dc, + { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, + { 6, 0x989c, + { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, + { 6, 0x989c, + { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, + { 6, 0x989c, + { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, + { 6, 0x989c, + { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, + { 6, 0x989c, + { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, + { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, + { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, + { 6, 0x989c, + { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, + { 6, 0x989c, + { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, + { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, + { 6, 0x989c, + { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, + { 6, 0x989c, + { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, + { 6, 0x989c, + { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, + { 6, 0x989c, + { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, + { 6, 0x989c, + { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, + { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, + { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, + { 6, 0x989c, + { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, + { 6, 0x989c, + { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, + { 6, 0x989c, + { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, + { 6, 0x989c, + { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, + { 6, 0x989c, + { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, + { 6, 0x989c, + { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, + { 6, 0x989c, + { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, + { 6, 0x989c, + { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, + { 6, 0x989c, + { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, + { 6, 0x989c, + { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, + { 6, 0x989c, + { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, + { 6, 0x989c, + { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, + { 6, 0x98d0, + { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, + { 7, 0x989c, + { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, + { 7, 0x989c, + { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, + { 7, 0x989c, + { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, + { 7, 0x989c, + { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, + { 7, 0x989c, + { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, + { 7, 0x989c, + { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, + { 7, 0x989c, + { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, + { 7, 0x989c, + { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, + { 7, 0x989c, + { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, + { 7, 0x989c, + { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, + { 7, 0x989c, + { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, + { 7, 0x989c, + { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, + { 7, 0x98c4, + { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, +}; + +/* RFX112A (Derby 2) */ + +/* BANK 6 len pos col */ +#define AR5K_RF5112A_OB_2GHZ { 3, 287, 0 } +#define AR5K_RF5112A_DB_2GHZ { 3, 290, 0 } + +#define AR5K_RF5112A_OB_5GHZ { 3, 279, 0 } +#define AR5K_RF5112A_DB_5GHZ { 3, 282, 0 } + +#define AR5K_RF5112A_FIXED_BIAS_A { 1, 278, 0 } +#define AR5K_RF5112A_FIXED_BIAS_B { 1, 277, 0 } + +#define AR5K_RF5112A_XPD_SEL { 1, 302, 0 } +#define AR5K_RF5112A_PDGAINLO { 2, 270, 0 } +#define AR5K_RF5112A_PDGAINHI { 2, 257, 0 } + +/* Access to PWD registers */ +#define AR5K_RF5112A_PWD(_n) { 1, (306 - _n), 3 } + +/* Voltage regulators */ +#define AR5K_RF5112A_HIGH_VC_CP { 2, 90, 2 } +#define AR5K_RF5112A_MID_VC_CP { 2, 92, 2 } +#define AR5K_RF5112A_LOW_VC_CP { 2, 94, 2 } +#define AR5K_RF5112A_PUSH_UP { 1, 254, 2 } + +/* Power consumption */ +#define AR5K_RF5112A_PAD2GND { 1, 281, 1 } +#define AR5K_RF5112A_XB2_LVL { 2, 1, 3 } +#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } + +static const struct ath5k_rf_reg rf_regs_5112a[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, + {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, + {6, AR5K_RF_DB_5GHZ, AR5K_RF5112A_DB_5GHZ}, + {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112A_FIXED_BIAS_A}, + {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112A_FIXED_BIAS_B}, + {6, AR5K_RF_XPD_SEL, AR5K_RF5112A_XPD_SEL}, + {6, AR5K_RF_PD_GAIN_LO, AR5K_RF5112A_PDGAINLO}, + {6, AR5K_RF_PD_GAIN_HI, AR5K_RF5112A_PDGAINHI}, + {6, AR5K_RF_PWD_130, AR5K_RF5112A_PWD(130)}, + {6, AR5K_RF_PWD_131, AR5K_RF5112A_PWD(131)}, + {6, AR5K_RF_PWD_132, AR5K_RF5112A_PWD(132)}, + {6, AR5K_RF_PWD_136, AR5K_RF5112A_PWD(136)}, + {6, AR5K_RF_PWD_137, AR5K_RF5112A_PWD(137)}, + {6, AR5K_RF_PWD_138, AR5K_RF5112A_PWD(138)}, + {6, AR5K_RF_PWD_166, AR5K_RF5112A_PWD(166)}, + {6, AR5K_RF_PWD_167, AR5K_RF5112A_PWD(167)}, + {6, AR5K_RF_HIGH_VC_CP, AR5K_RF5112A_HIGH_VC_CP}, + {6, AR5K_RF_MID_VC_CP, AR5K_RF5112A_MID_VC_CP}, + {6, AR5K_RF_LOW_VC_CP, AR5K_RF5112A_LOW_VC_CP}, + {6, AR5K_RF_PUSH_UP, AR5K_RF5112A_PUSH_UP}, + {6, AR5K_RF_PAD2GND, AR5K_RF5112A_PAD2GND}, + {6, AR5K_RF_XB2_LVL, AR5K_RF5112A_XB2_LVL}, + {6, AR5K_RF_XB5_LVL, AR5K_RF5112A_XB5_LVL}, + {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I}, + {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR}, + {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR}, + {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP}, + {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A}, + {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B}, + {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR}, + {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A}, + {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B}, + {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR}, +}; + +/* Default mode specific settings */ +static const struct ath5k_ini_rfbuffer rfb_5112a[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, + { 3, 0x98dc, + { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, + { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, + { 6, 0x989c, + { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, + { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, + { 6, 0x989c, + { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, + { 6, 0x989c, + { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, + { 6, 0x989c, + { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, + { 6, 0x989c, + { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, + { 6, 0x989c, + { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } }, + { 6, 0x989c, + { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, + { 6, 0x989c, + { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, + { 6, 0x989c, + { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, + { 6, 0x989c, + { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, + { 6, 0x989c, + { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, + { 6, 0x989c, + { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, + { 6, 0x989c, + { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, + { 6, 0x989c, + { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, + { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, + { 6, 0x989c, + { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, + { 6, 0x989c, + { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, + { 6, 0x989c, + { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, + { 6, 0x989c, + { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, + { 6, 0x989c, + { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, + { 6, 0x989c, + { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, + { 6, 0x989c, + { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } }, + { 6, 0x989c, + { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, + { 6, 0x989c, + { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, + { 6, 0x989c, + { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, + { 6, 0x989c, + { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, + { 6, 0x989c, + { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, + { 6, 0x98d8, + { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, + { 7, 0x989c, + { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, + { 7, 0x989c, + { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, + { 7, 0x989c, + { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, + { 7, 0x989c, + { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, + { 7, 0x989c, + { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, + { 7, 0x989c, + { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, + { 7, 0x989c, + { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, + { 7, 0x989c, + { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, + { 7, 0x989c, + { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, + { 7, 0x989c, + { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, + { 7, 0x989c, + { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, + { 7, 0x989c, + { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, + { 7, 0x98c4, + { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, +}; + + + +/******************\ +* RF2413 (Griffin) * +\******************/ + +/* BANK 6 len pos col */ +#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } +#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } + +static const struct ath5k_rf_reg rf_regs_2413[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, +}; + +/* Default mode specific settings + * XXX: a/aTurbo ??? + */ +static const struct ath5k_ini_rfbuffer rfb_2413[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, + { 3, 0x98dc, + { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, + { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } }, + { 6, 0x989c, + { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } }, + { 6, 0x989c, + { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } }, + { 6, 0x989c, + { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } }, + { 6, 0x989c, + { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } }, + { 6, 0x989c, + { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } }, + { 6, 0x989c, + { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, + { 6, 0x989c, + { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } }, + { 6, 0x989c, + { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } }, + { 6, 0x989c, + { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } }, + { 6, 0x989c, + { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } }, + { 6, 0x989c, + { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } }, + { 6, 0x989c, + { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } }, + { 6, 0x98d8, + { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } }, + { 7, 0x989c, + { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, + { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, +}; + + + +/***************************\ +* RF2315/RF2316 (Cobra SoC) * +\***************************/ + +/* BANK 6 len pos col */ +#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } +#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } + +static const struct ath5k_rf_reg rf_regs_2316[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, +}; + +/* Default mode specific settings */ +static const struct ath5k_ini_rfbuffer rfb_2316[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, + { 3, 0x98dc, + { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } }, + { 6, 0x989c, + { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, + { 6, 0x989c, + { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } }, + { 6, 0x989c, + { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } }, + { 6, 0x989c, + { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } }, + { 6, 0x989c, + { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } }, + { 6, 0x989c, + { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, + { 6, 0x989c, + { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, + { 6, 0x989c, + { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } }, + { 6, 0x989c, + { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } }, + { 6, 0x989c, + { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } }, + { 6, 0x989c, + { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } }, + { 6, 0x989c, + { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } }, + { 6, 0x989c, + { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } }, + { 6, 0x989c, + { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, + { 6, 0x989c, + { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, + { 6, 0x989c, + { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } }, + { 6, 0x989c, + { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } }, + { 6, 0x98c0, + { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, + { 7, 0x989c, + { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, + { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, +}; + + + +/******************************\ +* RF5413/RF5424 (Eagle/Condor) * +\******************************/ + +/* BANK 6 len pos col */ +#define AR5K_RF5413_OB_2GHZ { 3, 241, 0 } +#define AR5K_RF5413_DB_2GHZ { 3, 238, 0 } + +#define AR5K_RF5413_OB_5GHZ { 3, 247, 0 } +#define AR5K_RF5413_DB_5GHZ { 3, 244, 0 } + +#define AR5K_RF5413_PWD_ICLOBUF2G { 3, 131, 3 } +#define AR5K_RF5413_DERBY_CHAN_SEL_MODE { 1, 291, 2 } + +static const struct ath5k_rf_reg rf_regs_5413[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF5413_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF5413_DB_2GHZ}, + {6, AR5K_RF_OB_5GHZ, AR5K_RF5413_OB_5GHZ}, + {6, AR5K_RF_DB_5GHZ, AR5K_RF5413_DB_5GHZ}, + {6, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF5413_PWD_ICLOBUF2G}, + {6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE}, +}; + +/* Default mode specific settings */ +static const struct ath5k_ini_rfbuffer rfb_5413[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, + { 3, 0x98dc, + { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, + { 6, 0x989c, + { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, + { 6, 0x989c, + { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, + { 6, 0x989c, + { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, + { 6, 0x989c, + { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, + { 6, 0x989c, + { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, + { 6, 0x989c, + { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, + { 6, 0x989c, + { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, + { 6, 0x989c, + { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, + { 6, 0x989c, + { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, + { 6, 0x989c, + { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, + { 6, 0x989c, + { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, + { 6, 0x989c, + { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, + { 6, 0x989c, + { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, + { 6, 0x989c, + { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, + { 6, 0x989c, + { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, + { 6, 0x989c, + { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, + { 6, 0x989c, + { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, + { 6, 0x989c, + { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, + { 6, 0x989c, + { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, + { 6, 0x989c, + { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } }, + { 6, 0x989c, + { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, + { 6, 0x989c, + { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } }, + { 6, 0x98c8, + { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, + { 7, 0x989c, + { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, + { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, +}; + + + +/***************************\ +* RF2425/RF2417 (Swan/Nala) * +* AR2317 (Spider SoC) * +\***************************/ + +/* BANK 6 len pos col */ +#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } +#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } + +static const struct ath5k_rf_reg rf_regs_2425[] = { + {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, + {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, +}; + +/* Default mode specific settings + * XXX: a/aTurbo ? + */ +static const struct ath5k_ini_rfbuffer rfb_2425[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, + { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, + { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, + { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, + { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, + { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, + { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, + { 6, 0x989c, + { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, + { 6, 0x989c, + { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, + { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, + { 6, 0x989c, + { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, + { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, + { 6, 0x989c, + { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, + { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, + { 6, 0x98c4, + { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, + { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, + { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, +}; + +/* + * TODO: Handle the few differences with swan during + * bank modification and get rid of this + */ +static const struct ath5k_ini_rfbuffer rfb_2317[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, + { 3, 0x98dc, + { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, + { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, + { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, + { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, + { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, + { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, + { 6, 0x989c, + { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } }, + { 6, 0x989c, + { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, + { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, + { 6, 0x989c, + { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, + { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, + { 6, 0x989c, + { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, + { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } }, + { 6, 0x98c4, + { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, + { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, + { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, +}; + +/* + * TODO: Handle the few differences with swan during + * bank modification and get rid of this + * XXX: a/aTurbo ? + */ +static const struct ath5k_ini_rfbuffer rfb_2417[] = { + { 1, 0x98d4, + /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ + { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, + { 2, 0x98d0, + { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, + { 3, 0x98dc, + { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, 0x989c, + { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, + { 6, 0x989c, + { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, + { 6, 0x989c, + { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, + { 6, 0x989c, + { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, + { 6, 0x989c, + { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } }, + { 6, 0x989c, + { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, + { 6, 0x989c, + { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, + { 6, 0x989c, + { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } }, + { 6, 0x989c, + { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, + { 6, 0x989c, + { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, + { 6, 0x989c, + { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, + { 6, 0x989c, + { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, + { 6, 0x989c, + { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, + { 6, 0x98c4, + { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, + { 7, 0x989c, + { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, + { 7, 0x989c, + { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, + { 7, 0x98cc, + { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, +}; diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h new file mode 100644 index 000000000000..1354d8c392c8 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/rfgain.h @@ -0,0 +1,516 @@ +/* + * RF Gain optimization + * + * Copyright (c) 2004-2009 Reyk Floeter + * Copyright (c) 2006-2009 Nick Kossifidis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * Mode-specific RF Gain table (64bytes) for RF5111/5112 + * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial + * RF Gain values are included in AR5K_AR5210_INI) + */ +struct ath5k_ini_rfgain { + u16 rfg_register; /* RF Gain register address */ + u32 rfg_value[2]; /* [freq (see below)] */ +}; + +/* Initial RF Gain settings for RF5111 */ +static const struct ath5k_ini_rfgain rfgain_5111[] = { + /* 5Ghz 2Ghz */ + { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } }, + { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } }, + { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } }, + { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } }, + { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } }, + { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } }, + { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } }, + { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } }, + { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } }, + { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } }, + { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } }, + { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } }, + { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } }, + { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } }, + { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } }, + { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } }, + { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } }, + { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } }, + { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } }, + { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } }, + { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } }, + { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } }, + { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } }, + { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } }, + { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } }, + { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } }, + { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } }, + { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } }, + { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } }, + { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } }, + { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } }, + { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } }, + { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } }, + { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } }, + { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } }, + { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } }, + { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } }, + { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } }, + { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } }, + { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } }, + { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } }, + { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } }, + { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } }, + { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } }, + { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } }, + { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } }, + { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } }, + { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } }, + { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } }, +}; + +/* Initial RF Gain settings for RF5112 */ +static const struct ath5k_ini_rfgain rfgain_5112[] = { + /* 5Ghz 2Ghz */ + { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } }, + { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } }, + { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } }, + { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } }, + { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } }, + { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } }, + { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } }, + { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } }, + { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } }, + { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } }, + { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } }, + { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } }, + { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } }, + { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } }, + { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } }, + { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } }, + { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } }, + { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } }, + { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } }, + { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } }, + { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } }, + { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } }, + { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } }, + { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } }, + { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } }, + { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } }, + { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } }, + { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } }, + { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } }, + { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } }, + { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } }, + { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } }, + { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } }, + { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } }, + { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } }, + { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } }, + { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } }, + { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } }, + { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } }, + { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } }, + { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } }, + { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } }, + { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } }, + { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } }, + { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } }, + { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } }, + { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } }, + { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } }, + { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } }, + { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } }, + { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } }, + { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } }, + { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } }, + { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } }, + { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } }, + { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } }, +}; + +/* Initial RF Gain settings for RF2413 */ +static const struct ath5k_ini_rfgain rfgain_2413[] = { + { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } }, + { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } }, + { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } }, + { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } }, + { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } }, + { AR5K_RF_GAIN(8), { 0x00000000, 0x00000168 } }, + { AR5K_RF_GAIN(9), { 0x00000000, 0x000001a8 } }, + { AR5K_RF_GAIN(10), { 0x00000000, 0x000001e8 } }, + { AR5K_RF_GAIN(11), { 0x00000000, 0x00000028 } }, + { AR5K_RF_GAIN(12), { 0x00000000, 0x00000068 } }, + { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } }, + { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } }, + { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } }, + { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } }, + { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } }, + { AR5K_RF_GAIN(18), { 0x00000000, 0x00000190 } }, + { AR5K_RF_GAIN(19), { 0x00000000, 0x000001d0 } }, + { AR5K_RF_GAIN(20), { 0x00000000, 0x00000010 } }, + { AR5K_RF_GAIN(21), { 0x00000000, 0x00000050 } }, + { AR5K_RF_GAIN(22), { 0x00000000, 0x00000090 } }, + { AR5K_RF_GAIN(23), { 0x00000000, 0x00000191 } }, + { AR5K_RF_GAIN(24), { 0x00000000, 0x000001d1 } }, + { AR5K_RF_GAIN(25), { 0x00000000, 0x00000011 } }, + { AR5K_RF_GAIN(26), { 0x00000000, 0x00000051 } }, + { AR5K_RF_GAIN(27), { 0x00000000, 0x00000091 } }, + { AR5K_RF_GAIN(28), { 0x00000000, 0x00000178 } }, + { AR5K_RF_GAIN(29), { 0x00000000, 0x000001b8 } }, + { AR5K_RF_GAIN(30), { 0x00000000, 0x000001f8 } }, + { AR5K_RF_GAIN(31), { 0x00000000, 0x00000038 } }, + { AR5K_RF_GAIN(32), { 0x00000000, 0x00000078 } }, + { AR5K_RF_GAIN(33), { 0x00000000, 0x00000199 } }, + { AR5K_RF_GAIN(34), { 0x00000000, 0x000001d9 } }, + { AR5K_RF_GAIN(35), { 0x00000000, 0x00000019 } }, + { AR5K_RF_GAIN(36), { 0x00000000, 0x00000059 } }, + { AR5K_RF_GAIN(37), { 0x00000000, 0x00000099 } }, + { AR5K_RF_GAIN(38), { 0x00000000, 0x000000d9 } }, + { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } }, +}; + +/* Initial RF Gain settings for AR2316 */ +static const struct ath5k_ini_rfgain rfgain_2316[] = { + { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000000, 0x000000c0 } }, + { AR5K_RF_GAIN(4), { 0x00000000, 0x000000e0 } }, + { AR5K_RF_GAIN(5), { 0x00000000, 0x000000e0 } }, + { AR5K_RF_GAIN(6), { 0x00000000, 0x00000128 } }, + { AR5K_RF_GAIN(7), { 0x00000000, 0x00000128 } }, + { AR5K_RF_GAIN(8), { 0x00000000, 0x00000128 } }, + { AR5K_RF_GAIN(9), { 0x00000000, 0x00000168 } }, + { AR5K_RF_GAIN(10), { 0x00000000, 0x000001a8 } }, + { AR5K_RF_GAIN(11), { 0x00000000, 0x000001e8 } }, + { AR5K_RF_GAIN(12), { 0x00000000, 0x00000028 } }, + { AR5K_RF_GAIN(13), { 0x00000000, 0x00000068 } }, + { AR5K_RF_GAIN(14), { 0x00000000, 0x000000a8 } }, + { AR5K_RF_GAIN(15), { 0x00000000, 0x000000e8 } }, + { AR5K_RF_GAIN(16), { 0x00000000, 0x000000e8 } }, + { AR5K_RF_GAIN(17), { 0x00000000, 0x00000130 } }, + { AR5K_RF_GAIN(18), { 0x00000000, 0x00000130 } }, + { AR5K_RF_GAIN(19), { 0x00000000, 0x00000170 } }, + { AR5K_RF_GAIN(20), { 0x00000000, 0x000001b0 } }, + { AR5K_RF_GAIN(21), { 0x00000000, 0x000001f0 } }, + { AR5K_RF_GAIN(22), { 0x00000000, 0x00000030 } }, + { AR5K_RF_GAIN(23), { 0x00000000, 0x00000070 } }, + { AR5K_RF_GAIN(24), { 0x00000000, 0x000000b0 } }, + { AR5K_RF_GAIN(25), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(26), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(27), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(28), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(29), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(30), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(31), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(32), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(33), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(34), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(35), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(36), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f0 } }, + { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f0 } }, +}; + + +/* Initial RF Gain settings for RF5413 */ +static const struct ath5k_ini_rfgain rfgain_5413[] = { + /* 5Ghz 2Ghz */ + { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } }, + { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } }, + { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } }, + { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } }, + { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } }, + { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } }, + { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } }, + { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } }, + { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } }, + { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } }, + { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } }, + { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } }, + { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } }, + { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } }, + { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } }, + { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } }, + { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } }, + { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } }, + { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } }, + { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } }, + { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } }, + { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } }, + { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } }, + { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } }, + { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } }, + { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } }, + { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } }, + { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } }, + { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } }, + { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } }, + { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } }, + { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } }, + { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } }, + { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } }, + { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } }, + { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } }, + { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } }, + { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, +}; + + +/* Initial RF Gain settings for RF2425 */ +static const struct ath5k_ini_rfgain rfgain_2425[] = { + { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } }, + { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } }, + { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } }, + { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } }, + { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } }, + { AR5K_RF_GAIN(8), { 0x00000000, 0x00000188 } }, + { AR5K_RF_GAIN(9), { 0x00000000, 0x000001c8 } }, + { AR5K_RF_GAIN(10), { 0x00000000, 0x00000008 } }, + { AR5K_RF_GAIN(11), { 0x00000000, 0x00000048 } }, + { AR5K_RF_GAIN(12), { 0x00000000, 0x00000088 } }, + { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } }, + { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } }, + { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } }, + { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } }, + { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } }, + { AR5K_RF_GAIN(18), { 0x00000000, 0x000001b0 } }, + { AR5K_RF_GAIN(19), { 0x00000000, 0x000001f0 } }, + { AR5K_RF_GAIN(20), { 0x00000000, 0x00000030 } }, + { AR5K_RF_GAIN(21), { 0x00000000, 0x00000070 } }, + { AR5K_RF_GAIN(22), { 0x00000000, 0x00000171 } }, + { AR5K_RF_GAIN(23), { 0x00000000, 0x000001b1 } }, + { AR5K_RF_GAIN(24), { 0x00000000, 0x000001f1 } }, + { AR5K_RF_GAIN(25), { 0x00000000, 0x00000031 } }, + { AR5K_RF_GAIN(26), { 0x00000000, 0x00000071 } }, + { AR5K_RF_GAIN(27), { 0x00000000, 0x000001b8 } }, + { AR5K_RF_GAIN(28), { 0x00000000, 0x000001f8 } }, + { AR5K_RF_GAIN(29), { 0x00000000, 0x00000038 } }, + { AR5K_RF_GAIN(30), { 0x00000000, 0x00000078 } }, + { AR5K_RF_GAIN(31), { 0x00000000, 0x000000b8 } }, + { AR5K_RF_GAIN(32), { 0x00000000, 0x000001b9 } }, + { AR5K_RF_GAIN(33), { 0x00000000, 0x000001f9 } }, + { AR5K_RF_GAIN(34), { 0x00000000, 0x00000039 } }, + { AR5K_RF_GAIN(35), { 0x00000000, 0x00000079 } }, + { AR5K_RF_GAIN(36), { 0x00000000, 0x000000b9 } }, + { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } }, + { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } }, +}; + +#define AR5K_GAIN_CRN_FIX_BITS_5111 4 +#define AR5K_GAIN_CRN_FIX_BITS_5112 7 +#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112 +#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15 +#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20 +#define AR5K_GAIN_CCK_PROBE_CORR 5 +#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15 +#define AR5K_GAIN_STEP_COUNT 10 + +/* Check if our current measurement is inside our + * current variable attenuation window */ +#define AR5K_GAIN_CHECK_ADJUST(_g) \ + ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) + +struct ath5k_gain_opt_step { + s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; + s8 gos_gain; +}; + +struct ath5k_gain_opt { + u8 go_default; + u8 go_steps_count; + const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; +}; + +/* + * Parameters on gos_param: + * 1) Tx clip PHY register + * 2) PWD 90 RF register + * 3) PWD 84 RF register + * 4) RFGainSel RF register + */ +static const struct ath5k_gain_opt rfgain_opt_5111 = { + 4, + 9, + { + { { 4, 1, 1, 1 }, 6 }, + { { 4, 0, 1, 1 }, 4 }, + { { 3, 1, 1, 1 }, 3 }, + { { 4, 0, 0, 1 }, 1 }, + { { 4, 1, 1, 0 }, 0 }, + { { 4, 0, 1, 0 }, -2 }, + { { 3, 1, 1, 0 }, -3 }, + { { 4, 0, 0, 0 }, -4 }, + { { 2, 1, 1, 0 }, -6 } + } +}; + +/* + * Parameters on gos_param: + * 1) Mixgain ovr RF register + * 2) PWD 138 RF register + * 3) PWD 137 RF register + * 4) PWD 136 RF register + * 5) PWD 132 RF register + * 6) PWD 131 RF register + * 7) PWD 130 RF register + */ +static const struct ath5k_gain_opt rfgain_opt_5112 = { + 1, + 8, + { + { { 3, 0, 0, 0, 0, 0, 0 }, 6 }, + { { 2, 0, 0, 0, 0, 0, 0 }, 0 }, + { { 1, 0, 0, 0, 0, 0, 0 }, -3 }, + { { 0, 0, 0, 0, 0, 0, 0 }, -6 }, + { { 0, 1, 1, 0, 0, 0, 0 }, -8 }, + { { 0, 1, 1, 0, 1, 1, 0 }, -10 }, + { { 0, 1, 0, 1, 1, 1, 0 }, -13 }, + { { 0, 1, 0, 1, 1, 0, 1 }, -16 }, + } +}; + diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig new file mode 100644 index 000000000000..0ed1ac312aa6 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -0,0 +1,24 @@ +config ATH9K + tristate "Atheros 802.11n wireless cards support" + depends on PCI && MAC80211 && WLAN_80211 + depends on RFKILL || RFKILL=n + select ATH_COMMON + select MAC80211_LEDS + select LEDS_CLASS + select NEW_LEDS + ---help--- + This module adds support for wireless adapters based on + Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. + + If you choose to build a module, it'll be called ath9k. + +config ATH9K_DEBUG + bool "Atheros ath9k debugging" + depends on ATH9K + ---help--- + Say Y, if you need ath9k to display debug messages. + Pass the debug mask as a module parameter: + + modprobe ath9k debug=0x00002000 + + Look in ath9k/core.h for possible debug masks diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile new file mode 100644 index 000000000000..783bc39eb2ff --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -0,0 +1,18 @@ +ath9k-y += hw.o \ + eeprom.o \ + mac.o \ + calib.o \ + ani.o \ + phy.o \ + beacon.o \ + main.o \ + recv.o \ + xmit.o \ + virtual.o \ + rc.o + +ath9k-$(CONFIG_PCI) += pci.o +ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o +ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o + +obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c new file mode 100644 index 000000000000..0e65c51ba176 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2009 Gabor Juhos + * Copyright (c) 2009 Imre Kaloz + * + * 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 +#include +#include +#include "ath9k.h" + +/* return bus cachesize in 4B word units */ +static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz) +{ + *csz = L1_CACHE_BYTES >> 2; +} + +static void ath_ahb_cleanup(struct ath_softc *sc) +{ + iounmap(sc->mem); +} + +static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) +{ + struct ath_softc *sc = ah->ah_sc; + struct platform_device *pdev = to_platform_device(sc->dev); + struct ath9k_platform_data *pdata; + + pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; + if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "%s: flash read failed, offset %08x is out of range\n", + __func__, off); + return false; + } + + *data = pdata->eeprom_data[off]; + return true; +} + +static struct ath_bus_ops ath_ahb_bus_ops = { + .read_cachesize = ath_ahb_read_cachesize, + .cleanup = ath_ahb_cleanup, + + .eeprom_read = ath_ahb_eeprom_read, +}; + +static int ath_ahb_probe(struct platform_device *pdev) +{ + void __iomem *mem; + struct ath_wiphy *aphy; + struct ath_softc *sc; + struct ieee80211_hw *hw; + struct resource *res; + int irq; + int ret = 0; + struct ath_hw *ah; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "no platform data specified\n"); + ret = -EINVAL; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource found\n"); + ret = -ENXIO; + goto err_out; + } + + mem = ioremap_nocache(res->start, res->end - res->start + 1); + if (mem == NULL) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENOMEM; + goto err_out; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + ret = -ENXIO; + goto err_iounmap; + } + + irq = res->start; + + hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + + sizeof(struct ath_softc), &ath9k_ops); + if (hw == NULL) { + dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); + ret = -ENOMEM; + goto err_iounmap; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + platform_set_drvdata(pdev, hw); + + aphy = hw->priv; + sc = (struct ath_softc *) (aphy + 1); + aphy->sc = sc; + aphy->hw = hw; + sc->pri_wiphy = aphy; + sc->hw = hw; + sc->dev = &pdev->dev; + sc->mem = mem; + sc->bus_ops = &ath_ahb_bus_ops; + sc->irq = irq; + + ret = ath_attach(AR5416_AR9100_DEVID, sc); + if (ret != 0) { + dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); + ret = -ENODEV; + goto err_free_hw; + } + + ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); + if (ret) { + dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret); + ret = -EIO; + goto err_detach; + } + + ah = sc->sc_ah; + printk(KERN_INFO + "%s: Atheros AR%s MAC/BB Rev:%x, " + "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n", + wiphy_name(hw->wiphy), + ath_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev, + ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), + ah->hw_version.phyRev, + (unsigned long)mem, irq); + + return 0; + + err_detach: + ath_detach(sc); + err_free_hw: + ieee80211_free_hw(hw); + platform_set_drvdata(pdev, NULL); + err_iounmap: + iounmap(mem); + err_out: + return ret; +} + +static int ath_ahb_remove(struct platform_device *pdev) +{ + struct ieee80211_hw *hw = platform_get_drvdata(pdev); + + if (hw) { + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + ath_cleanup(sc); + platform_set_drvdata(pdev, NULL); + } + + return 0; +} + +static struct platform_driver ath_ahb_driver = { + .probe = ath_ahb_probe, + .remove = ath_ahb_remove, + .driver = { + .name = "ath9k", + .owner = THIS_MODULE, + }, +}; + +int ath_ahb_init(void) +{ + return platform_driver_register(&ath_ahb_driver); +} + +void ath_ahb_exit(void) +{ + platform_driver_unregister(&ath_ahb_driver); +} diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c new file mode 100644 index 000000000000..1aeafb511ddd --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -0,0 +1,822 @@ +/* + * 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 "ath9k.h" + +static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { + if (ah->ani[i].c && + ah->ani[i].c->channel == chan->channel) + return i; + if (ah->ani[i].c == NULL) { + ah->ani[i].c = chan; + return i; + } + } + + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "No more channel states left. Using channel 0\n"); + + return 0; +} + +static bool ath9k_hw_ani_control(struct ath_hw *ah, + enum ath9k_ani_cmd cmd, int param) +{ + struct ar5416AniState *aniState = ah->curani; + + switch (cmd & ah->ani_function) { + case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ + u32 level = param; + + if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); + return false; + } + + REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_TOT_DES, + ah->totalSizeDesired[level]); + REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_LOW, + ah->coarse_low[level]); + REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, + AR_PHY_AGC_CTL1_COARSE_HIGH, + ah->coarse_high[level]); + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRPWR, + ah->firpwr[level]); + + if (level > aniState->noiseImmunityLevel) + ah->stats.ast_ani_niup++; + else if (level < aniState->noiseImmunityLevel) + ah->stats.ast_ani_nidown++; + aniState->noiseImmunityLevel = level; + break; + } + case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ + const int m1ThreshLow[] = { 127, 50 }; + const int m2ThreshLow[] = { 127, 40 }; + const int m1Thresh[] = { 127, 0x4d }; + const int m2Thresh[] = { 127, 0x40 }; + const int m2CountThr[] = { 31, 16 }; + const int m2CountThrLow[] = { 63, 48 }; + u32 on = param ? 1 : 0; + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, + m1ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, + m2ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, + m1Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, + m2Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, + m2CountThr[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, + m2CountThrLow[on]); + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, + m1ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, + m2ThreshLow[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, + m1Thresh[on]); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, + m2Thresh[on]); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + else + REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + + if (!on != aniState->ofdmWeakSigDetectOff) { + if (on) + ah->stats.ast_ani_ofdmon++; + else + ah->stats.ast_ani_ofdmoff++; + aniState->ofdmWeakSigDetectOff = !on; + } + break; + } + case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ + const int weakSigThrCck[] = { 8, 6 }; + u32 high = param ? 1 : 0; + + REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, + AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, + weakSigThrCck[high]); + if (high != aniState->cckWeakSigThreshold) { + if (high) + ah->stats.ast_ani_cckhigh++; + else + ah->stats.ast_ani_ccklow++; + aniState->cckWeakSigThreshold = high; + } + break; + } + case ATH9K_ANI_FIRSTEP_LEVEL:{ + const int firstep[] = { 0, 4, 8 }; + u32 level = param; + + if (level >= ARRAY_SIZE(firstep)) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned) ARRAY_SIZE(firstep)); + return false; + } + REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, + AR_PHY_FIND_SIG_FIRSTEP, + firstep[level]); + if (level > aniState->firstepLevel) + ah->stats.ast_ani_stepup++; + else if (level < aniState->firstepLevel) + ah->stats.ast_ani_stepdown++; + aniState->firstepLevel = level; + break; + } + case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ + const int cycpwrThr1[] = + { 2, 4, 6, 8, 10, 12, 14, 16 }; + u32 level = param; + + if (level >= ARRAY_SIZE(cycpwrThr1)) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "level out of range (%u > %u)\n", + level, + (unsigned) + ARRAY_SIZE(cycpwrThr1)); + return false; + } + REG_RMW_FIELD(ah, AR_PHY_TIMING5, + AR_PHY_TIMING5_CYCPWR_THR1, + cycpwrThr1[level]); + if (level > aniState->spurImmunityLevel) + ah->stats.ast_ani_spurup++; + else if (level < aniState->spurImmunityLevel) + ah->stats.ast_ani_spurdown++; + aniState->spurImmunityLevel = level; + break; + } + case ATH9K_ANI_PRESENT: + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "invalid cmd %u\n", cmd); + return false; + } + + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n"); + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "noiseImmunityLevel=%d, spurImmunityLevel=%d, " + "ofdmWeakSigDetectOff=%d\n", + aniState->noiseImmunityLevel, aniState->spurImmunityLevel, + !aniState->ofdmWeakSigDetectOff); + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "cckWeakSigThreshold=%d, " + "firstepLevel=%d, listenTime=%d\n", + aniState->cckWeakSigThreshold, aniState->firstepLevel, + aniState->listenTime); + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", + aniState->cycleCount, aniState->ofdmPhyErrCount, + aniState->cckPhyErrCount); + + return true; +} + +static void ath9k_hw_update_mibstats(struct ath_hw *ah, + struct ath9k_mib_stats *stats) +{ + stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); + stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); + stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); + stats->rts_good += REG_READ(ah, AR_RTS_OK); + stats->beacons += REG_READ(ah, AR_BEACON_CNT); +} + +static void ath9k_ani_restart(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + + aniState->listenTime = 0; + if (ah->has_hw_phycounters) { + if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { + aniState->ofdmPhyErrBase = 0; + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "OFDM Trigger is too high for hw counters\n"); + } else { + aniState->ofdmPhyErrBase = + AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; + } + if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { + aniState->cckPhyErrBase = 0; + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "CCK Trigger is too high for hw counters\n"); + } else { + aniState->cckPhyErrBase = + AR_PHY_COUNTMAX - aniState->cckTrigHigh; + } + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Writing ofdmbase=%u cckbase=%u\n", + aniState->ofdmPhyErrBase, + aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + } + aniState->ofdmPhyErrCount = 0; + aniState->cckPhyErrCount = 0; +} + +static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct ar5416AniState *aniState; + int32_t rssi; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + + if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { + if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1)) { + return; + } + } + + if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) { + if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel + 1)) { + return; + } + } + + if (ah->opmode == NL80211_IFTYPE_AP) { + if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } + return; + } + rssi = BEACON_RSSI(ah); + if (rssi > aniState->rssiThrHigh) { + if (!aniState->ofdmWeakSigDetectOff) { + if (ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + false)) { + ath9k_hw_ani_control(ah, + ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); + return; + } + } + if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } + } else if (rssi > aniState->rssiThrLow) { + if (aniState->ofdmWeakSigDetectOff) + ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + true); + if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + return; + } else { + if (conf->channel->band == IEEE80211_BAND_2GHZ) { + if (!aniState->ofdmWeakSigDetectOff) + ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + false); + if (aniState->firstepLevel > 0) + ath9k_hw_ani_control(ah, + ATH9K_ANI_FIRSTEP_LEVEL, 0); + return; + } + } +} + +static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct ar5416AniState *aniState; + int32_t rssi; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { + if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel + 1)) { + return; + } + } + if (ah->opmode == NL80211_IFTYPE_AP) { + if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } + return; + } + rssi = BEACON_RSSI(ah); + if (rssi > aniState->rssiThrLow) { + if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel + 1); + } else { + if (conf->channel->band == IEEE80211_BAND_2GHZ) { + if (aniState->firstepLevel > 0) + ath9k_hw_ani_control(ah, + ATH9K_ANI_FIRSTEP_LEVEL, 0); + } + } +} + +static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + int32_t rssi; + + aniState = ah->curani; + + if (ah->opmode == NL80211_IFTYPE_AP) { + if (aniState->firstepLevel > 0) { + if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1)) + return; + } + } else { + rssi = BEACON_RSSI(ah); + if (rssi > aniState->rssiThrHigh) { + /* XXX: Handle me */ + } else if (rssi > aniState->rssiThrLow) { + if (aniState->ofdmWeakSigDetectOff) { + if (ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + true) == true) + return; + } + if (aniState->firstepLevel > 0) { + if (ath9k_hw_ani_control(ah, + ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1) == true) + return; + } + } else { + if (aniState->firstepLevel > 0) { + if (ath9k_hw_ani_control(ah, + ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel - 1) == true) + return; + } + } + } + + if (aniState->spurImmunityLevel > 0) { + if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel - 1)) + return; + } + + if (aniState->noiseImmunityLevel > 0) { + ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel - 1); + return; + } +} + +static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + u32 txFrameCount, rxFrameCount, cycleCount; + int32_t listenTime; + + txFrameCount = REG_READ(ah, AR_TFCNT); + rxFrameCount = REG_READ(ah, AR_RFCNT); + cycleCount = REG_READ(ah, AR_CCCNT); + + aniState = ah->curani; + if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { + + listenTime = 0; + ah->stats.ast_ani_lzero++; + } else { + int32_t ccdelta = cycleCount - aniState->cycleCount; + int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; + int32_t tfdelta = txFrameCount - aniState->txFrameCount; + listenTime = (ccdelta - rfdelta - tfdelta) / 44000; + } + aniState->cycleCount = cycleCount; + aniState->txFrameCount = txFrameCount; + aniState->rxFrameCount = rxFrameCount; + + return listenTime; +} + +void ath9k_ani_reset(struct ath_hw *ah) +{ + struct ar5416AniState *aniState; + struct ath9k_channel *chan = ah->curchan; + int index; + + if (!DO_ANI(ah)) + return; + + index = ath9k_hw_get_ani_channel_idx(ah, chan); + aniState = &ah->ani[index]; + ah->curani = aniState; + + if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION + && ah->opmode != NL80211_IFTYPE_ADHOC) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Reset ANI state opmode %u\n", ah->opmode); + ah->stats.ast_ani_reset++; + + ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); + ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); + ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !ATH9K_ANI_USE_OFDM_WEAK_SIG); + ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, + ATH9K_ANI_CCK_WEAK_SIG_THR); + + ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | + ATH9K_RX_FILTER_PHYERR); + + if (ah->opmode == NL80211_IFTYPE_AP) { + ah->curani->ofdmTrigHigh = + ah->config.ofdm_trig_high; + ah->curani->ofdmTrigLow = + ah->config.ofdm_trig_low; + ah->curani->cckTrigHigh = + ah->config.cck_trig_high; + ah->curani->cckTrigLow = + ah->config.cck_trig_low; + } + ath9k_ani_restart(ah); + return; + } + + if (aniState->noiseImmunityLevel != 0) + ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, + aniState->noiseImmunityLevel); + if (aniState->spurImmunityLevel != 0) + ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, + aniState->spurImmunityLevel); + if (aniState->ofdmWeakSigDetectOff) + ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + !aniState->ofdmWeakSigDetectOff); + if (aniState->cckWeakSigThreshold) + ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, + aniState->cckWeakSigThreshold); + if (aniState->firstepLevel != 0) + ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, + aniState->firstepLevel); + if (ah->has_hw_phycounters) { + ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & + ~ATH9K_RX_FILTER_PHYERR); + ath9k_ani_restart(ah); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + + } else { + ath9k_ani_restart(ah); + ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | + ATH9K_RX_FILTER_PHYERR); + } +} + +void ath9k_hw_ani_monitor(struct ath_hw *ah, + const struct ath9k_node_stats *stats, + struct ath9k_channel *chan) +{ + struct ar5416AniState *aniState; + int32_t listenTime; + + if (!DO_ANI(ah)) + return; + + aniState = ah->curani; + ah->stats.ast_nodestats = *stats; + + listenTime = ath9k_hw_ani_get_listen_time(ah); + if (listenTime < 0) { + ah->stats.ast_ani_lneg++; + ath9k_ani_restart(ah); + return; + } + + aniState->listenTime += listenTime; + + if (ah->has_hw_phycounters) { + u32 phyCnt1, phyCnt2; + u32 ofdmPhyErrCnt, cckPhyErrCnt; + + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + + phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); + + if (phyCnt1 < aniState->ofdmPhyErrBase || + phyCnt2 < aniState->cckPhyErrBase) { + if (phyCnt1 < aniState->ofdmPhyErrBase) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "phyCnt1 0x%x, resetting " + "counter value to 0x%x\n", + phyCnt1, aniState->ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_1, + aniState->ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, + AR_PHY_ERR_OFDM_TIMING); + } + if (phyCnt2 < aniState->cckPhyErrBase) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "phyCnt2 0x%x, resetting " + "counter value to 0x%x\n", + phyCnt2, aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_2, + aniState->cckPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, + AR_PHY_ERR_CCK_TIMING); + } + return; + } + + ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; + ah->stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; + ah->stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + } + + if (aniState->listenTime > 5 * ah->aniperiod) { + if (aniState->ofdmPhyErrCount <= aniState->listenTime * + aniState->ofdmTrigLow / 1000 && + aniState->cckPhyErrCount <= aniState->listenTime * + aniState->cckTrigLow / 1000) + ath9k_hw_ani_lower_immunity(ah); + ath9k_ani_restart(ah); + } else if (aniState->listenTime > ah->aniperiod) { + if (aniState->ofdmPhyErrCount > aniState->listenTime * + aniState->ofdmTrigHigh / 1000) { + ath9k_hw_ani_ofdm_err_trigger(ah); + ath9k_ani_restart(ah); + } else if (aniState->cckPhyErrCount > + aniState->listenTime * aniState->cckTrigHigh / + 1000) { + ath9k_hw_ani_cck_err_trigger(ah); + ath9k_ani_restart(ah); + } + } +} + +bool ath9k_hw_phycounters(struct ath_hw *ah) +{ + return ah->has_hw_phycounters ? true : false; +} + +void ath9k_enable_mib_counters(struct ath_hw *ah) +{ + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); + + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + + REG_WRITE(ah, AR_FILT_OFDM, 0); + REG_WRITE(ah, AR_FILT_CCK, 0); + REG_WRITE(ah, AR_MIBC, + ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) + & 0x0f); + REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); + REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); +} + +/* Freeze the MIB counters, get the stats and then clear them */ +void ath9k_hw_disable_mib_counters(struct ath_hw *ah) +{ + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n"); + REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC); + REG_WRITE(ah, AR_FILT_OFDM, 0); + REG_WRITE(ah, AR_FILT_CCK, 0); +} + +u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, + u32 *rxc_pcnt, + u32 *rxf_pcnt, + u32 *txf_pcnt) +{ + static u32 cycles, rx_clear, rx_frame, tx_frame; + u32 good = 1; + + u32 rc = REG_READ(ah, AR_RCCNT); + u32 rf = REG_READ(ah, AR_RFCNT); + u32 tf = REG_READ(ah, AR_TFCNT); + u32 cc = REG_READ(ah, AR_CCCNT); + + if (cycles == 0 || cycles > cc) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "cycle counter wrap. ExtBusy = 0\n"); + good = 0; + } else { + u32 cc_d = cc - cycles; + u32 rc_d = rc - rx_clear; + u32 rf_d = rf - rx_frame; + u32 tf_d = tf - tx_frame; + + if (cc_d != 0) { + *rxc_pcnt = rc_d * 100 / cc_d; + *rxf_pcnt = rf_d * 100 / cc_d; + *txf_pcnt = tf_d * 100 / cc_d; + } else { + good = 0; + } + } + + cycles = cc; + rx_frame = rf; + rx_clear = rc; + tx_frame = tf; + + return good; +} + +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ +void ath9k_hw_procmibevent(struct ath_hw *ah, + const struct ath9k_node_stats *stats) +{ + u32 phyCnt1, phyCnt2; + + /* Reset these counters regardless */ + REG_WRITE(ah, AR_FILT_OFDM, 0); + REG_WRITE(ah, AR_FILT_CCK, 0); + if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) + REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + + /* Clear the mib counters and save them in the stats */ + ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); + ah->stats.ast_nodestats = *stats; + + if (!DO_ANI(ah)) + return; + + /* NB: these are not reset-on-read */ + phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); + phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); + if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || + ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { + struct ar5416AniState *aniState = ah->curani; + u32 ofdmPhyErrCnt, cckPhyErrCnt; + + /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ + ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; + ah->stats.ast_ani_ofdmerrs += + ofdmPhyErrCnt - aniState->ofdmPhyErrCount; + aniState->ofdmPhyErrCount = ofdmPhyErrCnt; + + cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; + ah->stats.ast_ani_cckerrs += + cckPhyErrCnt - aniState->cckPhyErrCount; + aniState->cckPhyErrCount = cckPhyErrCnt; + + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ + if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) + ath9k_hw_ani_ofdm_err_trigger(ah); + if (aniState->cckPhyErrCount > aniState->cckTrigHigh) + ath9k_hw_ani_cck_err_trigger(ah); + /* NB: always restart to insure the h/w counters are reset */ + ath9k_ani_restart(ah); + } +} + +void ath9k_hw_ani_setup(struct ath_hw *ah) +{ + int i; + + const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; + const int coarseHigh[] = { -14, -14, -14, -14, -12 }; + const int coarseLow[] = { -64, -64, -64, -64, -70 }; + const int firpwr[] = { -78, -78, -78, -78, -80 }; + + for (i = 0; i < 5; i++) { + ah->totalSizeDesired[i] = totalSizeDesired[i]; + ah->coarse_high[i] = coarseHigh[i]; + ah->coarse_low[i] = coarseLow[i]; + ah->firpwr[i] = firpwr[i]; + } +} + +void ath9k_hw_ani_attach(struct ath_hw *ah) +{ + int i; + + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n"); + + ah->has_hw_phycounters = 1; + + memset(ah->ani, 0, sizeof(ah->ani)); + for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { + ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; + ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; + ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; + ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; + ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; + ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; + ah->ani[i].ofdmWeakSigDetectOff = + !ATH9K_ANI_USE_OFDM_WEAK_SIG; + ah->ani[i].cckWeakSigThreshold = + ATH9K_ANI_CCK_WEAK_SIG_THR; + ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; + ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; + if (ah->has_hw_phycounters) { + ah->ani[i].ofdmPhyErrBase = + AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; + ah->ani[i].cckPhyErrBase = + AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; + } + } + if (ah->has_hw_phycounters) { + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Setting OfdmErrBase = 0x%08x\n", + ah->ani[0].ofdmPhyErrBase); + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", + ah->ani[0].cckPhyErrBase); + + REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); + REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); + ath9k_enable_mib_counters(ah); + } + ah->aniperiod = ATH9K_ANI_PERIOD; + if (ah->config.enable_ani) + ah->proc_phyerr |= HAL_PROCESS_ANI; +} + +void ath9k_hw_ani_detach(struct ath_hw *ah) +{ + DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n"); + + if (ah->has_hw_phycounters) { + ath9k_hw_disable_mib_counters(ah); + REG_WRITE(ah, AR_PHY_ERR_1, 0); + REG_WRITE(ah, AR_PHY_ERR_2, 0); + } +} diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h new file mode 100644 index 000000000000..08b4e7ed5ff0 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -0,0 +1,138 @@ +/* + * 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 ANI_H +#define ANI_H + +#define HAL_PROCESS_ANI 0x00000001 +#define ATH9K_RSSI_EP_MULTIPLIER (1<<7) + +#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) + +#define HAL_EP_RND(x, mul) \ + ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) +#define BEACON_RSSI(ahp) \ + HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi, \ + ATH9K_RSSI_EP_MULTIPLIER) + +#define ATH9K_ANI_OFDM_TRIG_HIGH 500 +#define ATH9K_ANI_OFDM_TRIG_LOW 200 +#define ATH9K_ANI_CCK_TRIG_HIGH 200 +#define ATH9K_ANI_CCK_TRIG_LOW 100 +#define ATH9K_ANI_NOISE_IMMUNE_LVL 4 +#define ATH9K_ANI_USE_OFDM_WEAK_SIG true +#define ATH9K_ANI_CCK_WEAK_SIG_THR false +#define ATH9K_ANI_SPUR_IMMUNE_LVL 7 +#define ATH9K_ANI_FIRSTEP_LVL 0 +#define ATH9K_ANI_RSSI_THR_HIGH 40 +#define ATH9K_ANI_RSSI_THR_LOW 7 +#define ATH9K_ANI_PERIOD 100 + +#define HAL_NOISE_IMMUNE_MAX 4 +#define HAL_SPUR_IMMUNE_MAX 7 +#define HAL_FIRST_STEP_MAX 2 + +enum ath9k_ani_cmd { + ATH9K_ANI_PRESENT = 0x1, + ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4, + ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8, + ATH9K_ANI_FIRSTEP_LEVEL = 0x10, + ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, + ATH9K_ANI_MODE = 0x40, + ATH9K_ANI_PHYERR_RESET = 0x80, + ATH9K_ANI_ALL = 0xff +}; + +struct ath9k_mib_stats { + u32 ackrcv_bad; + u32 rts_bad; + u32 rts_good; + u32 fcs_bad; + u32 beacons; +}; + +struct ath9k_node_stats { + u32 ns_avgbrssi; + u32 ns_avgrssi; + u32 ns_avgtxrssi; + u32 ns_avgtxrate; +}; + +struct ar5416AniState { + struct ath9k_channel *c; + u8 noiseImmunityLevel; + u8 spurImmunityLevel; + u8 firstepLevel; + u8 ofdmWeakSigDetectOff; + u8 cckWeakSigThreshold; + u32 listenTime; + u32 ofdmTrigHigh; + u32 ofdmTrigLow; + int32_t cckTrigHigh; + int32_t cckTrigLow; + int32_t rssiThrLow; + int32_t rssiThrHigh; + u32 noiseFloor; + u32 txFrameCount; + u32 rxFrameCount; + u32 cycleCount; + u32 ofdmPhyErrCount; + u32 cckPhyErrCount; + u32 ofdmPhyErrBase; + u32 cckPhyErrBase; + int16_t pktRssi[2]; + int16_t ofdmErrRssi[2]; + int16_t cckErrRssi[2]; +}; + +struct ar5416Stats { + u32 ast_ani_niup; + u32 ast_ani_nidown; + u32 ast_ani_spurup; + u32 ast_ani_spurdown; + u32 ast_ani_ofdmon; + u32 ast_ani_ofdmoff; + u32 ast_ani_cckhigh; + u32 ast_ani_ccklow; + u32 ast_ani_stepup; + u32 ast_ani_stepdown; + u32 ast_ani_ofdmerrs; + u32 ast_ani_cckerrs; + u32 ast_ani_reset; + u32 ast_ani_lzero; + u32 ast_ani_lneg; + struct ath9k_mib_stats ast_mibstats; + struct ath9k_node_stats ast_nodestats; +}; +#define ah_mibStats stats.ast_mibstats + +void ath9k_ani_reset(struct ath_hw *ah); +void ath9k_hw_ani_monitor(struct ath_hw *ah, + const struct ath9k_node_stats *stats, + struct ath9k_channel *chan); +bool ath9k_hw_phycounters(struct ath_hw *ah); +void ath9k_enable_mib_counters(struct ath_hw *ah); +void ath9k_hw_disable_mib_counters(struct ath_hw *ah); +u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, + u32 *rxf_pcnt, u32 *txf_pcnt); +void ath9k_hw_procmibevent(struct ath_hw *ah, + const struct ath9k_node_stats *stats); +void ath9k_hw_ani_setup(struct ath_hw *ah); +void ath9k_hw_ani_attach(struct ath_hw *ah); +void ath9k_hw_ani_detach(struct ath_hw *ah); + +#endif /* ANI_H */ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h new file mode 100644 index 000000000000..c92d46fa9d51 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -0,0 +1,730 @@ +/* + * 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 ATH9K_H +#define ATH9K_H + +#include +#include +#include +#include +#include + +#include "hw.h" +#include "rc.h" +#include "debug.h" + +struct ath_node; + +/* Macro to expand scalars to 64-bit objects */ + +#define ito64(x) (sizeof(x) == 8) ? \ + (((unsigned long long int)(x)) & (0xff)) : \ + (sizeof(x) == 16) ? \ + (((unsigned long long int)(x)) & 0xffff) : \ + ((sizeof(x) == 32) ? \ + (((unsigned long long int)(x)) & 0xffffffff) : \ + (unsigned long long int)(x)) + +/* increment with wrap-around */ +#define INCR(_l, _sz) do { \ + (_l)++; \ + (_l) &= ((_sz) - 1); \ + } while (0) + +/* decrement with wrap-around */ +#define DECR(_l, _sz) do { \ + (_l)--; \ + (_l) &= ((_sz) - 1); \ + } while (0) + +#define A_MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define ASSERT(exp) BUG_ON(!(exp)) + +#define TSF_TO_TU(_h,_l) \ + ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) + +#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<bf_stale = false; \ + (_bf)->bf_lastbf = NULL; \ + (_bf)->bf_next = NULL; \ + memset(&((_bf)->bf_state), 0, \ + sizeof(struct ath_buf_state)); \ + } while (0) + +#define ATH_RXBUF_RESET(_bf) do { \ + (_bf)->bf_stale = false; \ + } while (0) + +/** + * enum buffer_type - Buffer type flags + * + * @BUF_HT: Send this buffer using HT capabilities + * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) + * @BUF_AGGR: Indicates whether the buffer can be aggregated + * (used in aggregation scheduling) + * @BUF_RETRY: Indicates whether the buffer is retried + * @BUF_XRETRY: To denote excessive retries of the buffer + */ +enum buffer_type { + BUF_HT = BIT(1), + BUF_AMPDU = BIT(2), + BUF_AGGR = BIT(3), + BUF_RETRY = BIT(4), + BUF_XRETRY = BIT(5), +}; + +struct ath_buf_state { + int bfs_nframes; + u16 bfs_al; + u16 bfs_frmlen; + int bfs_seqno; + int bfs_tidno; + int bfs_retries; + u8 bf_type; + u32 bfs_keyix; + enum ath9k_key_type bfs_keytype; +}; + +#define bf_nframes bf_state.bfs_nframes +#define bf_al bf_state.bfs_al +#define bf_frmlen bf_state.bfs_frmlen +#define bf_retries bf_state.bfs_retries +#define bf_seqno bf_state.bfs_seqno +#define bf_tidno bf_state.bfs_tidno +#define bf_keyix bf_state.bfs_keyix +#define bf_keytype bf_state.bfs_keytype +#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) +#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) +#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) +#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) +#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) + +struct ath_buf { + struct list_head list; + struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or + an aggregate) */ + struct ath_buf *bf_next; /* next subframe in the aggregate */ + struct sk_buff *bf_mpdu; /* enclosing frame structure */ + struct ath_desc *bf_desc; /* virtual addr of desc */ + dma_addr_t bf_daddr; /* physical addr of desc */ + dma_addr_t bf_buf_addr; /* physical addr of data buffer */ + bool bf_stale; + u16 bf_flags; + struct ath_buf_state bf_state; + dma_addr_t bf_dmacontext; +}; + +struct ath_descdma { + struct ath_desc *dd_desc; + dma_addr_t dd_desc_paddr; + u32 dd_desc_len; + struct ath_buf *dd_bufptr; +}; + +int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, + struct list_head *head, const char *name, + int nbuf, int ndesc); +void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, + struct list_head *head); + +/***********/ +/* RX / TX */ +/***********/ + +#define ATH_MAX_ANTENNA 3 +#define ATH_RXBUF 512 +#define WME_NUM_TID 16 +#define ATH_TXBUF 512 +#define ATH_TXMAXTRY 13 +#define ATH_11N_TXMAXTRY 10 +#define ATH_MGT_TXMAXTRY 4 +#define WME_BA_BMP_SIZE 64 +#define WME_MAX_BA WME_BA_BMP_SIZE +#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) + +#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 WME_AC_BE 0 +#define WME_AC_BK 1 +#define WME_AC_VI 2 +#define WME_AC_VO 3 +#define WME_NUM_AC 4 + +#define ADDBA_EXCHANGE_ATTEMPTS 10 +#define ATH_AGGR_DELIM_SZ 4 +#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ +/* number of delimiters for encryption padding */ +#define ATH_AGGR_ENCRYPTDELIM 10 +/* minimum h/w qdepth to be sustained to maximize aggregation */ +#define ATH_AGGR_MIN_QDEPTH 2 +#define ATH_AMPDU_SUBFRAME_DEFAULT 32 +#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) +#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX + +#define IEEE80211_SEQ_SEQ_SHIFT 4 +#define IEEE80211_SEQ_MAX 4096 +#define IEEE80211_MIN_AMPDU_BUF 0x8 +#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 +#define IEEE80211_WEP_IVLEN 3 +#define IEEE80211_WEP_KIDLEN 1 +#define IEEE80211_WEP_CRCLEN 4 +#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \ + (IEEE80211_WEP_IVLEN + \ + IEEE80211_WEP_KIDLEN + \ + IEEE80211_WEP_CRCLEN)) + +/* return whether a bit at index _n in bitmap _bm is set + * _sz is the size of the bitmap */ +#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ + ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) + +/* return block-ack bitmap index given sequence and starting sequence */ +#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) + +/* returns delimiter padding required given the packet length */ +#define ATH_AGGR_GET_NDELIM(_len) \ + (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ + (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) + +#define BAW_WITHIN(_start, _bawsz, _seqno) \ + ((((_seqno) - (_start)) & 4095) < (_bawsz)) + +#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) +#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) +#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) +#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) + +enum ATH_AGGR_STATUS { + ATH_AGGR_DONE, + ATH_AGGR_BAW_CLOSED, + ATH_AGGR_LIMITED, +}; + +struct ath_txq { + u32 axq_qnum; + u32 *axq_link; + struct list_head axq_q; + spinlock_t axq_lock; + u32 axq_depth; + u8 axq_aggr_depth; + u32 axq_totalqueued; + bool stopped; + struct ath_buf *axq_linkbuf; + + /* first desc of the last descriptor that contains CTS */ + struct ath_desc *axq_lastdsWithCTS; + + /* final desc of the gating desc that determines whether + lastdsWithCTS has been DMA'ed or not */ + struct ath_desc *axq_gatingds; + + struct list_head axq_acq; +}; + +#define AGGR_CLEANUP BIT(1) +#define AGGR_ADDBA_COMPLETE BIT(2) +#define AGGR_ADDBA_PROGRESS BIT(3) + +struct ath_atx_tid { + struct list_head list; + struct list_head buf_q; + struct ath_node *an; + struct ath_atx_ac *ac; + struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; + u16 seq_start; + u16 seq_next; + u16 baw_size; + int tidno; + int baw_head; /* first un-acked tx buffer */ + int baw_tail; /* next unused tx buffer slot */ + int sched; + int paused; + u8 state; + int addba_exchangeattempts; +}; + +struct ath_atx_ac { + int sched; + int qnum; + struct list_head list; + struct list_head tid_q; +}; + +struct ath_tx_control { + struct ath_txq *txq; + int if_id; + enum ath9k_internal_frame_type frame_type; +}; + +#define ATH_TX_ERROR 0x01 +#define ATH_TX_XRETRY 0x02 +#define ATH_TX_BAR 0x04 + +struct ath_node { + struct ath_softc *an_sc; + struct ath_atx_tid tid[WME_NUM_TID]; + struct ath_atx_ac ac[WME_NUM_AC]; + u16 maxampdu; + u8 mpdudensity; +}; + +struct ath_tx { + u16 seq_no; + u32 txqsetup; + int hwq_map[ATH9K_WME_AC_VO+1]; + spinlock_t txbuflock; + struct list_head txbuf; + struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; + struct ath_descdma txdma; +}; + +struct ath_rx { + u8 defant; + u8 rxotherant; + u32 *rxlink; + int bufsize; + unsigned int rxfilter; + spinlock_t rxflushlock; + spinlock_t rxbuflock; + struct list_head rxbuf; + struct ath_descdma rxdma; +}; + +int ath_startrecv(struct ath_softc *sc); +bool ath_stoprecv(struct ath_softc *sc); +void ath_flushrecv(struct ath_softc *sc); +u32 ath_calcrxfilter(struct ath_softc *sc); +int ath_rx_init(struct ath_softc *sc, int nbufs); +void ath_rx_cleanup(struct ath_softc *sc); +int ath_rx_tasklet(struct ath_softc *sc, int flush); +struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); +void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); +int ath_tx_setup(struct ath_softc *sc, int haltype); +void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); +void ath_draintxq(struct ath_softc *sc, + struct ath_txq *txq, bool retry_tx); +void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); +void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); +void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); +int ath_tx_init(struct ath_softc *sc, int nbufs); +void ath_tx_cleanup(struct ath_softc *sc); +struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); +int ath_txq_update(struct ath_softc *sc, int qnum, + struct ath9k_tx_queue_info *q); +int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath_tx_control *txctl); +void ath_tx_tasklet(struct ath_softc *sc); +void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); +bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); +int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, + u16 tid, u16 *ssn); +int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); +void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); + +/********/ +/* VIFs */ +/********/ + +struct ath_vif { + int av_bslot; + __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ + enum nl80211_iftype av_opmode; + struct ath_buf *av_bcbuf; + struct ath_tx_control av_btxctl; + u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ +}; + +/*******************/ +/* Beacon Handling */ +/*******************/ + +/* + * Regardless of the number of beacons we stagger, (i.e. regardless of the + * number of BSSIDs) if a given beacon does not go out even after waiting this + * number of beacon intervals, the game's up. + */ +#define BSTUCK_THRESH (9 * ATH_BCBUF) +#define ATH_BCBUF 4 +#define ATH_DEFAULT_BINTVAL 100 /* TU */ +#define ATH_DEFAULT_BMISS_LIMIT 10 +#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) + +struct ath_beacon_config { + u16 beacon_interval; + u16 listen_interval; + u16 dtim_period; + u16 bmiss_timeout; + u8 dtim_count; +}; + +struct ath_beacon { + enum { + OK, /* no change needed */ + UPDATE, /* update pending */ + COMMIT /* beacon sent, commit change */ + } updateslot; /* slot time update fsm */ + + u32 beaconq; + u32 bmisscnt; + u32 ast_be_xmit; + u64 bc_tstamp; + struct ieee80211_vif *bslot[ATH_BCBUF]; + struct ath_wiphy *bslot_aphy[ATH_BCBUF]; + int slottime; + int slotupdate; + struct ath9k_tx_queue_info beacon_qi; + struct ath_descdma bdma; + struct ath_txq *cabq; + struct list_head bbuf; +}; + +void ath_beacon_tasklet(unsigned long data); +void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); +int ath_beaconq_setup(struct ath_hw *ah); +int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); +void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); + +/*******/ +/* ANI */ +/*******/ + +#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ +#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ +#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ +#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ +#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ + +struct ath_ani { + bool caldone; + int16_t noise_floor; + unsigned int longcal_timer; + unsigned int shortcal_timer; + unsigned int resetcal_timer; + unsigned int checkani_timer; + struct timer_list timer; +}; + +/********************/ +/* LED Control */ +/********************/ + +#define ATH_LED_PIN 1 +#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ +#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ + +enum ath_led_type { + ATH_LED_RADIO, + ATH_LED_ASSOC, + ATH_LED_TX, + ATH_LED_RX +}; + +struct ath_led { + struct ath_softc *sc; + struct led_classdev led_cdev; + enum ath_led_type led_type; + char name[32]; + bool registered; +}; + +/* Rfkill */ +#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */ + +struct ath_rfkill { + struct rfkill *rfkill; + struct delayed_work rfkill_poll; + char rfkill_name[32]; +}; + +/********************/ +/* Main driver core */ +/********************/ + +/* + * Default cache line size, in bytes. + * Used when PCI device not fully initialized by bootrom/BIOS +*/ +#define DEFAULT_CACHELINE 32 +#define ATH_DEFAULT_NOISE_FLOOR -95 +#define ATH_REGCLASSIDS_MAX 10 +#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ +#define ATH_MAX_SW_RETRIES 10 +#define ATH_CHAN_MAX 255 +#define IEEE80211_WEP_NKID 4 /* number of key ids */ + +/* + * The key cache is used for h/w cipher state and also for + * tracking station state such as the current tx antenna. + * We also setup a mapping table between key cache slot indices + * and station state to short-circuit node lookups on rx. + * Different parts have different size key caches. We handle + * up to ATH_KEYMAX entries (could dynamically allocate state). + */ +#define ATH_KEYMAX 128 /* max key cache size we handle */ + +#define ATH_TXPOWER_MAX 100 /* .5 dBm units */ +#define ATH_RSSI_DUMMY_MARKER 0x127 +#define ATH_RATE_DUMMY_MARKER 0 + +#define SC_OP_INVALID BIT(0) +#define SC_OP_BEACONS BIT(1) +#define SC_OP_RXAGGR BIT(2) +#define SC_OP_TXAGGR BIT(3) +#define SC_OP_FULL_RESET BIT(4) +#define SC_OP_PREAMBLE_SHORT BIT(5) +#define SC_OP_PROTECT_ENABLE BIT(6) +#define SC_OP_RXFLUSH BIT(7) +#define SC_OP_LED_ASSOCIATED BIT(8) +#define SC_OP_RFKILL_REGISTERED BIT(9) +#define SC_OP_RFKILL_SW_BLOCKED BIT(10) +#define SC_OP_RFKILL_HW_BLOCKED BIT(11) +#define SC_OP_WAIT_FOR_BEACON BIT(12) +#define SC_OP_LED_ON BIT(13) +#define SC_OP_SCANNING BIT(14) +#define SC_OP_TSF_RESET BIT(15) + +struct ath_bus_ops { + void (*read_cachesize)(struct ath_softc *sc, int *csz); + void (*cleanup)(struct ath_softc *sc); + bool (*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data); +}; + +struct ath_wiphy; + +struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; + + spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ + struct ath_wiphy *pri_wiphy; + struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may + * have NULL entries */ + int num_sec_wiphy; /* number of sec_wiphy pointers in the array */ + int chan_idx; + int chan_is_ht; + struct ath_wiphy *next_wiphy; + struct work_struct chan_work; + int wiphy_select_failures; + unsigned long wiphy_select_first_fail; + struct delayed_work wiphy_work; + unsigned long wiphy_scheduler_int; + int wiphy_scheduler_index; + + struct tasklet_struct intr_tq; + struct tasklet_struct bcon_tasklet; + struct ath_hw *sc_ah; + void __iomem *mem; + int irq; + spinlock_t sc_resetlock; + spinlock_t sc_serial_rw; + struct mutex mutex; + + u8 curbssid[ETH_ALEN]; + u8 bssidmask[ETH_ALEN]; + u32 intrstatus; + u32 sc_flags; /* SC_OP_* */ + u16 curtxpow; + u16 curaid; + u16 cachelsz; + u8 nbcnvifs; + u16 nvifs; + u8 tx_chainmask; + u8 rx_chainmask; + u32 keymax; + DECLARE_BITMAP(keymap, ATH_KEYMAX); + u8 splitmic; + atomic_t ps_usecount; + enum ath9k_int imask; + enum ath9k_ht_extprotspacing ht_extprotspacing; + enum ath9k_ht_macmode tx_chan_width; + + struct ath_config config; + struct ath_rx rx; + struct ath_tx tx; + struct ath_beacon beacon; + struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; + struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; + struct ath_rate_table *cur_rate_table; + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + + struct ath_led radio_led; + struct ath_led assoc_led; + struct ath_led tx_led; + struct ath_led rx_led; + struct delayed_work ath_led_blink_work; + int led_on_duration; + int led_off_duration; + int led_on_cnt; + int led_off_cnt; + + struct ath_rfkill rf_kill; + struct ath_ani ani; + struct ath9k_node_stats nodestats; +#ifdef CONFIG_ATH9K_DEBUG + struct ath9k_debug debug; +#endif + struct ath_bus_ops *bus_ops; +}; + +struct ath_wiphy { + struct ath_softc *sc; /* shared for all virtual wiphys */ + struct ieee80211_hw *hw; + enum ath_wiphy_state { + ATH_WIPHY_INACTIVE, + ATH_WIPHY_ACTIVE, + ATH_WIPHY_PAUSING, + ATH_WIPHY_PAUSED, + ATH_WIPHY_SCAN, + } state; + int chan_idx; + int chan_is_ht; +}; + +int ath_reset(struct ath_softc *sc, bool retry_tx); +int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); +int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); +int ath_cabq_update(struct ath_softc *); + +static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) +{ + sc->bus_ops->read_cachesize(sc, csz); +} + +static inline void ath_bus_cleanup(struct ath_softc *sc) +{ + sc->bus_ops->cleanup(sc); +} + +extern struct ieee80211_ops ath9k_ops; + +irqreturn_t ath_isr(int irq, void *dev); +void ath_cleanup(struct ath_softc *sc); +int ath_attach(u16 devid, struct ath_softc *sc); +void ath_detach(struct ath_softc *sc); +const char *ath_mac_bb_name(u32 mac_bb_version); +const char *ath_rf_name(u16 rf_version); +void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); +void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, + struct ath9k_channel *ichan); +void ath_update_chainmask(struct ath_softc *sc, int is_ht); +int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, + struct ath9k_channel *hchan); +void ath_radio_enable(struct ath_softc *sc); +void ath_radio_disable(struct ath_softc *sc); + +#ifdef CONFIG_PCI +int ath_pci_init(void); +void ath_pci_exit(void); +#else +static inline int ath_pci_init(void) { return 0; }; +static inline void ath_pci_exit(void) {}; +#endif + +#ifdef CONFIG_ATHEROS_AR71XX +int ath_ahb_init(void); +void ath_ahb_exit(void); +#else +static inline int ath_ahb_init(void) { return 0; }; +static inline void ath_ahb_exit(void) {}; +#endif + +static inline void ath9k_ps_wakeup(struct ath_softc *sc) +{ + if (atomic_inc_return(&sc->ps_usecount) == 1) + if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { + sc->sc_ah->restore_mode = sc->sc_ah->power_mode; + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + } +} + +static inline void ath9k_ps_restore(struct ath_softc *sc) +{ + if (atomic_dec_and_test(&sc->ps_usecount)) + if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && + !(sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) + ath9k_hw_setpower(sc->sc_ah, + sc->sc_ah->restore_mode); +} + + +void ath9k_set_bssid_mask(struct ieee80211_hw *hw); +int ath9k_wiphy_add(struct ath_softc *sc); +int ath9k_wiphy_del(struct ath_wiphy *aphy); +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); +int ath9k_wiphy_pause(struct ath_wiphy *aphy); +int ath9k_wiphy_unpause(struct ath_wiphy *aphy); +int ath9k_wiphy_select(struct ath_wiphy *aphy); +void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int); +void ath9k_wiphy_chan_work(struct work_struct *work); +bool ath9k_wiphy_started(struct ath_softc *sc); +void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, + struct ath_wiphy *selected); +bool ath9k_wiphy_scanning(struct ath_softc *sc); +void ath9k_wiphy_work(struct work_struct *work); + +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +static inline void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) +{ + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + iowrite32(val, ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + iowrite32(val, ah->ah_sc->mem + reg_offset); +} + +static inline unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) +{ + u32 val; + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + val = ioread32(ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + val = ioread32(ah->ah_sc->mem + reg_offset); + return val; +} + +#endif /* ATH9K_H */ diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c new file mode 100644 index 000000000000..eb4759fc6a0d --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -0,0 +1,743 @@ +/* + * 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 "ath9k.h" + +#define FUDGE 2 + +/* + * This function will modify certain transmit queue properties depending on + * the operating mode of the station (AP or AdHoc). Parameters are AIFS + * settings and channel width min/max +*/ +static int ath_beaconq_config(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_tx_queue_info qi; + + ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); + if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { + /* Always burst out beacon and CAB traffic. */ + qi.tqi_aifs = 1; + qi.tqi_cwmin = 0; + qi.tqi_cwmax = 0; + } else { + /* Adhoc mode; important thing is to use 2x cwmin. */ + qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs; + qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin; + qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax; + } + + if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to update h/w beacon queue parameters\n"); + return 0; + } else { + ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); + return 1; + } +} + +/* + * Associates the beacon frame buffer with a transmit descriptor. Will set + * up all required antenna switch parameters, rate codes, and channel flags. + * Beacons are always sent out at the lowest rate, and are not retried. +*/ +static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, + struct ath_buf *bf) +{ + struct sk_buff *skb = bf->bf_mpdu; + struct ath_hw *ah = sc->sc_ah; + struct ath_desc *ds; + struct ath9k_11n_rate_series series[4]; + struct ath_rate_table *rt; + int flags, antenna, ctsrate = 0, ctsduration = 0; + u8 rate; + + ds = bf->bf_desc; + flags = ATH9K_TXDESC_NOACK; + + if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && + (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { + ds->ds_link = bf->bf_daddr; /* self-linked */ + flags |= ATH9K_TXDESC_VEOL; + /* Let hardware handle antenna switching. */ + antenna = 0; + } else { + ds->ds_link = 0; + /* + * Switch antenna every beacon. + * Should only switch every beacon period, not for every SWBA + * XXX assumes two antennae + */ + antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); + } + + ds->ds_data = bf->bf_buf_addr; + + rt = sc->cur_rate_table; + rate = rt->info[0].ratecode; + if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) + rate |= rt->info[0].short_preamble; + + ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, + ATH9K_PKT_TYPE_BEACON, + MAX_RATE_POWER, + ATH9K_TXKEYIX_INVALID, + ATH9K_KEY_TYPE_CLEAR, + flags); + + /* NB: beacon's BufLen must be a multiple of 4 bytes */ + ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), + true, true, ds); + + memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); + series[0].Tries = 1; + series[0].Rate = rate; + series[0].ChSel = sc->tx_chainmask; + series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; + ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, + series, 4, 0); +} + +static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_buf *bf; + struct ath_vif *avp; + struct sk_buff *skb; + struct ath_txq *cabq; + struct ieee80211_tx_info *info; + int cabq_depth; + + if (aphy->state != ATH_WIPHY_ACTIVE) + return NULL; + + avp = (void *)vif->drv_priv; + cabq = sc->beacon.cabq; + + if (avp->av_bcbuf == NULL) + return NULL; + + /* Release the old beacon first */ + + bf = avp->av_bcbuf; + skb = bf->bf_mpdu; + if (skb) { + dma_unmap_single(sc->dev, bf->bf_dmacontext, + skb->len, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + } + + /* Get a new beacon from mac80211 */ + + skb = ieee80211_beacon_get(hw, vif); + bf->bf_mpdu = skb; + if (skb == NULL) + return NULL; + ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = + avp->tsf_adjust; + + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + /* + * TODO: make sure the seq# gets assigned properly (vs. other + * TX frames) + */ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + sc->tx.seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); + } + + bf->bf_buf_addr = bf->bf_dmacontext = + dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n"); + return NULL; + } + + skb = ieee80211_get_buffered_bc(hw, vif); + + /* + * if the CABQ traffic from previous DTIM is pending and the current + * beacon is also a DTIM. + * 1) if there is only one vif let the cab traffic continue. + * 2) if there are more than one vif and we are using staggered + * beacons, then drain the cabq by dropping all the frames in + * the cabq so that the current vifs cab traffic can be scheduled. + */ + spin_lock_bh(&cabq->axq_lock); + cabq_depth = cabq->axq_depth; + spin_unlock_bh(&cabq->axq_lock); + + if (skb && cabq_depth) { + if (sc->nvifs > 1) { + DPRINTF(sc, ATH_DBG_BEACON, + "Flushing previous cabq traffic\n"); + ath_draintxq(sc, cabq, false); + } + } + + ath_beacon_setup(sc, avp, bf); + + while (skb) { + ath_tx_cabq(hw, skb); + skb = ieee80211_get_buffered_bc(hw, vif); + } + + return bf; +} + +/* + * Startup beacon transmission for adhoc mode when they are sent entirely + * by the hardware using the self-linked descriptor + veol trick. +*/ +static void ath_beacon_start_adhoc(struct ath_softc *sc, + struct ieee80211_vif *vif) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_buf *bf; + struct ath_vif *avp; + struct sk_buff *skb; + + avp = (void *)vif->drv_priv; + + if (avp->av_bcbuf == NULL) + return; + + bf = avp->av_bcbuf; + skb = bf->bf_mpdu; + + ath_beacon_setup(sc, avp, bf); + + /* NB: caller is known to have already stopped tx dma */ + ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); + ath9k_hw_txstart(ah, sc->beacon.beaconq); + DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", + sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); +} + +int ath_beaconq_setup(struct ath_hw *ah) +{ + struct ath9k_tx_queue_info qi; + + memset(&qi, 0, sizeof(qi)); + qi.tqi_aifs = 1; + qi.tqi_cwmin = 0; + qi.tqi_cwmax = 0; + /* NB: don't enable any interrupts */ + return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); +} + +int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) +{ + struct ath_softc *sc = aphy->sc; + struct ath_vif *avp; + struct ath_buf *bf; + struct sk_buff *skb; + __le64 tstamp; + + avp = (void *)vif->drv_priv; + + /* Allocate a beacon descriptor if we haven't done so. */ + if (!avp->av_bcbuf) { + /* Allocate beacon state for hostap/ibss. We know + * a buffer is available. */ + avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, + struct ath_buf, list); + list_del(&avp->av_bcbuf->list); + + if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || + !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { + int slot; + /* + * Assign the vif to a beacon xmit slot. As + * above, this cannot fail to find one. + */ + avp->av_bslot = 0; + for (slot = 0; slot < ATH_BCBUF; slot++) + if (sc->beacon.bslot[slot] == NULL) { + /* + * XXX hack, space out slots to better + * deal with misses + */ + if (slot+1 < ATH_BCBUF && + sc->beacon.bslot[slot+1] == NULL) { + avp->av_bslot = slot+1; + break; + } + avp->av_bslot = slot; + /* NB: keep looking for a double slot */ + } + BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); + sc->beacon.bslot[avp->av_bslot] = vif; + sc->beacon.bslot_aphy[avp->av_bslot] = aphy; + sc->nbcnvifs++; + } + } + + /* release the previous beacon frame, if it already exists. */ + bf = avp->av_bcbuf; + if (bf->bf_mpdu != NULL) { + skb = bf->bf_mpdu; + dma_unmap_single(sc->dev, bf->bf_dmacontext, + skb->len, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + } + + /* NB: the beacon data buffer must be 32-bit aligned. */ + skb = ieee80211_beacon_get(sc->hw, vif); + if (skb == NULL) { + DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n"); + return -ENOMEM; + } + + tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + sc->beacon.bc_tstamp = le64_to_cpu(tstamp); + /* Calculate a TSF adjustment factor required for staggered beacons. */ + if (avp->av_bslot > 0) { + u64 tsfadjust; + int intval; + + intval = sc->hw->conf.beacon_int ? + sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + + /* + * Calculate the TSF offset for this beacon slot, i.e., the + * number of usecs that need to be added to the timestamp field + * in Beacon and Probe Response frames. Beacon slot 0 is + * processed at the correct offset, so it does not require TSF + * adjustment. Other slots are adjusted to get the timestamp + * close to the TBTT for the BSS. + */ + tsfadjust = intval * avp->av_bslot / ATH_BCBUF; + avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); + + DPRINTF(sc, ATH_DBG_BEACON, + "stagger beacons, bslot %d intval %u tsfadjust %llu\n", + avp->av_bslot, intval, (unsigned long long)tsfadjust); + + ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = + avp->tsf_adjust; + } else + avp->tsf_adjust = cpu_to_le64(0); + + bf->bf_mpdu = skb; + bf->bf_buf_addr = bf->bf_dmacontext = + dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + DPRINTF(sc, ATH_DBG_FATAL, + "dma_mapping_error on beacon alloc\n"); + return -ENOMEM; + } + + return 0; +} + +void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) +{ + if (avp->av_bcbuf != NULL) { + struct ath_buf *bf; + + if (avp->av_bslot != -1) { + sc->beacon.bslot[avp->av_bslot] = NULL; + sc->beacon.bslot_aphy[avp->av_bslot] = NULL; + sc->nbcnvifs--; + } + + bf = avp->av_bcbuf; + if (bf->bf_mpdu != NULL) { + struct sk_buff *skb = bf->bf_mpdu; + dma_unmap_single(sc->dev, bf->bf_dmacontext, + skb->len, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + } + list_add_tail(&bf->list, &sc->beacon.bbuf); + + avp->av_bcbuf = NULL; + } +} + +void ath_beacon_tasklet(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *)data; + struct ath_hw *ah = sc->sc_ah; + struct ath_buf *bf = NULL; + struct ieee80211_vif *vif; + struct ath_wiphy *aphy; + int slot; + u32 bfaddr, bc = 0, tsftu; + u64 tsf; + u16 intval; + + /* + * Check if the previous beacon has gone out. If + * not don't try to post another, skip this period + * and wait for the next. Missed beacons indicate + * a problem and should not occur. If we miss too + * many consecutive beacons reset the device. + */ + if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { + sc->beacon.bmisscnt++; + + if (sc->beacon.bmisscnt < BSTUCK_THRESH) { + DPRINTF(sc, ATH_DBG_BEACON, + "missed %u consecutive beacons\n", + sc->beacon.bmisscnt); + } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { + DPRINTF(sc, ATH_DBG_BEACON, + "beacon is officially stuck\n"); + ath_reset(sc, false); + } + + return; + } + + if (sc->beacon.bmisscnt != 0) { + DPRINTF(sc, ATH_DBG_BEACON, + "resume beacon xmit after %u misses\n", + sc->beacon.bmisscnt); + sc->beacon.bmisscnt = 0; + } + + /* + * Generate beacon frames. we are sending frames + * staggered so calculate the slot for this frame based + * on the tsf to safeguard against missing an swba. + */ + + intval = sc->hw->conf.beacon_int ? + sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + + tsf = ath9k_hw_gettsf64(ah); + tsftu = TSF_TO_TU(tsf>>32, tsf); + slot = ((tsftu % intval) * ATH_BCBUF) / intval; + /* + * Reverse the slot order to get slot 0 on the TBTT offset that does + * not require TSF adjustment and other slots adding + * slot/ATH_BCBUF * beacon_int to timestamp. For example, with + * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. + * and slot 0 is at correct offset to TBTT. + */ + slot = ATH_BCBUF - slot - 1; + vif = sc->beacon.bslot[slot]; + aphy = sc->beacon.bslot_aphy[slot]; + + DPRINTF(sc, ATH_DBG_BEACON, + "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", + slot, tsf, tsftu, intval, vif); + + bfaddr = 0; + if (vif) { + bf = ath_beacon_generate(aphy->hw, vif); + if (bf != NULL) { + bfaddr = bf->bf_daddr; + bc = 1; + } + } + + /* + * Handle slot time change when a non-ERP station joins/leaves + * an 11g network. The 802.11 layer notifies us via callback, + * we mark updateslot, then wait one beacon before effecting + * the change. This gives associated stations at least one + * beacon interval to note the state change. + * + * NB: The slot time change state machine is clocked according + * to whether we are bursting or staggering beacons. We + * recognize the request to update and record the current + * slot then don't transition until that slot is reached + * again. If we miss a beacon for that slot then we'll be + * slow to transition but we'll be sure at least one beacon + * interval has passed. When bursting slot is always left + * set to ATH_BCBUF so this check is a noop. + */ + if (sc->beacon.updateslot == UPDATE) { + sc->beacon.updateslot = COMMIT; /* commit next beacon */ + sc->beacon.slotupdate = slot; + } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { + ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); + sc->beacon.updateslot = OK; + } + if (bfaddr != 0) { + /* + * Stop any current dma and put the new frame(s) on the queue. + * This should never fail since we check above that no frames + * are still pending on the queue. + */ + if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { + DPRINTF(sc, ATH_DBG_FATAL, + "beacon queue %u did not stop?\n", sc->beacon.beaconq); + } + + /* NB: cabq traffic should already be queued and primed */ + ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); + ath9k_hw_txstart(ah, sc->beacon.beaconq); + + sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ + } +} + +/* + * For multi-bss ap support beacons are either staggered evenly over N slots or + * burst together. For the former arrange for the SWBA to be delivered for each + * slot. Slots that are not occupied will generate nothing. + */ +static void ath_beacon_config_ap(struct ath_softc *sc, + struct ath_beacon_config *conf, + struct ath_vif *avp) +{ + u32 nexttbtt, intval; + + /* Configure the timers only when the TSF has to be reset */ + + if (!(sc->sc_flags & SC_OP_TSF_RESET)) + return; + + /* NB: the beacon interval is kept internally in TU's */ + intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; + intval /= ATH_BCBUF; /* for staggered beacons */ + nexttbtt = intval; + intval |= ATH9K_BEACON_RESET_TSF; + + /* + * In AP mode we enable the beacon timers and SWBA interrupts to + * prepare beacon frames. + */ + intval |= ATH9K_BEACON_ENA; + sc->imask |= ATH9K_INT_SWBA; + ath_beaconq_config(sc); + + /* Set the computed AP beacon timers */ + + ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); + sc->beacon.bmisscnt = 0; + ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + + /* Clear the reset TSF flag, so that subsequent beacon updation + will not reset the HW TSF. */ + + sc->sc_flags &= ~SC_OP_TSF_RESET; +} + +/* + * This sets up the beacon timers according to the timestamp of the last + * received beacon and the current TSF, configures PCF and DTIM + * handling, programs the sleep registers so the hardware will wakeup in + * time to receive beacons, and configures the beacon miss handling so + * we'll receive a BMISS interrupt when we stop seeing beacons from the AP + * we've associated with. + */ +static void ath_beacon_config_sta(struct ath_softc *sc, + struct ath_beacon_config *conf, + struct ath_vif *avp) +{ + struct ath9k_beacon_state bs; + int dtimperiod, dtimcount, sleepduration; + int cfpperiod, cfpcount; + u32 nexttbtt = 0, intval, tsftu; + u64 tsf; + + memset(&bs, 0, sizeof(bs)); + intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; + + /* + * Setup dtim and cfp parameters according to + * last beacon we received (which may be none). + */ + dtimperiod = conf->dtim_period; + if (dtimperiod <= 0) /* NB: 0 if not known */ + dtimperiod = 1; + dtimcount = conf->dtim_count; + if (dtimcount >= dtimperiod) /* NB: sanity check */ + dtimcount = 0; + cfpperiod = 1; /* NB: no PCF support yet */ + cfpcount = 0; + + sleepduration = conf->listen_interval * intval; + if (sleepduration <= 0) + sleepduration = intval; + + /* + * Pull nexttbtt forward to reflect the current + * TSF and calculate dtim+cfp state for the result. + */ + tsf = ath9k_hw_gettsf64(sc->sc_ah); + tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; + do { + nexttbtt += intval; + if (--dtimcount < 0) { + dtimcount = dtimperiod - 1; + if (--cfpcount < 0) + cfpcount = cfpperiod - 1; + } + } while (nexttbtt < tsftu); + + bs.bs_intval = intval; + bs.bs_nexttbtt = nexttbtt; + bs.bs_dtimperiod = dtimperiod*intval; + bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; + bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; + bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; + bs.bs_cfpmaxduration = 0; + + /* + * Calculate the number of consecutive beacons to miss* before taking + * a BMISS interrupt. The configuration is specified in TU so we only + * need calculate based on the beacon interval. Note that we clamp the + * result to at most 15 beacons. + */ + if (sleepduration > intval) { + bs.bs_bmissthreshold = conf->listen_interval * + ATH_DEFAULT_BMISS_LIMIT / 2; + } else { + bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval); + if (bs.bs_bmissthreshold > 15) + bs.bs_bmissthreshold = 15; + else if (bs.bs_bmissthreshold <= 0) + bs.bs_bmissthreshold = 1; + } + + /* + * Calculate sleep duration. The configuration is given in ms. + * We ensure a multiple of the beacon period is used. Also, if the sleep + * duration is greater than the DTIM period then it makes senses + * to make it a multiple of that. + * + * XXX fixed at 100ms + */ + + bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); + if (bs.bs_sleepduration > bs.bs_dtimperiod) + bs.bs_sleepduration = bs.bs_dtimperiod; + + /* TSF out of range threshold fixed at 1 second */ + bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; + + DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); + DPRINTF(sc, ATH_DBG_BEACON, + "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", + bs.bs_bmissthreshold, bs.bs_sleepduration, + bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); + + /* Set the computed STA beacon timers */ + + ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); + sc->imask |= ATH9K_INT_BMISS; + ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); +} + +static void ath_beacon_config_adhoc(struct ath_softc *sc, + struct ath_beacon_config *conf, + struct ath_vif *avp, + struct ieee80211_vif *vif) +{ + u64 tsf; + u32 tsftu, intval, nexttbtt; + + intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; + + /* Pull nexttbtt forward to reflect the current TSF */ + + nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); + if (nexttbtt == 0) + nexttbtt = intval; + else if (intval) + nexttbtt = roundup(nexttbtt, intval); + + tsf = ath9k_hw_gettsf64(sc->sc_ah); + tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; + do { + nexttbtt += intval; + } while (nexttbtt < tsftu); + + DPRINTF(sc, ATH_DBG_BEACON, + "IBSS nexttbtt %u intval %u (%u)\n", + nexttbtt, intval, conf->beacon_interval); + + /* + * In IBSS mode enable the beacon timers but only enable SWBA interrupts + * if we need to manually prepare beacon frames. Otherwise we use a + * self-linked tx descriptor and let the hardware deal with things. + */ + intval |= ATH9K_BEACON_ENA; + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) + sc->imask |= ATH9K_INT_SWBA; + + ath_beaconq_config(sc); + + /* Set the computed ADHOC beacon timers */ + + ath9k_hw_set_interrupts(sc->sc_ah, 0); + ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); + sc->beacon.bmisscnt = 0; + ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) + ath_beacon_start_adhoc(sc, vif); +} + +void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) +{ + struct ath_beacon_config conf; + + /* Setup the beacon configuration parameters */ + + memset(&conf, 0, sizeof(struct ath_beacon_config)); + conf.beacon_interval = sc->hw->conf.beacon_int ? + sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + conf.listen_interval = 1; + conf.dtim_period = conf.beacon_interval; + conf.dtim_count = 1; + conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; + + if (vif) { + struct ath_vif *avp = (struct ath_vif *)vif->drv_priv; + + switch(avp->av_opmode) { + case NL80211_IFTYPE_AP: + ath_beacon_config_ap(sc, &conf, avp); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + ath_beacon_config_adhoc(sc, &conf, avp, vif); + break; + case NL80211_IFTYPE_STATION: + ath_beacon_config_sta(sc, &conf, avp); + break; + default: + DPRINTF(sc, ATH_DBG_CONFIG, + "Unsupported beaconing mode\n"); + return; + } + + sc->sc_flags |= SC_OP_BEACONS; + } +} diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c new file mode 100644 index 000000000000..e2d62e97131c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -0,0 +1,1060 @@ +/* + * 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 "ath9k.h" + +/* We can tune this as we go by monitoring really low values */ +#define ATH9K_NF_TOO_LOW -60 + +/* AR5416 may return very high value (like -31 dBm), in those cases the nf + * is incorrect and we should use the static NF value. Later we can try to + * find out why they are reporting these values */ + +static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) +{ + if (nf > ATH9K_NF_TOO_LOW) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "noise floor value detected (%d) is " + "lower than what we think is a " + "reasonable value (%d)\n", + nf, ATH9K_NF_TOO_LOW); + return false; + } + return true; +} + +static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) +{ + int16_t nfval; + int16_t sort[ATH9K_NF_CAL_HIST_MAX]; + int i, j; + + for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) + sort[i] = nfCalBuffer[i]; + + for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { + for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { + if (sort[j] > sort[j - 1]) { + nfval = sort[j]; + sort[j] = sort[j - 1]; + sort[j - 1] = nfval; + } + } + } + nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; + + return nfval; +} + +static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, + int16_t *nfarray) +{ + int i; + + for (i = 0; i < NUM_NF_READINGS; i++) { + h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; + + if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) + h[i].currIndex = 0; + + if (h[i].invalidNFcount > 0) { + if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || + nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { + h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; + } else { + h[i].invalidNFcount--; + h[i].privNF = nfarray[i]; + } + } else { + h[i].privNF = + ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); + } + } + return; +} + +static void ath9k_hw_do_getnf(struct ath_hw *ah, + int16_t nfarray[NUM_NF_READINGS]) +{ + int16_t nf; + + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 0] is %d\n", nf); + nfarray[0] = nf; + + if (!AR_SREV_9285(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR9280_PHY_CH1_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR_PHY_CH1_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + if (!AR_SREV_9280(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), + AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; + } + } + + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), + AR9280_PHY_EXT_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), + AR_PHY_EXT_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 0] is %d\n", nf); + nfarray[3] = nf; + + if (!AR_SREV_9285(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR9280_PHY_CH1_EXT_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR_PHY_CH1_EXT_MINCCA_PWR); + + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + if (!AR_SREV_9280(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), + AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + } + } +} + +static bool getNoiseFloorThresh(struct ath_hw *ah, + enum ieee80211_band band, + int16_t *nft) +{ + switch (band) { + case IEEE80211_BAND_5GHZ: + *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); + break; + case IEEE80211_BAND_2GHZ: + *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); + break; + default: + BUG_ON(1); + return false; + } + + return true; +} + +static void ath9k_hw_setup_calibration(struct ath_hw *ah, + struct hal_cal_list *currCal) +{ + REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), + AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, + currCal->calData->calCountMax); + + switch (currCal->calData->calType) { + case IQ_MISMATCH_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "starting IQ Mismatch Calibration\n"); + break; + case ADC_GAIN_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "starting ADC Gain Calibration\n"); + break; + case ADC_DC_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "starting ADC DC Calibration\n"); + break; + case ADC_DC_INIT_CAL: + REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "starting Init ADC DC Calibration\n"); + break; + } + + REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), + AR_PHY_TIMING_CTRL4_DO_CAL); +} + +static void ath9k_hw_reset_calibration(struct ath_hw *ah, + struct hal_cal_list *currCal) +{ + int i; + + ath9k_hw_setup_calibration(ah, currCal); + + currCal->calState = CAL_RUNNING; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->meas0.sign[i] = 0; + ah->meas1.sign[i] = 0; + ah->meas2.sign[i] = 0; + ah->meas3.sign[i] = 0; + } + + ah->cal_samples = 0; +} + +static void ath9k_hw_per_calibration(struct ath_hw *ah, + struct ath9k_channel *ichan, + u8 rxchainmask, + struct hal_cal_list *currCal, + bool *isCalDone) +{ + *isCalDone = false; + + if (currCal->calState == CAL_RUNNING) { + if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & + AR_PHY_TIMING_CTRL4_DO_CAL)) { + + currCal->calData->calCollect(ah); + ah->cal_samples++; + + if (ah->cal_samples >= currCal->calData->calNumSamples) { + int i, numChains = 0; + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (rxchainmask & (1 << i)) + numChains++; + } + + currCal->calData->calPostProc(ah, numChains); + ichan->CalValid |= currCal->calData->calType; + currCal->calState = CAL_DONE; + *isCalDone = true; + } else { + ath9k_hw_setup_calibration(ah, currCal); + } + } + } else if (!(ichan->CalValid & currCal->calData->calType)) { + ath9k_hw_reset_calibration(ah, currCal); + } +} + +/* Assumes you are talking about the currently configured channel */ +static bool ath9k_hw_iscal_supported(struct ath_hw *ah, + enum hal_cal_types calType) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + + switch (calType & ah->supp_cals) { + case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ + return true; + case ADC_GAIN_CAL: + case ADC_DC_CAL: + if (conf->channel->band == IEEE80211_BAND_5GHZ && + conf_is_ht20(conf)) + return true; + break; + } + return false; +} + +static void ath9k_hw_iqcal_collect(struct ath_hw *ah) +{ + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalPowerMeasI[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalPowerMeasQ[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalIqCorrMeas[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", + ah->cal_samples, i, ah->totalPowerMeasI[i], + ah->totalPowerMeasQ[i], + ah->totalIqCorrMeas[i]); + } +} + +static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) +{ + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalAdcIOddPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalAdcIEvenPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalAdcQOddPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ah->totalAdcQEvenPhase[i] += + REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " + "oddq=0x%08x; evenq=0x%08x;\n", + ah->cal_samples, i, + ah->totalAdcIOddPhase[i], + ah->totalAdcIEvenPhase[i], + ah->totalAdcQOddPhase[i], + ah->totalAdcQEvenPhase[i]); + } +} + +static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) +{ + int i; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + ah->totalAdcDcOffsetIOddPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); + ah->totalAdcDcOffsetIEvenPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); + ah->totalAdcDcOffsetQOddPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); + ah->totalAdcDcOffsetQEvenPhase[i] += + (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " + "oddq=0x%08x; evenq=0x%08x;\n", + ah->cal_samples, i, + ah->totalAdcDcOffsetIOddPhase[i], + ah->totalAdcDcOffsetIEvenPhase[i], + ah->totalAdcDcOffsetQOddPhase[i], + ah->totalAdcDcOffsetQEvenPhase[i]); + } +} + +static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) +{ + u32 powerMeasQ, powerMeasI, iqCorrMeas; + u32 qCoffDenom, iCoffDenom; + int32_t qCoff, iCoff; + int iqCorrNeg, i; + + for (i = 0; i < numChains; i++) { + powerMeasI = ah->totalPowerMeasI[i]; + powerMeasQ = ah->totalPowerMeasQ[i]; + iqCorrMeas = ah->totalIqCorrMeas[i]; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Starting IQ Cal and Correction for Chain %d\n", + i); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Orignal: Chn %diq_corr_meas = 0x%08x\n", + i, ah->totalIqCorrMeas[i]); + + iqCorrNeg = 0; + + if (iqCorrMeas > 0x80000000) { + iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; + iqCorrNeg = 1; + } + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", + iqCorrNeg); + + iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; + qCoffDenom = powerMeasQ / 64; + + if (powerMeasQ != 0) { + iCoff = iqCorrMeas / iCoffDenom; + qCoff = powerMeasI / qCoffDenom - 64; + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d iCoff = 0x%08x\n", i, iCoff); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d qCoff = 0x%08x\n", i, qCoff); + + iCoff = iCoff & 0x3f; + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "New: Chn %d iCoff = 0x%08x\n", i, iCoff); + if (iqCorrNeg == 0x0) + iCoff = 0x40 - iCoff; + + if (qCoff > 15) + qCoff = 15; + else if (qCoff <= -16) + qCoff = 16; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", + i, iCoff, qCoff); + + REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, + iCoff); + REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, + qCoff); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "IQ Cal and Correction done for Chain %d\n", + i); + } + } + + REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), + AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); +} + +static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) +{ + u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; + u32 qGainMismatch, iGainMismatch, val, i; + + for (i = 0; i < numChains; i++) { + iOddMeasOffset = ah->totalAdcIOddPhase[i]; + iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; + qOddMeasOffset = ah->totalAdcQOddPhase[i]; + qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Starting ADC Gain Cal for Chain %d\n", i); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_i = 0x%08x\n", i, + iOddMeasOffset); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_i = 0x%08x\n", i, + iEvenMeasOffset); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_q = 0x%08x\n", i, + qOddMeasOffset); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_q = 0x%08x\n", i, + qEvenMeasOffset); + + if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { + iGainMismatch = + ((iEvenMeasOffset * 32) / + iOddMeasOffset) & 0x3f; + qGainMismatch = + ((qOddMeasOffset * 32) / + qEvenMeasOffset) & 0x3f; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d gain_mismatch_i = 0x%08x\n", i, + iGainMismatch); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d gain_mismatch_q = 0x%08x\n", i, + qGainMismatch); + + val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xfffff000; + val |= (qGainMismatch) | (iGainMismatch << 6); + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "ADC Gain Cal done for Chain %d\n", i); + } + } + + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | + AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); +} + +static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) +{ + u32 iOddMeasOffset, iEvenMeasOffset, val, i; + int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; + const struct hal_percal_data *calData = + ah->cal_list_curr->calData; + u32 numSamples = + (1 << (calData->calCountMax + 5)) * calData->calNumSamples; + + for (i = 0; i < numChains; i++) { + iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; + iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; + qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; + qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Starting ADC DC Offset Cal for Chain %d\n", i); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_i = %d\n", i, + iOddMeasOffset); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_i = %d\n", i, + iEvenMeasOffset); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_odd_q = %d\n", i, + qOddMeasOffset); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d pwr_meas_even_q = %d\n", i, + qEvenMeasOffset); + + iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / + numSamples) & 0x1ff; + qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / + numSamples) & 0x1ff; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, + iDcMismatch); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, + qDcMismatch); + + val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); + val &= 0xc0000fff; + val |= (qDcMismatch << 12) | (iDcMismatch << 21); + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "ADC DC Offset Cal done for Chain %d\n", i); + } + + REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), + REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | + AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); +} + +/* This is done for the currently configured channel */ +bool ath9k_hw_reset_calvalid(struct ath_hw *ah) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + struct hal_cal_list *currCal = ah->cal_list_curr; + + if (!ah->curchan) + return true; + + if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) + return true; + + if (currCal == NULL) + return true; + + if (currCal->calState != CAL_DONE) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Calibration state incorrect, %d\n", + currCal->calState); + return true; + } + + if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) + return true; + + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "Resetting Cal %d state for channel %u\n", + currCal->calData->calType, conf->channel->center_freq); + + ah->curchan->CalValid &= ~currCal->calData->calType; + currCal->calState = CAL_WAITING; + + return false; +} + +void ath9k_hw_start_nfcal(struct ath_hw *ah) +{ + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_ENABLE_NF); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); +} + +void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +{ + struct ath9k_nfcal_hist *h; + int i, j; + int32_t val; + const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, + AR_PHY_CH2_CCA, + AR_PHY_EXT_CCA, + AR_PHY_CH1_EXT_CCA, + AR_PHY_CH2_EXT_CCA + }; + u8 chainmask; + + if (AR_SREV_9285(ah)) + chainmask = 0x9; + else if (AR_SREV_9280(ah)) + chainmask = 0x1B; + else + chainmask = 0x3F; + + h = ah->nfCalHist; + + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { + val = REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (h[i].privNF) << 1) & 0x1ff); + REG_WRITE(ah, ar5416_cca_regs[i], val); + } + } + + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_ENABLE_NF); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + + for (j = 0; j < 1000; j++) { + if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & + AR_PHY_AGC_CONTROL_NF) == 0) + break; + udelay(10); + } + + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { + val = REG_READ(ah, ar5416_cca_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (-50) << 1) & 0x1ff); + REG_WRITE(ah, ar5416_cca_regs[i], val); + } + } +} + +int16_t ath9k_hw_getnf(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + int16_t nf, nfThresh; + int16_t nfarray[NUM_NF_READINGS] = { 0 }; + struct ath9k_nfcal_hist *h; + struct ieee80211_channel *c = chan->chan; + + chan->channelFlags &= (~CHANNEL_CW_INT); + if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF did not complete in calibration window\n"); + nf = 0; + chan->rawNoiseFloor = nf; + return chan->rawNoiseFloor; + } else { + ath9k_hw_do_getnf(ah, nfarray); + nf = nfarray[0]; + if (getNoiseFloorThresh(ah, c->band, &nfThresh) + && nf > nfThresh) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "noise floor failed detected; " + "detected %d, threshold %d\n", + nf, nfThresh); + chan->channelFlags |= CHANNEL_CW_INT; + } + } + + h = ah->nfCalHist; + + ath9k_hw_update_nfcal_hist_buffer(h, nfarray); + chan->rawNoiseFloor = h[0].privNF; + + return chan->rawNoiseFloor; +} + +void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) +{ + int i, j; + + for (i = 0; i < NUM_NF_READINGS; i++) { + ah->nfCalHist[i].currIndex = 0; + ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE; + ah->nfCalHist[i].invalidNFcount = + AR_PHY_CCA_FILTERWINDOW_LENGTH; + for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { + ah->nfCalHist[i].nfCalBuffer[j] = + AR_PHY_CCA_MAX_GOOD_VALUE; + } + } +} + +s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) +{ + s16 nf; + + if (chan->rawNoiseFloor == 0) + nf = -96; + else + nf = chan->rawNoiseFloor; + + if (!ath9k_hw_nf_in_range(ah, nf)) + nf = ATH_DEFAULT_NOISE_FLOOR; + + return nf; +} + +static void ath9k_olc_temp_compensation(struct ath_hw *ah) +{ + u32 rddata, i; + int delta, currPDADC, regval; + + rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); + + currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + + if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) + delta = (currPDADC - ah->initPDADC + 4) / 8; + else + delta = (currPDADC - ah->initPDADC + 5) / 10; + + if (delta != ah->PDADCdelta) { + ah->PDADCdelta = delta; + for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { + regval = ah->originalGain[i] - delta; + if (regval < 0) + regval = 0; + + REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, + AR_PHY_TX_GAIN, regval); + } + } +} + +static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) +{ + + u32 regVal; + int i, offset, offs_6_1, offs_0; + u32 ccomp_org, reg_field; + u32 regList[][2] = { + { 0x786c, 0 }, + { 0x7854, 0 }, + { 0x7820, 0 }, + { 0x7824, 0 }, + { 0x7868, 0 }, + { 0x783c, 0 }, + { 0x7838, 0 }, + }; + + if (AR_SREV_9285_11(ah)) { + REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); + udelay(10); + } + + for (i = 0; i < ARRAY_SIZE(regList); i++) + regList[i][1] = REG_READ(ah, regList[i][0]); + + regVal = REG_READ(ah, 0x7834); + regVal &= (~(0x1)); + REG_WRITE(ah, 0x7834, regVal); + regVal = REG_READ(ah, 0x9808); + regVal |= (0x1 << 27); + REG_WRITE(ah, 0x9808, regVal); + + REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); + REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); + REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); + REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); + ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7); + + REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); + udelay(30); + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); + + for (i = 6; i > 0; i--) { + regVal = REG_READ(ah, 0x7834); + regVal |= (1 << (19 + i)); + REG_WRITE(ah, 0x7834, regVal); + udelay(1); + regVal = REG_READ(ah, 0x7834); + regVal &= (~(0x1 << (19 + i))); + reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); + regVal |= (reg_field << (19 + i)); + REG_WRITE(ah, 0x7834, regVal); + } + + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); + udelay(1); + reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); + offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); + offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); + + offset = (offs_6_1<<1) | offs_0; + offset = offset - 0; + offs_6_1 = offset>>1; + offs_0 = offset & 1; + + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); + REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); + + regVal = REG_READ(ah, 0x7834); + regVal |= 0x1; + REG_WRITE(ah, 0x7834, regVal); + regVal = REG_READ(ah, 0x9808); + regVal &= (~(0x1 << 27)); + REG_WRITE(ah, 0x9808, regVal); + + for (i = 0; i < ARRAY_SIZE(regList); i++) + REG_WRITE(ah, regList[i][0], regList[i][1]); + + REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); + + if (AR_SREV_9285_11(ah)) + REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); + +} + +bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, + u8 rxchainmask, bool longcal, + bool *isCalDone) +{ + struct hal_cal_list *currCal = ah->cal_list_curr; + + *isCalDone = true; + + if (currCal && + (currCal->calState == CAL_RUNNING || + currCal->calState == CAL_WAITING)) { + ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, + isCalDone); + if (*isCalDone) { + ah->cal_list_curr = currCal = currCal->calNext; + + if (currCal->calState == CAL_WAITING) { + *isCalDone = false; + ath9k_hw_reset_calibration(ah, currCal); + } + } + } + + if (longcal) { + if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + ath9k_hw_9285_pa_cal(ah); + + if (OLC_FOR_AR9280_20_LATER) + ath9k_olc_temp_compensation(ah); + ath9k_hw_getnf(ah, chan); + ath9k_hw_loadnf(ah, ah->curchan); + ath9k_hw_start_nfcal(ah); + + if (chan->channelFlags & CHANNEL_CW_INT) + chan->channelFlags &= ~CHANNEL_CW_INT; + } + + return true; +} + +static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) +{ + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + if (chan->channelFlags & CHANNEL_HT20) { + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " + "calibration failed to complete in " + "1ms; noisy ??\n"); + return false; + } + REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " + "failed to complete in 1ms; noisy ??\n"); + return false; + } + + REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + + return true; +} + +bool ath9k_hw_init_cal(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { + if (!ar9285_clc(ah, chan)) + return false; + } else if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + + /* Kick off the cal */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); + + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, + AR_PHY_AGC_CONTROL_CAL, 0, + AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "offset calibration failed to complete in 1ms; " + "noisy environment?\n"); + return false; + } + + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } + + /* Calibrate the AGC */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); + + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "offset calibration failed to complete in 1ms; " + "noisy environment?\n"); + return false; + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + } + + /* Do PA Calibration */ + if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + ath9k_hw_9285_pa_cal(ah); + + /* Do NF Calibration */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_NF); + + ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + + if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { + if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { + INIT_CAL(&ah->adcgain_caldata); + INSERT_CAL(ah, &ah->adcgain_caldata); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "enabling ADC Gain Calibration.\n"); + } + if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { + INIT_CAL(&ah->adcdc_caldata); + INSERT_CAL(ah, &ah->adcdc_caldata); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "enabling ADC DC Calibration.\n"); + } + if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { + INIT_CAL(&ah->iq_caldata); + INSERT_CAL(ah, &ah->iq_caldata); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "enabling IQ Calibration.\n"); + } + + ah->cal_list_curr = ah->cal_list; + + if (ah->cal_list_curr) + ath9k_hw_reset_calibration(ah, ah->cal_list_curr); + } + + chan->CalValid = 0; + + return true; +} + +const struct hal_percal_data iq_cal_multi_sample = { + IQ_MISMATCH_CAL, + MAX_CAL_SAMPLES, + PER_MIN_LOG_COUNT, + ath9k_hw_iqcal_collect, + ath9k_hw_iqcalibrate +}; +const struct hal_percal_data iq_cal_single_sample = { + IQ_MISMATCH_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ath9k_hw_iqcal_collect, + ath9k_hw_iqcalibrate +}; +const struct hal_percal_data adc_gain_cal_multi_sample = { + ADC_GAIN_CAL, + MAX_CAL_SAMPLES, + PER_MIN_LOG_COUNT, + ath9k_hw_adc_gaincal_collect, + ath9k_hw_adc_gaincal_calibrate +}; +const struct hal_percal_data adc_gain_cal_single_sample = { + ADC_GAIN_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ath9k_hw_adc_gaincal_collect, + ath9k_hw_adc_gaincal_calibrate +}; +const struct hal_percal_data adc_dc_cal_multi_sample = { + ADC_DC_CAL, + MAX_CAL_SAMPLES, + PER_MIN_LOG_COUNT, + ath9k_hw_adc_dccal_collect, + ath9k_hw_adc_dccal_calibrate +}; +const struct hal_percal_data adc_dc_cal_single_sample = { + ADC_DC_CAL, + MIN_CAL_SAMPLES, + PER_MAX_LOG_COUNT, + ath9k_hw_adc_dccal_collect, + ath9k_hw_adc_dccal_calibrate +}; +const struct hal_percal_data adc_init_dc_cal = { + ADC_DC_INIT_CAL, + MIN_CAL_SAMPLES, + INIT_LOG_COUNT, + ath9k_hw_adc_dccal_collect, + ath9k_hw_adc_dccal_calibrate +}; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h new file mode 100644 index 000000000000..1c74bd50700d --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -0,0 +1,124 @@ +/* + * 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 CALIB_H +#define CALIB_H + +extern const struct hal_percal_data iq_cal_multi_sample; +extern const struct hal_percal_data iq_cal_single_sample; +extern const struct hal_percal_data adc_gain_cal_multi_sample; +extern const struct hal_percal_data adc_gain_cal_single_sample; +extern const struct hal_percal_data adc_dc_cal_multi_sample; +extern const struct hal_percal_data adc_dc_cal_single_sample; +extern const struct hal_percal_data adc_init_dc_cal; + +#define AR_PHY_CCA_MAX_GOOD_VALUE -85 +#define AR_PHY_CCA_MAX_HIGH_VALUE -62 +#define AR_PHY_CCA_MIN_BAD_VALUE -140 +#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 +#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 + +#define NUM_NF_READINGS 6 +#define ATH9K_NF_CAL_HIST_MAX 5 + +struct ar5416IniArray { + u32 *ia_array; + u32 ia_rows; + u32 ia_columns; +}; + +#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ + (iniarray)->ia_array = (u32 *)(array); \ + (iniarray)->ia_rows = (rows); \ + (iniarray)->ia_columns = (columns); \ + } while (0) + +#define INI_RA(iniarray, row, column) \ + (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) + +#define INIT_CAL(_perCal) do { \ + (_perCal)->calState = CAL_WAITING; \ + (_perCal)->calNext = NULL; \ + } while (0) + +#define INSERT_CAL(_ahp, _perCal) \ + do { \ + if ((_ahp)->cal_list_last == NULL) { \ + (_ahp)->cal_list = \ + (_ahp)->cal_list_last = (_perCal); \ + ((_ahp)->cal_list_last)->calNext = (_perCal); \ + } else { \ + ((_ahp)->cal_list_last)->calNext = (_perCal); \ + (_ahp)->cal_list_last = (_perCal); \ + (_perCal)->calNext = (_ahp)->cal_list; \ + } \ + } while (0) + +enum hal_cal_types { + ADC_DC_INIT_CAL = 0x1, + ADC_GAIN_CAL = 0x2, + ADC_DC_CAL = 0x4, + IQ_MISMATCH_CAL = 0x8 +}; + +enum hal_cal_state { + CAL_INACTIVE, + CAL_WAITING, + CAL_RUNNING, + CAL_DONE +}; + +#define MIN_CAL_SAMPLES 1 +#define MAX_CAL_SAMPLES 64 +#define INIT_LOG_COUNT 5 +#define PER_MIN_LOG_COUNT 2 +#define PER_MAX_LOG_COUNT 10 + +struct hal_percal_data { + enum hal_cal_types calType; + u32 calNumSamples; + u32 calCountMax; + void (*calCollect) (struct ath_hw *); + void (*calPostProc) (struct ath_hw *, u8); +}; + +struct hal_cal_list { + const struct hal_percal_data *calData; + enum hal_cal_state calState; + struct hal_cal_list *calNext; +}; + +struct ath9k_nfcal_hist { + int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX]; + u8 currIndex; + int16_t privNF; + u8 invalidNFcount; +}; + +bool ath9k_hw_reset_calvalid(struct ath_hw *ah); +void ath9k_hw_start_nfcal(struct ath_hw *ah); +void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); +int16_t ath9k_hw_getnf(struct ath_hw *ah, + struct ath9k_channel *chan); +void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); +s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); +bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, + u8 rxchainmask, bool longcal, + bool *isCalDone); +bool ath9k_hw_init_cal(struct ath_hw *ah, + struct ath9k_channel *chan); + +#endif /* CALIB_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c new file mode 100644 index 000000000000..97df20cbf528 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -0,0 +1,562 @@ +/* + * 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 + +#include "ath9k.h" + +static unsigned int ath9k_debug = DBG_DEFAULT; +module_param_named(debug, ath9k_debug, uint, 0); + +static struct dentry *ath9k_debugfs_root; + +void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) +{ + if (!sc) + return; + + if (sc->debug.debug_mask & dbg_mask) { + va_list args; + + va_start(args, fmt); + printk(KERN_DEBUG "ath9k: "); + vprintk(fmt, args); + va_end(args); + } +} + +static int ath9k_debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t read_file_dma(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_hw *ah = sc->sc_ah; + char buf[1024]; + unsigned int len = 0; + u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; + int i, qcuOffset = 0, dcuOffset = 0; + u32 *qcuBase = &val[0], *dcuBase = &val[4]; + + REG_WRITE(ah, AR_MACMISC, + ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | + (AR_MACMISC_MISC_OBS_BUS_1 << + AR_MACMISC_MISC_OBS_BUS_MSB_S))); + + len += snprintf(buf + len, sizeof(buf) - len, + "Raw DMA Debug values:\n"); + + for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { + if (i % 4 == 0) + len += snprintf(buf + len, sizeof(buf) - len, "\n"); + + val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))); + len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", + i, val[i]); + } + + len += snprintf(buf + len, sizeof(buf) - len, "\n\n"); + len += snprintf(buf + len, sizeof(buf) - len, + "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); + + for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { + if (i == 8) { + qcuOffset = 0; + qcuBase++; + } + + if (i == 6) { + dcuOffset = 0; + dcuBase++; + } + + len += snprintf(buf + len, sizeof(buf) - len, + "%2d %2x %1x %2x %2x\n", + i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, + (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), + val[2] & (0x7 << (i * 3)) >> (i * 3), + (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); + } + + len += snprintf(buf + len, sizeof(buf) - len, "\n"); + + len += snprintf(buf + len, sizeof(buf) - len, + "qcu_stitch state: %2x qcu_fetch state: %2x\n", + (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); + len += snprintf(buf + len, sizeof(buf) - len, + "qcu_complete state: %2x dcu_complete state: %2x\n", + (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); + len += snprintf(buf + len, sizeof(buf) - len, + "dcu_arb state: %2x dcu_fp state: %2x\n", + (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); + len += snprintf(buf + len, sizeof(buf) - len, + "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", + (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); + len += snprintf(buf + len, sizeof(buf) - len, + "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", + (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); + len += snprintf(buf + len, sizeof(buf) - len, + "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", + (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); + + len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", + REG_READ(ah, AR_OBS_BUS_1)); + len += snprintf(buf + len, sizeof(buf) - len, + "AR_CR: 0x%x \n", REG_READ(ah, AR_CR)); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_dma = { + .read = read_file_dma, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + + +void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) +{ + if (status) + sc->debug.stats.istats.total++; + if (status & ATH9K_INT_RX) + sc->debug.stats.istats.rxok++; + if (status & ATH9K_INT_RXEOL) + sc->debug.stats.istats.rxeol++; + if (status & ATH9K_INT_RXORN) + sc->debug.stats.istats.rxorn++; + if (status & ATH9K_INT_TX) + sc->debug.stats.istats.txok++; + if (status & ATH9K_INT_TXURN) + sc->debug.stats.istats.txurn++; + if (status & ATH9K_INT_MIB) + sc->debug.stats.istats.mib++; + if (status & ATH9K_INT_RXPHY) + sc->debug.stats.istats.rxphyerr++; + if (status & ATH9K_INT_RXKCM) + sc->debug.stats.istats.rx_keycache_miss++; + if (status & ATH9K_INT_SWBA) + sc->debug.stats.istats.swba++; + if (status & ATH9K_INT_BMISS) + sc->debug.stats.istats.bmiss++; + if (status & ATH9K_INT_BNR) + sc->debug.stats.istats.bnr++; + if (status & ATH9K_INT_CST) + sc->debug.stats.istats.cst++; + if (status & ATH9K_INT_GTT) + sc->debug.stats.istats.gtt++; + if (status & ATH9K_INT_TIM) + sc->debug.stats.istats.tim++; + if (status & ATH9K_INT_CABEND) + sc->debug.stats.istats.cabend++; + if (status & ATH9K_INT_DTIMSYNC) + sc->debug.stats.istats.dtimsync++; + if (status & ATH9K_INT_DTIM) + sc->debug.stats.istats.dtim++; +} + +static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[512]; + unsigned int len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "TX", sc->debug.stats.istats.txok); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "CST", sc->debug.stats.istats.cst); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); + len += snprintf(buf + len, sizeof(buf) - len, + "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_interrupt = { + .read = read_file_interrupt, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb) +{ + struct ath_tx_info_priv *tx_info_priv = NULL; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->status.rates; + int final_ts_idx, idx; + + tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + final_ts_idx = tx_info_priv->tx.ts_rateindex; + idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate; + + sc->debug.stats.n_rcstats[idx].success++; +} + +static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb) +{ + struct ath_tx_info_priv *tx_info_priv = NULL; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->status.rates; + int final_ts_idx, idx; + + tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + final_ts_idx = tx_info_priv->tx.ts_rateindex; + idx = rates[final_ts_idx].idx; + + sc->debug.stats.legacy_rcstats[idx].success++; +} + +void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) +{ + if (conf_is_ht(&sc->hw->conf)) + ath_debug_stat_11n_rc(sc, skb); + else + ath_debug_stat_legacy_rc(sc, skb); +} + +/* FIXME: legacy rates, later on .. */ +void ath_debug_stat_retries(struct ath_softc *sc, int rix, + int xretries, int retries, u8 per) +{ + if (conf_is_ht(&sc->hw->conf)) { + int idx = sc->cur_rate_table->info[rix].dot11rate; + + sc->debug.stats.n_rcstats[idx].xretries += xretries; + sc->debug.stats.n_rcstats[idx].retries += retries; + sc->debug.stats.n_rcstats[idx].per = per; + } +} + +static ssize_t ath_read_file_stat_11n_rc(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[1024]; + unsigned int len = 0; + int i = 0; + + len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success", + "Retries", "XRetries", "PER"); + + for (i = 0; i <= 15; i++) { + len += snprintf(buf + len, sizeof(buf) - len, + "%5s%3d: %8u %8u %8u %8u\n", "MCS", i, + sc->debug.stats.n_rcstats[i].success, + sc->debug.stats.n_rcstats[i].retries, + sc->debug.stats.n_rcstats[i].xretries, + sc->debug.stats.n_rcstats[i].per); + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t ath_read_file_stat_legacy_rc(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[512]; + unsigned int len = 0; + int i = 0; + + len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); + + for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { + len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n", + sc->cur_rate_table->info[i].ratekbps / 1000, + sc->debug.stats.legacy_rcstats[i].success); + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + + if (sc->cur_rate_table == NULL) + return 0; + + if (conf_is_ht(&sc->hw->conf)) + return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); + else + return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos); +} + +static const struct file_operations fops_rcstat = { + .read = read_file_rcstat, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +static const char * ath_wiphy_state_str(enum ath_wiphy_state state) +{ + switch (state) { + case ATH_WIPHY_INACTIVE: + return "INACTIVE"; + case ATH_WIPHY_ACTIVE: + return "ACTIVE"; + case ATH_WIPHY_PAUSING: + return "PAUSING"; + case ATH_WIPHY_PAUSED: + return "PAUSED"; + case ATH_WIPHY_SCAN: + return "SCAN"; + } + return "?"; +} + +static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[512]; + unsigned int len = 0; + int i; + u8 addr[ETH_ALEN]; + + len += snprintf(buf + len, sizeof(buf) - len, + "primary: %s (%s chan=%d ht=%d)\n", + wiphy_name(sc->pri_wiphy->hw->wiphy), + ath_wiphy_state_str(sc->pri_wiphy->state), + sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + if (aphy == NULL) + continue; + len += snprintf(buf + len, sizeof(buf) - len, + "secondary: %s (%s chan=%d ht=%d)\n", + wiphy_name(aphy->hw->wiphy), + ath_wiphy_state_str(aphy->state), + aphy->chan_idx, aphy->chan_is_ht); + } + + put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr); + put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); + len += snprintf(buf + len, sizeof(buf) - len, + "addr: %pM\n", addr); + put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr); + put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); + len += snprintf(buf + len, sizeof(buf) - len, + "addrmask: %pM\n", addr); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name) +{ + int i; + if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0) + return sc->pri_wiphy; + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0) + return aphy; + } + return NULL; +} + +static int del_wiphy(struct ath_softc *sc, const char *name) +{ + struct ath_wiphy *aphy = get_wiphy(sc, name); + if (!aphy) + return -ENOENT; + return ath9k_wiphy_del(aphy); +} + +static int pause_wiphy(struct ath_softc *sc, const char *name) +{ + struct ath_wiphy *aphy = get_wiphy(sc, name); + if (!aphy) + return -ENOENT; + return ath9k_wiphy_pause(aphy); +} + +static int unpause_wiphy(struct ath_softc *sc, const char *name) +{ + struct ath_wiphy *aphy = get_wiphy(sc, name); + if (!aphy) + return -ENOENT; + return ath9k_wiphy_unpause(aphy); +} + +static int select_wiphy(struct ath_softc *sc, const char *name) +{ + struct ath_wiphy *aphy = get_wiphy(sc, name); + if (!aphy) + return -ENOENT; + return ath9k_wiphy_select(aphy); +} + +static int schedule_wiphy(struct ath_softc *sc, const char *msec) +{ + ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0)); + return 0; +} + +static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[50]; + size_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + if (len > 0 && buf[len - 1] == '\n') + buf[len - 1] = '\0'; + + if (strncmp(buf, "add", 3) == 0) { + int res = ath9k_wiphy_add(sc); + if (res < 0) + return res; + } else if (strncmp(buf, "del=", 4) == 0) { + int res = del_wiphy(sc, buf + 4); + if (res < 0) + return res; + } else if (strncmp(buf, "pause=", 6) == 0) { + int res = pause_wiphy(sc, buf + 6); + if (res < 0) + return res; + } else if (strncmp(buf, "unpause=", 8) == 0) { + int res = unpause_wiphy(sc, buf + 8); + if (res < 0) + return res; + } else if (strncmp(buf, "select=", 7) == 0) { + int res = select_wiphy(sc, buf + 7); + if (res < 0) + return res; + } else if (strncmp(buf, "schedule=", 9) == 0) { + int res = schedule_wiphy(sc, buf + 9); + if (res < 0) + return res; + } else + return -EOPNOTSUPP; + + return count; +} + +static const struct file_operations fops_wiphy = { + .read = read_file_wiphy, + .write = write_file_wiphy, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + + +int ath9k_init_debug(struct ath_softc *sc) +{ + sc->debug.debug_mask = ath9k_debug; + + if (!ath9k_debugfs_root) + return -ENOENT; + + sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), + ath9k_debugfs_root); + if (!sc->debug.debugfs_phy) + goto err; + + sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO, + sc->debug.debugfs_phy, sc, &fops_dma); + if (!sc->debug.debugfs_dma) + goto err; + + sc->debug.debugfs_interrupt = debugfs_create_file("interrupt", + S_IRUGO, + sc->debug.debugfs_phy, + sc, &fops_interrupt); + if (!sc->debug.debugfs_interrupt) + goto err; + + sc->debug.debugfs_rcstat = debugfs_create_file("rcstat", + S_IRUGO, + sc->debug.debugfs_phy, + sc, &fops_rcstat); + if (!sc->debug.debugfs_rcstat) + goto err; + + sc->debug.debugfs_wiphy = debugfs_create_file( + "wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc, + &fops_wiphy); + if (!sc->debug.debugfs_wiphy) + goto err; + + return 0; +err: + ath9k_exit_debug(sc); + return -ENOMEM; +} + +void ath9k_exit_debug(struct ath_softc *sc) +{ + debugfs_remove(sc->debug.debugfs_wiphy); + debugfs_remove(sc->debug.debugfs_rcstat); + debugfs_remove(sc->debug.debugfs_interrupt); + debugfs_remove(sc->debug.debugfs_dma); + debugfs_remove(sc->debug.debugfs_phy); +} + +int ath9k_debug_create_root(void) +{ + ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!ath9k_debugfs_root) + return -ENOENT; + + return 0; +} + +void ath9k_debug_remove_root(void) +{ + debugfs_remove(ath9k_debugfs_root); + ath9k_debugfs_root = NULL; +} diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h new file mode 100644 index 000000000000..23298b90b52b --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -0,0 +1,161 @@ +/* + * 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 DEBUG_H +#define DEBUG_H + +enum ATH_DEBUG { + ATH_DBG_RESET = 0x00000001, + ATH_DBG_QUEUE = 0x00000002, + ATH_DBG_EEPROM = 0x00000004, + ATH_DBG_CALIBRATE = 0x00000008, + ATH_DBG_INTERRUPT = 0x00000010, + ATH_DBG_REGULATORY = 0x00000020, + ATH_DBG_ANI = 0x00000040, + ATH_DBG_XMIT = 0x00000080, + ATH_DBG_BEACON = 0x00000100, + ATH_DBG_CONFIG = 0x00000200, + ATH_DBG_FATAL = 0x00000400, + ATH_DBG_ANY = 0xffffffff +}; + +#define DBG_DEFAULT (ATH_DBG_FATAL) + +#ifdef CONFIG_ATH9K_DEBUG + +/** + * struct ath_interrupt_stats - Contains statistics about interrupts + * @total: Total no. of interrupts generated so far + * @rxok: RX with no errors + * @rxeol: RX with no more RXDESC available + * @rxorn: RX FIFO overrun + * @txok: TX completed at the requested rate + * @txurn: TX FIFO underrun + * @mib: MIB regs reaching its threshold + * @rxphyerr: RX with phy errors + * @rx_keycache_miss: RX with key cache misses + * @swba: Software Beacon Alert + * @bmiss: Beacon Miss + * @bnr: Beacon Not Ready + * @cst: Carrier Sense TImeout + * @gtt: Global TX Timeout + * @tim: RX beacon TIM occurrence + * @cabend: RX End of CAB traffic + * @dtimsync: DTIM sync lossage + * @dtim: RX Beacon with DTIM + */ +struct ath_interrupt_stats { + u32 total; + u32 rxok; + u32 rxeol; + u32 rxorn; + u32 txok; + u32 txeol; + u32 txurn; + u32 mib; + u32 rxphyerr; + u32 rx_keycache_miss; + u32 swba; + u32 bmiss; + u32 bnr; + u32 cst; + u32 gtt; + u32 tim; + u32 cabend; + u32 dtimsync; + u32 dtim; +}; + +struct ath_legacy_rc_stats { + u32 success; +}; + +struct ath_11n_rc_stats { + u32 success; + u32 retries; + u32 xretries; + u8 per; +}; + +struct ath_stats { + struct ath_interrupt_stats istats; + struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */ + struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */ +}; + +struct ath9k_debug { + int debug_mask; + struct dentry *debugfs_phy; + struct dentry *debugfs_dma; + struct dentry *debugfs_interrupt; + struct dentry *debugfs_rcstat; + struct dentry *debugfs_wiphy; + struct ath_stats stats; +}; + +void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); +int ath9k_init_debug(struct ath_softc *sc); +void ath9k_exit_debug(struct ath_softc *sc); +int ath9k_debug_create_root(void); +void ath9k_debug_remove_root(void); +void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); +void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); +void ath_debug_stat_retries(struct ath_softc *sc, int rix, + int xretries, int retries, u8 per); + +#else + +static inline void DPRINTF(struct ath_softc *sc, int dbg_mask, + const char *fmt, ...) +{ +} + +static inline int ath9k_init_debug(struct ath_softc *sc) +{ + return 0; +} + +static inline void ath9k_exit_debug(struct ath_softc *sc) +{ +} + +static inline int ath9k_debug_create_root(void) +{ + return 0; +} + +static inline void ath9k_debug_remove_root(void) +{ +} + +static inline void ath_debug_stat_interrupt(struct ath_softc *sc, + enum ath9k_int status) +{ +} + +static inline void ath_debug_stat_rc(struct ath_softc *sc, + struct sk_buff *skb) +{ +} + +static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, + int xretries, int retries, u8 per) +{ +} + +#endif /* CONFIG_ATH9K_DEBUG */ + +#endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c new file mode 100644 index 000000000000..44fee5ae8925 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -0,0 +1,2813 @@ +/* + * 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 "ath9k.h" + +static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, + u32 reg, u32 mask, + u32 shift, u32 val) +{ + u32 regVal; + + regVal = REG_READ(ah, reg) & ~mask; + regVal |= (val << shift) & mask; + + REG_WRITE(ah, reg, regVal); + + if (ah->config.analog_shiftreg) + udelay(100); + + return; +} + +static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) +{ + + if (fbin == AR5416_BCHAN_UNUSED) + return fbin; + + return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); +} + +static inline int16_t ath9k_hw_interpolate(u16 target, + u16 srcLeft, u16 srcRight, + int16_t targetLeft, + int16_t targetRight) +{ + int16_t rv; + + if (srcRight == srcLeft) { + rv = targetLeft; + } else { + rv = (int16_t) (((target - srcLeft) * targetRight + + (srcRight - target) * targetLeft) / + (srcRight - srcLeft)); + } + return rv; +} + +static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, + u16 listSize, u16 *indexL, + u16 *indexR) +{ + u16 i; + + if (target <= pList[0]) { + *indexL = *indexR = 0; + return true; + } + if (target >= pList[listSize - 1]) { + *indexL = *indexR = (u16) (listSize - 1); + return true; + } + + for (i = 0; i < listSize - 1; i++) { + if (pList[i] == target) { + *indexL = *indexR = i; + return true; + } + if (target < pList[i + 1]) { + *indexL = i; + *indexR = (u16) (i + 1); + return false; + } + } + return false; +} + +static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) +{ + struct ath_softc *sc = ah->ah_sc; + + return sc->bus_ops->eeprom_read(ah, off, data); +} + +static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, + u8 *pVpdList, u16 numIntercepts, + u8 *pRetVpdList) +{ + u16 i, k; + u8 currPwr = pwrMin; + u16 idxL = 0, idxR = 0; + + for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { + ath9k_hw_get_lower_upper_index(currPwr, pPwrList, + numIntercepts, &(idxL), + &(idxR)); + if (idxR < 1) + idxR = 1; + if (idxL == numIntercepts - 1) + idxL = (u16) (numIntercepts - 2); + if (pPwrList[idxL] == pPwrList[idxR]) + k = pVpdList[idxL]; + else + k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] + + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / + (pPwrList[idxR] - pPwrList[idxL])); + pRetVpdList[i] = (u8) k; + currPwr += 2; + } + + return true; +} + +static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, + struct ath9k_channel *chan, + struct cal_target_power_leg *powInfo, + u16 numChannels, + struct cal_target_power_leg *pNewPower, + u16 numRates, bool isExtTarget) +{ + struct chan_centers centers; + u16 clo, chi; + int i; + int matchIndex = -1, lowIndex = -1; + u16 freq; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = (isExtTarget) ? centers.ext_center : centers.ctl_center; + + if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, + IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && + (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) && + (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, + IS_CHAN_2GHZ(chan)))) { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) + matchIndex = i - 1; + } + + if (matchIndex != -1) { + *pNewPower = powInfo[matchIndex]; + } else { + clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, + IS_CHAN_2GHZ(chan)); + chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, + IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = + (u8)ath9k_hw_interpolate(freq, clo, chi, + powInfo[lowIndex].tPow2x[i], + powInfo[lowIndex + 1].tPow2x[i]); + } + } +} + +static void ath9k_get_txgain_index(struct ath_hw *ah, + struct ath9k_channel *chan, + struct calDataPerFreqOpLoop *rawDatasetOpLoop, + u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) +{ + u8 pcdac, i = 0; + u16 idxL = 0, idxR = 0, numPiers; + bool match; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) + if (calChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + + match = ath9k_hw_get_lower_upper_index( + (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), + calChans, numPiers, &idxL, &idxR); + if (match) { + pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; + *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; + } else { + pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; + *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + + rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; + } + + while (pcdac > ah->originalGain[i] && + i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) + i++; + + *pcdacIdx = i; + return; +} + +static void ath9k_olc_get_pdadcs(struct ath_hw *ah, + u32 initTxGain, + int txPower, + u8 *pPDADCValues) +{ + u32 i; + u32 offset; + + REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, + AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); + REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, + AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); + + REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, + AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); + + offset = txPower; + for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) + if (i < offset) + pPDADCValues[i] = 0x0; + else + pPDADCValues[i] = 0xFF; +} + + + + +static void ath9k_hw_get_target_powers(struct ath_hw *ah, + struct ath9k_channel *chan, + struct cal_target_power_ht *powInfo, + u16 numChannels, + struct cal_target_power_ht *pNewPower, + u16 numRates, bool isHt40Target) +{ + struct chan_centers centers; + u16 clo, chi; + int i; + int matchIndex = -1, lowIndex = -1; + u16 freq; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = isHt40Target ? centers.synth_center : centers.ctl_center; + + if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { + matchIndex = 0; + } else { + for (i = 0; (i < numChannels) && + (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) { + matchIndex = i; + break; + } else + if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, + IS_CHAN_2GHZ(chan))) && + (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, + IS_CHAN_2GHZ(chan)))) { + lowIndex = i - 1; + break; + } + } + if ((matchIndex == -1) && (lowIndex == -1)) + matchIndex = i - 1; + } + + if (matchIndex != -1) { + *pNewPower = powInfo[matchIndex]; + } else { + clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, + IS_CHAN_2GHZ(chan)); + chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, + IS_CHAN_2GHZ(chan)); + + for (i = 0; i < numRates; i++) { + pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq, + clo, chi, + powInfo[lowIndex].tPow2x[i], + powInfo[lowIndex + 1].tPow2x[i]); + } + } +} + +static u16 ath9k_hw_get_max_edge_power(u16 freq, + struct cal_ctl_edges *pRdEdgesPower, + bool is2GHz, int num_band_edges) +{ + u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + int i; + + for (i = 0; (i < num_band_edges) && + (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { + if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { + twiceMaxEdgePower = pRdEdgesPower[i].tPower; + break; + } else if ((i > 0) && + (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, + is2GHz))) { + if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel, + is2GHz) < freq && + pRdEdgesPower[i - 1].flag) { + twiceMaxEdgePower = + pRdEdgesPower[i - 1].tPower; + } + break; + } + } + + return twiceMaxEdgePower; +} + +/****************************************/ +/* EEPROM Operations for 4K sized cards */ +/****************************************/ + +static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) +{ + return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); +} + +static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) +{ + return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); +} + +static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) +{ +#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) + u16 *eep_data = (u16 *)&ah->eeprom.map4k; + int addr, eep_start_loc = 0; + + eep_start_loc = 64; + + if (!ath9k_hw_use_flash(ah)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "Reading from EEPROM, not flash\n"); + } + + for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { + if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "Unable to read eeprom region \n"); + return false; + } + eep_data++; + } + + return true; +#undef SIZE_EEPROM_4K +} + +static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) +{ +#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) + struct ar5416_eeprom_4k *eep = + (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; + u16 *eepdata, temp, magic, magic2; + u32 sum = 0, el; + bool need_swap = false; + int i, addr; + + + if (!ath9k_hw_use_flash(ah)) { + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, + &magic)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Reading Magic # failed\n"); + return false; + } + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "Read Magic = 0x%04X\n", magic); + + if (magic != AR5416_EEPROM_MAGIC) { + magic2 = swab16(magic); + + if (magic2 == AR5416_EEPROM_MAGIC) { + need_swap = true; + eepdata = (u16 *) (&ah->eeprom); + + for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { + temp = swab16(*eepdata); + *eepdata = temp; + eepdata++; + } + } else { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Invalid EEPROM Magic. " + "endianness mismatch.\n"); + return -EINVAL; + } + } + } + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); + + if (need_swap) + el = swab16(ah->eeprom.map4k.baseEepHeader.length); + else + el = ah->eeprom.map4k.baseEepHeader.length; + + if (el > sizeof(struct ar5416_eeprom_4k)) + el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); + else + el = el / sizeof(u16); + + eepdata = (u16 *)(&ah->eeprom); + + for (i = 0; i < el; i++) + sum ^= *eepdata++; + + if (need_swap) { + u32 integer; + u16 word; + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "EEPROM Endianness is not native.. Changing\n"); + + word = swab16(eep->baseEepHeader.length); + eep->baseEepHeader.length = word; + + word = swab16(eep->baseEepHeader.checksum); + eep->baseEepHeader.checksum = word; + + word = swab16(eep->baseEepHeader.version); + eep->baseEepHeader.version = word; + + word = swab16(eep->baseEepHeader.regDmn[0]); + eep->baseEepHeader.regDmn[0] = word; + + word = swab16(eep->baseEepHeader.regDmn[1]); + eep->baseEepHeader.regDmn[1] = word; + + word = swab16(eep->baseEepHeader.rfSilent); + eep->baseEepHeader.rfSilent = word; + + word = swab16(eep->baseEepHeader.blueToothOptions); + eep->baseEepHeader.blueToothOptions = word; + + word = swab16(eep->baseEepHeader.deviceCap); + eep->baseEepHeader.deviceCap = word; + + integer = swab32(eep->modalHeader.antCtrlCommon); + eep->modalHeader.antCtrlCommon = integer; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + integer = swab32(eep->modalHeader.antCtrlChain[i]); + eep->modalHeader.antCtrlChain[i] = integer; + } + + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = swab16(eep->modalHeader.spurChans[i].spurChan); + eep->modalHeader.spurChans[i].spurChan = word; + } + } + + if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || + ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Bad EEPROM checksum 0x%x or revision 0x%04x\n", + sum, ah->eep_ops->get_eeprom_ver(ah)); + return -EINVAL; + } + + return 0; +#undef EEPROM_4K_SIZE +} + +static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, + enum eeprom_param param) +{ + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + struct modal_eep_4k_header *pModal = &eep->modalHeader; + struct base_eep_header_4k *pBase = &eep->baseEepHeader; + + switch (param) { + case EEP_NFTHRESH_2: + return pModal->noiseFloorThreshCh[0]; + case AR_EEPROM_MAC(0): + return pBase->macAddr[0] << 8 | pBase->macAddr[1]; + case AR_EEPROM_MAC(1): + return pBase->macAddr[2] << 8 | pBase->macAddr[3]; + case AR_EEPROM_MAC(2): + return pBase->macAddr[4] << 8 | pBase->macAddr[5]; + case EEP_REG_0: + return pBase->regDmn[0]; + case EEP_REG_1: + return pBase->regDmn[1]; + case EEP_OP_CAP: + return pBase->deviceCap; + case EEP_OP_MODE: + return pBase->opCapFlags; + case EEP_RF_SILENT: + return pBase->rfSilent; + case EEP_OB_2: + return pModal->ob_01; + case EEP_DB_2: + return pModal->db1_01; + case EEP_MINOR_REV: + return pBase->version & AR5416_EEP_VER_MINOR_MASK; + case EEP_TX_MASK: + return pBase->txMask; + case EEP_RX_MASK: + return pBase->rxMask; + case EEP_FRAC_N_5G: + return 0; + default: + return 0; + } +} + +static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, + struct ath9k_channel *chan, + struct cal_data_per_freq_4k *pRawDataSet, + u8 *bChans, u16 availPiers, + u16 tPdGainOverlap, int16_t *pMinCalPower, + u16 *pPdGainBoundaries, u8 *pPDADCValues, + u16 numXpdGains) +{ +#define TMP_VAL_VPD_TABLE \ + ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); + int i, j, k; + int16_t ss; + u16 idxL = 0, idxR = 0, numPiers; + static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; + u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; + u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + u16 sizeCurrVpdTable, maxIndex, tgtIndex; + bool match; + int16_t minDelta = 0; + struct chan_centers centers; +#define PD_GAIN_BOUNDARY_DEFAULT 58; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (bChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + } + + match = ath9k_hw_get_lower_upper_index( + (u8)FREQ2FBIN(centers.synth_center, + IS_CHAN_2GHZ(chan)), bChans, numPiers, + &idxL, &idxR); + + if (match) { + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; + maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pRawDataSet[idxL].pwrPdg[i], + pRawDataSet[idxL].vpdPdg[i], + AR5416_EEP4K_PD_GAIN_ICEPTS, + vpdTableI[i]); + } + } else { + for (i = 0; i < numXpdGains; i++) { + pVpdL = pRawDataSet[idxL].vpdPdg[i]; + pPwrL = pRawDataSet[idxL].pwrPdg[i]; + pVpdR = pRawDataSet[idxR].vpdPdg[i]; + pPwrR = pRawDataSet[idxR].pwrPdg[i]; + + minPwrT4[i] = max(pPwrL[0], pPwrR[0]); + + maxPwrT4[i] = + min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], + pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); + + + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pPwrL, pVpdL, + AR5416_EEP4K_PD_GAIN_ICEPTS, + vpdTableL[i]); + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pPwrR, pVpdR, + AR5416_EEP4K_PD_GAIN_ICEPTS, + vpdTableR[i]); + + for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { + vpdTableI[i][j] = + (u8)(ath9k_hw_interpolate((u16) + FREQ2FBIN(centers. + synth_center, + IS_CHAN_2GHZ + (chan)), + bChans[idxL], bChans[idxR], + vpdTableL[i][j], vpdTableR[i][j])); + } + } + } + + *pMinCalPower = (int16_t)(minPwrT4[0] / 2); + + k = 0; + + for (i = 0; i < numXpdGains; i++) { + if (i == (numXpdGains - 1)) + pPdGainBoundaries[i] = + (u16)(maxPwrT4[i] / 2); + else + pPdGainBoundaries[i] = + (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); + + pPdGainBoundaries[i] = + min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); + + if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { + minDelta = pPdGainBoundaries[0] - 23; + pPdGainBoundaries[0] = 23; + } else { + minDelta = 0; + } + + if (i == 0) { + if (AR_SREV_9280_10_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; + } else { + ss = (int16_t)((pPdGainBoundaries[i - 1] - + (minPwrT4[i] / 2)) - + tPdGainOverlap + 1 + minDelta); + } + vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + + while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); + pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); + tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - + (minPwrT4[i] / 2)); + maxIndex = (tgtIndex < sizeCurrVpdTable) ? + tgtIndex : sizeCurrVpdTable; + + while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) + pPDADCValues[k++] = vpdTableI[i][ss++]; + + vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - + vpdTableI[i][sizeCurrVpdTable - 2]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + + if (tgtIndex >= maxIndex) { + while ((ss <= tgtIndex) && + (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t) TMP_VAL_VPD_TABLE; + pPDADCValues[k++] = (u8)((tmpVal > 255) ? + 255 : tmpVal); + ss++; + } + } + } + + while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { + pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; + i++; + } + + while (k < AR5416_NUM_PDADC_VALUES) { + pPDADCValues[k] = pPDADCValues[k - 1]; + k++; + } + + return; +#undef TMP_VAL_VPD_TABLE +} + +static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, + struct ath9k_channel *chan, + int16_t *pTxPowerIndexOffset) +{ + struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; + struct cal_data_per_freq_4k *pRawDataset; + u8 *pCalBChans = NULL; + u16 pdGainOverlap_t2; + static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; + u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; + u16 numPiers, i, j; + int16_t tMinCalPower; + u16 numXpdGain, xpdMask; + u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; + u32 reg32, regOffset, regChainOffset; + + xpdMask = pEepData->modalHeader.xpdGain; + + if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + pdGainOverlap_t2 = + pEepData->modalHeader.pdGainOverlap; + } else { + pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; + + numXpdGain = 0; + + for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) + break; + xpdGainValues[numXpdGain] = + (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); + numXpdGain++; + } + } + + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (numXpdGain - 1) & 0x3); + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, + xpdGainValues[0]); + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, + xpdGainValues[1]); + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); + + for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { + if (AR_SREV_5416_20_OR_LATER(ah) && + (ah->rxchainmask == 5 || ah->txchainmask == 5) && + (i != 0)) { + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else + regChainOffset = i * 0x1000; + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + pRawDataset = pEepData->calPierData2G[i]; + + ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, + pRawDataset, pCalBChans, + numPiers, pdGainOverlap_t2, + &tMinCalPower, gainBoundaries, + pdadcValues, numXpdGain); + + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { + REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, + SM(pdGainOverlap_t2, + AR_PHY_TPCRG5_PD_GAIN_OVERLAP) + | SM(gainBoundaries[0], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) + | SM(gainBoundaries[1], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) + | SM(gainBoundaries[2], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) + | SM(gainBoundaries[3], + AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); + } + + regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; + for (j = 0; j < 32; j++) { + reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | + ((pdadcValues[4 * j + 1] & 0xFF) << 8) | + ((pdadcValues[4 * j + 2] & 0xFF) << 16)| + ((pdadcValues[4 * j + 3] & 0xFF) << 24); + REG_WRITE(ah, regOffset, reg32); + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "PDADC (%d,%4x): %4.4x %8.8x\n", + i, regChainOffset, regOffset, + reg32); + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "PDADC: Chain %d | " + "PDADC %3d Value %3d | " + "PDADC %3d Value %3d | " + "PDADC %3d Value %3d | " + "PDADC %3d Value %3d |\n", + i, 4 * j, pdadcValues[4 * j], + 4 * j + 1, pdadcValues[4 * j + 1], + 4 * j + 2, pdadcValues[4 * j + 2], + 4 * j + 3, + pdadcValues[4 * j + 3]); + + regOffset += 4; + } + } + } + + *pTxPowerIndexOffset = 0; + + return true; +} + +static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, + struct ath9k_channel *chan, + int16_t *ratesArray, + u16 cfgCtl, + u16 AntennaReduction, + u16 twiceMaxRegulatoryPower, + u16 powerLimit) +{ + struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; + u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + static const u16 tpScaleReductionTable[5] = + { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; + + int i; + int16_t twiceLargestAntenna; + struct cal_ctl_data_4k *rep; + struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { + 0, { 0, 0, 0, 0} + }; + struct cal_target_power_leg targetPowerOfdmExt = { + 0, { 0, 0, 0, 0} }, targetPowerCckExt = { + 0, { 0, 0, 0, 0 } + }; + struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { + 0, {0, 0, 0, 0} + }; + u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; + u16 ctlModesFor11g[] = + { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, + CTL_2GHT40 + }; + u16 numCtlModes, *pCtlMode, ctlMode, freq; + struct chan_centers centers; + int tx_chainmask; + u16 twiceMinEdgePower; + + tx_chainmask = ah->txchainmask; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; + + twiceLargestAntenna = (int16_t)min(AntennaReduction - + twiceLargestAntenna, 0); + + maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; + + if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { + maxRegAllowedPower -= + (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); + } + + scaledPower = min(powerLimit, maxRegAllowedPower); + scaledPower = max((u16)0, scaledPower); + + numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; + pCtlMode = ctlModesFor11g; + + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, + &targetPowerCck, 4, false); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, + &targetPowerOfdm, 4, false); + ath9k_hw_get_target_powers(ah, chan, + pEepData->calTargetPower2GHT20, + AR5416_NUM_2G_20_TARGET_POWERS, + &targetPowerHt20, 8, false); + + if (IS_CHAN_HT40(chan)) { + numCtlModes = ARRAY_SIZE(ctlModesFor11g); + ath9k_hw_get_target_powers(ah, chan, + pEepData->calTargetPower2GHT40, + AR5416_NUM_2G_40_TARGET_POWERS, + &targetPowerHt40, 8, true); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, + &targetPowerCckExt, 4, true); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, + &targetPowerOfdmExt, 4, true); + } + + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) + freq = centers.synth_center; + else if (pCtlMode[ctlMode] & EXT_ADDITIVE) + freq = centers.ext_center; + else + freq = centers.ctl_center; + + if (ah->eep_ops->get_eeprom_ver(ah) == 14 && + ah->eep_ops->get_eeprom_rev(ah) <= 2) + twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " + "EXT_ADDITIVE %d\n", + ctlMode, numCtlModes, isHt40CtlMode, + (pCtlMode[ctlMode] & EXT_ADDITIVE)); + + for (i = 0; (i < AR5416_NUM_CTLS) && + pEepData->ctlIndex[i]; i++) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " + "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " + "chan %d\n", + i, cfgCtl, pCtlMode[ctlMode], + pEepData->ctlIndex[i], chan->channel); + + if ((((cfgCtl & ~CTL_MODE_M) | + (pCtlMode[ctlMode] & CTL_MODE_M)) == + pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | + (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | + SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + + twiceMinEdgePower = + ath9k_hw_get_max_edge_power(freq, + rep->ctlEdges[ar5416_get_ntxchains + (tx_chainmask) - 1], + IS_CHAN_2GHZ(chan), + AR5416_EEP4K_NUM_BAND_EDGES); + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + " MATCH-EE_IDX %d: ch %d is2 %d " + "2xMinEdge %d chainmask %d chains %d\n", + i, freq, IS_CHAN_2GHZ(chan), + twiceMinEdgePower, tx_chainmask, + ar5416_get_ntxchains + (tx_chainmask)); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + twiceMaxEdgePower = + min(twiceMaxEdgePower, + twiceMinEdgePower); + } else { + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + + minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + " SEL-Min ctlMode %d pCtlMode %d " + "2xMaxEdge %d sP %d minCtlPwr %d\n", + ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, + scaledPower, minCtlPower); + + switch (pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); + i++) { + targetPowerCck.tPow2x[i] = + min((u16)targetPowerCck.tPow2x[i], + minCtlPower); + } + break; + case CTL_11G: + for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); + i++) { + targetPowerOfdm.tPow2x[i] = + min((u16)targetPowerOfdm.tPow2x[i], + minCtlPower); + } + break; + case CTL_2GHT20: + for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); + i++) { + targetPowerHt20.tPow2x[i] = + min((u16)targetPowerHt20.tPow2x[i], + minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = min((u16) + targetPowerCckExt.tPow2x[0], + minCtlPower); + break; + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = min((u16) + targetPowerOfdmExt.tPow2x[0], + minCtlPower); + break; + case CTL_2GHT40: + for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); + i++) { + targetPowerHt40.tPow2x[i] = + min((u16)targetPowerHt40.tPow2x[i], + minCtlPower); + } + break; + default: + break; + } + } + + ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = + ratesArray[rate18mb] = ratesArray[rate24mb] = + targetPowerOfdm.tPow2x[0]; + ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; + ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; + ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; + ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; + + for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) + ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; + + ratesArray[rate1l] = targetPowerCck.tPow2x[0]; + ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; + ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; + ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; + + if (IS_CHAN_HT40(chan)) { + for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { + ratesArray[rateHt40_0 + i] = + targetPowerHt40.tPow2x[i]; + } + ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; + ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; + ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; + ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; + } + return true; +} + +static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, + struct ath9k_channel *chan, + u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, + u8 powerLimit) +{ + struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; + struct modal_eep_4k_header *pModal = &pEepData->modalHeader; + int16_t ratesArray[Ar5416RateSize]; + int16_t txPowerIndexOffset = 0; + u8 ht40PowerIncForPdadc = 2; + int i; + + memset(ratesArray, 0, sizeof(ratesArray)); + + if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + } + + if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan, + &ratesArray[0], cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, + powerLimit)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "ath9k_hw_set_txpower: unable to set " + "tx power per rate table\n"); + return -EIO; + } + + if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "ath9k_hw_set_txpower: unable to set power table\n"); + return -EIO; + } + + for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { + ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > AR5416_MAX_RATE_POWER) + ratesArray[i] = AR5416_MAX_RATE_POWER; + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; + } + + REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + ATH9K_POW_SM(ratesArray[rate18mb], 24) + | ATH9K_POW_SM(ratesArray[rate12mb], 16) + | ATH9K_POW_SM(ratesArray[rate9mb], 8) + | ATH9K_POW_SM(ratesArray[rate6mb], 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + ATH9K_POW_SM(ratesArray[rate54mb], 24) + | ATH9K_POW_SM(ratesArray[rate48mb], 16) + | ATH9K_POW_SM(ratesArray[rate36mb], 8) + | ATH9K_POW_SM(ratesArray[rate24mb], 0)); + + if (IS_CHAN_2GHZ(chan)) { + REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + ATH9K_POW_SM(ratesArray[rate2s], 24) + | ATH9K_POW_SM(ratesArray[rate2l], 16) + | ATH9K_POW_SM(ratesArray[rateXr], 8) + | ATH9K_POW_SM(ratesArray[rate1l], 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + ATH9K_POW_SM(ratesArray[rate11s], 24) + | ATH9K_POW_SM(ratesArray[rate11l], 16) + | ATH9K_POW_SM(ratesArray[rate5_5s], 8) + | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); + } + + REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, + ATH9K_POW_SM(ratesArray[rateHt20_3], 24) + | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) + | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) + | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, + ATH9K_POW_SM(ratesArray[rateHt20_7], 24) + | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) + | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) + | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); + + if (IS_CHAN_HT40(chan)) { + REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, + ATH9K_POW_SM(ratesArray[rateHt40_3] + + ht40PowerIncForPdadc, 24) + | ATH9K_POW_SM(ratesArray[rateHt40_2] + + ht40PowerIncForPdadc, 16) + | ATH9K_POW_SM(ratesArray[rateHt40_1] + + ht40PowerIncForPdadc, 8) + | ATH9K_POW_SM(ratesArray[rateHt40_0] + + ht40PowerIncForPdadc, 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, + ATH9K_POW_SM(ratesArray[rateHt40_7] + + ht40PowerIncForPdadc, 24) + | ATH9K_POW_SM(ratesArray[rateHt40_6] + + ht40PowerIncForPdadc, 16) + | ATH9K_POW_SM(ratesArray[rateHt40_5] + + ht40PowerIncForPdadc, 8) + | ATH9K_POW_SM(ratesArray[rateHt40_4] + + ht40PowerIncForPdadc, 0)); + + REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, + ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) + | ATH9K_POW_SM(ratesArray[rateExtCck], 16) + | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) + | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); + } + + i = rate6mb; + + if (IS_CHAN_HT40(chan)) + i = rateHt40_0; + else if (IS_CHAN_HT20(chan)) + i = rateHt20_0; + + if (AR_SREV_9280_10_OR_LATER(ah)) + ah->regulatory.max_power_level = + ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; + else + ah->regulatory.max_power_level = ratesArray[i]; + + return 0; +} + +static void ath9k_hw_4k_set_addac(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct modal_eep_4k_header *pModal; + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + u8 biaslevel; + + if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) + return; + + if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) + return; + + pModal = &eep->modalHeader; + + if (pModal->xpaBiasLvl != 0xff) { + biaslevel = pModal->xpaBiasLvl; + INI_RA(&ah->iniAddac, 7, 1) = + (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; + } +} + +static void ath9k_hw_4k_set_gain(struct ath_hw *ah, + struct modal_eep_4k_header *pModal, + struct ar5416_eeprom_4k *eep, + u8 txRxAttenLocal, int regChainOffset) +{ + REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, + pModal->antCtrlChain[0]); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_3) { + txRxAttenLocal = pModal->txRxAttenCh[0]; + + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[0]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); + } + + REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); + + if (AR_SREV_9285_11(ah)) + REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); +} + +static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct modal_eep_4k_header *pModal; + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + u8 txRxAttenLocal; + u8 ob[5], db1[5], db2[5]; + u8 ant_div_control1, ant_div_control2; + u32 regVal; + + pModal = &eep->modalHeader; + txRxAttenLocal = 23; + + REG_WRITE(ah, AR_PHY_SWITCH_COM, + ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); + + /* Single chain for 4K EEPROM*/ + ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); + + /* Initialize Ant Diversity settings from EEPROM */ + if (pModal->version == 3) { + ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); + ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); + regVal = REG_READ(ah, 0x99ac); + regVal &= (~(0x7f000000)); + regVal |= ((ant_div_control1 & 0x1) << 24); + regVal |= (((ant_div_control1 >> 1) & 0x1) << 29); + regVal |= (((ant_div_control1 >> 2) & 0x1) << 30); + regVal |= ((ant_div_control2 & 0x3) << 25); + regVal |= (((ant_div_control2 >> 2) & 0x3) << 27); + REG_WRITE(ah, 0x99ac, regVal); + regVal = REG_READ(ah, 0x99ac); + regVal = REG_READ(ah, 0xa208); + regVal &= (~(0x1 << 13)); + regVal |= (((ant_div_control1 >> 3) & 0x1) << 13); + REG_WRITE(ah, 0xa208, regVal); + regVal = REG_READ(ah, 0xa208); + } + + if (pModal->version >= 2) { + ob[0] = (pModal->ob_01 & 0xf); + ob[1] = (pModal->ob_01 >> 4) & 0xf; + ob[2] = (pModal->ob_234 & 0xf); + ob[3] = ((pModal->ob_234 >> 4) & 0xf); + ob[4] = ((pModal->ob_234 >> 8) & 0xf); + + db1[0] = (pModal->db1_01 & 0xf); + db1[1] = ((pModal->db1_01 >> 4) & 0xf); + db1[2] = (pModal->db1_234 & 0xf); + db1[3] = ((pModal->db1_234 >> 4) & 0xf); + db1[4] = ((pModal->db1_234 >> 8) & 0xf); + + db2[0] = (pModal->db2_01 & 0xf); + db2[1] = ((pModal->db2_01 >> 4) & 0xf); + db2[2] = (pModal->db2_234 & 0xf); + db2[3] = ((pModal->db2_234 >> 4) & 0xf); + db2[4] = ((pModal->db2_234 >> 8) & 0xf); + + } else if (pModal->version == 1) { + ob[0] = (pModal->ob_01 & 0xf); + ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; + db1[0] = (pModal->db1_01 & 0xf); + db1[1] = db1[2] = db1[3] = + db1[4] = ((pModal->db1_01 >> 4) & 0xf); + db2[0] = (pModal->db2_01 & 0xf); + db2[1] = db2[2] = db2[3] = + db2[4] = ((pModal->db2_01 >> 4) & 0xf); + } else { + int i; + for (i = 0; i < 5; i++) { + ob[i] = pModal->ob_01; + db1[i] = pModal->db1_01; + db2[i] = pModal->db1_01; + } + } + + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]); + + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, + AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]); + + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]); + ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, + AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]); + + + if (AR_SREV_9285_11(ah)) + REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); + + REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, + pModal->switchSettling); + REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, + pModal->adcDesiredSize); + + REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | + SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | + SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); + REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, + pModal->thresh62); + REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, + pModal->thresh62); + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, + pModal->txFrameToDataStart); + REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, + pModal->txFrameToPaOn); + } + + if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_3) { + if (IS_CHAN_HT40(chan)) + REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, + pModal->swSettleHt40); + } +} + +static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; + struct modal_eep_4k_header *pModal = &eep->modalHeader; + + return pModal->antCtrlCommon & 0xFFFF; +} + +static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, + enum ieee80211_band freq_band) +{ + return 1; +} + +static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) +{ +#define EEP_MAP4K_SPURCHAN \ + (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) + + u16 spur_val = AR_NO_SPUR; + + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Getting spur idx %d is2Ghz. %d val %x\n", + i, is2GHz, ah->config.spurchans[i][is2GHz]); + + switch (ah->config.spurmode) { + case SPUR_DISABLE: + break; + case SPUR_ENABLE_IOCTL: + spur_val = ah->config.spurchans[i][is2GHz]; + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Getting spur val from new loc. %d\n", spur_val); + break; + case SPUR_ENABLE_EEPROM: + spur_val = EEP_MAP4K_SPURCHAN; + break; + } + + return spur_val; + +#undef EEP_MAP4K_SPURCHAN +} + +static struct eeprom_ops eep_4k_ops = { + .check_eeprom = ath9k_hw_4k_check_eeprom, + .get_eeprom = ath9k_hw_4k_get_eeprom, + .fill_eeprom = ath9k_hw_4k_fill_eeprom, + .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, + .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, + .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, + .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, + .set_board_values = ath9k_hw_4k_set_board_values, + .set_addac = ath9k_hw_4k_set_addac, + .set_txpower = ath9k_hw_4k_set_txpower, + .get_spur_channel = ath9k_hw_4k_get_spur_channel +}; + +/************************************************/ +/* EEPROM Operations for non-4K (Default) cards */ +/************************************************/ + +static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) +{ + return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF); +} + +static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) +{ + return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); +} + +static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) +{ +#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) + u16 *eep_data = (u16 *)&ah->eeprom.def; + int addr, ar5416_eep_start_loc = 0x100; + + for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { + if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, + eep_data)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Unable to read eeprom region\n"); + return false; + } + eep_data++; + } + return true; +#undef SIZE_EEPROM_DEF +} + +static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) +{ + struct ar5416_eeprom_def *eep = + (struct ar5416_eeprom_def *) &ah->eeprom.def; + u16 *eepdata, temp, magic, magic2; + u32 sum = 0, el; + bool need_swap = false; + int i, addr, size; + + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); + return false; + } + + if (!ath9k_hw_use_flash(ah)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "Read Magic = 0x%04X\n", magic); + + if (magic != AR5416_EEPROM_MAGIC) { + magic2 = swab16(magic); + + if (magic2 == AR5416_EEPROM_MAGIC) { + size = sizeof(struct ar5416_eeprom_def); + need_swap = true; + eepdata = (u16 *) (&ah->eeprom); + + for (addr = 0; addr < size / sizeof(u16); addr++) { + temp = swab16(*eepdata); + *eepdata = temp; + eepdata++; + } + } else { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Invalid EEPROM Magic. " + "Endianness mismatch.\n"); + return -EINVAL; + } + } + } + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); + + if (need_swap) + el = swab16(ah->eeprom.def.baseEepHeader.length); + else + el = ah->eeprom.def.baseEepHeader.length; + + if (el > sizeof(struct ar5416_eeprom_def)) + el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); + else + el = el / sizeof(u16); + + eepdata = (u16 *)(&ah->eeprom); + + for (i = 0; i < el; i++) + sum ^= *eepdata++; + + if (need_swap) { + u32 integer, j; + u16 word; + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "EEPROM Endianness is not native.. Changing.\n"); + + word = swab16(eep->baseEepHeader.length); + eep->baseEepHeader.length = word; + + word = swab16(eep->baseEepHeader.checksum); + eep->baseEepHeader.checksum = word; + + word = swab16(eep->baseEepHeader.version); + eep->baseEepHeader.version = word; + + word = swab16(eep->baseEepHeader.regDmn[0]); + eep->baseEepHeader.regDmn[0] = word; + + word = swab16(eep->baseEepHeader.regDmn[1]); + eep->baseEepHeader.regDmn[1] = word; + + word = swab16(eep->baseEepHeader.rfSilent); + eep->baseEepHeader.rfSilent = word; + + word = swab16(eep->baseEepHeader.blueToothOptions); + eep->baseEepHeader.blueToothOptions = word; + + word = swab16(eep->baseEepHeader.deviceCap); + eep->baseEepHeader.deviceCap = word; + + for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { + struct modal_eep_header *pModal = + &eep->modalHeader[j]; + integer = swab32(pModal->antCtrlCommon); + pModal->antCtrlCommon = integer; + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + integer = swab32(pModal->antCtrlChain[i]); + pModal->antCtrlChain[i] = integer; + } + + for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { + word = swab16(pModal->spurChans[i].spurChan); + pModal->spurChans[i].spurChan = word; + } + } + } + + if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || + ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Bad EEPROM checksum 0x%x or revision 0x%04x\n", + sum, ah->eep_ops->get_eeprom_ver(ah)); + return -EINVAL; + } + + return 0; +} + +static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, + enum eeprom_param param) +{ + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + struct modal_eep_header *pModal = eep->modalHeader; + struct base_eep_header *pBase = &eep->baseEepHeader; + + switch (param) { + case EEP_NFTHRESH_5: + return pModal[0].noiseFloorThreshCh[0]; + case EEP_NFTHRESH_2: + return pModal[1].noiseFloorThreshCh[0]; + case AR_EEPROM_MAC(0): + return pBase->macAddr[0] << 8 | pBase->macAddr[1]; + case AR_EEPROM_MAC(1): + return pBase->macAddr[2] << 8 | pBase->macAddr[3]; + case AR_EEPROM_MAC(2): + return pBase->macAddr[4] << 8 | pBase->macAddr[5]; + case EEP_REG_0: + return pBase->regDmn[0]; + case EEP_REG_1: + return pBase->regDmn[1]; + case EEP_OP_CAP: + return pBase->deviceCap; + case EEP_OP_MODE: + return pBase->opCapFlags; + case EEP_RF_SILENT: + return pBase->rfSilent; + case EEP_OB_5: + return pModal[0].ob; + case EEP_DB_5: + return pModal[0].db; + case EEP_OB_2: + return pModal[1].ob; + case EEP_DB_2: + return pModal[1].db; + case EEP_MINOR_REV: + return AR5416_VER_MASK; + case EEP_TX_MASK: + return pBase->txMask; + case EEP_RX_MASK: + return pBase->rxMask; + case EEP_RXGAIN_TYPE: + return pBase->rxGainType; + case EEP_TXGAIN_TYPE: + return pBase->txGainType; + case EEP_OL_PWRCTRL: + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + return pBase->openLoopPwrCntl ? true : false; + else + return false; + case EEP_RC_CHAIN_MASK: + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + return pBase->rcChainMask; + else + return 0; + case EEP_DAC_HPWR_5G: + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) + return pBase->dacHiPwrMode_5G; + else + return 0; + case EEP_FRAC_N_5G: + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22) + return pBase->frac_n_5g; + else + return 0; + default: + return 0; + } +} + +static void ath9k_hw_def_set_gain(struct ath_hw *ah, + struct modal_eep_header *pModal, + struct ar5416_eeprom_def *eep, + u8 txRxAttenLocal, int regChainOffset, int i) +{ + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { + txRxAttenLocal = pModal->txRxAttenCh[i]; + + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, + pModal->bswMargin[i]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN1_DB, + pModal->bswAtten[i]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, + pModal->xatten2Margin[i]); + REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + AR_PHY_GAIN_2GHZ_XATTEN2_DB, + pModal->xatten2Db[i]); + } else { + REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & + ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) + | SM(pModal-> bswMargin[i], + AR_PHY_GAIN_2GHZ_BSW_MARGIN)); + REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, + (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & + ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) + | SM(pModal->bswAtten[i], + AR_PHY_GAIN_2GHZ_BSW_ATTEN)); + } + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); + REG_RMW_FIELD(ah, + AR_PHY_RXGAIN + regChainOffset, + AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); + } else { + REG_WRITE(ah, + AR_PHY_RXGAIN + regChainOffset, + (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & + ~AR_PHY_RXGAIN_TXRX_ATTEN) + | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); + REG_WRITE(ah, + AR_PHY_GAIN_2GHZ + regChainOffset, + (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & + ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | + SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); + } +} + +static void ath9k_hw_def_set_board_values(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct modal_eep_header *pModal; + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + int i, regChainOffset; + u8 txRxAttenLocal; + + pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); + txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; + + REG_WRITE(ah, AR_PHY_SWITCH_COM, + ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (AR_SREV_9280(ah)) { + if (i >= 2) + break; + } + + if (AR_SREV_5416_20_OR_LATER(ah) && + (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + else + regChainOffset = i * 0x1000; + + REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, + pModal->antCtrlChain[i]); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, + (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & + ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | + SM(pModal->iqCalICh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | + SM(pModal->iqCalQCh[i], + AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); + + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) + ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, + regChainOffset, i); + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + if (IS_CHAN_2GHZ(chan)) { + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, + AR_AN_RF2G1_CH0_OB, + AR_AN_RF2G1_CH0_OB_S, + pModal->ob); + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, + AR_AN_RF2G1_CH0_DB, + AR_AN_RF2G1_CH0_DB_S, + pModal->db); + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, + AR_AN_RF2G1_CH1_OB, + AR_AN_RF2G1_CH1_OB_S, + pModal->ob_ch1); + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, + AR_AN_RF2G1_CH1_DB, + AR_AN_RF2G1_CH1_DB_S, + pModal->db_ch1); + } else { + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, + AR_AN_RF5G1_CH0_OB5, + AR_AN_RF5G1_CH0_OB5_S, + pModal->ob); + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, + AR_AN_RF5G1_CH0_DB5, + AR_AN_RF5G1_CH0_DB5_S, + pModal->db); + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, + AR_AN_RF5G1_CH1_OB5, + AR_AN_RF5G1_CH1_OB5_S, + pModal->ob_ch1); + ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, + AR_AN_RF5G1_CH1_DB5, + AR_AN_RF5G1_CH1_DB5_S, + pModal->db_ch1); + } + ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, + AR_AN_TOP2_XPABIAS_LVL, + AR_AN_TOP2_XPABIAS_LVL_S, + pModal->xpaBiasLvl); + ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, + AR_AN_TOP2_LOCALBIAS, + AR_AN_TOP2_LOCALBIAS_S, + pModal->local_bias); + REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, + pModal->force_xpaon); + } + + REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, + pModal->switchSettling); + REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, + pModal->adcDesiredSize); + + if (!AR_SREV_9280_10_OR_LATER(ah)) + REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, + AR_PHY_DESIRED_SZ_PGA, + pModal->pgaDesiredSize); + + REG_WRITE(ah, AR_PHY_RF_CTL4, + SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) + | SM(pModal->txEndToXpaOff, + AR_PHY_RF_CTL4_TX_END_XPAB_OFF) + | SM(pModal->txFrameToXpaOn, + AR_PHY_RF_CTL4_FRAME_XPAA_ON) + | SM(pModal->txFrameToXpaOn, + AR_PHY_RF_CTL4_FRAME_XPAB_ON)); + + REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, + pModal->txEndToRxOn); + + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, + pModal->thresh62); + REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, + AR_PHY_EXT_CCA0_THRESH62, + pModal->thresh62); + } else { + REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, + pModal->thresh62); + REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, + AR_PHY_EXT_CCA_THRESH62, + pModal->thresh62); + } + + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { + REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, + AR_PHY_TX_END_DATA_START, + pModal->txFrameToDataStart); + REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, + pModal->txFrameToPaOn); + } + + if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { + if (IS_CHAN_HT40(chan)) + REG_RMW_FIELD(ah, AR_PHY_SETTLING, + AR_PHY_SETTLING_SWITCH, + pModal->swSettleHt40); + } + + if (AR_SREV_9280_20_OR_LATER(ah) && + AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, + AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, + pModal->miscBits); + + + if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { + if (IS_CHAN_2GHZ(chan)) + REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + else if (eep->baseEepHeader.dacHiPwrMode_5G) + REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); + else + REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, + eep->baseEepHeader.dacLpMode); + + REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, + pModal->miscBits >> 2); + + REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, + AR_PHY_TX_DESIRED_SCALE_CCK, + eep->baseEepHeader.desiredScaleCCK); + } +} + +static void ath9k_hw_def_set_addac(struct ath_hw *ah, + struct ath9k_channel *chan) +{ +#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) + struct modal_eep_header *pModal; + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + u8 biaslevel; + + if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) + return; + + if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) + return; + + pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); + + if (pModal->xpaBiasLvl != 0xff) { + biaslevel = pModal->xpaBiasLvl; + } else { + u16 resetFreqBin, freqBin, freqCount = 0; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + resetFreqBin = FREQ2FBIN(centers.synth_center, + IS_CHAN_2GHZ(chan)); + freqBin = XPA_LVL_FREQ(0) & 0xff; + biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14); + + freqCount++; + + while (freqCount < 3) { + if (XPA_LVL_FREQ(freqCount) == 0x0) + break; + + freqBin = XPA_LVL_FREQ(freqCount) & 0xff; + if (resetFreqBin >= freqBin) + biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14); + else + break; + freqCount++; + } + } + + if (IS_CHAN_2GHZ(chan)) { + INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac, + 7, 1) & (~0x18)) | biaslevel << 3; + } else { + INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac, + 6, 1) & (~0xc0)) | biaslevel << 6; + } +#undef XPA_LVL_FREQ +} + +static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, + struct ath9k_channel *chan, + struct cal_data_per_freq *pRawDataSet, + u8 *bChans, u16 availPiers, + u16 tPdGainOverlap, int16_t *pMinCalPower, + u16 *pPdGainBoundaries, u8 *pPDADCValues, + u16 numXpdGains) +{ + int i, j, k; + int16_t ss; + u16 idxL = 0, idxR = 0, numPiers; + static u8 vpdTableL[AR5416_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + static u8 vpdTableR[AR5416_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + static u8 vpdTableI[AR5416_NUM_PD_GAINS] + [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; + + u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; + u8 minPwrT4[AR5416_NUM_PD_GAINS]; + u8 maxPwrT4[AR5416_NUM_PD_GAINS]; + int16_t vpdStep; + int16_t tmpVal; + u16 sizeCurrVpdTable, maxIndex, tgtIndex; + bool match; + int16_t minDelta = 0; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + for (numPiers = 0; numPiers < availPiers; numPiers++) { + if (bChans[numPiers] == AR5416_BCHAN_UNUSED) + break; + } + + match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, + IS_CHAN_2GHZ(chan)), + bChans, numPiers, &idxL, &idxR); + + if (match) { + for (i = 0; i < numXpdGains; i++) { + minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; + maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pRawDataSet[idxL].pwrPdg[i], + pRawDataSet[idxL].vpdPdg[i], + AR5416_PD_GAIN_ICEPTS, + vpdTableI[i]); + } + } else { + for (i = 0; i < numXpdGains; i++) { + pVpdL = pRawDataSet[idxL].vpdPdg[i]; + pPwrL = pRawDataSet[idxL].pwrPdg[i]; + pVpdR = pRawDataSet[idxR].vpdPdg[i]; + pPwrR = pRawDataSet[idxR].pwrPdg[i]; + + minPwrT4[i] = max(pPwrL[0], pPwrR[0]); + + maxPwrT4[i] = + min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], + pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); + + + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pPwrL, pVpdL, + AR5416_PD_GAIN_ICEPTS, + vpdTableL[i]); + ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], + pPwrR, pVpdR, + AR5416_PD_GAIN_ICEPTS, + vpdTableR[i]); + + for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { + vpdTableI[i][j] = + (u8)(ath9k_hw_interpolate((u16) + FREQ2FBIN(centers. + synth_center, + IS_CHAN_2GHZ + (chan)), + bChans[idxL], bChans[idxR], + vpdTableL[i][j], vpdTableR[i][j])); + } + } + } + + *pMinCalPower = (int16_t)(minPwrT4[0] / 2); + + k = 0; + + for (i = 0; i < numXpdGains; i++) { + if (i == (numXpdGains - 1)) + pPdGainBoundaries[i] = + (u16)(maxPwrT4[i] / 2); + else + pPdGainBoundaries[i] = + (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); + + pPdGainBoundaries[i] = + min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); + + if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { + minDelta = pPdGainBoundaries[0] - 23; + pPdGainBoundaries[0] = 23; + } else { + minDelta = 0; + } + + if (i == 0) { + if (AR_SREV_9280_10_OR_LATER(ah)) + ss = (int16_t)(0 - (minPwrT4[i] / 2)); + else + ss = 0; + } else { + ss = (int16_t)((pPdGainBoundaries[i - 1] - + (minPwrT4[i] / 2)) - + tPdGainOverlap + 1 + minDelta); + } + vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + + while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); + pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); + ss++; + } + + sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); + tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - + (minPwrT4[i] / 2)); + maxIndex = (tgtIndex < sizeCurrVpdTable) ? + tgtIndex : sizeCurrVpdTable; + + while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { + pPDADCValues[k++] = vpdTableI[i][ss++]; + } + + vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - + vpdTableI[i][sizeCurrVpdTable - 2]); + vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); + + if (tgtIndex > maxIndex) { + while ((ss <= tgtIndex) && + (k < (AR5416_NUM_PDADC_VALUES - 1))) { + tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + + (ss - maxIndex + 1) * vpdStep)); + pPDADCValues[k++] = (u8)((tmpVal > 255) ? + 255 : tmpVal); + ss++; + } + } + } + + while (i < AR5416_PD_GAINS_IN_MASK) { + pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; + i++; + } + + while (k < AR5416_NUM_PDADC_VALUES) { + pPDADCValues[k] = pPDADCValues[k - 1]; + k++; + } + + return; +} + +static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, + struct ath9k_channel *chan, + int16_t *pTxPowerIndexOffset) +{ +#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) +#define SM_PDGAIN_B(x, y) \ + SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) + + struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; + struct cal_data_per_freq *pRawDataset; + u8 *pCalBChans = NULL; + u16 pdGainOverlap_t2; + static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; + u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; + u16 numPiers, i, j; + int16_t tMinCalPower; + u16 numXpdGain, xpdMask; + u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; + u32 reg32, regOffset, regChainOffset; + int16_t modalIdx; + + modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; + xpdMask = pEepData->modalHeader[modalIdx].xpdGain; + + if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + pdGainOverlap_t2 = + pEepData->modalHeader[modalIdx].pdGainOverlap; + } else { + pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), + AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); + } + + if (IS_CHAN_2GHZ(chan)) { + pCalBChans = pEepData->calFreqPier2G; + numPiers = AR5416_NUM_2G_CAL_PIERS; + } else { + pCalBChans = pEepData->calFreqPier5G; + numPiers = AR5416_NUM_5G_CAL_PIERS; + } + + if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { + pRawDataset = pEepData->calPierData2G[0]; + ah->initPDADC = ((struct calDataPerFreqOpLoop *) + pRawDataset)->vpdPdg[0][0]; + } + + numXpdGain = 0; + + for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { + if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { + if (numXpdGain >= AR5416_NUM_PD_GAINS) + break; + xpdGainValues[numXpdGain] = + (u16)(AR5416_PD_GAINS_IN_MASK - i); + numXpdGain++; + } + } + + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, + (numXpdGain - 1) & 0x3); + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, + xpdGainValues[0]); + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, + xpdGainValues[1]); + REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, + xpdGainValues[2]); + + for (i = 0; i < AR5416_MAX_CHAINS; i++) { + if (AR_SREV_5416_20_OR_LATER(ah) && + (ah->rxchainmask == 5 || ah->txchainmask == 5) && + (i != 0)) { + regChainOffset = (i == 1) ? 0x2000 : 0x1000; + } else + regChainOffset = i * 0x1000; + + if (pEepData->baseEepHeader.txMask & (1 << i)) { + if (IS_CHAN_2GHZ(chan)) + pRawDataset = pEepData->calPierData2G[i]; + else + pRawDataset = pEepData->calPierData5G[i]; + + + if (OLC_FOR_AR9280_20_LATER) { + u8 pcdacIdx; + u8 txPower; + + ath9k_get_txgain_index(ah, chan, + (struct calDataPerFreqOpLoop *)pRawDataset, + pCalBChans, numPiers, &txPower, &pcdacIdx); + ath9k_olc_get_pdadcs(ah, pcdacIdx, + txPower/2, pdadcValues); + } else { + ath9k_hw_get_def_gain_boundaries_pdadcs(ah, + chan, pRawDataset, + pCalBChans, numPiers, + pdGainOverlap_t2, + &tMinCalPower, + gainBoundaries, + pdadcValues, + numXpdGain); + } + + if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { + if (OLC_FOR_AR9280_20_LATER) { + REG_WRITE(ah, + AR_PHY_TPCRG5 + regChainOffset, + SM(0x6, + AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | + SM_PD_GAIN(1) | SM_PD_GAIN(2) | + SM_PD_GAIN(3) | SM_PD_GAIN(4)); + } else { + REG_WRITE(ah, + AR_PHY_TPCRG5 + regChainOffset, + SM(pdGainOverlap_t2, + AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| + SM_PDGAIN_B(0, 1) | + SM_PDGAIN_B(1, 2) | + SM_PDGAIN_B(2, 3) | + SM_PDGAIN_B(3, 4)); + } + } + + regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; + for (j = 0; j < 32; j++) { + reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | + ((pdadcValues[4 * j + 1] & 0xFF) << 8) | + ((pdadcValues[4 * j + 2] & 0xFF) << 16)| + ((pdadcValues[4 * j + 3] & 0xFF) << 24); + REG_WRITE(ah, regOffset, reg32); + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "PDADC (%d,%4x): %4.4x %8.8x\n", + i, regChainOffset, regOffset, + reg32); + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "PDADC: Chain %d | PDADC %3d " + "Value %3d | PDADC %3d Value %3d | " + "PDADC %3d Value %3d | PDADC %3d " + "Value %3d |\n", + i, 4 * j, pdadcValues[4 * j], + 4 * j + 1, pdadcValues[4 * j + 1], + 4 * j + 2, pdadcValues[4 * j + 2], + 4 * j + 3, + pdadcValues[4 * j + 3]); + + regOffset += 4; + } + } + } + + *pTxPowerIndexOffset = 0; + + return true; +#undef SM_PD_GAIN +#undef SM_PDGAIN_B +} + +static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, + struct ath9k_channel *chan, + int16_t *ratesArray, + u16 cfgCtl, + u16 AntennaReduction, + u16 twiceMaxRegulatoryPower, + u16 powerLimit) +{ +#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ +#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ + + struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; + u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + static const u16 tpScaleReductionTable[5] = + { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; + + int i; + int16_t twiceLargestAntenna; + struct cal_ctl_data *rep; + struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { + 0, { 0, 0, 0, 0} + }; + struct cal_target_power_leg targetPowerOfdmExt = { + 0, { 0, 0, 0, 0} }, targetPowerCckExt = { + 0, { 0, 0, 0, 0 } + }; + struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { + 0, {0, 0, 0, 0} + }; + u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; + u16 ctlModesFor11a[] = + { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; + u16 ctlModesFor11g[] = + { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, + CTL_2GHT40 + }; + u16 numCtlModes, *pCtlMode, ctlMode, freq; + struct chan_centers centers; + int tx_chainmask; + u16 twiceMinEdgePower; + + tx_chainmask = ah->txchainmask; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + + twiceLargestAntenna = max( + pEepData->modalHeader + [IS_CHAN_2GHZ(chan)].antennaGainCh[0], + pEepData->modalHeader + [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); + + twiceLargestAntenna = max((u8)twiceLargestAntenna, + pEepData->modalHeader + [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); + + twiceLargestAntenna = (int16_t)min(AntennaReduction - + twiceLargestAntenna, 0); + + maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; + + if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { + maxRegAllowedPower -= + (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); + } + + scaledPower = min(powerLimit, maxRegAllowedPower); + + switch (ar5416_get_ntxchains(tx_chainmask)) { + case 1: + break; + case 2: + scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + break; + case 3: + scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; + break; + } + + scaledPower = max((u16)0, scaledPower); + + if (IS_CHAN_2GHZ(chan)) { + numCtlModes = ARRAY_SIZE(ctlModesFor11g) - + SUB_NUM_CTL_MODES_AT_2G_40; + pCtlMode = ctlModesFor11g; + + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, + &targetPowerCck, 4, false); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, + &targetPowerOfdm, 4, false); + ath9k_hw_get_target_powers(ah, chan, + pEepData->calTargetPower2GHT20, + AR5416_NUM_2G_20_TARGET_POWERS, + &targetPowerHt20, 8, false); + + if (IS_CHAN_HT40(chan)) { + numCtlModes = ARRAY_SIZE(ctlModesFor11g); + ath9k_hw_get_target_powers(ah, chan, + pEepData->calTargetPower2GHT40, + AR5416_NUM_2G_40_TARGET_POWERS, + &targetPowerHt40, 8, true); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPowerCck, + AR5416_NUM_2G_CCK_TARGET_POWERS, + &targetPowerCckExt, 4, true); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPower2G, + AR5416_NUM_2G_20_TARGET_POWERS, + &targetPowerOfdmExt, 4, true); + } + } else { + numCtlModes = ARRAY_SIZE(ctlModesFor11a) - + SUB_NUM_CTL_MODES_AT_5G_40; + pCtlMode = ctlModesFor11a; + + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPower5G, + AR5416_NUM_5G_20_TARGET_POWERS, + &targetPowerOfdm, 4, false); + ath9k_hw_get_target_powers(ah, chan, + pEepData->calTargetPower5GHT20, + AR5416_NUM_5G_20_TARGET_POWERS, + &targetPowerHt20, 8, false); + + if (IS_CHAN_HT40(chan)) { + numCtlModes = ARRAY_SIZE(ctlModesFor11a); + ath9k_hw_get_target_powers(ah, chan, + pEepData->calTargetPower5GHT40, + AR5416_NUM_5G_40_TARGET_POWERS, + &targetPowerHt40, 8, true); + ath9k_hw_get_legacy_target_powers(ah, chan, + pEepData->calTargetPower5G, + AR5416_NUM_5G_20_TARGET_POWERS, + &targetPowerOfdmExt, 4, true); + } + } + + for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { + bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || + (pCtlMode[ctlMode] == CTL_2GHT40); + if (isHt40CtlMode) + freq = centers.synth_center; + else if (pCtlMode[ctlMode] & EXT_ADDITIVE) + freq = centers.ext_center; + else + freq = centers.ctl_center; + + if (ah->eep_ops->get_eeprom_ver(ah) == 14 && + ah->eep_ops->get_eeprom_rev(ah) <= 2) + twiceMaxEdgePower = AR5416_MAX_RATE_POWER; + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " + "EXT_ADDITIVE %d\n", + ctlMode, numCtlModes, isHt40CtlMode, + (pCtlMode[ctlMode] & EXT_ADDITIVE)); + + for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " + "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " + "chan %d\n", + i, cfgCtl, pCtlMode[ctlMode], + pEepData->ctlIndex[i], chan->channel); + + if ((((cfgCtl & ~CTL_MODE_M) | + (pCtlMode[ctlMode] & CTL_MODE_M)) == + pEepData->ctlIndex[i]) || + (((cfgCtl & ~CTL_MODE_M) | + (pCtlMode[ctlMode] & CTL_MODE_M)) == + ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { + rep = &(pEepData->ctlData[i]); + + twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, + rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], + IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + " MATCH-EE_IDX %d: ch %d is2 %d " + "2xMinEdge %d chainmask %d chains %d\n", + i, freq, IS_CHAN_2GHZ(chan), + twiceMinEdgePower, tx_chainmask, + ar5416_get_ntxchains + (tx_chainmask)); + if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { + twiceMaxEdgePower = min(twiceMaxEdgePower, + twiceMinEdgePower); + } else { + twiceMaxEdgePower = twiceMinEdgePower; + break; + } + } + } + + minCtlPower = min(twiceMaxEdgePower, scaledPower); + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + " SEL-Min ctlMode %d pCtlMode %d " + "2xMaxEdge %d sP %d minCtlPwr %d\n", + ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, + scaledPower, minCtlPower); + + switch (pCtlMode[ctlMode]) { + case CTL_11B: + for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { + targetPowerCck.tPow2x[i] = + min((u16)targetPowerCck.tPow2x[i], + minCtlPower); + } + break; + case CTL_11A: + case CTL_11G: + for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { + targetPowerOfdm.tPow2x[i] = + min((u16)targetPowerOfdm.tPow2x[i], + minCtlPower); + } + break; + case CTL_5GHT20: + case CTL_2GHT20: + for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { + targetPowerHt20.tPow2x[i] = + min((u16)targetPowerHt20.tPow2x[i], + minCtlPower); + } + break; + case CTL_11B_EXT: + targetPowerCckExt.tPow2x[0] = min((u16) + targetPowerCckExt.tPow2x[0], + minCtlPower); + break; + case CTL_11A_EXT: + case CTL_11G_EXT: + targetPowerOfdmExt.tPow2x[0] = min((u16) + targetPowerOfdmExt.tPow2x[0], + minCtlPower); + break; + case CTL_5GHT40: + case CTL_2GHT40: + for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { + targetPowerHt40.tPow2x[i] = + min((u16)targetPowerHt40.tPow2x[i], + minCtlPower); + } + break; + default: + break; + } + } + + ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = + ratesArray[rate18mb] = ratesArray[rate24mb] = + targetPowerOfdm.tPow2x[0]; + ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; + ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; + ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; + ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; + + for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) + ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; + + if (IS_CHAN_2GHZ(chan)) { + ratesArray[rate1l] = targetPowerCck.tPow2x[0]; + ratesArray[rate2s] = ratesArray[rate2l] = + targetPowerCck.tPow2x[1]; + ratesArray[rate5_5s] = ratesArray[rate5_5l] = + targetPowerCck.tPow2x[2]; + ; + ratesArray[rate11s] = ratesArray[rate11l] = + targetPowerCck.tPow2x[3]; + ; + } + if (IS_CHAN_HT40(chan)) { + for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { + ratesArray[rateHt40_0 + i] = + targetPowerHt40.tPow2x[i]; + } + ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; + ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; + ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; + if (IS_CHAN_2GHZ(chan)) { + ratesArray[rateExtCck] = + targetPowerCckExt.tPow2x[0]; + } + } + return true; +} + +static int ath9k_hw_def_set_txpower(struct ath_hw *ah, + struct ath9k_channel *chan, + u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, + u8 powerLimit) +{ +#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) + struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; + struct modal_eep_header *pModal = + &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); + int16_t ratesArray[Ar5416RateSize]; + int16_t txPowerIndexOffset = 0; + u8 ht40PowerIncForPdadc = 2; + int i, cck_ofdm_delta = 0; + + memset(ratesArray, 0, sizeof(ratesArray)); + + if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= + AR5416_EEP_MINOR_VER_2) { + ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; + } + + if (!ath9k_hw_set_def_power_per_rate_table(ah, chan, + &ratesArray[0], cfgCtl, + twiceAntennaReduction, + twiceMaxRegulatoryPower, + powerLimit)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "ath9k_hw_set_txpower: unable to set " + "tx power per rate table\n"); + return -EIO; + } + + if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "ath9k_hw_set_txpower: unable to set power table\n"); + return -EIO; + } + + for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { + ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > AR5416_MAX_RATE_POWER) + ratesArray[i] = AR5416_MAX_RATE_POWER; + } + + if (AR_SREV_9280_10_OR_LATER(ah)) { + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; + } + + REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, + ATH9K_POW_SM(ratesArray[rate18mb], 24) + | ATH9K_POW_SM(ratesArray[rate12mb], 16) + | ATH9K_POW_SM(ratesArray[rate9mb], 8) + | ATH9K_POW_SM(ratesArray[rate6mb], 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, + ATH9K_POW_SM(ratesArray[rate54mb], 24) + | ATH9K_POW_SM(ratesArray[rate48mb], 16) + | ATH9K_POW_SM(ratesArray[rate36mb], 8) + | ATH9K_POW_SM(ratesArray[rate24mb], 0)); + + if (IS_CHAN_2GHZ(chan)) { + if (OLC_FOR_AR9280_20_LATER) { + cck_ofdm_delta = 2; + REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) + | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) + | ATH9K_POW_SM(ratesArray[rateXr], 8) + | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) + | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) + | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) + | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); + } else { + REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, + ATH9K_POW_SM(ratesArray[rate2s], 24) + | ATH9K_POW_SM(ratesArray[rate2l], 16) + | ATH9K_POW_SM(ratesArray[rateXr], 8) + | ATH9K_POW_SM(ratesArray[rate1l], 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, + ATH9K_POW_SM(ratesArray[rate11s], 24) + | ATH9K_POW_SM(ratesArray[rate11l], 16) + | ATH9K_POW_SM(ratesArray[rate5_5s], 8) + | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); + } + } + + REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, + ATH9K_POW_SM(ratesArray[rateHt20_3], 24) + | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) + | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) + | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, + ATH9K_POW_SM(ratesArray[rateHt20_7], 24) + | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) + | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) + | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); + + if (IS_CHAN_HT40(chan)) { + REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, + ATH9K_POW_SM(ratesArray[rateHt40_3] + + ht40PowerIncForPdadc, 24) + | ATH9K_POW_SM(ratesArray[rateHt40_2] + + ht40PowerIncForPdadc, 16) + | ATH9K_POW_SM(ratesArray[rateHt40_1] + + ht40PowerIncForPdadc, 8) + | ATH9K_POW_SM(ratesArray[rateHt40_0] + + ht40PowerIncForPdadc, 0)); + REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, + ATH9K_POW_SM(ratesArray[rateHt40_7] + + ht40PowerIncForPdadc, 24) + | ATH9K_POW_SM(ratesArray[rateHt40_6] + + ht40PowerIncForPdadc, 16) + | ATH9K_POW_SM(ratesArray[rateHt40_5] + + ht40PowerIncForPdadc, 8) + | ATH9K_POW_SM(ratesArray[rateHt40_4] + + ht40PowerIncForPdadc, 0)); + if (OLC_FOR_AR9280_20_LATER) { + REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, + ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) + | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) + | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) + | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); + } else { + REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, + ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) + | ATH9K_POW_SM(ratesArray[rateExtCck], 16) + | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) + | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); + } + } + + REG_WRITE(ah, AR_PHY_POWER_TX_SUB, + ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) + | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); + + i = rate6mb; + + if (IS_CHAN_HT40(chan)) + i = rateHt40_0; + else if (IS_CHAN_HT20(chan)) + i = rateHt20_0; + + if (AR_SREV_9280_10_OR_LATER(ah)) + ah->regulatory.max_power_level = + ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; + else + ah->regulatory.max_power_level = ratesArray[i]; + + switch(ar5416_get_ntxchains(ah->txchainmask)) { + case 1: + break; + case 2: + ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; + break; + case 3: + ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "Invalid chainmask configuration\n"); + break; + } + + return 0; +} + +static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, + enum ieee80211_band freq_band) +{ + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + struct modal_eep_header *pModal = + &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); + struct base_eep_header *pBase = &eep->baseEepHeader; + u8 num_ant_config; + + num_ant_config = 1; + + if (pBase->version >= 0x0E0D) + if (pModal->useAnt1) + num_ant_config += 1; + + return num_ant_config; +} + +static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + struct ar5416_eeprom_def *eep = &ah->eeprom.def; + struct modal_eep_header *pModal = + &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); + + return pModal->antCtrlCommon & 0xFFFF; +} + +static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) +{ +#define EEP_DEF_SPURCHAN \ + (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) + + u16 spur_val = AR_NO_SPUR; + + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Getting spur idx %d is2Ghz. %d val %x\n", + i, is2GHz, ah->config.spurchans[i][is2GHz]); + + switch (ah->config.spurmode) { + case SPUR_DISABLE: + break; + case SPUR_ENABLE_IOCTL: + spur_val = ah->config.spurchans[i][is2GHz]; + DPRINTF(ah->ah_sc, ATH_DBG_ANI, + "Getting spur val from new loc. %d\n", spur_val); + break; + case SPUR_ENABLE_EEPROM: + spur_val = EEP_DEF_SPURCHAN; + break; + } + + return spur_val; + +#undef EEP_DEF_SPURCHAN +} + +static struct eeprom_ops eep_def_ops = { + .check_eeprom = ath9k_hw_def_check_eeprom, + .get_eeprom = ath9k_hw_def_get_eeprom, + .fill_eeprom = ath9k_hw_def_fill_eeprom, + .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, + .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, + .get_num_ant_config = ath9k_hw_def_get_num_ant_config, + .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, + .set_board_values = ath9k_hw_def_set_board_values, + .set_addac = ath9k_hw_def_set_addac, + .set_txpower = ath9k_hw_def_set_txpower, + .get_spur_channel = ath9k_hw_def_get_spur_channel +}; + +int ath9k_hw_eeprom_attach(struct ath_hw *ah) +{ + int status; + + if (AR_SREV_9285(ah)) { + ah->eep_map = EEP_MAP_4KBITS; + ah->eep_ops = &eep_4k_ops; + } else { + ah->eep_map = EEP_MAP_DEFAULT; + ah->eep_ops = &eep_def_ops; + } + + if (!ah->eep_ops->fill_eeprom(ah)) + return -EIO; + + status = ah->eep_ops->check_eeprom(ah); + + return status; +} diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h new file mode 100644 index 000000000000..9a7715df5cff --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -0,0 +1,509 @@ +/* + * 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 EEPROM_H +#define EEPROM_H + +#include + +#define AH_USE_EEPROM 0x1 + +#ifdef __BIG_ENDIAN +#define AR5416_EEPROM_MAGIC 0x5aa5 +#else +#define AR5416_EEPROM_MAGIC 0xa55a +#endif + +#define CTRY_DEBUG 0x1ff +#define CTRY_DEFAULT 0 + +#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 +#define AR_EEPROM_EEPCAP_AES_DIS 0x0002 +#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 +#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 +#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 +#define AR_EEPROM_EEPCAP_MAXQCU_S 4 +#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 +#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 +#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 + +#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 + +#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 +#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 + +#define AR5416_EEPROM_MAGIC_OFFSET 0x0 +#define AR5416_EEPROM_S 2 +#define AR5416_EEPROM_OFFSET 0x2000 +#define AR5416_EEPROM_MAX 0xae0 + +#define AR5416_EEPROM_START_ADDR \ + (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 + +#define SD_NO_CTL 0xE0 +#define NO_CTL 0xff +#define CTL_MODE_M 7 +#define CTL_11A 0 +#define CTL_11B 1 +#define CTL_11G 2 +#define CTL_2GHT20 5 +#define CTL_5GHT20 6 +#define CTL_2GHT40 7 +#define CTL_5GHT40 8 + +#define EXT_ADDITIVE (0x8000) +#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) +#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) +#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) + +#define SUB_NUM_CTL_MODES_AT_5G_40 2 +#define SUB_NUM_CTL_MODES_AT_2G_40 3 + +#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ +#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ + +/* + * For AR9285 and later chipsets, the following bits are not being programmed + * in EEPROM and so need to be enabled always. + * + * Bit 0: en_fcc_mid + * Bit 1: en_jap_mid + * Bit 2: en_fcc_dfs_ht40 + * Bit 3: en_jap_ht40 + * Bit 4: en_jap_dfs_ht40 + */ +#define AR9285_RDEXT_DEFAULT 0x1F + +#define AR_EEPROM_MAC(i) (0x1d+(i)) +#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) +#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) +#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) + +#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) +#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ + ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + +#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c +#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 +#define AR_EEPROM_RFSILENT_POLARITY 0x0002 +#define AR_EEPROM_RFSILENT_POLARITY_S 1 + +#define EEP_RFSILENT_ENABLED 0x0001 +#define EEP_RFSILENT_ENABLED_S 0 +#define EEP_RFSILENT_POLARITY 0x0002 +#define EEP_RFSILENT_POLARITY_S 1 +#define EEP_RFSILENT_GPIO_SEL 0x001c +#define EEP_RFSILENT_GPIO_SEL_S 2 + +#define AR5416_OPFLAGS_11A 0x01 +#define AR5416_OPFLAGS_11G 0x02 +#define AR5416_OPFLAGS_N_5G_HT40 0x04 +#define AR5416_OPFLAGS_N_2G_HT40 0x08 +#define AR5416_OPFLAGS_N_5G_HT20 0x10 +#define AR5416_OPFLAGS_N_2G_HT20 0x20 + +#define AR5416_EEP_NO_BACK_VER 0x1 +#define AR5416_EEP_VER 0xE +#define AR5416_EEP_VER_MINOR_MASK 0x0FFF +#define AR5416_EEP_MINOR_VER_2 0x2 +#define AR5416_EEP_MINOR_VER_3 0x3 +#define AR5416_EEP_MINOR_VER_7 0x7 +#define AR5416_EEP_MINOR_VER_9 0x9 +#define AR5416_EEP_MINOR_VER_16 0x10 +#define AR5416_EEP_MINOR_VER_17 0x11 +#define AR5416_EEP_MINOR_VER_19 0x13 +#define AR5416_EEP_MINOR_VER_20 0x14 +#define AR5416_EEP_MINOR_VER_22 0x16 + +#define AR5416_NUM_5G_CAL_PIERS 8 +#define AR5416_NUM_2G_CAL_PIERS 4 +#define AR5416_NUM_5G_20_TARGET_POWERS 8 +#define AR5416_NUM_5G_40_TARGET_POWERS 8 +#define AR5416_NUM_2G_CCK_TARGET_POWERS 3 +#define AR5416_NUM_2G_20_TARGET_POWERS 4 +#define AR5416_NUM_2G_40_TARGET_POWERS 4 +#define AR5416_NUM_CTLS 24 +#define AR5416_NUM_BAND_EDGES 8 +#define AR5416_NUM_PD_GAINS 4 +#define AR5416_PD_GAINS_IN_MASK 4 +#define AR5416_PD_GAIN_ICEPTS 5 +#define AR5416_EEPROM_MODAL_SPURS 5 +#define AR5416_MAX_RATE_POWER 63 +#define AR5416_NUM_PDADC_VALUES 128 +#define AR5416_BCHAN_UNUSED 0xFF +#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 +#define AR5416_MAX_CHAINS 3 +#define AR5416_PWR_TABLE_OFFSET -5 + +/* Rx gain type values */ +#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 +#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1 +#define AR5416_EEP_RXGAIN_ORIG 2 + +/* Tx gain type values */ +#define AR5416_EEP_TXGAIN_ORIGINAL 0 +#define AR5416_EEP_TXGAIN_HIGH_POWER 1 + +#define AR5416_EEP4K_START_LOC 64 +#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3 +#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3 +#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3 +#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3 +#define AR5416_EEP4K_NUM_CTLS 12 +#define AR5416_EEP4K_NUM_BAND_EDGES 4 +#define AR5416_EEP4K_NUM_PD_GAINS 2 +#define AR5416_EEP4K_PD_GAINS_IN_MASK 4 +#define AR5416_EEP4K_PD_GAIN_ICEPTS 5 +#define AR5416_EEP4K_MAX_CHAINS 1 + +#define AR9280_TX_GAIN_TABLE_SIZE 22 + +enum eeprom_param { + EEP_NFTHRESH_5, + EEP_NFTHRESH_2, + EEP_MAC_MSW, + EEP_MAC_MID, + EEP_MAC_LSW, + EEP_REG_0, + EEP_REG_1, + EEP_OP_CAP, + EEP_OP_MODE, + EEP_RF_SILENT, + EEP_OB_5, + EEP_DB_5, + EEP_OB_2, + EEP_DB_2, + EEP_MINOR_REV, + EEP_TX_MASK, + EEP_RX_MASK, + EEP_RXGAIN_TYPE, + EEP_TXGAIN_TYPE, + EEP_OL_PWRCTRL, + EEP_RC_CHAIN_MASK, + EEP_DAC_HPWR_5G, + EEP_FRAC_N_5G +}; + +enum ar5416_rates { + rate6mb, rate9mb, rate12mb, rate18mb, + rate24mb, rate36mb, rate48mb, rate54mb, + rate1l, rate2l, rate2s, rate5_5l, + rate5_5s, rate11l, rate11s, rateXr, + rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, + rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, + rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, + rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, + rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, + Ar5416RateSize +}; + +enum ath9k_hal_freq_band { + ATH9K_HAL_FREQ_BAND_5GHZ = 0, + ATH9K_HAL_FREQ_BAND_2GHZ = 1 +}; + +struct base_eep_header { + u16 length; + u16 checksum; + u16 version; + u8 opCapFlags; + u8 eepMisc; + u16 regDmn[2]; + u8 macAddr[6]; + u8 rxMask; + u8 txMask; + u16 rfSilent; + u16 blueToothOptions; + u16 deviceCap; + u32 binBuildNumber; + u8 deviceType; + u8 pwdclkind; + u8 futureBase_1[2]; + u8 rxGainType; + u8 dacHiPwrMode_5G; + u8 openLoopPwrCntl; + u8 dacLpMode; + u8 txGainType; + u8 rcChainMask; + u8 desiredScaleCCK; + u8 power_table_offset; + u8 frac_n_5g; + u8 futureBase_3[21]; +} __packed; + +struct base_eep_header_4k { + u16 length; + u16 checksum; + u16 version; + u8 opCapFlags; + u8 eepMisc; + u16 regDmn[2]; + u8 macAddr[6]; + u8 rxMask; + u8 txMask; + u16 rfSilent; + u16 blueToothOptions; + u16 deviceCap; + u32 binBuildNumber; + u8 deviceType; + u8 txGainType; +} __packed; + + +struct spur_chan { + u16 spurChan; + u8 spurRangeLow; + u8 spurRangeHigh; +} __packed; + +struct modal_eep_header { + u32 antCtrlChain[AR5416_MAX_CHAINS]; + u32 antCtrlCommon; + u8 antennaGainCh[AR5416_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR5416_MAX_CHAINS]; + u8 rxTxMarginCh[AR5416_MAX_CHAINS]; + u8 adcDesiredSize; + u8 pgaDesiredSize; + u8 xlnaGainCh[AR5416_MAX_CHAINS]; + u8 txEndToXpaOff; + u8 txEndToRxOn; + u8 txFrameToXpaOn; + u8 thresh62; + u8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; + u8 xpdGain; + u8 xpd; + u8 iqCalICh[AR5416_MAX_CHAINS]; + u8 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 xatten2Db[AR5416_MAX_CHAINS]; + u8 xatten2Margin[AR5416_MAX_CHAINS]; + u8 ob_ch1; + u8 db_ch1; + u8 useAnt1:1, + force_xpaon:1, + local_bias:1, + femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1; + u8 miscBits; + u16 xpaBiasLvlFreq[3]; + u8 futureModal[6]; + + struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; +} __packed; + +struct calDataPerFreqOpLoop { + u8 pwrPdg[2][5]; + u8 vpdPdg[2][5]; + u8 pcdac[2][5]; + u8 empty[2][5]; +} __packed; + +struct modal_eep_4k_header { + u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; + u32 antCtrlCommon; + u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; + u8 switchSettling; + u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; + u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS]; + u8 adcDesiredSize; + u8 pgaDesiredSize; + u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS]; + u8 txEndToXpaOff; + u8 txEndToRxOn; + u8 txFrameToXpaOn; + u8 thresh62; + u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS]; + u8 xpdGain; + u8 xpd; + u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS]; + u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS]; + u8 pdGainOverlap; + u8 ob_01; + u8 db1_01; + u8 xpaBiasLvl; + u8 txFrameToDataStart; + u8 txFrameToPaOn; + u8 ht40PowerIncForPdadc; + u8 bswAtten[AR5416_EEP4K_MAX_CHAINS]; + u8 bswMargin[AR5416_EEP4K_MAX_CHAINS]; + u8 swSettleHt40; + u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS]; + u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS]; + u8 db2_01; + u8 version; + u16 ob_234; + u16 db1_234; + u16 db2_234; + u8 futureModal[4]; + + struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; +} __packed; + + +struct cal_data_per_freq { + u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; + u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; +} __packed; + +struct cal_data_per_freq_4k { + u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; + u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; +} __packed; + +struct cal_target_power_leg { + u8 bChannel; + u8 tPow2x[4]; +} __packed; + +struct cal_target_power_ht { + u8 bChannel; + u8 tPow2x[8]; +} __packed; + + +#ifdef __BIG_ENDIAN_BITFIELD +struct cal_ctl_edges { + u8 bChannel; + u8 flag:2, tPower:6; +} __packed; +#else +struct cal_ctl_edges { + u8 bChannel; + u8 tPower:6, flag:2; +} __packed; +#endif + +struct cal_ctl_data { + struct cal_ctl_edges + ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; +} __packed; + +struct cal_ctl_data_4k { + struct cal_ctl_edges + ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES]; +} __packed; + +struct ar5416_eeprom_def { + struct base_eep_header baseEepHeader; + u8 custData[64]; + struct modal_eep_header modalHeader[2]; + u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; + u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; + struct cal_data_per_freq + calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS]; + struct cal_data_per_freq + calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; + struct cal_target_power_leg + calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS]; + struct cal_target_power_ht + calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; + struct cal_target_power_ht + calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; + struct cal_target_power_leg + calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; + struct cal_target_power_leg + calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS]; + struct cal_target_power_ht + calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; + struct cal_target_power_ht + calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; + u8 ctlIndex[AR5416_NUM_CTLS]; + struct cal_ctl_data ctlData[AR5416_NUM_CTLS]; + u8 padding; +} __packed; + +struct ar5416_eeprom_4k { + struct base_eep_header_4k baseEepHeader; + u8 custData[20]; + struct modal_eep_4k_header modalHeader; + u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS]; + struct cal_data_per_freq_4k + calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS]; + struct cal_target_power_leg + calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS]; + struct cal_target_power_leg + calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS]; + struct cal_target_power_ht + calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS]; + struct cal_target_power_ht + calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS]; + u8 ctlIndex[AR5416_EEP4K_NUM_CTLS]; + struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS]; + u8 padding; +} __packed; + +enum reg_ext_bitmap { + REG_EXT_JAPAN_MIDBAND = 1, + REG_EXT_FCC_DFS_HT40 = 2, + REG_EXT_JAPAN_NONDFS_HT40 = 3, + REG_EXT_JAPAN_DFS_HT40 = 4 +}; + +struct ath9k_country_entry { + u16 countryCode; + u16 regDmnEnum; + u16 regDmn5G; + u16 regDmn2G; + u8 isMultidomain; + u8 iso[3]; +}; + +enum ath9k_eep_map { + EEP_MAP_DEFAULT = 0x0, + EEP_MAP_4KBITS, + EEP_MAP_MAX +}; + +struct eeprom_ops { + int (*check_eeprom)(struct ath_hw *hw); + u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param); + bool (*fill_eeprom)(struct ath_hw *hw); + int (*get_eeprom_ver)(struct ath_hw *hw); + int (*get_eeprom_rev)(struct ath_hw *hw); + u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); + u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, + struct ath9k_channel *chan); + void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); + void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); + int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, + u16 cfgCtl, u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, u8 powerLimit); + u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); +}; + +#define ar5416_get_ntxchains(_txchainmask) \ + (((_txchainmask >> 2) & 1) + \ + ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) + +int ath9k_hw_eeprom_attach(struct ath_hw *ah); + +#endif /* EEPROM_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c new file mode 100644 index 000000000000..24299e65fdcf --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -0,0 +1,3861 @@ +/* + * 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 +#include + +#include "ath9k.h" +#include "initvals.h" + +static int btcoex_enable; +module_param(btcoex_enable, bool, 0); +MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support"); + +#define ATH9K_CLOCK_RATE_CCK 22 +#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 +#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 + +static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); +static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, + enum ath9k_ht_macmode macmode); +static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, + struct ar5416_eeprom_def *pEepData, + u32 reg, u32 value); +static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); +static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); + +/********************/ +/* Helper Functions */ +/********************/ + +static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + + if (!ah->curchan) /* should really check for CCK instead */ + return clks / ATH9K_CLOCK_RATE_CCK; + if (conf->channel->band == IEEE80211_BAND_2GHZ) + return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; + + return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; +} + +static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + + if (conf_is_ht40(conf)) + return ath9k_hw_mac_usec(ah, clks) / 2; + else + return ath9k_hw_mac_usec(ah, clks); +} + +static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + + if (!ah->curchan) /* should really check for CCK instead */ + return usecs *ATH9K_CLOCK_RATE_CCK; + if (conf->channel->band == IEEE80211_BAND_2GHZ) + return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; + return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM; +} + +static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) +{ + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; + + if (conf_is_ht40(conf)) + return ath9k_hw_mac_clks(ah, usecs) * 2; + else + return ath9k_hw_mac_clks(ah, usecs); +} + +bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) +{ + int i; + + BUG_ON(timeout < AH_TIME_QUANTUM); + + for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) { + if ((REG_READ(ah, reg) & mask) == val) + return true; + + udelay(AH_TIME_QUANTUM); + } + + DPRINTF(ah->ah_sc, ATH_DBG_ANY, + "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", + timeout, reg, REG_READ(ah, reg), mask, val); + + return false; +} + +u32 ath9k_hw_reverse_bits(u32 val, u32 n) +{ + u32 retval; + int i; + + for (i = 0, retval = 0; i < n; i++) { + retval = (retval << 1) | (val & 1); + val >>= 1; + } + return retval; +} + +bool ath9k_get_channel_edges(struct ath_hw *ah, + u16 flags, u16 *low, + u16 *high) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + + if (flags & CHANNEL_5GHZ) { + *low = pCap->low_5ghz_chan; + *high = pCap->high_5ghz_chan; + return true; + } + if ((flags & CHANNEL_2GHZ)) { + *low = pCap->low_2ghz_chan; + *high = pCap->high_2ghz_chan; + return true; + } + return false; +} + +u16 ath9k_hw_computetxtime(struct ath_hw *ah, + struct ath_rate_table *rates, + u32 frameLen, u16 rateix, + bool shortPreamble) +{ + u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; + u32 kbps; + + kbps = rates->info[rateix].ratekbps; + + if (kbps == 0) + return 0; + + switch (rates->info[rateix].phy) { + case WLAN_RC_PHY_CCK: + phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; + if (shortPreamble && rates->info[rateix].short_preamble) + phyTime >>= 1; + numBits = frameLen << 3; + txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); + break; + case WLAN_RC_PHY_OFDM: + if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME_QUARTER + + OFDM_PREAMBLE_TIME_QUARTER + + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); + } else if (ah->curchan && + IS_CHAN_HALF_RATE(ah->curchan)) { + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME_HALF + + OFDM_PREAMBLE_TIME_HALF + + (numSymbols * OFDM_SYMBOL_TIME_HALF); + } else { + bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; + numBits = OFDM_PLCP_BITS + (frameLen << 3); + numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); + txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME + + (numSymbols * OFDM_SYMBOL_TIME); + } + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Unknown phy %u (rate ix %u)\n", + rates->info[rateix].phy, rateix); + txTime = 0; + break; + } + + return txTime; +} + +void ath9k_hw_get_channel_centers(struct ath_hw *ah, + struct ath9k_channel *chan, + struct chan_centers *centers) +{ + int8_t extoff; + + if (!IS_CHAN_HT40(chan)) { + centers->ctl_center = centers->ext_center = + centers->synth_center = chan->channel; + return; + } + + if ((chan->chanmode == CHANNEL_A_HT40PLUS) || + (chan->chanmode == CHANNEL_G_HT40PLUS)) { + centers->synth_center = + chan->channel + HT40_CHANNEL_CENTER_SHIFT; + extoff = 1; + } else { + centers->synth_center = + chan->channel - HT40_CHANNEL_CENTER_SHIFT; + extoff = -1; + } + + centers->ctl_center = + centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); + centers->ext_center = + centers->synth_center + (extoff * + ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ? + HT40_CHANNEL_CENTER_SHIFT : 15)); +} + +/******************/ +/* Chip Revisions */ +/******************/ + +static void ath9k_hw_read_revisions(struct ath_hw *ah) +{ + u32 val; + + val = REG_READ(ah, AR_SREV) & AR_SREV_ID; + + if (val == 0xFF) { + val = REG_READ(ah, AR_SREV); + ah->hw_version.macVersion = + (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; + ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); + ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; + } else { + if (!AR_SREV_9100(ah)) + ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); + + ah->hw_version.macRev = val & AR_SREV_REVISION; + + if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) + ah->is_pciexpress = true; + } +} + +static int ath9k_hw_get_radiorev(struct ath_hw *ah) +{ + u32 val; + int i; + + REG_WRITE(ah, AR_PHY(0x36), 0x00007058); + + for (i = 0; i < 8; i++) + REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; + val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + + return ath9k_hw_reverse_bits(val, 8); +} + +/************************************/ +/* HW Attach, Detach, Init Routines */ +/************************************/ + +static void ath9k_hw_disablepcie(struct ath_hw *ah) +{ + if (AR_SREV_9100(ah)) + return; + + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); + REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); + REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); + REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); + + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); +} + +static bool ath9k_hw_chip_test(struct ath_hw *ah) +{ + u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; + u32 regHold[2]; + u32 patternData[4] = { 0x55555555, + 0xaaaaaaaa, + 0x66666666, + 0x99999999 }; + int i, j; + + for (i = 0; i < 2; i++) { + u32 addr = regAddr[i]; + u32 wrData, rdData; + + regHold[i] = REG_READ(ah, addr); + for (j = 0; j < 0x100; j++) { + wrData = (j << 16) | j; + REG_WRITE(ah, addr, wrData); + rdData = REG_READ(ah, addr); + if (rdData != wrData) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "address test failed " + "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + addr, wrData, rdData); + return false; + } + } + for (j = 0; j < 4; j++) { + wrData = patternData[j]; + REG_WRITE(ah, addr, wrData); + rdData = REG_READ(ah, addr); + if (wrData != rdData) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "address test failed " + "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", + addr, wrData, rdData); + return false; + } + } + REG_WRITE(ah, regAddr[i], regHold[i]); + } + udelay(100); + + return true; +} + +static const char *ath9k_hw_devname(u16 devid) +{ + switch (devid) { + case AR5416_DEVID_PCI: + return "Atheros 5416"; + case AR5416_DEVID_PCIE: + return "Atheros 5418"; + case AR9160_DEVID_PCI: + return "Atheros 9160"; + case AR5416_AR9100_DEVID: + return "Atheros 9100"; + case AR9280_DEVID_PCI: + case AR9280_DEVID_PCIE: + return "Atheros 9280"; + case AR9285_DEVID_PCIE: + return "Atheros 9285"; + } + + return NULL; +} + +static void ath9k_hw_set_defaults(struct ath_hw *ah) +{ + int i; + + ah->config.dma_beacon_response_time = 2; + ah->config.sw_beacon_response_time = 10; + ah->config.additional_swba_backoff = 0; + ah->config.ack_6mb = 0x0; + ah->config.cwm_ignore_extcca = 0; + ah->config.pcie_powersave_enable = 0; + ah->config.pcie_clock_req = 0; + ah->config.pcie_waen = 0; + ah->config.analog_shiftreg = 1; + ah->config.ht_enable = 1; + ah->config.ofdm_trig_low = 200; + ah->config.ofdm_trig_high = 500; + ah->config.cck_trig_high = 200; + ah->config.cck_trig_low = 100; + ah->config.enable_ani = 1; + ah->config.diversity_control = 0; + ah->config.antenna_switch_swap = 0; + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + ah->config.spurchans[i][0] = AR_NO_SPUR; + ah->config.spurchans[i][1] = AR_NO_SPUR; + } + + ah->config.intr_mitigation = true; + + /* + * We need this for PCI devices only (Cardbus, PCI, miniPCI) + * _and_ if on non-uniprocessor systems (Multiprocessor/HT). + * This means we use it for all AR5416 devices, and the few + * minor PCI AR9280 devices out there. + * + * Serialization is required because these devices do not handle + * well the case of two concurrent reads/writes due to the latency + * involved. During one read/write another read/write can be issued + * on another CPU while the previous read/write may still be working + * on our hardware, if we hit this case the hardware poops in a loop. + * We prevent this by serializing reads and writes. + * + * This issue is not present on PCI-Express devices or pre-AR5416 + * devices (legacy, 802.11abg). + */ + if (num_possible_cpus() > 1) + ah->config.serialize_regmode = SER_REG_MODE_AUTO; +} + +static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc, + int *status) +{ + struct ath_hw *ah; + + ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); + if (ah == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, + "Cannot allocate memory for state block\n"); + *status = -ENOMEM; + return NULL; + } + + ah->ah_sc = sc; + ah->hw_version.magic = AR5416_MAGIC; + ah->regulatory.country_code = CTRY_DEFAULT; + ah->hw_version.devid = devid; + ah->hw_version.subvendorid = 0; + + ah->ah_flags = 0; + if ((devid == AR5416_AR9100_DEVID)) + ah->hw_version.macVersion = AR_SREV_VERSION_9100; + if (!AR_SREV_9100(ah)) + ah->ah_flags = AH_USE_EEPROM; + + ah->regulatory.power_limit = MAX_RATE_POWER; + ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; + ah->atim_window = 0; + ah->diversity_control = ah->config.diversity_control; + ah->antenna_switch_swap = + ah->config.antenna_switch_swap; + ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; + ah->beacon_interval = 100; + ah->enable_32kHz_clock = DONT_USE_32KHZ; + ah->slottime = (u32) -1; + ah->acktimeout = (u32) -1; + ah->ctstimeout = (u32) -1; + ah->globaltxtimeout = (u32) -1; + + ah->gbeacon_rate = 0; + + return ah; +} + +static int ath9k_hw_rfattach(struct ath_hw *ah) +{ + bool rfStatus = false; + int ecode = 0; + + rfStatus = ath9k_hw_init_rf(ah, &ecode); + if (!rfStatus) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "RF setup failed, status: %u\n", ecode); + return ecode; + } + + return 0; +} + +static int ath9k_hw_rf_claim(struct ath_hw *ah) +{ + u32 val; + + REG_WRITE(ah, AR_PHY(0), 0x00000007); + + val = ath9k_hw_get_radiorev(ah); + switch (val & AR_RADIO_SREV_MAJOR) { + case 0: + val = AR_RAD5133_SREV_MAJOR; + break; + case AR_RAD5133_SREV_MAJOR: + case AR_RAD5122_SREV_MAJOR: + case AR_RAD2133_SREV_MAJOR: + case AR_RAD2122_SREV_MAJOR: + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Radio Chip Rev 0x%02X not supported\n", + val & AR_RADIO_SREV_MAJOR); + return -EOPNOTSUPP; + } + + ah->hw_version.analog5GhzRev = val; + + return 0; +} + +static int ath9k_hw_init_macaddr(struct ath_hw *ah) +{ + u32 sum; + int i; + u16 eeval; + + sum = 0; + for (i = 0; i < 3; i++) { + eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); + sum += eeval; + ah->macaddr[2 * i] = eeval >> 8; + ah->macaddr[2 * i + 1] = eeval & 0xff; + } + if (sum == 0 || sum == 0xffff * 3) + return -EADDRNOTAVAIL; + + return 0; +} + +static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah) +{ + u32 rxgain_type; + + if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) { + rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); + + if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_backoff_13db_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); + else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_backoff_23db_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); + else + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_original_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9280Modes_original_rxgain_9280_2, + ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); + } +} + +static void ath9k_hw_init_txgain_ini(struct ath_hw *ah) +{ + u32 txgain_type; + + if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) { + txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + + if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_high_power_tx_gain_9280_2, + ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); + else + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_original_tx_gain_9280_2, + ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9280Modes_original_tx_gain_9280_2, + ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); + } +} + +static int ath9k_hw_post_attach(struct ath_hw *ah) +{ + int ecode; + + if (!ath9k_hw_chip_test(ah)) + return -ENODEV; + + ecode = ath9k_hw_rf_claim(ah); + if (ecode != 0) + return ecode; + + ecode = ath9k_hw_eeprom_attach(ah); + if (ecode != 0) + return ecode; + + DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", + ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); + + ecode = ath9k_hw_rfattach(ah); + if (ecode != 0) + return ecode; + + if (!AR_SREV_9100(ah)) { + ath9k_hw_ani_setup(ah); + ath9k_hw_ani_attach(ah); + } + + return 0; +} + +static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, + int *status) +{ + struct ath_hw *ah; + int ecode; + u32 i, j; + + ah = ath9k_hw_newstate(devid, sc, status); + if (ah == NULL) + return NULL; + + ath9k_hw_set_defaults(ah); + + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { + DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); + ecode = -EIO; + goto bad; + } + + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { + DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); + ecode = -EIO; + goto bad; + } + + if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { + if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || + (AR_SREV_9280(ah) && !ah->is_pciexpress)) { + ah->config.serialize_regmode = + SER_REG_MODE_ON; + } else { + ah->config.serialize_regmode = + SER_REG_MODE_OFF; + } + } + + DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n", + ah->config.serialize_regmode); + + if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) && + (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && + (ah->hw_version.macVersion != AR_SREV_VERSION_9160) && + (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) { + DPRINTF(sc, ATH_DBG_FATAL, + "Mac Chip Rev 0x%02x.%x is not supported by " + "this driver\n", ah->hw_version.macVersion, + ah->hw_version.macRev); + ecode = -EOPNOTSUPP; + goto bad; + } + + if (AR_SREV_9100(ah)) { + ah->iq_caldata.calData = &iq_cal_multi_sample; + ah->supp_cals = IQ_MISMATCH_CAL; + ah->is_pciexpress = false; + } + ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); + + if (AR_SREV_9160_10_OR_LATER(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) { + ah->iq_caldata.calData = &iq_cal_single_sample; + ah->adcgain_caldata.calData = + &adc_gain_cal_single_sample; + ah->adcdc_caldata.calData = + &adc_dc_cal_single_sample; + ah->adcdc_calinitdata.calData = + &adc_init_dc_cal; + } else { + ah->iq_caldata.calData = &iq_cal_multi_sample; + ah->adcgain_caldata.calData = + &adc_gain_cal_multi_sample; + ah->adcdc_caldata.calData = + &adc_dc_cal_multi_sample; + ah->adcdc_calinitdata.calData = + &adc_init_dc_cal; + } + ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; + } + + ah->ani_function = ATH9K_ANI_ALL; + if (AR_SREV_9280_10_OR_LATER(ah)) + ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; + + if (AR_SREV_9285_12_OR_LATER(ah)) { + + INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, + ARRAY_SIZE(ar9285Modes_9285_1_2), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, + ARRAY_SIZE(ar9285Common_9285_1_2), 2); + + if (ah->config.pcie_clock_req) { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_off_L1_9285_1_2, + ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); + } else { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_always_on_L1_9285_1_2, + ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), + 2); + } + } else if (AR_SREV_9285_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, + ARRAY_SIZE(ar9285Modes_9285), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, + ARRAY_SIZE(ar9285Common_9285), 2); + + if (ah->config.pcie_clock_req) { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_off_L1_9285, + ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); + } else { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9285PciePhy_clkreq_always_on_L1_9285, + ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); + } + } else if (AR_SREV_9280_20_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, + ARRAY_SIZE(ar9280Modes_9280_2), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, + ARRAY_SIZE(ar9280Common_9280_2), 2); + + if (ah->config.pcie_clock_req) { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9280PciePhy_clkreq_off_L1_9280, + ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2); + } else { + INIT_INI_ARRAY(&ah->iniPcieSerdes, + ar9280PciePhy_clkreq_always_on_L1_9280, + ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); + } + INIT_INI_ARRAY(&ah->iniModesAdditional, + ar9280Modes_fast_clock_9280_2, + ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); + } else if (AR_SREV_9280_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, + ARRAY_SIZE(ar9280Modes_9280), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, + ARRAY_SIZE(ar9280Common_9280), 2); + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, + ARRAY_SIZE(ar5416Modes_9160), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, + ARRAY_SIZE(ar5416Common_9160), 2); + INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, + ARRAY_SIZE(ar5416Bank0_9160), 2); + INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, + ARRAY_SIZE(ar5416BB_RfGain_9160), 3); + INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, + ARRAY_SIZE(ar5416Bank1_9160), 2); + INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, + ARRAY_SIZE(ar5416Bank2_9160), 2); + INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, + ARRAY_SIZE(ar5416Bank3_9160), 3); + INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, + ARRAY_SIZE(ar5416Bank6_9160), 3); + INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, + ARRAY_SIZE(ar5416Bank6TPC_9160), 3); + INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, + ARRAY_SIZE(ar5416Bank7_9160), 2); + if (AR_SREV_9160_11(ah)) { + INIT_INI_ARRAY(&ah->iniAddac, + ar5416Addac_91601_1, + ARRAY_SIZE(ar5416Addac_91601_1), 2); + } else { + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, + ARRAY_SIZE(ar5416Addac_9160), 2); + } + } else if (AR_SREV_9100_OR_LATER(ah)) { + INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, + ARRAY_SIZE(ar5416Modes_9100), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, + ARRAY_SIZE(ar5416Common_9100), 2); + INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, + ARRAY_SIZE(ar5416Bank0_9100), 2); + INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, + ARRAY_SIZE(ar5416BB_RfGain_9100), 3); + INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, + ARRAY_SIZE(ar5416Bank1_9100), 2); + INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, + ARRAY_SIZE(ar5416Bank2_9100), 2); + INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, + ARRAY_SIZE(ar5416Bank3_9100), 3); + INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, + ARRAY_SIZE(ar5416Bank6_9100), 3); + INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, + ARRAY_SIZE(ar5416Bank6TPC_9100), 3); + INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, + ARRAY_SIZE(ar5416Bank7_9100), 2); + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, + ARRAY_SIZE(ar5416Addac_9100), 2); + } else { + INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, + ARRAY_SIZE(ar5416Modes), 6); + INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, + ARRAY_SIZE(ar5416Common), 2); + INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, + ARRAY_SIZE(ar5416Bank0), 2); + INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, + ARRAY_SIZE(ar5416BB_RfGain), 3); + INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, + ARRAY_SIZE(ar5416Bank1), 2); + INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, + ARRAY_SIZE(ar5416Bank2), 2); + INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, + ARRAY_SIZE(ar5416Bank3), 3); + INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, + ARRAY_SIZE(ar5416Bank6), 3); + INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, + ARRAY_SIZE(ar5416Bank6TPC), 3); + INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, + ARRAY_SIZE(ar5416Bank7), 2); + INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, + ARRAY_SIZE(ar5416Addac), 2); + } + + if (ah->is_pciexpress) + ath9k_hw_configpcipowersave(ah, 0); + else + ath9k_hw_disablepcie(ah); + + ecode = ath9k_hw_post_attach(ah); + if (ecode != 0) + goto bad; + + if (AR_SREV_9285_12_OR_LATER(ah)) { + u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + + /* txgain table */ + if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_high_power_tx_gain_9285_1_2, + ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); + } else { + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9285Modes_original_tx_gain_9285_1_2, + ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); + } + + } + + /* rxgain table */ + if (AR_SREV_9280_20(ah)) + ath9k_hw_init_rxgain_ini(ah); + + /* txgain table */ + if (AR_SREV_9280_20(ah)) + ath9k_hw_init_txgain_ini(ah); + + ath9k_hw_fill_cap_info(ah); + + if ((ah->hw_version.devid == AR9280_DEVID_PCI) && + test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { + + /* EEPROM Fixup */ + for (i = 0; i < ah->iniModes.ia_rows; i++) { + u32 reg = INI_RA(&ah->iniModes, i, 0); + + for (j = 1; j < ah->iniModes.ia_columns; j++) { + u32 val = INI_RA(&ah->iniModes, i, j); + + INI_RA(&ah->iniModes, i, j) = + ath9k_hw_ini_fixup(ah, + &ah->eeprom.def, + reg, val); + } + } + } + + ecode = ath9k_hw_init_macaddr(ah); + if (ecode != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to initialize MAC address\n"); + goto bad; + } + + if (AR_SREV_9285(ah)) + ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); + else + ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); + + ath9k_init_nfcal_hist_buffer(ah); + + return ah; +bad: + if (ah) + ath9k_hw_detach(ah); + if (status) + *status = ecode; + + return NULL; +} + +static void ath9k_hw_init_bb(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 synthDelay; + + synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_B(chan)) + synthDelay = (4 * synthDelay) / 22; + else + synthDelay /= 10; + + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + + udelay(synthDelay + BASE_ACTIVATE_DELAY); +} + +static void ath9k_hw_init_qos(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); + REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); + + REG_WRITE(ah, AR_QOS_NO_ACK, + SM(2, AR_QOS_NO_ACK_TWO_BIT) | + SM(5, AR_QOS_NO_ACK_BIT_OFF) | + SM(0, AR_QOS_NO_ACK_BYTE_OFF)); + + REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); + REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); + REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); + REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); + REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); +} + +static void ath9k_hw_init_pll(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 pll; + + if (AR_SREV_9100(ah)) { + if (chan && IS_CHAN_5GHZ(chan)) + pll = 0x1450; + else + pll = 0x1458; + } else { + if (AR_SREV_9280_10_OR_LATER(ah)) { + pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) { + pll |= SM(0x28, AR_RTC_9160_PLL_DIV); + + + if (AR_SREV_9280_20(ah)) { + if (((chan->channel % 20) == 0) + || ((chan->channel % 10) == 0)) + pll = 0x2850; + else + pll = 0x142c; + } + } else { + pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); + } + + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + + pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) + pll |= SM(0x50, AR_RTC_9160_PLL_DIV); + else + pll |= SM(0x58, AR_RTC_9160_PLL_DIV); + } else { + pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; + + if (chan && IS_CHAN_HALF_RATE(chan)) + pll |= SM(0x1, AR_RTC_PLL_CLKSEL); + else if (chan && IS_CHAN_QUARTER_RATE(chan)) + pll |= SM(0x2, AR_RTC_PLL_CLKSEL); + + if (chan && IS_CHAN_5GHZ(chan)) + pll |= SM(0xa, AR_RTC_PLL_DIV); + else + pll |= SM(0xb, AR_RTC_PLL_DIV); + } + } + REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + + udelay(RTC_PLL_SETTLE_DELAY); + + REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); +} + +static void ath9k_hw_init_chain_masks(struct ath_hw *ah) +{ + int rx_chainmask, tx_chainmask; + + rx_chainmask = ah->rxchainmask; + tx_chainmask = ah->txchainmask; + + switch (rx_chainmask) { + case 0x5: + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + case 0x3: + if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) { + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); + break; + } + case 0x1: + case 0x2: + case 0x7: + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); + break; + default: + break; + } + + REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); + if (tx_chainmask == 0x5) { + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + } + if (AR_SREV_9100(ah)) + REG_WRITE(ah, AR_PHY_ANALOG_SWAP, + REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); +} + +static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, + enum nl80211_iftype opmode) +{ + ah->mask_reg = AR_IMR_TXERR | + AR_IMR_TXURN | + AR_IMR_RXERR | + AR_IMR_RXORN | + AR_IMR_BCNMISC; + + if (ah->config.intr_mitigation) + ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; + else + ah->mask_reg |= AR_IMR_RXOK; + + ah->mask_reg |= AR_IMR_TXOK; + + if (opmode == NL80211_IFTYPE_AP) + ah->mask_reg |= AR_IMR_MIB; + + REG_WRITE(ah, AR_IMR, ah->mask_reg); + REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); + + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); + } +} + +static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) +{ + if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us); + ah->acktimeout = (u32) -1; + return false; + } else { + REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); + ah->acktimeout = us; + return true; + } +} + +static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) +{ + if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us); + ah->ctstimeout = (u32) -1; + return false; + } else { + REG_RMW_FIELD(ah, AR_TIME_OUT, + AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); + ah->ctstimeout = us; + return true; + } +} + +static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) +{ + if (tu > 0xFFFF) { + DPRINTF(ah->ah_sc, ATH_DBG_XMIT, + "bad global tx timeout %u\n", tu); + ah->globaltxtimeout = (u32) -1; + return false; + } else { + REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); + ah->globaltxtimeout = tu; + return true; + } +} + +static void ath9k_hw_init_user_settings(struct ath_hw *ah) +{ + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n", + ah->misc_mode); + + if (ah->misc_mode != 0) + REG_WRITE(ah, AR_PCU_MISC, + REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); + if (ah->slottime != (u32) -1) + ath9k_hw_setslottime(ah, ah->slottime); + if (ah->acktimeout != (u32) -1) + ath9k_hw_set_ack_timeout(ah, ah->acktimeout); + if (ah->ctstimeout != (u32) -1) + ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); + if (ah->globaltxtimeout != (u32) -1) + ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); +} + +const char *ath9k_hw_probe(u16 vendorid, u16 devid) +{ + return vendorid == ATHEROS_VENDOR_ID ? + ath9k_hw_devname(devid) : NULL; +} + +void ath9k_hw_detach(struct ath_hw *ah) +{ + if (!AR_SREV_9100(ah)) + ath9k_hw_ani_detach(ah); + + ath9k_hw_rfdetach(ah); + ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + kfree(ah); +} + +struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error) +{ + struct ath_hw *ah = NULL; + + switch (devid) { + case AR5416_DEVID_PCI: + case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: + case AR9160_DEVID_PCI: + case AR9280_DEVID_PCI: + case AR9280_DEVID_PCIE: + case AR9285_DEVID_PCIE: + ah = ath9k_hw_do_attach(devid, sc, error); + break; + default: + *error = -ENXIO; + break; + } + + return ah; +} + +/*******/ +/* INI */ +/*******/ + +static void ath9k_hw_override_ini(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + /* + * Set the RX_ABORT and RX_DIS and clear if off only after + * RXE is set for MAC. This prevents frames with corrupted + * descriptor status. + */ + REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + + + if (!AR_SREV_5416_20_OR_LATER(ah) || + AR_SREV_9280_10_OR_LATER(ah)) + return; + + REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); +} + +static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, + struct ar5416_eeprom_def *pEepData, + u32 reg, u32 value) +{ + struct base_eep_header *pBase = &(pEepData->baseEepHeader); + + switch (ah->hw_version.devid) { + case AR9280_DEVID_PCI: + if (reg == 0x7894) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "ini VAL: %x EEPROM: %x\n", value, + (pBase->version & 0xff)); + + if ((pBase->version & 0xff) > 0x0a) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "PWDCLKIND: %d\n", + pBase->pwdclkind); + value &= ~AR_AN_TOP2_PWDCLKIND; + value |= AR_AN_TOP2_PWDCLKIND & + (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); + } else { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "PWDCLKIND Earlier Rev\n"); + } + + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "final ini VAL: %x\n", value); + } + break; + } + + return value; +} + +static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, + struct ar5416_eeprom_def *pEepData, + u32 reg, u32 value) +{ + if (ah->eep_map == EEP_MAP_4KBITS) + return value; + else + return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); +} + +static void ath9k_olc_init(struct ath_hw *ah) +{ + u32 i; + + for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) + ah->originalGain[i] = + MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), + AR_PHY_TX_GAIN); + ah->PDADCdelta = 0; +} + +static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, + struct ath9k_channel *chan) +{ + u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); + + if (IS_CHAN_B(chan)) + ctl |= CTL_11B; + else if (IS_CHAN_G(chan)) + ctl |= CTL_11G; + else + ctl |= CTL_11A; + + return ctl; +} + +static int ath9k_hw_process_ini(struct ath_hw *ah, + struct ath9k_channel *chan, + enum ath9k_ht_macmode macmode) +{ + int i, regWrites = 0; + struct ieee80211_channel *channel = chan->chan; + u32 modesIndex, freqIndex; + int status; + + switch (chan->chanmode) { + case CHANNEL_A: + case CHANNEL_A_HT20: + modesIndex = 1; + freqIndex = 1; + break; + case CHANNEL_A_HT40PLUS: + case CHANNEL_A_HT40MINUS: + modesIndex = 2; + freqIndex = 1; + break; + case CHANNEL_G: + case CHANNEL_G_HT20: + case CHANNEL_B: + modesIndex = 4; + freqIndex = 2; + break; + case CHANNEL_G_HT40PLUS: + case CHANNEL_G_HT40MINUS: + modesIndex = 3; + freqIndex = 2; + break; + + default: + return -EINVAL; + } + + REG_WRITE(ah, AR_PHY(0), 0x00000007); + REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); + ah->eep_ops->set_addac(ah, chan); + + if (AR_SREV_5416_22_OR_LATER(ah)) { + REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); + } else { + struct ar5416IniArray temp; + u32 addacSize = + sizeof(u32) * ah->iniAddac.ia_rows * + ah->iniAddac.ia_columns; + + memcpy(ah->addac5416_21, + ah->iniAddac.ia_array, addacSize); + + (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; + + temp.ia_array = ah->addac5416_21; + temp.ia_columns = ah->iniAddac.ia_columns; + temp.ia_rows = ah->iniAddac.ia_rows; + REG_WRITE_ARRAY(&temp, 1, regWrites); + } + + REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + + for (i = 0; i < ah->iniModes.ia_rows; i++) { + u32 reg = INI_RA(&ah->iniModes, i, 0); + u32 val = INI_RA(&ah->iniModes, i, modesIndex); + + REG_WRITE(ah, reg, val); + + if (reg >= 0x7800 && reg < 0x78a0 + && ah->config.analog_shiftreg) { + udelay(100); + } + + DO_DELAY(regWrites); + } + + if (AR_SREV_9280(ah)) + REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); + + if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) && + AR_SREV_9285_12_OR_LATER(ah))) + REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); + + for (i = 0; i < ah->iniCommon.ia_rows; i++) { + u32 reg = INI_RA(&ah->iniCommon, i, 0); + u32 val = INI_RA(&ah->iniCommon, i, 1); + + REG_WRITE(ah, reg, val); + + if (reg >= 0x7800 && reg < 0x78a0 + && ah->config.analog_shiftreg) { + udelay(100); + } + + DO_DELAY(regWrites); + } + + ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); + + if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { + REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, + regWrites); + } + + ath9k_hw_override_ini(ah, chan); + ath9k_hw_set_regs(ah, chan, macmode); + ath9k_hw_init_chain_masks(ah); + + if (OLC_FOR_AR9280_20_LATER) + ath9k_olc_init(ah); + + status = ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(&ah->regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) ah->regulatory.power_limit)); + if (status != 0) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Error initializing transmit power\n"); + return -EIO; + } + + if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "ar5416SetRfRegs failed\n"); + return -EIO; + } + + return 0; +} + +/****************************************/ +/* Reset and Channel Switching Routines */ +/****************************************/ + +static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) +{ + u32 rfMode = 0; + + if (chan == NULL) + return; + + rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) + ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + + if (!AR_SREV_9280_10_OR_LATER(ah)) + rfMode |= (IS_CHAN_5GHZ(chan)) ? + AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; + + if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) + rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); + + REG_WRITE(ah, AR_PHY_MODE, rfMode); +} + +static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +} + +static inline void ath9k_hw_set_dma(struct ath_hw *ah) +{ + u32 regval; + + regval = REG_READ(ah, AR_AHB_MODE); + REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); + + regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; + REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); + + REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); + + regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; + REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); + + REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); + + if (AR_SREV_9285(ah)) { + REG_WRITE(ah, AR_PCU_TXBUF_CTRL, + AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); + } else { + REG_WRITE(ah, AR_PCU_TXBUF_CTRL, + AR_PCU_TXBUF_CTRL_USABLE_SIZE); + } +} + +static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) +{ + u32 val; + + val = REG_READ(ah, AR_STA_ID1); + val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); + switch (opmode) { + case NL80211_IFTYPE_AP: + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP + | AR_STA_ID1_KSRCH_MODE); + REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC + | AR_STA_ID1_KSRCH_MODE); + REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); + break; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_MONITOR: + REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + break; + } +} + +static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, + u32 coef_scaled, + u32 *coef_mantissa, + u32 *coef_exponent) +{ + u32 coef_exp, coef_man; + + for (coef_exp = 31; coef_exp > 0; coef_exp--) + if ((coef_scaled >> coef_exp) & 0x1) + break; + + coef_exp = 14 - (coef_exp - COEF_SCALE_S); + + coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); + + *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); + *coef_exponent = coef_exp - 16; +} + +static void ath9k_hw_set_delta_slope(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u32 coef_scaled, ds_coef_exp, ds_coef_man; + u32 clockMhzScaled = 0x64000000; + struct chan_centers centers; + + if (IS_CHAN_HALF_RATE(chan)) + clockMhzScaled = clockMhzScaled >> 1; + else if (IS_CHAN_QUARTER_RATE(chan)) + clockMhzScaled = clockMhzScaled >> 2; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + coef_scaled = clockMhzScaled / centers.synth_center; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_TIMING3, + AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + + coef_scaled = (9 * coef_scaled) / 10; + + ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, + &ds_coef_exp); + + REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_MAN, ds_coef_man); + REG_RMW_FIELD(ah, AR_PHY_HALFGI, + AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); +} + +static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) +{ + u32 rst_flags; + u32 tmpReg; + + if (AR_SREV_9100(ah)) { + u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); + val &= ~AR_RTC_DERIVED_CLK_PERIOD; + val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); + REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); + (void)REG_READ(ah, AR_RTC_DERIVED_CLK); + } + + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | + AR_RTC_FORCE_WAKE_ON_INT); + + if (AR_SREV_9100(ah)) { + rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | + AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; + } else { + tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE); + if (tmpReg & + (AR_INTR_SYNC_LOCAL_TIMEOUT | + AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); + } else { + REG_WRITE(ah, AR_RC, AR_RC_AHB); + } + + rst_flags = AR_RTC_RC_MAC_WARM; + if (type == ATH9K_RESET_COLD) + rst_flags |= AR_RTC_RC_MAC_COLD; + } + + REG_WRITE(ah, AR_RTC_RC, rst_flags); + udelay(50); + + REG_WRITE(ah, AR_RTC_RC, 0); + if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, + "RTC stuck in MAC reset\n"); + return false; + } + + if (!AR_SREV_9100(ah)) + REG_WRITE(ah, AR_RC, 0); + + ath9k_hw_init_pll(ah, NULL); + + if (AR_SREV_9100(ah)) + udelay(50); + + return true; +} + +static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | + AR_RTC_FORCE_WAKE_ON_INT); + + REG_WRITE(ah, AR_RTC_RESET, 0); + udelay(2); + REG_WRITE(ah, AR_RTC_RESET, 1); + + if (!ath9k_hw_wait(ah, + AR_RTC_STATUS, + AR_RTC_STATUS_M, + AR_RTC_STATUS_ON, + AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); + return false; + } + + ath9k_hw_read_revisions(ah); + + return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); +} + +static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) +{ + REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + + switch (type) { + case ATH9K_RESET_POWER_ON: + return ath9k_hw_set_reset_power_on(ah); + break; + case ATH9K_RESET_WARM: + case ATH9K_RESET_COLD: + return ath9k_hw_set_reset(ah, type); + break; + default: + return false; + } +} + +static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, + enum ath9k_ht_macmode macmode) +{ + u32 phymode; + u32 enableDacFifo = 0; + + if (AR_SREV_9285_10_OR_LATER(ah)) + enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & + AR_PHY_FC_ENABLE_DAC_FIFO); + + phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 + | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; + + if (IS_CHAN_HT40(chan)) { + phymode |= AR_PHY_FC_DYN2040_EN; + + if ((chan->chanmode == CHANNEL_A_HT40PLUS) || + (chan->chanmode == CHANNEL_G_HT40PLUS)) + phymode |= AR_PHY_FC_DYN2040_PRI_CH; + + if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25) + phymode |= AR_PHY_FC_DYN2040_EXT_CH; + } + REG_WRITE(ah, AR_PHY_TURBO, phymode); + + ath9k_hw_set11nmac2040(ah, macmode); + + REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); + REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); +} + +static bool ath9k_hw_chip_reset(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + if (OLC_FOR_AR9280_20_LATER) { + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) + return false; + } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) + return false; + + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) + return false; + + ah->chip_fullsleep = false; + ath9k_hw_init_pll(ah, chan); + ath9k_hw_set_rfmode(ah, chan); + + return true; +} + +static bool ath9k_hw_channel_change(struct ath_hw *ah, + struct ath9k_channel *chan, + enum ath9k_ht_macmode macmode) +{ + struct ieee80211_channel *channel = chan->chan; + u32 synthDelay, qnum; + + for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { + if (ath9k_hw_numtxpending(ah, qnum)) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + "Transmit frames pending on queue %d\n", qnum); + return false; + } + } + + REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); + if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, + AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Could not kill baseband RX\n"); + return false; + } + + ath9k_hw_set_regs(ah, chan, macmode); + + if (AR_SREV_9280_10_OR_LATER(ah)) { + if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Failed to set channel\n"); + return false; + } + } else { + if (!(ath9k_hw_set_channel(ah, chan))) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Failed to set channel\n"); + return false; + } + } + + if (ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(&ah->regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) ah->regulatory.power_limit)) != 0) { + DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, + "Error initializing transmit power\n"); + return false; + } + + synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; + if (IS_CHAN_B(chan)) + synthDelay = (4 * synthDelay) / 22; + else + synthDelay /= 10; + + udelay(synthDelay + BASE_ACTIVATE_DELAY); + + REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); + + if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) + ath9k_hw_set_delta_slope(ah, chan); + + if (AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_9280_spur_mitigate(ah, chan); + else + ath9k_hw_spur_mitigate(ah, chan); + + if (!chan->oneTimeCalsDone) + chan->oneTimeCalsDone = true; + + return true; +} + +static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int freq; + int bin, cur_bin; + int bb_spur_off, spur_subchannel_sd; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, newVal; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + struct chan_centers centers; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + ah->config.spurmode = SPUR_ENABLE_EEPROM; + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + + if (is2GHz) + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; + else + cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - freq; + + if (IS_CHAN_HT40(chan)) { + if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { + bb_spur = cur_bb_spur; + break; + } + } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && + (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + return; + } else { + REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, + AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); + } + + bin = bb_spur * 320; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + + newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); + + newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + + if (IS_CHAN_HT40(chan)) { + if (bb_spur < 0) { + spur_subchannel_sd = 1; + bb_spur_off = bb_spur + 10; + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur - 10; + } + } else { + spur_subchannel_sd = 0; + bb_spur_off = bb_spur; + } + + if (IS_CHAN_HT40(chan)) + spur_delta_phase = + ((bb_spur * 262144) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + else + spur_delta_phase = + ((bb_spur * 524288) / + 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; + spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + + newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, newVal); + + newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; + REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int bb_spur = AR_NO_SPUR; + int bin, cur_bin; + int spur_freq_sd; + int spur_delta_phase; + int denominator; + int upper, lower, cur_vit_mask; + int tmp, new; + int i; + int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, + AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 + }; + int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, + AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 + }; + int inc[4] = { 0, 100, 0, 0 }; + + int8_t mask_m[123]; + int8_t mask_p[123]; + int8_t mask_amt; + int tmp_mask; + int cur_bb_spur; + bool is2GHz = IS_CHAN_2GHZ(chan); + + memset(&mask_m, 0, sizeof(int8_t) * 123); + memset(&mask_p, 0, sizeof(int8_t) * 123); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { + cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + if (AR_NO_SPUR == cur_bb_spur) + break; + cur_bb_spur = cur_bb_spur - (chan->channel * 10); + if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { + bb_spur = cur_bb_spur; + break; + } + } + + if (AR_NO_SPUR == bb_spur) + return; + + bin = bb_spur * 32; + + tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | + AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | + AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | + AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + + REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); + + new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | + AR_PHY_SPUR_REG_ENABLE_MASK_PPM | + AR_PHY_SPUR_REG_MASK_RATE_SELECT | + AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | + SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); + REG_WRITE(ah, AR_PHY_SPUR_REG, new); + + spur_delta_phase = ((bb_spur * 524288) / 100) & + AR_PHY_TIMING11_SPUR_DELTA_PHASE; + + denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; + spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + + new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | + SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | + SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); + REG_WRITE(ah, AR_PHY_TIMING11, new); + + cur_bin = -6000; + upper = bin + 100; + lower = bin - 100; + + for (i = 0; i < 4; i++) { + int pilot_mask = 0; + int chan_mask = 0; + int bp = 0; + for (bp = 0; bp < 30; bp++) { + if ((cur_bin > lower) && (cur_bin < upper)) { + pilot_mask = pilot_mask | 0x1 << bp; + chan_mask = chan_mask | 0x1 << bp; + } + cur_bin += 100; + } + cur_bin += inc[i]; + REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); + REG_WRITE(ah, chan_mask_reg[i], chan_mask); + } + + cur_vit_mask = 6100; + upper = bin + 120; + lower = bin - 120; + + for (i = 0; i < 123; i++) { + if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + + /* workaround for gcc bug #37014 */ + volatile int tmp_v = abs(cur_vit_mask - bin); + + if (tmp_v < 75) + mask_amt = 1; + else + mask_amt = 0; + if (cur_vit_mask < 0) + mask_m[abs(cur_vit_mask / 100)] = mask_amt; + else + mask_p[cur_vit_mask / 100] = mask_amt; + } + cur_vit_mask -= 100; + } + + tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) + | (mask_m[48] << 26) | (mask_m[49] << 24) + | (mask_m[50] << 22) | (mask_m[51] << 20) + | (mask_m[52] << 18) | (mask_m[53] << 16) + | (mask_m[54] << 14) | (mask_m[55] << 12) + | (mask_m[56] << 10) | (mask_m[57] << 8) + | (mask_m[58] << 6) | (mask_m[59] << 4) + | (mask_m[60] << 2) | (mask_m[61] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); + REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + + tmp_mask = (mask_m[31] << 28) + | (mask_m[32] << 26) | (mask_m[33] << 24) + | (mask_m[34] << 22) | (mask_m[35] << 20) + | (mask_m[36] << 18) | (mask_m[37] << 16) + | (mask_m[48] << 14) | (mask_m[39] << 12) + | (mask_m[40] << 10) | (mask_m[41] << 8) + | (mask_m[42] << 6) | (mask_m[43] << 4) + | (mask_m[44] << 2) | (mask_m[45] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + + tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) + | (mask_m[18] << 26) | (mask_m[18] << 24) + | (mask_m[20] << 22) | (mask_m[20] << 20) + | (mask_m[22] << 18) | (mask_m[22] << 16) + | (mask_m[24] << 14) | (mask_m[24] << 12) + | (mask_m[25] << 10) | (mask_m[26] << 8) + | (mask_m[27] << 6) | (mask_m[28] << 4) + | (mask_m[29] << 2) | (mask_m[30] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + + tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) + | (mask_m[2] << 26) | (mask_m[3] << 24) + | (mask_m[4] << 22) | (mask_m[5] << 20) + | (mask_m[6] << 18) | (mask_m[7] << 16) + | (mask_m[8] << 14) | (mask_m[9] << 12) + | (mask_m[10] << 10) | (mask_m[11] << 8) + | (mask_m[12] << 6) | (mask_m[13] << 4) + | (mask_m[14] << 2) | (mask_m[15] << 0); + REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + + tmp_mask = (mask_p[15] << 28) + | (mask_p[14] << 26) | (mask_p[13] << 24) + | (mask_p[12] << 22) | (mask_p[11] << 20) + | (mask_p[10] << 18) | (mask_p[9] << 16) + | (mask_p[8] << 14) | (mask_p[7] << 12) + | (mask_p[6] << 10) | (mask_p[5] << 8) + | (mask_p[4] << 6) | (mask_p[3] << 4) + | (mask_p[2] << 2) | (mask_p[1] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + + tmp_mask = (mask_p[30] << 28) + | (mask_p[29] << 26) | (mask_p[28] << 24) + | (mask_p[27] << 22) | (mask_p[26] << 20) + | (mask_p[25] << 18) | (mask_p[24] << 16) + | (mask_p[23] << 14) | (mask_p[22] << 12) + | (mask_p[21] << 10) | (mask_p[20] << 8) + | (mask_p[19] << 6) | (mask_p[18] << 4) + | (mask_p[17] << 2) | (mask_p[16] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + + tmp_mask = (mask_p[45] << 28) + | (mask_p[44] << 26) | (mask_p[43] << 24) + | (mask_p[42] << 22) | (mask_p[41] << 20) + | (mask_p[40] << 18) | (mask_p[39] << 16) + | (mask_p[38] << 14) | (mask_p[37] << 12) + | (mask_p[36] << 10) | (mask_p[35] << 8) + | (mask_p[34] << 6) | (mask_p[33] << 4) + | (mask_p[32] << 2) | (mask_p[31] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + + tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) + | (mask_p[59] << 26) | (mask_p[58] << 24) + | (mask_p[57] << 22) | (mask_p[56] << 20) + | (mask_p[55] << 18) | (mask_p[54] << 16) + | (mask_p[53] << 14) | (mask_p[52] << 12) + | (mask_p[51] << 10) | (mask_p[50] << 8) + | (mask_p[49] << 6) | (mask_p[48] << 4) + | (mask_p[47] << 2) | (mask_p[46] << 0); + REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); + REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + bool bChannelChange) +{ + u32 saveLedState; + struct ath_softc *sc = ah->ah_sc; + struct ath9k_channel *curchan = ah->curchan; + u32 saveDefAntenna; + u32 macStaId1; + int i, rx_chainmask, r; + + ah->extprotspacing = sc->ht_extprotspacing; + ah->txchainmask = sc->tx_chainmask; + ah->rxchainmask = sc->rx_chainmask; + + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) + return -EIO; + + if (curchan) + ath9k_hw_getnf(ah, curchan); + + if (bChannelChange && + (ah->chip_fullsleep != true) && + (ah->curchan != NULL) && + (chan->channel != ah->curchan->channel) && + ((chan->channelFlags & CHANNEL_ALL) == + (ah->curchan->channelFlags & CHANNEL_ALL)) && + (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && + !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) { + + if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { + ath9k_hw_loadnf(ah, ah->curchan); + ath9k_hw_start_nfcal(ah); + return 0; + } + } + + saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); + if (saveDefAntenna == 0) + saveDefAntenna = 1; + + macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; + + saveLedState = REG_READ(ah, AR_CFG_LED) & + (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | + AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); + + ath9k_hw_mark_phy_inactive(ah); + + if (!ath9k_hw_chip_reset(ah, chan)) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); + return -EINVAL; + } + + if (AR_SREV_9280_10_OR_LATER(ah)) + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); + + r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); + if (r) + return r; + + /* Setup MFP options for CCMP */ + if (AR_SREV_9280_20_OR_LATER(ah)) { + /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt + * frames when constructing CCMP AAD. */ + REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, + 0xc7ff); + ah->sw_mgmt_crypto = false; + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + /* Disable hardware crypto for management frames */ + REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); + REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); + ah->sw_mgmt_crypto = true; + } else + ah->sw_mgmt_crypto = true; + + if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) + ath9k_hw_set_delta_slope(ah, chan); + + if (AR_SREV_9280_10_OR_LATER(ah)) + ath9k_hw_9280_spur_mitigate(ah, chan); + else + ath9k_hw_spur_mitigate(ah, chan); + + ah->eep_ops->set_board_values(ah, chan); + + ath9k_hw_decrease_chain_power(ah, chan); + + REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr)); + REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4) + | macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | (ah->config. + ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) + | ah->sta_id1_defaults); + ath9k_hw_set_operating_mode(ah, ah->opmode); + + REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); + REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); + + REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + + REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); + REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | + ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); + + REG_WRITE(ah, AR_ISR, ~0); + + REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); + + if (AR_SREV_9280_10_OR_LATER(ah)) { + if (!(ath9k_hw_ar9280_set_channel(ah, chan))) + return -EIO; + } else { + if (!(ath9k_hw_set_channel(ah, chan))) + return -EIO; + } + + for (i = 0; i < AR_NUM_DCU; i++) + REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + ah->intr_txqs = 0; + for (i = 0; i < ah->caps.total_queues; i++) + ath9k_hw_resettxqueue(ah, i); + + ath9k_hw_init_interrupt_masks(ah, ah->opmode); + ath9k_hw_init_qos(ah); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + ath9k_enable_rfkill(ah); +#endif + ath9k_hw_init_user_settings(ah); + + REG_WRITE(ah, AR_STA_ID1, + REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); + + ath9k_hw_set_dma(ah); + + REG_WRITE(ah, AR_OBS, 8); + + if (ah->config.intr_mitigation) { + REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); + REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); + } + + ath9k_hw_init_bb(ah, chan); + + if (!ath9k_hw_init_cal(ah, chan)) + return -EIO;; + + rx_chainmask = ah->rxchainmask; + if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); + } + + REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); + + if (AR_SREV_9100(ah)) { + u32 mask; + mask = REG_READ(ah, AR_CFG); + if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, + "CFG Byte Swap Set 0x%x\n", mask); + } else { + mask = + INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; + REG_WRITE(ah, AR_CFG, mask); + DPRINTF(ah->ah_sc, ATH_DBG_RESET, + "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); + } + } else { +#ifdef __BIG_ENDIAN + REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); +#endif + } + + return 0; +} + +/************************/ +/* Key Cache Management */ +/************************/ + +bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) +{ + u32 keyType; + + if (entry >= ah->caps.keycache_size) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); + return false; + } + + keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); + + REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); + REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); + REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); + REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); + + if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { + u16 micentry = entry + 64; + + REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); + REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); + + } + + if (ah->curchan == NULL) + return true; + + return true; +} + +bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) +{ + u32 macHi, macLo; + + if (entry >= ah->caps.keycache_size) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keychache entry %u out of range\n", entry); + return false; + } + + if (mac != NULL) { + macHi = (mac[5] << 8) | mac[4]; + macLo = (mac[3] << 24) | + (mac[2] << 16) | + (mac[1] << 8) | + mac[0]; + macLo >>= 1; + macLo |= (macHi & 1) << 31; + macHi >>= 1; + } else { + macLo = macHi = 0; + } + REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); + REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); + + return true; +} + +bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, + const struct ath9k_keyval *k, + const u8 *mac) +{ + const struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 key0, key1, key2, key3, key4; + u32 keyType; + + if (entry >= pCap->keycache_size) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "keycache entry %u out of range\n", entry); + return false; + } + + switch (k->kv_type) { + case ATH9K_CIPHER_AES_OCB: + keyType = AR_KEYTABLE_TYPE_AES; + break; + case ATH9K_CIPHER_AES_CCM: + if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { + DPRINTF(ah->ah_sc, ATH_DBG_ANY, + "AES-CCM not supported by mac rev 0x%x\n", + ah->hw_version.macRev); + return false; + } + keyType = AR_KEYTABLE_TYPE_CCM; + break; + case ATH9K_CIPHER_TKIP: + keyType = AR_KEYTABLE_TYPE_TKIP; + if (ATH9K_IS_MIC_ENABLED(ah) + && entry + 64 >= pCap->keycache_size) { + DPRINTF(ah->ah_sc, ATH_DBG_ANY, + "entry %u inappropriate for TKIP\n", entry); + return false; + } + break; + case ATH9K_CIPHER_WEP: + if (k->kv_len < LEN_WEP40) { + DPRINTF(ah->ah_sc, ATH_DBG_ANY, + "WEP key length %u too small\n", k->kv_len); + return false; + } + if (k->kv_len <= LEN_WEP40) + keyType = AR_KEYTABLE_TYPE_40; + else if (k->kv_len <= LEN_WEP104) + keyType = AR_KEYTABLE_TYPE_104; + else + keyType = AR_KEYTABLE_TYPE_128; + break; + case ATH9K_CIPHER_CLR: + keyType = AR_KEYTABLE_TYPE_CLR; + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "cipher %u not supported\n", k->kv_type); + return false; + } + + key0 = get_unaligned_le32(k->kv_val + 0); + key1 = get_unaligned_le16(k->kv_val + 4); + key2 = get_unaligned_le32(k->kv_val + 6); + key3 = get_unaligned_le16(k->kv_val + 10); + key4 = get_unaligned_le32(k->kv_val + 12); + if (k->kv_len <= LEN_WEP104) + key4 &= 0xff; + + /* + * Note: Key cache registers access special memory area that requires + * two 32-bit writes to actually update the values in the internal + * memory. Consequently, the exact order and pairs used here must be + * maintained. + */ + + if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { + u16 micentry = entry + 64; + + /* + * Write inverted key[47:0] first to avoid Michael MIC errors + * on frames that could be sent or received at the same time. + * The correct key will be written in the end once everything + * else is ready. + */ + REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); + + /* Write key[95:48] */ + REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + + /* Write key[127:96] and key type */ + REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + + /* Write MAC address for the entry */ + (void) ath9k_hw_keysetmac(ah, entry, mac); + + if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { + /* + * TKIP uses two key cache entries: + * Michael MIC TX/RX keys in the same key cache entry + * (idx = main index + 64): + * key0 [31:0] = RX key [31:0] + * key1 [15:0] = TX key [31:16] + * key1 [31:16] = reserved + * key2 [31:0] = RX key [63:32] + * key3 [15:0] = TX key [15:0] + * key3 [31:16] = reserved + * key4 [31:0] = TX key [63:32] + */ + u32 mic0, mic1, mic2, mic3, mic4; + + mic0 = get_unaligned_le32(k->kv_mic + 0); + mic2 = get_unaligned_le32(k->kv_mic + 4); + mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; + mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; + mic4 = get_unaligned_le32(k->kv_txmic + 4); + + /* Write RX[31:0] and TX[31:16] */ + REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); + + /* Write RX[63:32] and TX[15:0] */ + REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); + REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); + + /* Write TX[63:32] and keyType(reserved) */ + REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); + REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), + AR_KEYTABLE_TYPE_CLR); + + } else { + /* + * TKIP uses four key cache entries (two for group + * keys): + * Michael MIC TX/RX keys are in different key cache + * entries (idx = main index + 64 for TX and + * main index + 32 + 96 for RX): + * key0 [31:0] = TX/RX MIC key [31:0] + * key1 [31:0] = reserved + * key2 [31:0] = TX/RX MIC key [63:32] + * key3 [31:0] = reserved + * key4 [31:0] = reserved + * + * Upper layer code will call this function separately + * for TX and RX keys when these registers offsets are + * used. + */ + u32 mic0, mic2; + + mic0 = get_unaligned_le32(k->kv_mic + 0); + mic2 = get_unaligned_le32(k->kv_mic + 4); + + /* Write MIC key[31:0] */ + REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); + + /* Write MIC key[63:32] */ + REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); + REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); + + /* Write TX[63:32] and keyType(reserved) */ + REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); + REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), + AR_KEYTABLE_TYPE_CLR); + } + + /* MAC address registers are reserved for the MIC entry */ + REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); + REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); + + /* + * Write the correct (un-inverted) key[47:0] last to enable + * TKIP now that all other registers are set with correct + * values. + */ + REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + } else { + /* Write key[47:0] */ + REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); + REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); + + /* Write key[95:48] */ + REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); + REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); + + /* Write key[127:96] and key type */ + REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); + REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); + + /* Write MAC address for the entry */ + (void) ath9k_hw_keysetmac(ah, entry, mac); + } + + return true; +} + +bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) +{ + if (entry < ah->caps.keycache_size) { + u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry)); + if (val & AR_KEYTABLE_VALID) + return true; + } + return false; +} + +/******************************/ +/* Power Management (Chipset) */ +/******************************/ + +static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) +{ + REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) { + REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + if (!AR_SREV_9100(ah)) + REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); + + REG_CLR_BIT(ah, (AR_RTC_RESET), + AR_RTC_RESET_EN); + } +} + +static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) +{ + REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) { + struct ath9k_hw_capabilities *pCap = &ah->caps; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_ON_INT); + } else { + REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + } + } +} + +static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) +{ + u32 val; + int i; + + if (setChip) { + if ((REG_READ(ah, AR_RTC_STATUS) & + AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { + if (ath9k_hw_set_reset_reg(ah, + ATH9K_RESET_POWER_ON) != true) { + return false; + } + } + if (AR_SREV_9100(ah)) + REG_SET_BIT(ah, AR_RTC_RESET, + AR_RTC_RESET_EN); + + REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + udelay(50); + + for (i = POWER_UP_TIME / 50; i > 0; i--) { + val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; + if (val == AR_RTC_STATUS_ON) + break; + udelay(50); + REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + } + if (i == 0) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); + return false; + } + } + + REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + + return true; +} + +bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) +{ + int status = true, setChip = true; + static const char *modes[] = { + "AWAKE", + "FULL-SLEEP", + "NETWORK SLEEP", + "UNDEFINED" + }; + + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", + modes[ah->power_mode], modes[mode]); + + switch (mode) { + case ATH9K_PM_AWAKE: + status = ath9k_hw_set_power_awake(ah, setChip); + break; + case ATH9K_PM_FULL_SLEEP: + ath9k_set_power_sleep(ah, setChip); + ah->chip_fullsleep = true; + break; + case ATH9K_PM_NETWORK_SLEEP: + ath9k_set_power_network_sleep(ah, setChip); + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Unknown power mode %u\n", mode); + return false; + } + ah->power_mode = mode; + + return status; +} + +/* + * Helper for ASPM support. + * + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the SerDes. + * + * Programming the SerDes must go through the same 288 bit serial shift + * register as the other analog registers. Hence the 9 writes. + */ +void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) +{ + u8 i; + + if (ah->is_pciexpress != true) + return; + + /* Do not touch SerDes registers */ + if (ah->config.pcie_powersave_enable == 2) + return; + + /* Nothing to do on restore for 11N */ + if (restore) + return; + + if (AR_SREV_9280_20_OR_LATER(ah)) { + /* + * AR9280 2.0 or later chips use SerDes values from the + * initvals.h initialized depending on chipset during + * ath9k_hw_do_attach() + */ + for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { + REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), + INI_RA(&ah->iniPcieSerdes, i, 1)); + } + } else if (AR_SREV_9280(ah) && + (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); + REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + + /* RX shut off when elecidle is asserted */ + REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); + REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); + REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); + + /* Shut off CLKREQ active in L1 */ + if (ah->config.pcie_clock_req) + REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); + else + REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); + + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); + + /* Load the new settings */ + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + + } else { + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + + /* RX shut off when elecidle is asserted */ + REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); + REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); + REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); + + /* + * Ignore ah->ah_config.pcie_clock_req setting for + * pre-AR9280 11n + */ + REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); + + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); + + /* Load the new settings */ + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + } + + udelay(1000); + + /* set bit 19 to allow forcing of pcie core into L1 state */ + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + + /* Several PCIe massages to ensure proper behaviour */ + if (ah->config.pcie_waen) { + REG_WRITE(ah, AR_WA, ah->config.pcie_waen); + } else { + if (AR_SREV_9285(ah)) + REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); + /* + * On AR9280 chips bit 22 of 0x4004 needs to be set to + * otherwise card may disappear. + */ + else if (AR_SREV_9280(ah)) + REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); + else + REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); + } +} + +/**********************/ +/* Interrupt Handling */ +/**********************/ + +bool ath9k_hw_intrpend(struct ath_hw *ah) +{ + u32 host_isr; + + if (AR_SREV_9100(ah)) + return true; + + host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); + if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) + return true; + + host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); + if ((host_isr & AR_INTR_SYNC_DEFAULT) + && (host_isr != AR_INTR_SPURIOUS)) + return true; + + return false; +} + +bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) +{ + u32 isr = 0; + u32 mask2 = 0; + struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 sync_cause = 0; + bool fatal_int = false; + + if (!AR_SREV_9100(ah)) { + if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { + if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) + == AR_RTC_STATUS_ON) { + isr = REG_READ(ah, AR_ISR); + } + } + + sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & + AR_INTR_SYNC_DEFAULT; + + *masked = 0; + + if (!isr && !sync_cause) + return false; + } else { + *masked = 0; + isr = REG_READ(ah, AR_ISR); + } + + if (isr) { + if (isr & AR_ISR_BCNMISC) { + u32 isr2; + isr2 = REG_READ(ah, AR_ISR_S2); + if (isr2 & AR_ISR_S2_TIM) + mask2 |= ATH9K_INT_TIM; + if (isr2 & AR_ISR_S2_DTIM) + mask2 |= ATH9K_INT_DTIM; + if (isr2 & AR_ISR_S2_DTIMSYNC) + mask2 |= ATH9K_INT_DTIMSYNC; + if (isr2 & (AR_ISR_S2_CABEND)) + mask2 |= ATH9K_INT_CABEND; + if (isr2 & AR_ISR_S2_GTT) + mask2 |= ATH9K_INT_GTT; + if (isr2 & AR_ISR_S2_CST) + mask2 |= ATH9K_INT_CST; + if (isr2 & AR_ISR_S2_TSFOOR) + mask2 |= ATH9K_INT_TSFOOR; + } + + isr = REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { + *masked = 0; + return false; + } + + *masked = isr & ATH9K_INT_COMMON; + + if (ah->config.intr_mitigation) { + if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) + *masked |= ATH9K_INT_RX; + } + + if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) + *masked |= ATH9K_INT_RX; + if (isr & + (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | + AR_ISR_TXEOL)) { + u32 s0_s, s1_s; + + *masked |= ATH9K_INT_TX; + + s0_s = REG_READ(ah, AR_ISR_S0_S); + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); + + s1_s = REG_READ(ah, AR_ISR_S1_S); + ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); + ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); + } + + if (isr & AR_ISR_RXORN) { + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, + "receive FIFO overrun interrupt\n"); + } + + if (!AR_SREV_9100(ah)) { + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + u32 isr5 = REG_READ(ah, AR_ISR_S5_S); + if (isr5 & AR_ISR_S5_TIM_TIMER) + *masked |= ATH9K_INT_TIM_TIMER; + } + } + + *masked |= mask2; + } + + if (AR_SREV_9100(ah)) + return true; + + if (sync_cause) { + fatal_int = + (sync_cause & + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) + ? true : false; + + if (fatal_int) { + if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { + DPRINTF(ah->ah_sc, ATH_DBG_ANY, + "received PCI FATAL interrupt\n"); + } + if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { + DPRINTF(ah->ah_sc, ATH_DBG_ANY, + "received PCI PERR interrupt\n"); + } + } + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); + REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); + REG_WRITE(ah, AR_RC, 0); + *masked |= ATH9K_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, + "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + } + + REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); + (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + } + + return true; +} + +enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah) +{ + return ah->mask_reg; +} + +enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) +{ + u32 omask = ah->mask_reg; + u32 mask, mask2; + struct ath9k_hw_capabilities *pCap = &ah->caps; + + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); + + if (omask & ATH9K_INT_GLOBAL) { + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) REG_READ(ah, AR_IER); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); + } + } + + mask = ints & ATH9K_INT_COMMON; + mask2 = 0; + + if (ints & ATH9K_INT_TX) { + if (ah->txok_interrupt_mask) + mask |= AR_IMR_TXOK; + if (ah->txdesc_interrupt_mask) + mask |= AR_IMR_TXDESC; + if (ah->txerr_interrupt_mask) + mask |= AR_IMR_TXERR; + if (ah->txeol_interrupt_mask) + mask |= AR_IMR_TXEOL; + } + if (ints & ATH9K_INT_RX) { + mask |= AR_IMR_RXERR; + if (ah->config.intr_mitigation) + mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; + else + mask |= AR_IMR_RXOK | AR_IMR_RXDESC; + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + mask |= AR_IMR_GENTMR; + } + + if (ints & (ATH9K_INT_BMISC)) { + mask |= AR_IMR_BCNMISC; + if (ints & ATH9K_INT_TIM) + mask2 |= AR_IMR_S2_TIM; + if (ints & ATH9K_INT_DTIM) + mask2 |= AR_IMR_S2_DTIM; + if (ints & ATH9K_INT_DTIMSYNC) + mask2 |= AR_IMR_S2_DTIMSYNC; + if (ints & ATH9K_INT_CABEND) + mask2 |= AR_IMR_S2_CABEND; + if (ints & ATH9K_INT_TSFOOR) + mask2 |= AR_IMR_S2_TSFOOR; + } + + if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { + mask |= AR_IMR_BCNMISC; + if (ints & ATH9K_INT_GTT) + mask2 |= AR_IMR_S2_GTT; + if (ints & ATH9K_INT_CST) + mask2 |= AR_IMR_S2_CST; + } + + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); + REG_WRITE(ah, AR_IMR, mask); + mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | + AR_IMR_S2_DTIM | + AR_IMR_S2_DTIMSYNC | + AR_IMR_S2_CABEND | + AR_IMR_S2_CABTO | + AR_IMR_S2_TSFOOR | + AR_IMR_S2_GTT | AR_IMR_S2_CST); + REG_WRITE(ah, AR_IMR_S2, mask | mask2); + ah->mask_reg = ints; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + if (ints & ATH9K_INT_TIM_TIMER) + REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); + else + REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); + } + + if (ints & ATH9K_INT_GLOBAL) { + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_DEFAULT); + } + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); + } + + return omask; +} + +/*******************/ +/* Beacon Handling */ +/*******************/ + +void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) +{ + int flags = 0; + + ah->beacon_interval = beacon_period; + + switch (ah->opmode) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_MONITOR: + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); + REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); + REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); + flags |= AR_TBTT_TIMER_EN; + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + REG_SET_BIT(ah, AR_TXCFG, + AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); + REG_WRITE(ah, AR_NEXT_NDP_TIMER, + TU_TO_USEC(next_beacon + + (ah->atim_window ? ah-> + atim_window : 1))); + flags |= AR_NDP_TIMER_EN; + case NL80211_IFTYPE_AP: + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); + REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, + TU_TO_USEC(next_beacon - + ah->config. + dma_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_SWBA, + TU_TO_USEC(next_beacon - + ah->config. + sw_beacon_response_time)); + flags |= + AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_BEACON, + "%s: unsupported opmode: %d\n", + __func__, ah->opmode); + return; + break; + } + + REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); + + beacon_period &= ~ATH9K_BEACON_ENA; + if (beacon_period & ATH9K_BEACON_RESET_TSF) { + beacon_period &= ~ATH9K_BEACON_RESET_TSF; + ath9k_hw_reset_tsf(ah); + } + + REG_SET_BIT(ah, AR_TIMER_MODE, flags); +} + +void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, + const struct ath9k_beacon_state *bs) +{ + u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; + struct ath9k_hw_capabilities *pCap = &ah->caps; + + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); + + REG_WRITE(ah, AR_BEACON_PERIOD, + TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, + TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); + + REG_RMW_FIELD(ah, AR_RSSI_THR, + AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); + + beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; + + if (bs->bs_sleepduration > beaconintval) + beaconintval = bs->bs_sleepduration; + + dtimperiod = bs->bs_dtimperiod; + if (bs->bs_sleepduration > dtimperiod) + dtimperiod = bs->bs_sleepduration; + + if (beaconintval == dtimperiod) + nextTbtt = bs->bs_nextdtim; + else + nextTbtt = bs->bs_nexttbtt; + + DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); + DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); + DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); + DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); + + REG_WRITE(ah, AR_NEXT_DTIM, + TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); + REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); + + REG_WRITE(ah, AR_SLEEP1, + SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) + | AR_SLEEP1_ASSUME_DTIM); + + if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP) + beacontimeout = (BEACON_TIMEOUT_VAL << 3); + else + beacontimeout = MIN_BEACON_TIMEOUT_VAL; + + REG_WRITE(ah, AR_SLEEP2, + SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); + + REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); + REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); + + REG_SET_BIT(ah, AR_TIMER_MODE, + AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | + AR_DTIM_TIMER_EN); + + /* TSF Out of Range Threshold */ + REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); +} + +/*******************/ +/* HW Capabilities */ +/*******************/ + +void ath9k_hw_fill_cap_info(struct ath_hw *ah) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + u16 capField = 0, eeval; + + eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); + ah->regulatory.current_rd = eeval; + + eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); + if (AR_SREV_9285_10_OR_LATER(ah)) + eeval |= AR9285_RDEXT_DEFAULT; + ah->regulatory.current_rd_ext = eeval; + + capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); + + if (ah->opmode != NL80211_IFTYPE_AP && + ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { + if (ah->regulatory.current_rd == 0x64 || + ah->regulatory.current_rd == 0x65) + ah->regulatory.current_rd += 5; + else if (ah->regulatory.current_rd == 0x41) + ah->regulatory.current_rd = 0x43; + DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, + "regdomain mapped to 0x%x\n", ah->regulatory.current_rd); + } + + eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); + bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); + + if (eeval & AR5416_OPFLAGS_11A) { + set_bit(ATH9K_MODE_11A, pCap->wireless_modes); + if (ah->config.ht_enable) { + if (!(eeval & AR5416_OPFLAGS_N_5G_HT20)) + set_bit(ATH9K_MODE_11NA_HT20, + pCap->wireless_modes); + if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) { + set_bit(ATH9K_MODE_11NA_HT40PLUS, + pCap->wireless_modes); + set_bit(ATH9K_MODE_11NA_HT40MINUS, + pCap->wireless_modes); + } + } + } + + if (eeval & AR5416_OPFLAGS_11G) { + set_bit(ATH9K_MODE_11B, pCap->wireless_modes); + set_bit(ATH9K_MODE_11G, pCap->wireless_modes); + if (ah->config.ht_enable) { + if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) + set_bit(ATH9K_MODE_11NG_HT20, + pCap->wireless_modes); + if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) { + set_bit(ATH9K_MODE_11NG_HT40PLUS, + pCap->wireless_modes); + set_bit(ATH9K_MODE_11NG_HT40MINUS, + pCap->wireless_modes); + } + } + } + + pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); + if ((ah->hw_version.devid == AR5416_DEVID_PCI) && + !(eeval & AR5416_OPFLAGS_11A)) + pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; + else + pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); + + if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) + ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; + + pCap->low_2ghz_chan = 2312; + pCap->high_2ghz_chan = 2732; + + pCap->low_5ghz_chan = 4920; + pCap->high_5ghz_chan = 6100; + + pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; + pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; + pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; + + pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; + pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; + pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; + + if (ah->config.ht_enable) + pCap->hw_caps |= ATH9K_HW_CAP_HT; + else + pCap->hw_caps &= ~ATH9K_HW_CAP_HT; + + pCap->hw_caps |= ATH9K_HW_CAP_GTT; + pCap->hw_caps |= ATH9K_HW_CAP_VEOL; + pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; + pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; + + if (capField & AR_EEPROM_EEPCAP_MAXQCU) + pCap->total_queues = + MS(capField, AR_EEPROM_EEPCAP_MAXQCU); + else + pCap->total_queues = ATH9K_NUM_TX_QUEUES; + + if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) + pCap->keycache_size = + 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); + else + pCap->keycache_size = AR_KEYTABLE_SIZE; + + pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; + + if (AR_SREV_9285_10_OR_LATER(ah)) + pCap->num_gpio_pins = AR9285_NUM_GPIO; + else if (AR_SREV_9280_10_OR_LATER(ah)) + pCap->num_gpio_pins = AR928X_NUM_GPIO; + else + pCap->num_gpio_pins = AR_NUM_GPIO; + + if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { + pCap->hw_caps |= ATH9K_HW_CAP_CST; + pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; + } else { + pCap->rts_aggr_limit = (8 * 1024); + } + + pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); + if (ah->rfsilent & EEP_RFSILENT_ENABLED) { + ah->rfkill_gpio = + MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL); + ah->rfkill_polarity = + MS(ah->rfsilent, EEP_RFSILENT_POLARITY); + + pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; + } +#endif + + if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || + (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || + (ah->hw_version.macVersion == AR_SREV_VERSION_9160) || + (ah->hw_version.macVersion == AR_SREV_VERSION_9100) || + (ah->hw_version.macVersion == AR_SREV_VERSION_9280)) + pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; + else + pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; + + if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) + pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; + else + pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; + + if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { + pCap->reg_cap = + AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | + AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | + AR_EEPROM_EEREGCAP_EN_KK_U2 | + AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; + } else { + pCap->reg_cap = + AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | + AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; + } + + pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; + + pCap->num_antcfg_5ghz = + ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); + pCap->num_antcfg_2ghz = + ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); + + if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) { + pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX; + ah->btactive_gpio = 6; + ah->wlanactive_gpio = 5; + } +} + +bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, + u32 capability, u32 *result) +{ + switch (type) { + case ATH9K_CAP_CIPHER: + switch (capability) { + case ATH9K_CIPHER_AES_CCM: + case ATH9K_CIPHER_AES_OCB: + case ATH9K_CIPHER_TKIP: + case ATH9K_CIPHER_WEP: + case ATH9K_CIPHER_MIC: + case ATH9K_CIPHER_CLR: + return true; + default: + return false; + } + case ATH9K_CAP_TKIP_MIC: + switch (capability) { + case 0: + return true; + case 1: + return (ah->sta_id1_defaults & + AR_STA_ID1_CRPT_MIC_ENABLE) ? true : + false; + } + case ATH9K_CAP_TKIP_SPLIT: + return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? + false : true; + case ATH9K_CAP_DIVERSITY: + return (REG_READ(ah, AR_PHY_CCK_DETECT) & + AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? + true : false; + case ATH9K_CAP_MCAST_KEYSRCH: + switch (capability) { + case 0: + return true; + case 1: + if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { + return false; + } else { + return (ah->sta_id1_defaults & + AR_STA_ID1_MCAST_KSRCH) ? true : + false; + } + } + return false; + case ATH9K_CAP_TXPOW: + switch (capability) { + case 0: + return 0; + case 1: + *result = ah->regulatory.power_limit; + return 0; + case 2: + *result = ah->regulatory.max_power_level; + return 0; + case 3: + *result = ah->regulatory.tp_scale; + return 0; + } + return false; + case ATH9K_CAP_DS: + return (AR_SREV_9280_20_OR_LATER(ah) && + (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) + ? false : true; + default: + return false; + } +} + +bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, + u32 capability, u32 setting, int *status) +{ + u32 v; + + switch (type) { + case ATH9K_CAP_TKIP_MIC: + if (setting) + ah->sta_id1_defaults |= + AR_STA_ID1_CRPT_MIC_ENABLE; + else + ah->sta_id1_defaults &= + ~AR_STA_ID1_CRPT_MIC_ENABLE; + return true; + case ATH9K_CAP_DIVERSITY: + v = REG_READ(ah, AR_PHY_CCK_DETECT); + if (setting) + v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + else + v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; + REG_WRITE(ah, AR_PHY_CCK_DETECT, v); + return true; + case ATH9K_CAP_MCAST_KEYSRCH: + if (setting) + ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; + else + ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; + return true; + default: + return false; + } +} + +/****************************/ +/* GPIO / RFKILL / Antennae */ +/****************************/ + +static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, + u32 gpio, u32 type) +{ + int addr; + u32 gpio_shift, tmp; + + if (gpio > 11) + addr = AR_GPIO_OUTPUT_MUX3; + else if (gpio > 5) + addr = AR_GPIO_OUTPUT_MUX2; + else + addr = AR_GPIO_OUTPUT_MUX1; + + gpio_shift = (gpio % 6) * 5; + + if (AR_SREV_9280_20_OR_LATER(ah) + || (addr != AR_GPIO_OUTPUT_MUX1)) { + REG_RMW(ah, addr, (type << gpio_shift), + (0x1f << gpio_shift)); + } else { + tmp = REG_READ(ah, addr); + tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); + tmp &= ~(0x1f << gpio_shift); + tmp |= (type << gpio_shift); + REG_WRITE(ah, addr, tmp); + } +} + +void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) +{ + u32 gpio_shift; + + ASSERT(gpio < ah->caps.num_gpio_pins); + + gpio_shift = gpio << 1; + + REG_RMW(ah, + AR_GPIO_OE_OUT, + (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), + (AR_GPIO_OE_OUT_DRV << gpio_shift)); +} + +u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) +{ +#define MS_REG_READ(x, y) \ + (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y))) + + if (gpio >= ah->caps.num_gpio_pins) + return 0xffffffff; + + if (AR_SREV_9285_10_OR_LATER(ah)) + return MS_REG_READ(AR9285, gpio) != 0; + else if (AR_SREV_9280_10_OR_LATER(ah)) + return MS_REG_READ(AR928X, gpio) != 0; + else + return MS_REG_READ(AR, gpio) != 0; +} + +void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, + u32 ah_signal_type) +{ + u32 gpio_shift; + + ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); + + gpio_shift = 2 * gpio; + + REG_RMW(ah, + AR_GPIO_OE_OUT, + (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), + (AR_GPIO_OE_OUT_DRV << gpio_shift)); +} + +void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) +{ + REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), + AR_GPIO_BIT(gpio)); +} + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) +void ath9k_enable_rfkill(struct ath_hw *ah) +{ + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); + + REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, + AR_GPIO_INPUT_MUX2_RFSILENT); + + ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); + REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); +} +#endif + +u32 ath9k_hw_getdefantenna(struct ath_hw *ah) +{ + return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; +} + +void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) +{ + REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); +} + +bool ath9k_hw_setantennaswitch(struct ath_hw *ah, + enum ath9k_ant_setting settings, + struct ath9k_channel *chan, + u8 *tx_chainmask, + u8 *rx_chainmask, + u8 *antenna_cfgd) +{ + static u8 tx_chainmask_cfg, rx_chainmask_cfg; + + if (AR_SREV_9280(ah)) { + if (!tx_chainmask_cfg) { + + tx_chainmask_cfg = *tx_chainmask; + rx_chainmask_cfg = *rx_chainmask; + } + + switch (settings) { + case ATH9K_ANT_FIXED_A: + *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK; + *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK; + *antenna_cfgd = true; + break; + case ATH9K_ANT_FIXED_B: + if (ah->caps.tx_chainmask > + ATH9K_ANTENNA1_CHAINMASK) { + *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK; + } + *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK; + *antenna_cfgd = true; + break; + case ATH9K_ANT_VARIABLE: + *tx_chainmask = tx_chainmask_cfg; + *rx_chainmask = rx_chainmask_cfg; + *antenna_cfgd = true; + break; + default: + break; + } + } else { + ah->diversity_control = settings; + } + + return true; +} + +/*********************/ +/* General Operation */ +/*********************/ + +u32 ath9k_hw_getrxfilter(struct ath_hw *ah) +{ + u32 bits = REG_READ(ah, AR_RX_FILTER); + u32 phybits = REG_READ(ah, AR_PHY_ERR); + + if (phybits & AR_PHY_ERR_RADAR) + bits |= ATH9K_RX_FILTER_PHYRADAR; + if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) + bits |= ATH9K_RX_FILTER_PHYERR; + + return bits; +} + +void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) +{ + u32 phybits; + + REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR); + phybits = 0; + if (bits & ATH9K_RX_FILTER_PHYRADAR) + phybits |= AR_PHY_ERR_RADAR; + if (bits & ATH9K_RX_FILTER_PHYERR) + phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; + REG_WRITE(ah, AR_PHY_ERR, phybits); + + if (phybits) + REG_WRITE(ah, AR_RXCFG, + REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); + else + REG_WRITE(ah, AR_RXCFG, + REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); +} + +bool ath9k_hw_phy_disable(struct ath_hw *ah) +{ + return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); +} + +bool ath9k_hw_disable(struct ath_hw *ah) +{ + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) + return false; + + return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); +} + +bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) +{ + struct ath9k_channel *chan = ah->curchan; + struct ieee80211_channel *channel = chan->chan; + + ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); + + if (ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(&ah->regulatory, chan), + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, + (u32) ah->regulatory.power_limit)) != 0) + return false; + + return true; +} + +void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) +{ + memcpy(ah->macaddr, mac, ETH_ALEN); +} + +void ath9k_hw_setopmode(struct ath_hw *ah) +{ + ath9k_hw_set_operating_mode(ah, ah->opmode); +} + +void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) +{ + REG_WRITE(ah, AR_MCAST_FIL0, filter0); + REG_WRITE(ah, AR_MCAST_FIL1, filter1); +} + +void ath9k_hw_setbssidmask(struct ath_softc *sc) +{ + REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); + REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); +} + +void ath9k_hw_write_associd(struct ath_softc *sc) +{ + REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); + REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | + ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); +} + +u64 ath9k_hw_gettsf64(struct ath_hw *ah) +{ + u64 tsf; + + tsf = REG_READ(ah, AR_TSF_U32); + tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); + + return tsf; +} + +void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) +{ + REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); + REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); +} + +void ath9k_hw_reset_tsf(struct ath_hw *ah) +{ + int count; + + count = 0; + while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { + count++; + if (count > 10) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, + "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); + break; + } + udelay(10); + } + REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); +} + +bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) +{ + if (setting) + ah->misc_mode |= AR_PCU_TX_ADD_TSF; + else + ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; + + return true; +} + +bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) +{ + if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { + DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us); + ah->slottime = (u32) -1; + return false; + } else { + REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); + ah->slottime = us; + return true; + } +} + +void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode) +{ + u32 macmode; + + if (mode == ATH9K_HT_MACMODE_2040 && + !ah->config.cwm_ignore_extcca) + macmode = AR_2040_JOINED_RX_CLEAR; + else + macmode = 0; + + REG_WRITE(ah, AR_2040_MODE, macmode); +} + +/***************************/ +/* Bluetooth Coexistence */ +/***************************/ + +void ath9k_hw_btcoex_enable(struct ath_hw *ah) +{ + /* connect bt_active to baseband */ + REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, + (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | + AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); + + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); + + /* Set input mux for bt_active to gpio pin */ + REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, + AR_GPIO_INPUT_MUX1_BT_ACTIVE, + ah->btactive_gpio); + + /* Configure the desired gpio port for input */ + ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio); + + /* Configure the desired GPIO port for TX_FRAME output */ + ath9k_hw_cfg_output(ah, ah->wlanactive_gpio, + AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); +} diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h new file mode 100644 index 000000000000..5c4127e6c1c6 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -0,0 +1,631 @@ +/* + * 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 HW_H +#define HW_H + +#include +#include +#include + +#include "mac.h" +#include "ani.h" +#include "eeprom.h" +#include "calib.h" +#include "reg.h" +#include "phy.h" + +#include "../regd.h" + +#define ATHEROS_VENDOR_ID 0x168c +#define AR5416_DEVID_PCI 0x0023 +#define AR5416_DEVID_PCIE 0x0024 +#define AR9160_DEVID_PCI 0x0027 +#define AR9280_DEVID_PCI 0x0029 +#define AR9280_DEVID_PCIE 0x002a +#define AR9285_DEVID_PCIE 0x002b +#define AR5416_AR9100_DEVID 0x000b +#define AR_SUBVENDOR_ID_NOG 0x0e11 +#define AR_SUBVENDOR_ID_NEW_A 0x7065 +#define AR5416_MAGIC 0x19641014 + +/* Register read/write primitives */ +#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) +#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) + +#define SM(_v, _f) (((_v) << _f##_S) & _f) +#define MS(_v, _f) (((_v) & _f) >> _f##_S) +#define REG_RMW(_a, _r, _set, _clr) \ + REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) +#define REG_RMW_FIELD(_a, _r, _f, _v) \ + REG_WRITE(_a, _r, \ + (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) +#define REG_SET_BIT(_a, _r, _f) \ + REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) +#define REG_CLR_BIT(_a, _r, _f) \ + REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) + +#define DO_DELAY(x) do { \ + if ((++(x) % 64) == 0) \ + udelay(1); \ + } while (0) + +#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ + int r; \ + for (r = 0; r < ((iniarray)->ia_rows); r++) { \ + REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ + INI_RA((iniarray), r, (column))); \ + DO_DELAY(regWr); \ + } \ + } while (0) + +#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 +#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 +#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 +#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 + +#define AR_GPIOD_MASK 0x00001FFF +#define AR_GPIO_BIT(_gpio) (1 << (_gpio)) + +#define BASE_ACTIVATE_DELAY 100 +#define RTC_PLL_SETTLE_DELAY 1000 +#define COEF_SCALE_S 24 +#define HT40_CHANNEL_CENTER_SHIFT 10 + +#define ATH9K_ANTENNA0_CHAINMASK 0x1 +#define ATH9K_ANTENNA1_CHAINMASK 0x2 + +#define ATH9K_NUM_DMA_DEBUG_REGS 8 +#define ATH9K_NUM_QUEUES 10 + +#define MAX_RATE_POWER 63 +#define AH_WAIT_TIMEOUT 100000 /* (us) */ +#define AH_TIME_QUANTUM 10 +#define AR_KEYTABLE_SIZE 128 +#define POWER_UP_TIME 200000 +#define SPUR_RSSI_THRESH 40 + +#define CAB_TIMEOUT_VAL 10 +#define BEACON_TIMEOUT_VAL 10 +#define MIN_BEACON_TIMEOUT_VAL 1 +#define SLEEP_SLOP 3 + +#define INIT_CONFIG_STATUS 0x00000000 +#define INIT_RSSI_THR 0x00000700 +#define INIT_BCON_CNTRL_REG 0x00000000 + +#define TU_TO_USEC(_tu) ((_tu) << 10) + +enum wireless_mode { + ATH9K_MODE_11A = 0, + ATH9K_MODE_11B = 2, + ATH9K_MODE_11G = 3, + ATH9K_MODE_11NA_HT20 = 6, + ATH9K_MODE_11NG_HT20 = 7, + ATH9K_MODE_11NA_HT40PLUS = 8, + ATH9K_MODE_11NA_HT40MINUS = 9, + ATH9K_MODE_11NG_HT40PLUS = 10, + ATH9K_MODE_11NG_HT40MINUS = 11, + ATH9K_MODE_MAX +}; + +enum ath9k_hw_caps { + ATH9K_HW_CAP_MIC_AESCCM = BIT(0), + ATH9K_HW_CAP_MIC_CKIP = BIT(1), + ATH9K_HW_CAP_MIC_TKIP = BIT(2), + ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), + ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), + ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), + ATH9K_HW_CAP_VEOL = BIT(6), + ATH9K_HW_CAP_BSSIDMASK = BIT(7), + ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), + ATH9K_HW_CAP_HT = BIT(9), + ATH9K_HW_CAP_GTT = BIT(10), + ATH9K_HW_CAP_FASTCC = BIT(11), + ATH9K_HW_CAP_RFSILENT = BIT(12), + ATH9K_HW_CAP_CST = BIT(13), + ATH9K_HW_CAP_ENHANCEDPM = BIT(14), + ATH9K_HW_CAP_AUTOSLEEP = BIT(15), + ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), + ATH9K_HW_CAP_BT_COEX = BIT(17) +}; + +enum ath9k_capability_type { + ATH9K_CAP_CIPHER = 0, + ATH9K_CAP_TKIP_MIC, + ATH9K_CAP_TKIP_SPLIT, + ATH9K_CAP_DIVERSITY, + ATH9K_CAP_TXPOW, + ATH9K_CAP_MCAST_KEYSRCH, + ATH9K_CAP_DS +}; + +struct ath9k_hw_capabilities { + u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ + DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */ + u16 total_queues; + u16 keycache_size; + u16 low_5ghz_chan, high_5ghz_chan; + u16 low_2ghz_chan, high_2ghz_chan; + u16 rts_aggr_limit; + u8 tx_chainmask; + u8 rx_chainmask; + u16 tx_triglevel_max; + u16 reg_cap; + u8 num_gpio_pins; + u8 num_antcfg_2ghz; + u8 num_antcfg_5ghz; +}; + +struct ath9k_ops_config { + int dma_beacon_response_time; + int sw_beacon_response_time; + int additional_swba_backoff; + int ack_6mb; + int cwm_ignore_extcca; + u8 pcie_powersave_enable; + u8 pcie_clock_req; + u32 pcie_waen; + u8 analog_shiftreg; + u8 ht_enable; + u32 ofdm_trig_low; + u32 ofdm_trig_high; + u32 cck_trig_high; + u32 cck_trig_low; + u32 enable_ani; + u16 diversity_control; + u16 antenna_switch_swap; + int serialize_regmode; + bool intr_mitigation; +#define SPUR_DISABLE 0 +#define SPUR_ENABLE_IOCTL 1 +#define SPUR_ENABLE_EEPROM 2 +#define AR_EEPROM_MODAL_SPURS 5 +#define AR_SPUR_5413_1 1640 +#define AR_SPUR_5413_2 1200 +#define AR_NO_SPUR 0x8000 +#define AR_BASE_FREQ_2GHZ 2300 +#define AR_BASE_FREQ_5GHZ 4900 +#define AR_SPUR_FEEQ_BOUND_HT40 19 +#define AR_SPUR_FEEQ_BOUND_HT20 10 + int spurmode; + u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; +}; + +enum ath9k_int { + ATH9K_INT_RX = 0x00000001, + ATH9K_INT_RXDESC = 0x00000002, + ATH9K_INT_RXNOFRM = 0x00000008, + ATH9K_INT_RXEOL = 0x00000010, + ATH9K_INT_RXORN = 0x00000020, + ATH9K_INT_TX = 0x00000040, + ATH9K_INT_TXDESC = 0x00000080, + ATH9K_INT_TIM_TIMER = 0x00000100, + ATH9K_INT_TXURN = 0x00000800, + ATH9K_INT_MIB = 0x00001000, + ATH9K_INT_RXPHY = 0x00004000, + ATH9K_INT_RXKCM = 0x00008000, + ATH9K_INT_SWBA = 0x00010000, + ATH9K_INT_BMISS = 0x00040000, + ATH9K_INT_BNR = 0x00100000, + ATH9K_INT_TIM = 0x00200000, + ATH9K_INT_DTIM = 0x00400000, + ATH9K_INT_DTIMSYNC = 0x00800000, + ATH9K_INT_GPIO = 0x01000000, + ATH9K_INT_CABEND = 0x02000000, + ATH9K_INT_TSFOOR = 0x04000000, + ATH9K_INT_CST = 0x10000000, + ATH9K_INT_GTT = 0x20000000, + ATH9K_INT_FATAL = 0x40000000, + ATH9K_INT_GLOBAL = 0x80000000, + ATH9K_INT_BMISC = ATH9K_INT_TIM | + ATH9K_INT_DTIM | + ATH9K_INT_DTIMSYNC | + ATH9K_INT_TSFOOR | + ATH9K_INT_CABEND, + ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM | + ATH9K_INT_RXDESC | + ATH9K_INT_RXEOL | + ATH9K_INT_RXORN | + ATH9K_INT_TXURN | + ATH9K_INT_TXDESC | + ATH9K_INT_MIB | + ATH9K_INT_RXPHY | + ATH9K_INT_RXKCM | + ATH9K_INT_SWBA | + ATH9K_INT_BMISS | + ATH9K_INT_GPIO, + ATH9K_INT_NOCARD = 0xffffffff +}; + +#define CHANNEL_CW_INT 0x00002 +#define CHANNEL_CCK 0x00020 +#define CHANNEL_OFDM 0x00040 +#define CHANNEL_2GHZ 0x00080 +#define CHANNEL_5GHZ 0x00100 +#define CHANNEL_PASSIVE 0x00200 +#define CHANNEL_DYN 0x00400 +#define CHANNEL_HALF 0x04000 +#define CHANNEL_QUARTER 0x08000 +#define CHANNEL_HT20 0x10000 +#define CHANNEL_HT40PLUS 0x20000 +#define CHANNEL_HT40MINUS 0x40000 + +#define CHANNEL_INTERFERENCE 0x01 +#define CHANNEL_DFS 0x02 +#define CHANNEL_4MS_LIMIT 0x04 +#define CHANNEL_DFS_CLEAR 0x08 +#define CHANNEL_DISALLOW_ADHOC 0x10 +#define CHANNEL_PER_11D_ADHOC 0x20 + +#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) +#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) +#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) +#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) +#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) +#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) +#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) +#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) +#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) +#define CHANNEL_ALL \ + (CHANNEL_OFDM| \ + CHANNEL_CCK| \ + CHANNEL_2GHZ | \ + CHANNEL_5GHZ | \ + CHANNEL_HT20 | \ + CHANNEL_HT40PLUS | \ + CHANNEL_HT40MINUS) + +struct ath9k_channel { + struct ieee80211_channel *chan; + u16 channel; + u32 channelFlags; + u32 chanmode; + int32_t CalValid; + bool oneTimeCalsDone; + int8_t iCoff; + int8_t qCoff; + int16_t rawNoiseFloor; +}; + +#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ + (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ + (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ + (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) +#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ + (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ + (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ + (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) +#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) +#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) +#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) +#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) +#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) +#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) +#define IS_CHAN_A_5MHZ_SPACED(_c) \ + ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ + (((_c)->channel % 20) != 0) && \ + (((_c)->channel % 10) != 0)) + +/* These macros check chanmode and not channelFlags */ +#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) +#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ + ((_c)->chanmode == CHANNEL_G_HT20)) +#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ + ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ + ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ + ((_c)->chanmode == CHANNEL_G_HT40MINUS)) +#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) + +enum ath9k_power_mode { + ATH9K_PM_AWAKE = 0, + ATH9K_PM_FULL_SLEEP, + ATH9K_PM_NETWORK_SLEEP, + ATH9K_PM_UNDEFINED +}; + +enum ath9k_ant_setting { + ATH9K_ANT_VARIABLE = 0, + ATH9K_ANT_FIXED_A, + ATH9K_ANT_FIXED_B +}; + +enum ath9k_tp_scale { + ATH9K_TP_SCALE_MAX = 0, + ATH9K_TP_SCALE_50, + ATH9K_TP_SCALE_25, + ATH9K_TP_SCALE_12, + ATH9K_TP_SCALE_MIN +}; + +enum ser_reg_mode { + SER_REG_MODE_OFF = 0, + SER_REG_MODE_ON = 1, + SER_REG_MODE_AUTO = 2, +}; + +struct ath9k_beacon_state { + u32 bs_nexttbtt; + u32 bs_nextdtim; + u32 bs_intval; +#define ATH9K_BEACON_PERIOD 0x0000ffff +#define ATH9K_BEACON_ENA 0x00800000 +#define ATH9K_BEACON_RESET_TSF 0x01000000 +#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ + u32 bs_dtimperiod; + u16 bs_cfpperiod; + u16 bs_cfpmaxduration; + u32 bs_cfpnext; + u16 bs_timoffset; + u16 bs_bmissthreshold; + u32 bs_sleepduration; + u32 bs_tsfoor_threshold; +}; + +struct chan_centers { + u16 synth_center; + u16 ctl_center; + u16 ext_center; +}; + +enum { + ATH9K_RESET_POWER_ON, + ATH9K_RESET_WARM, + ATH9K_RESET_COLD, +}; + +struct ath9k_hw_version { + u32 magic; + u16 devid; + u16 subvendorid; + u32 macVersion; + u16 macRev; + u16 phyRev; + u16 analog5GhzRev; + u16 analog2GhzRev; +}; + +struct ath_hw { + struct ath_softc *ah_sc; + struct ath9k_hw_version hw_version; + struct ath9k_ops_config config; + struct ath9k_hw_capabilities caps; + struct ath_regulatory regulatory; + struct ath9k_channel channels[38]; + struct ath9k_channel *curchan; + + union { + struct ar5416_eeprom_def def; + struct ar5416_eeprom_4k map4k; + } eeprom; + const struct eeprom_ops *eep_ops; + enum ath9k_eep_map eep_map; + + bool sw_mgmt_crypto; + bool is_pciexpress; + u8 macaddr[ETH_ALEN]; + u16 tx_trig_level; + u16 rfsilent; + u32 rfkill_gpio; + u32 rfkill_polarity; + u32 btactive_gpio; + u32 wlanactive_gpio; + u32 ah_flags; + + enum nl80211_iftype opmode; + enum ath9k_power_mode power_mode; + enum ath9k_power_mode restore_mode; + + struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; + struct ar5416Stats stats; + struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; + + int16_t curchan_rad_index; + u32 mask_reg; + u32 txok_interrupt_mask; + u32 txerr_interrupt_mask; + u32 txdesc_interrupt_mask; + u32 txeol_interrupt_mask; + u32 txurn_interrupt_mask; + bool chip_fullsleep; + u32 atim_window; + u16 antenna_switch_swap; + enum ath9k_ant_setting diversity_control; + + /* Calibration */ + enum hal_cal_types supp_cals; + struct hal_cal_list iq_caldata; + struct hal_cal_list adcgain_caldata; + struct hal_cal_list adcdc_calinitdata; + struct hal_cal_list adcdc_caldata; + struct hal_cal_list *cal_list; + struct hal_cal_list *cal_list_last; + struct hal_cal_list *cal_list_curr; +#define totalPowerMeasI meas0.unsign +#define totalPowerMeasQ meas1.unsign +#define totalIqCorrMeas meas2.sign +#define totalAdcIOddPhase meas0.unsign +#define totalAdcIEvenPhase meas1.unsign +#define totalAdcQOddPhase meas2.unsign +#define totalAdcQEvenPhase meas3.unsign +#define totalAdcDcOffsetIOddPhase meas0.sign +#define totalAdcDcOffsetIEvenPhase meas1.sign +#define totalAdcDcOffsetQOddPhase meas2.sign +#define totalAdcDcOffsetQEvenPhase meas3.sign + union { + u32 unsign[AR5416_MAX_CHAINS]; + int32_t sign[AR5416_MAX_CHAINS]; + } meas0; + union { + u32 unsign[AR5416_MAX_CHAINS]; + int32_t sign[AR5416_MAX_CHAINS]; + } meas1; + union { + u32 unsign[AR5416_MAX_CHAINS]; + int32_t sign[AR5416_MAX_CHAINS]; + } meas2; + union { + u32 unsign[AR5416_MAX_CHAINS]; + int32_t sign[AR5416_MAX_CHAINS]; + } meas3; + u16 cal_samples; + + u32 sta_id1_defaults; + u32 misc_mode; + enum { + AUTO_32KHZ, + USE_32KHZ, + DONT_USE_32KHZ, + } enable_32kHz_clock; + + /* RF */ + u32 *analogBank0Data; + u32 *analogBank1Data; + u32 *analogBank2Data; + u32 *analogBank3Data; + u32 *analogBank6Data; + u32 *analogBank6TPCData; + u32 *analogBank7Data; + u32 *addac5416_21; + u32 *bank6Temp; + + int16_t txpower_indexoffset; + u32 beacon_interval; + u32 slottime; + u32 acktimeout; + u32 ctstimeout; + u32 globaltxtimeout; + u8 gbeacon_rate; + + /* ANI */ + u32 proc_phyerr; + bool has_hw_phycounters; + u32 aniperiod; + struct ar5416AniState *curani; + struct ar5416AniState ani[255]; + int totalSizeDesired[5]; + int coarse_high[5]; + int coarse_low[5]; + int firpwr[5]; + enum ath9k_ani_cmd ani_function; + + u32 intr_txqs; + enum ath9k_ht_extprotspacing extprotspacing; + u8 txchainmask; + u8 rxchainmask; + + u32 originalGain[22]; + int initPDADC; + int PDADCdelta; + + struct ar5416IniArray iniModes; + struct ar5416IniArray iniCommon; + struct ar5416IniArray iniBank0; + struct ar5416IniArray iniBB_RfGain; + struct ar5416IniArray iniBank1; + struct ar5416IniArray iniBank2; + struct ar5416IniArray iniBank3; + struct ar5416IniArray iniBank6; + struct ar5416IniArray iniBank6TPC; + struct ar5416IniArray iniBank7; + struct ar5416IniArray iniAddac; + struct ar5416IniArray iniPcieSerdes; + struct ar5416IniArray iniModesAdditional; + struct ar5416IniArray iniModesRxGain; + struct ar5416IniArray iniModesTxGain; +}; + +/* Attach, Detach, Reset */ +const char *ath9k_hw_probe(u16 vendorid, u16 devid); +void ath9k_hw_detach(struct ath_hw *ah); +struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error); +void ath9k_hw_rfdetach(struct ath_hw *ah); +int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + bool bChannelChange); +void ath9k_hw_fill_cap_info(struct ath_hw *ah); +bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, + u32 capability, u32 *result); +bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, + u32 capability, u32 setting, int *status); + +/* Key Cache Management */ +bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); +bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac); +bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, + const struct ath9k_keyval *k, + const u8 *mac); +bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry); + +/* GPIO / RFKILL / Antennae */ +void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); +u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); +void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, + u32 ah_signal_type); +void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) +void ath9k_enable_rfkill(struct ath_hw *ah); +#endif +u32 ath9k_hw_getdefantenna(struct ath_hw *ah); +void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); +bool ath9k_hw_setantennaswitch(struct ath_hw *ah, + enum ath9k_ant_setting settings, + struct ath9k_channel *chan, + u8 *tx_chainmask, u8 *rx_chainmask, + u8 *antenna_cfgd); + +/* General Operation */ +bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); +u32 ath9k_hw_reverse_bits(u32 val, u32 n); +bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); +u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, + u32 frameLen, u16 rateix, bool shortPreamble); +void ath9k_hw_get_channel_centers(struct ath_hw *ah, + struct ath9k_channel *chan, + struct chan_centers *centers); +u32 ath9k_hw_getrxfilter(struct ath_hw *ah); +void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); +bool ath9k_hw_phy_disable(struct ath_hw *ah); +bool ath9k_hw_disable(struct ath_hw *ah); +bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); +void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); +void ath9k_hw_setopmode(struct ath_hw *ah); +void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); +void ath9k_hw_setbssidmask(struct ath_softc *sc); +void ath9k_hw_write_associd(struct ath_softc *sc); +u64 ath9k_hw_gettsf64(struct ath_hw *ah); +void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); +void ath9k_hw_reset_tsf(struct ath_hw *ah); +bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); +bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); +void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); +void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); +void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, + const struct ath9k_beacon_state *bs); +bool ath9k_hw_setpower(struct ath_hw *ah, + enum ath9k_power_mode mode); +void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); + +/* Interrupt Handling */ +bool ath9k_hw_intrpend(struct ath_hw *ah); +bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); +enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah); +enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); + +void ath9k_hw_btcoex_enable(struct ath_hw *ah); + +#endif diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h new file mode 100644 index 000000000000..e2f0a34b79a1 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/initvals.h @@ -0,0 +1,4848 @@ +/* + * 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. + */ + +static const u32 ar5416Modes[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, + { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, + { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00007010, 0x00000000 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00070000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a002e }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5d50e188 }, + { 0x00009958, 0x00081fff }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x001fff00 }, + { 0x000099ac, 0x00000000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x000000aa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x00000bb5 }, + { 0x0000a22c, 0x00000011 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x051701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa1f }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x08000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const u32 ar5416Bank2[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const u32 ar5416Bank3[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6[][3] = { + + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank6TPC[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x201400df, 0x201400df }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007081, 0x00007081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x0000000c }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000030 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000060 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000058 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +static const u32 ar5416Modes_9100[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, + { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, + { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, + { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, +#ifdef TB243 + { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, +#else + { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, +#endif + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common_9100[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00020010, 0x00000003 }, + { 0x00020038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00004000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889ae }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000a000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79a8aa33 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0_9100[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain_9100[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1_9100[][2] = { + { 0x000098b0, 0x02108421}, + { 0x000098ec, 0x00000008}, +}; + +static const u32 ar5416Bank2_9100[][2] = { + { 0x000098b0, 0x0e73ff17}, + { 0x000098e0, 0x00000420}, +}; + +static const u32 ar5416Bank3_9100[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6_9100[][3] = { + + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014000f, 0x0014000f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x000180d6, 0x000180d6 }, + { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, + { 0x0000989c, 0x000000b1, 0x000000b1 }, + { 0x0000989c, 0x00002000, 0x00002000 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + + +static const u32 ar5416Bank6TPC_9100[][3] = { + + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7_9100[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac_9100[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000010 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000015 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +static const u32 ar5416Modes_9160[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, + { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, + { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, + { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, + { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, + { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, + { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, + { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, + { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, + { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, + { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, + { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, + { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, + { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, + { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, + { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, + { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, + { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, + { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, + { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, + { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common_9160[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00007010, 0x00000020 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xad848e19 }, + { 0x00009810, 0x7d14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x1284233c }, + { 0x00009854, 0x00000859 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x05100000 }, + { 0x0000a920, 0x05100000 }, + { 0x0000b920, 0x05100000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280b212 }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x00750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000200 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x00009b00, 0x00000000 }, + { 0x00009b04, 0x00000001 }, + { 0x00009b08, 0x00000002 }, + { 0x00009b0c, 0x00000003 }, + { 0x00009b10, 0x00000004 }, + { 0x00009b14, 0x00000005 }, + { 0x00009b18, 0x00000008 }, + { 0x00009b1c, 0x00000009 }, + { 0x00009b20, 0x0000000a }, + { 0x00009b24, 0x0000000b }, + { 0x00009b28, 0x0000000c }, + { 0x00009b2c, 0x0000000d }, + { 0x00009b30, 0x00000010 }, + { 0x00009b34, 0x00000011 }, + { 0x00009b38, 0x00000012 }, + { 0x00009b3c, 0x00000013 }, + { 0x00009b40, 0x00000014 }, + { 0x00009b44, 0x00000015 }, + { 0x00009b48, 0x00000018 }, + { 0x00009b4c, 0x00000019 }, + { 0x00009b50, 0x0000001a }, + { 0x00009b54, 0x0000001b }, + { 0x00009b58, 0x0000001c }, + { 0x00009b5c, 0x0000001d }, + { 0x00009b60, 0x00000020 }, + { 0x00009b64, 0x00000021 }, + { 0x00009b68, 0x00000022 }, + { 0x00009b6c, 0x00000023 }, + { 0x00009b70, 0x00000024 }, + { 0x00009b74, 0x00000025 }, + { 0x00009b78, 0x00000028 }, + { 0x00009b7c, 0x00000029 }, + { 0x00009b80, 0x0000002a }, + { 0x00009b84, 0x0000002b }, + { 0x00009b88, 0x0000002c }, + { 0x00009b8c, 0x0000002d }, + { 0x00009b90, 0x00000030 }, + { 0x00009b94, 0x00000031 }, + { 0x00009b98, 0x00000032 }, + { 0x00009b9c, 0x00000033 }, + { 0x00009ba0, 0x00000034 }, + { 0x00009ba4, 0x00000035 }, + { 0x00009ba8, 0x00000035 }, + { 0x00009bac, 0x00000035 }, + { 0x00009bb0, 0x00000035 }, + { 0x00009bb4, 0x00000035 }, + { 0x00009bb8, 0x00000035 }, + { 0x00009bbc, 0x00000035 }, + { 0x00009bc0, 0x00000035 }, + { 0x00009bc4, 0x00000035 }, + { 0x00009bc8, 0x00000035 }, + { 0x00009bcc, 0x00000035 }, + { 0x00009bd0, 0x00000035 }, + { 0x00009bd4, 0x00000035 }, + { 0x00009bd8, 0x00000035 }, + { 0x00009bdc, 0x00000035 }, + { 0x00009be0, 0x00000035 }, + { 0x00009be4, 0x00000035 }, + { 0x00009be8, 0x00000035 }, + { 0x00009bec, 0x00000035 }, + { 0x00009bf0, 0x00000035 }, + { 0x00009bf4, 0x00000035 }, + { 0x00009bf8, 0x00000010 }, + { 0x00009bfc, 0x0000001a }, + { 0x0000a210, 0x40806333 }, + { 0x0000a214, 0x00106c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x018830c6 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x001a0bb5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x0000e000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cc75380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000001 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000c26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a338, 0x00000000 }, + { 0x0000a33c, 0x00000000 }, + { 0x0000a340, 0x00000000 }, + { 0x0000a344, 0x00000000 }, + { 0x0000a348, 0x3fffffff }, + { 0x0000a34c, 0x3fffffff }, + { 0x0000a350, 0x3fffffff }, + { 0x0000a354, 0x0003ffff }, + { 0x0000a358, 0x79bfaa03 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0_9160[][2] = { + { 0x000098b0, 0x1e5795e5 }, + { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain_9160[][3] = { + { 0x00009a00, 0x00000000, 0x00000000 }, + { 0x00009a04, 0x00000040, 0x00000040 }, + { 0x00009a08, 0x00000080, 0x00000080 }, + { 0x00009a0c, 0x000001a1, 0x00000141 }, + { 0x00009a10, 0x000001e1, 0x00000181 }, + { 0x00009a14, 0x00000021, 0x000001c1 }, + { 0x00009a18, 0x00000061, 0x00000001 }, + { 0x00009a1c, 0x00000168, 0x00000041 }, + { 0x00009a20, 0x000001a8, 0x000001a8 }, + { 0x00009a24, 0x000001e8, 0x000001e8 }, + { 0x00009a28, 0x00000028, 0x00000028 }, + { 0x00009a2c, 0x00000068, 0x00000068 }, + { 0x00009a30, 0x00000189, 0x000000a8 }, + { 0x00009a34, 0x000001c9, 0x00000169 }, + { 0x00009a38, 0x00000009, 0x000001a9 }, + { 0x00009a3c, 0x00000049, 0x000001e9 }, + { 0x00009a40, 0x00000089, 0x00000029 }, + { 0x00009a44, 0x00000170, 0x00000069 }, + { 0x00009a48, 0x000001b0, 0x00000190 }, + { 0x00009a4c, 0x000001f0, 0x000001d0 }, + { 0x00009a50, 0x00000030, 0x00000010 }, + { 0x00009a54, 0x00000070, 0x00000050 }, + { 0x00009a58, 0x00000191, 0x00000090 }, + { 0x00009a5c, 0x000001d1, 0x00000151 }, + { 0x00009a60, 0x00000011, 0x00000191 }, + { 0x00009a64, 0x00000051, 0x000001d1 }, + { 0x00009a68, 0x00000091, 0x00000011 }, + { 0x00009a6c, 0x000001b8, 0x00000051 }, + { 0x00009a70, 0x000001f8, 0x00000198 }, + { 0x00009a74, 0x00000038, 0x000001d8 }, + { 0x00009a78, 0x00000078, 0x00000018 }, + { 0x00009a7c, 0x00000199, 0x00000058 }, + { 0x00009a80, 0x000001d9, 0x00000098 }, + { 0x00009a84, 0x00000019, 0x00000159 }, + { 0x00009a88, 0x00000059, 0x00000199 }, + { 0x00009a8c, 0x00000099, 0x000001d9 }, + { 0x00009a90, 0x000000d9, 0x00000019 }, + { 0x00009a94, 0x000000f9, 0x00000059 }, + { 0x00009a98, 0x000000f9, 0x00000099 }, + { 0x00009a9c, 0x000000f9, 0x000000d9 }, + { 0x00009aa0, 0x000000f9, 0x000000f9 }, + { 0x00009aa4, 0x000000f9, 0x000000f9 }, + { 0x00009aa8, 0x000000f9, 0x000000f9 }, + { 0x00009aac, 0x000000f9, 0x000000f9 }, + { 0x00009ab0, 0x000000f9, 0x000000f9 }, + { 0x00009ab4, 0x000000f9, 0x000000f9 }, + { 0x00009ab8, 0x000000f9, 0x000000f9 }, + { 0x00009abc, 0x000000f9, 0x000000f9 }, + { 0x00009ac0, 0x000000f9, 0x000000f9 }, + { 0x00009ac4, 0x000000f9, 0x000000f9 }, + { 0x00009ac8, 0x000000f9, 0x000000f9 }, + { 0x00009acc, 0x000000f9, 0x000000f9 }, + { 0x00009ad0, 0x000000f9, 0x000000f9 }, + { 0x00009ad4, 0x000000f9, 0x000000f9 }, + { 0x00009ad8, 0x000000f9, 0x000000f9 }, + { 0x00009adc, 0x000000f9, 0x000000f9 }, + { 0x00009ae0, 0x000000f9, 0x000000f9 }, + { 0x00009ae4, 0x000000f9, 0x000000f9 }, + { 0x00009ae8, 0x000000f9, 0x000000f9 }, + { 0x00009aec, 0x000000f9, 0x000000f9 }, + { 0x00009af0, 0x000000f9, 0x000000f9 }, + { 0x00009af4, 0x000000f9, 0x000000f9 }, + { 0x00009af8, 0x000000f9, 0x000000f9 }, + { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1_9160[][2] = { + { 0x000098b0, 0x02108421 }, + { 0x000098ec, 0x00000008 }, +}; + +static const u32 ar5416Bank2_9160[][2] = { + { 0x000098b0, 0x0e73ff17 }, + { 0x000098e0, 0x00000420 }, +}; + +static const u32 ar5416Bank3_9160[][3] = { + { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6_9160[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x004210a2, 0x004210a2 }, + { 0x0000989c, 0x0014008f, 0x0014008f }, + { 0x0000989c, 0x00c40003, 0x00c40003 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000f1, 0x000000f1 }, + { 0x0000989c, 0x00002081, 0x00002081 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank6TPC_9160[][3] = { + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00000000, 0x00000000 }, + { 0x0000989c, 0x00e00000, 0x00e00000 }, + { 0x0000989c, 0x005e0000, 0x005e0000 }, + { 0x0000989c, 0x00120000, 0x00120000 }, + { 0x0000989c, 0x00620000, 0x00620000 }, + { 0x0000989c, 0x00020000, 0x00020000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x40ff0000, 0x40ff0000 }, + { 0x0000989c, 0x005f0000, 0x005f0000 }, + { 0x0000989c, 0x00870000, 0x00870000 }, + { 0x0000989c, 0x00f90000, 0x00f90000 }, + { 0x0000989c, 0x007b0000, 0x007b0000 }, + { 0x0000989c, 0x00ff0000, 0x00ff0000 }, + { 0x0000989c, 0x00f50000, 0x00f50000 }, + { 0x0000989c, 0x00dc0000, 0x00dc0000 }, + { 0x0000989c, 0x00110000, 0x00110000 }, + { 0x0000989c, 0x006100a8, 0x006100a8 }, + { 0x0000989c, 0x00423022, 0x00423022 }, + { 0x0000989c, 0x2014008f, 0x2014008f }, + { 0x0000989c, 0x00c40002, 0x00c40002 }, + { 0x0000989c, 0x003000f2, 0x003000f2 }, + { 0x0000989c, 0x00440016, 0x00440016 }, + { 0x0000989c, 0x00410040, 0x00410040 }, + { 0x0000989c, 0x0001805e, 0x0001805e }, + { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, + { 0x0000989c, 0x000000e1, 0x000000e1 }, + { 0x0000989c, 0x00007080, 0x00007080 }, + { 0x0000989c, 0x000000d4, 0x000000d4 }, + { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7_9160[][2] = { + { 0x0000989c, 0x00000500 }, + { 0x0000989c, 0x00000800 }, + { 0x000098cc, 0x0000000e }, +}; + +static u32 ar5416Addac_9160[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000003 }, + {0x0000989c, 0x00000008 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +static u32 ar5416Addac_91601_1[][2] = { + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000018 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x000000c0 }, + {0x0000989c, 0x00000019 }, + {0x0000989c, 0x00000004 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x0000989c, 0x00000000 }, + {0x000098cc, 0x00000000 }, +}; + +/* XXX 9280 1 */ +static const u32 ar9280Modes_9280[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, + { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, + { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, + { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, + { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, + { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, + { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, + { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, + { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, + { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, + { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, + { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, + { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, + { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, + { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, + { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, + { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, + { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, + { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, + { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, + { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, + { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, + { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, + { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, + { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, + { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, + { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, +}; + +static const u32 ar9280Common_9280[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00007010, 0x00000033 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a82301a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c4, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x00008300, 0x00000000 }, + { 0x00008304, 0x00000000 }, + { 0x00008308, 0x00000000 }, + { 0x0000830c, 0x00000000 }, + { 0x00008310, 0x00000000 }, + { 0x00008314, 0x00000000 }, + { 0x00008318, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x00000000 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xaf268e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x00009840, 0x206a01ae }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0xe250a51e }, + { 0x00009958, 0x3388ffff }, + { 0x00009940, 0x00781204 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb514 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f00c4 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099fc, 0x00001042 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x23277200 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c889af }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000001 }, + { 0x0000a250, 0x001da000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce }, + { 0x0000a358, 0x7999aa0f }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f38081 }, + { 0x00007800, 0x00040000 }, + { 0x00007804, 0xdb005012 }, + { 0x00007808, 0x04924914 }, + { 0x0000780c, 0x21084210 }, + { 0x00007810, 0x6d801300 }, + { 0x00007814, 0x0019beff }, + { 0x00007818, 0x07e40000 }, + { 0x0000781c, 0x00492000 }, + { 0x00007820, 0x92492480 }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb005012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x6d801300 }, + { 0x00007838, 0x0019beff }, + { 0x0000783c, 0x07e40000 }, + { 0x00007840, 0x00492000 }, + { 0x00007844, 0x92492480 }, + { 0x00007848, 0x00120000 }, + { 0x00007850, 0x54214514 }, + { 0x00007858, 0x92592692 }, + { 0x00007860, 0x52802000 }, + { 0x00007864, 0x0a8e370e }, + { 0x00007868, 0xc0102850 }, + { 0x0000786c, 0x812d4000 }, + { 0x00007874, 0x001b6db0 }, + { 0x00007878, 0x00376b63 }, + { 0x0000787c, 0x06db6db6 }, + { 0x00007880, 0x006d8000 }, + { 0x00007884, 0xffeffffe }, + { 0x00007888, 0xffeffffe }, + { 0x00007890, 0x00060aeb }, + { 0x00007894, 0x5a108000 }, + { 0x00007898, 0x2a850160 }, +}; + +/* XXX 9280 2 */ +static const u32 ar9280Modes_9280_2[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, + { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, + { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, + { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e }, + { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, + { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, + { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, + { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, + { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, + { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, + { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, + { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, +}; + +static const u32 ar9280Common_9280_2[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020015 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000033 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x40000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000007 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x000107ff }, + { 0x00008344, 0x00581043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafa68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x0000a84c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x0000a920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009940, 0x14750604 }, + { 0x0000c95c, 0x004b6a8e }, + { 0x0000c968, 0x000003ce }, + { 0x00009970, 0x190fb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x006f0000 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x000099fc, 0x00001042 }, + { 0x0000a208, 0x803e4788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x40206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x233f7180 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a23c, 0x13c88000 }, + { 0x0000a240, 0x38490a20 }, + { 0x0000a244, 0x00007bb6 }, + { 0x0000a248, 0x0fff3ffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0cdbd380 }, + { 0x0000a25c, 0x0f0f0f01 }, + { 0x0000a260, 0xdfa91f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9c6 }, + { 0x0000b26c, 0x0ebae9c6 }, + { 0x0000d270, 0x00820820 }, + { 0x0000a278, 0x1ce739ce }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x1ce739ce }, + { 0x0000a398, 0x000001ce }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3c8, 0x00000246 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00040000 }, + { 0x00007804, 0xdb005012 }, + { 0x00007808, 0x04924914 }, + { 0x0000780c, 0x21084210 }, + { 0x00007810, 0x6d801300 }, + { 0x00007818, 0x07e41000 }, + { 0x00007824, 0x00040000 }, + { 0x00007828, 0xdb005012 }, + { 0x0000782c, 0x04924914 }, + { 0x00007830, 0x21084210 }, + { 0x00007834, 0x6d801300 }, + { 0x0000783c, 0x07e40000 }, + { 0x00007848, 0x00100000 }, + { 0x0000784c, 0x773f0567 }, + { 0x00007850, 0x54214514 }, + { 0x00007854, 0x12035828 }, + { 0x00007858, 0x9259269a }, + { 0x00007860, 0x52802000 }, + { 0x00007864, 0x0a8e370e }, + { 0x00007868, 0xc0102850 }, + { 0x0000786c, 0x812d4000 }, + { 0x00007870, 0x807ec400 }, + { 0x00007874, 0x001b6db0 }, + { 0x00007878, 0x00376b63 }, + { 0x0000787c, 0x06db6db6 }, + { 0x00007880, 0x006d8000 }, + { 0x00007884, 0xffeffffe }, + { 0x00007888, 0xffeffffe }, + { 0x0000788c, 0x00010000 }, + { 0x00007890, 0x02060aeb }, + { 0x00007898, 0x2a850160 }, +}; + +static const u32 ar9280Modes_fast_clock_9280_2[][3] = { + { 0x00001030, 0x00000268, 0x000004d0 }, + { 0x00001070, 0x0000018c, 0x00000318 }, + { 0x000010b0, 0x00000fd0, 0x00001fa0 }, + { 0x00008014, 0x044c044c, 0x08980898 }, + { 0x0000801c, 0x148ec02b, 0x148ec057 }, + { 0x00008318, 0x000044c0, 0x00008980 }, + { 0x00009820, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000f0f, 0x00000f0f }, + { 0x00009828, 0x0b020001, 0x0b020001 }, + { 0x00009834, 0x00000f0f, 0x00000f0f }, + { 0x00009844, 0x03721821, 0x03721821 }, + { 0x00009914, 0x00000898, 0x00001130 }, + { 0x00009918, 0x0000000b, 0x00000016 }, +}; + +static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, +}; + +static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, + { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, +}; + +static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { + { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, + { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, + { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, + { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, + { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, + { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, + { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, + { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, + { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, + { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, + { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, + { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, + { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, + { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, + { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, + { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, + { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, + { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, + { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, + { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, + { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, + { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, + { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, + { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, + { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, + { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, + { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, + { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, + { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, + { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, + { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, + { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, + { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, + { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, + { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, + { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, + { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, + { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, + { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, + { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, + { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, + { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, + { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, + { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, + { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, + { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, + { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, + { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, + { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, + { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, + { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, + { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, + { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, + { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, + { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, + { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, + { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, + { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, + { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, + { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, + { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, + { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, + { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, + { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, + { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, + { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, + { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, + { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, + { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, + { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, + { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, + { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, + { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, + { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, + { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, + { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, + { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, + { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, + { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, + { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, + { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, + { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, + { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, + { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, + { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, + { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, + { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, + { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, + { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, + { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, + { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, + { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, + { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, +}; + +static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, + { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, + { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, + { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, + { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, + { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, + { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, + { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, + { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, + { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, + { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, + { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, + { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, + { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, + { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, + { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, + { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, +}; + +static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, + { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, + { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, + { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, + { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, + { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, + { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, + { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, + { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, + { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, + { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, + { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, + { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, + { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, + { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, + { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, + { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, + { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, + { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, + { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, + { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, + { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, + { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, + { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, + { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, + { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, +}; + +static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +/* AR9285 */ +static const u_int32_t ar9285Modes_9285[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 }, + { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 }, + { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 }, + { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 }, + { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9285Common_9285[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000031 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04800 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0x00000000 }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x00003210 }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00000000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00581043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x1927b515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0a00 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e6788 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000a278, 0x39ce739c }, + { 0x0000a27c, 0x050e039c }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a394, 0x39ce739c }, + { 0x0000a398, 0x0000039c }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3dc, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025820 }, + { 0x00007810, 0x71c0d388 }, + { 0x00007814, 0x924934a8 }, + { 0x0000781c, 0x00000000 }, + { 0x00007820, 0x00000c04 }, + { 0x00007824, 0x00d86fff }, + { 0x00007828, 0x26d2491b }, + { 0x0000782c, 0x6e36d97b }, + { 0x00007830, 0xedb6d96c }, + { 0x00007834, 0x71400086 }, + { 0x00007838, 0xfac68800 }, + { 0x0000783c, 0x0001fffe }, + { 0x00007840, 0xffeb1a20 }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db61b6f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x0000786c, 0x48609eb4 }, + { 0x00007870, 0x10142c00 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +/* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */ +static const u_int32_t ar9285Modes_9285_1_2[][6] = { + { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, + { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, + { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, + { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, + { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, + { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, + { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, + { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, + { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, + { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, + { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, + { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, + { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, + { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, + { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, + { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, + { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, + { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, + { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, + { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, + { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, + { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, + { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, + { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, + { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, + { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, + { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, + { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, + { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, + { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, + { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, + { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, + { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, + { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, + { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, + { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, + { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, + { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, + { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, + { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, + { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, + { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, + { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, + { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, + { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, + { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, + { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, + { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, + { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, + { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, + { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, + { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, + { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, + { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, + { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, + { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, + { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, + { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, + { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, + { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, + { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, + { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, + { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, + { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, + { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, + { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, + { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, + { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, + { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, + { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, + { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, + { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, + { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, + { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, + { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, + { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, + { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, + { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, + { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, + { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, + { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, + { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, + { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, + { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, + { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, + { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, + { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, + { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, + { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, + { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, + { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, + { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, + { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, + { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, + { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, + { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, + { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, + { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, + { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, + { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, + { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, + { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, + { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, + { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, + { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, + { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, + { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, + { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, + { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, + { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, + { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, + { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, + { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, + { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, + { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, + { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, + { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, + { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, + { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, + { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, + { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, + { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, + { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, + { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, + { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, + { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, + { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, +}; + +static const u_int32_t ar9285Common_9285_1_2[][2] = { + { 0x0000000c, 0x00000000 }, + { 0x00000030, 0x00020045 }, + { 0x00000034, 0x00000005 }, + { 0x00000040, 0x00000000 }, + { 0x00000044, 0x00000008 }, + { 0x00000048, 0x00000008 }, + { 0x0000004c, 0x00000010 }, + { 0x00000050, 0x00000000 }, + { 0x00000054, 0x0000001f }, + { 0x00000800, 0x00000000 }, + { 0x00000804, 0x00000000 }, + { 0x00000808, 0x00000000 }, + { 0x0000080c, 0x00000000 }, + { 0x00000810, 0x00000000 }, + { 0x00000814, 0x00000000 }, + { 0x00000818, 0x00000000 }, + { 0x0000081c, 0x00000000 }, + { 0x00000820, 0x00000000 }, + { 0x00000824, 0x00000000 }, + { 0x00001040, 0x002ffc0f }, + { 0x00001044, 0x002ffc0f }, + { 0x00001048, 0x002ffc0f }, + { 0x0000104c, 0x002ffc0f }, + { 0x00001050, 0x002ffc0f }, + { 0x00001054, 0x002ffc0f }, + { 0x00001058, 0x002ffc0f }, + { 0x0000105c, 0x002ffc0f }, + { 0x00001060, 0x002ffc0f }, + { 0x00001064, 0x002ffc0f }, + { 0x00001230, 0x00000000 }, + { 0x00001270, 0x00000000 }, + { 0x00001038, 0x00000000 }, + { 0x00001078, 0x00000000 }, + { 0x000010b8, 0x00000000 }, + { 0x000010f8, 0x00000000 }, + { 0x00001138, 0x00000000 }, + { 0x00001178, 0x00000000 }, + { 0x000011b8, 0x00000000 }, + { 0x000011f8, 0x00000000 }, + { 0x00001238, 0x00000000 }, + { 0x00001278, 0x00000000 }, + { 0x000012b8, 0x00000000 }, + { 0x000012f8, 0x00000000 }, + { 0x00001338, 0x00000000 }, + { 0x00001378, 0x00000000 }, + { 0x000013b8, 0x00000000 }, + { 0x000013f8, 0x00000000 }, + { 0x00001438, 0x00000000 }, + { 0x00001478, 0x00000000 }, + { 0x000014b8, 0x00000000 }, + { 0x000014f8, 0x00000000 }, + { 0x00001538, 0x00000000 }, + { 0x00001578, 0x00000000 }, + { 0x000015b8, 0x00000000 }, + { 0x000015f8, 0x00000000 }, + { 0x00001638, 0x00000000 }, + { 0x00001678, 0x00000000 }, + { 0x000016b8, 0x00000000 }, + { 0x000016f8, 0x00000000 }, + { 0x00001738, 0x00000000 }, + { 0x00001778, 0x00000000 }, + { 0x000017b8, 0x00000000 }, + { 0x000017f8, 0x00000000 }, + { 0x0000103c, 0x00000000 }, + { 0x0000107c, 0x00000000 }, + { 0x000010bc, 0x00000000 }, + { 0x000010fc, 0x00000000 }, + { 0x0000113c, 0x00000000 }, + { 0x0000117c, 0x00000000 }, + { 0x000011bc, 0x00000000 }, + { 0x000011fc, 0x00000000 }, + { 0x0000123c, 0x00000000 }, + { 0x0000127c, 0x00000000 }, + { 0x000012bc, 0x00000000 }, + { 0x000012fc, 0x00000000 }, + { 0x0000133c, 0x00000000 }, + { 0x0000137c, 0x00000000 }, + { 0x000013bc, 0x00000000 }, + { 0x000013fc, 0x00000000 }, + { 0x0000143c, 0x00000000 }, + { 0x0000147c, 0x00000000 }, + { 0x00004030, 0x00000002 }, + { 0x0000403c, 0x00000002 }, + { 0x00004024, 0x0000001f }, + { 0x00004060, 0x00000000 }, + { 0x00004064, 0x00000000 }, + { 0x00007010, 0x00000031 }, + { 0x00007034, 0x00000002 }, + { 0x00007038, 0x000004c2 }, + { 0x00008004, 0x00000000 }, + { 0x00008008, 0x00000000 }, + { 0x0000800c, 0x00000000 }, + { 0x00008018, 0x00000700 }, + { 0x00008020, 0x00000000 }, + { 0x00008038, 0x00000000 }, + { 0x0000803c, 0x00000000 }, + { 0x00008048, 0x00000000 }, + { 0x00008054, 0x00000000 }, + { 0x00008058, 0x00000000 }, + { 0x0000805c, 0x000fc78f }, + { 0x00008060, 0x0000000f }, + { 0x00008064, 0x00000000 }, + { 0x00008070, 0x00000000 }, + { 0x000080c0, 0x2a80001a }, + { 0x000080c4, 0x05dc01e0 }, + { 0x000080c8, 0x1f402710 }, + { 0x000080cc, 0x01f40000 }, + { 0x000080d0, 0x00001e00 }, + { 0x000080d4, 0x00000000 }, + { 0x000080d8, 0x00400000 }, + { 0x000080e0, 0xffffffff }, + { 0x000080e4, 0x0000ffff }, + { 0x000080e8, 0x003f3f3f }, + { 0x000080ec, 0x00000000 }, + { 0x000080f0, 0x00000000 }, + { 0x000080f4, 0x00000000 }, + { 0x000080f8, 0x00000000 }, + { 0x000080fc, 0x00020000 }, + { 0x00008100, 0x00020000 }, + { 0x00008104, 0x00000001 }, + { 0x00008108, 0x00000052 }, + { 0x0000810c, 0x00000000 }, + { 0x00008110, 0x00000168 }, + { 0x00008118, 0x000100aa }, + { 0x0000811c, 0x00003210 }, + { 0x00008120, 0x08f04810 }, + { 0x00008124, 0x00000000 }, + { 0x00008128, 0x00000000 }, + { 0x0000812c, 0x00000000 }, + { 0x00008130, 0x00000000 }, + { 0x00008134, 0x00000000 }, + { 0x00008138, 0x00000000 }, + { 0x0000813c, 0x00000000 }, + { 0x00008144, 0xffffffff }, + { 0x00008168, 0x00000000 }, + { 0x0000816c, 0x00000000 }, + { 0x00008170, 0x32143320 }, + { 0x00008174, 0xfaa4fa50 }, + { 0x00008178, 0x00000100 }, + { 0x0000817c, 0x00000000 }, + { 0x000081c0, 0x00000000 }, + { 0x000081d0, 0x0000320a }, + { 0x000081ec, 0x00000000 }, + { 0x000081f0, 0x00000000 }, + { 0x000081f4, 0x00000000 }, + { 0x000081f8, 0x00000000 }, + { 0x000081fc, 0x00000000 }, + { 0x00008200, 0x00000000 }, + { 0x00008204, 0x00000000 }, + { 0x00008208, 0x00000000 }, + { 0x0000820c, 0x00000000 }, + { 0x00008210, 0x00000000 }, + { 0x00008214, 0x00000000 }, + { 0x00008218, 0x00000000 }, + { 0x0000821c, 0x00000000 }, + { 0x00008220, 0x00000000 }, + { 0x00008224, 0x00000000 }, + { 0x00008228, 0x00000000 }, + { 0x0000822c, 0x00000000 }, + { 0x00008230, 0x00000000 }, + { 0x00008234, 0x00000000 }, + { 0x00008238, 0x00000000 }, + { 0x0000823c, 0x00000000 }, + { 0x00008240, 0x00100000 }, + { 0x00008244, 0x0010f400 }, + { 0x00008248, 0x00000100 }, + { 0x0000824c, 0x0001e800 }, + { 0x00008250, 0x00000000 }, + { 0x00008254, 0x00000000 }, + { 0x00008258, 0x00000000 }, + { 0x0000825c, 0x400000ff }, + { 0x00008260, 0x00080922 }, + { 0x00008264, 0xa8a00010 }, + { 0x00008270, 0x00000000 }, + { 0x00008274, 0x40000000 }, + { 0x00008278, 0x003e4180 }, + { 0x0000827c, 0x00000000 }, + { 0x00008284, 0x0000002c }, + { 0x00008288, 0x0000002c }, + { 0x0000828c, 0x00000000 }, + { 0x00008294, 0x00000000 }, + { 0x00008298, 0x00000000 }, + { 0x0000829c, 0x00000000 }, + { 0x00008300, 0x00000040 }, + { 0x00008314, 0x00000000 }, + { 0x00008328, 0x00000000 }, + { 0x0000832c, 0x00000001 }, + { 0x00008330, 0x00000302 }, + { 0x00008334, 0x00000e00 }, + { 0x00008338, 0x00ff0000 }, + { 0x0000833c, 0x00000000 }, + { 0x00008340, 0x00010380 }, + { 0x00008344, 0x00581043 }, + { 0x00009808, 0x00000000 }, + { 0x0000980c, 0xafe68e30 }, + { 0x00009810, 0xfd14e000 }, + { 0x00009814, 0x9c0a9f6b }, + { 0x0000981c, 0x00000000 }, + { 0x0000982c, 0x0000a000 }, + { 0x00009830, 0x00000000 }, + { 0x0000983c, 0x00200400 }, + { 0x0000984c, 0x0040233c }, + { 0x00009854, 0x00000044 }, + { 0x00009900, 0x00000000 }, + { 0x00009904, 0x00000000 }, + { 0x00009908, 0x00000000 }, + { 0x0000990c, 0x00000000 }, + { 0x00009910, 0x01002310 }, + { 0x0000991c, 0x10000fff }, + { 0x00009920, 0x04900000 }, + { 0x00009928, 0x00000001 }, + { 0x0000992c, 0x00000004 }, + { 0x00009934, 0x1e1f2022 }, + { 0x00009938, 0x0a0b0c0d }, + { 0x0000993c, 0x00000000 }, + { 0x00009940, 0x14750604 }, + { 0x00009948, 0x9280c00a }, + { 0x0000994c, 0x00020028 }, + { 0x00009954, 0x5f3ca3de }, + { 0x00009958, 0x2108ecff }, + { 0x00009968, 0x000003ce }, + { 0x00009970, 0x192bb515 }, + { 0x00009974, 0x00000000 }, + { 0x00009978, 0x00000001 }, + { 0x0000997c, 0x00000000 }, + { 0x00009980, 0x00000000 }, + { 0x00009984, 0x00000000 }, + { 0x00009988, 0x00000000 }, + { 0x0000998c, 0x00000000 }, + { 0x00009990, 0x00000000 }, + { 0x00009994, 0x00000000 }, + { 0x00009998, 0x00000000 }, + { 0x0000999c, 0x00000000 }, + { 0x000099a0, 0x00000000 }, + { 0x000099a4, 0x00000001 }, + { 0x000099a8, 0x201fff00 }, + { 0x000099ac, 0x2def0400 }, + { 0x000099b0, 0x03051000 }, + { 0x000099b4, 0x00000820 }, + { 0x000099dc, 0x00000000 }, + { 0x000099e0, 0x00000000 }, + { 0x000099e4, 0xaaaaaaaa }, + { 0x000099e8, 0x3c466478 }, + { 0x000099ec, 0x0cc80caa }, + { 0x000099f0, 0x00000000 }, + { 0x0000a208, 0x803e68c8 }, + { 0x0000a210, 0x4080a333 }, + { 0x0000a214, 0x00206c10 }, + { 0x0000a218, 0x009c4060 }, + { 0x0000a220, 0x01834061 }, + { 0x0000a224, 0x00000400 }, + { 0x0000a228, 0x000003b5 }, + { 0x0000a22c, 0x00000000 }, + { 0x0000a234, 0x20202020 }, + { 0x0000a238, 0x20202020 }, + { 0x0000a244, 0x00000000 }, + { 0x0000a248, 0xfffffffc }, + { 0x0000a24c, 0x00000000 }, + { 0x0000a254, 0x00000000 }, + { 0x0000a258, 0x0ccb5380 }, + { 0x0000a25c, 0x15151501 }, + { 0x0000a260, 0xdfa90f01 }, + { 0x0000a268, 0x00000000 }, + { 0x0000a26c, 0x0ebae9e6 }, + { 0x0000d270, 0x0d820820 }, + { 0x0000d35c, 0x07ffffef }, + { 0x0000d360, 0x0fffffe7 }, + { 0x0000d364, 0x17ffffe5 }, + { 0x0000d368, 0x1fffffe4 }, + { 0x0000d36c, 0x37ffffe3 }, + { 0x0000d370, 0x3fffffe3 }, + { 0x0000d374, 0x57ffffe3 }, + { 0x0000d378, 0x5fffffe2 }, + { 0x0000d37c, 0x7fffffe2 }, + { 0x0000d380, 0x7f3c7bba }, + { 0x0000d384, 0xf3307ff0 }, + { 0x0000a388, 0x0c000000 }, + { 0x0000a38c, 0x20202020 }, + { 0x0000a390, 0x20202020 }, + { 0x0000a39c, 0x00000001 }, + { 0x0000a3a0, 0x00000000 }, + { 0x0000a3a4, 0x00000000 }, + { 0x0000a3a8, 0x00000000 }, + { 0x0000a3ac, 0x00000000 }, + { 0x0000a3b0, 0x00000000 }, + { 0x0000a3b4, 0x00000000 }, + { 0x0000a3b8, 0x00000000 }, + { 0x0000a3bc, 0x00000000 }, + { 0x0000a3c0, 0x00000000 }, + { 0x0000a3c4, 0x00000000 }, + { 0x0000a3cc, 0x20202020 }, + { 0x0000a3d0, 0x20202020 }, + { 0x0000a3d4, 0x20202020 }, + { 0x0000a3e4, 0x00000000 }, + { 0x0000a3e8, 0x18c43433 }, + { 0x0000a3ec, 0x00f70081 }, + { 0x00007800, 0x00140000 }, + { 0x00007804, 0x0e4548d8 }, + { 0x00007808, 0x54214514 }, + { 0x0000780c, 0x02025820 }, + { 0x00007810, 0x71c0d388 }, + { 0x00007814, 0x924934a8 }, + { 0x0000781c, 0x00000000 }, + { 0x00007824, 0x00d86fff }, + { 0x00007828, 0x26d2491b }, + { 0x0000782c, 0x6e36d97b }, + { 0x00007830, 0xedb6d96e }, + { 0x00007834, 0x71400087 }, + { 0x0000783c, 0x0001fffe }, + { 0x00007840, 0xffeb1a20 }, + { 0x00007844, 0x000c0db6 }, + { 0x00007848, 0x6db61b6f }, + { 0x0000784c, 0x6d9b66db }, + { 0x00007850, 0x6d8c6dba }, + { 0x00007854, 0x00040000 }, + { 0x00007858, 0xdb003012 }, + { 0x0000785c, 0x04924914 }, + { 0x00007860, 0x21084210 }, + { 0x00007864, 0xf7d7ffde }, + { 0x00007868, 0xc2034080 }, + { 0x00007870, 0x10142c00 }, +}; + +static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, + { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, + { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, + { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, + { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, + { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, + { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, + { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, + { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, +}; + +static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { + /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ + { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, + { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, + { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, + { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, + { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, + { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, + { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, + { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, + { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, + { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, + { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, + { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, + { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, + { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, + { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, + { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, + { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, + { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, + { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, + { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, + { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, + { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, + { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, + { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffd }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; + +static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { + {0x00004040, 0x9248fd00 }, + {0x00004040, 0x24924924 }, + {0x00004040, 0xa8000019 }, + {0x00004040, 0x13160820 }, + {0x00004040, 0xe5980560 }, + {0x00004040, 0xc01dcffc }, + {0x00004040, 0x1aaabe41 }, + {0x00004040, 0xbe105554 }, + {0x00004040, 0x00043007 }, + {0x00004044, 0x00000000 }, +}; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c new file mode 100644 index 000000000000..8ae4ec21667b --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -0,0 +1,976 @@ +/* + * 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 "ath9k.h" + +static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, + struct ath9k_tx_queue_info *qi) +{ + DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, + "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", + ah->txok_interrupt_mask, ah->txerr_interrupt_mask, + ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, + ah->txurn_interrupt_mask); + + REG_WRITE(ah, AR_IMR_S0, + SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) + | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); + REG_WRITE(ah, AR_IMR_S1, + SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) + | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); + REG_RMW_FIELD(ah, AR_IMR_S2, + AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask); +} + +u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) +{ + return REG_READ(ah, AR_QTXDP(q)); +} + +bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) +{ + REG_WRITE(ah, AR_QTXDP(q), txdp); + + return true; +} + +bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) +{ + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); + + REG_WRITE(ah, AR_Q_TXE, 1 << q); + + return true; +} + +u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) +{ + u32 npend; + + npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; + if (npend == 0) { + + if (REG_READ(ah, AR_Q_TXE) & (1 << q)) + npend = 1; + } + + return npend; +} + +bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) +{ + u32 txcfg, curLevel, newLevel; + enum ath9k_int omask; + + if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) + return false; + + omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); + + txcfg = REG_READ(ah, AR_TXCFG); + curLevel = MS(txcfg, AR_FTRIG); + newLevel = curLevel; + if (bIncTrigLevel) { + if (curLevel < MAX_TX_FIFO_THRESHOLD) + newLevel++; + } else if (curLevel > MIN_TX_FIFO_THRESHOLD) + newLevel--; + if (newLevel != curLevel) + REG_WRITE(ah, AR_TXCFG, + (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); + + ath9k_hw_set_interrupts(ah, omask); + + ah->tx_trig_level = newLevel; + + return newLevel != curLevel; +} + +bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) +{ +#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ +#define ATH9K_TIME_QUANTUM 100 /* usec */ + + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath9k_tx_queue_info *qi; + u32 tsfLow, j, wait; + u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " + "invalid queue: %u\n", q); + return false; + } + + qi = &ah->txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " + "inactive queue: %u\n", q); + return false; + } + + REG_WRITE(ah, AR_Q_TXD, 1 << q); + + for (wait = wait_time; wait != 0; wait--) { + if (ath9k_hw_numtxpending(ah, q) == 0) + break; + udelay(ATH9K_TIME_QUANTUM); + } + + if (ath9k_hw_numtxpending(ah, q)) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ath9k_hw_numtxpending(ah, q), q); + + for (j = 0; j < 2; j++) { + tsfLow = REG_READ(ah, AR_TSF_L32); + REG_WRITE(ah, AR_QUIET2, + SM(10, AR_QUIET2_QUIET_DUR)); + REG_WRITE(ah, AR_QUIET_PERIOD, 100); + REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); + REG_SET_BIT(ah, AR_TIMER_MODE, + AR_QUIET_TIMER_EN); + + if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) + break; + + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + "TSF has moved while trying to set " + "quiet time TSF: 0x%08x\n", tsfLow); + } + + REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); + + udelay(200); + REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); + + wait = wait_time; + while (ath9k_hw_numtxpending(ah, q)) { + if ((--wait) == 0) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + "Failed to stop TX DMA in 100 " + "msec after killing last frame\n"); + break; + } + udelay(ATH9K_TIME_QUANTUM); + } + + REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); + } + + REG_WRITE(ah, AR_Q_TXD, 0); + return wait != 0; + +#undef ATH9K_TX_STOP_DMA_TIMEOUT +#undef ATH9K_TIME_QUANTUM +} + +bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 segLen, bool firstSeg, + bool lastSeg, const struct ath_desc *ds0) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (firstSeg) { + ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); + } else if (lastSeg) { + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen; + ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; + ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; + } else { + ads->ds_ctl0 = 0; + ads->ds_ctl1 = segLen | AR_TxMore; + ads->ds_ctl2 = 0; + ads->ds_ctl3 = 0; + } + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + ads->ds_txstatus2 = ads->ds_txstatus3 = 0; + ads->ds_txstatus4 = ads->ds_txstatus5 = 0; + ads->ds_txstatus6 = ads->ds_txstatus7 = 0; + ads->ds_txstatus8 = ads->ds_txstatus9 = 0; + + return true; +} + +void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_txstatus0 = ads->ds_txstatus1 = 0; + ads->ds_txstatus2 = ads->ds_txstatus3 = 0; + ads->ds_txstatus4 = ads->ds_txstatus5 = 0; + ads->ds_txstatus6 = ads->ds_txstatus7 = 0; + ads->ds_txstatus8 = ads->ds_txstatus9 = 0; +} + +int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if ((ads->ds_txstatus9 & AR_TxDone) == 0) + return -EINPROGRESS; + + ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); + ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; + ds->ds_txstat.ts_status = 0; + ds->ds_txstat.ts_flags = 0; + + if (ads->ds_txstatus1 & AR_ExcessiveRetries) + ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; + if (ads->ds_txstatus1 & AR_Filtered) + ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; + if (ads->ds_txstatus1 & AR_FIFOUnderrun) { + ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->ds_txstatus9 & AR_TxOpExceeded) + ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; + if (ads->ds_txstatus1 & AR_TxTimerExpired) + ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; + + if (ads->ds_txstatus1 & AR_DescCfgErr) + ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; + if (ads->ds_txstatus1 & AR_TxDataUnderrun) { + ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { + ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; + ath9k_hw_updatetxtriglevel(ah, true); + } + if (ads->ds_txstatus0 & AR_TxBaStatus) { + ds->ds_txstat.ts_flags |= ATH9K_TX_BA; + ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; + ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; + } + + ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); + switch (ds->ds_txstat.ts_rateindex) { + case 0: + ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); + break; + case 1: + ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); + break; + case 2: + ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); + break; + case 3: + ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); + break; + } + + ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); + ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); + ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); + ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); + ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); + ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); + ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); + ds->ds_txstat.evm0 = ads->AR_TxEVM0; + ds->ds_txstat.evm1 = ads->AR_TxEVM1; + ds->ds_txstat.evm2 = ads->AR_TxEVM2; + ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); + ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); + ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); + ds->ds_txstat.ts_antenna = 0; + + return 0; +} + +void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 pktLen, enum ath9k_pkt_type type, u32 txPower, + u32 keyIx, enum ath9k_key_type keyType, u32 flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + txPower += ah->txpower_indexoffset; + if (txPower > 63) + txPower = 63; + + ads->ds_ctl0 = (pktLen & AR_FrameLen) + | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) + | SM(txPower, AR_XmitPower) + | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) + | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) + | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) + | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); + + ads->ds_ctl1 = + (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) + | SM(type, AR_FrameType) + | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) + | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) + | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); + + ads->ds_ctl6 = SM(keyType, AR_EncrType); + + if (AR_SREV_9285(ah)) { + ads->ds_ctl8 = 0; + ads->ds_ctl9 = 0; + ads->ds_ctl10 = 0; + ads->ds_ctl11 = 0; + } +} + +void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, + struct ath_desc *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + struct ar5416_desc *last_ads = AR5416DESC(lastds); + u32 ds_ctl0; + + if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { + ds_ctl0 = ads->ds_ctl0; + + if (flags & ATH9K_TXDESC_RTSENA) { + ds_ctl0 &= ~AR_CTSEnable; + ds_ctl0 |= AR_RTSEnable; + } else { + ds_ctl0 &= ~AR_RTSEnable; + ds_ctl0 |= AR_CTSEnable; + } + + ads->ds_ctl0 = ds_ctl0; + } else { + ads->ds_ctl0 = + (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); + } + + ads->ds_ctl2 = set11nTries(series, 0) + | set11nTries(series, 1) + | set11nTries(series, 2) + | set11nTries(series, 3) + | (durUpdateEn ? AR_DurUpdateEna : 0) + | SM(0, AR_BurstDur); + + ads->ds_ctl3 = set11nRate(series, 0) + | set11nRate(series, 1) + | set11nRate(series, 2) + | set11nRate(series, 3); + + ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) + | set11nPktDurRTSCTS(series, 1); + + ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) + | set11nPktDurRTSCTS(series, 3); + + ads->ds_ctl7 = set11nRateFlags(series, 0) + | set11nRateFlags(series, 1) + | set11nRateFlags(series, 2) + | set11nRateFlags(series, 3) + | SM(rtsctsRate, AR_RTSCTSRate); + last_ads->ds_ctl2 = ads->ds_ctl2; + last_ads->ds_ctl3 = ads->ds_ctl3; +} + +void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, + u32 aggrLen) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + ads->ds_ctl6 &= ~AR_AggrLen; + ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); +} + +void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, + u32 numDelims) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + unsigned int ctl6; + + ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + + ctl6 = ads->ds_ctl6; + ctl6 &= ~AR_PadDelim; + ctl6 |= SM(numDelims, AR_PadDelim); + ads->ds_ctl6 = ctl6; +} + +void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 |= AR_IsAggr; + ads->ds_ctl1 &= ~AR_MoreAggr; + ads->ds_ctl6 &= ~AR_PadDelim; +} + +void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); +} + +void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, + u32 burstDuration) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + ads->ds_ctl2 &= ~AR_BurstDur; + ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); +} + +void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, + u32 vmf) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + + if (vmf) + ads->ds_ctl0 |= AR_VirtMoreFrag; + else + ads->ds_ctl0 &= ~AR_VirtMoreFrag; +} + +void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) +{ + *txqs &= ah->intr_txqs; + ah->intr_txqs &= ~(*txqs); +} + +bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, + const struct ath9k_tx_queue_info *qinfo) +{ + u32 cw; + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath9k_tx_queue_info *qi; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " + "invalid queue: %u\n", q); + return false; + } + + qi = &ah->txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " + "inactive queue: %u\n", q); + return false; + } + + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); + + qi->tqi_ver = qinfo->tqi_ver; + qi->tqi_subtype = qinfo->tqi_subtype; + qi->tqi_qflags = qinfo->tqi_qflags; + qi->tqi_priority = qinfo->tqi_priority; + if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT) + qi->tqi_aifs = min(qinfo->tqi_aifs, 255U); + else + qi->tqi_aifs = INIT_AIFS; + if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) { + cw = min(qinfo->tqi_cwmin, 1024U); + qi->tqi_cwmin = 1; + while (qi->tqi_cwmin < cw) + qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; + } else + qi->tqi_cwmin = qinfo->tqi_cwmin; + if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) { + cw = min(qinfo->tqi_cwmax, 1024U); + qi->tqi_cwmax = 1; + while (qi->tqi_cwmax < cw) + qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; + } else + qi->tqi_cwmax = INIT_CWMAX; + + if (qinfo->tqi_shretry != 0) + qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U); + else + qi->tqi_shretry = INIT_SH_RETRY; + if (qinfo->tqi_lgretry != 0) + qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U); + else + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod; + qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit; + qi->tqi_burstTime = qinfo->tqi_burstTime; + qi->tqi_readyTime = qinfo->tqi_readyTime; + + switch (qinfo->tqi_subtype) { + case ATH9K_WME_UPSD: + if (qi->tqi_type == ATH9K_TX_QUEUE_DATA) + qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS; + break; + default: + break; + } + + return true; +} + +bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, + struct ath9k_tx_queue_info *qinfo) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath9k_tx_queue_info *qi; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " + "invalid queue: %u\n", q); + return false; + } + + qi = &ah->txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " + "inactive queue: %u\n", q); + return false; + } + + qinfo->tqi_qflags = qi->tqi_qflags; + qinfo->tqi_ver = qi->tqi_ver; + qinfo->tqi_subtype = qi->tqi_subtype; + qinfo->tqi_qflags = qi->tqi_qflags; + qinfo->tqi_priority = qi->tqi_priority; + qinfo->tqi_aifs = qi->tqi_aifs; + qinfo->tqi_cwmin = qi->tqi_cwmin; + qinfo->tqi_cwmax = qi->tqi_cwmax; + qinfo->tqi_shretry = qi->tqi_shretry; + qinfo->tqi_lgretry = qi->tqi_lgretry; + qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; + qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; + qinfo->tqi_burstTime = qi->tqi_burstTime; + qinfo->tqi_readyTime = qi->tqi_readyTime; + + return true; +} + +int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, + const struct ath9k_tx_queue_info *qinfo) +{ + struct ath9k_tx_queue_info *qi; + struct ath9k_hw_capabilities *pCap = &ah->caps; + int q; + + switch (type) { + case ATH9K_TX_QUEUE_BEACON: + q = pCap->total_queues - 1; + break; + case ATH9K_TX_QUEUE_CAB: + q = pCap->total_queues - 2; + break; + case ATH9K_TX_QUEUE_PSPOLL: + q = 1; + break; + case ATH9K_TX_QUEUE_UAPSD: + q = pCap->total_queues - 3; + break; + case ATH9K_TX_QUEUE_DATA: + for (q = 0; q < pCap->total_queues; q++) + if (ah->txq[q].tqi_type == + ATH9K_TX_QUEUE_INACTIVE) + break; + if (q == pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "No available TX queue\n"); + return -1; + } + break; + default: + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", + type); + return -1; + } + + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); + + qi = &ah->txq[q]; + if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "TX queue: %u already active\n", q); + return -1; + } + memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); + qi->tqi_type = type; + if (qinfo == NULL) { + qi->tqi_qflags = + TXQ_FLAG_TXOKINT_ENABLE + | TXQ_FLAG_TXERRINT_ENABLE + | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; + qi->tqi_aifs = INIT_AIFS; + qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; + qi->tqi_cwmax = INIT_CWMAX; + qi->tqi_shretry = INIT_SH_RETRY; + qi->tqi_lgretry = INIT_LG_RETRY; + qi->tqi_physCompBuf = 0; + } else { + qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; + (void) ath9k_hw_set_txq_props(ah, q, qinfo); + } + + return q; +} + +bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath9k_tx_queue_info *qi; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " + "invalid queue: %u\n", q); + return false; + } + qi = &ah->txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " + "inactive queue: %u\n", q); + return false; + } + + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); + + qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; + ah->txok_interrupt_mask &= ~(1 << q); + ah->txerr_interrupt_mask &= ~(1 << q); + ah->txdesc_interrupt_mask &= ~(1 << q); + ah->txeol_interrupt_mask &= ~(1 << q); + ah->txurn_interrupt_mask &= ~(1 << q); + ath9k_hw_set_txq_interrupts(ah, qi); + + return true; +} + +bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) +{ + struct ath9k_hw_capabilities *pCap = &ah->caps; + struct ath9k_channel *chan = ah->curchan; + struct ath9k_tx_queue_info *qi; + u32 cwMin, chanCwMin, value; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " + "invalid queue: %u\n", q); + return false; + } + + qi = &ah->txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " + "inactive queue: %u\n", q); + return true; + } + + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); + + if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { + if (chan && IS_CHAN_B(chan)) + chanCwMin = INIT_CWMIN_11B; + else + chanCwMin = INIT_CWMIN; + + for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); + } else + cwMin = qi->tqi_cwmin; + + REG_WRITE(ah, AR_DLCL_IFS(q), + SM(cwMin, AR_D_LCL_IFS_CWMIN) | + SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | + SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); + + REG_WRITE(ah, AR_DRETRY_LIMIT(q), + SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | + SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | + SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); + + REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); + REG_WRITE(ah, AR_DMISC(q), + AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); + + if (qi->tqi_cbrPeriod) { + REG_WRITE(ah, AR_QCBRCFG(q), + SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | + SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); + REG_WRITE(ah, AR_QMISC(q), + REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | + (qi->tqi_cbrOverflowLimit ? + AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); + } + if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { + REG_WRITE(ah, AR_QRDYTIMECFG(q), + SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | + AR_Q_RDYTIMECFG_EN); + } + + REG_WRITE(ah, AR_DCHNTIME(q), + SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | + (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); + + if (qi->tqi_burstTime + && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { + REG_WRITE(ah, AR_QMISC(q), + REG_READ(ah, AR_QMISC(q)) | + AR_Q_MISC_RDYTIME_EXP_POLICY); + + } + + if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { + REG_WRITE(ah, AR_DMISC(q), + REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_POST_FR_BKOFF_DIS); + } + if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { + REG_WRITE(ah, AR_DMISC(q), + REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_FRAG_BKOFF_EN); + } + switch (qi->tqi_type) { + case ATH9K_TX_QUEUE_BEACON: + REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_BEACON_USE + | AR_Q_MISC_CBR_INCR_DIS1); + + REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) + | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << + AR_D_MISC_ARB_LOCKOUT_CNTRL_S) + | AR_D_MISC_BEACON_USE + | AR_D_MISC_POST_FR_BKOFF_DIS); + break; + case ATH9K_TX_QUEUE_CAB: + REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) + | AR_Q_MISC_FSP_DBA_GATED + | AR_Q_MISC_CBR_INCR_DIS1 + | AR_Q_MISC_CBR_INCR_DIS0); + value = (qi->tqi_readyTime - + (ah->config.sw_beacon_response_time - + ah->config.dma_beacon_response_time) - + ah->config.additional_swba_backoff) * 1024; + REG_WRITE(ah, AR_QRDYTIMECFG(q), + value | AR_Q_RDYTIMECFG_EN); + REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) + | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << + AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); + break; + case ATH9K_TX_QUEUE_PSPOLL: + REG_WRITE(ah, AR_QMISC(q), + REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); + break; + case ATH9K_TX_QUEUE_UAPSD: + REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | + AR_D_MISC_POST_FR_BKOFF_DIS); + break; + default: + break; + } + + if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { + REG_WRITE(ah, AR_DMISC(q), + REG_READ(ah, AR_DMISC(q)) | + SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, + AR_D_MISC_ARB_LOCKOUT_CNTRL) | + AR_D_MISC_POST_FR_BKOFF_DIS); + } + + if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) + ah->txok_interrupt_mask |= 1 << q; + else + ah->txok_interrupt_mask &= ~(1 << q); + if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE) + ah->txerr_interrupt_mask |= 1 << q; + else + ah->txerr_interrupt_mask &= ~(1 << q); + if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) + ah->txdesc_interrupt_mask |= 1 << q; + else + ah->txdesc_interrupt_mask &= ~(1 << q); + if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) + ah->txeol_interrupt_mask |= 1 << q; + else + ah->txeol_interrupt_mask &= ~(1 << q); + if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) + ah->txurn_interrupt_mask |= 1 << q; + else + ah->txurn_interrupt_mask &= ~(1 << q); + ath9k_hw_set_txq_interrupts(ah, qi); + + return true; +} + +int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 pa, struct ath_desc *nds, u64 tsf) +{ + struct ar5416_desc ads; + struct ar5416_desc *adsp = AR5416DESC(ds); + u32 phyerr; + + if ((adsp->ds_rxstatus8 & AR_RxDone) == 0) + return -EINPROGRESS; + + ads.u.rx = adsp->u.rx; + + ds->ds_rxstat.rs_status = 0; + ds->ds_rxstat.rs_flags = 0; + + ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; + ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; + + ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); + ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); + ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); + ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); + ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); + ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); + ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); + if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) + ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); + else + ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; + + ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); + ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; + + ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; + ds->ds_rxstat.rs_moreaggr = + (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; + ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); + ds->ds_rxstat.rs_flags = + (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; + ds->ds_rxstat.rs_flags |= + (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; + + if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) + ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; + if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) + ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; + if (ads.ds_rxstatus8 & AR_DecryptBusyErr) + ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; + + if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { + if (ads.ds_rxstatus8 & AR_CRCErr) + ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; + else if (ads.ds_rxstatus8 & AR_PHYErr) { + ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; + phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); + ds->ds_rxstat.rs_phyerr = phyerr; + } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) + ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; + else if (ads.ds_rxstatus8 & AR_MichaelErr) + ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; + } + + return 0; +} + +bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 size, u32 flags) +{ + struct ar5416_desc *ads = AR5416DESC(ds); + struct ath9k_hw_capabilities *pCap = &ah->caps; + + ads->ds_ctl1 = size & AR_BufLen; + if (flags & ATH9K_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxIntrReq; + + ads->ds_rxstatus8 &= ~AR_RxDone; + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) + memset(&(ads->u), 0, sizeof(ads->u)); + + return true; +} + +bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) +{ + u32 reg; + + if (set) { + REG_SET_BIT(ah, AR_DIAG_SW, + (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + + if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, + 0, AH_WAIT_TIMEOUT)) { + REG_CLR_BIT(ah, AR_DIAG_SW, + (AR_DIAG_RX_DIS | + AR_DIAG_RX_ABORT)); + + reg = REG_READ(ah, AR_OBS_BUS_1); + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); + + return false; + } + } else { + REG_CLR_BIT(ah, AR_DIAG_SW, + (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + } + + return true; +} + +void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) +{ + REG_WRITE(ah, AR_RXDP, rxdp); +} + +void ath9k_hw_rxena(struct ath_hw *ah) +{ + REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +void ath9k_hw_startpcureceive(struct ath_hw *ah) +{ + ath9k_enable_mib_counters(ah); + + ath9k_ani_reset(ah); + + REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); +} + +void ath9k_hw_stoppcurecv(struct ath_hw *ah) +{ + REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); + + ath9k_hw_disable_mib_counters(ah); +} + +bool ath9k_hw_stopdmarecv(struct ath_hw *ah) +{ +#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ +#define AH_RX_TIME_QUANTUM 100 /* usec */ + + int i; + + REG_WRITE(ah, AR_CR, AR_CR_RXD); + + /* Wait for rx enable bit to go low */ + for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { + if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) + break; + udelay(AH_TIME_QUANTUM); + } + + if (i == 0) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "DMA failed to stop in %d ms " + "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", + AH_RX_STOP_DMA_TIMEOUT / 1000, + REG_READ(ah, AR_CR), + REG_READ(ah, AR_DIAG_SW)); + return false; + } else { + return true; + } + +#undef AH_RX_TIME_QUANTUM +#undef AH_RX_STOP_DMA_TIMEOUT +} diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h new file mode 100644 index 000000000000..1176bce8b76c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -0,0 +1,680 @@ +/* + * 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 MAC_H +#define MAC_H + +#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ + MS(ads->ds_rxstatus0, AR_RxRate) : \ + (ads->ds_rxstatus3 >> 2) & 0xFF) + +#define set11nTries(_series, _index) \ + (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) + +#define set11nRate(_series, _index) \ + (SM((_series)[_index].Rate, AR_XmitRate##_index)) + +#define set11nPktDurRTSCTS(_series, _index) \ + (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \ + ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \ + AR_RTSCTSQual##_index : 0)) + +#define set11nRateFlags(_series, _index) \ + (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ + AR_2040_##_index : 0) \ + |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ + AR_GI##_index : 0) \ + |SM((_series)[_index].ChSel, AR_ChainSel##_index)) + +#define CCK_SIFS_TIME 10 +#define CCK_PREAMBLE_BITS 144 +#define CCK_PLCP_BITS 48 + +#define OFDM_SIFS_TIME 16 +#define OFDM_PREAMBLE_TIME 20 +#define OFDM_PLCP_BITS 22 +#define OFDM_SYMBOL_TIME 4 + +#define OFDM_SIFS_TIME_HALF 32 +#define OFDM_PREAMBLE_TIME_HALF 40 +#define OFDM_PLCP_BITS_HALF 22 +#define OFDM_SYMBOL_TIME_HALF 8 + +#define OFDM_SIFS_TIME_QUARTER 64 +#define OFDM_PREAMBLE_TIME_QUARTER 80 +#define OFDM_PLCP_BITS_QUARTER 22 +#define OFDM_SYMBOL_TIME_QUARTER 16 + +#define INIT_AIFS 2 +#define INIT_CWMIN 15 +#define INIT_CWMIN_11B 31 +#define INIT_CWMAX 1023 +#define INIT_SH_RETRY 10 +#define INIT_LG_RETRY 10 +#define INIT_SSH_RETRY 32 +#define INIT_SLG_RETRY 32 + +#define ATH9K_SLOT_TIME_6 6 +#define ATH9K_SLOT_TIME_9 9 +#define ATH9K_SLOT_TIME_20 20 + +#define ATH9K_TXERR_XRETRY 0x01 +#define ATH9K_TXERR_FILT 0x02 +#define ATH9K_TXERR_FIFO 0x04 +#define ATH9K_TXERR_XTXOP 0x08 +#define ATH9K_TXERR_TIMER_EXPIRED 0x10 + +#define ATH9K_TX_BA 0x01 +#define ATH9K_TX_PWRMGMT 0x02 +#define ATH9K_TX_DESC_CFG_ERR 0x04 +#define ATH9K_TX_DATA_UNDERRUN 0x08 +#define ATH9K_TX_DELIM_UNDERRUN 0x10 +#define ATH9K_TX_SW_ABORTED 0x40 +#define ATH9K_TX_SW_FILTERED 0x80 + +#define MIN_TX_FIFO_THRESHOLD 0x1 +#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) +#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD + +struct ath_tx_status { + u32 ts_tstamp; + u16 ts_seqnum; + u8 ts_status; + u8 ts_ratecode; + u8 ts_rateindex; + int8_t ts_rssi; + u8 ts_shortretry; + u8 ts_longretry; + u8 ts_virtcol; + u8 ts_antenna; + u8 ts_flags; + int8_t ts_rssi_ctl0; + int8_t ts_rssi_ctl1; + int8_t ts_rssi_ctl2; + int8_t ts_rssi_ext0; + int8_t ts_rssi_ext1; + int8_t ts_rssi_ext2; + u8 pad[3]; + u32 ba_low; + u32 ba_high; + u32 evm0; + u32 evm1; + u32 evm2; +}; + +struct ath_rx_status { + u32 rs_tstamp; + u16 rs_datalen; + u8 rs_status; + u8 rs_phyerr; + int8_t rs_rssi; + u8 rs_keyix; + u8 rs_rate; + u8 rs_antenna; + u8 rs_more; + int8_t rs_rssi_ctl0; + int8_t rs_rssi_ctl1; + int8_t rs_rssi_ctl2; + int8_t rs_rssi_ext0; + int8_t rs_rssi_ext1; + int8_t rs_rssi_ext2; + u8 rs_isaggr; + u8 rs_moreaggr; + u8 rs_num_delims; + u8 rs_flags; + u32 evm0; + u32 evm1; + u32 evm2; +}; + +#define ATH9K_RXERR_CRC 0x01 +#define ATH9K_RXERR_PHY 0x02 +#define ATH9K_RXERR_FIFO 0x04 +#define ATH9K_RXERR_DECRYPT 0x08 +#define ATH9K_RXERR_MIC 0x10 + +#define ATH9K_RX_MORE 0x01 +#define ATH9K_RX_MORE_AGGR 0x02 +#define ATH9K_RX_GI 0x04 +#define ATH9K_RX_2040 0x08 +#define ATH9K_RX_DELIM_CRC_PRE 0x10 +#define ATH9K_RX_DELIM_CRC_POST 0x20 +#define ATH9K_RX_DECRYPT_BUSY 0x40 + +#define ATH9K_RXKEYIX_INVALID ((u8)-1) +#define ATH9K_TXKEYIX_INVALID ((u32)-1) + +struct ath_desc { + u32 ds_link; + u32 ds_data; + u32 ds_ctl0; + u32 ds_ctl1; + u32 ds_hw[20]; + union { + struct ath_tx_status tx; + struct ath_rx_status rx; + void *stats; + } ds_us; + void *ds_vdata; +} __packed; + +#define ds_txstat ds_us.tx +#define ds_rxstat ds_us.rx +#define ds_stat ds_us.stats + +#define ATH9K_TXDESC_CLRDMASK 0x0001 +#define ATH9K_TXDESC_NOACK 0x0002 +#define ATH9K_TXDESC_RTSENA 0x0004 +#define ATH9K_TXDESC_CTSENA 0x0008 +/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for + * the descriptor its marked on. We take a tx interrupt to reap + * descriptors when the h/w hits an EOL condition or + * when the descriptor is specifically marked to generate + * an interrupt with this flag. Descriptors should be + * marked periodically to insure timely replenishing of the + * supply needed for sending frames. Defering interrupts + * reduces system load and potentially allows more concurrent + * work to be done but if done to aggressively can cause + * senders to backup. When the hardware queue is left too + * large rate control information may also be too out of + * date. An Alternative for this is TX interrupt mitigation + * but this needs more testing. */ +#define ATH9K_TXDESC_INTREQ 0x0010 +#define ATH9K_TXDESC_VEOL 0x0020 +#define ATH9K_TXDESC_EXT_ONLY 0x0040 +#define ATH9K_TXDESC_EXT_AND_CTL 0x0080 +#define ATH9K_TXDESC_VMF 0x0100 +#define ATH9K_TXDESC_FRAG_IS_ON 0x0200 +#define ATH9K_TXDESC_CAB 0x0400 + +#define ATH9K_RXDESC_INTREQ 0x0020 + +struct ar5416_desc { + u32 ds_link; + u32 ds_data; + u32 ds_ctl0; + u32 ds_ctl1; + union { + struct { + u32 ctl2; + u32 ctl3; + u32 ctl4; + u32 ctl5; + u32 ctl6; + u32 ctl7; + u32 ctl8; + u32 ctl9; + u32 ctl10; + u32 ctl11; + u32 status0; + u32 status1; + u32 status2; + u32 status3; + u32 status4; + u32 status5; + u32 status6; + u32 status7; + u32 status8; + u32 status9; + } tx; + struct { + u32 status0; + u32 status1; + u32 status2; + u32 status3; + u32 status4; + u32 status5; + u32 status6; + u32 status7; + u32 status8; + } rx; + } u; +} __packed; + +#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) +#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) + +#define ds_ctl2 u.tx.ctl2 +#define ds_ctl3 u.tx.ctl3 +#define ds_ctl4 u.tx.ctl4 +#define ds_ctl5 u.tx.ctl5 +#define ds_ctl6 u.tx.ctl6 +#define ds_ctl7 u.tx.ctl7 +#define ds_ctl8 u.tx.ctl8 +#define ds_ctl9 u.tx.ctl9 +#define ds_ctl10 u.tx.ctl10 +#define ds_ctl11 u.tx.ctl11 + +#define ds_txstatus0 u.tx.status0 +#define ds_txstatus1 u.tx.status1 +#define ds_txstatus2 u.tx.status2 +#define ds_txstatus3 u.tx.status3 +#define ds_txstatus4 u.tx.status4 +#define ds_txstatus5 u.tx.status5 +#define ds_txstatus6 u.tx.status6 +#define ds_txstatus7 u.tx.status7 +#define ds_txstatus8 u.tx.status8 +#define ds_txstatus9 u.tx.status9 + +#define ds_rxstatus0 u.rx.status0 +#define ds_rxstatus1 u.rx.status1 +#define ds_rxstatus2 u.rx.status2 +#define ds_rxstatus3 u.rx.status3 +#define ds_rxstatus4 u.rx.status4 +#define ds_rxstatus5 u.rx.status5 +#define ds_rxstatus6 u.rx.status6 +#define ds_rxstatus7 u.rx.status7 +#define ds_rxstatus8 u.rx.status8 + +#define AR_FrameLen 0x00000fff +#define AR_VirtMoreFrag 0x00001000 +#define AR_TxCtlRsvd00 0x0000e000 +#define AR_XmitPower 0x003f0000 +#define AR_XmitPower_S 16 +#define AR_RTSEnable 0x00400000 +#define AR_VEOL 0x00800000 +#define AR_ClrDestMask 0x01000000 +#define AR_TxCtlRsvd01 0x1e000000 +#define AR_TxIntrReq 0x20000000 +#define AR_DestIdxValid 0x40000000 +#define AR_CTSEnable 0x80000000 + +#define AR_BufLen 0x00000fff +#define AR_TxMore 0x00001000 +#define AR_DestIdx 0x000fe000 +#define AR_DestIdx_S 13 +#define AR_FrameType 0x00f00000 +#define AR_FrameType_S 20 +#define AR_NoAck 0x01000000 +#define AR_InsertTS 0x02000000 +#define AR_CorruptFCS 0x04000000 +#define AR_ExtOnly 0x08000000 +#define AR_ExtAndCtl 0x10000000 +#define AR_MoreAggr 0x20000000 +#define AR_IsAggr 0x40000000 + +#define AR_BurstDur 0x00007fff +#define AR_BurstDur_S 0 +#define AR_DurUpdateEna 0x00008000 +#define AR_XmitDataTries0 0x000f0000 +#define AR_XmitDataTries0_S 16 +#define AR_XmitDataTries1 0x00f00000 +#define AR_XmitDataTries1_S 20 +#define AR_XmitDataTries2 0x0f000000 +#define AR_XmitDataTries2_S 24 +#define AR_XmitDataTries3 0xf0000000 +#define AR_XmitDataTries3_S 28 + +#define AR_XmitRate0 0x000000ff +#define AR_XmitRate0_S 0 +#define AR_XmitRate1 0x0000ff00 +#define AR_XmitRate1_S 8 +#define AR_XmitRate2 0x00ff0000 +#define AR_XmitRate2_S 16 +#define AR_XmitRate3 0xff000000 +#define AR_XmitRate3_S 24 + +#define AR_PacketDur0 0x00007fff +#define AR_PacketDur0_S 0 +#define AR_RTSCTSQual0 0x00008000 +#define AR_PacketDur1 0x7fff0000 +#define AR_PacketDur1_S 16 +#define AR_RTSCTSQual1 0x80000000 + +#define AR_PacketDur2 0x00007fff +#define AR_PacketDur2_S 0 +#define AR_RTSCTSQual2 0x00008000 +#define AR_PacketDur3 0x7fff0000 +#define AR_PacketDur3_S 16 +#define AR_RTSCTSQual3 0x80000000 + +#define AR_AggrLen 0x0000ffff +#define AR_AggrLen_S 0 +#define AR_TxCtlRsvd60 0x00030000 +#define AR_PadDelim 0x03fc0000 +#define AR_PadDelim_S 18 +#define AR_EncrType 0x0c000000 +#define AR_EncrType_S 26 +#define AR_TxCtlRsvd61 0xf0000000 + +#define AR_2040_0 0x00000001 +#define AR_GI0 0x00000002 +#define AR_ChainSel0 0x0000001c +#define AR_ChainSel0_S 2 +#define AR_2040_1 0x00000020 +#define AR_GI1 0x00000040 +#define AR_ChainSel1 0x00000380 +#define AR_ChainSel1_S 7 +#define AR_2040_2 0x00000400 +#define AR_GI2 0x00000800 +#define AR_ChainSel2 0x00007000 +#define AR_ChainSel2_S 12 +#define AR_2040_3 0x00008000 +#define AR_GI3 0x00010000 +#define AR_ChainSel3 0x000e0000 +#define AR_ChainSel3_S 17 +#define AR_RTSCTSRate 0x0ff00000 +#define AR_RTSCTSRate_S 20 +#define AR_TxCtlRsvd70 0xf0000000 + +#define AR_TxRSSIAnt00 0x000000ff +#define AR_TxRSSIAnt00_S 0 +#define AR_TxRSSIAnt01 0x0000ff00 +#define AR_TxRSSIAnt01_S 8 +#define AR_TxRSSIAnt02 0x00ff0000 +#define AR_TxRSSIAnt02_S 16 +#define AR_TxStatusRsvd00 0x3f000000 +#define AR_TxBaStatus 0x40000000 +#define AR_TxStatusRsvd01 0x80000000 + +#define AR_FrmXmitOK 0x00000001 +#define AR_ExcessiveRetries 0x00000002 +#define AR_FIFOUnderrun 0x00000004 +#define AR_Filtered 0x00000008 +#define AR_RTSFailCnt 0x000000f0 +#define AR_RTSFailCnt_S 4 +#define AR_DataFailCnt 0x00000f00 +#define AR_DataFailCnt_S 8 +#define AR_VirtRetryCnt 0x0000f000 +#define AR_VirtRetryCnt_S 12 +#define AR_TxDelimUnderrun 0x00010000 +#define AR_TxDataUnderrun 0x00020000 +#define AR_DescCfgErr 0x00040000 +#define AR_TxTimerExpired 0x00080000 +#define AR_TxStatusRsvd10 0xfff00000 + +#define AR_SendTimestamp ds_txstatus2 +#define AR_BaBitmapLow ds_txstatus3 +#define AR_BaBitmapHigh ds_txstatus4 + +#define AR_TxRSSIAnt10 0x000000ff +#define AR_TxRSSIAnt10_S 0 +#define AR_TxRSSIAnt11 0x0000ff00 +#define AR_TxRSSIAnt11_S 8 +#define AR_TxRSSIAnt12 0x00ff0000 +#define AR_TxRSSIAnt12_S 16 +#define AR_TxRSSICombined 0xff000000 +#define AR_TxRSSICombined_S 24 + +#define AR_TxEVM0 ds_txstatus5 +#define AR_TxEVM1 ds_txstatus6 +#define AR_TxEVM2 ds_txstatus7 + +#define AR_TxDone 0x00000001 +#define AR_SeqNum 0x00001ffe +#define AR_SeqNum_S 1 +#define AR_TxStatusRsvd80 0x0001e000 +#define AR_TxOpExceeded 0x00020000 +#define AR_TxStatusRsvd81 0x001c0000 +#define AR_FinalTxIdx 0x00600000 +#define AR_FinalTxIdx_S 21 +#define AR_TxStatusRsvd82 0x01800000 +#define AR_PowerMgmt 0x02000000 +#define AR_TxStatusRsvd83 0xfc000000 + +#define AR_RxCTLRsvd00 0xffffffff + +#define AR_BufLen 0x00000fff +#define AR_RxCtlRsvd00 0x00001000 +#define AR_RxIntrReq 0x00002000 +#define AR_RxCtlRsvd01 0xffffc000 + +#define AR_RxRSSIAnt00 0x000000ff +#define AR_RxRSSIAnt00_S 0 +#define AR_RxRSSIAnt01 0x0000ff00 +#define AR_RxRSSIAnt01_S 8 +#define AR_RxRSSIAnt02 0x00ff0000 +#define AR_RxRSSIAnt02_S 16 +#define AR_RxRate 0xff000000 +#define AR_RxRate_S 24 +#define AR_RxStatusRsvd00 0xff000000 + +#define AR_DataLen 0x00000fff +#define AR_RxMore 0x00001000 +#define AR_NumDelim 0x003fc000 +#define AR_NumDelim_S 14 +#define AR_RxStatusRsvd10 0xff800000 + +#define AR_RcvTimestamp ds_rxstatus2 + +#define AR_GI 0x00000001 +#define AR_2040 0x00000002 +#define AR_Parallel40 0x00000004 +#define AR_Parallel40_S 2 +#define AR_RxStatusRsvd30 0x000000f8 +#define AR_RxAntenna 0xffffff00 +#define AR_RxAntenna_S 8 + +#define AR_RxRSSIAnt10 0x000000ff +#define AR_RxRSSIAnt10_S 0 +#define AR_RxRSSIAnt11 0x0000ff00 +#define AR_RxRSSIAnt11_S 8 +#define AR_RxRSSIAnt12 0x00ff0000 +#define AR_RxRSSIAnt12_S 16 +#define AR_RxRSSICombined 0xff000000 +#define AR_RxRSSICombined_S 24 + +#define AR_RxEVM0 ds_rxstatus4 +#define AR_RxEVM1 ds_rxstatus5 +#define AR_RxEVM2 ds_rxstatus6 + +#define AR_RxDone 0x00000001 +#define AR_RxFrameOK 0x00000002 +#define AR_CRCErr 0x00000004 +#define AR_DecryptCRCErr 0x00000008 +#define AR_PHYErr 0x00000010 +#define AR_MichaelErr 0x00000020 +#define AR_PreDelimCRCErr 0x00000040 +#define AR_RxStatusRsvd70 0x00000080 +#define AR_RxKeyIdxValid 0x00000100 +#define AR_KeyIdx 0x0000fe00 +#define AR_KeyIdx_S 9 +#define AR_PHYErrCode 0x0000ff00 +#define AR_PHYErrCode_S 8 +#define AR_RxMoreAggr 0x00010000 +#define AR_RxAggr 0x00020000 +#define AR_PostDelimCRCErr 0x00040000 +#define AR_RxStatusRsvd71 0x3ff80000 +#define AR_DecryptBusyErr 0x40000000 +#define AR_KeyMiss 0x80000000 + +enum ath9k_tx_queue { + ATH9K_TX_QUEUE_INACTIVE = 0, + ATH9K_TX_QUEUE_DATA, + ATH9K_TX_QUEUE_BEACON, + ATH9K_TX_QUEUE_CAB, + ATH9K_TX_QUEUE_UAPSD, + ATH9K_TX_QUEUE_PSPOLL +}; + +#define ATH9K_NUM_TX_QUEUES 10 + +enum ath9k_tx_queue_subtype { + ATH9K_WME_AC_BK = 0, + ATH9K_WME_AC_BE, + ATH9K_WME_AC_VI, + ATH9K_WME_AC_VO, + ATH9K_WME_UPSD +}; + +enum ath9k_tx_queue_flags { + TXQ_FLAG_TXOKINT_ENABLE = 0x0001, + TXQ_FLAG_TXERRINT_ENABLE = 0x0001, + TXQ_FLAG_TXDESCINT_ENABLE = 0x0002, + TXQ_FLAG_TXEOLINT_ENABLE = 0x0004, + TXQ_FLAG_TXURNINT_ENABLE = 0x0008, + TXQ_FLAG_BACKOFF_DISABLE = 0x0010, + TXQ_FLAG_COMPRESSION_ENABLE = 0x0020, + TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040, + TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080, +}; + +#define ATH9K_TXQ_USEDEFAULT ((u32) -1) +#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 + +#define ATH9K_DECOMP_MASK_SIZE 128 +#define ATH9K_READY_TIME_LO_BOUND 50 +#define ATH9K_READY_TIME_HI_BOUND 96 + +enum ath9k_pkt_type { + ATH9K_PKT_TYPE_NORMAL = 0, + ATH9K_PKT_TYPE_ATIM, + ATH9K_PKT_TYPE_PSPOLL, + ATH9K_PKT_TYPE_BEACON, + ATH9K_PKT_TYPE_PROBE_RESP, + ATH9K_PKT_TYPE_CHIRP, + ATH9K_PKT_TYPE_GRP_POLL, +}; + +struct ath9k_tx_queue_info { + u32 tqi_ver; + enum ath9k_tx_queue tqi_type; + enum ath9k_tx_queue_subtype tqi_subtype; + enum ath9k_tx_queue_flags tqi_qflags; + u32 tqi_priority; + u32 tqi_aifs; + u32 tqi_cwmin; + u32 tqi_cwmax; + u16 tqi_shretry; + u16 tqi_lgretry; + u32 tqi_cbrPeriod; + u32 tqi_cbrOverflowLimit; + u32 tqi_burstTime; + u32 tqi_readyTime; + u32 tqi_physCompBuf; + u32 tqi_intFlags; +}; + +enum ath9k_rx_filter { + ATH9K_RX_FILTER_UCAST = 0x00000001, + ATH9K_RX_FILTER_MCAST = 0x00000002, + ATH9K_RX_FILTER_BCAST = 0x00000004, + ATH9K_RX_FILTER_CONTROL = 0x00000008, + ATH9K_RX_FILTER_BEACON = 0x00000010, + ATH9K_RX_FILTER_PROM = 0x00000020, + ATH9K_RX_FILTER_PROBEREQ = 0x00000080, + ATH9K_RX_FILTER_PHYERR = 0x00000100, + ATH9K_RX_FILTER_MYBEACON = 0x00000200, + ATH9K_RX_FILTER_PSPOLL = 0x00004000, + ATH9K_RX_FILTER_PHYRADAR = 0x00002000, + ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, +}; + +#define ATH9K_RATESERIES_RTS_CTS 0x0001 +#define ATH9K_RATESERIES_2040 0x0002 +#define ATH9K_RATESERIES_HALFGI 0x0004 + +struct ath9k_11n_rate_series { + u32 Tries; + u32 Rate; + u32 PktDuration; + u32 ChSel; + u32 RateFlags; +}; + +struct ath9k_keyval { + u8 kv_type; + u8 kv_pad; + u16 kv_len; + u8 kv_val[16]; /* TK */ + u8 kv_mic[8]; /* Michael MIC key */ + u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware + * supports both MIC keys in the same key cache entry; + * in that case, kv_mic is the RX key) */ +}; + +enum ath9k_key_type { + ATH9K_KEY_TYPE_CLEAR, + ATH9K_KEY_TYPE_WEP, + ATH9K_KEY_TYPE_AES, + ATH9K_KEY_TYPE_TKIP, +}; + +enum ath9k_cipher { + ATH9K_CIPHER_WEP = 0, + ATH9K_CIPHER_AES_OCB = 1, + ATH9K_CIPHER_AES_CCM = 2, + ATH9K_CIPHER_CKIP = 3, + ATH9K_CIPHER_TKIP = 4, + ATH9K_CIPHER_CLR = 5, + ATH9K_CIPHER_MIC = 127 +}; + +enum ath9k_ht_macmode { + ATH9K_HT_MACMODE_20 = 0, + ATH9K_HT_MACMODE_2040 = 1, +}; + +enum ath9k_ht_extprotspacing { + ATH9K_HT_EXTPROTSPACING_20 = 0, + ATH9K_HT_EXTPROTSPACING_25 = 1, +}; + +struct ath_hw; +struct ath9k_channel; +struct ath_rate_table; + +u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); +bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); +bool ath9k_hw_txstart(struct ath_hw *ah, u32 q); +u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); +bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); +bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); +bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 segLen, bool firstSeg, + bool lastSeg, const struct ath_desc *ds0); +void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); +int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds); +void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 pktLen, enum ath9k_pkt_type type, u32 txPower, + u32 keyIx, enum ath9k_key_type keyType, u32 flags); +void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, + struct ath_desc *lastds, + u32 durUpdateEn, u32 rtsctsRate, + u32 rtsctsDuration, + struct ath9k_11n_rate_series series[], + u32 nseries, u32 flags); +void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, + u32 aggrLen); +void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, + u32 numDelims); +void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds); +void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds); +void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, + u32 burstDuration); +void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, + u32 vmf); +void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); +bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, + const struct ath9k_tx_queue_info *qinfo); +bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, + struct ath9k_tx_queue_info *qinfo); +int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, + const struct ath9k_tx_queue_info *qinfo); +bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); +bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); +int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 pa, struct ath_desc *nds, u64 tsf); +bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 size, u32 flags); +bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); +void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); +void ath9k_hw_rxena(struct ath_hw *ah); +void ath9k_hw_startpcureceive(struct ath_hw *ah); +void ath9k_hw_stoppcurecv(struct ath_hw *ah); +bool ath9k_hw_stopdmarecv(struct ath_hw *ah); + +#endif /* MAC_H */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c new file mode 100644 index 000000000000..8b6a7ea4e59b --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -0,0 +1,2890 @@ +/* + * 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 +#include "ath9k.h" + +#define ATH_PCI_VERSION "0.1" + +static char *dev_info = "ath9k"; + +MODULE_AUTHOR("Atheros Communications"); +MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); +MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); +MODULE_LICENSE("Dual BSD/GPL"); + +static int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +/* We use the hw_value as an index into our private channel structure */ + +#define CHAN2G(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 30, \ +} + +#define CHAN5G(_freq, _idx) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 30, \ +} + +/* Some 2 GHz radios are actually tunable on 2312-2732 + * on 5 MHz steps, we support the channels which we know + * we have calibration data for all cards though to make + * this static */ +static struct ieee80211_channel ath9k_2ghz_chantable[] = { + CHAN2G(2412, 0), /* Channel 1 */ + CHAN2G(2417, 1), /* Channel 2 */ + CHAN2G(2422, 2), /* Channel 3 */ + CHAN2G(2427, 3), /* Channel 4 */ + CHAN2G(2432, 4), /* Channel 5 */ + CHAN2G(2437, 5), /* Channel 6 */ + CHAN2G(2442, 6), /* Channel 7 */ + CHAN2G(2447, 7), /* Channel 8 */ + CHAN2G(2452, 8), /* Channel 9 */ + CHAN2G(2457, 9), /* Channel 10 */ + CHAN2G(2462, 10), /* Channel 11 */ + CHAN2G(2467, 11), /* Channel 12 */ + CHAN2G(2472, 12), /* Channel 13 */ + CHAN2G(2484, 13), /* Channel 14 */ +}; + +/* Some 5 GHz radios are actually tunable on XXXX-YYYY + * on 5 MHz steps, we support the channels which we know + * we have calibration data for all cards though to make + * this static */ +static struct ieee80211_channel ath9k_5ghz_chantable[] = { + /* _We_ call this UNII 1 */ + CHAN5G(5180, 14), /* Channel 36 */ + CHAN5G(5200, 15), /* Channel 40 */ + CHAN5G(5220, 16), /* Channel 44 */ + CHAN5G(5240, 17), /* Channel 48 */ + /* _We_ call this UNII 2 */ + CHAN5G(5260, 18), /* Channel 52 */ + CHAN5G(5280, 19), /* Channel 56 */ + CHAN5G(5300, 20), /* Channel 60 */ + CHAN5G(5320, 21), /* Channel 64 */ + /* _We_ call this "Middle band" */ + CHAN5G(5500, 22), /* Channel 100 */ + CHAN5G(5520, 23), /* Channel 104 */ + CHAN5G(5540, 24), /* Channel 108 */ + CHAN5G(5560, 25), /* Channel 112 */ + CHAN5G(5580, 26), /* Channel 116 */ + CHAN5G(5600, 27), /* Channel 120 */ + CHAN5G(5620, 28), /* Channel 124 */ + CHAN5G(5640, 29), /* Channel 128 */ + CHAN5G(5660, 30), /* Channel 132 */ + CHAN5G(5680, 31), /* Channel 136 */ + CHAN5G(5700, 32), /* Channel 140 */ + /* _We_ call this UNII 3 */ + CHAN5G(5745, 33), /* Channel 149 */ + CHAN5G(5765, 34), /* Channel 153 */ + CHAN5G(5785, 35), /* Channel 157 */ + CHAN5G(5805, 36), /* Channel 161 */ + CHAN5G(5825, 37), /* Channel 165 */ +}; + +static void ath_cache_conf_rate(struct ath_softc *sc, + struct ieee80211_conf *conf) +{ + switch (conf->channel->band) { + case IEEE80211_BAND_2GHZ: + if (conf_is_ht20(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; + else if (conf_is_ht40_minus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; + else if (conf_is_ht40_plus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; + else + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11G]; + break; + case IEEE80211_BAND_5GHZ: + if (conf_is_ht20(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; + else if (conf_is_ht40_minus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; + else if (conf_is_ht40_plus(conf)) + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; + else + sc->cur_rate_table = + sc->hw_rate_table[ATH9K_MODE_11A]; + break; + default: + BUG_ON(1); + break; + } +} + +static void ath_update_txpow(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + u32 txpow; + + if (sc->curtxpow != sc->config.txpowlimit) { + ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); + /* read back in case value is clamped */ + ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); + sc->curtxpow = txpow; + } +} + +static u8 parse_mpdudensity(u8 mpdudensity) +{ + /* + * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": + * 0 for no restriction + * 1 for 1/4 us + * 2 for 1/2 us + * 3 for 1 us + * 4 for 2 us + * 5 for 4 us + * 6 for 8 us + * 7 for 16 us + */ + switch (mpdudensity) { + case 0: + return 0; + case 1: + case 2: + case 3: + /* Our lower layer calculations limit our precision to + 1 microsecond */ + return 1; + case 4: + return 2; + case 5: + return 4; + case 6: + return 8; + case 7: + return 16; + default: + return 0; + } +} + +static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) +{ + struct ath_rate_table *rate_table = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_rate *rate; + int i, maxrates; + + switch (band) { + case IEEE80211_BAND_2GHZ: + rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; + break; + case IEEE80211_BAND_5GHZ: + rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; + break; + default: + break; + } + + if (rate_table == NULL) + return; + + sband = &sc->sbands[band]; + rate = sc->rates[band]; + + if (rate_table->rate_cnt > ATH_RATE_MAX) + maxrates = ATH_RATE_MAX; + else + maxrates = rate_table->rate_cnt; + + for (i = 0; i < maxrates; i++) { + rate[i].bitrate = rate_table->info[i].ratekbps / 100; + rate[i].hw_value = rate_table->info[i].ratecode; + if (rate_table->info[i].short_preamble) { + rate[i].hw_value_short = rate_table->info[i].ratecode | + rate_table->info[i].short_preamble; + rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE; + } + sband->n_bitrates++; + + DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n", + rate[i].bitrate / 10, rate[i].hw_value); + } +} + +/* + * Set/change channels. If the channel is really being changed, it's done + * by reseting the chip. To accomplish this we must first cleanup any pending + * DMA, then restart stuff. +*/ +int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, + struct ath9k_channel *hchan) +{ + struct ath_hw *ah = sc->sc_ah; + bool fastcc = true, stopped; + struct ieee80211_channel *channel = hw->conf.channel; + int r; + + if (sc->sc_flags & SC_OP_INVALID) + return -EIO; + + ath9k_ps_wakeup(sc); + + /* + * This is only performed if the channel settings have + * actually changed. + * + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the + * hardware at the new frequency, and then re-enable + * the relevant bits of the h/w. + */ + ath9k_hw_set_interrupts(ah, 0); + ath_drain_all_txq(sc, false); + stopped = ath_stoprecv(sc); + + /* XXX: do not flush receive queue here. We don't want + * to flush data frames already in queue because of + * changing channel. */ + + if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) + fastcc = false; + + DPRINTF(sc, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), chanwidth: %d\n", + sc->sc_ah->curchan->channel, + channel->center_freq, sc->tx_chan_width); + + spin_lock_bh(&sc->sc_resetlock); + + r = ath9k_hw_reset(ah, hchan, fastcc); + if (r) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset channel (%u Mhz) " + "reset status %u\n", + channel->center_freq, r); + spin_unlock_bh(&sc->sc_resetlock); + return r; + } + spin_unlock_bh(&sc->sc_resetlock); + + sc->sc_flags &= ~SC_OP_FULL_RESET; + + if (ath_startrecv(sc) != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to restart recv logic\n"); + return -EIO; + } + + ath_cache_conf_rate(sc, &hw->conf); + ath_update_txpow(sc); + ath9k_hw_set_interrupts(ah, sc->imask); + ath9k_ps_restore(sc); + return 0; +} + +/* + * This routine performs the periodic noise floor calibration function + * that is used to adjust and optimize the chip performance. This + * takes environmental changes (location, temperature) into account. + * When the task is complete, it reschedules itself depending on the + * appropriate interval that was calculated. + */ +static void ath_ani_calibrate(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *)data; + struct ath_hw *ah = sc->sc_ah; + bool longcal = false; + bool shortcal = false; + bool aniflag = false; + unsigned int timestamp = jiffies_to_msecs(jiffies); + u32 cal_interval, short_cal_interval; + + short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? + ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; + + /* + * don't calibrate when we're scanning. + * we are most likely not on our home channel. + */ + if (sc->sc_flags & SC_OP_SCANNING) + goto set_timer; + + /* Long calibration runs independently of short calibration. */ + if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { + longcal = true; + DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + sc->ani.longcal_timer = timestamp; + } + + /* Short calibration applies only while caldone is false */ + if (!sc->ani.caldone) { + if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) { + shortcal = true; + DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies); + sc->ani.shortcal_timer = timestamp; + sc->ani.resetcal_timer = timestamp; + } + } else { + if ((timestamp - sc->ani.resetcal_timer) >= + ATH_RESTART_CALINTERVAL) { + sc->ani.caldone = ath9k_hw_reset_calvalid(ah); + if (sc->ani.caldone) + sc->ani.resetcal_timer = timestamp; + } + } + + /* Verify whether we must check ANI */ + if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { + aniflag = true; + sc->ani.checkani_timer = timestamp; + } + + /* Skip all processing if there's nothing to do. */ + if (longcal || shortcal || aniflag) { + /* Call ANI routine if necessary */ + if (aniflag) + ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan); + + /* Perform calibration if necessary */ + if (longcal || shortcal) { + bool iscaldone = false; + + if (ath9k_hw_calibrate(ah, ah->curchan, + sc->rx_chainmask, longcal, + &iscaldone)) { + if (longcal) + sc->ani.noise_floor = + ath9k_hw_getchan_noise(ah, + ah->curchan); + + DPRINTF(sc, ATH_DBG_ANI, + "calibrate chan %u/%x nf: %d\n", + ah->curchan->channel, + ah->curchan->channelFlags, + sc->ani.noise_floor); + } else { + DPRINTF(sc, ATH_DBG_ANY, + "calibrate chan %u/%x failed\n", + ah->curchan->channel, + ah->curchan->channelFlags); + } + sc->ani.caldone = iscaldone; + } + } + +set_timer: + /* + * Set timer interval based on previous results. + * The interval must be the shortest necessary to satisfy ANI, + * short calibration and long calibration. + */ + cal_interval = ATH_LONG_CALINTERVAL; + if (sc->sc_ah->config.enable_ani) + cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); + if (!sc->ani.caldone) + cal_interval = min(cal_interval, (u32)short_cal_interval); + + mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); +} + +/* + * Update tx/rx chainmask. For legacy association, + * hard code chainmask to 1x1, for 11n association, use + * the chainmask configuration, for bt coexistence, use + * the chainmask configuration even in legacy mode. + */ +void ath_update_chainmask(struct ath_softc *sc, int is_ht) +{ + if (is_ht || + (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { + sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; + sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask; + } else { + sc->tx_chainmask = 1; + sc->rx_chainmask = 1; + } + + DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n", + sc->tx_chainmask, sc->rx_chainmask); +} + +static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) +{ + struct ath_node *an; + + an = (struct ath_node *)sta->drv_priv; + + if (sc->sc_flags & SC_OP_TXAGGR) { + ath_tx_node_init(sc, an); + an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + + sta->ht_cap.ampdu_factor); + an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); + } +} + +static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) +{ + struct ath_node *an = (struct ath_node *)sta->drv_priv; + + if (sc->sc_flags & SC_OP_TXAGGR) + ath_tx_node_cleanup(sc, an); +} + +static void ath9k_tasklet(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *)data; + u32 status = sc->intrstatus; + + if (status & ATH9K_INT_FATAL) { + ath_reset(sc, false); + return; + } + + if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { + spin_lock_bh(&sc->rx.rxflushlock); + ath_rx_tasklet(sc, 0); + spin_unlock_bh(&sc->rx.rxflushlock); + } + + if (status & ATH9K_INT_TX) + ath_tx_tasklet(sc); + + /* re-enable hardware interrupt */ + ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); +} + +irqreturn_t ath_isr(int irq, void *dev) +{ +#define SCHED_INTR ( \ + ATH9K_INT_FATAL | \ + ATH9K_INT_RXORN | \ + ATH9K_INT_RXEOL | \ + ATH9K_INT_RX | \ + ATH9K_INT_TX | \ + ATH9K_INT_BMISS | \ + ATH9K_INT_CST | \ + ATH9K_INT_TSFOOR) + + struct ath_softc *sc = dev; + struct ath_hw *ah = sc->sc_ah; + enum ath9k_int status; + bool sched = false; + + /* + * The hardware is not ready/present, don't + * touch anything. Note this can happen early + * on if the IRQ is shared. + */ + if (sc->sc_flags & SC_OP_INVALID) + return IRQ_NONE; + + ath9k_ps_wakeup(sc); + + /* shared irq, not for us */ + + if (!ath9k_hw_intrpend(ah)) { + ath9k_ps_restore(sc); + return IRQ_NONE; + } + + /* + * Figure out the reason(s) for the interrupt. Note + * that the hal returns a pseudo-ISR that may include + * bits we haven't explicitly enabled so we mask the + * value to insure we only process bits we requested. + */ + ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ + status &= sc->imask; /* discard unasked-for bits */ + + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). + */ + if (!status) { + ath9k_ps_restore(sc); + return IRQ_NONE; + } + + /* Cache the status */ + sc->intrstatus = status; + + if (status & SCHED_INTR) + sched = true; + + /* + * If a FATAL or RXORN interrupt is received, we have to reset the + * chip immediately. + */ + if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) + goto chip_reset; + + if (status & ATH9K_INT_SWBA) + tasklet_schedule(&sc->bcon_tasklet); + + if (status & ATH9K_INT_TXURN) + ath9k_hw_updatetxtriglevel(ah, true); + + if (status & ATH9K_INT_MIB) { + /* + * Disable interrupts until we service the MIB + * interrupt; otherwise it will continue to + * fire. + */ + ath9k_hw_set_interrupts(ah, 0); + /* + * Let the hal handle the event. We assume + * it will clear whatever condition caused + * the interrupt. + */ + ath9k_hw_procmibevent(ah, &sc->nodestats); + ath9k_hw_set_interrupts(ah, sc->imask); + } + + if (status & ATH9K_INT_TIM_TIMER) { + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + /* Clear RxAbort bit so that we can + * receive frames */ + ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); + ath9k_hw_setrxabort(ah, 0); + sched = true; + sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; + } + } + +chip_reset: + + ath9k_ps_restore(sc); + ath_debug_stat_interrupt(sc, status); + + if (sched) { + /* turn off every interrupt except SWBA */ + ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA)); + tasklet_schedule(&sc->intr_tq); + } + + return IRQ_HANDLED; + +#undef SCHED_INTR +} + +static u32 ath_get_extchanmode(struct ath_softc *sc, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +{ + u32 chanmode = 0; + + switch (chan->band) { + case IEEE80211_BAND_2GHZ: + switch(channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + chanmode = CHANNEL_G_HT20; + break; + case NL80211_CHAN_HT40PLUS: + chanmode = CHANNEL_G_HT40PLUS; + break; + case NL80211_CHAN_HT40MINUS: + chanmode = CHANNEL_G_HT40MINUS; + break; + } + break; + case IEEE80211_BAND_5GHZ: + switch(channel_type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + chanmode = CHANNEL_A_HT20; + break; + case NL80211_CHAN_HT40PLUS: + chanmode = CHANNEL_A_HT40PLUS; + break; + case NL80211_CHAN_HT40MINUS: + chanmode = CHANNEL_A_HT40MINUS; + break; + } + break; + default: + break; + } + + return chanmode; +} + +static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, + struct ath9k_keyval *hk, const u8 *addr, + bool authenticator) +{ + const u8 *key_rxmic; + const u8 *key_txmic; + + key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; + key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; + + if (addr == NULL) { + /* + * Group key installation - only two key cache entries are used + * regardless of splitmic capability since group key is only + * used either for TX or RX. + */ + if (authenticator) { + memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); + } else { + memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); + } + return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr); + } + if (!sc->splitmic) { + /* TX and RX keys share the same key cache entry. */ + memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); + return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr); + } + + /* Separate key cache entries for TX and RX */ + + /* TX key goes at first index, RX key at +32. */ + memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); + if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { + /* TX MIC entry failed. No need to proceed further */ + DPRINTF(sc, ATH_DBG_FATAL, + "Setting TX MIC Key Failed\n"); + return 0; + } + + memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); + /* XXX delete tx key on failure? */ + return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr); +} + +static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc) +{ + int i; + + for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) { + if (test_bit(i, sc->keymap) || + test_bit(i + 64, sc->keymap)) + continue; /* At least one part of TKIP key allocated */ + if (sc->splitmic && + (test_bit(i + 32, sc->keymap) || + test_bit(i + 64 + 32, sc->keymap))) + continue; /* At least one part of TKIP key allocated */ + + /* Found a free slot for a TKIP key */ + return i; + } + return -1; +} + +static int ath_reserve_key_cache_slot(struct ath_softc *sc) +{ + int i; + + /* First, try to find slots that would not be available for TKIP. */ + if (sc->splitmic) { + for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) { + if (!test_bit(i, sc->keymap) && + (test_bit(i + 32, sc->keymap) || + test_bit(i + 64, sc->keymap) || + test_bit(i + 64 + 32, sc->keymap))) + return i; + if (!test_bit(i + 32, sc->keymap) && + (test_bit(i, sc->keymap) || + test_bit(i + 64, sc->keymap) || + test_bit(i + 64 + 32, sc->keymap))) + return i + 32; + if (!test_bit(i + 64, sc->keymap) && + (test_bit(i , sc->keymap) || + test_bit(i + 32, sc->keymap) || + test_bit(i + 64 + 32, sc->keymap))) + return i + 64; + if (!test_bit(i + 64 + 32, sc->keymap) && + (test_bit(i, sc->keymap) || + test_bit(i + 32, sc->keymap) || + test_bit(i + 64, sc->keymap))) + return i + 64 + 32; + } + } else { + for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) { + if (!test_bit(i, sc->keymap) && + test_bit(i + 64, sc->keymap)) + return i; + if (test_bit(i, sc->keymap) && + !test_bit(i + 64, sc->keymap)) + return i + 64; + } + } + + /* No partially used TKIP slots, pick any available slot */ + for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) { + /* Do not allow slots that could be needed for TKIP group keys + * to be used. This limitation could be removed if we know that + * TKIP will not be used. */ + if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) + continue; + if (sc->splitmic) { + if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) + continue; + if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) + continue; + } + + if (!test_bit(i, sc->keymap)) + return i; /* Found a free slot for a key */ + } + + /* No free slot found */ + return -1; +} + +static int ath_key_config(struct ath_softc *sc, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath9k_keyval hk; + const u8 *mac = NULL; + int ret = 0; + int idx; + + memset(&hk, 0, sizeof(hk)); + + switch (key->alg) { + case ALG_WEP: + hk.kv_type = ATH9K_CIPHER_WEP; + break; + case ALG_TKIP: + hk.kv_type = ATH9K_CIPHER_TKIP; + break; + case ALG_CCMP: + hk.kv_type = ATH9K_CIPHER_AES_CCM; + break; + default: + return -EOPNOTSUPP; + } + + hk.kv_len = key->keylen; + memcpy(hk.kv_val, key->key, key->keylen); + + if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { + /* For now, use the default keys for broadcast keys. This may + * need to change with virtual interfaces. */ + idx = key->keyidx; + } else if (key->keyidx) { + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + + if (vif->type != NL80211_IFTYPE_AP) { + /* Only keyidx 0 should be used with unicast key, but + * allow this for client mode for now. */ + idx = key->keyidx; + } else + return -EIO; + } else { + if (WARN_ON(!sta)) + return -EOPNOTSUPP; + mac = sta->addr; + + if (key->alg == ALG_TKIP) + idx = ath_reserve_key_cache_slot_tkip(sc); + else + idx = ath_reserve_key_cache_slot(sc); + if (idx < 0) + return -ENOSPC; /* no free key cache entries */ + } + + if (key->alg == ALG_TKIP) + ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac, + vif->type == NL80211_IFTYPE_AP); + else + ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac); + + if (!ret) + return -EIO; + + set_bit(idx, sc->keymap); + if (key->alg == ALG_TKIP) { + set_bit(idx + 64, sc->keymap); + if (sc->splitmic) { + set_bit(idx + 32, sc->keymap); + set_bit(idx + 64 + 32, sc->keymap); + } + } + + return idx; +} + +static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) +{ + ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx); + if (key->hw_key_idx < IEEE80211_WEP_NKID) + return; + + clear_bit(key->hw_key_idx, sc->keymap); + if (key->alg != ALG_TKIP) + return; + + clear_bit(key->hw_key_idx + 64, sc->keymap); + if (sc->splitmic) { + clear_bit(key->hw_key_idx + 32, sc->keymap); + clear_bit(key->hw_key_idx + 64 + 32, sc->keymap); + } +} + +static void setup_ht_cap(struct ath_softc *sc, + struct ieee80211_sta_ht_cap *ht_info) +{ +#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ +#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ + + ht_info->ht_supported = true; + ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40; + + ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; + ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; + + /* set up supported mcs set */ + memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); + + switch(sc->rx_chainmask) { + case 1: + ht_info->mcs.rx_mask[0] = 0xff; + break; + case 3: + case 5: + case 7: + default: + ht_info->mcs.rx_mask[0] = 0xff; + ht_info->mcs.rx_mask[1] = 0xff; + break; + } + + ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +} + +static void ath9k_bss_assoc_info(struct ath_softc *sc, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + struct ath_vif *avp = (void *)vif->drv_priv; + + if (bss_conf->assoc) { + DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, sc->curbssid); + + /* New association, store aid */ + if (avp->av_opmode == NL80211_IFTYPE_STATION) { + sc->curaid = bss_conf->aid; + ath9k_hw_write_associd(sc); + } + + /* Configure the beacon */ + ath_beacon_config(sc, vif); + + /* Reset rssi stats */ + sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; + sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; + sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; + sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; + + /* Start ANI */ + mod_timer(&sc->ani.timer, + jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + } else { + DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); + sc->curaid = 0; + } +} + +/********************************/ +/* LED functions */ +/********************************/ + +static void ath_led_blink_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + ath_led_blink_work.work); + + if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) + return; + + if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || + (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + else + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); + + queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, + (sc->sc_flags & SC_OP_LED_ON) ? + msecs_to_jiffies(sc->led_off_duration) : + msecs_to_jiffies(sc->led_on_duration)); + + sc->led_on_duration = sc->led_on_cnt ? + max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : + ATH_LED_ON_DURATION_IDLE; + sc->led_off_duration = sc->led_off_cnt ? + max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : + ATH_LED_OFF_DURATION_IDLE; + sc->led_on_cnt = sc->led_off_cnt = 0; + if (sc->sc_flags & SC_OP_LED_ON) + sc->sc_flags &= ~SC_OP_LED_ON; + else + sc->sc_flags |= SC_OP_LED_ON; +} + +static void ath_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); + struct ath_softc *sc = led->sc; + + switch (brightness) { + case LED_OFF: + if (led->led_type == ATH_LED_ASSOC || + led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + (led->led_type == ATH_LED_RADIO)); + sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; + if (led->led_type == ATH_LED_RADIO) + sc->sc_flags &= ~SC_OP_LED_ON; + } else { + sc->led_off_cnt++; + } + break; + case LED_FULL: + if (led->led_type == ATH_LED_ASSOC) { + sc->sc_flags |= SC_OP_LED_ASSOCIATED; + queue_delayed_work(sc->hw->workqueue, + &sc->ath_led_blink_work, 0); + } else if (led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + sc->sc_flags |= SC_OP_LED_ON; + } else { + sc->led_on_cnt++; + } + break; + default: + break; + } +} + +static int ath_register_led(struct ath_softc *sc, struct ath_led *led, + char *trigger) +{ + int ret; + + led->sc = sc; + led->led_cdev.name = led->name; + led->led_cdev.default_trigger = trigger; + led->led_cdev.brightness_set = ath_led_brightness; + + ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); + if (ret) + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to register led:%s", led->name); + else + led->registered = 1; + return ret; +} + +static void ath_unregister_led(struct ath_led *led) +{ + if (led->registered) { + led_classdev_unregister(&led->led_cdev); + led->registered = 0; + } +} + +static void ath_deinit_leds(struct ath_softc *sc) +{ + cancel_delayed_work_sync(&sc->ath_led_blink_work); + ath_unregister_led(&sc->assoc_led); + sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; + ath_unregister_led(&sc->tx_led); + ath_unregister_led(&sc->rx_led); + ath_unregister_led(&sc->radio_led); + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); +} + +static void ath_init_leds(struct ath_softc *sc) +{ + char *trigger; + int ret; + + /* Configure gpio 1 for output */ + ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + /* LED off, active low */ + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + + INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); + + trigger = ieee80211_get_radio_led_name(sc->hw); + snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), + "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->radio_led, trigger); + sc->radio_led.led_type = ATH_LED_RADIO; + if (ret) + goto fail; + + trigger = ieee80211_get_assoc_led_name(sc->hw); + snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), + "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->assoc_led, trigger); + sc->assoc_led.led_type = ATH_LED_ASSOC; + if (ret) + goto fail; + + trigger = ieee80211_get_tx_led_name(sc->hw); + snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), + "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->tx_led, trigger); + sc->tx_led.led_type = ATH_LED_TX; + if (ret) + goto fail; + + trigger = ieee80211_get_rx_led_name(sc->hw); + snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), + "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->rx_led, trigger); + sc->rx_led.led_type = ATH_LED_RX; + if (ret) + goto fail; + + return; + +fail: + ath_deinit_leds(sc); +} + +void ath_radio_enable(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_channel *channel = sc->hw->conf.channel; + int r; + + ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_resetlock); + + r = ath9k_hw_reset(ah, ah->curchan, false); + + if (r) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset channel %u (%uMhz) ", + "reset status %u\n", + channel->center_freq, r); + } + spin_unlock_bh(&sc->sc_resetlock); + + ath_update_txpow(sc); + if (ath_startrecv(sc) != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to restart recv logic\n"); + return; + } + + if (sc->sc_flags & SC_OP_BEACONS) + ath_beacon_config(sc, NULL); /* restart beacons */ + + /* Re-Enable interrupts */ + ath9k_hw_set_interrupts(ah, sc->imask); + + /* Enable LED */ + ath9k_hw_cfg_output(ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); + + ieee80211_wake_queues(sc->hw); + ath9k_ps_restore(sc); +} + +void ath_radio_disable(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_channel *channel = sc->hw->conf.channel; + int r; + + ath9k_ps_wakeup(sc); + ieee80211_stop_queues(sc->hw); + + /* Disable LED */ + ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1); + ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN); + + /* Disable interrupts */ + ath9k_hw_set_interrupts(ah, 0); + + ath_drain_all_txq(sc, false); /* clear pending tx frames */ + ath_stoprecv(sc); /* turn off frame recv */ + ath_flushrecv(sc); /* flush recv queue */ + + spin_lock_bh(&sc->sc_resetlock); + r = ath9k_hw_reset(ah, ah->curchan, false); + if (r) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset channel %u (%uMhz) " + "reset status %u\n", + channel->center_freq, r); + } + spin_unlock_bh(&sc->sc_resetlock); + + ath9k_hw_phy_disable(ah); + ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); + ath9k_ps_restore(sc); +} + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + +/*******************/ +/* Rfkill */ +/*******************/ + +static bool ath_is_rfkill_set(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + + return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == + ah->rfkill_polarity; +} + +/* h/w rfkill poll function */ +static void ath_rfkill_poll(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + rf_kill.rfkill_poll.work); + bool radio_on; + + if (sc->sc_flags & SC_OP_INVALID) + return; + + radio_on = !ath_is_rfkill_set(sc); + + /* + * enable/disable radio only when there is a + * state change in RF switch + */ + if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) { + enum rfkill_state state; + + if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) { + state = radio_on ? RFKILL_STATE_SOFT_BLOCKED + : RFKILL_STATE_HARD_BLOCKED; + } else if (radio_on) { + ath_radio_enable(sc); + state = RFKILL_STATE_UNBLOCKED; + } else { + ath_radio_disable(sc); + state = RFKILL_STATE_HARD_BLOCKED; + } + + if (state == RFKILL_STATE_HARD_BLOCKED) + sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED; + else + sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED; + + rfkill_force_state(sc->rf_kill.rfkill, state); + } + + queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, + msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL)); +} + +/* s/w rfkill handler */ +static int ath_sw_toggle_radio(void *data, enum rfkill_state state) +{ + struct ath_softc *sc = data; + + switch (state) { + case RFKILL_STATE_SOFT_BLOCKED: + if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED | + SC_OP_RFKILL_SW_BLOCKED))) + ath_radio_disable(sc); + sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED; + return 0; + case RFKILL_STATE_UNBLOCKED: + if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) { + sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED; + if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) { + DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the" + "radio as it is disabled by h/w\n"); + return -EPERM; + } + ath_radio_enable(sc); + } + return 0; + default: + return -EINVAL; + } +} + +/* Init s/w rfkill */ +static int ath_init_sw_rfkill(struct ath_softc *sc) +{ + sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy), + RFKILL_TYPE_WLAN); + if (!sc->rf_kill.rfkill) { + DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n"); + return -ENOMEM; + } + + snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), + "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy)); + sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name; + sc->rf_kill.rfkill->data = sc; + sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; + sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED; + + return 0; +} + +/* Deinitialize rfkill */ +static void ath_deinit_rfkill(struct ath_softc *sc) +{ + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); + + if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) { + rfkill_unregister(sc->rf_kill.rfkill); + sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED; + sc->rf_kill.rfkill = NULL; + } +} + +static int ath_start_rfkill_poll(struct ath_softc *sc) +{ + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + queue_delayed_work(sc->hw->workqueue, + &sc->rf_kill.rfkill_poll, 0); + + if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { + if (rfkill_register(sc->rf_kill.rfkill)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to register rfkill\n"); + rfkill_free(sc->rf_kill.rfkill); + + /* Deinitialize the device */ + ath_cleanup(sc); + return -EIO; + } else { + sc->sc_flags |= SC_OP_RFKILL_REGISTERED; + } + } + + return 0; +} +#endif /* CONFIG_RFKILL */ + +void ath_cleanup(struct ath_softc *sc) +{ + ath_detach(sc); + free_irq(sc->irq, sc); + ath_bus_cleanup(sc); + kfree(sc->sec_wiphy); + ieee80211_free_hw(sc->hw); +} + +void ath_detach(struct ath_softc *sc) +{ + struct ieee80211_hw *hw = sc->hw; + int i = 0; + + ath9k_ps_wakeup(sc); + + DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + ath_deinit_rfkill(sc); +#endif + ath_deinit_leds(sc); + cancel_work_sync(&sc->chan_work); + cancel_delayed_work_sync(&sc->wiphy_work); + + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + if (aphy == NULL) + continue; + sc->sec_wiphy[i] = NULL; + ieee80211_unregister_hw(aphy->hw); + ieee80211_free_hw(aphy->hw); + } + ieee80211_unregister_hw(hw); + ath_rx_cleanup(sc); + ath_tx_cleanup(sc); + + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + + if (!(sc->sc_flags & SC_OP_INVALID)) + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + ath9k_hw_detach(sc->sc_ah); + ath9k_exit_debug(sc); + ath9k_ps_restore(sc); +} + +static int ath9k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_regulatory *reg = &sc->sc_ah->regulatory; + + return ath_reg_notifier_apply(wiphy, request, reg); +} + +static int ath_init(u16 devid, struct ath_softc *sc) +{ + struct ath_hw *ah = NULL; + int status; + int error = 0, i; + int csz = 0; + + /* XXX: hardware will not be ready until ath_open() being called */ + sc->sc_flags |= SC_OP_INVALID; + + if (ath9k_init_debug(sc) < 0) + printk(KERN_ERR "Unable to create debugfs files\n"); + + spin_lock_init(&sc->wiphy_lock); + spin_lock_init(&sc->sc_resetlock); + spin_lock_init(&sc->sc_serial_rw); + mutex_init(&sc->mutex); + tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); + tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, + (unsigned long)sc); + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath_read_cachesize(sc, &csz); + /* XXX assert csz is non-zero */ + sc->cachelsz = csz << 2; /* convert to bytes */ + + ah = ath9k_hw_attach(devid, sc, &status); + if (ah == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to attach hardware; HAL status %d\n", status); + error = -ENXIO; + goto bad; + } + sc->sc_ah = ah; + + /* Get the hardware key cache size. */ + sc->keymax = ah->caps.keycache_size; + if (sc->keymax > ATH_KEYMAX) { + DPRINTF(sc, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, sc->keymax); + sc->keymax = ATH_KEYMAX; + } + + /* + * Reset the key cache since some parts do not + * reset the contents on initial power up. + */ + for (i = 0; i < sc->keymax; i++) + ath9k_hw_keyreset(ah, (u16) i); + + if (ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, + ath9k_reg_notifier)) + goto bad; + + /* default to MONITOR mode */ + sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; + + /* Setup rate tables */ + + ath_rate_attach(sc); + ath_setup_rates(sc, IEEE80211_BAND_2GHZ); + ath_setup_rates(sc, IEEE80211_BAND_5GHZ); + + /* + * Allocate hardware transmit queues: one queue for + * beacon frames and one data queue for each QoS + * priority. Note that the hal handles reseting + * these queues at the needed time. + */ + sc->beacon.beaconq = ath_beaconq_setup(ah); + if (sc->beacon.beaconq == -1) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to setup a beacon xmit queue\n"); + error = -EIO; + goto bad2; + } + sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); + if (sc->beacon.cabq == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to setup CAB xmit queue\n"); + error = -EIO; + goto bad2; + } + + sc->config.cabqReadytime = ATH_CABQ_READY_TIME; + ath_cabq_update(sc); + + for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) + sc->tx.hwq_map[i] = -1; + + /* Setup data queues */ + /* NB: ensure BK queue is the lowest priority h/w queue */ + if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to setup xmit queue for BK traffic\n"); + error = -EIO; + goto bad2; + } + + if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to setup xmit queue for BE traffic\n"); + error = -EIO; + goto bad2; + } + if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to setup xmit queue for VI traffic\n"); + error = -EIO; + goto bad2; + } + if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to setup xmit queue for VO traffic\n"); + error = -EIO; + goto bad2; + } + + /* Initializes the noise floor to a reasonable default value. + * Later on this will be updated during ANI processing. */ + + sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; + setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc); + + if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL)) { + /* + * Whether we should enable h/w TKIP MIC. + * XXX: if we don't support WME TKIP MIC, then we wouldn't + * report WMM capable, so it's always safe to turn on + * TKIP MIC in this case. + */ + ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, + 0, 1, NULL); + } + + /* + * Check whether the separate key cache entries + * are required to handle both tx+rx MIC keys. + * With split mic keys the number of stations is limited + * to 27 otherwise 59. + */ + if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL) + && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_MIC, NULL) + && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, + 0, NULL)) + sc->splitmic = 1; + + /* turn on mcast key search if possible */ + if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) + (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, + 1, NULL); + + sc->config.txpowlimit = ATH_TXPOWER_MAX; + + /* 11n Capabilities */ + if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + sc->sc_flags |= SC_OP_TXAGGR; + sc->sc_flags |= SC_OP_RXAGGR; + } + + sc->tx_chainmask = ah->caps.tx_chainmask; + sc->rx_chainmask = ah->caps.rx_chainmask; + + ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); + sc->rx.defant = ath9k_hw_getdefantenna(ah); + + if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); + + sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ + + /* initialize beacon slots */ + for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { + sc->beacon.bslot[i] = NULL; + sc->beacon.bslot_aphy[i] = NULL; + } + + /* setup channels and rates */ + + sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; + sc->sbands[IEEE80211_BAND_2GHZ].bitrates = + sc->rates[IEEE80211_BAND_2GHZ]; + sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + sc->sbands[IEEE80211_BAND_2GHZ].n_channels = + ARRAY_SIZE(ath9k_2ghz_chantable); + + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { + sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; + sc->sbands[IEEE80211_BAND_5GHZ].bitrates = + sc->rates[IEEE80211_BAND_5GHZ]; + sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; + sc->sbands[IEEE80211_BAND_5GHZ].n_channels = + ARRAY_SIZE(ath9k_5ghz_chantable); + } + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX) + ath9k_hw_btcoex_enable(sc->sc_ah); + + return 0; +bad2: + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); +bad: + if (ah) + ath9k_hw_detach(ah); + ath9k_exit_debug(sc); + + return error; +} + +void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) +{ + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_SPECTRUM_MGMT; + + if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) + hw->flags |= IEEE80211_HW_MFP_CAPABLE; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->queues = 4; + hw->max_rates = 4; + hw->channel_change_time = 5000; + hw->max_listen_interval = 10; + hw->max_rate_tries = ATH_11N_TXMAXTRY; + hw->sta_data_size = sizeof(struct ath_node); + hw->vif_data_size = sizeof(struct ath_vif); + + hw->rate_control_algorithm = "ath9k_rate_control"; + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &sc->sbands[IEEE80211_BAND_2GHZ]; + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &sc->sbands[IEEE80211_BAND_5GHZ]; +} + +int ath_attach(u16 devid, struct ath_softc *sc) +{ + struct ieee80211_hw *hw = sc->hw; + int error = 0, i; + struct ath_regulatory *reg; + + DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); + + error = ath_init(devid, sc); + if (error != 0) + return error; + + reg = &sc->sc_ah->regulatory; + + /* get mac address from hardware and set in mac80211 */ + + SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); + + ath_set_hw_capab(sc, hw); + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); + } + + /* initialize tx/rx engine */ + error = ath_tx_init(sc, ATH_TXBUF); + if (error != 0) + goto error_attach; + + error = ath_rx_init(sc, ATH_RXBUF); + if (error != 0) + goto error_attach; + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + /* Initialze h/w Rfkill */ + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); + + /* Initialize s/w rfkill */ + error = ath_init_sw_rfkill(sc); + if (error) + goto error_attach; +#endif + + INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); + INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); + sc->wiphy_scheduler_int = msecs_to_jiffies(500); + + error = ieee80211_register_hw(hw); + + if (!ath_is_world_regd(reg)) { + error = regulatory_hint(hw->wiphy, reg->alpha2); + if (error) + goto error_attach; + } + + /* Initialize LED control */ + ath_init_leds(sc); + + + return 0; + +error_attach: + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + ath9k_hw_detach(sc->sc_ah); + ath9k_exit_debug(sc); + + return error; +} + +int ath_reset(struct ath_softc *sc, bool retry_tx) +{ + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_hw *hw = sc->hw; + int r; + + ath9k_hw_set_interrupts(ah, 0); + ath_drain_all_txq(sc, retry_tx); + ath_stoprecv(sc); + ath_flushrecv(sc); + + spin_lock_bh(&sc->sc_resetlock); + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); + if (r) + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %u\n", r); + spin_unlock_bh(&sc->sc_resetlock); + + if (ath_startrecv(sc) != 0) + DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); + + /* + * We may be doing a reset in response to a request + * that changes the channel so update any state that + * might change as a result. + */ + ath_cache_conf_rate(sc, &hw->conf); + + ath_update_txpow(sc); + + if (sc->sc_flags & SC_OP_BEACONS) + ath_beacon_config(sc, NULL); /* restart beacons */ + + ath9k_hw_set_interrupts(ah, sc->imask); + + if (retry_tx) { + int i; + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) { + spin_lock_bh(&sc->tx.txq[i].axq_lock); + ath_txq_schedule(sc, &sc->tx.txq[i]); + spin_unlock_bh(&sc->tx.txq[i].axq_lock); + } + } + } + + return r; +} + +/* + * This function will allocate both the DMA descriptor structure, and the + * buffers it contains. These are used to contain the descriptors used + * by the system. +*/ +int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, + struct list_head *head, const char *name, + int nbuf, int ndesc) +{ +#define DS2PHYS(_dd, _ds) \ + ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) +#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) +#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) + + struct ath_desc *ds; + struct ath_buf *bf; + int i, bsize, error; + + DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", + name, nbuf, ndesc); + + INIT_LIST_HEAD(head); + /* ath_desc must be a multiple of DWORDs */ + if ((sizeof(struct ath_desc) % 4) != 0) { + DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); + ASSERT((sizeof(struct ath_desc) % 4) == 0); + error = -ENOMEM; + goto fail; + } + + dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; + + /* + * Need additional DMA memory because we can't use + * descriptors that cross the 4K page boundary. Assume + * one skipped descriptor per 4K page. + */ + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { + u32 ndesc_skipped = + ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); + u32 dma_len; + + while (ndesc_skipped) { + dma_len = ndesc_skipped * sizeof(struct ath_desc); + dd->dd_desc_len += dma_len; + + ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); + }; + } + + /* allocate descriptors */ + dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, + &dd->dd_desc_paddr, GFP_KERNEL); + if (dd->dd_desc == NULL) { + error = -ENOMEM; + goto fail; + } + ds = dd->dd_desc; + DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", + name, ds, (u32) dd->dd_desc_len, + ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); + + /* allocate buffers */ + bsize = sizeof(struct ath_buf) * nbuf; + bf = kzalloc(bsize, GFP_KERNEL); + if (bf == NULL) { + error = -ENOMEM; + goto fail2; + } + dd->dd_bufptr = bf; + + for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { + bf->bf_desc = ds; + bf->bf_daddr = DS2PHYS(dd, ds); + + if (!(sc->sc_ah->caps.hw_caps & + ATH9K_HW_CAP_4KB_SPLITTRANS)) { + /* + * Skip descriptor addresses which can cause 4KB + * boundary crossing (addr + length) with a 32 dword + * descriptor fetch. + */ + while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { + ASSERT((caddr_t) bf->bf_desc < + ((caddr_t) dd->dd_desc + + dd->dd_desc_len)); + + ds += ndesc; + bf->bf_desc = ds; + bf->bf_daddr = DS2PHYS(dd, ds); + } + } + list_add_tail(&bf->list, head); + } + return 0; +fail2: + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); +fail: + memset(dd, 0, sizeof(*dd)); + return error; +#undef ATH_DESC_4KB_BOUND_CHECK +#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED +#undef DS2PHYS +} + +void ath_descdma_cleanup(struct ath_softc *sc, + struct ath_descdma *dd, + struct list_head *head) +{ + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); + + INIT_LIST_HEAD(head); + kfree(dd->dd_bufptr); + memset(dd, 0, sizeof(*dd)); +} + +int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) +{ + int qnum; + + switch (queue) { + case 0: + qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO]; + break; + case 1: + qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI]; + break; + case 2: + qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; + break; + case 3: + qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK]; + break; + default: + qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; + break; + } + + return qnum; +} + +int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) +{ + int qnum; + + switch (queue) { + case ATH9K_WME_AC_VO: + qnum = 0; + break; + case ATH9K_WME_AC_VI: + qnum = 1; + break; + case ATH9K_WME_AC_BE: + qnum = 2; + break; + case ATH9K_WME_AC_BK: + qnum = 3; + break; + default: + qnum = -1; + break; + } + + return qnum; +} + +/* XXX: Remove me once we don't depend on ath9k_channel for all + * this redundant data */ +void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, + struct ath9k_channel *ichan) +{ + struct ieee80211_channel *chan = hw->conf.channel; + struct ieee80211_conf *conf = &hw->conf; + + ichan->channel = chan->center_freq; + ichan->chan = chan; + + if (chan->band == IEEE80211_BAND_2GHZ) { + ichan->chanmode = CHANNEL_G; + ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; + } else { + ichan->chanmode = CHANNEL_A; + ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; + } + + sc->tx_chan_width = ATH9K_HT_MACMODE_20; + + if (conf_is_ht(conf)) { + if (conf_is_ht40(conf)) + sc->tx_chan_width = ATH9K_HT_MACMODE_2040; + + ichan->chanmode = ath_get_extchanmode(sc, chan, + conf->channel_type); + } +} + +/**********************/ +/* mac80211 callbacks */ +/**********************/ + +static int ath9k_start(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ieee80211_channel *curchan = hw->conf.channel; + struct ath9k_channel *init_channel; + int r, pos; + + DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " + "initial channel: %d MHz\n", curchan->center_freq); + + mutex_lock(&sc->mutex); + + if (ath9k_wiphy_started(sc)) { + if (sc->chan_idx == curchan->hw_value) { + /* + * Already on the operational channel, the new wiphy + * can be marked active. + */ + aphy->state = ATH_WIPHY_ACTIVE; + ieee80211_wake_queues(hw); + } else { + /* + * Another wiphy is on another channel, start the new + * wiphy in paused state. + */ + aphy->state = ATH_WIPHY_PAUSED; + ieee80211_stop_queues(hw); + } + mutex_unlock(&sc->mutex); + return 0; + } + aphy->state = ATH_WIPHY_ACTIVE; + + /* setup initial channel */ + + pos = curchan->hw_value; + + sc->chan_idx = pos; + init_channel = &sc->sc_ah->channels[pos]; + ath9k_update_ichannel(sc, hw, init_channel); + + /* Reset SERDES registers */ + ath9k_hw_configpcipowersave(sc->sc_ah, 0); + + /* + * The basic interface to setting the hardware in a good + * state is ``reset''. On return the hardware is known to + * be powered up and with interrupts disabled. This must + * be followed by initialization of the appropriate bits + * and then setup of the interrupt mask. + */ + spin_lock_bh(&sc->sc_resetlock); + r = ath9k_hw_reset(sc->sc_ah, init_channel, false); + if (r) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %u " + "(freq %u MHz)\n", r, + curchan->center_freq); + spin_unlock_bh(&sc->sc_resetlock); + goto mutex_unlock; + } + spin_unlock_bh(&sc->sc_resetlock); + + /* + * This is needed only to setup initial state + * but it's best done after a reset. + */ + ath_update_txpow(sc); + + /* + * Setup the hardware after reset: + * The receive engine is set going. + * Frame transmit is handled entirely + * in the frame output path; there's nothing to do + * here except setup the interrupt mask. + */ + if (ath_startrecv(sc) != 0) { + DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); + r = -EIO; + goto mutex_unlock; + } + + /* Setup our intr mask. */ + sc->imask = ATH9K_INT_RX | ATH9K_INT_TX + | ATH9K_INT_RXEOL | ATH9K_INT_RXORN + | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT) + sc->imask |= ATH9K_INT_GTT; + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) + sc->imask |= ATH9K_INT_CST; + + ath_cache_conf_rate(sc, &hw->conf); + + sc->sc_flags &= ~SC_OP_INVALID; + + /* Disable BMISS interrupt when we're not associated */ + sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); + ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + + ieee80211_wake_queues(hw); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + r = ath_start_rfkill_poll(sc); +#endif + +mutex_unlock: + mutex_unlock(&sc->mutex); + + return r; +} + +static int ath9k_tx(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_tx_control txctl; + int hdrlen, padsize; + + if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { + printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " + "%d\n", wiphy_name(hw->wiphy), aphy->state); + goto exit; + } + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + + /* + * As a temporary workaround, assign seq# here; this will likely need + * to be cleaned up to work better with Beacon transmission and virtual + * BSSes. + */ + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + sc->tx.seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); + } + + /* Add the padding after the header if this is not already done */ + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + if (hdrlen & 3) { + padsize = hdrlen % 4; + if (skb_headroom(skb) < padsize) + return -1; + skb_push(skb, padsize); + memmove(skb->data, skb->data + padsize, hdrlen); + } + + /* Check if a tx queue is available */ + + txctl.txq = ath_test_get_txq(sc, skb); + if (!txctl.txq) + goto exit; + + DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); + + if (ath_tx_start(hw, skb, &txctl) != 0) { + DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n"); + goto exit; + } + + return 0; +exit: + dev_kfree_skb_any(skb); + return 0; +} + +static void ath9k_stop(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + aphy->state = ATH_WIPHY_INACTIVE; + + if (sc->sc_flags & SC_OP_INVALID) { + DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); + return; + } + + mutex_lock(&sc->mutex); + + ieee80211_stop_queues(hw); + + if (ath9k_wiphy_started(sc)) { + mutex_unlock(&sc->mutex); + return; /* another wiphy still in use */ + } + + /* make sure h/w will not generate any interrupt + * before setting the invalid flag. */ + ath9k_hw_set_interrupts(sc->sc_ah, 0); + + if (!(sc->sc_flags & SC_OP_INVALID)) { + ath_drain_all_txq(sc, false); + ath_stoprecv(sc); + ath9k_hw_phy_disable(sc->sc_ah); + } else + sc->rx.rxlink = NULL; + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); +#endif + /* disable HAL and put h/w to sleep */ + ath9k_hw_disable(sc->sc_ah); + ath9k_hw_configpcipowersave(sc->sc_ah, 1); + + sc->sc_flags |= SC_OP_INVALID; + + mutex_unlock(&sc->mutex); + + DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n"); +} + +static int ath9k_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_vif *avp = (void *)conf->vif->drv_priv; + enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; + int ret = 0; + + mutex_lock(&sc->mutex); + + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && + sc->nvifs > 0) { + ret = -ENOBUFS; + goto out; + } + + switch (conf->type) { + case NL80211_IFTYPE_STATION: + ic_opmode = NL80211_IFTYPE_STATION; + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + if (sc->nbcnvifs >= ATH_BCBUF) { + ret = -ENOBUFS; + goto out; + } + ic_opmode = conf->type; + break; + default: + DPRINTF(sc, ATH_DBG_FATAL, + "Interface type %d not yet supported\n", conf->type); + ret = -EOPNOTSUPP; + goto out; + } + + DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); + + /* Set the VIF opmode */ + avp->av_opmode = ic_opmode; + avp->av_bslot = -1; + + sc->nvifs++; + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + ath9k_set_bssid_mask(hw); + + if (sc->nvifs > 1) + goto out; /* skip global settings for secondary vif */ + + if (ic_opmode == NL80211_IFTYPE_AP) { + ath9k_hw_set_tsfadjust(sc->sc_ah, 1); + sc->sc_flags |= SC_OP_TSF_RESET; + } + + /* Set the device opmode */ + sc->sc_ah->opmode = ic_opmode; + + /* + * Enable MIB interrupts when there are hardware phy counters. + * Note we only do this (at the moment) for station mode. + */ + if ((conf->type == NL80211_IFTYPE_STATION) || + (conf->type == NL80211_IFTYPE_ADHOC) || + (conf->type == NL80211_IFTYPE_MESH_POINT)) { + if (ath9k_hw_phycounters(sc->sc_ah)) + sc->imask |= ATH9K_INT_MIB; + sc->imask |= ATH9K_INT_TSFOOR; + } + + ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); + + if (conf->type == NL80211_IFTYPE_AP) { + /* TODO: is this a suitable place to start ANI for AP mode? */ + /* Start ANI */ + mod_timer(&sc->ani.timer, + jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + } + +out: + mutex_unlock(&sc->mutex); + return ret; +} + +static void ath9k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_vif *avp = (void *)conf->vif->drv_priv; + int i; + + DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); + + mutex_lock(&sc->mutex); + + /* Stop ANI */ + del_timer_sync(&sc->ani.timer); + + /* Reclaim beacon resources */ + if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || + (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + ath_beacon_return(sc, avp); + } + + sc->sc_flags &= ~SC_OP_BEACONS; + + for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { + if (sc->beacon.bslot[i] == conf->vif) { + printk(KERN_DEBUG "%s: vif had allocated beacon " + "slot\n", __func__); + sc->beacon.bslot[i] = NULL; + sc->beacon.bslot_aphy[i] = NULL; + } + } + + sc->nvifs--; + + mutex_unlock(&sc->mutex); +} + +static int ath9k_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ieee80211_conf *conf = &hw->conf; + struct ath_hw *ah = sc->sc_ah; + + mutex_lock(&sc->mutex); + + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) { + if (!(ah->caps.hw_caps & + ATH9K_HW_CAP_AUTOSLEEP)) { + if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { + sc->imask |= ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } + ath9k_hw_setrxabort(sc->sc_ah, 1); + } + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); + } else { + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + if (!(ah->caps.hw_caps & + ATH9K_HW_CAP_AUTOSLEEP)) { + ath9k_hw_setrxabort(sc->sc_ah, 0); + sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; + if (sc->imask & ATH9K_INT_TIM_TIMER) { + sc->imask &= ~ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } + } + } + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + struct ieee80211_channel *curchan = hw->conf.channel; + int pos = curchan->hw_value; + + aphy->chan_idx = pos; + aphy->chan_is_ht = conf_is_ht(conf); + + if (aphy->state == ATH_WIPHY_SCAN || + aphy->state == ATH_WIPHY_ACTIVE) + ath9k_wiphy_pause_all_forced(sc, aphy); + else { + /* + * Do not change operational channel based on a paused + * wiphy changes. + */ + goto skip_chan_change; + } + + DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); + + /* XXX: remove me eventualy */ + ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); + + ath_update_chainmask(sc, conf_is_ht(conf)); + + if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { + DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); + mutex_unlock(&sc->mutex); + return -EINVAL; + } + } + +skip_chan_change: + if (changed & IEEE80211_CONF_CHANGE_POWER) + sc->config.txpowlimit = 2 * conf->power_level; + + /* + * The HW TSF has to be reset when the beacon interval changes. + * We set the flag here, and ath_beacon_config_ap() would take this + * into account when it gets called through the subsequent + * config_interface() call - with IFCC_BEACON in the changed field. + */ + + if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) + sc->sc_flags |= SC_OP_TSF_RESET; + + mutex_unlock(&sc->mutex); + + return 0; +} + +static int ath9k_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + struct ath_vif *avp = (void *)vif->drv_priv; + u32 rfilt = 0; + int error, i; + + mutex_lock(&sc->mutex); + + /* TODO: Need to decide which hw opmode to use for multi-interface + * cases */ + if (vif->type == NL80211_IFTYPE_AP && + ah->opmode != NL80211_IFTYPE_AP) { + ah->opmode = NL80211_IFTYPE_STATION; + ath9k_hw_setopmode(ah); + memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); + sc->curaid = 0; + ath9k_hw_write_associd(sc); + /* Request full reset to get hw opmode changed properly */ + sc->sc_flags |= SC_OP_FULL_RESET; + } + + if ((conf->changed & IEEE80211_IFCC_BSSID) && + !is_zero_ether_addr(conf->bssid)) { + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + /* Set BSSID */ + memcpy(sc->curbssid, conf->bssid, ETH_ALEN); + memcpy(avp->bssid, conf->bssid, ETH_ALEN); + sc->curaid = 0; + ath9k_hw_write_associd(sc); + + /* Set aggregation protection mode parameters */ + sc->config.ath_aggr_prot = 0; + + DPRINTF(sc, ATH_DBG_CONFIG, + "RX filter 0x%x bssid %pM aid 0x%x\n", + rfilt, sc->curbssid, sc->curaid); + + /* need to reconfigure the beacon */ + sc->sc_flags &= ~SC_OP_BEACONS ; + + break; + default: + break; + } + } + + if ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { + if ((conf->changed & IEEE80211_IFCC_BEACON) || + (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && + conf->enable_beacon)) { + /* + * Allocate and setup the beacon frame. + * + * Stop any previous beacon DMA. This may be + * necessary, for example, when an ibss merge + * causes reconfiguration; we may be called + * with beacon transmission active. + */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + + error = ath_beacon_alloc(aphy, vif); + if (error != 0) { + mutex_unlock(&sc->mutex); + return error; + } + + ath_beacon_config(sc, vif); + } + } + + /* Check for WLAN_CAPABILITY_PRIVACY ? */ + if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { + for (i = 0; i < IEEE80211_WEP_NKID; i++) + if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) + ath9k_hw_keysetmac(sc->sc_ah, + (u16)i, + sc->curbssid); + } + + /* Only legacy IBSS for now */ + if (vif->type == NL80211_IFTYPE_ADHOC) + ath_update_chainmask(sc, 0); + + mutex_unlock(&sc->mutex); + + return 0; +} + +#define SUPPORTED_FILTERS \ + (FIF_PROMISC_IN_BSS | \ + FIF_ALLMULTI | \ + FIF_CONTROL | \ + FIF_OTHER_BSS | \ + FIF_BCN_PRBRESP_PROMISC | \ + FIF_FCSFAIL) + +/* FIXME: sc->sc_full_reset ? */ +static void ath9k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_mc_list *mclist) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + u32 rfilt; + + changed_flags &= SUPPORTED_FILTERS; + *total_flags &= SUPPORTED_FILTERS; + + sc->rx.rxfilter = *total_flags; + rfilt = ath_calcrxfilter(sc); + ath9k_hw_setrxfilter(sc->sc_ah, rfilt); + + DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter); +} + +static void ath9k_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + switch (cmd) { + case STA_NOTIFY_ADD: + ath_node_attach(sc, sta); + break; + case STA_NOTIFY_REMOVE: + ath_node_detach(sc, sta); + break; + default: + break; + } +} + +static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath9k_tx_queue_info qi; + int ret = 0, qnum; + + if (queue >= WME_NUM_AC) + return 0; + + mutex_lock(&sc->mutex); + + memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); + + qi.tqi_aifs = params->aifs; + qi.tqi_cwmin = params->cw_min; + qi.tqi_cwmax = params->cw_max; + qi.tqi_burstTime = params->txop; + qnum = ath_get_hal_qnum(queue, sc); + + DPRINTF(sc, ATH_DBG_CONFIG, + "Configure tx [queue/halq] [%d/%d], " + "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); + + ret = ath_txq_update(sc, qnum, &qi); + if (ret) + DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n"); + + mutex_unlock(&sc->mutex); + + return ret; +} + +static int ath9k_set_key(struct ieee80211_hw *hw, + enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + int ret = 0; + + if (modparam_nohwcrypt) + return -ENOSPC; + + mutex_lock(&sc->mutex); + ath9k_ps_wakeup(sc); + DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); + + switch (cmd) { + case SET_KEY: + ret = ath_key_config(sc, vif, sta, key); + if (ret >= 0) { + key->hw_key_idx = ret; + /* push IV and Michael MIC generation to stack */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + if (key->alg == ALG_TKIP) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; + ret = 0; + } + break; + case DISABLE_KEY: + ath_key_delete(sc, key); + break; + default: + ret = -EINVAL; + } + + ath9k_ps_restore(sc); + mutex_unlock(&sc->mutex); + + return ret; +} + +static void ath9k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + mutex_lock(&sc->mutex); + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + sc->sc_flags |= SC_OP_PREAMBLE_SHORT; + else + sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; + } + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && + hw->conf.channel->band != IEEE80211_BAND_5GHZ) + sc->sc_flags |= SC_OP_PROTECT_ENABLE; + else + sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; + } + + if (changed & BSS_CHANGED_ASSOC) { + DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + bss_conf->assoc); + ath9k_bss_assoc_info(sc, vif, bss_conf); + } + + mutex_unlock(&sc->mutex); +} + +static u64 ath9k_get_tsf(struct ieee80211_hw *hw) +{ + u64 tsf; + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + mutex_lock(&sc->mutex); + tsf = ath9k_hw_gettsf64(sc->sc_ah); + mutex_unlock(&sc->mutex); + + return tsf; +} + +static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + mutex_lock(&sc->mutex); + ath9k_hw_settsf64(sc->sc_ah, tsf); + mutex_unlock(&sc->mutex); +} + +static void ath9k_reset_tsf(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + mutex_lock(&sc->mutex); + ath9k_hw_reset_tsf(sc->sc_ah); + mutex_unlock(&sc->mutex); +} + +static int ath9k_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + int ret = 0; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + if (!(sc->sc_flags & SC_OP_RXAGGR)) + ret = -ENOTSUPP; + break; + case IEEE80211_AMPDU_RX_STOP: + break; + case IEEE80211_AMPDU_TX_START: + ret = ath_tx_aggr_start(sc, sta, tid, ssn); + if (ret < 0) + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to start TX aggregation\n"); + else + ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP: + ret = ath_tx_aggr_stop(sc, sta, tid); + if (ret < 0) + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to stop TX aggregation\n"); + + ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + ath_tx_aggr_resume(sc, sta, tid); + break; + default: + DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); + } + + return ret; +} + +static void ath9k_sw_scan_start(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + if (ath9k_wiphy_scanning(sc)) { + printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the " + "same time\n"); + /* + * Do not allow the concurrent scanning state for now. This + * could be improved with scanning control moved into ath9k. + */ + return; + } + + aphy->state = ATH_WIPHY_SCAN; + ath9k_wiphy_pause_all_forced(sc, aphy); + + mutex_lock(&sc->mutex); + sc->sc_flags |= SC_OP_SCANNING; + mutex_unlock(&sc->mutex); +} + +static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + mutex_lock(&sc->mutex); + aphy->state = ATH_WIPHY_ACTIVE; + sc->sc_flags &= ~SC_OP_SCANNING; + mutex_unlock(&sc->mutex); +} + +struct ieee80211_ops ath9k_ops = { + .tx = ath9k_tx, + .start = ath9k_start, + .stop = ath9k_stop, + .add_interface = ath9k_add_interface, + .remove_interface = ath9k_remove_interface, + .config = ath9k_config, + .config_interface = ath9k_config_interface, + .configure_filter = ath9k_configure_filter, + .sta_notify = ath9k_sta_notify, + .conf_tx = ath9k_conf_tx, + .bss_info_changed = ath9k_bss_info_changed, + .set_key = ath9k_set_key, + .get_tsf = ath9k_get_tsf, + .set_tsf = ath9k_set_tsf, + .reset_tsf = ath9k_reset_tsf, + .ampdu_action = ath9k_ampdu_action, + .sw_scan_start = ath9k_sw_scan_start, + .sw_scan_complete = ath9k_sw_scan_complete, +}; + +static struct { + u32 version; + const char * name; +} ath_mac_bb_names[] = { + { AR_SREV_VERSION_5416_PCI, "5416" }, + { AR_SREV_VERSION_5416_PCIE, "5418" }, + { AR_SREV_VERSION_9100, "9100" }, + { AR_SREV_VERSION_9160, "9160" }, + { AR_SREV_VERSION_9280, "9280" }, + { AR_SREV_VERSION_9285, "9285" } +}; + +static struct { + u16 version; + const char * name; +} ath_rf_names[] = { + { 0, "5133" }, + { AR_RAD5133_SREV_MAJOR, "5133" }, + { AR_RAD5122_SREV_MAJOR, "5122" }, + { AR_RAD2133_SREV_MAJOR, "2133" }, + { AR_RAD2122_SREV_MAJOR, "2122" } +}; + +/* + * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. + */ +const char * +ath_mac_bb_name(u32 mac_bb_version) +{ + int i; + + for (i=0; i +#include +#include "ath9k.h" + +static struct pci_device_id ath_pci_id_table[] __devinitdata = { + { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ + { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ + { 0 } +}; + +/* return bus cachesize in 4B word units */ +static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) +{ + u8 u8tmp; + + pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, + (u8 *)&u8tmp); + *csz = (int)u8tmp; + + /* + * This check was put in to avoid "unplesant" consequences if + * the bootrom has not fully initialized all PCI devices. + * Sometimes the cache line size register is not set + */ + + if (*csz == 0) + *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ +} + +static void ath_pci_cleanup(struct ath_softc *sc) +{ + struct pci_dev *pdev = to_pci_dev(sc->dev); + + pci_iounmap(pdev, sc->mem); + pci_disable_device(pdev); + pci_release_region(pdev, 0); +} + +static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) +{ + (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); + + if (!ath9k_hw_wait(ah, + AR_EEPROM_STATUS_DATA, + AR_EEPROM_STATUS_DATA_BUSY | + AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, + AH_WAIT_TIMEOUT)) { + return false; + } + + *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), + AR_EEPROM_STATUS_DATA_VAL); + + return true; +} + +static struct ath_bus_ops ath_pci_bus_ops = { + .read_cachesize = ath_pci_read_cachesize, + .cleanup = ath_pci_cleanup, + .eeprom_read = ath_pci_eeprom_read, +}; + +static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + void __iomem *mem; + struct ath_wiphy *aphy; + struct ath_softc *sc; + struct ieee80211_hw *hw; + u8 csz; + int ret = 0; + struct ath_hw *ah; + + if (pci_enable_device(pdev)) + return -EIO; + + ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + + if (ret) { + printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); + goto bad; + } + + ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + + if (ret) { + printk(KERN_ERR "ath9k: 32-bit DMA consistent " + "DMA enable failed\n"); + goto bad; + } + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); + if (csz == 0) { + /* + * Linux 2.4.18 (at least) writes the cache line size + * register as a 16-bit wide register which is wrong. + * We must have this setup properly for rx buffer + * DMA to work so force a reasonable value here if it + * comes up zero. + */ + csz = L1_CACHE_BYTES / sizeof(u32); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); + } + /* + * The default setting of latency timer yields poor results, + * set it to the value used by other systems. It may be worth + * tweaking this setting more. + */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); + + pci_set_master(pdev); + + ret = pci_request_region(pdev, 0, "ath9k"); + if (ret) { + dev_err(&pdev->dev, "PCI memory region reserve error\n"); + ret = -ENODEV; + goto bad; + } + + mem = pci_iomap(pdev, 0, 0); + if (!mem) { + printk(KERN_ERR "PCI memory map error\n") ; + ret = -EIO; + goto bad1; + } + + hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + + sizeof(struct ath_softc), &ath9k_ops); + if (hw == NULL) { + printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); + goto bad2; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + aphy = hw->priv; + sc = (struct ath_softc *) (aphy + 1); + aphy->sc = sc; + aphy->hw = hw; + sc->pri_wiphy = aphy; + sc->hw = hw; + sc->dev = &pdev->dev; + sc->mem = mem; + sc->bus_ops = &ath_pci_bus_ops; + + if (ath_attach(id->device, sc) != 0) { + ret = -ENODEV; + goto bad3; + } + + /* setup interrupt service routine */ + + if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { + printk(KERN_ERR "%s: request_irq failed\n", + wiphy_name(hw->wiphy)); + ret = -EIO; + goto bad4; + } + + sc->irq = pdev->irq; + + ah = sc->sc_ah; + printk(KERN_INFO + "%s: Atheros AR%s MAC/BB Rev:%x " + "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", + wiphy_name(hw->wiphy), + ath_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev, + ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), + ah->hw_version.phyRev, + (unsigned long)mem, pdev->irq); + + return 0; +bad4: + ath_detach(sc); +bad3: + ieee80211_free_hw(hw); +bad2: + pci_iounmap(pdev, mem); +bad1: + pci_release_region(pdev, 0); +bad: + pci_disable_device(pdev); + return ret; +} + +static void ath_pci_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + ath_cleanup(sc); +} + +#ifdef CONFIG_PM + +static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); +#endif + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int ath_pci_resume(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + int err; + + err = pci_enable_device(pdev); + if (err) + return err; + pci_restore_state(pdev); + + /* Enable LED */ + ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) + /* + * check the h/w rfkill state on resume + * and start the rfkill poll timer + */ + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + queue_delayed_work(sc->hw->workqueue, + &sc->rf_kill.rfkill_poll, 0); +#endif + + return 0; +} + +#endif /* CONFIG_PM */ + +MODULE_DEVICE_TABLE(pci, ath_pci_id_table); + +static struct pci_driver ath_pci_driver = { + .name = "ath9k", + .id_table = ath_pci_id_table, + .probe = ath_pci_probe, + .remove = ath_pci_remove, +#ifdef CONFIG_PM + .suspend = ath_pci_suspend, + .resume = ath_pci_resume, +#endif /* CONFIG_PM */ +}; + +int ath_pci_init(void) +{ + return pci_register_driver(&ath_pci_driver); +} + +void ath_pci_exit(void) +{ + pci_unregister_driver(&ath_pci_driver); +} diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c new file mode 100644 index 000000000000..5ec9ce91d979 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/phy.c @@ -0,0 +1,424 @@ +/* + * 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 "ath9k.h" + +void +ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, + int regWrites) +{ + REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); +} + +bool +ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ + u32 channelSel = 0; + u32 bModeSynth = 0; + u32 aModeRefSel = 0; + u32 reg32 = 0; + u16 freq; + struct chan_centers centers; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + if (freq < 4800) { + u32 txctl; + + if (((freq - 2192) % 5) == 0) { + channelSel = ((freq - 672) * 2 - 3040) / 10; + bModeSynth = 0; + } else if (((freq - 2224) % 5) == 0) { + channelSel = ((freq - 704) * 2 - 3040) / 10; + bModeSynth = 1; + } else { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return false; + } + + channelSel = (channelSel << 2) & 0xff; + channelSel = ath9k_hw_reverse_bits(channelSel, 8); + + txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); + } + + } else if ((freq % 20) == 0 && freq >= 5120) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 10) == 0) { + channelSel = + ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); + if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) + aModeRefSel = ath9k_hw_reverse_bits(2, 2); + else + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else if ((freq % 5) == 0) { + channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); + aModeRefSel = ath9k_hw_reverse_bits(1, 2); + } else { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Invalid channel %u MHz\n", freq); + return false; + } + + reg32 = + (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | + (1 << 5) | 0x1; + + REG_WRITE(ah, AR_PHY(0x37), reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + + return true; +} + +bool +ath9k_hw_ar9280_set_channel(struct ath_hw *ah, + struct ath9k_channel *chan) +{ + u16 bMode, fracMode, aModeRefSel = 0; + u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; + struct chan_centers centers; + u32 refDivA = 24; + + ath9k_hw_get_channel_centers(ah, chan, ¢ers); + freq = centers.synth_center; + + reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); + reg32 &= 0xc0000000; + + if (freq < 4800) { + u32 txctl; + + bMode = 1; + fracMode = 1; + aModeRefSel = 0; + channelSel = (freq * 0x10000) / 15; + + txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); + if (freq == 2484) { + + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl | AR_PHY_CCK_TX_CTRL_JAPAN); + } else { + REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, + txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); + } + } else { + bMode = 0; + fracMode = 0; + + switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { + case 0: + if ((freq % 20) == 0) { + aModeRefSel = 3; + } else if ((freq % 10) == 0) { + aModeRefSel = 2; + } + if (aModeRefSel) + break; + case 1: + default: + aModeRefSel = 0; + fracMode = 1; + refDivA = 1; + channelSel = (freq * 0x8000) / 15; + + REG_RMW_FIELD(ah, AR_AN_SYNTH9, + AR_AN_SYNTH9_REFDIVA, refDivA); + + } + + if (!fracMode) { + ndiv = (freq * (refDivA >> aModeRefSel)) / 60; + channelSel = ndiv & 0x1ff; + channelFrac = (ndiv & 0xfffffe00) * 2; + channelSel = (channelSel << 17) | channelFrac; + } + } + + reg32 = reg32 | + (bMode << 29) | + (fracMode << 28) | (aModeRefSel << 26) | (channelSel); + + REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + + ah->curchan = chan; + ah->curchan_rad_index = -1; + + return true; +} + +static void +ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, + u32 numBits, u32 firstBit, + u32 column) +{ + u32 tmp32, mask, arrayEntry, lastBit; + int32_t bitPosition, bitsLeft; + + tmp32 = ath9k_hw_reverse_bits(reg32, numBits); + arrayEntry = (firstBit - 1) / 8; + bitPosition = (firstBit - 1) % 8; + bitsLeft = numBits; + while (bitsLeft > 0) { + lastBit = (bitPosition + bitsLeft > 8) ? + 8 : bitPosition + bitsLeft; + mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << + (column * 8); + rfBuf[arrayEntry] &= ~mask; + rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << + (column * 8)) & mask; + bitsLeft -= 8 - bitPosition; + tmp32 = tmp32 >> (8 - bitPosition); + bitPosition = 0; + arrayEntry++; + } +} + +bool +ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, + u16 modesIndex) +{ + u32 eepMinorRev; + u32 ob5GHz = 0, db5GHz = 0; + u32 ob2GHz = 0, db2GHz = 0; + int regWrites = 0; + + if (AR_SREV_9280_10_OR_LATER(ah)) + return true; + + eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); + + RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); + + RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); + + RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); + + RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, + modesIndex); + { + int i; + for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { + ah->analogBank6Data[i] = + INI_RA(&ah->iniBank6TPC, i, modesIndex); + } + } + + if (eepMinorRev >= 2) { + if (IS_CHAN_2GHZ(chan)) { + ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); + db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); + ath9k_phy_modify_rx_buffer(ah->analogBank6Data, + ob2GHz, 3, 197, 0); + ath9k_phy_modify_rx_buffer(ah->analogBank6Data, + db2GHz, 3, 194, 0); + } else { + ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); + db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); + ath9k_phy_modify_rx_buffer(ah->analogBank6Data, + ob5GHz, 3, 203, 0); + ath9k_phy_modify_rx_buffer(ah->analogBank6Data, + db5GHz, 3, 200, 0); + } + } + + RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); + + REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, + regWrites); + REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, + regWrites); + + return true; +} + +void +ath9k_hw_rfdetach(struct ath_hw *ah) +{ + if (ah->analogBank0Data != NULL) { + kfree(ah->analogBank0Data); + ah->analogBank0Data = NULL; + } + if (ah->analogBank1Data != NULL) { + kfree(ah->analogBank1Data); + ah->analogBank1Data = NULL; + } + if (ah->analogBank2Data != NULL) { + kfree(ah->analogBank2Data); + ah->analogBank2Data = NULL; + } + if (ah->analogBank3Data != NULL) { + kfree(ah->analogBank3Data); + ah->analogBank3Data = NULL; + } + if (ah->analogBank6Data != NULL) { + kfree(ah->analogBank6Data); + ah->analogBank6Data = NULL; + } + if (ah->analogBank6TPCData != NULL) { + kfree(ah->analogBank6TPCData); + ah->analogBank6TPCData = NULL; + } + if (ah->analogBank7Data != NULL) { + kfree(ah->analogBank7Data); + ah->analogBank7Data = NULL; + } + if (ah->addac5416_21 != NULL) { + kfree(ah->addac5416_21); + ah->addac5416_21 = NULL; + } + if (ah->bank6Temp != NULL) { + kfree(ah->bank6Temp); + ah->bank6Temp = NULL; + } +} + +bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) +{ + if (!AR_SREV_9280_10_OR_LATER(ah)) { + ah->analogBank0Data = + kzalloc((sizeof(u32) * + ah->iniBank0.ia_rows), GFP_KERNEL); + ah->analogBank1Data = + kzalloc((sizeof(u32) * + ah->iniBank1.ia_rows), GFP_KERNEL); + ah->analogBank2Data = + kzalloc((sizeof(u32) * + ah->iniBank2.ia_rows), GFP_KERNEL); + ah->analogBank3Data = + kzalloc((sizeof(u32) * + ah->iniBank3.ia_rows), GFP_KERNEL); + ah->analogBank6Data = + kzalloc((sizeof(u32) * + ah->iniBank6.ia_rows), GFP_KERNEL); + ah->analogBank6TPCData = + kzalloc((sizeof(u32) * + ah->iniBank6TPC.ia_rows), GFP_KERNEL); + ah->analogBank7Data = + kzalloc((sizeof(u32) * + ah->iniBank7.ia_rows), GFP_KERNEL); + + if (ah->analogBank0Data == NULL + || ah->analogBank1Data == NULL + || ah->analogBank2Data == NULL + || ah->analogBank3Data == NULL + || ah->analogBank6Data == NULL + || ah->analogBank6TPCData == NULL + || ah->analogBank7Data == NULL) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Cannot allocate RF banks\n"); + *status = -ENOMEM; + return false; + } + + ah->addac5416_21 = + kzalloc((sizeof(u32) * + ah->iniAddac.ia_rows * + ah->iniAddac.ia_columns), GFP_KERNEL); + if (ah->addac5416_21 == NULL) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Cannot allocate addac5416_21\n"); + *status = -ENOMEM; + return false; + } + + ah->bank6Temp = + kzalloc((sizeof(u32) * + ah->iniBank6.ia_rows), GFP_KERNEL); + if (ah->bank6Temp == NULL) { + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, + "Cannot allocate bank6Temp\n"); + *status = -ENOMEM; + return false; + } + } + + return true; +} + +void +ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) +{ + int i, regWrites = 0; + u32 bank6SelMask; + u32 *bank6Temp = ah->bank6Temp; + + switch (ah->diversity_control) { + case ATH9K_ANT_FIXED_A: + bank6SelMask = + (ah-> + antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 : + REDUCE_CHAIN_1; + break; + case ATH9K_ANT_FIXED_B: + bank6SelMask = + (ah-> + antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 : + REDUCE_CHAIN_0; + break; + case ATH9K_ANT_VARIABLE: + return; + break; + default: + return; + break; + } + + for (i = 0; i < ah->iniBank6.ia_rows; i++) + bank6Temp[i] = ah->analogBank6Data[i]; + + REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); + + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); + ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); + + REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); + + REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); +#ifdef ALTER_SWITCH + REG_WRITE(ah, PHY_SWITCH_CHAIN_0, + (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) + | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); +#endif +} diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h new file mode 100644 index 000000000000..296d0e985f25 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -0,0 +1,576 @@ +/* + * 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 PHY_H +#define PHY_H + +bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah, + struct ath9k_channel + *chan); +bool ath9k_hw_set_channel(struct ath_hw *ah, + struct ath9k_channel *chan); +void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, + u32 freqIndex, int regWrites); +bool ath9k_hw_set_rf_regs(struct ath_hw *ah, + struct ath9k_channel *chan, + u16 modesIndex); +void ath9k_hw_decrease_chain_power(struct ath_hw *ah, + struct ath9k_channel *chan); +bool ath9k_hw_init_rf(struct ath_hw *ah, + int *status); + +#define AR_PHY_BASE 0x9800 +#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) + +#define AR_PHY_TEST 0x9800 +#define PHY_AGC_CLR 0x10000000 +#define RFSILENT_BB 0x00002000 + +#define AR_PHY_TURBO 0x9804 +#define AR_PHY_FC_TURBO_MODE 0x00000001 +#define AR_PHY_FC_TURBO_SHORT 0x00000002 +#define AR_PHY_FC_DYN2040_EN 0x00000004 +#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 +#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 +#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 +#define AR_PHY_FC_HT_EN 0x00000040 +#define AR_PHY_FC_SHORT_GI_40 0x00000080 +#define AR_PHY_FC_WALSH 0x00000100 +#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 +#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800 + +#define AR_PHY_TEST2 0x9808 + +#define AR_PHY_TIMING2 0x9810 +#define AR_PHY_TIMING3 0x9814 +#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S 17 +#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S 13 + +#define AR_PHY_CHIP_ID 0x9818 +#define AR_PHY_CHIP_ID_REV_0 0x80 +#define AR_PHY_CHIP_ID_REV_1 0x81 +#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 + +#define AR_PHY_ACTIVE 0x981C +#define AR_PHY_ACTIVE_EN 0x00000001 +#define AR_PHY_ACTIVE_DIS 0x00000000 + +#define AR_PHY_RF_CTL2 0x9824 +#define AR_PHY_TX_END_DATA_START 0x000000FF +#define AR_PHY_TX_END_DATA_START_S 0 +#define AR_PHY_TX_END_PA_ON 0x0000FF00 +#define AR_PHY_TX_END_PA_ON_S 8 + +#define AR_PHY_RF_CTL3 0x9828 +#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 + +#define AR_PHY_ADC_CTL 0x982C +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 +#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 +#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 +#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 + +#define AR_PHY_ADC_SERIAL_CTL 0x9830 +#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 +#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 + +#define AR_PHY_RF_CTL4 0x9834 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 + +#define AR_PHY_TSTDAC_CONST 0x983c + +#define AR_PHY_SETTLING 0x9844 +#define AR_PHY_SETTLING_SWITCH 0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S 7 + +#define AR_PHY_RXGAIN 0x9848 +#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 + +#define AR_PHY_DESIRED_SZ 0x9850 +#define AR_PHY_DESIRED_SZ_ADC 0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S 0 +#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S 8 +#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 + +#define AR_PHY_FIND_SIG 0x9858 +#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S 12 +#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S 18 + +#define AR_PHY_AGC_CTL1 0x985C +#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 +#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 +#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 +#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 + +#define AR_PHY_AGC_CONTROL 0x9860 +#define AR_PHY_AGC_CONTROL_CAL 0x00000001 +#define AR_PHY_AGC_CONTROL_NF 0x00000002 +#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 +#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 + +#define AR_PHY_CCA 0x9864 +#define AR_PHY_MINCCA_PWR 0x0FF80000 +#define AR_PHY_MINCCA_PWR_S 19 +#define AR_PHY_CCA_THRESH62 0x0007F000 +#define AR_PHY_CCA_THRESH62_S 12 +#define AR9280_PHY_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S 20 +#define AR9280_PHY_CCA_THRESH62 0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S 12 + +#define AR_PHY_SFCORR_LOW 0x986C +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 + +#define AR_PHY_SFCORR 0x9868 +#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S 0 +#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S 17 +#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S 24 + +#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 +#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 +#define AR_PHY_SYNTH_CONTROL 0x9874 +#define AR_PHY_SLEEP_SCAL 0x9878 + +#define AR_PHY_PLL_CTL 0x987c +#define AR_PHY_PLL_CTL_40 0xaa +#define AR_PHY_PLL_CTL_40_5413 0x04 +#define AR_PHY_PLL_CTL_44 0xab +#define AR_PHY_PLL_CTL_44_2133 0xeb +#define AR_PHY_PLL_CTL_40_2133 0xea + +#define AR_PHY_RX_DELAY 0x9914 +#define AR_PHY_SEARCH_START_DELAY 0x9918 +#define AR_PHY_RX_DELAY_DELAY 0x00003FFF + +#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12)) +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 +#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 + +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 +#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 + +#define AR_PHY_TIMING5 0x9924 +#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 + +#define AR_PHY_POWER_TX_RATE1 0x9934 +#define AR_PHY_POWER_TX_RATE2 0x9938 +#define AR_PHY_POWER_TX_RATE_MAX 0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 + +#define AR_PHY_FRAME_CTL 0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 + +#define AR_PHY_TXPWRADJ 0x994C +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 + +#define AR_PHY_RADAR_EXT 0x9940 +#define AR_PHY_RADAR_EXT_ENA 0x00004000 + +#define AR_PHY_RADAR_0 0x9954 +#define AR_PHY_RADAR_0_ENA 0x00000001 +#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 +#define AR_PHY_RADAR_0_INBAND 0x0000003e +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 +#define AR_PHY_RADAR_0_PRSSI_S 6 +#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 +#define AR_PHY_RADAR_0_RRSSI_S 18 +#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 +#define AR_PHY_RADAR_0_FIRPWR_S 24 + +#define AR_PHY_RADAR_1 0x9958 +#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 +#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN 0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S 0 + +#define AR_PHY_SWITCH_CHAIN_0 0x9960 +#define AR_PHY_SWITCH_COM 0x9964 + +#define AR_PHY_SIGMA_DELTA 0x996C +#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 +#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 +#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 +#define AR_PHY_SIGMA_DELTA_FILT2_S 3 +#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 +#define AR_PHY_SIGMA_DELTA_FILT1_S 8 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +#define AR_PHY_RESTART 0x9970 +#define AR_PHY_RESTART_DIV_GC 0x001C0000 +#define AR_PHY_RESTART_DIV_GC_S 18 + +#define AR_PHY_RFBUS_REQ 0x997C +#define AR_PHY_RFBUS_REQ_EN 0x00000001 + +#define AR_PHY_TIMING7 0x9980 +#define AR_PHY_TIMING8 0x9984 +#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 + +#define AR_PHY_BIN_MASK2_1 0x9988 +#define AR_PHY_BIN_MASK2_2 0x998c +#define AR_PHY_BIN_MASK2_3 0x9990 +#define AR_PHY_BIN_MASK2_4 0x9994 + +#define AR_PHY_BIN_MASK_1 0x9900 +#define AR_PHY_BIN_MASK_2 0x9904 +#define AR_PHY_BIN_MASK_3 0x9908 + +#define AR_PHY_MASK_CTL 0x990c + +#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF +#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 + +#define AR_PHY_TIMING9 0x9998 +#define AR_PHY_TIMING10 0x999c +#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF +#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 + +#define AR_PHY_TIMING11 0x99a0 +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 +#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 +#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 + +#define AR_PHY_RX_CHAINMASK 0x99a4 +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 +#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac + +#define AR_PHY_EXT_CCA0 0x99b8 +#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S 0 + +#define AR_PHY_EXT_CCA 0x99bc +#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 +#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 +#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S 16 +#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_SFCORR_EXT 0x99c0 +#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 +#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 + +#define AR_PHY_HALFGI 0x99D0 +#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 +#define AR_PHY_HALFGI_DSC_MAN_S 4 +#define AR_PHY_HALFGI_DSC_EXP 0x0000000F +#define AR_PHY_HALFGI_DSC_EXP_S 0 + +#define AR_PHY_CHAN_INFO_MEMORY 0x99DC +#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 + +#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 + +#define AR_PHY_M_SLEEP 0x99f0 +#define AR_PHY_REFCLKDLY 0x99f4 +#define AR_PHY_REFCLKPD 0x99f8 + +#define AR_PHY_CALMODE 0x99f0 + +#define AR_PHY_CALMODE_IQ 0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 + +#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) + +#define AR_PHY_CURRENT_RSSI 0x9c1c +#define AR9280_PHY_CURRENT_RSSI 0x9c3c + +#define AR_PHY_RFBUS_GRANT 0x9C20 +#define AR_PHY_RFBUS_GRANT_EN 0x00000001 + +#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + +#define AR_PHY_CHAN_INFO_GAIN 0x9CFC + +#define AR_PHY_MODE 0xA200 +#define AR_PHY_MODE_AR2133 0x08 +#define AR_PHY_MODE_AR5111 0x00 +#define AR_PHY_MODE_AR5112 0x08 +#define AR_PHY_MODE_DYNAMIC 0x04 +#define AR_PHY_MODE_RF2GHZ 0x02 +#define AR_PHY_MODE_RF5GHZ 0x00 +#define AR_PHY_MODE_CCK 0x01 +#define AR_PHY_MODE_OFDM 0x00 +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 + +#define AR_PHY_CCK_TX_CTRL 0xA204 +#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 + +#define AR_PHY_CCK_DETECT 0xA208 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 +/* [12:6] settling time for antenna switch */ +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 + +#define AR_PHY_GAIN_2GHZ 0xA20C +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 + +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 + +#define AR_PHY_CCK_RXCTRL4 0xA21C +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 + +#define AR_PHY_DAG_CTRLCCK 0xA228 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 + +#define AR_PHY_FORCE_CLKEN_CCK 0xA22C +#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 + +#define AR_PHY_POWER_TX_RATE3 0xA234 +#define AR_PHY_POWER_TX_RATE4 0xA238 + +#define AR_PHY_SCRM_SEQ_XR 0xA23C +#define AR_PHY_HEADER_DETECT_XR 0xA240 +#define AR_PHY_CHIRP_DETECTED_XR 0xA244 +#define AR_PHY_BLUETOOTH 0xA254 + +#define AR_PHY_TPCRG1 0xA258 +#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 + +#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 +#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 +#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 + +#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + +#define AR_PHY_TX_PWRCTRL4 0xa264 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 + +#define AR_PHY_TX_PWRCTRL6_0 0xa270 +#define AR_PHY_TX_PWRCTRL6_1 0xb270 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 + +#define AR_PHY_TX_PWRCTRL7 0xa274 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 + +#define AR_PHY_TX_PWRCTRL9 0xa27C +#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 +#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 + +#define AR_PHY_TX_GAIN_TBL1 0xa300 +#define AR_PHY_TX_GAIN 0x0007F000 +#define AR_PHY_TX_GAIN_S 12 + +#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 +#define AR_PHY_MASK2_M_31_45 0xa3a4 +#define AR_PHY_MASK2_M_16_30 0xa3a8 +#define AR_PHY_MASK2_M_00_15 0xa3ac +#define AR_PHY_MASK2_P_15_01 0xa3b8 +#define AR_PHY_MASK2_P_30_16 0xa3bc +#define AR_PHY_MASK2_P_45_31 0xa3c0 +#define AR_PHY_MASK2_P_61_45 0xa3c4 +#define AR_PHY_SPUR_REG 0x994c + +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 +#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 + +#define AR_PHY_PILOT_MASK_01_30 0xa3b0 +#define AR_PHY_PILOT_MASK_31_60 0xa3b4 + +#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 +#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 + +#define AR_PHY_ANALOG_SWAP 0xa268 +#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 + +#define AR_PHY_TPCRG5 0xA26C +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 + +/* Carrier leak calibration control, do it after AGC calibration */ +#define AR_PHY_CL_CAL_CTL 0xA358 +#define AR_PHY_CL_CAL_ENABLE 0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 + +#define AR_PHY_POWER_TX_RATE5 0xA38C +#define AR_PHY_POWER_TX_RATE6 0xA390 + +#define AR_PHY_CAL_CHAINMASK 0xA39C + +#define AR_PHY_POWER_TX_SUB 0xA3C8 +#define AR_PHY_POWER_TX_RATE7 0xA3CC +#define AR_PHY_POWER_TX_RATE8 0xA3D0 +#define AR_PHY_POWER_TX_RATE9 0xA3D4 + +#define AR_PHY_XPA_CFG 0xA3D8 +#define AR_PHY_FORCE_XPA_CFG 0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S 0 + +#define AR_PHY_CH1_CCA 0xa864 +#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH1_MINCCA_PWR_S 19 +#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 +#define AR9280_PHY_CH1_MINCCA_PWR_S 20 + +#define AR_PHY_CH2_CCA 0xb864 +#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 +#define AR_PHY_CH2_MINCCA_PWR_S 19 + +#define AR_PHY_CH1_EXT_CCA 0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_CH2_EXT_CCA 0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 + +#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ + int r; \ + for (r = 0; r < ((iniarray)->ia_rows); r++) { \ + REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ + DO_DELAY(regWr); \ + } \ + } while (0) + +#define ATH9K_IS_MIC_ENABLED(ah) \ + ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) + +#define ANTSWAP_AB 0x0001 +#define REDUCE_CHAIN_0 0x00000050 +#define REDUCE_CHAIN_1 0x00000051 + +#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ + int i; \ + for (i = 0; i < (_iniarray)->ia_rows; i++) \ + (_bank)[i] = INI_RA((_iniarray), i, _col);; \ + } while (0) + +#endif diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c new file mode 100644 index 000000000000..a13668b9b6dc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -0,0 +1,1752 @@ +/* + * Copyright (c) 2004 Video54 Technologies, Inc. + * Copyright (c) 2004-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 "ath9k.h" + +static struct ath_rate_table ar5416_11na_ratetable = { + 42, + { + { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ + 5400, 0x0b, 0x00, 12, + 0, 2, 1, 0, 0, 0, 0, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + 7800, 0x0f, 0x00, 18, + 0, 3, 1, 1, 1, 1, 1, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ + 10000, 0x0a, 0x00, 24, + 2, 4, 2, 2, 2, 2, 2, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ + 13900, 0x0e, 0x00, 36, + 2, 6, 2, 3, 3, 3, 3, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ + 17300, 0x09, 0x00, 48, + 4, 10, 3, 4, 4, 4, 4, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ + 23000, 0x0d, 0x00, 72, + 4, 14, 3, 5, 5, 5, 5, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ + 27400, 0x08, 0x00, 96, + 4, 20, 3, 6, 6, 6, 6, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ + 29300, 0x0c, 0x00, 108, + 4, 23, 3, 7, 7, 7, 7, 0 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ + 6400, 0x80, 0x00, 0, + 0, 2, 3, 8, 24, 8, 24, 3216 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ + 12700, 0x81, 0x00, 1, + 2, 4, 3, 9, 25, 9, 25, 6434 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ + 18800, 0x82, 0x00, 2, + 2, 6, 3, 10, 26, 10, 26, 9650 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ + 25000, 0x83, 0x00, 3, + 4, 10, 3, 11, 27, 11, 27, 12868 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ + 36700, 0x84, 0x00, 4, + 4, 14, 3, 12, 28, 12, 28, 19304 }, + { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ + 48100, 0x85, 0x00, 5, + 4, 20, 3, 13, 29, 13, 29, 25740 }, + { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ + 53500, 0x86, 0x00, 6, + 4, 23, 3, 14, 30, 14, 30, 28956 }, + { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ + 59000, 0x87, 0x00, 7, + 4, 25, 3, 15, 31, 15, 32, 32180 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ + 12700, 0x88, 0x00, + 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ + 24800, 0x89, 0x00, 9, + 2, 4, 3, 17, 34, 17, 34, 12860 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ + 36600, 0x8a, 0x00, 10, + 2, 6, 3, 18, 35, 18, 35, 19300 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ + 48100, 0x8b, 0x00, 11, + 4, 10, 3, 19, 36, 19, 36, 25736 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ + 69500, 0x8c, 0x00, 12, + 4, 14, 3, 20, 37, 20, 37, 38600 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ + 89500, 0x8d, 0x00, 13, + 4, 20, 3, 21, 38, 21, 38, 51472 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ + 98900, 0x8e, 0x00, 14, + 4, 23, 3, 22, 39, 22, 39, 57890 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ + 108300, 0x8f, 0x00, 15, + 4, 25, 3, 23, 40, 23, 41, 64320 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ + 13200, 0x80, 0x00, 0, + 0, 2, 3, 8, 24, 24, 24, 6684 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ + 25900, 0x81, 0x00, 1, + 2, 4, 3, 9, 25, 25, 25, 13368 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ + 38600, 0x82, 0x00, 2, + 2, 6, 3, 10, 26, 26, 26, 20052 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ + 49800, 0x83, 0x00, 3, + 4, 10, 3, 11, 27, 27, 27, 26738 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ + 72200, 0x84, 0x00, 4, + 4, 14, 3, 12, 28, 28, 28, 40104 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ + 92900, 0x85, 0x00, 5, + 4, 20, 3, 13, 29, 29, 29, 53476 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ + 102700, 0x86, 0x00, 6, + 4, 23, 3, 14, 30, 30, 30, 60156 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ + 112000, 0x87, 0x00, 7, + 4, 25, 3, 15, 31, 32, 32, 66840 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ + 122000, 0x87, 0x00, 7, + 4, 25, 3, 15, 31, 32, 32, 74200 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ + 25800, 0x88, 0x00, 8, + 0, 2, 3, 16, 33, 33, 33, 13360 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ + 49800, 0x89, 0x00, 9, + 2, 4, 3, 17, 34, 34, 34, 26720 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ + 71900, 0x8a, 0x00, 10, + 2, 6, 3, 18, 35, 35, 35, 40080 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ + 92500, 0x8b, 0x00, 11, + 4, 10, 3, 19, 36, 36, 36, 53440 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ + 130300, 0x8c, 0x00, 12, + 4, 14, 3, 20, 37, 37, 37, 80160 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ + 162800, 0x8d, 0x00, 13, + 4, 20, 3, 21, 38, 38, 38, 106880 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ + 178200, 0x8e, 0x00, 14, + 4, 23, 3, 22, 39, 39, 39, 120240 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ + 192100, 0x8f, 0x00, 15, + 4, 25, 3, 23, 40, 41, 41, 133600 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ + 207000, 0x8f, 0x00, 15, + 4, 25, 3, 23, 40, 41, 41, 148400 }, + }, + 50, /* probe interval */ + 50, /* rssi reduce interval */ + WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ +}; + +/* 4ms frame limit not used for NG mode. The values filled + * for HT are the 64K max aggregate limit */ + +static struct ath_rate_table ar5416_11ng_ratetable = { + 46, + { + { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ + 900, 0x1b, 0x00, 2, + 0, 0, 1, 0, 0, 0, 0, 0 }, + { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ + 1900, 0x1a, 0x04, 4, + 1, 1, 1, 1, 1, 1, 1, 0 }, + { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ + 4900, 0x19, 0x04, 11, + 2, 2, 2, 2, 2, 2, 2, 0 }, + { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ + 8100, 0x18, 0x04, 22, + 3, 3, 2, 3, 3, 3, 3, 0 }, + { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ + 5400, 0x0b, 0x00, 12, + 4, 2, 1, 4, 4, 4, 4, 0 }, + { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + 7800, 0x0f, 0x00, 18, + 4, 3, 1, 5, 5, 5, 5, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ + 10100, 0x0a, 0x00, 24, + 6, 4, 1, 6, 6, 6, 6, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ + 14100, 0x0e, 0x00, 36, + 6, 6, 2, 7, 7, 7, 7, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ + 17700, 0x09, 0x00, 48, + 8, 10, 3, 8, 8, 8, 8, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ + 23700, 0x0d, 0x00, 72, + 8, 14, 3, 9, 9, 9, 9, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ + 27400, 0x08, 0x00, 96, + 8, 20, 3, 10, 10, 10, 10, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ + 30900, 0x0c, 0x00, 108, + 8, 23, 3, 11, 11, 11, 11, 0 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ + 6400, 0x80, 0x00, 0, + 4, 2, 3, 12, 28, 12, 28, 3216 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ + 12700, 0x81, 0x00, 1, + 6, 4, 3, 13, 29, 13, 29, 6434 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ + 18800, 0x82, 0x00, 2, + 6, 6, 3, 14, 30, 14, 30, 9650 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ + 25000, 0x83, 0x00, 3, + 8, 10, 3, 15, 31, 15, 31, 12868 }, + { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ + 36700, 0x84, 0x00, 4, + 8, 14, 3, 16, 32, 16, 32, 19304 }, + { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ + 48100, 0x85, 0x00, 5, + 8, 20, 3, 17, 33, 17, 33, 25740 }, + { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ + 53500, 0x86, 0x00, 6, + 8, 23, 3, 18, 34, 18, 34, 28956 }, + { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ + 59000, 0x87, 0x00, 7, + 8, 25, 3, 19, 35, 19, 36, 32180 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ + 12700, 0x88, 0x00, 8, + 4, 2, 3, 20, 37, 20, 37, 6430 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ + 24800, 0x89, 0x00, 9, + 6, 4, 3, 21, 38, 21, 38, 12860 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ + 36600, 0x8a, 0x00, 10, + 6, 6, 3, 22, 39, 22, 39, 19300 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ + 48100, 0x8b, 0x00, 11, + 8, 10, 3, 23, 40, 23, 40, 25736 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ + 69500, 0x8c, 0x00, 12, + 8, 14, 3, 24, 41, 24, 41, 38600 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ + 89500, 0x8d, 0x00, 13, + 8, 20, 3, 25, 42, 25, 42, 51472 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ + 98900, 0x8e, 0x00, 14, + 8, 23, 3, 26, 43, 26, 44, 57890 }, + { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ + 108300, 0x8f, 0x00, 15, + 8, 25, 3, 27, 44, 27, 45, 64320 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ + 13200, 0x80, 0x00, 0, + 8, 2, 3, 12, 28, 28, 28, 6684 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ + 25900, 0x81, 0x00, 1, + 8, 4, 3, 13, 29, 29, 29, 13368 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ + 38600, 0x82, 0x00, 2, + 8, 6, 3, 14, 30, 30, 30, 20052 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ + 49800, 0x83, 0x00, 3, + 8, 10, 3, 15, 31, 31, 31, 26738 }, + { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ + 72200, 0x84, 0x00, 4, + 8, 14, 3, 16, 32, 32, 32, 40104 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ + 92900, 0x85, 0x00, 5, + 8, 20, 3, 17, 33, 33, 33, 53476 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ + 102700, 0x86, 0x00, 6, + 8, 23, 3, 18, 34, 34, 34, 60156 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ + 112000, 0x87, 0x00, 7, + 8, 23, 3, 19, 35, 36, 36, 66840 }, + { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ + 122000, 0x87, 0x00, 7, + 8, 25, 3, 19, 35, 36, 36, 74200 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ + 25800, 0x88, 0x00, 8, + 8, 2, 3, 20, 37, 37, 37, 13360 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ + 49800, 0x89, 0x00, 9, + 8, 4, 3, 21, 38, 38, 38, 26720 }, + { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ + 71900, 0x8a, 0x00, 10, + 8, 6, 3, 22, 39, 39, 39, 40080 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ + 92500, 0x8b, 0x00, 11, + 8, 10, 3, 23, 40, 40, 40, 53440 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ + 130300, 0x8c, 0x00, 12, + 8, 14, 3, 24, 41, 41, 41, 80160 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ + 162800, 0x8d, 0x00, 13, + 8, 20, 3, 25, 42, 42, 42, 106880 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ + 178200, 0x8e, 0x00, 14, + 8, 23, 3, 26, 43, 43, 43, 120240 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ + 192100, 0x8f, 0x00, 15, + 8, 23, 3, 27, 44, 45, 45, 133600 }, + { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ + 207000, 0x8f, 0x00, 15, + 8, 25, 3, 27, 44, 45, 45, 148400 }, + }, + 50, /* probe interval */ + 50, /* rssi reduce interval */ + WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ +}; + +static struct ath_rate_table ar5416_11a_ratetable = { + 8, + { + { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ + 5400, 0x0b, 0x00, (0x80|12), + 0, 2, 1, 0, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + 7800, 0x0f, 0x00, 18, + 0, 3, 1, 1, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ + 10000, 0x0a, 0x00, (0x80|24), + 2, 4, 2, 2, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ + 13900, 0x0e, 0x00, 36, + 2, 6, 2, 3, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ + 17300, 0x09, 0x00, (0x80|48), + 4, 10, 3, 4, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ + 23000, 0x0d, 0x00, 72, + 4, 14, 3, 5, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ + 27400, 0x08, 0x00, 96, + 4, 19, 3, 6, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ + 29300, 0x0c, 0x00, 108, + 4, 23, 3, 7, 0 }, + }, + 50, /* probe interval */ + 50, /* rssi reduce interval */ + 0, /* Phy rates allowed initially */ +}; + +static struct ath_rate_table ar5416_11g_ratetable = { + 12, + { + { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ + 900, 0x1b, 0x00, 2, + 0, 0, 1, 0, 0 }, + { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ + 1900, 0x1a, 0x04, 4, + 1, 1, 1, 1, 0 }, + { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ + 4900, 0x19, 0x04, 11, + 2, 2, 2, 2, 0 }, + { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ + 8100, 0x18, 0x04, 22, + 3, 3, 2, 3, 0 }, + { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ + 5400, 0x0b, 0x00, 12, + 4, 2, 1, 4, 0 }, + { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ + 7800, 0x0f, 0x00, 18, + 4, 3, 1, 5, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ + 10000, 0x0a, 0x00, 24, + 6, 4, 1, 6, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ + 13900, 0x0e, 0x00, 36, + 6, 6, 2, 7, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ + 17300, 0x09, 0x00, 48, + 8, 10, 3, 8, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ + 23000, 0x0d, 0x00, 72, + 8, 14, 3, 9, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ + 27400, 0x08, 0x00, 96, + 8, 19, 3, 10, 0 }, + { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ + 29300, 0x0c, 0x00, 108, + 8, 23, 3, 11, 0 }, + }, + 50, /* probe interval */ + 50, /* rssi reduce interval */ + 0, /* Phy rates allowed initially */ +}; + +static struct ath_rate_table ar5416_11b_ratetable = { + 4, + { + { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ + 900, 0x1b, 0x00, (0x80|2), + 0, 0, 1, 0, 0 }, + { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ + 1800, 0x1a, 0x04, (0x80|4), + 1, 1, 1, 1, 0 }, + { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ + 4300, 0x19, 0x04, (0x80|11), + 1, 2, 2, 2, 0 }, + { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ + 7100, 0x18, 0x04, (0x80|22), + 1, 4, 100, 3, 0 }, + }, + 100, /* probe interval */ + 100, /* rssi reduce interval */ + 0, /* Phy rates allowed initially */ +}; + +static inline int8_t median(int8_t a, int8_t b, int8_t c) +{ + if (a >= b) { + if (b >= c) + return b; + else if (a > c) + return c; + else + return a; + } else { + if (a >= c) + return a; + else if (b >= c) + return c; + else + return b; + } +} + +static void ath_rc_sort_validrates(struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv) +{ + u8 i, j, idx, idx_next; + + for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { + for (j = 0; j <= i-1; j++) { + idx = ath_rc_priv->valid_rate_index[j]; + idx_next = ath_rc_priv->valid_rate_index[j+1]; + + if (rate_table->info[idx].ratekbps > + rate_table->info[idx_next].ratekbps) { + ath_rc_priv->valid_rate_index[j] = idx_next; + ath_rc_priv->valid_rate_index[j+1] = idx; + } + } + } +} + +static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) +{ + u8 i; + + for (i = 0; i < ath_rc_priv->rate_table_size; i++) + ath_rc_priv->valid_rate_index[i] = 0; +} + +static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, + u8 index, int valid_tx_rate) +{ + ASSERT(index <= ath_rc_priv->rate_table_size); + ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; +} + +static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, + u8 index) +{ + ASSERT(index <= ath_rc_priv->rate_table_size); + return ath_rc_priv->valid_rate_index[index]; +} + +static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv, + u8 cur_valid_txrate, + u8 *next_idx) +{ + u8 i; + + for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) { + if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { + *next_idx = ath_rc_priv->valid_rate_index[i+1]; + return 1; + } + } + + /* No more valid rates */ + *next_idx = 0; + + return 0; +} + +/* Return true only for single stream */ + +static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) +{ + if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) + return 0; + if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) + return 0; + if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) + return 0; + if (!ignore_cw && WLAN_RC_PHY_HT(phy)) + if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) + return 0; + if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) + return 0; + return 1; +} + +static inline int +ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv, + u8 cur_valid_txrate, u8 *next_idx) +{ + int8_t i; + + for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) { + if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { + *next_idx = ath_rc_priv->valid_rate_index[i-1]; + return 1; + } + } + + return 0; +} + +static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, + struct ath_rate_table *rate_table, + u32 capflag) +{ + u8 i, hi = 0; + u32 valid; + + for (i = 0; i < rate_table->rate_cnt; i++) { + valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? + rate_table->info[i].valid_single_stream : + rate_table->info[i].valid); + if (valid == 1) { + u32 phy = rate_table->info[i].phy; + u8 valid_rate_count = 0; + + if (!ath_rc_valid_phyrate(phy, capflag, 0)) + continue; + + valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; + + ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; + ath_rc_priv->valid_phy_ratecnt[phy] += 1; + ath_rc_set_valid_txmask(ath_rc_priv, i, 1); + hi = A_MAX(hi, i); + } + } + + return hi; +} + +static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, + struct ath_rate_table *rate_table, + struct ath_rateset *rateset, + u32 capflag) +{ + u8 i, j, hi = 0; + + /* Use intersection of working rates and valid rates */ + for (i = 0; i < rateset->rs_nrates; i++) { + for (j = 0; j < rate_table->rate_cnt; j++) { + u32 phy = rate_table->info[j].phy; + u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? + rate_table->info[j].valid_single_stream : + rate_table->info[j].valid); + u8 rate = rateset->rs_rates[i]; + u8 dot11rate = rate_table->info[j].dot11rate; + + /* We allow a rate only if its valid and the + * capflag matches one of the validity + * (VALID/VALID_20/VALID_40) flags */ + + if (((rate & 0x7F) == (dot11rate & 0x7F)) && + ((valid & WLAN_RC_CAP_MODE(capflag)) == + WLAN_RC_CAP_MODE(capflag)) && + !WLAN_RC_PHY_HT(phy)) { + u8 valid_rate_count = 0; + + if (!ath_rc_valid_phyrate(phy, capflag, 0)) + continue; + + valid_rate_count = + ath_rc_priv->valid_phy_ratecnt[phy]; + + ath_rc_priv->valid_phy_rateidx[phy] + [valid_rate_count] = j; + ath_rc_priv->valid_phy_ratecnt[phy] += 1; + ath_rc_set_valid_txmask(ath_rc_priv, j, 1); + hi = A_MAX(hi, j); + } + } + } + + return hi; +} + +static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, + struct ath_rate_table *rate_table, + u8 *mcs_set, u32 capflag) +{ + struct ath_rateset *rateset = (struct ath_rateset *)mcs_set; + + u8 i, j, hi = 0; + + /* Use intersection of working rates and valid rates */ + for (i = 0; i < rateset->rs_nrates; i++) { + for (j = 0; j < rate_table->rate_cnt; j++) { + u32 phy = rate_table->info[j].phy; + u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? + rate_table->info[j].valid_single_stream : + rate_table->info[j].valid); + u8 rate = rateset->rs_rates[i]; + u8 dot11rate = rate_table->info[j].dot11rate; + + if (((rate & 0x7F) != (dot11rate & 0x7F)) || + !WLAN_RC_PHY_HT(phy) || + !WLAN_RC_PHY_HT_VALID(valid, capflag)) + continue; + + if (!ath_rc_valid_phyrate(phy, capflag, 0)) + continue; + + ath_rc_priv->valid_phy_rateidx[phy] + [ath_rc_priv->valid_phy_ratecnt[phy]] = j; + ath_rc_priv->valid_phy_ratecnt[phy] += 1; + ath_rc_set_valid_txmask(ath_rc_priv, j, 1); + hi = A_MAX(hi, j); + } + } + + return hi; +} + +static u8 ath_rc_ratefind_ht(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + struct ath_rate_table *rate_table, + int *is_probing) +{ + u32 dt, best_thruput, this_thruput, now_msec; + u8 rate, next_rate, best_rate, maxindex, minindex; + int8_t rssi_last, rssi_reduce = 0, index = 0; + + *is_probing = 0; + + rssi_last = median(ath_rc_priv->rssi_last, + ath_rc_priv->rssi_last_prev, + ath_rc_priv->rssi_last_prev2); + + /* + * Age (reduce) last ack rssi based on how old it is. + * The bizarre numbers are so the delta is 160msec, + * meaning we divide by 16. + * 0msec <= dt <= 25msec: don't derate + * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB + * 185msec <= dt: derate by 10dB + */ + + now_msec = jiffies_to_msecs(jiffies); + dt = now_msec - ath_rc_priv->rssi_time; + + if (dt >= 185) + rssi_reduce = 10; + else if (dt >= 25) + rssi_reduce = (u8)((dt - 25) >> 4); + + /* Now reduce rssi_last by rssi_reduce */ + if (rssi_last < rssi_reduce) + rssi_last = 0; + else + rssi_last -= rssi_reduce; + + /* + * Now look up the rate in the rssi table and return it. + * If no rates match then we return 0 (lowest rate) + */ + + best_thruput = 0; + maxindex = ath_rc_priv->max_valid_rate-1; + + minindex = 0; + best_rate = minindex; + + /* + * Try the higher rate first. It will reduce memory moving time + * if we have very good channel characteristics. + */ + for (index = maxindex; index >= minindex ; index--) { + u8 per_thres; + + rate = ath_rc_priv->valid_rate_index[index]; + if (rate > ath_rc_priv->rate_max_phy) + continue; + + /* + * For TCP the average collision rate is around 11%, + * so we ignore PERs less than this. This is to + * prevent the rate we are currently using (whose + * PER might be in the 10-15 range because of TCP + * collisions) looking worse than the next lower + * rate whose PER has decayed close to 0. If we + * used to next lower rate, its PER would grow to + * 10-15 and we would be worse off then staying + * at the current rate. + */ + per_thres = ath_rc_priv->state[rate].per; + if (per_thres < 12) + per_thres = 12; + + this_thruput = rate_table->info[rate].user_ratekbps * + (100 - per_thres); + + if (best_thruput <= this_thruput) { + best_thruput = this_thruput; + best_rate = rate; + } + } + + rate = best_rate; + ath_rc_priv->rssi_last_lookup = rssi_last; + + /* + * Must check the actual rate (ratekbps) to account for + * non-monoticity of 11g's rate table + */ + + if (rate >= ath_rc_priv->rate_max_phy) { + rate = ath_rc_priv->rate_max_phy; + + /* Probe the next allowed phy state */ + if (ath_rc_get_nextvalid_txrate(rate_table, + ath_rc_priv, rate, &next_rate) && + (now_msec - ath_rc_priv->probe_time > + rate_table->probe_interval) && + (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { + rate = next_rate; + ath_rc_priv->probe_rate = rate; + ath_rc_priv->probe_time = now_msec; + ath_rc_priv->hw_maxretry_pktcnt = 0; + *is_probing = 1; + } + } + + if (rate > (ath_rc_priv->rate_table_size - 1)) + rate = ath_rc_priv->rate_table_size - 1; + + ASSERT((rate_table->info[rate].valid && + (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) || + (rate_table->info[rate].valid_single_stream && + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))); + + return rate; +} + +static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, + struct ieee80211_tx_rate *rate, + struct ieee80211_tx_rate_control *txrc, + u8 tries, u8 rix, int rtsctsenable) +{ + rate->count = tries; + rate->idx = rix; + + if (txrc->short_preamble) + rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; + if (txrc->rts || rtsctsenable) + rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; + if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) + rate->flags |= IEEE80211_TX_RC_SHORT_GI; + if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) + rate->flags |= IEEE80211_TX_RC_MCS; +} + +static void ath_rc_rate_set_rtscts(struct ath_softc *sc, + struct ath_rate_table *rate_table, + struct ieee80211_tx_info *tx_info) +{ + struct ieee80211_tx_rate *rates = tx_info->control.rates; + int i = 0, rix = 0, cix, enable_g_protection = 0; + + /* get the cix for the lowest valid rix */ + for (i = 3; i >= 0; i--) { + if (rates[i].count && (rates[i].idx >= 0)) { + rix = rates[i].idx; + break; + } + } + cix = rate_table->info[rix].ctrl_rate; + + /* All protection frames are transmited at 2Mb/s for 802.11g, + * otherwise we transmit them at 1Mb/s */ + if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ && + !conf_is_ht(&sc->hw->conf)) + enable_g_protection = 1; + + /* + * If 802.11g protection is enabled, determine whether to use RTS/CTS or + * just CTS. Note that this is only done for OFDM/HT unicast frames. + */ + if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && + !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && + (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || + WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { + rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; + cix = rate_table->info[enable_g_protection].ctrl_rate; + } + + tx_info->control.rts_cts_rate_idx = cix; +} + +static u8 ath_rc_rate_getidx(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + struct ath_rate_table *rate_table, + u8 rix, u16 stepdown, + u16 min_rate) +{ + u32 j; + u8 nextindex; + + if (min_rate) { + for (j = RATE_TABLE_SIZE; j > 0; j--) { + if (ath_rc_get_nextlowervalid_txrate(rate_table, + ath_rc_priv, rix, &nextindex)) + rix = nextindex; + else + break; + } + } else { + for (j = stepdown; j > 0; j--) { + if (ath_rc_get_nextlowervalid_txrate(rate_table, + ath_rc_priv, rix, &nextindex)) + rix = nextindex; + else + break; + } + } + return rix; +} + +static void ath_rc_ratefind(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + struct ieee80211_tx_rate_control *txrc) +{ + struct ath_rate_table *rate_table; + struct sk_buff *skb = txrc->skb; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->control.rates; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; + u8 try_per_rate = 0, i = 0, rix, nrix; + int is_probe = 0; + + rate_table = sc->cur_rate_table; + rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe); + nrix = rix; + + if (is_probe) { + /* set one try for probe rates. For the + * probes don't enable rts */ + ath_rc_rate_set_series(rate_table, &rates[i++], txrc, + 1, nrix, 0); + + try_per_rate = (ATH_11N_TXMAXTRY/4); + /* Get the next tried/allowed rate. No RTS for the next series + * after the probe rate + */ + nrix = ath_rc_rate_getidx(sc, ath_rc_priv, + rate_table, nrix, 1, 0); + ath_rc_rate_set_series(rate_table, &rates[i++], txrc, + try_per_rate, nrix, 0); + + tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; + } else { + try_per_rate = (ATH_11N_TXMAXTRY/4); + /* Set the choosen rate. No RTS for first series entry. */ + ath_rc_rate_set_series(rate_table, &rates[i++], txrc, + try_per_rate, nrix, 0); + } + + /* Fill in the other rates for multirate retry */ + for ( ; i < 4; i++) { + u8 try_num; + u8 min_rate; + + try_num = ((i + 1) == 4) ? + ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ; + min_rate = (((i + 1) == 4) && 0); + + nrix = ath_rc_rate_getidx(sc, ath_rc_priv, + rate_table, nrix, 1, min_rate); + /* All other rates in the series have RTS enabled */ + ath_rc_rate_set_series(rate_table, &rates[i], txrc, + try_num, nrix, 1); + } + + /* + * NB:Change rate series to enable aggregation when operating + * at lower MCS rates. When first rate in series is MCS2 + * in HT40 @ 2.4GHz, series should look like: + * + * {MCS2, MCS1, MCS0, MCS0}. + * + * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should + * look like: + * + * {MCS3, MCS2, MCS1, MCS1} + * + * So, set fourth rate in series to be same as third one for + * above conditions. + */ + if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) && + (conf_is_ht(&sc->hw->conf))) { + u8 dot11rate = rate_table->info[rix].dot11rate; + u8 phy = rate_table->info[rix].phy; + if (i == 4 && + ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || + (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { + rates[3].idx = rates[2].idx; + rates[3].flags = rates[2].flags; + } + } + + /* + * Force hardware to use computed duration for next + * fragment by disabling multi-rate retry, which + * updates duration based on the multi-rate duration table. + * + * FIXME: Fix duration + */ + if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && + (ieee80211_has_morefrags(fc) || + (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) { + rates[1].count = rates[2].count = rates[3].count = 0; + rates[1].idx = rates[2].idx = rates[3].idx = 0; + rates[0].count = ATH_TXMAXTRY; + } + + /* Setup RTS/CTS */ + ath_rc_rate_set_rtscts(sc, rate_table, tx_info); +} + +static bool ath_rc_update_per(struct ath_softc *sc, + struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv, + struct ath_tx_info_priv *tx_info_priv, + int tx_rate, int xretries, int retries, + u32 now_msec) +{ + bool state_change = false; + int count; + u8 last_per; + static u32 nretry_to_per_lookup[10] = { + 100 * 0 / 1, + 100 * 1 / 4, + 100 * 1 / 2, + 100 * 3 / 4, + 100 * 4 / 5, + 100 * 5 / 6, + 100 * 6 / 7, + 100 * 7 / 8, + 100 * 8 / 9, + 100 * 9 / 10 + }; + + last_per = ath_rc_priv->state[tx_rate].per; + + if (xretries) { + if (xretries == 1) { + ath_rc_priv->state[tx_rate].per += 30; + if (ath_rc_priv->state[tx_rate].per > 100) + ath_rc_priv->state[tx_rate].per = 100; + } else { + /* xretries == 2 */ + count = ARRAY_SIZE(nretry_to_per_lookup); + if (retries >= count) + retries = count - 1; + + /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ + ath_rc_priv->state[tx_rate].per = + (u8)(last_per - (last_per >> 3) + (100 >> 3)); + } + + /* xretries == 1 or 2 */ + + if (ath_rc_priv->probe_rate == tx_rate) + ath_rc_priv->probe_rate = 0; + + } else { /* xretries == 0 */ + count = ARRAY_SIZE(nretry_to_per_lookup); + if (retries >= count) + retries = count - 1; + + if (tx_info_priv->n_bad_frames) { + /* new_PER = 7/8*old_PER + 1/8*(currentPER) + * Assuming that n_frames is not 0. The current PER + * from the retries is 100 * retries / (retries+1), + * since the first retries attempts failed, and the + * next one worked. For the one that worked, + * n_bad_frames subframes out of n_frames wored, + * so the PER for that part is + * 100 * n_bad_frames / n_frames, and it contributes + * 100 * n_bad_frames / (n_frames * (retries+1)) to + * the above PER. The expression below is a + * simplified version of the sum of these two terms. + */ + if (tx_info_priv->n_frames > 0) { + int n_frames, n_bad_frames; + u8 cur_per, new_per; + + n_bad_frames = retries * tx_info_priv->n_frames + + tx_info_priv->n_bad_frames; + n_frames = tx_info_priv->n_frames * (retries + 1); + cur_per = (100 * n_bad_frames / n_frames) >> 3; + new_per = (u8)(last_per - (last_per >> 3) + cur_per); + ath_rc_priv->state[tx_rate].per = new_per; + } + } else { + ath_rc_priv->state[tx_rate].per = + (u8)(last_per - (last_per >> 3) + + (nretry_to_per_lookup[retries] >> 3)); + } + + ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev; + ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last; + ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi; + ath_rc_priv->rssi_time = now_msec; + + /* + * If we got at most one retry then increase the max rate if + * this was a probe. Otherwise, ignore the probe. + */ + if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { + if (retries > 0 || 2 * tx_info_priv->n_bad_frames > + tx_info_priv->n_frames) { + /* + * Since we probed with just a single attempt, + * any retries means the probe failed. Also, + * if the attempt worked, but more than half + * the subframes were bad then also consider + * the probe a failure. + */ + ath_rc_priv->probe_rate = 0; + } else { + u8 probe_rate = 0; + + ath_rc_priv->rate_max_phy = + ath_rc_priv->probe_rate; + probe_rate = ath_rc_priv->probe_rate; + + if (ath_rc_priv->state[probe_rate].per > 30) + ath_rc_priv->state[probe_rate].per = 20; + + ath_rc_priv->probe_rate = 0; + + /* + * Since this probe succeeded, we allow the next + * probe twice as soon. This allows the maxRate + * to move up faster if the probes are + * succesful. + */ + ath_rc_priv->probe_time = + now_msec - rate_table->probe_interval / 2; + } + } + + if (retries > 0) { + /* + * Don't update anything. We don't know if + * this was because of collisions or poor signal. + * + * Later: if rssi_ack is close to + * ath_rc_priv->state[txRate].rssi_thres and we see lots + * of retries, then we could increase + * ath_rc_priv->state[txRate].rssi_thres. + */ + ath_rc_priv->hw_maxretry_pktcnt = 0; + } else { + int32_t rssi_ackAvg; + int8_t rssi_thres; + int8_t rssi_ack_vmin; + + /* + * It worked with no retries. First ignore bogus (small) + * rssi_ack values. + */ + if (tx_rate == ath_rc_priv->rate_max_phy && + ath_rc_priv->hw_maxretry_pktcnt < 255) { + ath_rc_priv->hw_maxretry_pktcnt++; + } + + if (tx_info_priv->tx.ts_rssi < + rate_table->info[tx_rate].rssi_ack_validmin) + goto exit; + + /* Average the rssi */ + if (tx_rate != ath_rc_priv->rssi_sum_rate) { + ath_rc_priv->rssi_sum_rate = tx_rate; + ath_rc_priv->rssi_sum = + ath_rc_priv->rssi_sum_cnt = 0; + } + + ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi; + ath_rc_priv->rssi_sum_cnt++; + + if (ath_rc_priv->rssi_sum_cnt < 4) + goto exit; + + rssi_ackAvg = + (ath_rc_priv->rssi_sum + 2) / 4; + rssi_thres = + ath_rc_priv->state[tx_rate].rssi_thres; + rssi_ack_vmin = + rate_table->info[tx_rate].rssi_ack_validmin; + + ath_rc_priv->rssi_sum = + ath_rc_priv->rssi_sum_cnt = 0; + + /* Now reduce the current rssi threshold */ + if ((rssi_ackAvg < rssi_thres + 2) && + (rssi_thres > rssi_ack_vmin)) { + ath_rc_priv->state[tx_rate].rssi_thres--; + } + + state_change = true; + } + } +exit: + return state_change; +} + +/* Update PER, RSSI and whatever else that the code thinks it is doing. + If you can make sense of all this, you really need to go out more. */ + +static void ath_rc_update_ht(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + struct ath_tx_info_priv *tx_info_priv, + int tx_rate, int xretries, int retries) +{ +#define CHK_RSSI(rate) \ + ((ath_rc_priv->state[(rate)].rssi_thres + \ + rate_table->info[(rate)].rssi_ack_deltamin) > \ + ath_rc_priv->state[(rate)+1].rssi_thres) + + u32 now_msec = jiffies_to_msecs(jiffies); + int rate; + u8 last_per; + bool state_change = false; + struct ath_rate_table *rate_table = sc->cur_rate_table; + int size = ath_rc_priv->rate_table_size; + + if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) + return; + + /* To compensate for some imbalance between ctrl and ext. channel */ + + if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) + tx_info_priv->tx.ts_rssi = + tx_info_priv->tx.ts_rssi < 3 ? 0 : + tx_info_priv->tx.ts_rssi - 3; + + last_per = ath_rc_priv->state[tx_rate].per; + + /* Update PER first */ + state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, + tx_info_priv, tx_rate, xretries, + retries, now_msec); + + /* + * If this rate looks bad (high PER) then stop using it for + * a while (except if we are probing). + */ + if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 && + rate_table->info[tx_rate].ratekbps <= + rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { + ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, + (u8)tx_rate, &ath_rc_priv->rate_max_phy); + + /* Don't probe for a little while. */ + ath_rc_priv->probe_time = now_msec; + } + + if (state_change) { + /* + * Make sure the rates above this have higher rssi thresholds. + * (Note: Monotonicity is kept within the OFDM rates and + * within the CCK rates. However, no adjustment is + * made to keep the rssi thresholds monotonically + * increasing between the CCK and OFDM rates.) + */ + for (rate = tx_rate; rate < size - 1; rate++) { + if (rate_table->info[rate+1].phy != + rate_table->info[tx_rate].phy) + break; + + if (CHK_RSSI(rate)) { + ath_rc_priv->state[rate+1].rssi_thres = + ath_rc_priv->state[rate].rssi_thres + + rate_table->info[rate].rssi_ack_deltamin; + } + } + + /* Make sure the rates below this have lower rssi thresholds. */ + for (rate = tx_rate - 1; rate >= 0; rate--) { + if (rate_table->info[rate].phy != + rate_table->info[tx_rate].phy) + break; + + if (CHK_RSSI(rate)) { + if (ath_rc_priv->state[rate+1].rssi_thres < + rate_table->info[rate].rssi_ack_deltamin) + ath_rc_priv->state[rate].rssi_thres = 0; + else { + ath_rc_priv->state[rate].rssi_thres = + ath_rc_priv->state[rate+1].rssi_thres - + rate_table->info[rate].rssi_ack_deltamin; + } + + if (ath_rc_priv->state[rate].rssi_thres < + rate_table->info[rate].rssi_ack_validmin) { + ath_rc_priv->state[rate].rssi_thres = + rate_table->info[rate].rssi_ack_validmin; + } + } + } + } + + /* Make sure the rates below this have lower PER */ + /* Monotonicity is kept only for rates below the current rate. */ + if (ath_rc_priv->state[tx_rate].per < last_per) { + for (rate = tx_rate - 1; rate >= 0; rate--) { + if (rate_table->info[rate].phy != + rate_table->info[tx_rate].phy) + break; + + if (ath_rc_priv->state[rate].per > + ath_rc_priv->state[rate+1].per) { + ath_rc_priv->state[rate].per = + ath_rc_priv->state[rate+1].per; + } + } + } + + /* Maintain monotonicity for rates above the current rate */ + for (rate = tx_rate; rate < size - 1; rate++) { + if (ath_rc_priv->state[rate+1].per < + ath_rc_priv->state[rate].per) + ath_rc_priv->state[rate+1].per = + ath_rc_priv->state[rate].per; + } + + /* Every so often, we reduce the thresholds and + * PER (different for CCK and OFDM). */ + if (now_msec - ath_rc_priv->rssi_down_time >= + rate_table->rssi_reduce_interval) { + + for (rate = 0; rate < size; rate++) { + if (ath_rc_priv->state[rate].rssi_thres > + rate_table->info[rate].rssi_ack_validmin) + ath_rc_priv->state[rate].rssi_thres -= 1; + } + ath_rc_priv->rssi_down_time = now_msec; + } + + /* Every so often, we reduce the thresholds + * and PER (different for CCK and OFDM). */ + if (now_msec - ath_rc_priv->per_down_time >= + rate_table->rssi_reduce_interval) { + for (rate = 0; rate < size; rate++) { + ath_rc_priv->state[rate].per = + 7 * ath_rc_priv->state[rate].per / 8; + } + + ath_rc_priv->per_down_time = now_msec; + } + + ath_debug_stat_retries(sc, tx_rate, xretries, retries, + ath_rc_priv->state[tx_rate].per); + +#undef CHK_RSSI +} + +static int ath_rc_get_rateindex(struct ath_rate_table *rate_table, + struct ieee80211_tx_rate *rate) +{ + int rix; + + if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && + (rate->flags & IEEE80211_TX_RC_SHORT_GI)) + rix = rate_table->info[rate->idx].ht_index; + else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + rix = rate_table->info[rate->idx].sgi_index; + else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + rix = rate_table->info[rate->idx].cw40index; + else + rix = rate_table->info[rate->idx].base_index; + + return rix; +} + +static void ath_rc_tx_status(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + struct ieee80211_tx_info *tx_info, + int final_ts_idx, int xretries, int long_retry) +{ + struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + struct ath_rate_table *rate_table; + struct ieee80211_tx_rate *rates = tx_info->status.rates; + u8 flags; + u32 i = 0, rix; + + rate_table = sc->cur_rate_table; + + /* + * If the first rate is not the final index, there + * are intermediate rate failures to be processed. + */ + if (final_ts_idx != 0) { + /* Process intermediate rates that failed.*/ + for (i = 0; i < final_ts_idx ; i++) { + if (rates[i].count != 0 && (rates[i].idx >= 0)) { + flags = rates[i].flags; + + /* If HT40 and we have switched mode from + * 40 to 20 => don't update */ + + if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && + !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) + return; + + rix = ath_rc_get_rateindex(rate_table, &rates[i]); + ath_rc_update_ht(sc, ath_rc_priv, + tx_info_priv, rix, + xretries ? 1 : 2, + rates[i].count); + } + } + } else { + /* + * Handle the special case of MIMO PS burst, where the second + * aggregate is sent out with only one rate and one try. + * Treating it as an excessive retry penalizes the rate + * inordinately. + */ + if (rates[0].count == 1 && xretries == 1) + xretries = 2; + } + + flags = rates[i].flags; + + /* If HT40 and we have switched mode from 40 to 20 => don't update */ + if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && + !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) + return; + + rix = ath_rc_get_rateindex(rate_table, &rates[i]); + ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, + xretries, long_retry); +} + +static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, + enum ieee80211_band band, + bool is_ht, bool is_cw_40) +{ + int mode = 0; + + switch(band) { + case IEEE80211_BAND_2GHZ: + mode = ATH9K_MODE_11G; + if (is_ht) + mode = ATH9K_MODE_11NG_HT20; + if (is_cw_40) + mode = ATH9K_MODE_11NG_HT40PLUS; + break; + case IEEE80211_BAND_5GHZ: + mode = ATH9K_MODE_11A; + if (is_ht) + mode = ATH9K_MODE_11NA_HT20; + if (is_cw_40) + mode = ATH9K_MODE_11NA_HT40PLUS; + break; + default: + DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n"); + return NULL; + } + + BUG_ON(mode >= ATH9K_MODE_MAX); + + DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode); + return sc->hw_rate_table[mode]; +} + +static void ath_rc_init(struct ath_softc *sc, + struct ath_rate_priv *ath_rc_priv, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct ath_rate_table *rate_table) +{ + struct ath_rateset *rateset = &ath_rc_priv->neg_rates; + u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; + u8 i, j, k, hi = 0, hthi = 0; + + if (!rate_table) { + DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n"); + return; + } + + /* Initial rate table size. Will change depending + * on the working rate set */ + ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; + + /* Initialize thresholds according to the global rate table */ + for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { + ath_rc_priv->state[i].rssi_thres = + rate_table->info[i].rssi_ack_validmin; + ath_rc_priv->state[i].per = 0; + } + + /* Determine the valid rates */ + ath_rc_init_valid_txmask(ath_rc_priv); + + for (i = 0; i < WLAN_RC_PHY_MAX; i++) { + for (j = 0; j < MAX_TX_RATE_PHY; j++) + ath_rc_priv->valid_phy_rateidx[i][j] = 0; + ath_rc_priv->valid_phy_ratecnt[i] = 0; + } + + if (!rateset->rs_nrates) { + /* No working rate, just initialize valid rates */ + hi = ath_rc_init_validrates(ath_rc_priv, rate_table, + ath_rc_priv->ht_cap); + } else { + /* Use intersection of working rates and valid rates */ + hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table, + rateset, ath_rc_priv->ht_cap); + if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) { + hthi = ath_rc_setvalid_htrates(ath_rc_priv, + rate_table, + ht_mcs, + ath_rc_priv->ht_cap); + } + hi = A_MAX(hi, hthi); + } + + ath_rc_priv->rate_table_size = hi + 1; + ath_rc_priv->rate_max_phy = 0; + ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); + + for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { + for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { + ath_rc_priv->valid_rate_index[k++] = + ath_rc_priv->valid_phy_rateidx[i][j]; + } + + if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) + || !ath_rc_priv->valid_phy_ratecnt[i]) + continue; + + ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; + } + ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); + ASSERT(k <= RATE_TABLE_SIZE); + + ath_rc_priv->max_valid_rate = k; + ath_rc_sort_validrates(rate_table, ath_rc_priv); + ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; + sc->cur_rate_table = rate_table; + + DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n", + ath_rc_priv->ht_cap); +} + +static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, + bool is_cw40, bool is_sgi40) +{ + u8 caps = 0; + + if (sta->ht_cap.ht_supported) { + caps = WLAN_RC_HT_FLAG; + if (sc->sc_ah->caps.tx_chainmask != 1 && + ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { + if (sta->ht_cap.mcs.rx_mask[1]) + caps |= WLAN_RC_DS_FLAG; + } + if (is_cw40) + caps |= WLAN_RC_40_FLAG; + if (is_sgi40) + caps |= WLAN_RC_SGI_FLAG; + } + + return caps; +} + +/***********************************/ +/* mac80211 Rate Control callbacks */ +/***********************************/ + +static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb) +{ + struct ath_softc *sc = priv; + struct ath_rate_priv *ath_rc_priv = priv_sta; + struct ath_tx_info_priv *tx_info_priv = NULL; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; + int final_ts_idx, tx_status = 0, is_underrun = 0; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + final_ts_idx = tx_info_priv->tx.ts_rateindex; + + if (!priv_sta || !ieee80211_is_data(fc) || + !tx_info_priv->update_rc) + goto exit; + + if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT) + goto exit; + + /* + * If underrun error is seen assume it as an excessive retry only + * if prefetch trigger level have reached the max (0x3f for 5416) + * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY + * times. This affects how ratectrl updates PER for the failed rate. + */ + if (tx_info_priv->tx.ts_flags & + (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && + ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) { + tx_status = 1; + is_underrun = 1; + } + + if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || + (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) + tx_status = 1; + + ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, + (is_underrun) ? ATH_11N_TXMAXTRY : + tx_info_priv->tx.ts_longretry); + + /* Check if aggregation has to be enabled for this tid */ + if (conf_is_ht(&sc->hw->conf) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 *qc, tid; + struct ath_node *an; + + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + an = (struct ath_node *)sta->drv_priv; + + if(ath_tx_aggr_check(sc, an, tid)) + ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); + } + } + + ath_debug_stat_rc(sc, skb); +exit: + kfree(tx_info_priv); +} + +static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc) +{ + struct ieee80211_supported_band *sband = txrc->sband; + struct sk_buff *skb = txrc->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_softc *sc = priv; + struct ath_rate_priv *ath_rc_priv = priv_sta; + __le16 fc = hdr->frame_control; + + /* lowest rate for management and multicast/broadcast frames */ + if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || + !sta) { + tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); + tx_info->control.rates[0].count = + is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; + return; + } + + /* Find tx rate for unicast frames */ + ath_rc_ratefind(sc, ath_rc_priv, txrc); +} + +static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) +{ + struct ath_softc *sc = priv; + struct ath_rate_priv *ath_rc_priv = priv_sta; + struct ath_rate_table *rate_table = NULL; + bool is_cw40, is_sgi40; + int i, j = 0; + + for (i = 0; i < sband->n_bitrates; i++) { + if (sta->supp_rates[sband->band] & BIT(i)) { + ath_rc_priv->neg_rates.rs_rates[j] + = (sband->bitrates[i].bitrate * 2) / 10; + j++; + } + } + ath_rc_priv->neg_rates.rs_nrates = j; + + if (sta->ht_cap.ht_supported) { + for (i = 0, j = 0; i < 77; i++) { + if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) + ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; + if (j == ATH_RATE_MAX) + break; + } + ath_rc_priv->neg_ht_rates.rs_nrates = j; + } + + is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; + is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + + /* Choose rate table first */ + + if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || + (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { + rate_table = ath_choose_rate_table(sc, sband->band, + sta->ht_cap.ht_supported, + is_cw40); + } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { + /* cur_rate_table would be set on init through config() */ + rate_table = sc->cur_rate_table; + } + + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); + ath_rc_init(sc, priv_sta, sband, sta, rate_table); +} + +static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + u32 changed) +{ + struct ath_softc *sc = priv; + struct ath_rate_priv *ath_rc_priv = priv_sta; + struct ath_rate_table *rate_table = NULL; + bool oper_cw40 = false, oper_sgi40; + bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? + true : false; + bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? + true : false; + + /* FIXME: Handle AP mode later when we support CWM */ + + if (changed & IEEE80211_RC_HT_CHANGED) { + if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) + return; + + if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || + sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) + oper_cw40 = true; + + oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + true : false; + + if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { + rate_table = ath_choose_rate_table(sc, sband->band, + sta->ht_cap.ht_supported, + oper_cw40); + ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, + oper_cw40, oper_sgi40); + ath_rc_init(sc, priv_sta, sband, sta, rate_table); + + DPRINTF(sc, ATH_DBG_CONFIG, + "Operating HT Bandwidth changed to: %d\n", + sc->hw->conf.channel_type); + } + } +} + +static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +{ + struct ath_wiphy *aphy = hw->priv; + return aphy->sc; +} + +static void ath_rate_free(void *priv) +{ + return; +} + +static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) +{ + struct ath_softc *sc = priv; + struct ath_rate_priv *rate_priv; + + rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); + if (!rate_priv) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to allocate private rc structure\n"); + return NULL; + } + + rate_priv->rssi_down_time = jiffies_to_msecs(jiffies); + rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; + + return rate_priv; +} + +static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) +{ + struct ath_rate_priv *rate_priv = priv_sta; + kfree(rate_priv); +} + +static struct rate_control_ops ath_rate_ops = { + .module = NULL, + .name = "ath9k_rate_control", + .tx_status = ath_tx_status, + .get_rate = ath_get_rate, + .rate_init = ath_rate_init, + .rate_update = ath_rate_update, + .alloc = ath_rate_alloc, + .free = ath_rate_free, + .alloc_sta = ath_rate_alloc_sta, + .free_sta = ath_rate_free_sta, +}; + +void ath_rate_attach(struct ath_softc *sc) +{ + sc->hw_rate_table[ATH9K_MODE_11B] = + &ar5416_11b_ratetable; + sc->hw_rate_table[ATH9K_MODE_11A] = + &ar5416_11a_ratetable; + sc->hw_rate_table[ATH9K_MODE_11G] = + &ar5416_11g_ratetable; + sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = + &ar5416_11na_ratetable; + sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = + &ar5416_11ng_ratetable; + sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = + &ar5416_11na_ratetable; + sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = + &ar5416_11na_ratetable; + sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = + &ar5416_11ng_ratetable; + sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = + &ar5416_11ng_ratetable; +} + +int ath_rate_control_register(void) +{ + return ieee80211_rate_control_register(&ath_rate_ops); +} + +void ath_rate_control_unregister(void) +{ + ieee80211_rate_control_unregister(&ath_rate_ops); +} diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h new file mode 100644 index 000000000000..e3abd76103fd --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2004 Sam Leffler, Errno Consulting + * Copyright (c) 2004 Video54 Technologies, Inc. + * 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 RC_H +#define RC_H + +struct ath_softc; + +#define ATH_RATE_MAX 30 +#define RATE_TABLE_SIZE 64 +#define MAX_TX_RATE_PHY 48 + +/* VALID_ALL - valid for 20/40/Legacy, + * VALID - Legacy only, + * VALID_20 - HT 20 only, + * VALID_40 - HT 40 only */ + +#define INVALID 0x0 +#define VALID 0x1 +#define VALID_20 0x2 +#define VALID_40 0x4 +#define VALID_2040 (VALID_20|VALID_40) +#define VALID_ALL (VALID_2040|VALID) + +enum { + WLAN_RC_PHY_OFDM, + WLAN_RC_PHY_CCK, + WLAN_RC_PHY_HT_20_SS, + WLAN_RC_PHY_HT_20_DS, + WLAN_RC_PHY_HT_40_SS, + WLAN_RC_PHY_HT_40_DS, + WLAN_RC_PHY_HT_20_SS_HGI, + WLAN_RC_PHY_HT_20_DS_HGI, + WLAN_RC_PHY_HT_40_SS_HGI, + WLAN_RC_PHY_HT_40_DS_HGI, + WLAN_RC_PHY_MAX +}; + +#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ + || (_phy == WLAN_RC_PHY_HT_40_DS) \ + || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) +#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ + || (_phy == WLAN_RC_PHY_HT_40_DS) \ + || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) +#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) + +#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) + +#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ + (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID)) + +/* Return TRUE if flag supports HT20 && client supports HT20 or + * return TRUE if flag supports HT40 && client supports HT40. + * This is used becos some rates overlap between HT20/HT40. + */ +#define WLAN_RC_PHY_HT_VALID(flag, capflag) \ + (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \ + ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG))) + +#define WLAN_RC_DS_FLAG (0x01) +#define WLAN_RC_40_FLAG (0x02) +#define WLAN_RC_SGI_FLAG (0x04) +#define WLAN_RC_HT_FLAG (0x08) + +/** + * struct ath_rate_table - Rate Control table + * @valid: valid for use in rate control + * @valid_single_stream: valid for use in rate control for + * single stream operation + * @phy: CCK/OFDM + * @ratekbps: rate in Kbits per second + * @user_ratekbps: user rate in Kbits per second + * @ratecode: rate that goes into HW descriptors + * @short_preamble: Mask for enabling short preamble in ratecode for CCK + * @dot11rate: value that goes into supported + * rates info element of MLME + * @ctrl_rate: Index of next lower basic rate, used for duration computation + * @max_4ms_framelen: maximum frame length(bytes) for tx duration + * @probe_interval: interval for rate control to probe for other rates + * @rssi_reduce_interval: interval for rate control to reduce rssi + * @initial_ratemax: initial ratemax value + */ +struct ath_rate_table { + int rate_cnt; + struct { + int valid; + int valid_single_stream; + u8 phy; + u32 ratekbps; + u32 user_ratekbps; + u8 ratecode; + u8 short_preamble; + u8 dot11rate; + u8 ctrl_rate; + int8_t rssi_ack_validmin; + int8_t rssi_ack_deltamin; + u8 base_index; + u8 cw40index; + u8 sgi_index; + u8 ht_index; + u32 max_4ms_framelen; + } info[RATE_TABLE_SIZE]; + u32 probe_interval; + u32 rssi_reduce_interval; + u8 initial_ratemax; +}; + +struct ath_tx_ratectrl_state { + int8_t rssi_thres; /* required rssi for this rate (dB) */ + u8 per; /* recent estimate of packet error rate (%) */ +}; + +struct ath_rateset { + u8 rs_nrates; + u8 rs_rates[ATH_RATE_MAX]; +}; + +/** + * struct ath_rate_priv - Rate Control priv data + * @state: RC state + * @rssi_last: last ACK rssi + * @rssi_last_lookup: last ACK rssi used for lookup + * @rssi_last_prev: previous last ACK rssi + * @rssi_last_prev2: 2nd previous last ACK rssi + * @rssi_sum_cnt: count of rssi_sum for averaging + * @rssi_sum_rate: rate that we are averaging + * @rssi_sum: running sum of rssi for averaging + * @probe_rate: rate we are probing at + * @rssi_time: msec timestamp for last ack rssi + * @rssi_down_time: msec timestamp for last down step + * @probe_time: msec timestamp for last probe + * @hw_maxretry_pktcnt: num of packets since we got HW max retry error + * @max_valid_rate: maximum number of valid rate + * @per_down_time: msec timestamp for last PER down step + * @valid_phy_ratecnt: valid rate count + * @rate_max_phy: phy index for the max rate + * @probe_interval: interval for ratectrl to probe for other rates + * @prev_data_rix: rate idx of last data frame + * @ht_cap: HT capabilities + * @neg_rates: Negotatied rates + * @neg_ht_rates: Negotiated HT rates + */ +struct ath_rate_priv { + int8_t rssi_last; + int8_t rssi_last_lookup; + int8_t rssi_last_prev; + int8_t rssi_last_prev2; + int32_t rssi_sum_cnt; + int32_t rssi_sum_rate; + int32_t rssi_sum; + u8 rate_table_size; + u8 probe_rate; + u8 hw_maxretry_pktcnt; + u8 max_valid_rate; + u8 valid_rate_index[RATE_TABLE_SIZE]; + u8 ht_cap; + u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; + u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; + u8 rate_max_phy; + u32 rssi_time; + u32 rssi_down_time; + u32 probe_time; + u32 per_down_time; + u32 probe_interval; + u32 prev_data_rix; + u32 tx_triglevel_max; + struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE]; + struct ath_rateset neg_rates; + struct ath_rateset neg_ht_rates; + struct ath_rate_softc *asc; +}; + +enum ath9k_internal_frame_type { + ATH9K_NOT_INTERNAL, + ATH9K_INT_PAUSE, + ATH9K_INT_UNPAUSE +}; + +struct ath_tx_info_priv { + struct ath_wiphy *aphy; + struct ath_tx_status tx; + int n_frames; + int n_bad_frames; + bool update_rc; + enum ath9k_internal_frame_type frame_type; +}; + +#define ATH_TX_INFO_PRIV(tx_info) \ + ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0])) + +void ath_rate_attach(struct ath_softc *sc); +u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); +int ath_rate_control_register(void); +void ath_rate_control_unregister(void); + +#endif /* RC_H */ diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c new file mode 100644 index 000000000000..b46badd21f73 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -0,0 +1,704 @@ +/* + * 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 "ath9k.h" + +static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, + struct ieee80211_hdr *hdr) +{ + struct ieee80211_hw *hw = sc->pri_wiphy->hw; + int i; + + spin_lock_bh(&sc->wiphy_lock); + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + if (aphy == NULL) + continue; + if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) + == 0) { + hw = aphy->hw; + break; + } + } + spin_unlock_bh(&sc->wiphy_lock); + return hw; +} + +/* + * Setup and link descriptors. + * + * 11N: we can no longer afford to self link the last descriptor. + * MAC acknowledges BA status as long as it copies frames to host + * buffer (or rx fifo). This can incorrectly acknowledge packets + * to a sender if last desc is self-linked. + */ +static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_desc *ds; + struct sk_buff *skb; + + ATH_RXBUF_RESET(bf); + + ds = bf->bf_desc; + ds->ds_link = 0; /* link to null */ + ds->ds_data = bf->bf_buf_addr; + + /* virtual addr of the beginning of the buffer. */ + skb = bf->bf_mpdu; + ASSERT(skb != NULL); + ds->ds_vdata = skb->data; + + /* setup rx descriptors. The rx.bufsize here tells the harware + * how much data it can DMA to us and that we are prepared + * to process */ + ath9k_hw_setuprxdesc(ah, ds, + sc->rx.bufsize, + 0); + + if (sc->rx.rxlink == NULL) + ath9k_hw_putrxbuf(ah, bf->bf_daddr); + else + *sc->rx.rxlink = bf->bf_daddr; + + sc->rx.rxlink = &ds->ds_link; + ath9k_hw_rxena(ah); +} + +static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) +{ + /* XXX block beacon interrupts */ + ath9k_hw_setantenna(sc->sc_ah, antenna); + sc->rx.defant = antenna; + sc->rx.rxotherant = 0; +} + +/* + * Extend 15-bit time stamp from rx descriptor to + * a full 64-bit TSF using the current h/w TSF. +*/ +static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) +{ + u64 tsf; + + tsf = ath9k_hw_gettsf64(sc->sc_ah); + if ((tsf & 0x7fff) < rstamp) + tsf -= 0x8000; + return (tsf & ~0x7fff) | rstamp; +} + +static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask) +{ + struct sk_buff *skb; + u32 off; + + /* + * Cache-line-align. This is important (for the + * 5210 at least) as not doing so causes bogus data + * in rx'd frames. + */ + + /* Note: the kernel can allocate a value greater than + * what we ask it to give us. We really only need 4 KB as that + * is this hardware supports and in fact we need at least 3849 + * as that is the MAX AMSDU size this hardware supports. + * Unfortunately this means we may get 8 KB here from the + * kernel... and that is actually what is observed on some + * systems :( */ + skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask); + if (skb != NULL) { + off = ((unsigned long) skb->data) % sc->cachelsz; + if (off != 0) + skb_reserve(skb, sc->cachelsz - off); + } else { + DPRINTF(sc, ATH_DBG_FATAL, + "skbuff alloc of size %u failed\n", len); + return NULL; + } + + return skb; +} + +/* + * For Decrypt or Demic errors, we only mark packet status here and always push + * up the frame up to let mac80211 handle the actual error case, be it no + * decryption key or real decryption error. This let us keep statistics there. + */ +static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, + struct ieee80211_rx_status *rx_status, bool *decrypt_error, + struct ath_softc *sc) +{ + struct ieee80211_hdr *hdr; + u8 ratecode; + __le16 fc; + struct ieee80211_hw *hw; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + hw = ath_get_virt_hw(sc, hdr); + + if (ds->ds_rxstat.rs_more) { + /* + * Frame spans multiple descriptors; this cannot happen yet + * as we don't support jumbograms. If not in monitor mode, + * discard the frame. Enable this if you want to see + * error frames in Monitor mode. + */ + if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR) + goto rx_next; + } else if (ds->ds_rxstat.rs_status != 0) { + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) + goto rx_next; + + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) { + *decrypt_error = true; + } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) { + if (ieee80211_is_ctl(fc)) + /* + * Sometimes, we get invalid + * MIC failures on valid control frames. + * Remove these mic errors. + */ + ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC; + else + rx_status->flag |= RX_FLAG_MMIC_ERROR; + } + /* + * Reject error frames with the exception of + * decryption and MIC failures. For monitor mode, + * we also ignore the CRC error. + */ + if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) { + if (ds->ds_rxstat.rs_status & + ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | + ATH9K_RXERR_CRC)) + goto rx_next; + } else { + if (ds->ds_rxstat.rs_status & + ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { + goto rx_next; + } + } + } + + ratecode = ds->ds_rxstat.rs_rate; + + if (ratecode & 0x80) { + /* HT rate */ + rx_status->flag |= RX_FLAG_HT; + if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) + rx_status->flag |= RX_FLAG_40MHZ; + if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) + rx_status->flag |= RX_FLAG_SHORT_GI; + rx_status->rate_idx = ratecode & 0x7f; + } else { + int i = 0, cur_band, n_rates; + + cur_band = hw->conf.channel->band; + n_rates = sc->sbands[cur_band].n_bitrates; + + for (i = 0; i < n_rates; i++) { + if (sc->sbands[cur_band].bitrates[i].hw_value == + ratecode) { + rx_status->rate_idx = i; + break; + } + + if (sc->sbands[cur_band].bitrates[i].hw_value_short == + ratecode) { + rx_status->rate_idx = i; + rx_status->flag |= RX_FLAG_SHORTPRE; + break; + } + } + } + + rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); + rx_status->band = hw->conf.channel->band; + rx_status->freq = hw->conf.channel->center_freq; + rx_status->noise = sc->ani.noise_floor; + rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; + rx_status->antenna = ds->ds_rxstat.rs_antenna; + + /* at 45 you will be able to use MCS 15 reliably. A more elaborate + * scheme can be used here but it requires tables of SNR/throughput for + * each possible mode used. */ + rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45; + + /* rssi can be more than 45 though, anything above that + * should be considered at 100% */ + if (rx_status->qual > 100) + rx_status->qual = 100; + + rx_status->flag |= RX_FLAG_TSFT; + + return 1; +rx_next: + return 0; +} + +static void ath_opmode_init(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + u32 rfilt, mfilt[2]; + + /* configure rx filter */ + rfilt = ath_calcrxfilter(sc); + ath9k_hw_setrxfilter(ah, rfilt); + + /* configure bssid mask */ + if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + ath9k_hw_setbssidmask(sc); + + /* configure operational mode */ + ath9k_hw_setopmode(ah); + + /* Handle any link-level address change. */ + ath9k_hw_setmac(ah, sc->sc_ah->macaddr); + + /* calculate and install multicast filter */ + mfilt[0] = mfilt[1] = ~0; + ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); +} + +int ath_rx_init(struct ath_softc *sc, int nbufs) +{ + struct sk_buff *skb; + struct ath_buf *bf; + int error = 0; + + spin_lock_init(&sc->rx.rxflushlock); + sc->sc_flags &= ~SC_OP_RXFLUSH; + spin_lock_init(&sc->rx.rxbuflock); + + sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, + min(sc->cachelsz, (u16)64)); + + DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", + sc->cachelsz, sc->rx.bufsize); + + /* Initialize rx descriptors */ + + error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, + "rx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "failed to allocate rx descriptors: %d\n", error); + goto err; + } + + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); + if (skb == NULL) { + error = -ENOMEM; + goto err; + } + + bf->bf_mpdu = skb; + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + sc->rx.bufsize, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, + bf->bf_buf_addr))) { + dev_kfree_skb_any(skb); + bf->bf_mpdu = NULL; + DPRINTF(sc, ATH_DBG_FATAL, + "dma_mapping_error() on RX init\n"); + error = -ENOMEM; + goto err; + } + bf->bf_dmacontext = bf->bf_buf_addr; + } + sc->rx.rxlink = NULL; + +err: + if (error) + ath_rx_cleanup(sc); + + return error; +} + +void ath_rx_cleanup(struct ath_softc *sc) +{ + struct sk_buff *skb; + struct ath_buf *bf; + + list_for_each_entry(bf, &sc->rx.rxbuf, list) { + skb = bf->bf_mpdu; + if (skb) { + dma_unmap_single(sc->dev, bf->bf_buf_addr, + sc->rx.bufsize, DMA_FROM_DEVICE); + dev_kfree_skb(skb); + } + } + + if (sc->rx.rxdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); +} + +/* + * Calculate the receive filter according to the + * operating mode and state: + * + * o always accept unicast, broadcast, and multicast traffic + * o maintain current state of phy error reception (the hal + * may enable phy error frames for noise immunity work) + * o probe request frames are accepted only when operating in + * hostap, adhoc, or monitor modes + * o enable promiscuous mode according to the interface state + * o accept beacons: + * - when operating in adhoc mode so the 802.11 layer creates + * node table entries for peers, + * - when operating in station mode for collecting rssi data when + * the station is otherwise quiet, or + * - when operating as a repeater so we see repeater-sta beacons + * - when scanning + */ + +u32 ath_calcrxfilter(struct ath_softc *sc) +{ +#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) + + u32 rfilt; + + rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) + | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST + | ATH9K_RX_FILTER_MCAST; + + /* If not a STA, enable processing of Probe Requests */ + if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) + rfilt |= ATH9K_RX_FILTER_PROBEREQ; + + /* + * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station + * mode interface or when in monitor mode. AP mode does not need this + * since it receives all in-BSS frames anyway. + */ + if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && + (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || + (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) + rfilt |= ATH9K_RX_FILTER_PROM; + + if (sc->rx.rxfilter & FIF_CONTROL) + rfilt |= ATH9K_RX_FILTER_CONTROL; + + if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && + !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) + rfilt |= ATH9K_RX_FILTER_MYBEACON; + else + rfilt |= ATH9K_RX_FILTER_BEACON; + + /* If in HOSTAP mode, want to enable reception of PSPOLL frames */ + if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) + rfilt |= ATH9K_RX_FILTER_PSPOLL; + + if (sc->sec_wiphy) { + /* TODO: only needed if more than one BSSID is in use in + * station/adhoc mode */ + /* TODO: for older chips, may need to add ATH9K_RX_FILTER_PROM + */ + rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; + } + + return rfilt; + +#undef RX_FILTER_PRESERVE +} + +int ath_startrecv(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_buf *bf, *tbf; + + spin_lock_bh(&sc->rx.rxbuflock); + if (list_empty(&sc->rx.rxbuf)) + goto start_recv; + + sc->rx.rxlink = NULL; + list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { + ath_rx_buf_link(sc, bf); + } + + /* We could have deleted elements so the list may be empty now */ + if (list_empty(&sc->rx.rxbuf)) + goto start_recv; + + bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); + ath9k_hw_putrxbuf(ah, bf->bf_daddr); + ath9k_hw_rxena(ah); + +start_recv: + spin_unlock_bh(&sc->rx.rxbuflock); + ath_opmode_init(sc); + ath9k_hw_startpcureceive(ah); + + return 0; +} + +bool ath_stoprecv(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + bool stopped; + + ath9k_hw_stoppcurecv(ah); + ath9k_hw_setrxfilter(ah, 0); + stopped = ath9k_hw_stopdmarecv(ah); + sc->rx.rxlink = NULL; + + return stopped; +} + +void ath_flushrecv(struct ath_softc *sc) +{ + spin_lock_bh(&sc->rx.rxflushlock); + sc->sc_flags |= SC_OP_RXFLUSH; + ath_rx_tasklet(sc, 1); + sc->sc_flags &= ~SC_OP_RXFLUSH; + spin_unlock_bh(&sc->rx.rxflushlock); +} + +int ath_rx_tasklet(struct ath_softc *sc, int flush) +{ +#define PA2DESC(_sc, _pa) \ + ((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \ + ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr))) + + struct ath_buf *bf; + struct ath_desc *ds; + struct sk_buff *skb = NULL, *requeue_skb; + struct ieee80211_rx_status rx_status; + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_hdr *hdr; + int hdrlen, padsize, retval; + bool decrypt_error = false; + u8 keyix; + __le16 fc; + + spin_lock_bh(&sc->rx.rxbuflock); + + do { + /* If handling rx interrupt and flush is in progress => exit */ + if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) + break; + + if (list_empty(&sc->rx.rxbuf)) { + sc->rx.rxlink = NULL; + break; + } + + bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); + ds = bf->bf_desc; + + /* + * Must provide the virtual address of the current + * descriptor, the physical address, and the virtual + * address of the next descriptor in the h/w chain. + * This allows the HAL to look ahead to see if the + * hardware is done with a descriptor by checking the + * done bit in the following descriptor and the address + * of the current descriptor the DMA engine is working + * on. All this is necessary because of our use of + * a self-linked list to avoid rx overruns. + */ + retval = ath9k_hw_rxprocdesc(ah, ds, + bf->bf_daddr, + PA2DESC(sc, ds->ds_link), + 0); + if (retval == -EINPROGRESS) { + struct ath_buf *tbf; + struct ath_desc *tds; + + if (list_is_last(&bf->list, &sc->rx.rxbuf)) { + sc->rx.rxlink = NULL; + break; + } + + tbf = list_entry(bf->list.next, struct ath_buf, list); + + /* + * On some hardware the descriptor status words could + * get corrupted, including the done bit. Because of + * this, check if the next descriptor's done bit is + * set or not. + * + * If the next descriptor's done bit is set, the current + * descriptor has been corrupted. Force s/w to discard + * this descriptor and continue... + */ + + tds = tbf->bf_desc; + retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, + PA2DESC(sc, tds->ds_link), 0); + if (retval == -EINPROGRESS) { + break; + } + } + + skb = bf->bf_mpdu; + if (!skb) + continue; + + /* + * Synchronize the DMA transfer with CPU before + * 1. accessing the frame + * 2. requeueing the same buffer to h/w + */ + dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, + sc->rx.bufsize, + DMA_FROM_DEVICE); + + /* + * If we're asked to flush receive queue, directly + * chain it back at the queue without processing it. + */ + if (flush) + goto requeue; + + if (!ds->ds_rxstat.rs_datalen) + goto requeue; + + /* The status portion of the descriptor could get corrupted. */ + if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen) + goto requeue; + + if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc)) + goto requeue; + + /* Ensure we always have an skb to requeue once we are done + * processing the current buffer's skb */ + requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); + + /* If there is no memory we ignore the current RX'd frame, + * tell hardware it can give us a new frame using the old + * skb and put it at the tail of the sc->rx.rxbuf list for + * processing. */ + if (!requeue_skb) + goto requeue; + + /* Unmap the frame */ + dma_unmap_single(sc->dev, bf->bf_buf_addr, + sc->rx.bufsize, + DMA_FROM_DEVICE); + + skb_put(skb, ds->ds_rxstat.rs_datalen); + skb->protocol = cpu_to_be16(ETH_P_CONTROL); + + /* see if any padding is done by the hw and remove it */ + hdr = (struct ieee80211_hdr *)skb->data; + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + fc = hdr->frame_control; + + /* The MAC header is padded to have 32-bit boundary if the + * packet payload is non-zero. The general calculation for + * padsize would take into account odd header lengths: + * padsize = (4 - hdrlen % 4) % 4; However, since only + * even-length headers are used, padding can only be 0 or 2 + * bytes and we can optimize this a bit. In addition, we must + * not try to remove padding from short control frames that do + * not have payload. */ + padsize = hdrlen & 3; + if (padsize && hdrlen >= 24) { + memmove(skb->data + padsize, skb->data, hdrlen); + skb_pull(skb, padsize); + } + + keyix = ds->ds_rxstat.rs_keyix; + + if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { + rx_status.flag |= RX_FLAG_DECRYPTED; + } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) + && !decrypt_error && skb->len >= hdrlen + 4) { + keyix = skb->data[hdrlen + 3] >> 6; + + if (test_bit(keyix, sc->keymap)) + rx_status.flag |= RX_FLAG_DECRYPTED; + } + if (ah->sw_mgmt_crypto && + (rx_status.flag & RX_FLAG_DECRYPTED) && + ieee80211_is_mgmt(hdr->frame_control)) { + /* Use software decrypt for management frames. */ + rx_status.flag &= ~RX_FLAG_DECRYPTED; + } + + /* Send the frame to mac80211 */ + if (hdr->addr1[5] & 0x01) { + int i; + /* + * Deliver broadcast/multicast frames to all suitable + * virtual wiphys. + */ + /* TODO: filter based on channel configuration */ + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + struct sk_buff *nskb; + if (aphy == NULL) + continue; + nskb = skb_copy(skb, GFP_ATOMIC); + if (nskb) + __ieee80211_rx(aphy->hw, nskb, + &rx_status); + } + __ieee80211_rx(sc->hw, skb, &rx_status); + } else { + /* Deliver unicast frames based on receiver address */ + __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, + &rx_status); + } + + /* We will now give hardware our shiny new allocated skb */ + bf->bf_mpdu = requeue_skb; + bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, + sc->rx.bufsize, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, + bf->bf_buf_addr))) { + dev_kfree_skb_any(requeue_skb); + bf->bf_mpdu = NULL; + DPRINTF(sc, ATH_DBG_FATAL, + "dma_mapping_error() on RX\n"); + break; + } + bf->bf_dmacontext = bf->bf_buf_addr; + + /* + * change the default rx antenna if rx diversity chooses the + * other antenna 3 times in a row. + */ + if (sc->rx.defant != ds->ds_rxstat.rs_antenna) { + if (++sc->rx.rxotherant >= 3) + ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna); + } else { + sc->rx.rxotherant = 0; + } + + if (ieee80211_is_beacon(fc) && + (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { + sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); + } +requeue: + list_move_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_buf_link(sc, bf); + } while (1); + + spin_unlock_bh(&sc->rx.rxbuflock); + + return 0; +#undef PA2DESC +} diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h new file mode 100644 index 000000000000..52605246679f --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -0,0 +1,1511 @@ +/* + * 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 REG_H +#define REG_H + +#define AR_CR 0x0008 +#define AR_CR_RXE 0x00000004 +#define AR_CR_RXD 0x00000020 +#define AR_CR_SWI 0x00000040 + +#define AR_RXDP 0x000C + +#define AR_CFG 0x0014 +#define AR_CFG_SWTD 0x00000001 +#define AR_CFG_SWTB 0x00000002 +#define AR_CFG_SWRD 0x00000004 +#define AR_CFG_SWRB 0x00000008 +#define AR_CFG_SWRG 0x00000010 +#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 +#define AR_CFG_PHOK 0x00000100 +#define AR_CFG_CLK_GATE_DIS 0x00000400 +#define AR_CFG_EEBS 0x00000200 +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 +#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 + +#define AR_MIRT 0x0020 +#define AR_MIRT_VAL 0x0000ffff +#define AR_MIRT_VAL_S 16 + +#define AR_IER 0x0024 +#define AR_IER_ENABLE 0x00000001 +#define AR_IER_DISABLE 0x00000000 + +#define AR_TIMT 0x0028 +#define AR_TIMT_LAST 0x0000ffff +#define AR_TIMT_LAST_S 0 +#define AR_TIMT_FIRST 0xffff0000 +#define AR_TIMT_FIRST_S 16 + +#define AR_RIMT 0x002C +#define AR_RIMT_LAST 0x0000ffff +#define AR_RIMT_LAST_S 0 +#define AR_RIMT_FIRST 0xffff0000 +#define AR_RIMT_FIRST_S 16 + +#define AR_DMASIZE_4B 0x00000000 +#define AR_DMASIZE_8B 0x00000001 +#define AR_DMASIZE_16B 0x00000002 +#define AR_DMASIZE_32B 0x00000003 +#define AR_DMASIZE_64B 0x00000004 +#define AR_DMASIZE_128B 0x00000005 +#define AR_DMASIZE_256B 0x00000006 +#define AR_DMASIZE_512B 0x00000007 + +#define AR_TXCFG 0x0030 +#define AR_TXCFG_DMASZ_MASK 0x00000007 +#define AR_TXCFG_DMASZ_4B 0 +#define AR_TXCFG_DMASZ_8B 1 +#define AR_TXCFG_DMASZ_16B 2 +#define AR_TXCFG_DMASZ_32B 3 +#define AR_TXCFG_DMASZ_64B 4 +#define AR_TXCFG_DMASZ_128B 5 +#define AR_TXCFG_DMASZ_256B 6 +#define AR_TXCFG_DMASZ_512B 7 +#define AR_FTRIG 0x000003F0 +#define AR_FTRIG_S 4 +#define AR_FTRIG_IMMED 0x00000000 +#define AR_FTRIG_64B 0x00000010 +#define AR_FTRIG_128B 0x00000020 +#define AR_FTRIG_192B 0x00000030 +#define AR_FTRIG_256B 0x00000040 +#define AR_FTRIG_512B 0x00000080 +#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800 + +#define AR_RXCFG 0x0034 +#define AR_RXCFG_CHIRP 0x00000008 +#define AR_RXCFG_ZLFDMA 0x00000010 +#define AR_RXCFG_DMASZ_MASK 0x00000007 +#define AR_RXCFG_DMASZ_4B 0 +#define AR_RXCFG_DMASZ_8B 1 +#define AR_RXCFG_DMASZ_16B 2 +#define AR_RXCFG_DMASZ_32B 3 +#define AR_RXCFG_DMASZ_64B 4 +#define AR_RXCFG_DMASZ_128B 5 +#define AR_RXCFG_DMASZ_256B 6 +#define AR_RXCFG_DMASZ_512B 7 + +#define AR_MIBC 0x0040 +#define AR_MIBC_COW 0x00000001 +#define AR_MIBC_FMC 0x00000002 +#define AR_MIBC_CMC 0x00000004 +#define AR_MIBC_MCS 0x00000008 + +#define AR_TOPS 0x0044 +#define AR_TOPS_MASK 0x0000FFFF + +#define AR_RXNPTO 0x0048 +#define AR_RXNPTO_MASK 0x000003FF + +#define AR_TXNPTO 0x004C +#define AR_TXNPTO_MASK 0x000003FF +#define AR_TXNPTO_QCU_MASK 0x000FFC00 + +#define AR_RPGTO 0x0050 +#define AR_RPGTO_MASK 0x000003FF + +#define AR_RPCNT 0x0054 +#define AR_RPCNT_MASK 0x0000001F + +#define AR_MACMISC 0x0058 +#define AR_MACMISC_PCI_EXT_FORCE 0x00000010 +#define AR_MACMISC_DMA_OBS 0x000001E0 +#define AR_MACMISC_DMA_OBS_S 5 +#define AR_MACMISC_DMA_OBS_LINE_0 0 +#define AR_MACMISC_DMA_OBS_LINE_1 1 +#define AR_MACMISC_DMA_OBS_LINE_2 2 +#define AR_MACMISC_DMA_OBS_LINE_3 3 +#define AR_MACMISC_DMA_OBS_LINE_4 4 +#define AR_MACMISC_DMA_OBS_LINE_5 5 +#define AR_MACMISC_DMA_OBS_LINE_6 6 +#define AR_MACMISC_DMA_OBS_LINE_7 7 +#define AR_MACMISC_DMA_OBS_LINE_8 8 +#define AR_MACMISC_MISC_OBS 0x00000E00 +#define AR_MACMISC_MISC_OBS_S 9 +#define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000 +#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12 +#define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000 +#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15 +#define AR_MACMISC_MISC_OBS_BUS_1 1 + +#define AR_GTXTO 0x0064 +#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF +#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 +#define AR_GTXTO_TIMEOUT_LIMIT_S 16 + +#define AR_GTTM 0x0068 +#define AR_GTTM_USEC 0x00000001 +#define AR_GTTM_IGNORE_IDLE 0x00000002 +#define AR_GTTM_RESET_IDLE 0x00000004 +#define AR_GTTM_CST_USEC 0x00000008 + +#define AR_CST 0x006C +#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF +#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 +#define AR_CST_TIMEOUT_LIMIT_S 16 + +#define AR_ISR 0x0080 +#define AR_ISR_RXOK 0x00000001 +#define AR_ISR_RXDESC 0x00000002 +#define AR_ISR_RXERR 0x00000004 +#define AR_ISR_RXNOPKT 0x00000008 +#define AR_ISR_RXEOL 0x00000010 +#define AR_ISR_RXORN 0x00000020 +#define AR_ISR_TXOK 0x00000040 +#define AR_ISR_TXDESC 0x00000080 +#define AR_ISR_TXERR 0x00000100 +#define AR_ISR_TXNOPKT 0x00000200 +#define AR_ISR_TXEOL 0x00000400 +#define AR_ISR_TXURN 0x00000800 +#define AR_ISR_MIB 0x00001000 +#define AR_ISR_SWI 0x00002000 +#define AR_ISR_RXPHY 0x00004000 +#define AR_ISR_RXKCM 0x00008000 +#define AR_ISR_SWBA 0x00010000 +#define AR_ISR_BRSSI 0x00020000 +#define AR_ISR_BMISS 0x00040000 +#define AR_ISR_BNR 0x00100000 +#define AR_ISR_RXCHIRP 0x00200000 +#define AR_ISR_BCNMISC 0x00800000 +#define AR_ISR_TIM 0x00800000 +#define AR_ISR_QCBROVF 0x02000000 +#define AR_ISR_QCBRURN 0x04000000 +#define AR_ISR_QTRIG 0x08000000 +#define AR_ISR_GENTMR 0x10000000 + +#define AR_ISR_TXMINTR 0x00080000 +#define AR_ISR_RXMINTR 0x01000000 +#define AR_ISR_TXINTM 0x40000000 +#define AR_ISR_RXINTM 0x80000000 + +#define AR_ISR_S0 0x0084 +#define AR_ISR_S0_QCU_TXOK 0x000003FF +#define AR_ISR_S0_QCU_TXOK_S 0 +#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 +#define AR_ISR_S0_QCU_TXDESC_S 16 + +#define AR_ISR_S1 0x0088 +#define AR_ISR_S1_QCU_TXERR 0x000003FF +#define AR_ISR_S1_QCU_TXERR_S 0 +#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 +#define AR_ISR_S1_QCU_TXEOL_S 16 + +#define AR_ISR_S2 0x008c +#define AR_ISR_S2_QCU_TXURN 0x000003FF +#define AR_ISR_S2_CST 0x00400000 +#define AR_ISR_S2_GTT 0x00800000 +#define AR_ISR_S2_TIM 0x01000000 +#define AR_ISR_S2_CABEND 0x02000000 +#define AR_ISR_S2_DTIMSYNC 0x04000000 +#define AR_ISR_S2_BCNTO 0x08000000 +#define AR_ISR_S2_CABTO 0x10000000 +#define AR_ISR_S2_DTIM 0x20000000 +#define AR_ISR_S2_TSFOOR 0x40000000 +#define AR_ISR_S2_TBTT_TIME 0x80000000 + +#define AR_ISR_S3 0x0090 +#define AR_ISR_S3_QCU_QCBROVF 0x000003FF +#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 + +#define AR_ISR_S4 0x0094 +#define AR_ISR_S4_QCU_QTRIG 0x000003FF +#define AR_ISR_S4_RESV0 0xFFFFFC00 + +#define AR_ISR_S5 0x0098 +#define AR_ISR_S5_TIMER_TRIG 0x000000FF +#define AR_ISR_S5_TIMER_THRESH 0x0007FE00 +#define AR_ISR_S5_TIM_TIMER 0x00000010 +#define AR_ISR_S5_DTIM_TIMER 0x00000020 +#define AR_ISR_S5_S 0x00d8 +#define AR_IMR_S5 0x00b8 +#define AR_IMR_S5_TIM_TIMER 0x00000010 +#define AR_IMR_S5_DTIM_TIMER 0x00000020 + + +#define AR_IMR 0x00a0 +#define AR_IMR_RXOK 0x00000001 +#define AR_IMR_RXDESC 0x00000002 +#define AR_IMR_RXERR 0x00000004 +#define AR_IMR_RXNOPKT 0x00000008 +#define AR_IMR_RXEOL 0x00000010 +#define AR_IMR_RXORN 0x00000020 +#define AR_IMR_TXOK 0x00000040 +#define AR_IMR_TXDESC 0x00000080 +#define AR_IMR_TXERR 0x00000100 +#define AR_IMR_TXNOPKT 0x00000200 +#define AR_IMR_TXEOL 0x00000400 +#define AR_IMR_TXURN 0x00000800 +#define AR_IMR_MIB 0x00001000 +#define AR_IMR_SWI 0x00002000 +#define AR_IMR_RXPHY 0x00004000 +#define AR_IMR_RXKCM 0x00008000 +#define AR_IMR_SWBA 0x00010000 +#define AR_IMR_BRSSI 0x00020000 +#define AR_IMR_BMISS 0x00040000 +#define AR_IMR_BNR 0x00100000 +#define AR_IMR_RXCHIRP 0x00200000 +#define AR_IMR_BCNMISC 0x00800000 +#define AR_IMR_TIM 0x00800000 +#define AR_IMR_QCBROVF 0x02000000 +#define AR_IMR_QCBRURN 0x04000000 +#define AR_IMR_QTRIG 0x08000000 +#define AR_IMR_GENTMR 0x10000000 + +#define AR_IMR_TXMINTR 0x00080000 +#define AR_IMR_RXMINTR 0x01000000 +#define AR_IMR_TXINTM 0x40000000 +#define AR_IMR_RXINTM 0x80000000 + +#define AR_IMR_S0 0x00a4 +#define AR_IMR_S0_QCU_TXOK 0x000003FF +#define AR_IMR_S0_QCU_TXOK_S 0 +#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 +#define AR_IMR_S0_QCU_TXDESC_S 16 + +#define AR_IMR_S1 0x00a8 +#define AR_IMR_S1_QCU_TXERR 0x000003FF +#define AR_IMR_S1_QCU_TXERR_S 0 +#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 +#define AR_IMR_S1_QCU_TXEOL_S 16 + +#define AR_IMR_S2 0x00ac +#define AR_IMR_S2_QCU_TXURN 0x000003FF +#define AR_IMR_S2_QCU_TXURN_S 0 +#define AR_IMR_S2_CST 0x00400000 +#define AR_IMR_S2_GTT 0x00800000 +#define AR_IMR_S2_TIM 0x01000000 +#define AR_IMR_S2_CABEND 0x02000000 +#define AR_IMR_S2_DTIMSYNC 0x04000000 +#define AR_IMR_S2_BCNTO 0x08000000 +#define AR_IMR_S2_CABTO 0x10000000 +#define AR_IMR_S2_DTIM 0x20000000 +#define AR_IMR_S2_TSFOOR 0x40000000 + +#define AR_IMR_S3 0x00b0 +#define AR_IMR_S3_QCU_QCBROVF 0x000003FF +#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 +#define AR_IMR_S3_QCU_QCBRURN_S 16 + +#define AR_IMR_S4 0x00b4 +#define AR_IMR_S4_QCU_QTRIG 0x000003FF +#define AR_IMR_S4_RESV0 0xFFFFFC00 + +#define AR_IMR_S5 0x00b8 +#define AR_IMR_S5_TIMER_TRIG 0x000000FF +#define AR_IMR_S5_TIMER_THRESH 0x0000FF00 + + +#define AR_ISR_RAC 0x00c0 +#define AR_ISR_S0_S 0x00c4 +#define AR_ISR_S0_QCU_TXOK 0x000003FF +#define AR_ISR_S0_QCU_TXOK_S 0 +#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 +#define AR_ISR_S0_QCU_TXDESC_S 16 + +#define AR_ISR_S1_S 0x00c8 +#define AR_ISR_S1_QCU_TXERR 0x000003FF +#define AR_ISR_S1_QCU_TXERR_S 0 +#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 +#define AR_ISR_S1_QCU_TXEOL_S 16 + +#define AR_ISR_S2_S 0x00cc +#define AR_ISR_S3_S 0x00d0 +#define AR_ISR_S4_S 0x00d4 +#define AR_ISR_S5_S 0x00d8 +#define AR_DMADBG_0 0x00e0 +#define AR_DMADBG_1 0x00e4 +#define AR_DMADBG_2 0x00e8 +#define AR_DMADBG_3 0x00ec +#define AR_DMADBG_4 0x00f0 +#define AR_DMADBG_5 0x00f4 +#define AR_DMADBG_6 0x00f8 +#define AR_DMADBG_7 0x00fc + +#define AR_NUM_QCU 10 +#define AR_QCU_0 0x0001 +#define AR_QCU_1 0x0002 +#define AR_QCU_2 0x0004 +#define AR_QCU_3 0x0008 +#define AR_QCU_4 0x0010 +#define AR_QCU_5 0x0020 +#define AR_QCU_6 0x0040 +#define AR_QCU_7 0x0080 +#define AR_QCU_8 0x0100 +#define AR_QCU_9 0x0200 + +#define AR_Q0_TXDP 0x0800 +#define AR_Q1_TXDP 0x0804 +#define AR_Q2_TXDP 0x0808 +#define AR_Q3_TXDP 0x080c +#define AR_Q4_TXDP 0x0810 +#define AR_Q5_TXDP 0x0814 +#define AR_Q6_TXDP 0x0818 +#define AR_Q7_TXDP 0x081c +#define AR_Q8_TXDP 0x0820 +#define AR_Q9_TXDP 0x0824 +#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) + +#define AR_Q_TXE 0x0840 +#define AR_Q_TXE_M 0x000003FF + +#define AR_Q_TXD 0x0880 +#define AR_Q_TXD_M 0x000003FF + +#define AR_Q0_CBRCFG 0x08c0 +#define AR_Q1_CBRCFG 0x08c4 +#define AR_Q2_CBRCFG 0x08c8 +#define AR_Q3_CBRCFG 0x08cc +#define AR_Q4_CBRCFG 0x08d0 +#define AR_Q5_CBRCFG 0x08d4 +#define AR_Q6_CBRCFG 0x08d8 +#define AR_Q7_CBRCFG 0x08dc +#define AR_Q8_CBRCFG 0x08e0 +#define AR_Q9_CBRCFG 0x08e4 +#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) +#define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF +#define AR_Q_CBRCFG_INTERVAL_S 0 +#define AR_Q_CBRCFG_OVF_THRESH 0xFF000000 +#define AR_Q_CBRCFG_OVF_THRESH_S 24 + +#define AR_Q0_RDYTIMECFG 0x0900 +#define AR_Q1_RDYTIMECFG 0x0904 +#define AR_Q2_RDYTIMECFG 0x0908 +#define AR_Q3_RDYTIMECFG 0x090c +#define AR_Q4_RDYTIMECFG 0x0910 +#define AR_Q5_RDYTIMECFG 0x0914 +#define AR_Q6_RDYTIMECFG 0x0918 +#define AR_Q7_RDYTIMECFG 0x091c +#define AR_Q8_RDYTIMECFG 0x0920 +#define AR_Q9_RDYTIMECFG 0x0924 +#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) +#define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF +#define AR_Q_RDYTIMECFG_DURATION_S 0 +#define AR_Q_RDYTIMECFG_EN 0x01000000 + +#define AR_Q_ONESHOTARM_SC 0x0940 +#define AR_Q_ONESHOTARM_SC_M 0x000003FF +#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00 + +#define AR_Q_ONESHOTARM_CC 0x0980 +#define AR_Q_ONESHOTARM_CC_M 0x000003FF +#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00 + +#define AR_Q0_MISC 0x09c0 +#define AR_Q1_MISC 0x09c4 +#define AR_Q2_MISC 0x09c8 +#define AR_Q3_MISC 0x09cc +#define AR_Q4_MISC 0x09d0 +#define AR_Q5_MISC 0x09d4 +#define AR_Q6_MISC 0x09d8 +#define AR_Q7_MISC 0x09dc +#define AR_Q8_MISC 0x09e0 +#define AR_Q9_MISC 0x09e4 +#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) +#define AR_Q_MISC_FSP 0x0000000F +#define AR_Q_MISC_FSP_ASAP 0 +#define AR_Q_MISC_FSP_CBR 1 +#define AR_Q_MISC_FSP_DBA_GATED 2 +#define AR_Q_MISC_FSP_TIM_GATED 3 +#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 +#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5 +#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 +#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 +#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 +#define AR_Q_MISC_BEACON_USE 0x00000080 +#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100 +#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 +#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 +#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 +#define AR_Q_MISC_RESV0 0xFFFFF000 + +#define AR_Q0_STS 0x0a00 +#define AR_Q1_STS 0x0a04 +#define AR_Q2_STS 0x0a08 +#define AR_Q3_STS 0x0a0c +#define AR_Q4_STS 0x0a10 +#define AR_Q5_STS 0x0a14 +#define AR_Q6_STS 0x0a18 +#define AR_Q7_STS 0x0a1c +#define AR_Q8_STS 0x0a20 +#define AR_Q9_STS 0x0a24 +#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) +#define AR_Q_STS_PEND_FR_CNT 0x00000003 +#define AR_Q_STS_RESV0 0x000000FC +#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 +#define AR_Q_STS_RESV1 0xFFFF0000 + +#define AR_Q_RDYTIMESHDN 0x0a40 +#define AR_Q_RDYTIMESHDN_M 0x000003FF + + +#define AR_NUM_DCU 10 +#define AR_DCU_0 0x0001 +#define AR_DCU_1 0x0002 +#define AR_DCU_2 0x0004 +#define AR_DCU_3 0x0008 +#define AR_DCU_4 0x0010 +#define AR_DCU_5 0x0020 +#define AR_DCU_6 0x0040 +#define AR_DCU_7 0x0080 +#define AR_DCU_8 0x0100 +#define AR_DCU_9 0x0200 + +#define AR_D0_QCUMASK 0x1000 +#define AR_D1_QCUMASK 0x1004 +#define AR_D2_QCUMASK 0x1008 +#define AR_D3_QCUMASK 0x100c +#define AR_D4_QCUMASK 0x1010 +#define AR_D5_QCUMASK 0x1014 +#define AR_D6_QCUMASK 0x1018 +#define AR_D7_QCUMASK 0x101c +#define AR_D8_QCUMASK 0x1020 +#define AR_D9_QCUMASK 0x1024 +#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) +#define AR_D_QCUMASK 0x000003FF +#define AR_D_QCUMASK_RESV0 0xFFFFFC00 + +#define AR_D_TXBLK_CMD 0x1038 +#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) + +#define AR_D0_LCL_IFS 0x1040 +#define AR_D1_LCL_IFS 0x1044 +#define AR_D2_LCL_IFS 0x1048 +#define AR_D3_LCL_IFS 0x104c +#define AR_D4_LCL_IFS 0x1050 +#define AR_D5_LCL_IFS 0x1054 +#define AR_D6_LCL_IFS 0x1058 +#define AR_D7_LCL_IFS 0x105c +#define AR_D8_LCL_IFS 0x1060 +#define AR_D9_LCL_IFS 0x1064 +#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) +#define AR_D_LCL_IFS_CWMIN 0x000003FF +#define AR_D_LCL_IFS_CWMIN_S 0 +#define AR_D_LCL_IFS_CWMAX 0x000FFC00 +#define AR_D_LCL_IFS_CWMAX_S 10 +#define AR_D_LCL_IFS_AIFS 0x0FF00000 +#define AR_D_LCL_IFS_AIFS_S 20 + +#define AR_D_LCL_IFS_RESV0 0xF0000000 + +#define AR_D0_RETRY_LIMIT 0x1080 +#define AR_D1_RETRY_LIMIT 0x1084 +#define AR_D2_RETRY_LIMIT 0x1088 +#define AR_D3_RETRY_LIMIT 0x108c +#define AR_D4_RETRY_LIMIT 0x1090 +#define AR_D5_RETRY_LIMIT 0x1094 +#define AR_D6_RETRY_LIMIT 0x1098 +#define AR_D7_RETRY_LIMIT 0x109c +#define AR_D8_RETRY_LIMIT 0x10a0 +#define AR_D9_RETRY_LIMIT 0x10a4 +#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) +#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F +#define AR_D_RETRY_LIMIT_FR_SH_S 0 +#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 +#define AR_D_RETRY_LIMIT_STA_SH_S 8 +#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 +#define AR_D_RETRY_LIMIT_STA_LG_S 14 +#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 + +#define AR_D0_CHNTIME 0x10c0 +#define AR_D1_CHNTIME 0x10c4 +#define AR_D2_CHNTIME 0x10c8 +#define AR_D3_CHNTIME 0x10cc +#define AR_D4_CHNTIME 0x10d0 +#define AR_D5_CHNTIME 0x10d4 +#define AR_D6_CHNTIME 0x10d8 +#define AR_D7_CHNTIME 0x10dc +#define AR_D8_CHNTIME 0x10e0 +#define AR_D9_CHNTIME 0x10e4 +#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) +#define AR_D_CHNTIME_DUR 0x000FFFFF +#define AR_D_CHNTIME_DUR_S 0 +#define AR_D_CHNTIME_EN 0x00100000 +#define AR_D_CHNTIME_RESV0 0xFFE00000 + +#define AR_D0_MISC 0x1100 +#define AR_D1_MISC 0x1104 +#define AR_D2_MISC 0x1108 +#define AR_D3_MISC 0x110c +#define AR_D4_MISC 0x1110 +#define AR_D5_MISC 0x1114 +#define AR_D6_MISC 0x1118 +#define AR_D7_MISC 0x111c +#define AR_D8_MISC 0x1120 +#define AR_D9_MISC 0x1124 +#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) +#define AR_D_MISC_BKOFF_THRESH 0x0000003F +#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040 +#define AR_D_MISC_CW_RESET_EN 0x00000080 +#define AR_D_MISC_FRAG_WAIT_EN 0x00000100 +#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 +#define AR_D_MISC_CW_BKOFF_EN 0x00001000 +#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 +#define AR_D_MISC_VIR_COL_HANDLING_S 14 +#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 +#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 +#define AR_D_MISC_BEACON_USE 0x00010000 +#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 +#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 +#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 +#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 +#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 +#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000 +#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000 +#define AR_D_MISC_RESV0 0xFF000000 + +#define AR_D_SEQNUM 0x1140 + +#define AR_D_GBL_IFS_SIFS 0x1030 +#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF +#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF + +#define AR_D_TXBLK_BASE 0x1038 +#define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF +#define AR_D_TXBLK_WRITE_BITMASK_S 0 +#define AR_D_TXBLK_WRITE_SLICE 0x000F0000 +#define AR_D_TXBLK_WRITE_SLICE_S 16 +#define AR_D_TXBLK_WRITE_DCU 0x00F00000 +#define AR_D_TXBLK_WRITE_DCU_S 20 +#define AR_D_TXBLK_WRITE_COMMAND 0x0F000000 +#define AR_D_TXBLK_WRITE_COMMAND_S 24 + +#define AR_D_GBL_IFS_SLOT 0x1070 +#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF +#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 + +#define AR_D_GBL_IFS_EIFS 0x10b0 +#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF +#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 + +#define AR_D_GBL_IFS_MISC 0x10f0 +#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 +#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 +#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 +#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 +#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000 +#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000 +#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000 +#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000 + +#define AR_D_FPCTL 0x1230 +#define AR_D_FPCTL_DCU 0x0000000F +#define AR_D_FPCTL_DCU_S 0 +#define AR_D_FPCTL_PREFETCH_EN 0x00000010 +#define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0 +#define AR_D_FPCTL_BURST_PREFETCH_S 5 + +#define AR_D_TXPSE 0x1270 +#define AR_D_TXPSE_CTRL 0x000003FF +#define AR_D_TXPSE_RESV0 0x0000FC00 +#define AR_D_TXPSE_STATUS 0x00010000 +#define AR_D_TXPSE_RESV1 0xFFFE0000 + +#define AR_D_TXSLOTMASK 0x12f0 +#define AR_D_TXSLOTMASK_NUM 0x0000000F + +#define AR_CFG_LED 0x1f04 +#define AR_CFG_SCLK_RATE_IND 0x00000003 +#define AR_CFG_SCLK_RATE_IND_S 0 +#define AR_CFG_SCLK_32MHZ 0x00000000 +#define AR_CFG_SCLK_4MHZ 0x00000001 +#define AR_CFG_SCLK_1MHZ 0x00000002 +#define AR_CFG_SCLK_32KHZ 0x00000003 +#define AR_CFG_LED_BLINK_SLOW 0x00000008 +#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 +#define AR_CFG_LED_MODE_SEL 0x00000380 +#define AR_CFG_LED_MODE_SEL_S 7 +#define AR_CFG_LED_POWER 0x00000280 +#define AR_CFG_LED_POWER_S 7 +#define AR_CFG_LED_NETWORK 0x00000300 +#define AR_CFG_LED_NETWORK_S 7 +#define AR_CFG_LED_MODE_PROP 0x0 +#define AR_CFG_LED_MODE_RPROP 0x1 +#define AR_CFG_LED_MODE_SPLIT 0x2 +#define AR_CFG_LED_MODE_RAND 0x3 +#define AR_CFG_LED_MODE_POWER_OFF 0x4 +#define AR_CFG_LED_MODE_POWER_ON 0x5 +#define AR_CFG_LED_MODE_NETWORK_OFF 0x4 +#define AR_CFG_LED_MODE_NETWORK_ON 0x6 +#define AR_CFG_LED_ASSOC_CTL 0x00000c00 +#define AR_CFG_LED_ASSOC_CTL_S 10 +#define AR_CFG_LED_ASSOC_NONE 0x0 +#define AR_CFG_LED_ASSOC_ACTIVE 0x1 +#define AR_CFG_LED_ASSOC_PENDING 0x2 + +#define AR_CFG_LED_BLINK_SLOW 0x00000008 +#define AR_CFG_LED_BLINK_SLOW_S 3 + +#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 +#define AR_CFG_LED_BLINK_THRESH_SEL_S 4 + +#define AR_MAC_SLEEP 0x1f00 +#define AR_MAC_SLEEP_MAC_AWAKE 0x00000000 +#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001 + +#define AR_RC 0x4000 +#define AR_RC_AHB 0x00000001 +#define AR_RC_APB 0x00000002 +#define AR_RC_HOSTIF 0x00000100 + +#define AR_WA 0x4004 +#define AR9285_WA_DEFAULT 0x004a05cb +#define AR9280_WA_DEFAULT 0x0040073f +#define AR_WA_DEFAULT 0x0000073f + + +#define AR_PM_STATE 0x4008 +#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 + +#define AR_HOST_TIMEOUT 0x4018 +#define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF +#define AR_HOST_TIMEOUT_APB_CNTR_S 0 +#define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 +#define AR_HOST_TIMEOUT_LCL_CNTR_S 16 + +#define AR_EEPROM 0x401c +#define AR_EEPROM_ABSENT 0x00000100 +#define AR_EEPROM_CORRUPT 0x00000200 +#define AR_EEPROM_PROT_MASK 0x03FFFC00 +#define AR_EEPROM_PROT_MASK_S 10 + +#define EEPROM_PROTECT_RP_0_31 0x0001 +#define EEPROM_PROTECT_WP_0_31 0x0002 +#define EEPROM_PROTECT_RP_32_63 0x0004 +#define EEPROM_PROTECT_WP_32_63 0x0008 +#define EEPROM_PROTECT_RP_64_127 0x0010 +#define EEPROM_PROTECT_WP_64_127 0x0020 +#define EEPROM_PROTECT_RP_128_191 0x0040 +#define EEPROM_PROTECT_WP_128_191 0x0080 +#define EEPROM_PROTECT_RP_192_255 0x0100 +#define EEPROM_PROTECT_WP_192_255 0x0200 +#define EEPROM_PROTECT_RP_256_511 0x0400 +#define EEPROM_PROTECT_WP_256_511 0x0800 +#define EEPROM_PROTECT_RP_512_1023 0x1000 +#define EEPROM_PROTECT_WP_512_1023 0x2000 +#define EEPROM_PROTECT_RP_1024_2047 0x4000 +#define EEPROM_PROTECT_WP_1024_2047 0x8000 + +#define AR_SREV \ + ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) + +#define AR_SREV_ID \ + ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) +#define AR_SREV_VERSION 0x000000F0 +#define AR_SREV_VERSION_S 4 +#define AR_SREV_REVISION 0x00000007 + +#define AR_SREV_ID2 0xFFFFFFFF +#define AR_SREV_VERSION2 0xFFFC0000 +#define AR_SREV_VERSION2_S 18 +#define AR_SREV_TYPE2 0x0003F000 +#define AR_SREV_TYPE2_S 12 +#define AR_SREV_TYPE2_CHAIN 0x00001000 +#define AR_SREV_TYPE2_HOST_MODE 0x00002000 +#define AR_SREV_REVISION2 0x00000F00 +#define AR_SREV_REVISION2_S 8 + +#define AR_SREV_VERSION_5416_PCI 0xD +#define AR_SREV_VERSION_5416_PCIE 0xC +#define AR_SREV_REVISION_5416_10 0 +#define AR_SREV_REVISION_5416_20 1 +#define AR_SREV_REVISION_5416_22 2 +#define AR_SREV_VERSION_9100 0x14 +#define AR_SREV_VERSION_9160 0x40 +#define AR_SREV_REVISION_9160_10 0 +#define AR_SREV_REVISION_9160_11 1 +#define AR_SREV_VERSION_9280 0x80 +#define AR_SREV_REVISION_9280_10 0 +#define AR_SREV_REVISION_9280_20 1 +#define AR_SREV_REVISION_9280_21 2 +#define AR_SREV_VERSION_9285 0xC0 +#define AR_SREV_REVISION_9285_10 0 +#define AR_SREV_REVISION_9285_11 1 +#define AR_SREV_REVISION_9285_12 2 + +#define AR_SREV_5416(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ + ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) +#define AR_SREV_5416_20_OR_LATER(_ah) \ + (((AR_SREV_5416(_ah)) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ + ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) +#define AR_SREV_5416_22_OR_LATER(_ah) \ + (((AR_SREV_5416(_ah)) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ + ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) + +#define AR_SREV_9100(ah) \ + ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) +#define AR_SREV_9100_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) + +#define AR_SREV_9160(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) +#define AR_SREV_9160_10_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160)) +#define AR_SREV_9160_11(_ah) \ + (AR_SREV_9160(_ah) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) +#define AR_SREV_9280(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) +#define AR_SREV_9280_10_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280)) +#define AR_SREV_9280_20(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)) +#define AR_SREV_9280_20_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))) + +#define AR_SREV_9285(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) +#define AR_SREV_9285_10_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) +#define AR_SREV_9285_11(_ah) \ + (AR_SREV_9285(ah) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) +#define AR_SREV_9285_11_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ + (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ + AR_SREV_REVISION_9285_11))) +#define AR_SREV_9285_12(_ah) \ + (AR_SREV_9285(ah) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) +#define AR_SREV_9285_12_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ + (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ + AR_SREV_REVISION_9285_12))) + +#define AR_RADIO_SREV_MAJOR 0xf0 +#define AR_RAD5133_SREV_MAJOR 0xc0 +#define AR_RAD2133_SREV_MAJOR 0xd0 +#define AR_RAD5122_SREV_MAJOR 0xe0 +#define AR_RAD2122_SREV_MAJOR 0xf0 + +#define AR_AHB_MODE 0x4024 +#define AR_AHB_EXACT_WR_EN 0x00000000 +#define AR_AHB_BUF_WR_EN 0x00000001 +#define AR_AHB_EXACT_RD_EN 0x00000000 +#define AR_AHB_CACHELINE_RD_EN 0x00000002 +#define AR_AHB_PREFETCH_RD_EN 0x00000004 +#define AR_AHB_PAGE_SIZE_1K 0x00000000 +#define AR_AHB_PAGE_SIZE_2K 0x00000008 +#define AR_AHB_PAGE_SIZE_4K 0x00000010 + +#define AR_INTR_RTC_IRQ 0x00000001 +#define AR_INTR_MAC_IRQ 0x00000002 +#define AR_INTR_EEP_PROT_ACCESS 0x00000004 +#define AR_INTR_MAC_AWAKE 0x00020000 +#define AR_INTR_MAC_ASLEEP 0x00040000 +#define AR_INTR_SPURIOUS 0xFFFFFFFF + + +#define AR_INTR_SYNC_CAUSE_CLR 0x4028 + +#define AR_INTR_SYNC_CAUSE 0x4028 + +#define AR_INTR_SYNC_ENABLE 0x402c +#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 +#define AR_INTR_SYNC_ENABLE_GPIO_S 18 + +enum { + AR_INTR_SYNC_RTC_IRQ = 0x00000001, + AR_INTR_SYNC_MAC_IRQ = 0x00000002, + AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004, + AR_INTR_SYNC_APB_TIMEOUT = 0x00000008, + AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010, + AR_INTR_SYNC_HOST1_FATAL = 0x00000020, + AR_INTR_SYNC_HOST1_PERR = 0x00000040, + AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080, + AR_INTR_SYNC_RADM_CPL_EP = 0x00000100, + AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200, + AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400, + AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800, + AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000, + AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000, + AR_INTR_SYNC_PM_ACCESS = 0x00004000, + AR_INTR_SYNC_MAC_AWAKE = 0x00008000, + AR_INTR_SYNC_MAC_ASLEEP = 0x00010000, + AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000, + AR_INTR_SYNC_ALL = 0x0003FFFF, + + + AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL | + AR_INTR_SYNC_HOST1_PERR | + AR_INTR_SYNC_RADM_CPL_EP | + AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | + AR_INTR_SYNC_RADM_CPL_TLP_ABORT | + AR_INTR_SYNC_RADM_CPL_ECRC_ERR | + AR_INTR_SYNC_RADM_CPL_TIMEOUT | + AR_INTR_SYNC_LOCAL_TIMEOUT | + AR_INTR_SYNC_MAC_SLEEP_ACCESS), + + AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, + +}; + +#define AR_INTR_ASYNC_MASK 0x4030 +#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 +#define AR_INTR_ASYNC_MASK_GPIO_S 18 + +#define AR_INTR_SYNC_MASK 0x4034 +#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 +#define AR_INTR_SYNC_MASK_GPIO_S 18 + +#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 +#define AR_INTR_ASYNC_CAUSE 0x4038 + +#define AR_INTR_ASYNC_ENABLE 0x403c +#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 +#define AR_INTR_ASYNC_ENABLE_GPIO_S 18 + +#define AR_PCIE_SERDES 0x4040 +#define AR_PCIE_SERDES2 0x4044 +#define AR_PCIE_PM_CTRL 0x4014 +#define AR_PCIE_PM_CTRL_ENA 0x00080000 + +#define AR_NUM_GPIO 14 +#define AR928X_NUM_GPIO 10 +#define AR9285_NUM_GPIO 12 + +#define AR_GPIO_IN_OUT 0x4048 +#define AR_GPIO_IN_VAL 0x0FFFC000 +#define AR_GPIO_IN_VAL_S 14 +#define AR928X_GPIO_IN_VAL 0x000FFC00 +#define AR928X_GPIO_IN_VAL_S 10 +#define AR9285_GPIO_IN_VAL 0x00FFF000 +#define AR9285_GPIO_IN_VAL_S 12 + +#define AR_GPIO_OE_OUT 0x404c +#define AR_GPIO_OE_OUT_DRV 0x3 +#define AR_GPIO_OE_OUT_DRV_NO 0x0 +#define AR_GPIO_OE_OUT_DRV_LOW 0x1 +#define AR_GPIO_OE_OUT_DRV_HI 0x2 +#define AR_GPIO_OE_OUT_DRV_ALL 0x3 + +#define AR_GPIO_INTR_POL 0x4050 +#define AR_GPIO_INTR_POL_VAL 0x00001FFF +#define AR_GPIO_INTR_POL_VAL_S 0 + +#define AR_GPIO_INPUT_EN_VAL 0x4054 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 +#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 +#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 +#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 +#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 +#define AR_GPIO_JTAG_DISABLE 0x00020000 + +#define AR_GPIO_INPUT_MUX1 0x4058 +#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 +#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 + +#define AR_GPIO_INPUT_MUX2 0x405c +#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f +#define AR_GPIO_INPUT_MUX2_CLK25_S 0 +#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 +#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4 +#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 +#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 + +#define AR_GPIO_OUTPUT_MUX1 0x4060 +#define AR_GPIO_OUTPUT_MUX2 0x4064 +#define AR_GPIO_OUTPUT_MUX3 0x4068 + +#define AR_INPUT_STATE 0x406c + +#define AR_EEPROM_STATUS_DATA 0x407c +#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff +#define AR_EEPROM_STATUS_DATA_VAL_S 0 +#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 +#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 +#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 +#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 + +#define AR_OBS 0x4080 + +#define AR_PCIE_MSI 0x4094 +#define AR_PCIE_MSI_ENABLE 0x00000001 + + +#define AR_RTC_9160_PLL_DIV 0x000003ff +#define AR_RTC_9160_PLL_DIV_S 0 +#define AR_RTC_9160_PLL_REFDIV 0x00003C00 +#define AR_RTC_9160_PLL_REFDIV_S 10 +#define AR_RTC_9160_PLL_CLKSEL 0x0000C000 +#define AR_RTC_9160_PLL_CLKSEL_S 14 + +#define AR_RTC_BASE 0x00020000 +#define AR_RTC_RC \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000) +#define AR_RTC_RC_M 0x00000003 +#define AR_RTC_RC_MAC_WARM 0x00000001 +#define AR_RTC_RC_MAC_COLD 0x00000002 +#define AR_RTC_RC_COLD_RESET 0x00000004 +#define AR_RTC_RC_WARM_RESET 0x00000008 + +#define AR_RTC_PLL_CONTROL \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) + +#define AR_RTC_PLL_DIV 0x0000001f +#define AR_RTC_PLL_DIV_S 0 +#define AR_RTC_PLL_DIV2 0x00000020 +#define AR_RTC_PLL_REFDIV_5 0x000000c0 +#define AR_RTC_PLL_CLKSEL 0x00000300 +#define AR_RTC_PLL_CLKSEL_S 8 + +#define AR_RTC_RESET \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) +#define AR_RTC_RESET_EN (0x00000001) + +#define AR_RTC_STATUS \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044) + +#define AR_RTC_STATUS_M \ + ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f) + +#define AR_RTC_PM_STATUS_M 0x0000000f + +#define AR_RTC_STATUS_SHUTDOWN 0x00000001 +#define AR_RTC_STATUS_ON 0x00000002 +#define AR_RTC_STATUS_SLEEP 0x00000004 +#define AR_RTC_STATUS_WAKEUP 0x00000008 + +#define AR_RTC_SLEEP_CLK \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048) +#define AR_RTC_FORCE_DERIVED_CLK 0x2 + +#define AR_RTC_FORCE_WAKE \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c) +#define AR_RTC_FORCE_WAKE_EN 0x00000001 +#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 + + +#define AR_RTC_INTR_CAUSE \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050) + +#define AR_RTC_INTR_ENABLE \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054) + +#define AR_RTC_INTR_MASK \ + ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) + +/* RTC_DERIVED_* - only for AR9100 */ + +#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) +#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe +#define AR_RTC_DERIVED_CLK_PERIOD_S 1 + +#define AR_SEQ_MASK 0x8060 + +#define AR_AN_RF2G1_CH0 0x7810 +#define AR_AN_RF2G1_CH0_OB 0x03800000 +#define AR_AN_RF2G1_CH0_OB_S 23 +#define AR_AN_RF2G1_CH0_DB 0x1C000000 +#define AR_AN_RF2G1_CH0_DB_S 26 + +#define AR_AN_RF5G1_CH0 0x7818 +#define AR_AN_RF5G1_CH0_OB5 0x00070000 +#define AR_AN_RF5G1_CH0_OB5_S 16 +#define AR_AN_RF5G1_CH0_DB5 0x00380000 +#define AR_AN_RF5G1_CH0_DB5_S 19 + +#define AR_AN_RF2G1_CH1 0x7834 +#define AR_AN_RF2G1_CH1_OB 0x03800000 +#define AR_AN_RF2G1_CH1_OB_S 23 +#define AR_AN_RF2G1_CH1_DB 0x1C000000 +#define AR_AN_RF2G1_CH1_DB_S 26 + +#define AR_AN_RF5G1_CH1 0x783C +#define AR_AN_RF5G1_CH1_OB5 0x00070000 +#define AR_AN_RF5G1_CH1_OB5_S 16 +#define AR_AN_RF5G1_CH1_DB5 0x00380000 +#define AR_AN_RF5G1_CH1_DB5_S 19 + +#define AR_AN_TOP1 0x7890 +#define AR_AN_TOP1_DACIPMODE 0x00040000 +#define AR_AN_TOP1_DACIPMODE_S 18 + +#define AR_AN_TOP2 0x7894 +#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 +#define AR_AN_TOP2_XPABIAS_LVL_S 30 +#define AR_AN_TOP2_LOCALBIAS 0x00200000 +#define AR_AN_TOP2_LOCALBIAS_S 21 +#define AR_AN_TOP2_PWDCLKIND 0x00400000 +#define AR_AN_TOP2_PWDCLKIND_S 22 + +#define AR_AN_SYNTH9 0x7868 +#define AR_AN_SYNTH9_REFDIVA 0xf8000000 +#define AR_AN_SYNTH9_REFDIVA_S 27 + +#define AR9285_AN_RF2G1 0x7820 +#define AR9285_AN_RF2G1_ENPACAL 0x00000800 +#define AR9285_AN_RF2G1_ENPACAL_S 11 +#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 +#define AR9285_AN_RF2G1_PDPADRV1_S 25 +#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 +#define AR9285_AN_RF2G1_PDPADRV2_S 24 +#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 +#define AR9285_AN_RF2G1_PDPAOUT_S 23 + + +#define AR9285_AN_RF2G2 0x7824 +#define AR9285_AN_RF2G2_OFFCAL 0x00001000 +#define AR9285_AN_RF2G2_OFFCAL_S 12 + +#define AR9285_AN_RF2G3 0x7828 +#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 +#define AR9285_AN_RF2G3_PDVCCOMP_S 25 +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 + +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 +#define AR9285_AN_RF2G4 0x782C +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_AN_RF2G6 0x7834 +#define AR9285_AN_RF2G6_CCOMP 0x00007800 +#define AR9285_AN_RF2G6_CCOMP_S 11 +#define AR9285_AN_RF2G6_OFFS 0x03f00000 +#define AR9285_AN_RF2G6_OFFS_S 20 + +#define AR9285_AN_RF2G7 0x7838 +#define AR9285_AN_RF2G7_PWDDB 0x00000002 +#define AR9285_AN_RF2G7_PWDDB_S 1 +#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 +#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 + +#define AR9285_AN_RF2G8 0x783C +#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 +#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 + + +#define AR9285_AN_RF2G9 0x7840 +#define AR9285_AN_RXTXBB1 0x7854 +#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 +#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 +#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 +#define AR9285_AN_RXTXBB1_PDV2I_S 7 +#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 +#define AR9285_AN_RXTXBB1_PDDACIF_S 8 +#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 +#define AR9285_AN_RXTXBB1_SPARE9_S 0 + +#define AR9285_AN_TOP2 0x7868 + +#define AR9285_AN_TOP3 0x786c +#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C +#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 +#define AR9285_AN_TOP3_PWDDAC 0x00800000 +#define AR9285_AN_TOP3_PWDDAC_S 23 + +#define AR9285_AN_TOP4 0x7870 +#define AR9285_AN_TOP4_DEFAULT 0x10142c00 + +#define AR_STA_ID0 0x8000 +#define AR_STA_ID1 0x8004 +#define AR_STA_ID1_SADH_MASK 0x0000FFFF +#define AR_STA_ID1_STA_AP 0x00010000 +#define AR_STA_ID1_ADHOC 0x00020000 +#define AR_STA_ID1_PWR_SAV 0x00040000 +#define AR_STA_ID1_KSRCHDIS 0x00080000 +#define AR_STA_ID1_PCF 0x00100000 +#define AR_STA_ID1_USE_DEFANT 0x00200000 +#define AR_STA_ID1_DEFANT_UPDATE 0x00400000 +#define AR_STA_ID1_RTS_USE_DEF 0x00800000 +#define AR_STA_ID1_ACKCTS_6MB 0x01000000 +#define AR_STA_ID1_BASE_RATE_11B 0x02000000 +#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000 +#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 +#define AR_STA_ID1_KSRCH_MODE 0x10000000 +#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 +#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 +#define AR_STA_ID1_MCAST_KSRCH 0x80000000 + +#define AR_BSS_ID0 0x8008 +#define AR_BSS_ID1 0x800C +#define AR_BSS_ID1_U16 0x0000FFFF +#define AR_BSS_ID1_AID 0x07FF0000 +#define AR_BSS_ID1_AID_S 16 + +#define AR_BCN_RSSI_AVE 0x8010 +#define AR_BCN_RSSI_AVE_MASK 0x00000FFF + +#define AR_TIME_OUT 0x8014 +#define AR_TIME_OUT_ACK 0x00003FFF +#define AR_TIME_OUT_ACK_S 0 +#define AR_TIME_OUT_CTS 0x3FFF0000 +#define AR_TIME_OUT_CTS_S 16 + +#define AR_RSSI_THR 0x8018 +#define AR_RSSI_THR_MASK 0x000000FF +#define AR_RSSI_THR_BM_THR 0x0000FF00 +#define AR_RSSI_THR_BM_THR_S 8 +#define AR_RSSI_BCN_WEIGHT 0x1F000000 +#define AR_RSSI_BCN_WEIGHT_S 24 +#define AR_RSSI_BCN_RSSI_RST 0x20000000 + +#define AR_USEC 0x801c +#define AR_USEC_USEC 0x0000007F +#define AR_USEC_TX_LAT 0x007FC000 +#define AR_USEC_TX_LAT_S 14 +#define AR_USEC_RX_LAT 0x1F800000 +#define AR_USEC_RX_LAT_S 23 + +#define AR_RESET_TSF 0x8020 +#define AR_RESET_TSF_ONCE 0x01000000 + +#define AR_MAX_CFP_DUR 0x8038 +#define AR_CFP_VAL 0x0000FFFF + +#define AR_RX_FILTER 0x803C +#define AR_RX_COMPR_BAR 0x00000400 + +#define AR_MCAST_FIL0 0x8040 +#define AR_MCAST_FIL1 0x8044 + +#define AR_DIAG_SW 0x8048 +#define AR_DIAG_CACHE_ACK 0x00000001 +#define AR_DIAG_ACK_DIS 0x00000002 +#define AR_DIAG_CTS_DIS 0x00000004 +#define AR_DIAG_ENCRYPT_DIS 0x00000008 +#define AR_DIAG_DECRYPT_DIS 0x00000010 +#define AR_DIAG_RX_DIS 0x00000020 +#define AR_DIAG_LOOP_BACK 0x00000040 +#define AR_DIAG_CORR_FCS 0x00000080 +#define AR_DIAG_CHAN_INFO 0x00000100 +#define AR_DIAG_SCRAM_SEED 0x0001FE00 +#define AR_DIAG_SCRAM_SEED_S 8 +#define AR_DIAG_FRAME_NV0 0x00020000 +#define AR_DIAG_OBS_PT_SEL1 0x000C0000 +#define AR_DIAG_OBS_PT_SEL1_S 18 +#define AR_DIAG_FORCE_RX_CLEAR 0x00100000 +#define AR_DIAG_IGNORE_VIRT_CS 0x00200000 +#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 +#define AR_DIAG_EIFS_CTRL_ENA 0x00800000 +#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 +#define AR_DIAG_RX_ABORT 0x02000000 +#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000 +#define AR_DIAG_OBS_PT_SEL2 0x08000000 +#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000 +#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000 + +#define AR_TSF_L32 0x804c +#define AR_TSF_U32 0x8050 + +#define AR_TST_ADDAC 0x8054 +#define AR_DEF_ANTENNA 0x8058 + +#define AR_AES_MUTE_MASK0 0x805c +#define AR_AES_MUTE_MASK0_FC 0x0000FFFF +#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 +#define AR_AES_MUTE_MASK0_QOS_S 16 + +#define AR_AES_MUTE_MASK1 0x8060 +#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF +#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 +#define AR_AES_MUTE_MASK1_FC_MGMT_S 16 + +#define AR_GATED_CLKS 0x8064 +#define AR_GATED_CLKS_TX 0x00000002 +#define AR_GATED_CLKS_RX 0x00000004 +#define AR_GATED_CLKS_REG 0x00000008 + +#define AR_OBS_BUS_CTRL 0x8068 +#define AR_OBS_BUS_SEL_1 0x00040000 +#define AR_OBS_BUS_SEL_2 0x00080000 +#define AR_OBS_BUS_SEL_3 0x000C0000 +#define AR_OBS_BUS_SEL_4 0x08040000 +#define AR_OBS_BUS_SEL_5 0x08080000 + +#define AR_OBS_BUS_1 0x806c +#define AR_OBS_BUS_1_PCU 0x00000001 +#define AR_OBS_BUS_1_RX_END 0x00000002 +#define AR_OBS_BUS_1_RX_WEP 0x00000004 +#define AR_OBS_BUS_1_RX_BEACON 0x00000008 +#define AR_OBS_BUS_1_RX_FILTER 0x00000010 +#define AR_OBS_BUS_1_TX_HCF 0x00000020 +#define AR_OBS_BUS_1_QUIET_TIME 0x00000040 +#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080 +#define AR_OBS_BUS_1_TX_HOLD 0x00000100 +#define AR_OBS_BUS_1_TX_FRAME 0x00000200 +#define AR_OBS_BUS_1_RX_FRAME 0x00000400 +#define AR_OBS_BUS_1_RX_CLEAR 0x00000800 +#define AR_OBS_BUS_1_WEP_STATE 0x0003F000 +#define AR_OBS_BUS_1_WEP_STATE_S 12 +#define AR_OBS_BUS_1_RX_STATE 0x01F00000 +#define AR_OBS_BUS_1_RX_STATE_S 20 +#define AR_OBS_BUS_1_TX_STATE 0x7E000000 +#define AR_OBS_BUS_1_TX_STATE_S 25 + +#define AR_LAST_TSTP 0x8080 +#define AR_NAV 0x8084 +#define AR_RTS_OK 0x8088 +#define AR_RTS_FAIL 0x808c +#define AR_ACK_FAIL 0x8090 +#define AR_FCS_FAIL 0x8094 +#define AR_BEACON_CNT 0x8098 + +#define AR_SLEEP1 0x80d4 +#define AR_SLEEP1_ASSUME_DTIM 0x00080000 +#define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000 +#define AR_SLEEP1_CAB_TIMEOUT_S 21 + +#define AR_SLEEP2 0x80d8 +#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 +#define AR_SLEEP2_BEACON_TIMEOUT_S 21 + +#define AR_BSSMSKL 0x80e0 +#define AR_BSSMSKU 0x80e4 + +#define AR_TPC 0x80e8 +#define AR_TPC_ACK 0x0000003f +#define AR_TPC_ACK_S 0x00 +#define AR_TPC_CTS 0x00003f00 +#define AR_TPC_CTS_S 0x08 +#define AR_TPC_CHIRP 0x003f0000 +#define AR_TPC_CHIRP_S 0x16 + +#define AR_TFCNT 0x80ec +#define AR_RFCNT 0x80f0 +#define AR_RCCNT 0x80f4 +#define AR_CCCNT 0x80f8 + +#define AR_QUIET1 0x80fc +#define AR_QUIET1_NEXT_QUIET_S 0 +#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff +#define AR_QUIET1_QUIET_ENABLE 0x00010000 +#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 +#define AR_QUIET2 0x8100 +#define AR_QUIET2_QUIET_PERIOD_S 0 +#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff +#define AR_QUIET2_QUIET_DUR_S 16 +#define AR_QUIET2_QUIET_DUR 0xffff0000 + +#define AR_TSF_PARM 0x8104 +#define AR_TSF_INCREMENT_M 0x000000ff +#define AR_TSF_INCREMENT_S 0x00 + +#define AR_QOS_NO_ACK 0x8108 +#define AR_QOS_NO_ACK_TWO_BIT 0x0000000f +#define AR_QOS_NO_ACK_TWO_BIT_S 0 +#define AR_QOS_NO_ACK_BIT_OFF 0x00000070 +#define AR_QOS_NO_ACK_BIT_OFF_S 4 +#define AR_QOS_NO_ACK_BYTE_OFF 0x00000180 +#define AR_QOS_NO_ACK_BYTE_OFF_S 7 + +#define AR_PHY_ERR 0x810c + +#define AR_PHY_ERR_DCHIRP 0x00000008 +#define AR_PHY_ERR_RADAR 0x00000020 +#define AR_PHY_ERR_OFDM_TIMING 0x00020000 +#define AR_PHY_ERR_CCK_TIMING 0x02000000 + +#define AR_RXFIFO_CFG 0x8114 + + +#define AR_MIC_QOS_CONTROL 0x8118 +#define AR_MIC_QOS_SELECT 0x811c + +#define AR_PCU_MISC 0x8120 +#define AR_PCU_FORCE_BSSID_MATCH 0x00000001 +#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 +#define AR_PCU_TX_ADD_TSF 0x00000008 +#define AR_PCU_CCK_SIFS_MODE 0x00000010 +#define AR_PCU_RX_ANT_UPDT 0x00000800 +#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 +#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 +#define AR_PCU_BUG_12306_FIX_ENA 0x00020000 +#define AR_PCU_FORCE_QUIET_COLL 0x00040000 +#define AR_PCU_TBTT_PROTECT 0x00200000 +#define AR_PCU_CLEAR_VMF 0x01000000 +#define AR_PCU_CLEAR_BA_VALID 0x04000000 + + +#define AR_FILT_OFDM 0x8124 +#define AR_FILT_OFDM_COUNT 0x00FFFFFF + +#define AR_FILT_CCK 0x8128 +#define AR_FILT_CCK_COUNT 0x00FFFFFF + +#define AR_PHY_ERR_1 0x812c +#define AR_PHY_ERR_1_COUNT 0x00FFFFFF +#define AR_PHY_ERR_MASK_1 0x8130 + +#define AR_PHY_ERR_2 0x8134 +#define AR_PHY_ERR_2_COUNT 0x00FFFFFF +#define AR_PHY_ERR_MASK_2 0x8138 + +#define AR_PHY_COUNTMAX (3 << 22) +#define AR_MIBCNT_INTRMASK (3 << 22) + +#define AR_TSFOOR_THRESHOLD 0x813c +#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF + +#define AR_PHY_ERR_EIFS_MASK 8144 + +#define AR_PHY_ERR_3 0x8168 +#define AR_PHY_ERR_3_COUNT 0x00FFFFFF +#define AR_PHY_ERR_MASK_3 0x816c + +#define AR_TXSIFS 0x81d0 +#define AR_TXSIFS_TIME 0x000000FF +#define AR_TXSIFS_TX_LATENCY 0x00000F00 +#define AR_TXSIFS_TX_LATENCY_S 8 +#define AR_TXSIFS_ACK_SHIFT 0x00007000 +#define AR_TXSIFS_ACK_SHIFT_S 12 + +#define AR_TXOP_X 0x81ec +#define AR_TXOP_X_VAL 0x000000FF + + +#define AR_TXOP_0_3 0x81f0 +#define AR_TXOP_4_7 0x81f4 +#define AR_TXOP_8_11 0x81f8 +#define AR_TXOP_12_15 0x81fc + + +#define AR_NEXT_TBTT_TIMER 0x8200 +#define AR_NEXT_DMA_BEACON_ALERT 0x8204 +#define AR_NEXT_SWBA 0x8208 +#define AR_NEXT_CFP 0x8208 +#define AR_NEXT_HCF 0x820C +#define AR_NEXT_TIM 0x8210 +#define AR_NEXT_DTIM 0x8214 +#define AR_NEXT_QUIET_TIMER 0x8218 +#define AR_NEXT_NDP_TIMER 0x821C + +#define AR_BEACON_PERIOD 0x8220 +#define AR_DMA_BEACON_PERIOD 0x8224 +#define AR_SWBA_PERIOD 0x8228 +#define AR_HCF_PERIOD 0x822C +#define AR_TIM_PERIOD 0x8230 +#define AR_DTIM_PERIOD 0x8234 +#define AR_QUIET_PERIOD 0x8238 +#define AR_NDP_PERIOD 0x823C + +#define AR_TIMER_MODE 0x8240 +#define AR_TBTT_TIMER_EN 0x00000001 +#define AR_DBA_TIMER_EN 0x00000002 +#define AR_SWBA_TIMER_EN 0x00000004 +#define AR_HCF_TIMER_EN 0x00000008 +#define AR_TIM_TIMER_EN 0x00000010 +#define AR_DTIM_TIMER_EN 0x00000020 +#define AR_QUIET_TIMER_EN 0x00000040 +#define AR_NDP_TIMER_EN 0x00000080 +#define AR_TIMER_OVERFLOW_INDEX 0x00000700 +#define AR_TIMER_OVERFLOW_INDEX_S 8 +#define AR_TIMER_THRESH 0xFFFFF000 +#define AR_TIMER_THRESH_S 12 + +#define AR_SLP32_MODE 0x8244 +#define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF +#define AR_SLP32_ENA 0x00100000 +#define AR_SLP32_TSF_WRITE_STATUS 0x00200000 + +#define AR_SLP32_WAKE 0x8248 +#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF + +#define AR_SLP32_INC 0x824c +#define AR_SLP32_TST_INC 0x000FFFFF + +#define AR_SLP_CNT 0x8250 +#define AR_SLP_CYCLE_CNT 0x8254 + +#define AR_SLP_MIB_CTRL 0x8258 +#define AR_SLP_MIB_CLEAR 0x00000001 +#define AR_SLP_MIB_PENDING 0x00000002 + +#define AR_2040_MODE 0x8318 +#define AR_2040_JOINED_RX_CLEAR 0x00000001 + + +#define AR_EXTRCCNT 0x8328 + +#define AR_SELFGEN_MASK 0x832c + +#define AR_PCU_TXBUF_CTRL 0x8340 +#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF +#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 +#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 + +#define AR_PCU_MISC_MODE2 0x8344 +#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 +#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 + +#define AR_KEYTABLE_0 0x8800 +#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) +#define AR_KEY_CACHE_SIZE 128 +#define AR_RSVD_KEYTABLE_ENTRIES 4 +#define AR_KEY_TYPE 0x00000007 +#define AR_KEYTABLE_TYPE_40 0x00000000 +#define AR_KEYTABLE_TYPE_104 0x00000001 +#define AR_KEYTABLE_TYPE_128 0x00000003 +#define AR_KEYTABLE_TYPE_TKIP 0x00000004 +#define AR_KEYTABLE_TYPE_AES 0x00000005 +#define AR_KEYTABLE_TYPE_CCM 0x00000006 +#define AR_KEYTABLE_TYPE_CLR 0x00000007 +#define AR_KEYTABLE_ANT 0x00000008 +#define AR_KEYTABLE_VALID 0x00008000 +#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) +#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) +#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) +#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) +#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) +#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) +#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) +#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) + +#endif diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c new file mode 100644 index 000000000000..1ff429b027d7 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -0,0 +1,662 @@ +/* + * 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 "ath9k.h" + +struct ath9k_vif_iter_data { + int count; + u8 *addr; +}; + +static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath9k_vif_iter_data *iter_data = data; + u8 *nbuf; + + nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN, + GFP_ATOMIC); + if (nbuf == NULL) + return; + + memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN); + iter_data->addr = nbuf; + iter_data->count++; +} + +void ath9k_set_bssid_mask(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath9k_vif_iter_data iter_data; + int i, j; + u8 mask[ETH_ALEN]; + + /* + * Add primary MAC address even if it is not in active use since it + * will be configured to the hardware as the starting point and the + * BSSID mask will need to be changed if another address is active. + */ + iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); + if (iter_data.addr) { + memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN); + iter_data.count = 1; + } else + iter_data.count = 0; + + /* Get list of all active MAC addresses */ + spin_lock_bh(&sc->wiphy_lock); + ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, + &iter_data); + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] == NULL) + continue; + ieee80211_iterate_active_interfaces_atomic( + sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data); + } + spin_unlock_bh(&sc->wiphy_lock); + + /* Generate an address mask to cover all active addresses */ + memset(mask, 0, ETH_ALEN); + for (i = 0; i < iter_data.count; i++) { + u8 *a1 = iter_data.addr + i * ETH_ALEN; + for (j = i + 1; j < iter_data.count; j++) { + u8 *a2 = iter_data.addr + j * ETH_ALEN; + mask[0] |= a1[0] ^ a2[0]; + mask[1] |= a1[1] ^ a2[1]; + mask[2] |= a1[2] ^ a2[2]; + mask[3] |= a1[3] ^ a2[3]; + mask[4] |= a1[4] ^ a2[4]; + mask[5] |= a1[5] ^ a2[5]; + } + } + + kfree(iter_data.addr); + + /* Invert the mask and configure hardware */ + sc->bssidmask[0] = ~mask[0]; + sc->bssidmask[1] = ~mask[1]; + sc->bssidmask[2] = ~mask[2]; + sc->bssidmask[3] = ~mask[3]; + sc->bssidmask[4] = ~mask[4]; + sc->bssidmask[5] = ~mask[5]; + + ath9k_hw_setbssidmask(sc); +} + +int ath9k_wiphy_add(struct ath_softc *sc) +{ + int i, error; + struct ath_wiphy *aphy; + struct ieee80211_hw *hw; + u8 addr[ETH_ALEN]; + + hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); + if (hw == NULL) + return -ENOMEM; + + spin_lock_bh(&sc->wiphy_lock); + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] == NULL) + break; + } + + if (i == sc->num_sec_wiphy) { + /* No empty slot available; increase array length */ + struct ath_wiphy **n; + n = krealloc(sc->sec_wiphy, + (sc->num_sec_wiphy + 1) * + sizeof(struct ath_wiphy *), + GFP_ATOMIC); + if (n == NULL) { + spin_unlock_bh(&sc->wiphy_lock); + ieee80211_free_hw(hw); + return -ENOMEM; + } + n[i] = NULL; + sc->sec_wiphy = n; + sc->num_sec_wiphy++; + } + + SET_IEEE80211_DEV(hw, sc->dev); + + aphy = hw->priv; + aphy->sc = sc; + aphy->hw = hw; + sc->sec_wiphy[i] = aphy; + spin_unlock_bh(&sc->wiphy_lock); + + memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN); + addr[0] |= 0x02; /* Locally managed address */ + /* + * XOR virtual wiphy index into the least significant bits to generate + * a different MAC address for each virtual wiphy. + */ + addr[5] ^= i & 0xff; + addr[4] ^= (i & 0xff00) >> 8; + addr[3] ^= (i & 0xff0000) >> 16; + + SET_IEEE80211_PERM_ADDR(hw, addr); + + ath_set_hw_capab(sc, hw); + + error = ieee80211_register_hw(hw); + + if (error == 0) { + /* Make sure wiphy scheduler is started (if enabled) */ + ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); + } + + return error; +} + +int ath9k_wiphy_del(struct ath_wiphy *aphy) +{ + struct ath_softc *sc = aphy->sc; + int i; + + spin_lock_bh(&sc->wiphy_lock); + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (aphy == sc->sec_wiphy[i]) { + sc->sec_wiphy[i] = NULL; + spin_unlock_bh(&sc->wiphy_lock); + ieee80211_unregister_hw(aphy->hw); + ieee80211_free_hw(aphy->hw); + return 0; + } + } + spin_unlock_bh(&sc->wiphy_lock); + return -ENOENT; +} + +static int ath9k_send_nullfunc(struct ath_wiphy *aphy, + struct ieee80211_vif *vif, const u8 *bssid, + int ps) +{ + struct ath_softc *sc = aphy->sc; + struct ath_tx_control txctl; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + __le16 fc; + struct ieee80211_tx_info *info; + + skb = dev_alloc_skb(24); + if (skb == NULL) + return -ENOMEM; + hdr = (struct ieee80211_hdr *) skb_put(skb, 24); + memset(hdr, 0, 24); + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS); + if (ps) + fc |= cpu_to_le16(IEEE80211_FCTL_PM); + hdr->frame_control = fc; + memcpy(hdr->addr1, bssid, ETH_ALEN); + memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN); + memcpy(hdr->addr3, bssid, ETH_ALEN); + + info = IEEE80211_SKB_CB(skb); + memset(info, 0, sizeof(*info)); + info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS; + info->control.vif = vif; + info->control.rates[0].idx = 0; + info->control.rates[0].count = 4; + info->control.rates[1].idx = -1; + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; + txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE; + + if (ath_tx_start(aphy->hw, skb, &txctl) != 0) + goto exit; + + return 0; +exit: + dev_kfree_skb_any(skb); + return -1; +} + +static bool __ath9k_wiphy_pausing(struct ath_softc *sc) +{ + int i; + if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING) + return true; + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] && + sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING) + return true; + } + return false; +} + +static bool ath9k_wiphy_pausing(struct ath_softc *sc) +{ + bool ret; + spin_lock_bh(&sc->wiphy_lock); + ret = __ath9k_wiphy_pausing(sc); + spin_unlock_bh(&sc->wiphy_lock); + return ret; +} + +static bool __ath9k_wiphy_scanning(struct ath_softc *sc) +{ + int i; + if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) + return true; + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] && + sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) + return true; + } + return false; +} + +bool ath9k_wiphy_scanning(struct ath_softc *sc) +{ + bool ret; + spin_lock_bh(&sc->wiphy_lock); + ret = __ath9k_wiphy_scanning(sc); + spin_unlock_bh(&sc->wiphy_lock); + return ret; +} + +static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); + +/* caller must hold wiphy_lock */ +static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy) +{ + if (aphy == NULL) + return; + if (aphy->chan_idx != aphy->sc->chan_idx) + return; /* wiphy not on the selected channel */ + __ath9k_wiphy_unpause(aphy); +} + +static void ath9k_wiphy_unpause_channel(struct ath_softc *sc) +{ + int i; + spin_lock_bh(&sc->wiphy_lock); + __ath9k_wiphy_unpause_ch(sc->pri_wiphy); + for (i = 0; i < sc->num_sec_wiphy; i++) + __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]); + spin_unlock_bh(&sc->wiphy_lock); +} + +void ath9k_wiphy_chan_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); + struct ath_wiphy *aphy = sc->next_wiphy; + + if (aphy == NULL) + return; + + /* + * All pending interfaces paused; ready to change + * channels. + */ + + /* Change channels */ + mutex_lock(&sc->mutex); + /* XXX: remove me eventually */ + ath9k_update_ichannel(sc, aphy->hw, + &sc->sc_ah->channels[sc->chan_idx]); + ath_update_chainmask(sc, sc->chan_is_ht); + if (ath_set_channel(sc, aphy->hw, + &sc->sc_ah->channels[sc->chan_idx]) < 0) { + printk(KERN_DEBUG "ath9k: Failed to set channel for new " + "virtual wiphy\n"); + mutex_unlock(&sc->mutex); + return; + } + mutex_unlock(&sc->mutex); + + ath9k_wiphy_unpause_channel(sc); +} + +/* + * ath9k version of ieee80211_tx_status() for TX frames that are generated + * internally in the driver. + */ +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath_wiphy *aphy = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + + if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE && + aphy->state == ATH_WIPHY_PAUSING) { + if (!(info->flags & IEEE80211_TX_STAT_ACK)) { + printk(KERN_DEBUG "ath9k: %s: no ACK for pause " + "frame\n", wiphy_name(hw->wiphy)); + /* + * The AP did not reply; ignore this to allow us to + * continue. + */ + } + aphy->state = ATH_WIPHY_PAUSED; + if (!ath9k_wiphy_pausing(aphy->sc)) { + /* + * Drop from tasklet to work to allow mutex for channel + * change. + */ + queue_work(aphy->sc->hw->workqueue, + &aphy->sc->chan_work); + } + } + + kfree(tx_info_priv); + tx_info->rate_driver_data[0] = NULL; + + dev_kfree_skb(skb); +} + +static void ath9k_mark_paused(struct ath_wiphy *aphy) +{ + struct ath_softc *sc = aphy->sc; + aphy->state = ATH_WIPHY_PAUSED; + if (!__ath9k_wiphy_pausing(sc)) + queue_work(sc->hw->workqueue, &sc->chan_work); +} + +static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath_wiphy *aphy = data; + struct ath_vif *avp = (void *) vif->drv_priv; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + if (!vif->bss_conf.assoc) { + ath9k_mark_paused(aphy); + break; + } + /* TODO: could avoid this if already in PS mode */ + if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) { + printk(KERN_DEBUG "%s: failed to send PS nullfunc\n", + __func__); + ath9k_mark_paused(aphy); + } + break; + case NL80211_IFTYPE_AP: + /* Beacon transmission is paused by aphy->state change */ + ath9k_mark_paused(aphy); + break; + default: + break; + } +} + +/* caller must hold wiphy_lock */ +static int __ath9k_wiphy_pause(struct ath_wiphy *aphy) +{ + ieee80211_stop_queues(aphy->hw); + aphy->state = ATH_WIPHY_PAUSING; + /* + * TODO: handle PAUSING->PAUSED for the case where there are multiple + * active vifs (now we do it on the first vif getting ready; should be + * on the last) + */ + ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter, + aphy); + return 0; +} + +int ath9k_wiphy_pause(struct ath_wiphy *aphy) +{ + int ret; + spin_lock_bh(&aphy->sc->wiphy_lock); + ret = __ath9k_wiphy_pause(aphy); + spin_unlock_bh(&aphy->sc->wiphy_lock); + return ret; +} + +static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath_wiphy *aphy = data; + struct ath_vif *avp = (void *) vif->drv_priv; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + if (!vif->bss_conf.assoc) + break; + ath9k_send_nullfunc(aphy, vif, avp->bssid, 0); + break; + case NL80211_IFTYPE_AP: + /* Beacon transmission is re-enabled by aphy->state change */ + break; + default: + break; + } +} + +/* caller must hold wiphy_lock */ +static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy) +{ + ieee80211_iterate_active_interfaces_atomic(aphy->hw, + ath9k_unpause_iter, aphy); + aphy->state = ATH_WIPHY_ACTIVE; + ieee80211_wake_queues(aphy->hw); + return 0; +} + +int ath9k_wiphy_unpause(struct ath_wiphy *aphy) +{ + int ret; + spin_lock_bh(&aphy->sc->wiphy_lock); + ret = __ath9k_wiphy_unpause(aphy); + spin_unlock_bh(&aphy->sc->wiphy_lock); + return ret; +} + +static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc) +{ + int i; + if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) + sc->pri_wiphy->state = ATH_WIPHY_PAUSED; + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] && + sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) + sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED; + } +} + +/* caller must hold wiphy_lock */ +static void __ath9k_wiphy_pause_all(struct ath_softc *sc) +{ + int i; + if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) + __ath9k_wiphy_pause(sc->pri_wiphy); + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] && + sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) + __ath9k_wiphy_pause(sc->sec_wiphy[i]); + } +} + +int ath9k_wiphy_select(struct ath_wiphy *aphy) +{ + struct ath_softc *sc = aphy->sc; + bool now; + + spin_lock_bh(&sc->wiphy_lock); + if (__ath9k_wiphy_scanning(sc)) { + /* + * For now, we are using mac80211 sw scan and it expects to + * have full control over channel changes, so avoid wiphy + * scheduling during a scan. This could be optimized if the + * scanning control were moved into the driver. + */ + spin_unlock_bh(&sc->wiphy_lock); + return -EBUSY; + } + if (__ath9k_wiphy_pausing(sc)) { + if (sc->wiphy_select_failures == 0) + sc->wiphy_select_first_fail = jiffies; + sc->wiphy_select_failures++; + if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2)) + { + printk(KERN_DEBUG "ath9k: Previous wiphy select timed " + "out; disable/enable hw to recover\n"); + __ath9k_wiphy_mark_all_paused(sc); + /* + * TODO: this workaround to fix hardware is unlikely to + * be specific to virtual wiphy changes. It can happen + * on normal channel change, too, and as such, this + * should really be made more generic. For example, + * tricker radio disable/enable on GTT interrupt burst + * (say, 10 GTT interrupts received without any TX + * frame being completed) + */ + spin_unlock_bh(&sc->wiphy_lock); + ath_radio_disable(sc); + ath_radio_enable(sc); + queue_work(aphy->sc->hw->workqueue, + &aphy->sc->chan_work); + return -EBUSY; /* previous select still in progress */ + } + spin_unlock_bh(&sc->wiphy_lock); + return -EBUSY; /* previous select still in progress */ + } + sc->wiphy_select_failures = 0; + + /* Store the new channel */ + sc->chan_idx = aphy->chan_idx; + sc->chan_is_ht = aphy->chan_is_ht; + sc->next_wiphy = aphy; + + __ath9k_wiphy_pause_all(sc); + now = !__ath9k_wiphy_pausing(aphy->sc); + spin_unlock_bh(&sc->wiphy_lock); + + if (now) { + /* Ready to request channel change immediately */ + queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work); + } + + /* + * wiphys will be unpaused in ath9k_tx_status() once channel has been + * changed if any wiphy needs time to become paused. + */ + + return 0; +} + +bool ath9k_wiphy_started(struct ath_softc *sc) +{ + int i; + spin_lock_bh(&sc->wiphy_lock); + if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { + spin_unlock_bh(&sc->wiphy_lock); + return true; + } + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] && + sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { + spin_unlock_bh(&sc->wiphy_lock); + return true; + } + } + spin_unlock_bh(&sc->wiphy_lock); + return false; +} + +static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, + struct ath_wiphy *selected) +{ + if (selected->state == ATH_WIPHY_SCAN) { + if (aphy == selected) + return; + /* + * Pause all other wiphys for the duration of the scan even if + * they are on the current channel now. + */ + } else if (aphy->chan_idx == selected->chan_idx) + return; + aphy->state = ATH_WIPHY_PAUSED; + ieee80211_stop_queues(aphy->hw); +} + +void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, + struct ath_wiphy *selected) +{ + int i; + spin_lock_bh(&sc->wiphy_lock); + if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) + ath9k_wiphy_pause_chan(sc->pri_wiphy, selected); + for (i = 0; i < sc->num_sec_wiphy; i++) { + if (sc->sec_wiphy[i] && + sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) + ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected); + } + spin_unlock_bh(&sc->wiphy_lock); +} + +void ath9k_wiphy_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + wiphy_work.work); + struct ath_wiphy *aphy = NULL; + bool first = true; + + spin_lock_bh(&sc->wiphy_lock); + + if (sc->wiphy_scheduler_int == 0) { + /* wiphy scheduler is disabled */ + spin_unlock_bh(&sc->wiphy_lock); + return; + } + +try_again: + sc->wiphy_scheduler_index++; + while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { + aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; + if (aphy && aphy->state != ATH_WIPHY_INACTIVE) + break; + + sc->wiphy_scheduler_index++; + aphy = NULL; + } + if (aphy == NULL) { + sc->wiphy_scheduler_index = 0; + if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { + if (first) { + first = false; + goto try_again; + } + /* No wiphy is ready to be scheduled */ + } else + aphy = sc->pri_wiphy; + } + + spin_unlock_bh(&sc->wiphy_lock); + + if (aphy && + aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && + ath9k_wiphy_select(aphy)) { + printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " + "change\n"); + } + + queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, + sc->wiphy_scheduler_int); +} + +void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) +{ + cancel_delayed_work_sync(&sc->wiphy_work); + sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); + if (sc->wiphy_scheduler_int) + queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, + sc->wiphy_scheduler_int); +} diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c new file mode 100644 index 000000000000..628b780d8844 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -0,0 +1,2171 @@ +/* + * 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 "ath9k.h" + +#define BITS_PER_BYTE 8 +#define OFDM_PLCP_BITS 22 +#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) +#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) +#define L_STF 8 +#define L_LTF 8 +#define L_SIG 4 +#define HT_SIG 8 +#define HT_STF 4 +#define HT_LTF(_ns) (4 * (_ns)) +#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */ +#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */ +#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) +#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) + +#define OFDM_SIFS_TIME 16 + +static u32 bits_per_symbol[][2] = { + /* 20MHz 40MHz */ + { 26, 54 }, /* 0: BPSK */ + { 52, 108 }, /* 1: QPSK 1/2 */ + { 78, 162 }, /* 2: QPSK 3/4 */ + { 104, 216 }, /* 3: 16-QAM 1/2 */ + { 156, 324 }, /* 4: 16-QAM 3/4 */ + { 208, 432 }, /* 5: 64-QAM 2/3 */ + { 234, 486 }, /* 6: 64-QAM 3/4 */ + { 260, 540 }, /* 7: 64-QAM 5/6 */ + { 52, 108 }, /* 8: BPSK */ + { 104, 216 }, /* 9: QPSK 1/2 */ + { 156, 324 }, /* 10: QPSK 3/4 */ + { 208, 432 }, /* 11: 16-QAM 1/2 */ + { 312, 648 }, /* 12: 16-QAM 3/4 */ + { 416, 864 }, /* 13: 64-QAM 2/3 */ + { 468, 972 }, /* 14: 64-QAM 3/4 */ + { 520, 1080 }, /* 15: 64-QAM 5/6 */ +}; + +#define IS_HT_RATE(_rate) ((_rate) & 0x80) + +static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head); +static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, + struct list_head *bf_q, + int txok, int sendbar); +static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, + struct list_head *head); +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); +static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, + int txok); +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, + int nbad, int txok, bool update_rc); + +/*********************/ +/* Aggregation logic */ +/*********************/ + +static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) +{ + struct ath_atx_tid *tid; + tid = ATH_AN_2_TID(an, tidno); + + if (tid->state & AGGR_ADDBA_COMPLETE || + tid->state & AGGR_ADDBA_PROGRESS) + return 1; + else + return 0; +} + +static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) +{ + struct ath_atx_ac *ac = tid->ac; + + if (tid->paused) + return; + + if (tid->sched) + return; + + tid->sched = true; + list_add_tail(&tid->list, &ac->tid_q); + + if (ac->sched) + return; + + ac->sched = true; + list_add_tail(&ac->list, &txq->axq_acq); +} + +static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) +{ + struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + + spin_lock_bh(&txq->axq_lock); + tid->paused++; + spin_unlock_bh(&txq->axq_lock); +} + +static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) +{ + struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + + ASSERT(tid->paused > 0); + spin_lock_bh(&txq->axq_lock); + + tid->paused--; + + if (tid->paused > 0) + goto unlock; + + if (list_empty(&tid->buf_q)) + goto unlock; + + ath_tx_queue_tid(txq, tid); + ath_txq_schedule(sc, txq); +unlock: + spin_unlock_bh(&txq->axq_lock); +} + +static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) +{ + struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_buf *bf; + struct list_head bf_head; + INIT_LIST_HEAD(&bf_head); + + ASSERT(tid->paused > 0); + spin_lock_bh(&txq->axq_lock); + + tid->paused--; + + if (tid->paused > 0) { + spin_unlock_bh(&txq->axq_lock); + return; + } + + while (!list_empty(&tid->buf_q)) { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + ASSERT(!bf_isretried(bf)); + list_move_tail(&bf->list, &bf_head); + ath_tx_send_ht_normal(sc, txq, tid, &bf_head); + } + + spin_unlock_bh(&txq->axq_lock); +} + +static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, + int seqno) +{ + int index, cindex; + + index = ATH_BA_INDEX(tid->seq_start, seqno); + cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); + + tid->tx_buf[cindex] = NULL; + + while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { + INCR(tid->seq_start, IEEE80211_SEQ_MAX); + INCR(tid->baw_head, ATH_TID_MAX_BUFS); + } +} + +static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, + struct ath_buf *bf) +{ + int index, cindex; + + if (bf_isretried(bf)) + return; + + index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); + cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); + + ASSERT(tid->tx_buf[cindex] == NULL); + tid->tx_buf[cindex] = bf; + + if (index >= ((tid->baw_tail - tid->baw_head) & + (ATH_TID_MAX_BUFS - 1))) { + tid->baw_tail = cindex; + INCR(tid->baw_tail, ATH_TID_MAX_BUFS); + } +} + +/* + * TODO: For frame(s) that are in the retry state, we will reuse the + * sequence number(s) without setting the retry bit. The + * alternative is to give up on these and BAR the receiver's window + * forward. + */ +static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) + +{ + struct ath_buf *bf; + struct list_head bf_head; + INIT_LIST_HEAD(&bf_head); + + for (;;) { + if (list_empty(&tid->buf_q)) + break; + + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); + + if (bf_isretried(bf)) + ath_tx_update_baw(sc, tid, bf->bf_seqno); + + spin_unlock(&txq->axq_lock); + ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); + spin_lock(&txq->axq_lock); + } + + tid->seq_next = tid->seq_start; + tid->baw_tail = tid->baw_head; +} + +static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) +{ + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + + bf->bf_state.bf_type |= BUF_RETRY; + bf->bf_retries++; + + skb = bf->bf_mpdu; + hdr = (struct ieee80211_hdr *)skb->data; + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); +} + +static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) +{ + struct ath_buf *tbf; + + spin_lock_bh(&sc->tx.txbuflock); + ASSERT(!list_empty((&sc->tx.txbuf))); + tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + list_del(&tbf->list); + spin_unlock_bh(&sc->tx.txbuflock); + + ATH_TXBUF_RESET(tbf); + + tbf->bf_mpdu = bf->bf_mpdu; + tbf->bf_buf_addr = bf->bf_buf_addr; + *(tbf->bf_desc) = *(bf->bf_desc); + tbf->bf_state = bf->bf_state; + tbf->bf_dmacontext = bf->bf_dmacontext; + + return tbf; +} + +static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_buf *bf, struct list_head *bf_q, + int txok) +{ + struct ath_node *an = NULL; + struct sk_buff *skb; + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; + struct ath_atx_tid *tid = NULL; + struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; + struct ath_desc *ds = bf_last->bf_desc; + struct list_head bf_head, bf_pending; + u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; + bool rc_update = true; + + skb = bf->bf_mpdu; + hdr = (struct ieee80211_hdr *)skb->data; + + rcu_read_lock(); + + sta = ieee80211_find_sta(sc->hw, hdr->addr1); + if (!sta) { + rcu_read_unlock(); + return; + } + + an = (struct ath_node *)sta->drv_priv; + tid = ATH_AN_2_TID(an, bf->bf_tidno); + + isaggr = bf_isaggr(bf); + memset(ba, 0, WME_BA_BMP_SIZE >> 3); + + if (isaggr && txok) { + if (ATH_DS_TX_BA(ds)) { + seq_st = ATH_DS_BA_SEQ(ds); + memcpy(ba, ATH_DS_BA_BITMAP(ds), + WME_BA_BMP_SIZE >> 3); + } else { + /* + * AR5416 can become deaf/mute when BA + * issue happens. Chip needs to be reset. + * But AP code may have sychronization issues + * when perform internal reset in this routine. + * Only enable reset in STA mode for now. + */ + if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) + needreset = 1; + } + } + + INIT_LIST_HEAD(&bf_pending); + INIT_LIST_HEAD(&bf_head); + + nbad = ath_tx_num_badfrms(sc, bf, txok); + while (bf) { + txfail = txpending = 0; + bf_next = bf->bf_next; + + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { + /* transmit completion, subframe is + * acked by block ack */ + acked_cnt++; + } else if (!isaggr && txok) { + /* transmit completion */ + acked_cnt++; + } else { + if (!(tid->state & AGGR_CLEANUP) && + ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { + if (bf->bf_retries < ATH_MAX_SW_RETRIES) { + ath_tx_set_retry(sc, bf); + txpending = 1; + } else { + bf->bf_state.bf_type |= BUF_XRETRY; + txfail = 1; + sendbar = 1; + txfail_cnt++; + } + } else { + /* + * cleanup in progress, just fail + * the un-acked sub-frames + */ + txfail = 1; + } + } + + if (bf_next == NULL) { + INIT_LIST_HEAD(&bf_head); + } else { + ASSERT(!list_empty(bf_q)); + list_move_tail(&bf->list, &bf_head); + } + + if (!txpending) { + /* + * complete the acked-ones/xretried ones; update + * block-ack window + */ + spin_lock_bh(&txq->axq_lock); + ath_tx_update_baw(sc, tid, bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); + + if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { + ath_tx_rc_status(bf, ds, nbad, txok, true); + rc_update = false; + } else { + ath_tx_rc_status(bf, ds, nbad, txok, false); + } + + ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); + } else { + /* retry the un-acked ones */ + if (bf->bf_next == NULL && bf_last->bf_stale) { + struct ath_buf *tbf; + + tbf = ath_clone_txbuf(sc, bf_last); + ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); + list_add_tail(&tbf->list, &bf_head); + } else { + /* + * Clear descriptor status words for + * software retry + */ + ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc); + } + + /* + * Put this buffer to the temporary pending + * queue to retain ordering + */ + list_splice_tail_init(&bf_head, &bf_pending); + } + + bf = bf_next; + } + + if (tid->state & AGGR_CLEANUP) { + if (tid->baw_head == tid->baw_tail) { + tid->state &= ~AGGR_ADDBA_COMPLETE; + tid->addba_exchangeattempts = 0; + tid->state &= ~AGGR_CLEANUP; + + /* send buffered frames as singles */ + ath_tx_flush_tid(sc, tid); + } + rcu_read_unlock(); + return; + } + + /* prepend un-acked frames to the beginning of the pending frame queue */ + if (!list_empty(&bf_pending)) { + spin_lock_bh(&txq->axq_lock); + list_splice(&bf_pending, &tid->buf_q); + ath_tx_queue_tid(txq, tid); + spin_unlock_bh(&txq->axq_lock); + } + + rcu_read_unlock(); + + if (needreset) + ath_reset(sc, false); +} + +static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, + struct ath_atx_tid *tid) +{ + struct ath_rate_table *rate_table = sc->cur_rate_table; + struct sk_buff *skb; + struct ieee80211_tx_info *tx_info; + struct ieee80211_tx_rate *rates; + struct ath_tx_info_priv *tx_info_priv; + u32 max_4ms_framelen, frmlen; + u16 aggr_limit, legacy = 0, maxampdu; + int i; + + skb = bf->bf_mpdu; + tx_info = IEEE80211_SKB_CB(skb); + rates = tx_info->control.rates; + tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; + + /* + * Find the lowest frame length among the rate series that will have a + * 4ms transmit duration. + * TODO - TXOP limit needs to be considered. + */ + max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; + + for (i = 0; i < 4; i++) { + if (rates[i].count) { + if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { + legacy = 1; + break; + } + + frmlen = rate_table->info[rates[i].idx].max_4ms_framelen; + max_4ms_framelen = min(max_4ms_framelen, frmlen); + } + } + + /* + * limit aggregate size by the minimum rate if rate selected is + * not a probe rate, if rate selected is a probe rate then + * avoid aggregation of this packet. + */ + if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) + return 0; + + aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT); + + /* + * h/w can accept aggregates upto 16 bit lengths (65535). + * The IE, however can hold upto 65536, which shows up here + * as zero. Ignore 65536 since we are constrained by hw. + */ + maxampdu = tid->an->maxampdu; + if (maxampdu) + aggr_limit = min(aggr_limit, maxampdu); + + return aggr_limit; +} + +/* + * Returns the number of delimiters to be added to + * meet the minimum required mpdudensity. + * caller should make sure that the rate is HT rate . + */ +static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, + struct ath_buf *bf, u16 frmlen) +{ + struct ath_rate_table *rt = sc->cur_rate_table; + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + u32 nsymbits, nsymbols, mpdudensity; + u16 minlen; + u8 rc, flags, rix; + int width, half_gi, ndelim, mindelim; + + /* Select standard number of delimiters based on frame length alone */ + ndelim = ATH_AGGR_GET_NDELIM(frmlen); + + /* + * If encryption enabled, hardware requires some more padding between + * subframes. + * TODO - this could be improved to be dependent on the rate. + * The hardware can keep up at lower rates, but not higher rates + */ + if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) + ndelim += ATH_AGGR_ENCRYPTDELIM; + + /* + * Convert desired mpdu density from microeconds to bytes based + * on highest rate in rate series (i.e. first rate) to determine + * required minimum length for subframe. Take into account + * whether high rate is 20 or 40Mhz and half or full GI. + */ + mpdudensity = tid->an->mpdudensity; + + /* + * If there is no mpdu density restriction, no further calculation + * is needed. + */ + if (mpdudensity == 0) + return ndelim; + + rix = tx_info->control.rates[0].idx; + flags = tx_info->control.rates[0].flags; + rc = rt->info[rix].ratecode; + width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; + half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; + + if (half_gi) + nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); + else + nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); + + if (nsymbols == 0) + nsymbols = 1; + + nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; + minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; + + if (frmlen < minlen) { + mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; + ndelim = max(mindelim, ndelim); + } + + return ndelim; +} + +static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, + struct ath_atx_tid *tid, + struct list_head *bf_q) +{ +#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) + struct ath_buf *bf, *bf_first, *bf_prev = NULL; + int rl = 0, nframes = 0, ndelim, prev_al = 0; + u16 aggr_limit = 0, al = 0, bpad = 0, + al_delta, h_baw = tid->baw_size / 2; + enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; + + bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); + + do { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + + /* do not step over block-ack window */ + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { + status = ATH_AGGR_BAW_CLOSED; + break; + } + + if (!rl) { + aggr_limit = ath_lookup_rate(sc, bf, tid); + rl = 1; + } + + /* do not exceed aggregation limit */ + al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; + + if (nframes && + (aggr_limit < (al + bpad + al_delta + prev_al))) { + status = ATH_AGGR_LIMITED; + break; + } + + /* do not exceed subframe limit */ + if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { + status = ATH_AGGR_LIMITED; + break; + } + nframes++; + + /* add padding for previous frame to aggregation length */ + al += bpad + al_delta; + + /* + * Get the delimiters needed to meet the MPDU + * density for this node. + */ + ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); + bpad = PADBYTES(al_delta) + (ndelim << 2); + + bf->bf_next = NULL; + bf->bf_desc->ds_link = 0; + + /* link buffers of this frame to the aggregate */ + ath_tx_addto_baw(sc, tid, bf); + ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); + list_move_tail(&bf->list, bf_q); + if (bf_prev) { + bf_prev->bf_next = bf; + bf_prev->bf_desc->ds_link = bf->bf_daddr; + } + bf_prev = bf; + } while (!list_empty(&tid->buf_q)); + + bf_first->bf_al = al; + bf_first->bf_nframes = nframes; + + return status; +#undef PADBYTES +} + +static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) +{ + struct ath_buf *bf; + enum ATH_AGGR_STATUS status; + struct list_head bf_q; + + do { + if (list_empty(&tid->buf_q)) + return; + + INIT_LIST_HEAD(&bf_q); + + status = ath_tx_form_aggr(sc, tid, &bf_q); + + /* + * no frames picked up to be aggregated; + * block-ack window is not open. + */ + if (list_empty(&bf_q)) + break; + + bf = list_first_entry(&bf_q, struct ath_buf, list); + bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); + + /* if only one frame, send as non-aggregate */ + if (bf->bf_nframes == 1) { + bf->bf_state.bf_type &= ~BUF_AGGR; + ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txq, &bf_q); + continue; + } + + /* setup first desc of aggregate */ + bf->bf_state.bf_type |= BUF_AGGR; + ath_buf_set_rate(sc, bf); + ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); + + /* anchor last desc of aggregate */ + ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); + + txq->axq_aggr_depth++; + ath_tx_txqaddbuf(sc, txq, &bf_q); + + } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && + status != ATH_AGGR_BAW_CLOSED); +} + +int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, + u16 tid, u16 *ssn) +{ + struct ath_atx_tid *txtid; + struct ath_node *an; + + an = (struct ath_node *)sta->drv_priv; + + if (sc->sc_flags & SC_OP_TXAGGR) { + txtid = ATH_AN_2_TID(an, tid); + txtid->state |= AGGR_ADDBA_PROGRESS; + ath_tx_pause_tid(sc, txtid); + *ssn = txtid->seq_start; + } + + return 0; +} + +int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) +{ + struct ath_node *an = (struct ath_node *)sta->drv_priv; + struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); + struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; + struct ath_buf *bf; + struct list_head bf_head; + INIT_LIST_HEAD(&bf_head); + + if (txtid->state & AGGR_CLEANUP) + return 0; + + if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { + txtid->addba_exchangeattempts = 0; + return 0; + } + + ath_tx_pause_tid(sc, txtid); + + /* drop all software retried frames and mark this TID */ + spin_lock_bh(&txq->axq_lock); + while (!list_empty(&txtid->buf_q)) { + bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); + if (!bf_isretried(bf)) { + /* + * NB: it's based on the assumption that + * software retried frame will always stay + * at the head of software queue. + */ + break; + } + list_move_tail(&bf->list, &bf_head); + ath_tx_update_baw(sc, txtid, bf->bf_seqno); + ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); + } + spin_unlock_bh(&txq->axq_lock); + + if (txtid->baw_head != txtid->baw_tail) { + txtid->state |= AGGR_CLEANUP; + } else { + txtid->state &= ~AGGR_ADDBA_COMPLETE; + txtid->addba_exchangeattempts = 0; + ath_tx_flush_tid(sc, txtid); + } + + return 0; +} + +void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) +{ + struct ath_atx_tid *txtid; + struct ath_node *an; + + an = (struct ath_node *)sta->drv_priv; + + if (sc->sc_flags & SC_OP_TXAGGR) { + txtid = ATH_AN_2_TID(an, tid); + txtid->baw_size = + IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; + txtid->state |= AGGR_ADDBA_COMPLETE; + txtid->state &= ~AGGR_ADDBA_PROGRESS; + ath_tx_resume_tid(sc, txtid); + } +} + +bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) +{ + struct ath_atx_tid *txtid; + + if (!(sc->sc_flags & SC_OP_TXAGGR)) + return false; + + txtid = ATH_AN_2_TID(an, tidno); + + if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { + if (!(txtid->state & AGGR_ADDBA_PROGRESS) && + (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) { + txtid->addba_exchangeattempts++; + return true; + } + } + + return false; +} + +/********************/ +/* Queue Management */ +/********************/ + +static void ath_txq_drain_pending_buffers(struct ath_softc *sc, + struct ath_txq *txq) +{ + struct ath_atx_ac *ac, *ac_tmp; + struct ath_atx_tid *tid, *tid_tmp; + + list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { + list_del(&ac->list); + ac->sched = false; + list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { + list_del(&tid->list); + tid->sched = false; + ath_tid_drain(sc, txq, tid); + } + } +} + +struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_tx_queue_info qi; + int qnum; + + memset(&qi, 0, sizeof(qi)); + qi.tqi_subtype = subtype; + qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; + qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; + qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; + qi.tqi_physCompBuf = 0; + + /* + * Enable interrupts only for EOL and DESC conditions. + * We mark tx descriptors to receive a DESC interrupt + * when a tx queue gets deep; otherwise waiting for the + * EOL to reap descriptors. Note that this is done to + * reduce interrupt load and this only defers reaping + * descriptors, never transmitting frames. Aside from + * reducing interrupts this also permits more concurrency. + * The only potential downside is if the tx queue backs + * up in which case the top half of the kernel may backup + * due to a lack of tx descriptors. + * + * The UAPSD queue is an exception, since we take a desc- + * based intr on the EOSP frames. + */ + if (qtype == ATH9K_TX_QUEUE_UAPSD) + qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; + else + qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | + TXQ_FLAG_TXDESCINT_ENABLE; + qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); + if (qnum == -1) { + /* + * NB: don't print a message, this happens + * normally on parts with too few tx queues + */ + return NULL; + } + if (qnum >= ARRAY_SIZE(sc->tx.txq)) { + DPRINTF(sc, ATH_DBG_FATAL, + "qnum %u out of range, max %u!\n", + qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); + ath9k_hw_releasetxqueue(ah, qnum); + return NULL; + } + if (!ATH_TXQ_SETUP(sc, qnum)) { + struct ath_txq *txq = &sc->tx.txq[qnum]; + + txq->axq_qnum = qnum; + txq->axq_link = NULL; + INIT_LIST_HEAD(&txq->axq_q); + INIT_LIST_HEAD(&txq->axq_acq); + spin_lock_init(&txq->axq_lock); + txq->axq_depth = 0; + txq->axq_aggr_depth = 0; + txq->axq_totalqueued = 0; + txq->axq_linkbuf = NULL; + sc->tx.txqsetup |= 1<tx.txq[qnum]; +} + +static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) +{ + int qnum; + + switch (qtype) { + case ATH9K_TX_QUEUE_DATA: + if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { + DPRINTF(sc, ATH_DBG_FATAL, + "HAL AC %u out of range, max %zu!\n", + haltype, ARRAY_SIZE(sc->tx.hwq_map)); + return -1; + } + qnum = sc->tx.hwq_map[haltype]; + break; + case ATH9K_TX_QUEUE_BEACON: + qnum = sc->beacon.beaconq; + break; + case ATH9K_TX_QUEUE_CAB: + qnum = sc->beacon.cabq->axq_qnum; + break; + default: + qnum = -1; + } + return qnum; +} + +struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) +{ + struct ath_txq *txq = NULL; + int qnum; + + qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); + txq = &sc->tx.txq[qnum]; + + spin_lock_bh(&txq->axq_lock); + + if (txq->axq_depth >= (ATH_TXBUF - 20)) { + DPRINTF(sc, ATH_DBG_XMIT, + "TX queue: %d is full, depth: %d\n", + qnum, txq->axq_depth); + ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); + txq->stopped = 1; + spin_unlock_bh(&txq->axq_lock); + return NULL; + } + + spin_unlock_bh(&txq->axq_lock); + + return txq; +} + +int ath_txq_update(struct ath_softc *sc, int qnum, + struct ath9k_tx_queue_info *qinfo) +{ + struct ath_hw *ah = sc->sc_ah; + int error = 0; + struct ath9k_tx_queue_info qi; + + if (qnum == sc->beacon.beaconq) { + /* + * XXX: for beacon queue, we just save the parameter. + * It will be picked up by ath_beaconq_config when + * it's necessary. + */ + sc->beacon.beacon_qi = *qinfo; + return 0; + } + + ASSERT(sc->tx.txq[qnum].axq_qnum == qnum); + + ath9k_hw_get_txq_props(ah, qnum, &qi); + qi.tqi_aifs = qinfo->tqi_aifs; + qi.tqi_cwmin = qinfo->tqi_cwmin; + qi.tqi_cwmax = qinfo->tqi_cwmax; + qi.tqi_burstTime = qinfo->tqi_burstTime; + qi.tqi_readyTime = qinfo->tqi_readyTime; + + if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to update hardware queue %u!\n", qnum); + error = -EIO; + } else { + ath9k_hw_resettxqueue(ah, qnum); + } + + return error; +} + +int ath_cabq_update(struct ath_softc *sc) +{ + struct ath9k_tx_queue_info qi; + int qnum = sc->beacon.cabq->axq_qnum; + + ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); + /* + * Ensure the readytime % is within the bounds. + */ + if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) + sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; + else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) + sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; + + qi.tqi_readyTime = (sc->hw->conf.beacon_int * + sc->config.cabqReadytime) / 100; + ath_txq_update(sc, qnum, &qi); + + return 0; +} + +/* + * Drain a given TX queue (could be Beacon or Data) + * + * This assumes output has been stopped and + * we do not need to block ath_tx_tasklet. + */ +void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) +{ + struct ath_buf *bf, *lastbf; + struct list_head bf_head; + + INIT_LIST_HEAD(&bf_head); + + for (;;) { + spin_lock_bh(&txq->axq_lock); + + if (list_empty(&txq->axq_q)) { + txq->axq_link = NULL; + txq->axq_linkbuf = NULL; + spin_unlock_bh(&txq->axq_lock); + break; + } + + bf = list_first_entry(&txq->axq_q, struct ath_buf, list); + + if (bf->bf_stale) { + list_del(&bf->list); + spin_unlock_bh(&txq->axq_lock); + + spin_lock_bh(&sc->tx.txbuflock); + list_add_tail(&bf->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + continue; + } + + lastbf = bf->bf_lastbf; + if (!retry_tx) + lastbf->bf_desc->ds_txstat.ts_flags = + ATH9K_TX_SW_ABORTED; + + /* remove ath_buf's of the same mpdu from txq */ + list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); + txq->axq_depth--; + + spin_unlock_bh(&txq->axq_lock); + + if (bf_isampdu(bf)) + ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); + else + ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); + } + + /* flush any pending frames if aggregation is enabled */ + if (sc->sc_flags & SC_OP_TXAGGR) { + if (!retry_tx) { + spin_lock_bh(&txq->axq_lock); + ath_txq_drain_pending_buffers(sc, txq); + spin_unlock_bh(&txq->axq_lock); + } + } +} + +void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_txq *txq; + int i, npend = 0; + + if (sc->sc_flags & SC_OP_INVALID) + return; + + /* Stop beacon queue */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + + /* Stop data queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) { + txq = &sc->tx.txq[i]; + ath9k_hw_stoptxdma(ah, txq->axq_qnum); + npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); + } + } + + if (npend) { + int r; + + DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); + + spin_lock_bh(&sc->sc_resetlock); + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); + if (r) + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to reset hardware; reset status %u\n", + r); + spin_unlock_bh(&sc->sc_resetlock); + } + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) + ath_draintxq(sc, &sc->tx.txq[i], retry_tx); + } +} + +void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) +{ + ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); + sc->tx.txqsetup &= ~(1<axq_qnum); +} + +void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) +{ + struct ath_atx_ac *ac; + struct ath_atx_tid *tid; + + if (list_empty(&txq->axq_acq)) + return; + + ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); + list_del(&ac->list); + ac->sched = false; + + do { + if (list_empty(&ac->tid_q)) + return; + + tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); + list_del(&tid->list); + tid->sched = false; + + if (tid->paused) + continue; + + if ((txq->axq_depth % 2) == 0) + ath_tx_sched_aggr(sc, txq, tid); + + /* + * add tid to round-robin queue if more frames + * are pending for the tid + */ + if (!list_empty(&tid->buf_q)) + ath_tx_queue_tid(txq, tid); + + break; + } while (!list_empty(&ac->tid_q)); + + if (!list_empty(&ac->tid_q)) { + if (!ac->sched) { + ac->sched = true; + list_add_tail(&ac->list, &txq->axq_acq); + } + } +} + +int ath_tx_setup(struct ath_softc *sc, int haltype) +{ + struct ath_txq *txq; + + if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { + DPRINTF(sc, ATH_DBG_FATAL, + "HAL AC %u out of range, max %zu!\n", + haltype, ARRAY_SIZE(sc->tx.hwq_map)); + return 0; + } + txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); + if (txq != NULL) { + sc->tx.hwq_map[haltype] = txq->axq_qnum; + return 1; + } else + return 0; +} + +/***********/ +/* TX, DMA */ +/***********/ + +/* + * Insert a chain of ath_buf (descriptors) on a txq and + * assume the descriptors are already chained together by caller. + */ +static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, + struct list_head *head) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_buf *bf; + + /* + * Insert the frame on the outbound list and + * pass it on to the hardware. + */ + + if (list_empty(head)) + return; + + bf = list_first_entry(head, struct ath_buf, list); + + list_splice_tail_init(head, &txq->axq_q); + txq->axq_depth++; + txq->axq_totalqueued++; + txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); + + DPRINTF(sc, ATH_DBG_QUEUE, + "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); + + if (txq->axq_link == NULL) { + ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); + DPRINTF(sc, ATH_DBG_XMIT, + "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); + } else { + *txq->axq_link = bf->bf_daddr; + DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", + txq->axq_qnum, txq->axq_link, + ito64(bf->bf_daddr), bf->bf_desc); + } + txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); + ath9k_hw_txstart(ah, txq->axq_qnum); +} + +static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) +{ + struct ath_buf *bf = NULL; + + spin_lock_bh(&sc->tx.txbuflock); + + if (unlikely(list_empty(&sc->tx.txbuf))) { + spin_unlock_bh(&sc->tx.txbuflock); + return NULL; + } + + bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + list_del(&bf->list); + + spin_unlock_bh(&sc->tx.txbuflock); + + return bf; +} + +static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, + struct list_head *bf_head, + struct ath_tx_control *txctl) +{ + struct ath_buf *bf; + + bf = list_first_entry(bf_head, struct ath_buf, list); + bf->bf_state.bf_type |= BUF_AMPDU; + + /* + * Do not queue to h/w when any of the following conditions is true: + * - there are pending frames in software queue + * - the TID is currently paused for ADDBA/BAR request + * - seqno is not within block-ack window + * - h/w queue depth exceeds low water mark + */ + if (!list_empty(&tid->buf_q) || tid->paused || + !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || + txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { + /* + * Add this frame to software queue for scheduling later + * for aggregation. + */ + list_move_tail(&bf->list, &tid->buf_q); + ath_tx_queue_tid(txctl->txq, tid); + return; + } + + /* Add sub-frame to BAW */ + ath_tx_addto_baw(sc, tid, bf); + + /* Queue to h/w without aggregation */ + bf->bf_nframes = 1; + bf->bf_lastbf = bf; + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txctl->txq, bf_head); +} + +static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head) +{ + struct ath_buf *bf; + + bf = list_first_entry(bf_head, struct ath_buf, list); + bf->bf_state.bf_type &= ~BUF_AMPDU; + + /* update starting sequence number for subsequent ADDBA request */ + INCR(tid->seq_start, IEEE80211_SEQ_MAX); + + bf->bf_nframes = 1; + bf->bf_lastbf = bf; + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txq, bf_head); +} + +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct list_head *bf_head) +{ + struct ath_buf *bf; + + bf = list_first_entry(bf_head, struct ath_buf, list); + + bf->bf_lastbf = bf; + bf->bf_nframes = 1; + ath_buf_set_rate(sc, bf); + ath_tx_txqaddbuf(sc, txq, bf_head); +} + +static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + enum ath9k_pkt_type htype; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_beacon(fc)) + htype = ATH9K_PKT_TYPE_BEACON; + else if (ieee80211_is_probe_resp(fc)) + htype = ATH9K_PKT_TYPE_PROBE_RESP; + else if (ieee80211_is_atim(fc)) + htype = ATH9K_PKT_TYPE_ATIM; + else if (ieee80211_is_pspoll(fc)) + htype = ATH9K_PKT_TYPE_PSPOLL; + else + htype = ATH9K_PKT_TYPE_NORMAL; + + return htype; +} + +static bool is_pae(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_data(fc)) { + if (ieee80211_is_nullfunc(fc) || + /* Port Access Entity (IEEE 802.1X) */ + (skb->protocol == cpu_to_be16(ETH_P_PAE))) { + return true; + } + } + + return false; +} + +static int get_hw_crypto_keytype(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + + if (tx_info->control.hw_key) { + if (tx_info->control.hw_key->alg == ALG_WEP) + return ATH9K_KEY_TYPE_WEP; + else if (tx_info->control.hw_key->alg == ALG_TKIP) + return ATH9K_KEY_TYPE_TKIP; + else if (tx_info->control.hw_key->alg == ALG_CCMP) + return ATH9K_KEY_TYPE_AES; + } + + return ATH9K_KEY_TYPE_CLEAR; +} + +static void assign_aggr_tid_seqno(struct sk_buff *skb, + struct ath_buf *bf) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; + struct ath_node *an; + struct ath_atx_tid *tid; + __le16 fc; + u8 *qc; + + if (!tx_info->control.sta) + return; + + an = (struct ath_node *)tx_info->control.sta->drv_priv; + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); + bf->bf_tidno = qc[0] & 0xf; + } + + /* + * For HT capable stations, we save tidno for later use. + * We also override seqno set by upper layer with the one + * in tx aggregation state. + * + * If fragmentation is on, the sequence number is + * not overridden, since it has been + * incremented by the fragmentation routine. + * + * FIXME: check if the fragmentation threshold exceeds + * IEEE80211 max. + */ + tid = ATH_AN_2_TID(an, bf->bf_tidno); + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << + IEEE80211_SEQ_SEQ_SHIFT); + bf->bf_seqno = tid->seq_next; + INCR(tid->seq_next, IEEE80211_SEQ_MAX); +} + +static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, + struct ath_txq *txq) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + int flags = 0; + + flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ + flags |= ATH9K_TXDESC_INTREQ; + + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) + flags |= ATH9K_TXDESC_NOACK; + + return flags; +} + +/* + * rix - rate index + * pktlen - total bytes (delims + data + fcs + pads + pad delims) + * width - 0 for 20 MHz, 1 for 40 MHz + * half_gi - to use 4us v/s 3.6 us for symbol time + */ +static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, + int width, int half_gi, bool shortPreamble) +{ + struct ath_rate_table *rate_table = sc->cur_rate_table; + u32 nbits, nsymbits, duration, nsymbols; + u8 rc; + int streams, pktlen; + + pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; + rc = rate_table->info[rix].ratecode; + + /* for legacy rates, use old function to compute packet duration */ + if (!IS_HT_RATE(rc)) + return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, + rix, shortPreamble); + + /* find number of symbols: PLCP + data */ + nbits = (pktlen << 3) + OFDM_PLCP_BITS; + nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; + nsymbols = (nbits + nsymbits - 1) / nsymbits; + + if (!half_gi) + duration = SYMBOL_TIME(nsymbols); + else + duration = SYMBOL_TIME_HALFGI(nsymbols); + + /* addup duration for legacy/ht training and signal fields */ + streams = HT_RC_2_STREAMS(rc); + duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); + + return duration; +} + +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) +{ + struct ath_rate_table *rt = sc->cur_rate_table; + struct ath9k_11n_rate_series series[4]; + struct sk_buff *skb; + struct ieee80211_tx_info *tx_info; + struct ieee80211_tx_rate *rates; + struct ieee80211_hdr *hdr; + int i, flags = 0; + u8 rix = 0, ctsrate = 0; + bool is_pspoll; + + memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); + + skb = bf->bf_mpdu; + tx_info = IEEE80211_SKB_CB(skb); + rates = tx_info->control.rates; + hdr = (struct ieee80211_hdr *)skb->data; + is_pspoll = ieee80211_is_pspoll(hdr->frame_control); + + /* + * We check if Short Preamble is needed for the CTS rate by + * checking the BSS's global flag. + * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. + */ + if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) + ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode | + rt->info[tx_info->control.rts_cts_rate_idx].short_preamble; + else + ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode; + + /* + * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. + * Check the first rate in the series to decide whether RTS/CTS + * or CTS-to-self has to be used. + */ + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) + flags = ATH9K_TXDESC_CTSENA; + else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) + flags = ATH9K_TXDESC_RTSENA; + + /* FIXME: Handle aggregation protection */ + if (sc->config.ath_aggr_prot && + (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { + flags = ATH9K_TXDESC_RTSENA; + } + + /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ + if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) + flags &= ~(ATH9K_TXDESC_RTSENA); + + for (i = 0; i < 4; i++) { + if (!rates[i].count || (rates[i].idx < 0)) + continue; + + rix = rates[i].idx; + series[i].Tries = rates[i].count; + series[i].ChSel = sc->tx_chainmask; + + if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + series[i].Rate = rt->info[rix].ratecode | + rt->info[rix].short_preamble; + else + series[i].Rate = rt->info[rix].ratecode; + + if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) + series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; + if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + series[i].RateFlags |= ATH9K_RATESERIES_2040; + if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) + series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; + + series[i].PktDuration = ath_pkt_duration(sc, rix, bf, + (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, + (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), + (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)); + } + + /* set dur_update_en for l-sig computation except for PS-Poll frames */ + ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, + bf->bf_lastbf->bf_desc, + !is_pspoll, ctsrate, + 0, series, 4, flags); + + if (sc->config.ath_aggr_prot && flags) + ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); +} + +static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, + struct sk_buff *skb, + struct ath_tx_control *txctl) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ath_tx_info_priv *tx_info_priv; + int hdrlen; + __le16 fc; + + tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); + if (unlikely(!tx_info_priv)) + return -ENOMEM; + tx_info->rate_driver_data[0] = tx_info_priv; + tx_info_priv->aphy = aphy; + tx_info_priv->frame_type = txctl->frame_type; + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + fc = hdr->frame_control; + + ATH_TXBUF_RESET(bf); + + bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); + + if (conf_is_ht(&sc->hw->conf) && !is_pae(skb)) + bf->bf_state.bf_type |= BUF_HT; + + bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); + + bf->bf_keytype = get_hw_crypto_keytype(skb); + if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { + bf->bf_frmlen += tx_info->control.hw_key->icv_len; + bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; + } else { + bf->bf_keyix = ATH9K_TXKEYIX_INVALID; + } + + if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) + assign_aggr_tid_seqno(skb, bf); + + bf->bf_mpdu = skb; + + bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { + bf->bf_mpdu = NULL; + DPRINTF(sc, ATH_DBG_CONFIG, + "dma_mapping_error() on TX\n"); + return -ENOMEM; + } + + bf->bf_buf_addr = bf->bf_dmacontext; + return 0; +} + +/* FIXME: tx power */ +static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_control *txctl) +{ + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ath_node *an = NULL; + struct list_head bf_head; + struct ath_desc *ds; + struct ath_atx_tid *tid; + struct ath_hw *ah = sc->sc_ah; + int frm_type; + __le16 fc; + + frm_type = get_hw_packet_type(skb); + fc = hdr->frame_control; + + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); + + ds = bf->bf_desc; + ds->ds_link = 0; + ds->ds_data = bf->bf_buf_addr; + + ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, + bf->bf_keyix, bf->bf_keytype, bf->bf_flags); + + ath9k_hw_filltxdesc(ah, ds, + skb->len, /* segment length */ + true, /* first segment */ + true, /* last segment */ + ds); /* first descriptor */ + + spin_lock_bh(&txctl->txq->axq_lock); + + if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && + tx_info->control.sta) { + an = (struct ath_node *)tx_info->control.sta->drv_priv; + tid = ATH_AN_2_TID(an, bf->bf_tidno); + + if (!ieee80211_is_data_qos(fc)) { + ath_tx_send_normal(sc, txctl->txq, &bf_head); + goto tx_done; + } + + if (ath_aggr_query(sc, an, bf->bf_tidno)) { + /* + * Try aggregation if it's a unicast data frame + * and the destination is HT capable. + */ + ath_tx_send_ampdu(sc, tid, &bf_head, txctl); + } else { + /* + * Send this frame as regular when ADDBA + * exchange is neither complete nor pending. + */ + ath_tx_send_ht_normal(sc, txctl->txq, + tid, &bf_head); + } + } else { + ath_tx_send_normal(sc, txctl->txq, &bf_head); + } + +tx_done: + spin_unlock_bh(&txctl->txq->axq_lock); +} + +/* Upon failure caller should free skb */ +int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath_tx_control *txctl) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_buf *bf; + int r; + + bf = ath_tx_get_buffer(sc); + if (!bf) { + DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n"); + return -1; + } + + r = ath_tx_setup_buffer(hw, bf, skb, txctl); + if (unlikely(r)) { + struct ath_txq *txq = txctl->txq; + + DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n"); + + /* upon ath_tx_processq() this TX queue will be resumed, we + * guarantee this will happen by knowing beforehand that + * we will at least have to run TX completionon one buffer + * on the queue */ + spin_lock_bh(&txq->axq_lock); + if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { + ieee80211_stop_queue(sc->hw, + skb_get_queue_mapping(skb)); + txq->stopped = 1; + } + spin_unlock_bh(&txq->axq_lock); + + spin_lock_bh(&sc->tx.txbuflock); + list_add_tail(&bf->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + + return r; + } + + ath_tx_start_dma(sc, bf, txctl); + + return 0; +} + +void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + int hdrlen, padsize; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath_tx_control txctl; + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + + /* + * As a temporary workaround, assign seq# here; this will likely need + * to be cleaned up to work better with Beacon transmission and virtual + * BSSes. + */ + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + sc->tx.seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); + } + + /* Add the padding after the header if this is not already done */ + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + if (hdrlen & 3) { + padsize = hdrlen % 4; + if (skb_headroom(skb) < padsize) { + DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n"); + dev_kfree_skb_any(skb); + return; + } + skb_push(skb, padsize); + memmove(skb->data, skb->data + padsize, hdrlen); + } + + txctl.txq = sc->beacon.cabq; + + DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); + + if (ath_tx_start(hw, skb, &txctl) != 0) { + DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); + goto exit; + } + + return; +exit: + dev_kfree_skb_any(skb); +} + +/*****************/ +/* TX Completion */ +/*****************/ + +static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, + int tx_flags) +{ + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + int hdrlen, padsize; + int frame_type = ATH9K_NOT_INTERNAL; + + DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); + + if (tx_info_priv) { + hw = tx_info_priv->aphy->hw; + frame_type = tx_info_priv->frame_type; + } + + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || + tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { + kfree(tx_info_priv); + tx_info->rate_driver_data[0] = NULL; + } + + if (tx_flags & ATH_TX_BAR) + tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + + if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { + /* Frame was ACKed */ + tx_info->flags |= IEEE80211_TX_STAT_ACK; + } + + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + padsize = hdrlen & 3; + if (padsize && hdrlen >= 24) { + /* + * Remove MAC header padding before giving the frame back to + * mac80211. + */ + memmove(skb->data + padsize, skb->data, hdrlen); + skb_pull(skb, padsize); + } + + if (frame_type == ATH9K_NOT_INTERNAL) + ieee80211_tx_status(hw, skb); + else + ath9k_tx_status(hw, skb); +} + +static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, + struct list_head *bf_q, + int txok, int sendbar) +{ + struct sk_buff *skb = bf->bf_mpdu; + unsigned long flags; + int tx_flags = 0; + + + if (sendbar) + tx_flags = ATH_TX_BAR; + + if (!txok) { + tx_flags |= ATH_TX_ERROR; + + if (bf_isxretried(bf)) + tx_flags |= ATH_TX_XRETRY; + } + + dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); + ath_tx_complete(sc, skb, tx_flags); + + /* + * Return the list of ath_buf of this mpdu to free queue + */ + spin_lock_irqsave(&sc->tx.txbuflock, flags); + list_splice_tail_init(bf_q, &sc->tx.txbuf); + spin_unlock_irqrestore(&sc->tx.txbuflock, flags); +} + +static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, + int txok) +{ + struct ath_buf *bf_last = bf->bf_lastbf; + struct ath_desc *ds = bf_last->bf_desc; + u16 seq_st = 0; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int ba_index; + int nbad = 0; + int isaggr = 0; + + if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) + return 0; + + isaggr = bf_isaggr(bf); + if (isaggr) { + seq_st = ATH_DS_BA_SEQ(ds); + memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); + } + + while (bf) { + ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); + if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) + nbad++; + + bf = bf->bf_next; + } + + return nbad; +} + +static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, + int nbad, int txok, bool update_rc) +{ + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); + struct ieee80211_hw *hw = tx_info_priv->aphy->hw; + u8 i, tx_rateindex; + + if (txok) + tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; + + tx_rateindex = ds->ds_txstat.ts_rateindex; + WARN_ON(tx_rateindex >= hw->max_rates); + + tx_info_priv->update_rc = update_rc; + if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) + tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; + + if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && + (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { + if (ieee80211_is_data(hdr->frame_control)) { + memcpy(&tx_info_priv->tx, &ds->ds_txstat, + sizeof(tx_info_priv->tx)); + tx_info_priv->n_frames = bf->bf_nframes; + tx_info_priv->n_bad_frames = nbad; + } + } + + for (i = tx_rateindex + 1; i < hw->max_rates; i++) + tx_info->status.rates[i].count = 0; + + tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; +} + +static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) +{ + int qnum; + + spin_lock_bh(&txq->axq_lock); + if (txq->stopped && + sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) { + qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); + if (qnum != -1) { + ieee80211_wake_queue(sc->hw, qnum); + txq->stopped = 0; + } + } + spin_unlock_bh(&txq->axq_lock); +} + +static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_buf *bf, *lastbf, *bf_held = NULL; + struct list_head bf_head; + struct ath_desc *ds; + int txok; + int status; + + DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", + txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), + txq->axq_link); + + for (;;) { + spin_lock_bh(&txq->axq_lock); + if (list_empty(&txq->axq_q)) { + txq->axq_link = NULL; + txq->axq_linkbuf = NULL; + spin_unlock_bh(&txq->axq_lock); + break; + } + bf = list_first_entry(&txq->axq_q, struct ath_buf, list); + + /* + * There is a race condition that a BH gets scheduled + * after sw writes TxE and before hw re-load the last + * descriptor to get the newly chained one. + * Software must keep the last DONE descriptor as a + * holding descriptor - software does so by marking + * it with the STALE flag. + */ + bf_held = NULL; + if (bf->bf_stale) { + bf_held = bf; + if (list_is_last(&bf_held->list, &txq->axq_q)) { + txq->axq_link = NULL; + txq->axq_linkbuf = NULL; + spin_unlock_bh(&txq->axq_lock); + + /* + * The holding descriptor is the last + * descriptor in queue. It's safe to remove + * the last holding descriptor in BH context. + */ + spin_lock_bh(&sc->tx.txbuflock); + list_move_tail(&bf_held->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + + break; + } else { + bf = list_entry(bf_held->list.next, + struct ath_buf, list); + } + } + + lastbf = bf->bf_lastbf; + ds = lastbf->bf_desc; + + status = ath9k_hw_txprocdesc(ah, ds); + if (status == -EINPROGRESS) { + spin_unlock_bh(&txq->axq_lock); + break; + } + if (bf->bf_desc == txq->axq_lastdsWithCTS) + txq->axq_lastdsWithCTS = NULL; + if (ds == txq->axq_gatingds) + txq->axq_gatingds = NULL; + + /* + * Remove ath_buf's of the same transmit unit from txq, + * however leave the last descriptor back as the holding + * descriptor for hw. + */ + lastbf->bf_stale = true; + INIT_LIST_HEAD(&bf_head); + if (!list_is_singular(&lastbf->list)) + list_cut_position(&bf_head, + &txq->axq_q, lastbf->list.prev); + + txq->axq_depth--; + if (bf_isaggr(bf)) + txq->axq_aggr_depth--; + + txok = (ds->ds_txstat.ts_status == 0); + spin_unlock_bh(&txq->axq_lock); + + if (bf_held) { + spin_lock_bh(&sc->tx.txbuflock); + list_move_tail(&bf_held->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + } + + if (!bf_isampdu(bf)) { + /* + * This frame is sent out as a single frame. + * Use hardware retry status for this frame. + */ + bf->bf_retries = ds->ds_txstat.ts_longretry; + if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) + bf->bf_state.bf_type |= BUF_XRETRY; + ath_tx_rc_status(bf, ds, 0, txok, true); + } + + if (bf_isampdu(bf)) + ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); + else + ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); + + ath_wake_mac80211_queue(sc, txq); + + spin_lock_bh(&txq->axq_lock); + if (sc->sc_flags & SC_OP_TXAGGR) + ath_txq_schedule(sc, txq); + spin_unlock_bh(&txq->axq_lock); + } +} + + +void ath_tx_tasklet(struct ath_softc *sc) +{ + int i; + u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); + + ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) + ath_tx_processq(sc, &sc->tx.txq[i]); + } +} + +/*****************/ +/* Init, Cleanup */ +/*****************/ + +int ath_tx_init(struct ath_softc *sc, int nbufs) +{ + int error = 0; + + spin_lock_init(&sc->tx.txbuflock); + + error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, + "tx", nbufs, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate tx descriptors: %d\n", error); + goto err; + } + + error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, + "beacon", ATH_BCBUF, 1); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to allocate beacon descriptors: %d\n", error); + goto err; + } + +err: + if (error != 0) + ath_tx_cleanup(sc); + + return error; +} + +void ath_tx_cleanup(struct ath_softc *sc) +{ + if (sc->beacon.bdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); + + if (sc->tx.txdma.dd_desc_len != 0) + ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); +} + +void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) +{ + struct ath_atx_tid *tid; + struct ath_atx_ac *ac; + int tidno, acno; + + for (tidno = 0, tid = &an->tid[tidno]; + tidno < WME_NUM_TID; + tidno++, tid++) { + tid->an = an; + tid->tidno = tidno; + tid->seq_start = tid->seq_next = 0; + tid->baw_size = WME_MAX_BA; + tid->baw_head = tid->baw_tail = 0; + tid->sched = false; + tid->paused = false; + tid->state &= ~AGGR_CLEANUP; + INIT_LIST_HEAD(&tid->buf_q); + acno = TID_TO_WME_AC(tidno); + tid->ac = &an->ac[acno]; + tid->state &= ~AGGR_ADDBA_COMPLETE; + tid->state &= ~AGGR_ADDBA_PROGRESS; + tid->addba_exchangeattempts = 0; + } + + for (acno = 0, ac = &an->ac[acno]; + acno < WME_NUM_AC; acno++, ac++) { + ac->sched = false; + INIT_LIST_HEAD(&ac->tid_q); + + switch (acno) { + case WME_AC_BE: + ac->qnum = ath_tx_get_qnum(sc, + ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); + break; + case WME_AC_BK: + ac->qnum = ath_tx_get_qnum(sc, + ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); + break; + case WME_AC_VI: + ac->qnum = ath_tx_get_qnum(sc, + ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); + break; + case WME_AC_VO: + ac->qnum = ath_tx_get_qnum(sc, + ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); + break; + } + } +} + +void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) +{ + int i; + struct ath_atx_ac *ac, *ac_tmp; + struct ath_atx_tid *tid, *tid_tmp; + struct ath_txq *txq; + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) { + txq = &sc->tx.txq[i]; + + spin_lock(&txq->axq_lock); + + list_for_each_entry_safe(ac, + ac_tmp, &txq->axq_acq, list) { + tid = list_first_entry(&ac->tid_q, + struct ath_atx_tid, list); + if (tid && tid->an != an) + continue; + list_del(&ac->list); + ac->sched = false; + + list_for_each_entry_safe(tid, + tid_tmp, &ac->tid_q, list) { + list_del(&tid->list); + tid->sched = false; + ath_tid_drain(sc, txq, tid); + tid->state &= ~AGGR_ADDBA_COMPLETE; + tid->addba_exchangeattempts = 0; + tid->state &= ~AGGR_CLEANUP; + } + } + + spin_unlock(&txq->axq_lock); + } + } +} diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig deleted file mode 100644 index 509b6f94f73b..000000000000 --- a/drivers/net/wireless/ath5k/Kconfig +++ /dev/null @@ -1,41 +0,0 @@ -config ATH5K - tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL - select ATH_COMMON - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS - ---help--- - This module adds support for wireless adapters based on - Atheros 5xxx chipset. - - Currently the following chip versions are supported: - - MAC: AR5211 AR5212 - PHY: RF5111/2111 RF5112/2112 RF5413/2413 - - This driver uses the kernel's mac80211 subsystem. - - If you choose to build a module, it'll be called ath5k. Say M if - unsure. - -config ATH5K_DEBUG - bool "Atheros 5xxx debugging" - depends on ATH5K - ---help--- - Atheros 5xxx debugging messages. - - Say Y, if and you will get debug options for ath5k. - To use this, you need to mount debugfs: - - mkdir /debug/ - mount -t debugfs debug /debug/ - - You will get access to files under: - /debug/ath5k/phy0/ - - To enable debug, pass the debug level to the debug module - parameter. For example: - - modprobe ath5k debug=0x00000400 - diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile deleted file mode 100644 index 84a74c5248e5..000000000000 --- a/drivers/net/wireless/ath5k/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -ath5k-y += caps.o -ath5k-y += initvals.o -ath5k-y += eeprom.o -ath5k-y += gpio.o -ath5k-y += desc.o -ath5k-y += dma.o -ath5k-y += qcu.o -ath5k-y += pcu.o -ath5k-y += phy.o -ath5k-y += reset.o -ath5k-y += attach.o -ath5k-y += base.o -ath5k-y += led.o -ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o -obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h deleted file mode 100644 index 48c18d11c507..000000000000 --- a/drivers/net/wireless/ath5k/ath5k.h +++ /dev/null @@ -1,1354 +0,0 @@ -/* - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2007 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _ATH5K_H -#define _ATH5K_H - -/* TODO: Clean up channel debuging -doesn't work anyway- and start - * working on reg. control code using all available eeprom information - * -rev. engineering needed- */ -#define CHAN_DEBUG 0 - -#include -#include -#include - -#include "../ath/regd.h" - -/* RX/TX descriptor hw structs - * TODO: Driver part should only see sw structs */ -#include "desc.h" - -/* EEPROM structs/offsets - * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) - * and clean up common bits, then introduce set/get functions in eeprom.c */ -#include "eeprom.h" - -/* PCI IDs */ -#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ -#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */ -#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */ -#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */ -#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */ -#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */ -#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */ -#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */ -#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */ -#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */ -#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */ -#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */ - -/****************************\ - GENERIC DRIVER DEFINITIONS -\****************************/ - -#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__) - -#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \ - printk(_level "ath5k %s: " _fmt, \ - ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \ - ##__VA_ARGS__) - -#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \ - if (net_ratelimit()) \ - ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \ - } while (0) - -#define ATH5K_INFO(_sc, _fmt, ...) \ - ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__) - -#define ATH5K_WARN(_sc, _fmt, ...) \ - ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__) - -#define ATH5K_ERR(_sc, _fmt, ...) \ - ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) - -/* - * AR5K REGISTER ACCESS - */ - -/* Some macros to read/write fields */ - -/* First shift, then mask */ -#define AR5K_REG_SM(_val, _flags) \ - (((_val) << _flags##_S) & (_flags)) - -/* First mask, then shift */ -#define AR5K_REG_MS(_val, _flags) \ - (((_val) & (_flags)) >> _flags##_S) - -/* Some registers can hold multiple values of interest. For this - * reason when we want to write to these registers we must first - * retrieve the values which we do not want to clear (lets call this - * old_data) and then set the register with this and our new_value: - * ( old_data | new_value) */ -#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \ - (((_val) << _flags##_S) & (_flags)), _reg) - -#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \ - (_mask)) | (_flags), _reg) - -#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \ - ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg) - -#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ - ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) - -/* Access to PHY registers */ -#define AR5K_PHY_READ(ah, _reg) \ - ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2)) - -#define AR5K_PHY_WRITE(ah, _reg, _val) \ - ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2)) - -/* Access QCU registers per queue */ -#define AR5K_REG_READ_Q(ah, _reg, _queue) \ - (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ - -#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \ - ath5k_hw_reg_write(ah, (1 << _queue), _reg) - -#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \ - _reg |= 1 << _queue; \ -} while (0) - -#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \ - _reg &= ~(1 << _queue); \ -} while (0) - -/* Used while writing initvals */ -#define AR5K_REG_WAIT(_i) do { \ - if (_i % 64) \ - udelay(1); \ -} while (0) - -/* Register dumps are done per operation mode */ -#define AR5K_INI_RFGAIN_5GHZ 0 -#define AR5K_INI_RFGAIN_2GHZ 1 - -/* TODO: Clean this up */ -#define AR5K_INI_VAL_11A 0 -#define AR5K_INI_VAL_11A_TURBO 1 -#define AR5K_INI_VAL_11B 2 -#define AR5K_INI_VAL_11G 3 -#define AR5K_INI_VAL_11G_TURBO 4 -#define AR5K_INI_VAL_XR 0 -#define AR5K_INI_VAL_MAX 5 - -/* Used for BSSID etc manipulation */ -#define AR5K_LOW_ID(_a)( \ -(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ -) - -#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) - -/* - * Some tuneable values (these should be changeable by the user) - * TODO: Make use of them and add more options OR use debug/configfs - */ -#define AR5K_TUNE_DMA_BEACON_RESP 2 -#define AR5K_TUNE_SW_BEACON_RESP 10 -#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 -#define AR5K_TUNE_RADAR_ALERT false -#define AR5K_TUNE_MIN_TX_FIFO_THRES 1 -#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) -#define AR5K_TUNE_REGISTER_TIMEOUT 20000 -/* Register for RSSI threshold has a mask of 0xff, so 255 seems to - * be the max value. */ -#define AR5K_TUNE_RSSI_THRES 129 -/* This must be set when setting the RSSI threshold otherwise it can - * prevent a reset. If AR5K_RSSI_THR is read after writing to it - * the BMISS_THRES will be seen as 0, seems harware doesn't keep - * track of it. Max value depends on harware. For AR5210 this is just 7. - * For AR5211+ this seems to be up to 255. */ -#define AR5K_TUNE_BMISS_THRES 7 -#define AR5K_TUNE_REGISTER_DWELL_TIME 20000 -#define AR5K_TUNE_BEACON_INTERVAL 100 -#define AR5K_TUNE_AIFS 2 -#define AR5K_TUNE_AIFS_11B 2 -#define AR5K_TUNE_AIFS_XR 0 -#define AR5K_TUNE_CWMIN 15 -#define AR5K_TUNE_CWMIN_11B 31 -#define AR5K_TUNE_CWMIN_XR 3 -#define AR5K_TUNE_CWMAX 1023 -#define AR5K_TUNE_CWMAX_11B 1023 -#define AR5K_TUNE_CWMAX_XR 7 -#define AR5K_TUNE_NOISE_FLOOR -72 -#define AR5K_TUNE_MAX_TXPOWER 63 -#define AR5K_TUNE_DEFAULT_TXPOWER 25 -#define AR5K_TUNE_TPC_TXPOWER false -#define AR5K_TUNE_ANT_DIVERSITY true -#define AR5K_TUNE_HWTXTRIES 4 - -#define AR5K_INIT_CARR_SENSE_EN 1 - -/*Swap RX/TX Descriptor for big endian archs*/ -#if defined(__BIG_ENDIAN) -#define AR5K_INIT_CFG ( \ - AR5K_CFG_SWTD | AR5K_CFG_SWRD \ -) -#else -#define AR5K_INIT_CFG 0x00000000 -#endif - -/* Initial values */ -#define AR5K_INIT_CYCRSSI_THR1 2 -#define AR5K_INIT_TX_LATENCY 502 -#define AR5K_INIT_USEC 39 -#define AR5K_INIT_USEC_TURBO 79 -#define AR5K_INIT_USEC_32 31 -#define AR5K_INIT_SLOT_TIME 396 -#define AR5K_INIT_SLOT_TIME_TURBO 480 -#define AR5K_INIT_ACK_CTS_TIMEOUT 1024 -#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 -#define AR5K_INIT_PROG_IFS 920 -#define AR5K_INIT_PROG_IFS_TURBO 960 -#define AR5K_INIT_EIFS 3440 -#define AR5K_INIT_EIFS_TURBO 6880 -#define AR5K_INIT_SIFS 560 -#define AR5K_INIT_SIFS_TURBO 480 -#define AR5K_INIT_SH_RETRY 10 -#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY -#define AR5K_INIT_SSH_RETRY 32 -#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY -#define AR5K_INIT_TX_RETRY 10 - -#define AR5K_INIT_TRANSMIT_LATENCY ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC) \ -) -#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC_TURBO) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ - (AR5K_INIT_PROG_IFS) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ - (AR5K_INIT_PROG_IFS_TURBO) \ -) - -/* token to use for aifs, cwmin, cwmax in MadWiFi */ -#define AR5K_TXQ_USEDEFAULT ((u32) -1) - -/* GENERIC CHIPSET DEFINITIONS */ - -/* MAC Chips */ -enum ath5k_version { - AR5K_AR5210 = 0, - AR5K_AR5211 = 1, - AR5K_AR5212 = 2, -}; - -/* PHY Chips */ -enum ath5k_radio { - AR5K_RF5110 = 0, - AR5K_RF5111 = 1, - AR5K_RF5112 = 2, - AR5K_RF2413 = 3, - AR5K_RF5413 = 4, - AR5K_RF2316 = 5, - AR5K_RF2317 = 6, - AR5K_RF2425 = 7, -}; - -/* - * Common silicon revision/version values - */ - -enum ath5k_srev_type { - AR5K_VERSION_MAC, - AR5K_VERSION_RAD, -}; - -struct ath5k_srev_name { - const char *sr_name; - enum ath5k_srev_type sr_type; - u_int sr_val; -}; - -#define AR5K_SREV_UNKNOWN 0xffff - -#define AR5K_SREV_AR5210 0x00 /* Crete */ -#define AR5K_SREV_AR5311 0x10 /* Maui 1 */ -#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */ -#define AR5K_SREV_AR5311B 0x30 /* Spirit */ -#define AR5K_SREV_AR5211 0x40 /* Oahu */ -#define AR5K_SREV_AR5212 0x50 /* Venice */ -#define AR5K_SREV_AR5213 0x55 /* ??? */ -#define AR5K_SREV_AR5213A 0x59 /* Hainan */ -#define AR5K_SREV_AR2413 0x78 /* Griffin lite */ -#define AR5K_SREV_AR2414 0x70 /* Griffin */ -#define AR5K_SREV_AR5424 0x90 /* Condor */ -#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ -#define AR5K_SREV_AR5414 0xa0 /* Eagle */ -#define AR5K_SREV_AR2415 0xb0 /* Talon */ -#define AR5K_SREV_AR5416 0xc0 /* PCI-E */ -#define AR5K_SREV_AR5418 0xca /* PCI-E */ -#define AR5K_SREV_AR2425 0xe0 /* Swan */ -#define AR5K_SREV_AR2417 0xf0 /* Nala */ - -#define AR5K_SREV_RAD_5110 0x00 -#define AR5K_SREV_RAD_5111 0x10 -#define AR5K_SREV_RAD_5111A 0x15 -#define AR5K_SREV_RAD_2111 0x20 -#define AR5K_SREV_RAD_5112 0x30 -#define AR5K_SREV_RAD_5112A 0x35 -#define AR5K_SREV_RAD_5112B 0x36 -#define AR5K_SREV_RAD_2112 0x40 -#define AR5K_SREV_RAD_2112A 0x45 -#define AR5K_SREV_RAD_2112B 0x46 -#define AR5K_SREV_RAD_2413 0x50 -#define AR5K_SREV_RAD_5413 0x60 -#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */ -#define AR5K_SREV_RAD_2317 0x80 -#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */ -#define AR5K_SREV_RAD_2425 0xa2 -#define AR5K_SREV_RAD_5133 0xc0 - -#define AR5K_SREV_PHY_5211 0x30 -#define AR5K_SREV_PHY_5212 0x41 -#define AR5K_SREV_PHY_5212A 0x42 -#define AR5K_SREV_PHY_5212B 0x43 -#define AR5K_SREV_PHY_2413 0x45 -#define AR5K_SREV_PHY_5413 0x61 -#define AR5K_SREV_PHY_2425 0x70 - -/* IEEE defs */ -#define IEEE80211_MAX_LEN 2500 - -/* TODO add support to mac80211 for vendor-specific rates and modes */ - -/* - * Some of this information is based on Documentation from: - * - * http://madwifi.org/wiki/ChipsetFeatures/SuperAG - * - * Modulation for Atheros' eXtended Range - range enhancing extension that is - * supposed to double the distance an Atheros client device can keep a - * connection with an Atheros access point. This is achieved by increasing - * the receiver sensitivity up to, -105dBm, which is about 20dB above what - * the 802.11 specifications demand. In addition, new (proprietary) data rates - * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. - * - * Please note that can you either use XR or TURBO but you cannot use both, - * they are exclusive. - * - */ -#define MODULATION_XR 0x00000200 -/* - * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a - * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s - * signaling rate achieved through the bonding of two 54Mbit/s 802.11g - * channels. To use this feature your Access Point must also suport it. - * There is also a distinction between "static" and "dynamic" turbo modes: - * - * - Static: is the dumb version: devices set to this mode stick to it until - * the mode is turned off. - * - Dynamic: is the intelligent version, the network decides itself if it - * is ok to use turbo. As soon as traffic is detected on adjacent channels - * (which would get used in turbo mode), or when a non-turbo station joins - * the network, turbo mode won't be used until the situation changes again. - * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which - * monitors the used radio band in order to decide whether turbo mode may - * be used or not. - * - * This article claims Super G sticks to bonding of channels 5 and 6 for - * USA: - * - * http://www.pcworld.com/article/id,113428-page,1/article.html - * - * The channel bonding seems to be driver specific though. In addition to - * deciding what channels will be used, these "Turbo" modes are accomplished - * by also enabling the following features: - * - * - Bursting: allows multiple frames to be sent at once, rather than pausing - * after each frame. Bursting is a standards-compliant feature that can be - * used with any Access Point. - * - Fast frames: increases the amount of information that can be sent per - * frame, also resulting in a reduction of transmission overhead. It is a - * proprietary feature that needs to be supported by the Access Point. - * - Compression: data frames are compressed in real time using a Lempel Ziv - * algorithm. This is done transparently. Once this feature is enabled, - * compression and decompression takes place inside the chipset, without - * putting additional load on the host CPU. - * - */ -#define MODULATION_TURBO 0x00000080 - -enum ath5k_driver_mode { - AR5K_MODE_11A = 0, - AR5K_MODE_11A_TURBO = 1, - AR5K_MODE_11B = 2, - AR5K_MODE_11G = 3, - AR5K_MODE_11G_TURBO = 4, - AR5K_MODE_XR = 0, - AR5K_MODE_MAX = 5 -}; - - -/****************\ - TX DEFINITIONS -\****************/ - -/* - * TX Status descriptor - */ -struct ath5k_tx_status { - u16 ts_seqnum; - u16 ts_tstamp; - u8 ts_status; - u8 ts_rate[4]; - u8 ts_retry[4]; - u8 ts_final_idx; - s8 ts_rssi; - u8 ts_shortretry; - u8 ts_longretry; - u8 ts_virtcol; - u8 ts_antenna; -}; - -#define AR5K_TXSTAT_ALTRATE 0x80 -#define AR5K_TXERR_XRETRY 0x01 -#define AR5K_TXERR_FILT 0x02 -#define AR5K_TXERR_FIFO 0x04 - -/** - * enum ath5k_tx_queue - Queue types used to classify tx queues. - * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue - * @AR5K_TX_QUEUE_DATA: A normal data queue - * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue - * @AR5K_TX_QUEUE_BEACON: The beacon queue - * @AR5K_TX_QUEUE_CAB: The after-beacon queue - * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue - */ -enum ath5k_tx_queue { - AR5K_TX_QUEUE_INACTIVE = 0, - AR5K_TX_QUEUE_DATA, - AR5K_TX_QUEUE_XR_DATA, - AR5K_TX_QUEUE_BEACON, - AR5K_TX_QUEUE_CAB, - AR5K_TX_QUEUE_UAPSD, -}; - -#define AR5K_NUM_TX_QUEUES 10 -#define AR5K_NUM_TX_QUEUES_NOQCU 2 - -/* - * Queue syb-types to classify normal data queues. - * These are the 4 Access Categories as defined in - * WME spec. 0 is the lowest priority and 4 is the - * highest. Normal data that hasn't been classified - * goes to the Best Effort AC. - */ -enum ath5k_tx_queue_subtype { - AR5K_WME_AC_BK = 0, /*Background traffic*/ - AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/ - AR5K_WME_AC_VI, /*Video traffic*/ - AR5K_WME_AC_VO, /*Voice traffic*/ -}; - -/* - * Queue ID numbers as returned by the hw functions, each number - * represents a hw queue. If hw does not support hw queues - * (eg 5210) all data goes in one queue. These match - * d80211 definitions (net80211/MadWiFi don't use them). - */ -enum ath5k_tx_queue_id { - AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, - AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, - AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ - AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/ - AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ - AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ - AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ - AR5K_TX_QUEUE_ID_UAPSD = 8, - AR5K_TX_QUEUE_ID_XR_DATA = 9, -}; - -/* - * Flags to set hw queue's parameters... - */ -#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */ -#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */ -#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */ -#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */ -#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */ -#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */ -#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */ -#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */ -#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */ -#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */ -#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/ -#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */ -#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ -#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ - -/* - * A struct to hold tx queue's parameters - */ -struct ath5k_txq_info { - enum ath5k_tx_queue tqi_type; - enum ath5k_tx_queue_subtype tqi_subtype; - u16 tqi_flags; /* Tx queue flags (see above) */ - u32 tqi_aifs; /* Arbitrated Interframe Space */ - s32 tqi_cw_min; /* Minimum Contention Window */ - s32 tqi_cw_max; /* Maximum Contention Window */ - u32 tqi_cbr_period; /* Constant bit rate period */ - u32 tqi_cbr_overflow_limit; - u32 tqi_burst_time; - u32 tqi_ready_time; /* Not used */ -}; - -/* - * Transmit packet types. - * used on tx control descriptor - * TODO: Use them inside base.c corectly - */ -enum ath5k_pkt_type { - AR5K_PKT_TYPE_NORMAL = 0, - AR5K_PKT_TYPE_ATIM = 1, - AR5K_PKT_TYPE_PSPOLL = 2, - AR5K_PKT_TYPE_BEACON = 3, - AR5K_PKT_TYPE_PROBE_RESP = 4, - AR5K_PKT_TYPE_PIFS = 5, -}; - -/* - * TX power and TPC settings - */ -#define AR5K_TXPOWER_OFDM(_r, _v) ( \ - ((0 & 1) << ((_v) + 6)) | \ - (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \ -) - -#define AR5K_TXPOWER_CCK(_r, _v) ( \ - (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ -) - -/* - * DMA size definitions (2^n+2) - */ -enum ath5k_dmasize { - AR5K_DMASIZE_4B = 0, - AR5K_DMASIZE_8B, - AR5K_DMASIZE_16B, - AR5K_DMASIZE_32B, - AR5K_DMASIZE_64B, - AR5K_DMASIZE_128B, - AR5K_DMASIZE_256B, - AR5K_DMASIZE_512B -}; - - -/****************\ - RX DEFINITIONS -\****************/ - -/* - * RX Status descriptor - */ -struct ath5k_rx_status { - u16 rs_datalen; - u16 rs_tstamp; - u8 rs_status; - u8 rs_phyerr; - s8 rs_rssi; - u8 rs_keyix; - u8 rs_rate; - u8 rs_antenna; - u8 rs_more; -}; - -#define AR5K_RXERR_CRC 0x01 -#define AR5K_RXERR_PHY 0x02 -#define AR5K_RXERR_FIFO 0x04 -#define AR5K_RXERR_DECRYPT 0x08 -#define AR5K_RXERR_MIC 0x10 -#define AR5K_RXKEYIX_INVALID ((u8) - 1) -#define AR5K_TXKEYIX_INVALID ((u32) - 1) - - -/**************************\ - BEACON TIMERS DEFINITIONS -\**************************/ - -#define AR5K_BEACON_PERIOD 0x0000ffff -#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ -#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ - -#if 0 -/** - * struct ath5k_beacon_state - Per-station beacon timer state. - * @bs_interval: in TU's, can also include the above flags - * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a - * Point Coordination Function capable AP - */ -struct ath5k_beacon_state { - u32 bs_next_beacon; - u32 bs_next_dtim; - u32 bs_interval; - u8 bs_dtim_period; - u8 bs_cfp_period; - u16 bs_cfp_max_duration; - u16 bs_cfp_du_remain; - u16 bs_tim_offset; - u16 bs_sleep_duration; - u16 bs_bmiss_threshold; - u32 bs_cfp_next; -}; -#endif - - -/* - * TSF to TU conversion: - * - * TSF is a 64bit value in usec (microseconds). - * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of - * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024). - */ -#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) - - -/*******************************\ - GAIN OPTIMIZATION DEFINITIONS -\*******************************/ - -enum ath5k_rfgain { - AR5K_RFGAIN_INACTIVE = 0, - AR5K_RFGAIN_ACTIVE, - AR5K_RFGAIN_READ_REQUESTED, - AR5K_RFGAIN_NEED_CHANGE, -}; - -struct ath5k_gain { - u8 g_step_idx; - u8 g_current; - u8 g_target; - u8 g_low; - u8 g_high; - u8 g_f_corr; - u8 g_state; -}; - -/********************\ - COMMON DEFINITIONS -\********************/ - -#define AR5K_SLOT_TIME_9 396 -#define AR5K_SLOT_TIME_20 880 -#define AR5K_SLOT_TIME_MAX 0xffff - -/* channel_flags */ -#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ -#define CHANNEL_TURBO 0x0010 /* Turbo Channel */ -#define CHANNEL_CCK 0x0020 /* CCK channel */ -#define CHANNEL_OFDM 0x0040 /* OFDM channel */ -#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ -#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */ -#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */ -#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */ -#define CHANNEL_XR 0x0800 /* XR channel */ - -#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) -#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) -#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) -#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_108A CHANNEL_T -#define CHANNEL_108G CHANNEL_TG -#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) - -#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ - CHANNEL_TURBO) - -#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) -#define CHANNEL_MODES CHANNEL_ALL - -/* - * Used internaly for reset_tx_queue). - * Also see struct struct ieee80211_channel. - */ -#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0) -#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0) - -/* - * The following structure is used to map 2GHz channels to - * 5GHz Atheros channels. - * TODO: Clean up - */ -struct ath5k_athchan_2ghz { - u32 a2_flags; - u16 a2_athchan; -}; - - -/******************\ - RATE DEFINITIONS -\******************/ - -/** - * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32. - * - * The rate code is used to get the RX rate or set the TX rate on the - * hardware descriptors. It is also used for internal modulation control - * and settings. - * - * This is the hardware rate map we are aware of: - * - * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 - * rate_kbps 3000 1000 ? ? ? 2000 500 48000 - * - * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 - * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? - * - * rate_code 17 18 19 20 21 22 23 24 - * rate_kbps ? ? ? ? ? ? ? 11000 - * - * rate_code 25 26 27 28 29 30 31 32 - * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ? - * - * "S" indicates CCK rates with short preamble. - * - * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the - * lowest 4 bits, so they are the same as below with a 0xF mask. - * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). - * We handle this in ath5k_setup_bands(). - */ -#define AR5K_MAX_RATES 32 - -/* B */ -#define ATH5K_RATE_CODE_1M 0x1B -#define ATH5K_RATE_CODE_2M 0x1A -#define ATH5K_RATE_CODE_5_5M 0x19 -#define ATH5K_RATE_CODE_11M 0x18 -/* A and G */ -#define ATH5K_RATE_CODE_6M 0x0B -#define ATH5K_RATE_CODE_9M 0x0F -#define ATH5K_RATE_CODE_12M 0x0A -#define ATH5K_RATE_CODE_18M 0x0E -#define ATH5K_RATE_CODE_24M 0x09 -#define ATH5K_RATE_CODE_36M 0x0D -#define ATH5K_RATE_CODE_48M 0x08 -#define ATH5K_RATE_CODE_54M 0x0C -/* XR */ -#define ATH5K_RATE_CODE_XR_500K 0x07 -#define ATH5K_RATE_CODE_XR_1M 0x02 -#define ATH5K_RATE_CODE_XR_2M 0x06 -#define ATH5K_RATE_CODE_XR_3M 0x01 - -/* adding this flag to rate_code enables short preamble */ -#define AR5K_SET_SHORT_PREAMBLE 0x04 - -/* - * Crypto definitions - */ - -#define AR5K_KEYCACHE_SIZE 8 - -/***********************\ - HW RELATED DEFINITIONS -\***********************/ - -/* - * Misc definitions - */ -#define AR5K_RSSI_EP_MULTIPLIER (1<<7) - -#define AR5K_ASSERT_ENTRY(_e, _s) do { \ - if (_e >= _s) \ - return (false); \ -} while (0) - -/* - * Hardware interrupt abstraction - */ - -/** - * enum ath5k_int - Hardware interrupt masks helpers - * - * @AR5K_INT_RX: mask to identify received frame interrupts, of type - * AR5K_ISR_RXOK or AR5K_ISR_RXERR - * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?) - * @AR5K_INT_RXNOFRM: No frame received (?) - * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The - * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's - * LinkPtr is NULL. For more details, refer to: - * http://www.freepatentsonline.com/20030225739.html - * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). - * Note that Rx overrun is not always fatal, on some chips we can continue - * operation without reseting the card, that's why int_fatal is not - * common for all chips. - * @AR5K_INT_TX: mask to identify received frame interrupts, of type - * AR5K_ISR_TXOK or AR5K_ISR_TXERR - * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?) - * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold - * We currently do increments on interrupt by - * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 - * @AR5K_INT_MIB: Indicates the Management Information Base counters should be - * checked. We should do this with ath5k_hw_update_mib_counters() but - * it seems we should also then do some noise immunity work. - * @AR5K_INT_RXPHY: RX PHY Error - * @AR5K_INT_RXKCM: RX Key cache miss - * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a - * beacon that must be handled in software. The alternative is if you - * have VEOL support, in that case you let the hardware deal with things. - * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing - * beacons from the AP have associated with, we should probably try to - * reassociate. When in IBSS mode this might mean we have not received - * any beacons from any local stations. Note that every station in an - * IBSS schedules to send beacons at the Target Beacon Transmission Time - * (TBTT) with a random backoff. - * @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? - * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now - * until properly handled - * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA - * errors. These types of errors we can enable seem to be of type - * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. - * @AR5K_INT_GLOBAL: Used to clear and set the IER - * @AR5K_INT_NOCARD: signals the card has been removed - * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same - * bit value - * - * These are mapped to take advantage of some common bits - * between the MACs, to be able to set intr properties - * easier. Some of them are not used yet inside hw.c. Most map - * to the respective hw interrupt value as they are common amogst different - * MACs. - */ -enum ath5k_int { - AR5K_INT_RXOK = 0x00000001, - AR5K_INT_RXDESC = 0x00000002, - AR5K_INT_RXERR = 0x00000004, - AR5K_INT_RXNOFRM = 0x00000008, - AR5K_INT_RXEOL = 0x00000010, - AR5K_INT_RXORN = 0x00000020, - AR5K_INT_TXOK = 0x00000040, - AR5K_INT_TXDESC = 0x00000080, - AR5K_INT_TXERR = 0x00000100, - AR5K_INT_TXNOFRM = 0x00000200, - AR5K_INT_TXEOL = 0x00000400, - AR5K_INT_TXURN = 0x00000800, - AR5K_INT_MIB = 0x00001000, - AR5K_INT_SWI = 0x00002000, - AR5K_INT_RXPHY = 0x00004000, - AR5K_INT_RXKCM = 0x00008000, - AR5K_INT_SWBA = 0x00010000, - AR5K_INT_BRSSI = 0x00020000, - AR5K_INT_BMISS = 0x00040000, - AR5K_INT_FATAL = 0x00080000, /* Non common */ - AR5K_INT_BNR = 0x00100000, /* Non common */ - AR5K_INT_TIM = 0x00200000, /* Non common */ - AR5K_INT_DTIM = 0x00400000, /* Non common */ - AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */ - AR5K_INT_GPIO = 0x01000000, - AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ - AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ - AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */ - AR5K_INT_QCBRORN = 0x10000000, /* Non common */ - AR5K_INT_QCBRURN = 0x20000000, /* Non common */ - AR5K_INT_QTRIG = 0x40000000, /* Non common */ - AR5K_INT_GLOBAL = 0x80000000, - - AR5K_INT_COMMON = AR5K_INT_RXOK - | AR5K_INT_RXDESC - | AR5K_INT_RXERR - | AR5K_INT_RXNOFRM - | AR5K_INT_RXEOL - | AR5K_INT_RXORN - | AR5K_INT_TXOK - | AR5K_INT_TXDESC - | AR5K_INT_TXERR - | AR5K_INT_TXNOFRM - | AR5K_INT_TXEOL - | AR5K_INT_TXURN - | AR5K_INT_MIB - | AR5K_INT_SWI - | AR5K_INT_RXPHY - | AR5K_INT_RXKCM - | AR5K_INT_SWBA - | AR5K_INT_BRSSI - | AR5K_INT_BMISS - | AR5K_INT_GPIO - | AR5K_INT_GLOBAL, - - AR5K_INT_NOCARD = 0xffffffff -}; - -/* - * Power management - */ -enum ath5k_power_mode { - AR5K_PM_UNDEFINED = 0, - AR5K_PM_AUTO, - AR5K_PM_AWAKE, - AR5K_PM_FULL_SLEEP, - AR5K_PM_NETWORK_SLEEP, -}; - -/* - * These match net80211 definitions (not used in - * mac80211). - * TODO: Clean this up - */ -#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/ -#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/ -#define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/ -#define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/ -#define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/ - -/* GPIO-controlled software LED */ -#define AR5K_SOFTLED_PIN 0 -#define AR5K_SOFTLED_ON 0 -#define AR5K_SOFTLED_OFF 1 - -/* - * Chipset capabilities -see ath5k_hw_get_capability- - * get_capability function is not yet fully implemented - * in ath5k so most of these don't work yet... - * TODO: Implement these & merge with _TUNE_ stuff above - */ -enum ath5k_capability_type { - AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ - AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */ - AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */ - AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */ - AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */ - AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */ - AR5K_CAP_VEOL = 7, /* Supports virtual EOL */ - AR5K_CAP_COMPRESSION = 8, /* Supports compression */ - AR5K_CAP_BURST = 9, /* Supports packet bursting */ - AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */ - AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */ - AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */ - AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */ - AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */ - AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */ - AR5K_CAP_XR = 16, /* Supports XR mode */ - AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */ - AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */ - AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */ - AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */ -}; - - -/* XXX: we *may* move cap_range stuff to struct wiphy */ -struct ath5k_capabilities { - /* - * Supported PHY modes - * (ie. CHANNEL_A, CHANNEL_B, ...) - */ - DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX); - - /* - * Frequency range (without regulation restrictions) - */ - struct { - u16 range_2ghz_min; - u16 range_2ghz_max; - u16 range_5ghz_min; - u16 range_5ghz_max; - } cap_range; - - /* - * Values stored in the EEPROM (some of them...) - */ - struct ath5k_eeprom_info cap_eeprom; - - /* - * Queue information - */ - struct { - u8 q_tx_num; - } cap_queues; -}; - - -/***************************************\ - HARDWARE ABSTRACTION LAYER STRUCTURE -\***************************************/ - -/* - * Misc defines - */ - -#define AR5K_MAX_GPIO 10 -#define AR5K_MAX_RF_BANKS 8 - -/* TODO: Clean up and merge with ath5k_softc */ -struct ath5k_hw { - u32 ah_magic; - - struct ath5k_softc *ah_sc; - void __iomem *ah_iobase; - - enum ath5k_int ah_imr; - - enum nl80211_iftype ah_op_mode; - enum ath5k_power_mode ah_power_mode; - struct ieee80211_channel ah_current_channel; - bool ah_turbo; - bool ah_calibration; - bool ah_running; - bool ah_single_chip; - bool ah_combined_mic; - - u32 ah_mac_srev; - u16 ah_mac_version; - u16 ah_mac_revision; - u16 ah_phy_revision; - u16 ah_radio_5ghz_revision; - u16 ah_radio_2ghz_revision; - - enum ath5k_version ah_version; - enum ath5k_radio ah_radio; - u32 ah_phy; - - bool ah_5ghz; - bool ah_2ghz; - -#define ah_modes ah_capabilities.cap_mode -#define ah_ee_version ah_capabilities.cap_eeprom.ee_version - - u32 ah_atim_window; - u32 ah_aifs; - u32 ah_cw_min; - u32 ah_cw_max; - bool ah_software_retry; - u32 ah_limit_tx_retries; - - u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; - bool ah_ant_diversity; - - u8 ah_sta_id[ETH_ALEN]; - - /* Current BSSID we are trying to assoc to / create. - * This is passed by mac80211 on config_interface() and cached here for - * use in resets */ - u8 ah_bssid[ETH_ALEN]; - u8 ah_bssid_mask[ETH_ALEN]; - - u32 ah_gpio[AR5K_MAX_GPIO]; - int ah_gpio_npins; - - struct ath_regulatory ah_regulatory; - struct ath5k_capabilities ah_capabilities; - - struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; - u32 ah_txq_status; - u32 ah_txq_imr_txok; - u32 ah_txq_imr_txerr; - u32 ah_txq_imr_txurn; - u32 ah_txq_imr_txdesc; - u32 ah_txq_imr_txeol; - u32 ah_txq_imr_cbrorn; - u32 ah_txq_imr_cbrurn; - u32 ah_txq_imr_qtrig; - u32 ah_txq_imr_nofrm; - u32 ah_txq_isr; - u32 *ah_rf_banks; - size_t ah_rf_banks_size; - size_t ah_rf_regs_count; - struct ath5k_gain ah_gain; - u8 ah_offset[AR5K_MAX_RF_BANKS]; - - - struct { - /* Temporary tables used for interpolation */ - u8 tmpL[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_POWER_TABLE_SIZE]; - u8 tmpR[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_POWER_TABLE_SIZE]; - u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2]; - u16 txp_rates_power_table[AR5K_MAX_RATES]; - u8 txp_min_idx; - bool txp_tpc; - /* Values in 0.25dB units */ - s16 txp_min_pwr; - s16 txp_max_pwr; - s16 txp_offset; - s16 txp_ofdm; - /* Values in dB units */ - s16 txp_cck_ofdm_pwr_delta; - s16 txp_cck_ofdm_gainf_delta; - } ah_txpower; - - struct { - bool r_enabled; - int r_last_alert; - struct ieee80211_channel r_last_channel; - } ah_radar; - - /* noise floor from last periodic calibration */ - s32 ah_noise_floor; - - /* - * Function pointers - */ - int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, - u32 size, unsigned int flags); - int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, - unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int); - int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int); - int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - struct ath5k_tx_status *); - int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, - struct ath5k_rx_status *); -}; - -/* - * Prototypes - */ - -/* Attach/Detach Functions */ -extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); -extern void ath5k_hw_detach(struct ath5k_hw *ah); - -/* LED functions */ -extern int ath5k_init_leds(struct ath5k_softc *sc); -extern void ath5k_led_enable(struct ath5k_softc *sc); -extern void ath5k_led_off(struct ath5k_softc *sc); -extern void ath5k_unregister_leds(struct ath5k_softc *sc); - -/* Reset Functions */ -extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); -extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); -/* Power management functions */ -extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); - -/* DMA Related Functions */ -extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); -extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); -extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); -extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); -extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); -extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, - u32 phys_addr); -extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); -/* Interrupt handling */ -extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); -extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); -extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum -ath5k_int new_mask); -extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); - -/* EEPROM access functions */ -extern int ath5k_eeprom_init(struct ath5k_hw *ah); -extern void ath5k_eeprom_detach(struct ath5k_hw *ah); -extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); -extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); - -/* Protocol Control Unit Functions */ -extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); -/* BSSID Functions */ -extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac); -extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); -extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id); -extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); -/* Receive start/stop functions */ -extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); -extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); -/* RX Filter functions */ -extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); -extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); -extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); -extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); -extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); -/* Beacon control functions */ -extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); -extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); -extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); -extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); -extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); -#if 0 -extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); -extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); -extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); -#endif -/* ACK bit rate */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); -/* ACK/CTS Timeouts */ -extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); -extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); -extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); -extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); -/* Key table (WEP) functions */ -extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); -extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); -extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); -extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); - -/* Queue Control Unit, DFS Control Unit Functions */ -extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); -extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, - const struct ath5k_txq_info *queue_info); -extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, - enum ath5k_tx_queue queue_type, - struct ath5k_txq_info *queue_info); -extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); -extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); -extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); - -/* Hardware Descriptor Functions */ -extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); - -/* GPIO Functions */ -extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); -extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); -extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); -extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); -extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); -extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); - -/* Misc functions */ -int ath5k_hw_set_capabilities(struct ath5k_hw *ah); -extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); -extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); -extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); - -/* Initial register settings functions */ -extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); - -/* Initialize RF */ -extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - unsigned int mode); -extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); -extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); -extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); -/* PHY/RF channel functions */ -extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); -extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); -/* PHY calibration */ -extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); -extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); -/* Misc PHY functions */ -extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); -extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); -extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); -/* TX power setup */ -extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); -extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); - -/* - * Functions used internaly - */ - -/* - * Translate usec to hw clock units - * TODO: Half/quarter rate - */ -static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) -{ - return turbo ? (usec * 80) : (usec * 40); -} - -/* - * Translate hw clock units to usec - * TODO: Half/quarter rate - */ -static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) -{ - return turbo ? (clock / 80) : (clock / 40); -} - -/* - * Read from a register - */ -static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) -{ - return ioread32(ah->ah_iobase + reg); -} - -/* - * Write to a register - */ -static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) -{ - iowrite32(val, ah->ah_iobase + reg); -} - -#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) -/* - * Check if a register write has been completed - */ -static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, - u32 val, bool is_set) -{ - int i; - u32 data; - - for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { - data = ath5k_hw_reg_read(ah, reg); - if (is_set && (data & flag)) - break; - else if ((data & flag) == val) - break; - udelay(15); - } - - return (i <= 0) ? -EAGAIN : 0; -} -#endif - -static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) -{ - u32 retval = 0, bit, i; - - for (i = 0; i < bits; i++) { - bit = (val >> i) & 1; - retval = (retval << 1) | bit; - } - - return retval; -} - -static inline int ath5k_pad_size(int hdrlen) -{ - return (hdrlen < 24) ? 0 : hdrlen & 3; -} - -#endif diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c deleted file mode 100644 index 70d376c63aac..000000000000 --- a/drivers/net/wireless/ath5k/attach.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*************************************\ -* Attach/Detach Functions and helpers * -\*************************************/ - -#include -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/** - * ath5k_hw_post - Power On Self Test helper function - * - * @ah: The &struct ath5k_hw - */ -static int ath5k_hw_post(struct ath5k_hw *ah) -{ - - static const u32 static_pattern[4] = { - 0x55555555, 0xaaaaaaaa, - 0x66666666, 0x99999999 - }; - static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) }; - int i, c; - u16 cur_reg; - u32 var_pattern; - u32 init_val; - u32 cur_val; - - for (c = 0; c < 2; c++) { - - cur_reg = regs[c]; - - /* Save previous value */ - init_val = ath5k_hw_reg_read(ah, cur_reg); - - for (i = 0; i < 256; i++) { - var_pattern = i << 16 | i; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - cur_val = ath5k_hw_reg_read(ah, cur_reg); - - if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); - return -EAGAIN; - } - - /* Found on ndiswrapper dumps */ - var_pattern = 0x0039080f; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - } - - for (i = 0; i < 4; i++) { - var_pattern = static_pattern[i]; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - cur_val = ath5k_hw_reg_read(ah, cur_reg); - - if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); - return -EAGAIN; - } - - /* Found on ndiswrapper dumps */ - var_pattern = 0x003b080f; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - } - - /* Restore previous value */ - ath5k_hw_reg_write(ah, init_val, cur_reg); - - } - - return 0; - -} - -/** - * ath5k_hw_attach - Check if hw is supported and init the needed structs - * - * @sc: The &struct ath5k_softc we got from the driver's attach function - * @mac_version: The mac version id (check out ath5k.h) based on pci id - * - * Check if the device is supported, perform a POST and initialize the needed - * structs. Returns -ENOMEM if we don't have memory for the needed structs, - * -ENODEV if the device is not supported or prints an error msg if something - * else went wrong. - */ -struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) -{ - struct ath5k_hw *ah; - struct pci_dev *pdev = sc->pdev; - int ret; - u32 srev; - - /*If we passed the test malloc a ath5k_hw struct*/ - ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); - if (ah == NULL) { - ret = -ENOMEM; - ATH5K_ERR(sc, "out of memory\n"); - goto err; - } - - ah->ah_sc = sc; - ah->ah_iobase = sc->iobase; - - /* - * HW information - */ - ah->ah_op_mode = NL80211_IFTYPE_STATION; - ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; - ah->ah_turbo = false; - ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; - ah->ah_imr = 0; - ah->ah_atim_window = 0; - ah->ah_aifs = AR5K_TUNE_AIFS; - ah->ah_cw_min = AR5K_TUNE_CWMIN; - ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; - ah->ah_software_retry = false; - ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; - - /* - * Set the mac version based on the pci id - */ - ah->ah_version = mac_version; - - /*Fill the ath5k_hw struct with the needed functions*/ - ret = ath5k_hw_init_desc_functions(ah); - if (ret) - goto err_free; - - /* Bring device out of sleep and reset it's units */ - ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true); - if (ret) - goto err_free; - - /* Get MAC, PHY and RADIO revisions */ - srev = ath5k_hw_reg_read(ah, AR5K_SREV); - ah->ah_mac_srev = srev; - ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); - ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); - ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & - 0xffffffff; - ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_5GHZ); - ah->ah_phy = AR5K_PHY(0); - - /* Try to identify radio chip based on it's srev */ - switch (ah->ah_radio_5ghz_revision & 0xf0) { - case AR5K_SREV_RAD_5111: - ah->ah_radio = AR5K_RF5111; - ah->ah_single_chip = false; - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - break; - case AR5K_SREV_RAD_5112: - case AR5K_SREV_RAD_2112: - ah->ah_radio = AR5K_RF5112; - ah->ah_single_chip = false; - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - break; - case AR5K_SREV_RAD_2413: - ah->ah_radio = AR5K_RF2413; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_5413: - ah->ah_radio = AR5K_RF5413; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_2316: - ah->ah_radio = AR5K_RF2316; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_2317: - ah->ah_radio = AR5K_RF2317; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_5424: - if (ah->ah_mac_version == AR5K_SREV_AR2425 || - ah->ah_mac_version == AR5K_SREV_AR2417){ - ah->ah_radio = AR5K_RF2425; - ah->ah_single_chip = true; - } else { - ah->ah_radio = AR5K_RF5413; - ah->ah_single_chip = true; - } - break; - default: - /* Identify radio based on mac/phy srev */ - if (ah->ah_version == AR5K_AR5210) { - ah->ah_radio = AR5K_RF5110; - ah->ah_single_chip = false; - } else if (ah->ah_version == AR5K_AR5211) { - ah->ah_radio = AR5K_RF5111; - ah->ah_single_chip = false; - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || - ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || - ah->ah_phy_revision == AR5K_SREV_PHY_2425) { - ah->ah_radio = AR5K_RF2425; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425; - } else if (srev == AR5K_SREV_AR5213A && - ah->ah_phy_revision == AR5K_SREV_PHY_5212B) { - ah->ah_radio = AR5K_RF5112; - ah->ah_single_chip = false; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B; - } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) { - ah->ah_radio = AR5K_RF2316; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; - } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) || - ah->ah_phy_revision == AR5K_SREV_PHY_5413) { - ah->ah_radio = AR5K_RF5413; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413; - } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) || - ah->ah_phy_revision == AR5K_SREV_PHY_2413) { - ah->ah_radio = AR5K_RF2413; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; - } else { - ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); - ret = -ENODEV; - goto err_free; - } - } - - - /* Return on unsuported chips (unsupported eeprom etc) */ - if ((srev >= AR5K_SREV_AR5416) && - (srev < AR5K_SREV_AR2425)) { - ATH5K_ERR(sc, "Device not yet supported.\n"); - ret = -ENODEV; - goto err_free; - } - - /* - * Write PCI-E power save settings - */ - if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { - ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); - /* Shut off RX when elecidle is asserted */ - ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); - /* TODO: EEPROM work */ - ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); - /* Shut off PLL and CLKREQ active in L1 */ - ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); - /* Preserce other settings */ - ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); - /* Reset SERDES to load new settings */ - ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); - mdelay(1); - } - - /* - * POST - */ - ret = ath5k_hw_post(ah); - if (ret) - goto err_free; - - /* Enable pci core retry fix on Hainan (5213A) and later chips */ - if (srev >= AR5K_SREV_AR5213A) - ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG); - - /* - * Get card capabilities, calibration values etc - * TODO: EEPROM work - */ - ret = ath5k_eeprom_init(ah); - if (ret) { - ATH5K_ERR(sc, "unable to init EEPROM\n"); - goto err_free; - } - - /* Get misc capabilities */ - ret = ath5k_hw_set_capabilities(ah); - if (ret) { - ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", - sc->pdev->device); - goto err_free; - } - - if (srev >= AR5K_SREV_AR2414) { - ah->ah_combined_mic = true; - AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, - AR5K_MISC_MODE_COMBINED_MIC); - } - - /* MAC address is cleared until add_interface */ - ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); - - /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ - memset(ah->ah_bssid, 0xff, ETH_ALEN); - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - ath5k_hw_set_opmode(ah); - - ath5k_hw_rfgain_opt_init(ah); - - return ah; -err_free: - kfree(ah); -err: - return ERR_PTR(ret); -} - -/** - * ath5k_hw_detach - Free the ath5k_hw struct - * - * @ah: The &struct ath5k_hw - */ -void ath5k_hw_detach(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); - - if (ah->ah_rf_banks != NULL) - kfree(ah->ah_rf_banks); - - ath5k_eeprom_detach(ah); - - /* assume interrupts are down */ - kfree(ah); -} diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c deleted file mode 100644 index ff6d4f839734..000000000000 --- a/drivers/net/wireless/ath5k/base.c +++ /dev/null @@ -1,3110 +0,0 @@ -/*- - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2006 Devicescape Software, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2007 Luis R. Rodriguez - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "base.h" -#include "reg.h" -#include "debug.h" - -static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -static int modparam_all_channels; -module_param_named(all_channels, modparam_all_channels, int, 0444); -MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); - - -/******************\ -* Internal defines * -\******************/ - -/* Module info */ -MODULE_AUTHOR("Jiri Slaby"); -MODULE_AUTHOR("Nick Kossifidis"); -MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); -MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); - - -/* Known PCI ids */ -static const struct pci_device_id ath5k_pci_id_table[] = { - { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ - { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ - { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ - { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */ - { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */ - { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */ - { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */ - { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */ - { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ - { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); - -/* Known SREVs */ -static const struct ath5k_srev_name srev_names[] = { - { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, - { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, - { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, - { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B }, - { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 }, - { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 }, - { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 }, - { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A }, - { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 }, - { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 }, - { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 }, - { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 }, - { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 }, - { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 }, - { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 }, - { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, - { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, - { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, - { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, - { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, - { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, - { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A }, - { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, - { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, - { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, - { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B }, - { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, - { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, - { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, - { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, - { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, - { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, - { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, - { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, - { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, - { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, -}; - -static const struct ieee80211_rate ath5k_rates[] = { - { .bitrate = 10, - .hw_value = ATH5K_RATE_CODE_1M, }, - { .bitrate = 20, - .hw_value = ATH5K_RATE_CODE_2M, - .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, - .hw_value = ATH5K_RATE_CODE_5_5M, - .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, - .hw_value = ATH5K_RATE_CODE_11M, - .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, - .hw_value = ATH5K_RATE_CODE_6M, - .flags = 0 }, - { .bitrate = 90, - .hw_value = ATH5K_RATE_CODE_9M, - .flags = 0 }, - { .bitrate = 120, - .hw_value = ATH5K_RATE_CODE_12M, - .flags = 0 }, - { .bitrate = 180, - .hw_value = ATH5K_RATE_CODE_18M, - .flags = 0 }, - { .bitrate = 240, - .hw_value = ATH5K_RATE_CODE_24M, - .flags = 0 }, - { .bitrate = 360, - .hw_value = ATH5K_RATE_CODE_36M, - .flags = 0 }, - { .bitrate = 480, - .hw_value = ATH5K_RATE_CODE_48M, - .flags = 0 }, - { .bitrate = 540, - .hw_value = ATH5K_RATE_CODE_54M, - .flags = 0 }, - /* XR missing */ -}; - -/* - * Prototypes - PCI stack related functions - */ -static int __devinit ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -static void __devexit ath5k_pci_remove(struct pci_dev *pdev); -#ifdef CONFIG_PM -static int ath5k_pci_suspend(struct pci_dev *pdev, - pm_message_t state); -static int ath5k_pci_resume(struct pci_dev *pdev); -#else -#define ath5k_pci_suspend NULL -#define ath5k_pci_resume NULL -#endif /* CONFIG_PM */ - -static struct pci_driver ath5k_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = ath5k_pci_id_table, - .probe = ath5k_pci_probe, - .remove = __devexit_p(ath5k_pci_remove), - .suspend = ath5k_pci_suspend, - .resume = ath5k_pci_resume, -}; - - - -/* - * Prototypes - MAC 802.11 stack related functions - */ -static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -static int ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel); -static int ath5k_reset_wake(struct ath5k_softc *sc); -static int ath5k_start(struct ieee80211_hw *hw); -static void ath5k_stop(struct ieee80211_hw *hw); -static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -static int ath5k_config(struct ieee80211_hw *hw, u32 changed); -static int ath5k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); -static void ath5k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist); -static int ath5k_set_key(struct ieee80211_hw *hw, - enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -static int ath5k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats); -static int ath5k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); -static u64 ath5k_get_tsf(struct ieee80211_hw *hw); -static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); -static void ath5k_reset_tsf(struct ieee80211_hw *hw); -static int ath5k_beacon_update(struct ath5k_softc *sc, - struct sk_buff *skb); -static void ath5k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes); - -static const struct ieee80211_ops ath5k_hw_ops = { - .tx = ath5k_tx, - .start = ath5k_start, - .stop = ath5k_stop, - .add_interface = ath5k_add_interface, - .remove_interface = ath5k_remove_interface, - .config = ath5k_config, - .config_interface = ath5k_config_interface, - .configure_filter = ath5k_configure_filter, - .set_key = ath5k_set_key, - .get_stats = ath5k_get_stats, - .conf_tx = NULL, - .get_tx_stats = ath5k_get_tx_stats, - .get_tsf = ath5k_get_tsf, - .set_tsf = ath5k_set_tsf, - .reset_tsf = ath5k_reset_tsf, - .bss_info_changed = ath5k_bss_info_changed, -}; - -/* - * Prototypes - Internal functions - */ -/* Attach detach */ -static int ath5k_attach(struct pci_dev *pdev, - struct ieee80211_hw *hw); -static void ath5k_detach(struct pci_dev *pdev, - struct ieee80211_hw *hw); -/* Channel/mode setup */ -static inline short ath5k_ieee2mhz(short chan); -static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, - struct ieee80211_channel *channels, - unsigned int mode, - unsigned int max); -static int ath5k_setup_bands(struct ieee80211_hw *hw); -static int ath5k_chan_set(struct ath5k_softc *sc, - struct ieee80211_channel *chan); -static void ath5k_setcurmode(struct ath5k_softc *sc, - unsigned int mode); -static void ath5k_mode_setup(struct ath5k_softc *sc); - -/* Descriptor setup */ -static int ath5k_desc_alloc(struct ath5k_softc *sc, - struct pci_dev *pdev); -static void ath5k_desc_free(struct ath5k_softc *sc, - struct pci_dev *pdev); -/* Buffers setup */ -static int ath5k_rxbuf_setup(struct ath5k_softc *sc, - struct ath5k_buf *bf); -static int ath5k_txbuf_setup(struct ath5k_softc *sc, - struct ath5k_buf *bf); -static inline void ath5k_txbuf_free(struct ath5k_softc *sc, - struct ath5k_buf *bf) -{ - BUG_ON(!bf); - if (!bf->skb) - return; - pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(bf->skb); - bf->skb = NULL; -} - -static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, - struct ath5k_buf *bf) -{ - BUG_ON(!bf); - if (!bf->skb) - return; - pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(bf->skb); - bf->skb = NULL; -} - - -/* Queues setup */ -static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, - int qtype, int subtype); -static int ath5k_beaconq_setup(struct ath5k_hw *ah); -static int ath5k_beaconq_config(struct ath5k_softc *sc); -static void ath5k_txq_drainq(struct ath5k_softc *sc, - struct ath5k_txq *txq); -static void ath5k_txq_cleanup(struct ath5k_softc *sc); -static void ath5k_txq_release(struct ath5k_softc *sc); -/* Rx handling */ -static int ath5k_rx_start(struct ath5k_softc *sc); -static void ath5k_rx_stop(struct ath5k_softc *sc); -static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, - struct ath5k_desc *ds, - struct sk_buff *skb, - struct ath5k_rx_status *rs); -static void ath5k_tasklet_rx(unsigned long data); -/* Tx handling */ -static void ath5k_tx_processq(struct ath5k_softc *sc, - struct ath5k_txq *txq); -static void ath5k_tasklet_tx(unsigned long data); -/* Beacon handling */ -static int ath5k_beacon_setup(struct ath5k_softc *sc, - struct ath5k_buf *bf); -static void ath5k_beacon_send(struct ath5k_softc *sc); -static void ath5k_beacon_config(struct ath5k_softc *sc); -static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); -static void ath5k_tasklet_beacon(unsigned long data); - -static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) -{ - u64 tsf = ath5k_hw_get_tsf64(ah); - - if ((tsf & 0x7fff) < rstamp) - tsf -= 0x8000; - - return (tsf & ~0x7fff) | rstamp; -} - -/* Interrupt handling */ -static int ath5k_init(struct ath5k_softc *sc); -static int ath5k_stop_locked(struct ath5k_softc *sc); -static int ath5k_stop_hw(struct ath5k_softc *sc); -static irqreturn_t ath5k_intr(int irq, void *dev_id); -static void ath5k_tasklet_reset(unsigned long data); - -static void ath5k_calibrate(unsigned long data); - -/* - * Module init/exit functions - */ -static int __init -init_ath5k_pci(void) -{ - int ret; - - ath5k_debug_init(); - - ret = pci_register_driver(&ath5k_pci_driver); - if (ret) { - printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); - return ret; - } - - return 0; -} - -static void __exit -exit_ath5k_pci(void) -{ - pci_unregister_driver(&ath5k_pci_driver); - - ath5k_debug_finish(); -} - -module_init(init_ath5k_pci); -module_exit(exit_ath5k_pci); - - -/********************\ -* PCI Initialization * -\********************/ - -static const char * -ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) -{ - const char *name = "xxxxx"; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(srev_names); i++) { - if (srev_names[i].sr_type != type) - continue; - - if ((val & 0xf0) == srev_names[i].sr_val) - name = srev_names[i].sr_name; - - if ((val & 0xff) == srev_names[i].sr_val) { - name = srev_names[i].sr_name; - break; - } - } - - return name; -} - -static int __devinit -ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath5k_softc *sc; - struct ieee80211_hw *hw; - int ret; - u8 csz; - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "can't enable device\n"); - goto err; - } - - /* XXX 32-bit addressing only */ - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&pdev->dev, "32-bit DMA not available\n"); - goto err_dis; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES / sizeof(u32); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_write_config_byte(pdev, 0x41, 0); - - ret = pci_request_region(pdev, 0, "ath5k"); - if (ret) { - dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); - goto err_dis; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; - ret = -EIO; - goto err_reg; - } - - /* - * Allocate hw (mac80211 main struct) - * and hw->priv (driver private data) - */ - hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); - ret = -ENOMEM; - goto err_map; - } - - dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); - - /* Initialize driver private data */ - SET_IEEE80211_DEV(hw, &pdev->dev); - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->extra_tx_headroom = 2; - hw->channel_change_time = 5000; - sc = hw->priv; - sc->hw = hw; - sc->pdev = pdev; - - ath5k_debug_init_device(sc); - - /* - * Mark the device as detached to avoid processing - * interrupts until setup is complete. - */ - __set_bit(ATH_STAT_INVALID, sc->status); - - sc->iobase = mem; /* So we can unmap it on detach */ - sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ - sc->opmode = NL80211_IFTYPE_STATION; - mutex_init(&sc->lock); - spin_lock_init(&sc->rxbuflock); - spin_lock_init(&sc->txbuflock); - spin_lock_init(&sc->block); - - /* Set private data */ - pci_set_drvdata(pdev, hw); - - /* Setup interrupt handler */ - ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (ret) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_free; - } - - /* Initialize device */ - sc->ah = ath5k_hw_attach(sc, id->driver_data); - if (IS_ERR(sc->ah)) { - ret = PTR_ERR(sc->ah); - goto err_irq; - } - - /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { - hw->max_rates = 4; - hw->max_rate_tries = 11; - } - - /* Finish private driver data initialization */ - ret = ath5k_attach(pdev, hw); - if (ret) - goto err_ah; - - ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), - sc->ah->ah_mac_srev, - sc->ah->ah_phy_revision); - - if (!sc->ah->ah_single_chip) { - /* Single chip radio (!RF5111) */ - if (sc->ah->ah_radio_5ghz_revision && - !sc->ah->ah_radio_2ghz_revision) { - /* No 5GHz support -> report 2GHz radio */ - if (!test_bit(AR5K_MODE_11A, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* No 2GHz support (5110 and some - * 5Ghz only cards) -> report 5Ghz radio */ - } else if (!test_bit(AR5K_MODE_11B, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* Multiband radio */ - } else { - ATH5K_INFO(sc, "RF%s multiband radio found" - " (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - } - } - /* Multi chip radio (RF5111 - RF2111) -> - * report both 2GHz/5GHz radios */ - else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision){ - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); - } - } - - - /* ready to process interrupts */ - __clear_bit(ATH_STAT_INVALID, sc->status); - - return 0; -err_ah: - ath5k_hw_detach(sc->ah); -err_irq: - free_irq(pdev->irq, sc); -err_free: - ieee80211_free_hw(hw); -err_map: - pci_iounmap(pdev, mem); -err_reg: - pci_release_region(pdev, 0); -err_dis: - pci_disable_device(pdev); -err: - return ret; -} - -static void __devexit -ath5k_pci_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; - - ath5k_debug_finish_device(sc); - ath5k_detach(pdev, hw); - ath5k_hw_detach(sc->ah); - free_irq(pdev->irq, sc); - pci_iounmap(pdev, sc->iobase); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - ieee80211_free_hw(hw); -} - -#ifdef CONFIG_PM -static int -ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; - - ath5k_led_off(sc); - - free_irq(pdev->irq, sc); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int -ath5k_pci_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; - int err; - - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) - return err; - - err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (err) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_no_irq; - } - - ath5k_led_enable(sc); - return 0; - -err_no_irq: - pci_disable_device(pdev); - return err; -} -#endif /* CONFIG_PM */ - - -/***********************\ -* Driver Initialization * -\***********************/ - -static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath5k_softc *sc = hw->priv; - struct ath_regulatory *reg = &sc->ah->ah_regulatory; - - return ath_reg_notifier_apply(wiphy, request, reg); -} - -static int -ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - u8 mac[ETH_ALEN] = {}; - int ret; - - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); - - /* - * Check if the MAC has multi-rate retry support. - * We do this by trying to setup a fake extended - * descriptor. MAC's that don't have support will - * return false w/o doing anything. MAC's that do - * support it will return true w/o doing anything. - */ - ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); - if (ret < 0) - goto err; - if (ret > 0) - __set_bit(ATH_STAT_MRRETRY, sc->status); - - /* - * Collect the channel list. The 802.11 layer - * is resposible for filtering this list based - * on settings like the phy mode and regulatory - * domain restrictions. - */ - ret = ath5k_setup_bands(hw); - if (ret) { - ATH5K_ERR(sc, "can't get channels\n"); - goto err; - } - - /* NB: setup here so ath5k_rate_update is happy */ - if (test_bit(AR5K_MODE_11A, ah->ah_modes)) - ath5k_setcurmode(sc, AR5K_MODE_11A); - else - ath5k_setcurmode(sc, AR5K_MODE_11B); - - /* - * Allocate tx+rx descriptors and populate the lists. - */ - ret = ath5k_desc_alloc(sc, pdev); - if (ret) { - ATH5K_ERR(sc, "can't allocate descriptors\n"); - goto err; - } - - /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS - * priority. Note that hw functions handle reseting - * these queues at the needed time. - */ - ret = ath5k_beaconq_setup(ah); - if (ret < 0) { - ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); - goto err_desc; - } - sc->bhalq = ret; - - sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); - if (IS_ERR(sc->txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(sc->txq); - goto err_bhal; - } - - tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); - tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); - tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); - tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); - setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); - - ret = ath5k_eeprom_read_mac(ah, mac); - if (ret) { - ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", - sc->pdev->device); - goto err_queues; - } - - SET_IEEE80211_PERM_ADDR(hw, mac); - /* All MAC address bits matter for ACKs */ - memset(sc->bssidmask, 0xff, ETH_ALEN); - ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); - - ah->ah_regulatory.current_rd = - ah->ah_capabilities.cap_eeprom.ee_regdomain; - ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); - if (ret) { - ATH5K_ERR(sc, "can't initialize regulatory system\n"); - goto err_queues; - } - - ret = ieee80211_register_hw(hw); - if (ret) { - ATH5K_ERR(sc, "can't register ieee80211 hw\n"); - goto err_queues; - } - - if (!ath_is_world_regd(&sc->ah->ah_regulatory)) - regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); - - ath5k_init_leds(sc); - - return 0; -err_queues: - ath5k_txq_release(sc); -err_bhal: - ath5k_hw_release_tx_queue(ah, sc->bhalq); -err_desc: - ath5k_desc_free(sc, pdev); -err: - return ret; -} - -static void -ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - /* - * NB: the order of these is important: - * o call the 802.11 layer before detaching ath5k_hw to - * insure callbacks into the driver to delete global - * key cache entries can be handled - * o reclaim the tx queue data structures after calling - * the 802.11 layer as we'll get called back to reclaim - * node state and potentially want to use them - * o to cleanup the tx queues the hal is called, so detach - * it last - * XXX: ??? detach ath5k_hw ??? - * Other than that, it's straightforward... - */ - ieee80211_unregister_hw(hw); - ath5k_desc_free(sc, pdev); - ath5k_txq_release(sc); - ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); - ath5k_unregister_leds(sc); - - /* - * NB: can't reclaim these until after ieee80211_ifdetach - * returns because we'll get called back to reclaim node - * state and potentially want to use them. - */ -} - - - - -/********************\ -* Channel/mode setup * -\********************/ - -/* - * Convert IEEE channel number to MHz frequency. - */ -static inline short -ath5k_ieee2mhz(short chan) -{ - if (chan <= 14 || chan >= 27) - return ieee80211chan2mhz(chan); - else - return 2212 + chan * 20; -} - -/* - * Returns true for the channel numbers used without all_channels modparam. - */ -static bool ath5k_is_standard_channel(short chan) -{ - return ((chan <= 14) || - /* UNII 1,2 */ - ((chan & 3) == 0 && chan >= 36 && chan <= 64) || - /* midband */ - ((chan & 3) == 0 && chan >= 100 && chan <= 140) || - /* UNII-3 */ - ((chan & 3) == 1 && chan >= 149 && chan <= 165)); -} - -static unsigned int -ath5k_copy_channels(struct ath5k_hw *ah, - struct ieee80211_channel *channels, - unsigned int mode, - unsigned int max) -{ - unsigned int i, count, size, chfreq, freq, ch; - - if (!test_bit(mode, ah->ah_modes)) - return 0; - - switch (mode) { - case AR5K_MODE_11A: - case AR5K_MODE_11A_TURBO: - /* 1..220, but 2GHz frequencies are filtered by check_channel */ - size = 220 ; - chfreq = CHANNEL_5GHZ; - break; - case AR5K_MODE_11B: - case AR5K_MODE_11G: - case AR5K_MODE_11G_TURBO: - size = 26; - chfreq = CHANNEL_2GHZ; - break; - default: - ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); - return 0; - } - - for (i = 0, count = 0; i < size && max > 0; i++) { - ch = i + 1 ; - freq = ath5k_ieee2mhz(ch); - - /* Check if channel is supported by the chipset */ - if (!ath5k_channel_ok(ah, freq, chfreq)) - continue; - - if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) - continue; - - /* Write channel info and increment counter */ - channels[count].center_freq = freq; - channels[count].band = (chfreq == CHANNEL_2GHZ) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - switch (mode) { - case AR5K_MODE_11A: - case AR5K_MODE_11G: - channels[count].hw_value = chfreq | CHANNEL_OFDM; - break; - case AR5K_MODE_11A_TURBO: - case AR5K_MODE_11G_TURBO: - channels[count].hw_value = chfreq | - CHANNEL_OFDM | CHANNEL_TURBO; - break; - case AR5K_MODE_11B: - channels[count].hw_value = CHANNEL_B; - } - - count++; - max--; - } - - return count; -} - -static void -ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b) -{ - u8 i; - - for (i = 0; i < AR5K_MAX_RATES; i++) - sc->rate_idx[b->band][i] = -1; - - for (i = 0; i < b->n_bitrates; i++) { - sc->rate_idx[b->band][b->bitrates[i].hw_value] = i; - if (b->bitrates[i].hw_value_short) - sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i; - } -} - -static int -ath5k_setup_bands(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ieee80211_supported_band *sband; - int max_c, count_c = 0; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS); - max_c = ARRAY_SIZE(sc->channels); - - /* 2GHz band */ - sband = &sc->sbands[IEEE80211_BAND_2GHZ]; - sband->band = IEEE80211_BAND_2GHZ; - sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0]; - - if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) { - /* G mode */ - memcpy(sband->bitrates, &ath5k_rates[0], - sizeof(struct ieee80211_rate) * 12); - sband->n_bitrates = 12; - - sband->channels = sc->channels; - sband->n_channels = ath5k_copy_channels(ah, sband->channels, - AR5K_MODE_11G, max_c); - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - count_c = sband->n_channels; - max_c -= count_c; - } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) { - /* B mode */ - memcpy(sband->bitrates, &ath5k_rates[0], - sizeof(struct ieee80211_rate) * 4); - sband->n_bitrates = 4; - - /* 5211 only supports B rates and uses 4bit rate codes - * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B) - * fix them up here: - */ - if (ah->ah_version == AR5K_AR5211) { - for (i = 0; i < 4; i++) { - sband->bitrates[i].hw_value = - sband->bitrates[i].hw_value & 0xF; - sband->bitrates[i].hw_value_short = - sband->bitrates[i].hw_value_short & 0xF; - } - } - - sband->channels = sc->channels; - sband->n_channels = ath5k_copy_channels(ah, sband->channels, - AR5K_MODE_11B, max_c); - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - count_c = sband->n_channels; - max_c -= count_c; - } - ath5k_setup_rate_idx(sc, sband); - - /* 5GHz band, A mode */ - if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) { - sband = &sc->sbands[IEEE80211_BAND_5GHZ]; - sband->band = IEEE80211_BAND_5GHZ; - sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0]; - - memcpy(sband->bitrates, &ath5k_rates[4], - sizeof(struct ieee80211_rate) * 8); - sband->n_bitrates = 8; - - sband->channels = &sc->channels[count_c]; - sband->n_channels = ath5k_copy_channels(ah, sband->channels, - AR5K_MODE_11A, max_c); - - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; - } - ath5k_setup_rate_idx(sc, sband); - - ath5k_debug_dump_bands(sc); - - return 0; -} - -/* - * Set/change channels. If the channel is really being changed, - * it's done by reseting the chip. To accomplish this we must - * first cleanup any pending DMA, then restart stuff after a la - * ath5k_init. - * - * Called with sc->lock. - */ -static int -ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) -{ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", - sc->curchan->center_freq, chan->center_freq); - - if (chan->center_freq != sc->curchan->center_freq || - chan->hw_value != sc->curchan->hw_value) { - - sc->curchan = chan; - sc->curband = &sc->sbands[chan->band]; - - /* - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the - * hardware at the new frequency, and then re-enable - * the relevant bits of the h/w. - */ - return ath5k_reset(sc, true, true); - } - - return 0; -} - -static void -ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) -{ - sc->curmode = mode; - - if (mode == AR5K_MODE_11A) { - sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; - } else { - sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; - } -} - -static void -ath5k_mode_setup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - u32 rfilt; - - /* configure rx filter */ - rfilt = sc->filter_flags; - ath5k_hw_set_rx_filter(ah, rfilt); - - if (ath5k_hw_hasbssidmask(ah)) - ath5k_hw_set_bssid_mask(ah, sc->bssidmask); - - /* configure operational mode */ - ath5k_hw_set_opmode(ah); - - ath5k_hw_set_mcast_filter(ah, 0, 0); - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); -} - -static inline int -ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) -{ - int rix; - - /* return base rate on errors */ - if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES, - "hw_rix out of bounds: %x\n", hw_rix)) - return 0; - - rix = sc->rate_idx[sc->curband->band][hw_rix]; - if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) - rix = 0; - - return rix; -} - -/***************\ -* Buffers setup * -\***************/ - -static -struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) -{ - struct sk_buff *skb; - unsigned int off; - - /* - * Allocate buffer with headroom_needed space for the - * fake physical layer header at the start. - */ - skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); - - if (!skb) { - ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", - sc->rxbufsize + sc->cachelsz - 1); - return NULL; - } - /* - * Cache-line-align. This is important (for the - * 5210 at least) as not doing so causes bogus data - * in rx'd frames. - */ - off = ((unsigned long)skb->data) % sc->cachelsz; - if (off != 0) - skb_reserve(skb, sc->cachelsz - off); - - *skb_addr = pci_map_single(sc->pdev, - skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { - ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); - dev_kfree_skb(skb); - return NULL; - } - return skb; -} - -static int -ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct ath5k_hw *ah = sc->ah; - struct sk_buff *skb = bf->skb; - struct ath5k_desc *ds; - - if (!skb) { - skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); - if (!skb) - return -ENOMEM; - bf->skb = skb; - } - - /* - * Setup descriptors. For receive we always terminate - * the descriptor list with a self-linked entry so we'll - * not get overrun under high load (as can happen with a - * 5212 when ANI processing enables PHY error frames). - * - * To insure the last descriptor is self-linked we create - * each descriptor as self-linked and add it to the end. As - * each additional descriptor is added the previous self-linked - * entry is ``fixed'' naturally. This should be safe even - * if DMA is happening. When processing RX interrupts we - * never remove/process the last, self-linked, entry on the - * descriptor list. This insures the hardware always has - * someplace to write a new frame. - */ - ds = bf->desc; - ds->ds_link = bf->daddr; /* link to self */ - ds->ds_data = bf->skbaddr; - ah->ah_setup_rx_desc(ah, ds, - skb_tailroom(skb), /* buffer size */ - 0); - - if (sc->rxlink != NULL) - *sc->rxlink = bf->daddr; - sc->rxlink = &ds->ds_link; - return 0; -} - -static int -ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_txq *txq = sc->txq; - struct ath5k_desc *ds = bf->desc; - struct sk_buff *skb = bf->skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; - struct ieee80211_rate *rate; - unsigned int mrr_rate[3], mrr_tries[3]; - int i, ret; - u16 hw_rate; - u16 cts_rate = 0; - u16 duration = 0; - u8 rc_flags; - - flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; - - /* XXX endianness */ - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - - rate = ieee80211_get_tx_rate(sc->hw, info); - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - flags |= AR5K_TXDESC_NOACK; - - rc_flags = info->control.rates[0].flags; - hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? - rate->hw_value_short : rate->hw_value; - - pktlen = skb->len; - - /* FIXME: If we are in g mode and rate is a CCK rate - * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta - * from tx power (value is in dB units already) */ - if (info->control.hw_key) { - keyidx = info->control.hw_key->hw_key_idx; - pktlen += info->control.hw_key->icv_len; - } - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - flags |= AR5K_TXDESC_RTSENA; - cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; - duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, - sc->vif, pktlen, info)); - } - if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - flags |= AR5K_TXDESC_CTSENA; - cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; - duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, - sc->vif, pktlen, info)); - } - ret = ah->ah_setup_tx_desc(ah, ds, pktlen, - ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, - (sc->power_level * 2), - hw_rate, - info->control.rates[0].count, keyidx, 0, flags, - cts_rate, duration); - if (ret) - goto err_unmap; - - memset(mrr_rate, 0, sizeof(mrr_rate)); - memset(mrr_tries, 0, sizeof(mrr_tries)); - for (i = 0; i < 3; i++) { - rate = ieee80211_get_alt_retry_rate(sc->hw, info, i); - if (!rate) - break; - - mrr_rate[i] = rate->hw_value; - mrr_tries[i] = info->control.rates[i + 1].count; - } - - ah->ah_setup_mrr_tx_desc(ah, ds, - mrr_rate[0], mrr_tries[0], - mrr_rate[1], mrr_tries[1], - mrr_rate[2], mrr_tries[2]); - - ds->ds_link = 0; - ds->ds_data = bf->skbaddr; - - spin_lock_bh(&txq->lock); - list_add_tail(&bf->list, &txq->q); - sc->tx_stats[txq->qnum].len++; - if (txq->link == NULL) /* is this first packet? */ - ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); - else /* no, so only link it */ - *txq->link = bf->daddr; - - txq->link = &ds->ds_link; - ath5k_hw_start_tx_dma(ah, txq->qnum); - mmiowb(); - spin_unlock_bh(&txq->lock); - - return 0; -err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); - return ret; -} - -/*******************\ -* Descriptors setup * -\*******************/ - -static int -ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) -{ - struct ath5k_desc *ds; - struct ath5k_buf *bf; - dma_addr_t da; - unsigned int i; - int ret; - - /* allocate descriptors */ - sc->desc_len = sizeof(struct ath5k_desc) * - (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); - sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); - if (sc->desc == NULL) { - ATH5K_ERR(sc, "can't allocate descriptors\n"); - ret = -ENOMEM; - goto err; - } - ds = sc->desc; - da = sc->desc_daddr; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n", - ds, sc->desc_len, (unsigned long long)sc->desc_daddr); - - bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF, - sizeof(struct ath5k_buf), GFP_KERNEL); - if (bf == NULL) { - ATH5K_ERR(sc, "can't allocate bufptr\n"); - ret = -ENOMEM; - goto err_free; - } - sc->bufptr = bf; - - INIT_LIST_HEAD(&sc->rxbuf); - for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) { - bf->desc = ds; - bf->daddr = da; - list_add_tail(&bf->list, &sc->rxbuf); - } - - INIT_LIST_HEAD(&sc->txbuf); - sc->txbuf_len = ATH_TXBUF; - for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, - da += sizeof(*ds)) { - bf->desc = ds; - bf->daddr = da; - list_add_tail(&bf->list, &sc->txbuf); - } - - /* beacon buffer */ - bf->desc = ds; - bf->daddr = da; - sc->bbuf = bf; - - return 0; -err_free: - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); -err: - sc->desc = NULL; - return ret; -} - -static void -ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) -{ - struct ath5k_buf *bf; - - ath5k_txbuf_free(sc, sc->bbuf); - list_for_each_entry(bf, &sc->txbuf, list) - ath5k_txbuf_free(sc, bf); - list_for_each_entry(bf, &sc->rxbuf, list) - ath5k_rxbuf_free(sc, bf); - - /* Free memory associated with all descriptors */ - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); - - kfree(sc->bufptr); - sc->bufptr = NULL; -} - - - - - -/**************\ -* Queues setup * -\**************/ - -static struct ath5k_txq * -ath5k_txq_setup(struct ath5k_softc *sc, - int qtype, int subtype) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_txq *txq; - struct ath5k_txq_info qi = { - .tqi_subtype = subtype, - .tqi_aifs = AR5K_TXQ_USEDEFAULT, - .tqi_cw_min = AR5K_TXQ_USEDEFAULT, - .tqi_cw_max = AR5K_TXQ_USEDEFAULT - }; - int qnum; - - /* - * Enable interrupts only for EOL and DESC conditions. - * We mark tx descriptors to receive a DESC interrupt - * when a tx queue gets deep; otherwise waiting for the - * EOL to reap descriptors. Note that this is done to - * reduce interrupt load and this only defers reaping - * descriptors, never transmitting frames. Aside from - * reducing interrupts this also permits more concurrency. - * The only potential downside is if the tx queue backs - * up in which case the top half of the kernel may backup - * due to a lack of tx descriptors. - */ - qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE | - AR5K_TXQ_FLAG_TXDESCINT_ENABLE; - qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi); - if (qnum < 0) { - /* - * NB: don't print a message, this happens - * normally on parts with too few tx queues - */ - return ERR_PTR(qnum); - } - if (qnum >= ARRAY_SIZE(sc->txqs)) { - ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n", - qnum, ARRAY_SIZE(sc->txqs)); - ath5k_hw_release_tx_queue(ah, qnum); - return ERR_PTR(-EINVAL); - } - txq = &sc->txqs[qnum]; - if (!txq->setup) { - txq->qnum = qnum; - txq->link = NULL; - INIT_LIST_HEAD(&txq->q); - spin_lock_init(&txq->lock); - txq->setup = true; - } - return &sc->txqs[qnum]; -} - -static int -ath5k_beaconq_setup(struct ath5k_hw *ah) -{ - struct ath5k_txq_info qi = { - .tqi_aifs = AR5K_TXQ_USEDEFAULT, - .tqi_cw_min = AR5K_TXQ_USEDEFAULT, - .tqi_cw_max = AR5K_TXQ_USEDEFAULT, - /* NB: for dynamic turbo, don't enable any other interrupts */ - .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE - }; - - return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi); -} - -static int -ath5k_beaconq_config(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_txq_info qi; - int ret; - - ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); - if (ret) - return ret; - if (sc->opmode == NL80211_IFTYPE_AP || - sc->opmode == NL80211_IFTYPE_MESH_POINT) { - /* - * Always burst out beacon and CAB traffic - * (aifs = cwmin = cwmax = 0) - */ - qi.tqi_aifs = 0; - qi.tqi_cw_min = 0; - qi.tqi_cw_max = 0; - } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* - * Adhoc mode; backoff between 0 and (2 * cw_min). - */ - qi.tqi_aifs = 0; - qi.tqi_cw_min = 0; - qi.tqi_cw_max = 2 * ah->ah_cw_min; - } - - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n", - qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max); - - ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi); - if (ret) { - ATH5K_ERR(sc, "%s: unable to update parameters for beacon " - "hardware queue!\n", __func__); - return ret; - } - - return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; -} - -static void -ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) -{ - struct ath5k_buf *bf, *bf0; - - /* - * NB: this assumes output has been stopped and - * we do not need to block ath5k_tx_tasklet - */ - spin_lock_bh(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf); - - ath5k_txbuf_free(sc, bf); - - spin_lock_bh(&sc->txbuflock); - sc->tx_stats[txq->qnum].len--; - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock_bh(&sc->txbuflock); - } - txq->link = NULL; - spin_unlock_bh(&txq->lock); -} - -/* - * Drain the transmit queues and reclaim resources. - */ -static void -ath5k_txq_cleanup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned int i; - - /* XXX return value */ - if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { - /* don't touch the hardware if marked invalid */ - ath5k_hw_stop_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", - ath5k_hw_get_txdp(ah, sc->bhalq)); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) { - ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " - "link %p\n", - sc->txqs[i].qnum, - ath5k_hw_get_txdp(ah, - sc->txqs[i].qnum), - sc->txqs[i].link); - } - } - ieee80211_wake_queues(sc->hw); /* XXX move to callers */ - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) - ath5k_txq_drainq(sc, &sc->txqs[i]); -} - -static void -ath5k_txq_release(struct ath5k_softc *sc) -{ - struct ath5k_txq *txq = sc->txqs; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++) - if (txq->setup) { - ath5k_hw_release_tx_queue(sc->ah, txq->qnum); - txq->setup = false; - } -} - - - - -/*************\ -* RX Handling * -\*************/ - -/* - * Enable the receive h/w following a reset. - */ -static int -ath5k_rx_start(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_buf *bf; - int ret; - - sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz); - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", - sc->cachelsz, sc->rxbufsize); - - sc->rxlink = NULL; - - spin_lock_bh(&sc->rxbuflock); - list_for_each_entry(bf, &sc->rxbuf, list) { - ret = ath5k_rxbuf_setup(sc, bf); - if (ret != 0) { - spin_unlock_bh(&sc->rxbuflock); - goto err; - } - } - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); - spin_unlock_bh(&sc->rxbuflock); - - ath5k_hw_set_rxdp(ah, bf->daddr); - ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ - ath5k_mode_setup(sc); /* set filters, etc. */ - ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ - - return 0; -err: - return ret; -} - -/* - * Disable the receive h/w in preparation for a reset. - */ -static void -ath5k_rx_stop(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - - ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ - ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ - ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ - - ath5k_debug_printrxbuffs(sc, ah); - - sc->rxlink = NULL; /* just in case */ -} - -static unsigned int -ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, - struct sk_buff *skb, struct ath5k_rx_status *rs) -{ - struct ieee80211_hdr *hdr = (void *)skb->data; - unsigned int keyix, hlen; - - if (!(rs->rs_status & AR5K_RXERR_DECRYPT) && - rs->rs_keyix != AR5K_RXKEYIX_INVALID) - return RX_FLAG_DECRYPTED; - - /* Apparently when a default key is used to decrypt the packet - the hw does not set the index used to decrypt. In such cases - get the index from the packet. */ - hlen = ieee80211_hdrlen(hdr->frame_control); - if (ieee80211_has_protected(hdr->frame_control) && - !(rs->rs_status & AR5K_RXERR_DECRYPT) && - skb->len >= hlen + 4) { - keyix = skb->data[hlen + 3] >> 6; - - if (test_bit(keyix, sc->keymap)) - return RX_FLAG_DECRYPTED; - } - - return 0; -} - - -static void -ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, - struct ieee80211_rx_status *rxs) -{ - u64 tsf, bc_tstamp; - u32 hw_tu; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - - if (ieee80211_is_beacon(mgmt->frame_control) && - le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && - memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { - /* - * Received an IBSS beacon with the same BSSID. Hardware *must* - * have updated the local TSF. We have to work around various - * hardware bugs, though... - */ - tsf = ath5k_hw_get_tsf64(sc->ah); - bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp); - hw_tu = TSF_TO_TU(tsf); - - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", - (unsigned long long)bc_tstamp, - (unsigned long long)rxs->mactime, - (unsigned long long)(rxs->mactime - bc_tstamp), - (unsigned long long)tsf); - - /* - * Sometimes the HW will give us a wrong tstamp in the rx - * status, causing the timestamp extension to go wrong. - * (This seems to happen especially with beacon frames bigger - * than 78 byte (incl. FCS)) - * But we know that the receive timestamp must be later than the - * timestamp of the beacon since HW must have synced to that. - * - * NOTE: here we assume mactime to be after the frame was - * received, not like mac80211 which defines it at the start. - */ - if (bc_tstamp > rxs->mactime) { - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "fixing mactime from %llx to %llx\n", - (unsigned long long)rxs->mactime, - (unsigned long long)tsf); - rxs->mactime = tsf; - } - - /* - * Local TSF might have moved higher than our beacon timers, - * in that case we have to update them to continue sending - * beacons. This also takes care of synchronizing beacon sending - * times with other stations. - */ - if (hw_tu >= sc->nexttbtt) - ath5k_beacon_update_timers(sc, bc_tstamp); - } -} - -static void ath5k_tasklet_beacon(unsigned long data) -{ - struct ath5k_softc *sc = (struct ath5k_softc *) data; - - /* - * Software beacon alert--time to send a beacon. - * - * In IBSS mode we use this interrupt just to - * keep track of the next TBTT (target beacon - * transmission time) in order to detect wether - * automatic TSF updates happened. - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* XXX: only if VEOL suppported */ - u64 tsf = ath5k_hw_get_tsf64(sc->ah); - sc->nexttbtt += sc->bintval; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "SWBA nexttbtt: %x hw_tu: %x " - "TSF: %llx\n", - sc->nexttbtt, - TSF_TO_TU(tsf), - (unsigned long long) tsf); - } else { - spin_lock(&sc->block); - ath5k_beacon_send(sc); - spin_unlock(&sc->block); - } -} - -static void -ath5k_tasklet_rx(unsigned long data) -{ - struct ieee80211_rx_status rxs = {}; - struct ath5k_rx_status rs = {}; - struct sk_buff *skb, *next_skb; - dma_addr_t next_skb_addr; - struct ath5k_softc *sc = (void *)data; - struct ath5k_buf *bf, *bf_last; - struct ath5k_desc *ds; - int ret; - int hdrlen; - int padsize; - - spin_lock(&sc->rxbuflock); - if (list_empty(&sc->rxbuf)) { - ATH5K_WARN(sc, "empty rx buf pool\n"); - goto unlock; - } - bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); - do { - rxs.flag = 0; - - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); - BUG_ON(bf->skb == NULL); - skb = bf->skb; - ds = bf->desc; - - /* - * last buffer must not be freed to ensure proper hardware - * function. When the hardware finishes also a packet next to - * it, we are sure, it doesn't use it anymore and we can go on. - */ - if (bf_last == bf) - bf->flags |= 1; - if (bf->flags) { - struct ath5k_buf *bf_next = list_entry(bf->list.next, - struct ath5k_buf, list); - ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, - &rs); - if (ret) - break; - bf->flags &= ~1; - /* skip the overwritten one (even status is martian) */ - goto next; - } - - ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); - if (unlikely(ret == -EINPROGRESS)) - break; - else if (unlikely(ret)) { - ATH5K_ERR(sc, "error in processing rx descriptor\n"); - spin_unlock(&sc->rxbuflock); - return; - } - - if (unlikely(rs.rs_more)) { - ATH5K_WARN(sc, "unsupported jumbo\n"); - goto next; - } - - if (unlikely(rs.rs_status)) { - if (rs.rs_status & AR5K_RXERR_PHY) - goto next; - if (rs.rs_status & AR5K_RXERR_DECRYPT) { - /* - * Decrypt error. If the error occurred - * because there was no hardware key, then - * let the frame through so the upper layers - * can process it. This is necessary for 5210 - * parts which have no way to setup a ``clear'' - * key cache entry. - * - * XXX do key cache faulting - */ - if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && - !(rs.rs_status & AR5K_RXERR_CRC)) - goto accept; - } - if (rs.rs_status & AR5K_RXERR_MIC) { - rxs.flag |= RX_FLAG_MMIC_ERROR; - goto accept; - } - - /* let crypto-error packets fall through in MNTR */ - if ((rs.rs_status & - ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || - sc->opmode != NL80211_IFTYPE_MONITOR) - goto next; - } -accept: - next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); - - /* - * If we can't replace bf->skb with a new skb under memory - * pressure, just skip this packet - */ - if (!next_skb) - goto next; - - pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, - PCI_DMA_FROMDEVICE); - skb_put(skb, rs.rs_datalen); - - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - hdrlen % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = ath5k_pad_size(hdrlen); - if (padsize) { - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - /* - * always extend the mac timestamp, since this information is - * also needed for proper IBSS merging. - * - * XXX: it might be too late to do it here, since rs_tstamp is - * 15bit only. that means TSF extension has to be done within - * 32768usec (about 32ms). it might be necessary to move this to - * the interrupt handler, like it is done in madwifi. - * - * Unfortunately we don't know when the hardware takes the rx - * timestamp (beginning of phy frame, data frame, end of rx?). - * The only thing we know is that it is hardware specific... - * On AR5213 it seems the rx timestamp is at the end of the - * frame, but i'm not sure. - * - * NOTE: mac80211 defines mactime at the beginning of the first - * data symbol. Since we don't have any time references it's - * impossible to comply to that. This affects IBSS merge only - * right now, so it's not too bad... - */ - rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); - rxs.flag |= RX_FLAG_TSFT; - - rxs.freq = sc->curchan->center_freq; - rxs.band = sc->curband->band; - - rxs.noise = sc->ah->ah_noise_floor; - rxs.signal = rxs.noise + rs.rs_rssi; - - /* An rssi of 35 indicates you should be able use - * 54 Mbps reliably. A more elaborate scheme can be used - * here but it requires a map of SNR/throughput for each - * possible mode used */ - rxs.qual = rs.rs_rssi * 100 / 35; - - /* rssi can be more than 35 though, anything above that - * should be considered at 100% */ - if (rxs.qual > 100) - rxs.qual = 100; - - rxs.antenna = rs.rs_antenna; - rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); - rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); - - if (rxs.rate_idx >= 0 && rs.rs_rate == - sc->curband->bitrates[rxs.rate_idx].hw_value_short) - rxs.flag |= RX_FLAG_SHORTPRE; - - ath5k_debug_dump_skb(sc, skb, "RX ", 0); - - /* check beacons in IBSS mode */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_check_ibss_tsf(sc, skb, &rxs); - - __ieee80211_rx(sc->hw, skb, &rxs); - - bf->skb = next_skb; - bf->skbaddr = next_skb_addr; -next: - list_move_tail(&bf->list, &sc->rxbuf); - } while (ath5k_rxbuf_setup(sc, bf) == 0); -unlock: - spin_unlock(&sc->rxbuflock); -} - - - - -/*************\ -* TX Handling * -\*************/ - -static void -ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) -{ - struct ath5k_tx_status ts = {}; - struct ath5k_buf *bf, *bf0; - struct ath5k_desc *ds; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - int i, ret; - - spin_lock(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ds = bf->desc; - - ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); - if (unlikely(ret == -EINPROGRESS)) - break; - else if (unlikely(ret)) { - ATH5K_ERR(sc, "error %d while processing queue %u\n", - ret, txq->qnum); - break; - } - - skb = bf->skb; - info = IEEE80211_SKB_CB(skb); - bf->skb = NULL; - - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, - PCI_DMA_TODEVICE); - - ieee80211_tx_info_clear_status(info); - for (i = 0; i < 4; i++) { - struct ieee80211_tx_rate *r = - &info->status.rates[i]; - - if (ts.ts_rate[i]) { - r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); - r->count = ts.ts_retry[i]; - } else { - r->idx = -1; - r->count = 0; - } - } - - /* count the successful attempt as well */ - info->status.rates[ts.ts_final_idx].count++; - - if (unlikely(ts.ts_status)) { - sc->ll_stats.dot11ACKFailureCount++; - if (ts.ts_status & AR5K_TXERR_FILT) - info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - } else { - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.ack_signal = ts.ts_rssi; - } - - ieee80211_tx_status(sc->hw, skb); - sc->tx_stats[txq->qnum].count++; - - spin_lock(&sc->txbuflock); - sc->tx_stats[txq->qnum].len--; - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock(&sc->txbuflock); - } - if (likely(list_empty(&txq->q))) - txq->link = NULL; - spin_unlock(&txq->lock); - if (sc->txbuf_len > ATH_TXBUF / 5) - ieee80211_wake_queues(sc->hw); -} - -static void -ath5k_tasklet_tx(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - - ath5k_tx_processq(sc, sc->txq); -} - - -/*****************\ -* Beacon handling * -\*****************/ - -/* - * Setup the beacon frame for transmit. - */ -static int -ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct sk_buff *skb = bf->skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath5k_hw *ah = sc->ah; - struct ath5k_desc *ds; - int ret, antenna = 0; - u32 flags; - - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " - "skbaddr %llx\n", skb, skb->data, skb->len, - (unsigned long long)bf->skbaddr); - if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { - ATH5K_ERR(sc, "beacon DMA mapping failed\n"); - return -EIO; - } - - ds = bf->desc; - - flags = AR5K_TXDESC_NOACK; - if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { - ds->ds_link = bf->daddr; /* self-linked */ - flags |= AR5K_TXDESC_VEOL; - /* - * Let hardware handle antenna switching if txantenna is not set - */ - } else { - ds->ds_link = 0; - /* - * Switch antenna every 4 beacons if txantenna is not set - * XXX assumes two antennas - */ - if (antenna == 0) - antenna = sc->bsent & 4 ? 2 : 1; - } - - /* FIXME: If we are in g mode and rate is a CCK rate - * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta - * from tx power (value is in dB units already) */ - ds->ds_data = bf->skbaddr; - ret = ah->ah_setup_tx_desc(ah, ds, skb->len, - ieee80211_get_hdrlen_from_skb(skb), - AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), - ieee80211_get_tx_rate(sc->hw, info)->hw_value, - 1, AR5K_TXKEYIX_INVALID, - antenna, flags, 0, 0); - if (ret) - goto err_unmap; - - return 0; -err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); - return ret; -} - -/* - * Transmit a beacon frame at SWBA. Dynamic updates to the - * frame contents are done as needed and the slot time is - * also adjusted based on current state. - * - * This is called from software irq context (beacontq or restq - * tasklets) or user context from ath5k_beacon_config. - */ -static void -ath5k_beacon_send(struct ath5k_softc *sc) -{ - struct ath5k_buf *bf = sc->bbuf; - struct ath5k_hw *ah = sc->ah; - - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); - - if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_MONITOR)) { - ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); - return; - } - /* - * Check if the previous beacon has gone out. If - * not don't don't try to post another, skip this - * period and wait for the next. Missed beacons - * indicate a problem and should not occur. If we - * miss too many consecutive beacons reset the device. - */ - if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { - sc->bmisscount++; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "missed %u consecutive beacons\n", sc->bmisscount); - if (sc->bmisscount > 3) { /* NB: 3 is a guess */ - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "stuck beacon time (%u missed)\n", - sc->bmisscount); - tasklet_schedule(&sc->restq); - } - return; - } - if (unlikely(sc->bmisscount != 0)) { - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "resume beacon xmit after %u misses\n", - sc->bmisscount); - sc->bmisscount = 0; - } - - /* - * Stop any current dma and put the new frame on the queue. - * This should never fail since we check above that no frames - * are still pending on the queue. - */ - if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { - ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); - /* NB: hw still stops DMA, so proceed */ - } - - ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); - ath5k_hw_start_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", - sc->bhalq, (unsigned long long)bf->daddr, bf->desc); - - sc->bsent++; -} - - -/** - * ath5k_beacon_update_timers - update beacon timers - * - * @sc: struct ath5k_softc pointer we are operating on - * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a - * beacon timer update based on the current HW TSF. - * - * Calculate the next target beacon transmit time (TBTT) based on the timestamp - * of a received beacon or the current local hardware TSF and write it to the - * beacon timer registers. - * - * This is called in a variety of situations, e.g. when a beacon is received, - * when a TSF update has been detected, but also when an new IBSS is created or - * when we otherwise know we have to update the timers, but we keep it in this - * function to have it all together in one place. - */ -static void -ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) -{ - struct ath5k_hw *ah = sc->ah; - u32 nexttbtt, intval, hw_tu, bc_tu; - u64 hw_tsf; - - intval = sc->bintval & AR5K_BEACON_PERIOD; - if (WARN_ON(!intval)) - return; - - /* beacon TSF converted to TU */ - bc_tu = TSF_TO_TU(bc_tsf); - - /* current TSF converted to TU */ - hw_tsf = ath5k_hw_get_tsf64(ah); - hw_tu = TSF_TO_TU(hw_tsf); - -#define FUDGE 3 - /* we use FUDGE to make sure the next TBTT is ahead of the current TU */ - if (bc_tsf == -1) { - /* - * no beacons received, called internally. - * just need to refresh timers based on HW TSF. - */ - nexttbtt = roundup(hw_tu + FUDGE, intval); - } else if (bc_tsf == 0) { - /* - * no beacon received, probably called by ath5k_reset_tsf(). - * reset TSF to start with 0. - */ - nexttbtt = intval; - intval |= AR5K_BEACON_RESET_TSF; - } else if (bc_tsf > hw_tsf) { - /* - * beacon received, SW merge happend but HW TSF not yet updated. - * not possible to reconfigure timers yet, but next time we - * receive a beacon with the same BSSID, the hardware will - * automatically update the TSF and then we need to reconfigure - * the timers. - */ - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "need to wait for HW TSF sync\n"); - return; - } else { - /* - * most important case for beacon synchronization between STA. - * - * beacon received and HW TSF has been already updated by HW. - * update next TBTT based on the TSF of the beacon, but make - * sure it is ahead of our local TSF timer. - */ - nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval); - } -#undef FUDGE - - sc->nexttbtt = nexttbtt; - - intval |= AR5K_BEACON_ENA; - ath5k_hw_init_beacon(ah, nexttbtt, intval); - - /* - * debugging output last in order to preserve the time critical aspect - * of this function - */ - if (bc_tsf == -1) - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "reconfigured timers based on HW TSF\n"); - else if (bc_tsf == 0) - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "reset HW TSF and timers\n"); - else - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "updated timers based on beacon TSF\n"); - - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", - (unsigned long long) bc_tsf, - (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt); - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", - intval & AR5K_BEACON_PERIOD, - intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", - intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); -} - - -/** - * ath5k_beacon_config - Configure the beacon queues and interrupts - * - * @sc: struct ath5k_softc pointer we are operating on - * - * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA - * interrupts to detect TSF updates only. - */ -static void -ath5k_beacon_config(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned long flags; - - ath5k_hw_set_imr(ah, 0); - sc->bmisscount = 0; - sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); - - if (sc->opmode == NL80211_IFTYPE_ADHOC || - sc->opmode == NL80211_IFTYPE_MESH_POINT || - sc->opmode == NL80211_IFTYPE_AP) { - /* - * In IBSS mode we use a self-linked tx descriptor and let the - * hardware send the beacons automatically. We have to load it - * only once here. - * We use the SWBA interrupt only to keep track of the beacon - * timers in order to detect automatic TSF updates. - */ - ath5k_beaconq_config(sc); - - sc->imask |= AR5K_INT_SWBA; - - if (sc->opmode == NL80211_IFTYPE_ADHOC) { - if (ath5k_hw_hasveol(ah)) { - spin_lock_irqsave(&sc->block, flags); - ath5k_beacon_send(sc); - spin_unlock_irqrestore(&sc->block, flags); - } - } else - ath5k_beacon_update_timers(sc, -1); - } - - ath5k_hw_set_imr(ah, sc->imask); -} - - -/********************\ -* Interrupt handling * -\********************/ - -static int -ath5k_init(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - int ret, i; - - mutex_lock(&sc->lock); - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); - - /* - * Stop anything previously setup. This is safe - * no matter this is the first time through or not. - */ - ath5k_stop_locked(sc); - - /* - * The basic interface to setting the hardware in a good - * state is ``reset''. On return the hardware is known to - * be powered up and with interrupts disabled. This must - * be followed by initialization of the appropriate bits - * and then setup of the interrupt mask. - */ - sc->curchan = sc->hw->conf.channel; - sc->curband = &sc->sbands[sc->curchan->band]; - sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | - AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | - AR5K_INT_FATAL | AR5K_INT_GLOBAL; - ret = ath5k_reset(sc, false, false); - if (ret) - goto done; - - /* - * Reset the key cache since some parts do not reset the - * contents on initial power up or resume from suspend. - */ - for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) - ath5k_hw_reset_key(ah, i); - - /* Set ack to be sent at low bit-rates */ - ath5k_hw_set_ack_bitrate_high(ah, false); - - mod_timer(&sc->calib_tim, round_jiffies(jiffies + - msecs_to_jiffies(ath5k_calinterval * 1000))); - - ret = 0; -done: - mmiowb(); - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_stop_locked(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", - test_bit(ATH_STAT_INVALID, sc->status)); - - /* - * Shutdown the hardware and driver: - * stop output from above - * disable interrupts - * turn off timers - * turn off the radio - * clear transmit machinery - * clear receive machinery - * drain and release tx queues - * reclaim beacon resources - * power down hardware - * - * Note that some of this work is not possible if the - * hardware is gone (invalid). - */ - ieee80211_stop_queues(sc->hw); - - if (!test_bit(ATH_STAT_INVALID, sc->status)) { - ath5k_led_off(sc); - ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); - } - ath5k_txq_cleanup(sc); - if (!test_bit(ATH_STAT_INVALID, sc->status)) { - ath5k_rx_stop(sc); - ath5k_hw_phy_disable(ah); - } else - sc->rxlink = NULL; - - return 0; -} - -/* - * Stop the device, grabbing the top-level lock to protect - * against concurrent entry through ath5k_init (which can happen - * if another thread does a system call and the thread doing the - * stop is preempted). - */ -static int -ath5k_stop_hw(struct ath5k_softc *sc) -{ - int ret; - - mutex_lock(&sc->lock); - ret = ath5k_stop_locked(sc); - if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { - /* - * Set the chip in full sleep mode. Note that we are - * careful to do this only when bringing the interface - * completely to a stop. When the chip is in this state - * it must be carefully woken up or references to - * registers in the PCI clock domain may freeze the bus - * (and system). This varies by chip and is mostly an - * issue with newer parts that go to sleep more quickly. - */ - if (sc->ah->ah_mac_srev >= 0x78) { - /* - * XXX - * don't put newer MAC revisions > 7.8 to sleep because - * of the above mentioned problems - */ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, " - "not putting device to sleep\n"); - } else { - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, - "putting device to full sleep\n"); - ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0); - } - } - ath5k_txbuf_free(sc, sc->bbuf); - - mmiowb(); - mutex_unlock(&sc->lock); - - del_timer_sync(&sc->calib_tim); - tasklet_kill(&sc->rxtq); - tasklet_kill(&sc->txtq); - tasklet_kill(&sc->restq); - tasklet_kill(&sc->beacontq); - - return ret; -} - -static irqreturn_t -ath5k_intr(int irq, void *dev_id) -{ - struct ath5k_softc *sc = dev_id; - struct ath5k_hw *ah = sc->ah; - enum ath5k_int status; - unsigned int counter = 1000; - - if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || - !ath5k_hw_is_intr_pending(ah))) - return IRQ_NONE; - - do { - ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ - ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", - status, sc->imask); - if (unlikely(status & AR5K_INT_FATAL)) { - /* - * Fatal errors are unrecoverable. - * Typically these are caused by DMA errors. - */ - tasklet_schedule(&sc->restq); - } else if (unlikely(status & AR5K_INT_RXORN)) { - tasklet_schedule(&sc->restq); - } else { - if (status & AR5K_INT_SWBA) { - tasklet_schedule(&sc->beacontq); - } - if (status & AR5K_INT_RXEOL) { - /* - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work at - * least on older hardware revs. - */ - sc->rxlink = NULL; - } - if (status & AR5K_INT_TXURN) { - /* bump tx trigger level */ - ath5k_hw_update_tx_triglevel(ah, true); - } - if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) - tasklet_schedule(&sc->rxtq); - if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC - | AR5K_INT_TXERR | AR5K_INT_TXEOL)) - tasklet_schedule(&sc->txtq); - if (status & AR5K_INT_BMISS) { - /* TODO */ - } - if (status & AR5K_INT_MIB) { - /* - * These stats are also used for ANI i think - * so how about updating them more often ? - */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); - } - } - } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); - - if (unlikely(!counter)) - ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); - - return IRQ_HANDLED; -} - -static void -ath5k_tasklet_reset(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - - ath5k_reset_wake(sc); -} - -/* - * Periodically recalibrate the PHY to account - * for temperature/environment changes. - */ -static void -ath5k_calibrate(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - struct ath5k_hw *ah = sc->ah; - - ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", - ieee80211_frequency_to_channel(sc->curchan->center_freq), - sc->curchan->hw_value); - - if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { - /* - * Rfgain is out of bounds, reset the chip - * to load new gain values. - */ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); - ath5k_reset_wake(sc); - } - if (ath5k_hw_phy_calibrate(ah, sc->curchan)) - ATH5K_ERR(sc, "calibration of channel %u failed\n", - ieee80211_frequency_to_channel( - sc->curchan->center_freq)); - - mod_timer(&sc->calib_tim, round_jiffies(jiffies + - msecs_to_jiffies(ath5k_calinterval * 1000))); -} - - -/********************\ -* Mac80211 functions * -\********************/ - -static int -ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_buf *bf; - unsigned long flags; - int hdrlen; - int padsize; - - ath5k_debug_dump_skb(sc, skb, "TX ", 1); - - if (sc->opmode == NL80211_IFTYPE_MONITOR) - ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); - - /* - * the hardware expects the header padded to 4 byte boundaries - * if this is not the case we add the padding after the header - */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = ath5k_pad_size(hdrlen); - if (padsize) { - - if (skb_headroom(skb) < padsize) { - ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" - " headroom to pad %d\n", hdrlen, padsize); - goto drop_packet; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data+padsize, hdrlen); - } - - spin_lock_irqsave(&sc->txbuflock, flags); - if (list_empty(&sc->txbuf)) { - ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); - spin_unlock_irqrestore(&sc->txbuflock, flags); - ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); - goto drop_packet; - } - bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); - list_del(&bf->list); - sc->txbuf_len--; - if (list_empty(&sc->txbuf)) - ieee80211_stop_queues(hw); - spin_unlock_irqrestore(&sc->txbuflock, flags); - - bf->skb = skb; - - if (ath5k_txbuf_setup(sc, bf)) { - bf->skb = NULL; - spin_lock_irqsave(&sc->txbuflock, flags); - list_add_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock_irqrestore(&sc->txbuflock, flags); - goto drop_packet; - } - return NETDEV_TX_OK; - -drop_packet: - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static int -ath5k_reset(struct ath5k_softc *sc, bool stop, bool change_channel) -{ - struct ath5k_hw *ah = sc->ah; - int ret; - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); - - if (stop) { - ath5k_hw_set_imr(ah, 0); - ath5k_txq_cleanup(sc); - ath5k_rx_stop(sc); - } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true); - if (ret) { - ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); - goto err; - } - - ret = ath5k_rx_start(sc); - if (ret) { - ATH5K_ERR(sc, "can't start recv logic\n"); - goto err; - } - - /* - * Change channels and update the h/w rate map if we're switching; - * e.g. 11a to 11b/g. - * - * We may be doing a reset in response to an ioctl that changes the - * channel so update any state that might change as a result. - * - * XXX needed? - */ -/* ath5k_chan_change(sc, c); */ - - ath5k_beacon_config(sc); - /* intrs are enabled by ath5k_beacon_config */ - - return 0; -err: - return ret; -} - -static int -ath5k_reset_wake(struct ath5k_softc *sc) -{ - int ret; - - ret = ath5k_reset(sc, true, true); - if (!ret) - ieee80211_wake_queues(sc->hw); - - return ret; -} - -static int ath5k_start(struct ieee80211_hw *hw) -{ - return ath5k_init(hw->priv); -} - -static void ath5k_stop(struct ieee80211_hw *hw) -{ - ath5k_stop_hw(hw->priv); -} - -static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath5k_softc *sc = hw->priv; - int ret; - - mutex_lock(&sc->lock); - if (sc->vif) { - ret = 0; - goto end; - } - - sc->vif = conf->vif; - - switch (conf->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_MONITOR: - sc->opmode = conf->type; - break; - default: - ret = -EOPNOTSUPP; - goto end; - } - - /* Set to a reasonable value. Note that this will - * be set to mac80211's value at ath5k_config(). */ - sc->bintval = 1000; - ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); - - ret = 0; -end: - mutex_unlock(&sc->lock); - return ret; -} - -static void -ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath5k_softc *sc = hw->priv; - u8 mac[ETH_ALEN] = {}; - - mutex_lock(&sc->lock); - if (sc->vif != conf->vif) - goto end; - - ath5k_hw_set_lladdr(sc->ah, mac); - sc->vif = NULL; -end: - mutex_unlock(&sc->lock); -} - -/* - * TODO: Phy disable/diversity etc - */ -static int -ath5k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath5k_softc *sc = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - int ret; - - mutex_lock(&sc->lock); - - sc->bintval = conf->beacon_int; - sc->power_level = conf->power_level; - - ret = ath5k_chan_set(sc, conf->channel); - - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - int ret = 0; - - mutex_lock(&sc->lock); - if (sc->vif != vif) { - ret = -EIO; - goto unlock; - } - if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { - /* Cache for later use during resets */ - memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); - /* XXX: assoc id is set to 0 for now, mac80211 doesn't have - * a clean way of letting us retrieve this yet. */ - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - mmiowb(); - } - if (conf->changed & IEEE80211_IFCC_BEACON && - (vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_AP)) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) { - ret = -ENOMEM; - goto unlock; - } - ath5k_beacon_update(sc, beacon); - } - -unlock: - mutex_unlock(&sc->lock); - return ret; -} - -#define SUPPORTED_FIF_FLAGS \ - FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ - FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC -/* - * o always accept unicast, broadcast, and multicast traffic - * o multicast traffic for all BSSIDs will be enabled if mac80211 - * says it should be - * o maintain current state of phy ofdm or phy cck error reception. - * If the hardware detects any of these type of errors then - * ath5k_hw_get_rx_filter() will pass to us the respective - * hardware filters to be able to receive these type of frames. - * o probe request frames are accepted only when operating in - * hostap, adhoc, or monitor modes - * o enable promiscuous mode according to the interface state - * o accept beacons: - * - when operating in adhoc mode so the 802.11 layer creates - * node table entries for peers, - * - when operating in station mode for collecting rssi data when - * the station is otherwise quiet, or - * - when scanning - */ -static void ath5k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - int mc_count, struct dev_mc_list *mclist) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - u32 mfilt[2], val, rfilt; - u8 pos; - int i; - - mfilt[0] = 0; - mfilt[1] = 0; - - /* Only deal with supported flags */ - changed_flags &= SUPPORTED_FIF_FLAGS; - *new_flags &= SUPPORTED_FIF_FLAGS; - - /* If HW detects any phy or radar errors, leave those filters on. - * Also, always enable Unicast, Broadcasts and Multicast - * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ - rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | - (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | - AR5K_RX_FILTER_MCAST); - - if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { - if (*new_flags & FIF_PROMISC_IN_BSS) { - rfilt |= AR5K_RX_FILTER_PROM; - __set_bit(ATH_STAT_PROMISC, sc->status); - } else { - __clear_bit(ATH_STAT_PROMISC, sc->status); - } - } - - /* Note, AR5K_RX_FILTER_MCAST is already enabled */ - if (*new_flags & FIF_ALLMULTI) { - mfilt[0] = ~0; - mfilt[1] = ~0; - } else { - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(mclist->dmi_addr + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(mclist->dmi_addr + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); - /* XXX: we might be able to just do this instead, - * but not sure, needs testing, if we do use this we'd - * neet to inform below to not reset the mcast */ - /* ath5k_hw_set_mcast_filterindex(ah, - * mclist->dmi_addr[5]); */ - mclist = mclist->next; - } - } - - /* This is the best we can do */ - if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) - rfilt |= AR5K_RX_FILTER_PHYERR; - - /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons - * and probes for any BSSID, this needs testing */ - if (*new_flags & FIF_BCN_PRBRESP_PROMISC) - rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; - - /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not - * set we should only pass on control frames for this - * station. This needs testing. I believe right now this - * enables *all* control frames, which is OK.. but - * but we should see if we can improve on granularity */ - if (*new_flags & FIF_CONTROL) - rfilt |= AR5K_RX_FILTER_CONTROL; - - /* Additional settings per mode -- this is per ath5k */ - - /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ - - if (sc->opmode == NL80211_IFTYPE_MONITOR) - rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | - AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; - if (sc->opmode != NL80211_IFTYPE_STATION) - rfilt |= AR5K_RX_FILTER_PROBEREQ; - if (sc->opmode != NL80211_IFTYPE_AP && - sc->opmode != NL80211_IFTYPE_MESH_POINT && - test_bit(ATH_STAT_PROMISC, sc->status)) - rfilt |= AR5K_RX_FILTER_PROM; - if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) || - sc->opmode == NL80211_IFTYPE_ADHOC || - sc->opmode == NL80211_IFTYPE_AP) - rfilt |= AR5K_RX_FILTER_BEACON; - if (sc->opmode == NL80211_IFTYPE_MESH_POINT) - rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | - AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; - - /* Set filters */ - ath5k_hw_set_rx_filter(ah, rfilt); - - /* Set multicast bits */ - ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); - /* Set the cached hw filter flags, this will alter actually - * be set in HW */ - sc->filter_flags = rfilt; -} - -static int -ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath5k_softc *sc = hw->priv; - int ret = 0; - - if (modparam_nohwcrypt) - return -EOPNOTSUPP; - - switch (key->alg) { - case ALG_WEP: - case ALG_TKIP: - break; - case ALG_CCMP: - return -EOPNOTSUPP; - default: - WARN_ON(1); - return -EINVAL; - } - - mutex_lock(&sc->lock); - - switch (cmd) { - case SET_KEY: - ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, - sta ? sta->addr : NULL); - if (ret) { - ATH5K_ERR(sc, "can't set the key\n"); - goto unlock; - } - __set_bit(key->keyidx, sc->keymap); - key->hw_key_idx = key->keyidx; - key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | - IEEE80211_KEY_FLAG_GENERATE_MMIC); - break; - case DISABLE_KEY: - ath5k_hw_reset_key(sc->ah, key->keyidx); - __clear_bit(key->keyidx, sc->keymap); - break; - default: - ret = -EINVAL; - goto unlock; - } - -unlock: - mmiowb(); - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - - /* Force update */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); - - memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); - - return 0; -} - -static int -ath5k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct ath5k_softc *sc = hw->priv; - - memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); - - return 0; -} - -static u64 -ath5k_get_tsf(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - return ath5k_hw_get_tsf64(sc->ah); -} - -static void -ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct ath5k_softc *sc = hw->priv; - - ath5k_hw_set_tsf64(sc->ah, tsf); -} - -static void -ath5k_reset_tsf(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - /* - * in IBSS mode we need to update the beacon timers too. - * this will also reset the TSF if we call it with 0 - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_beacon_update_timers(sc, 0); - else - ath5k_hw_reset_tsf(sc->ah); -} - -static int -ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) -{ - unsigned long flags; - int ret; - - ath5k_debug_dump_skb(sc, skb, "BC ", 1); - - spin_lock_irqsave(&sc->block, flags); - ath5k_txbuf_free(sc, sc->bbuf); - sc->bbuf->skb = skb; - ret = ath5k_beacon_setup(sc, sc->bbuf); - if (ret) - sc->bbuf->skb = NULL; - spin_unlock_irqrestore(&sc->block, flags); - if (!ret) { - ath5k_beacon_config(sc); - mmiowb(); - } - - return ret; -} -static void -set_beacon_filter(struct ieee80211_hw *hw, bool enable) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - u32 rfilt; - rfilt = ath5k_hw_get_rx_filter(ah); - if (enable) - rfilt |= AR5K_RX_FILTER_BEACON; - else - rfilt &= ~AR5K_RX_FILTER_BEACON; - ath5k_hw_set_rx_filter(ah, rfilt); - sc->filter_flags = rfilt; -} - -static void ath5k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct ath5k_softc *sc = hw->priv; - if (changes & BSS_CHANGED_ASSOC) { - mutex_lock(&sc->lock); - sc->assoc = bss_conf->assoc; - if (sc->opmode == NL80211_IFTYPE_STATION) - set_beacon_filter(hw, sc->assoc); - mutex_unlock(&sc->lock); - } -} diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h deleted file mode 100644 index 822956114cd7..000000000000 --- a/drivers/net/wireless/ath5k/base.h +++ /dev/null @@ -1,190 +0,0 @@ -/*- - * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -/* - * Defintions for the Atheros Wireless LAN controller driver. - */ -#ifndef _DEV_ATH_ATHVAR_H -#define _DEV_ATH_ATHVAR_H - -#include -#include -#include -#include -#include - -#include "ath5k.h" -#include "debug.h" - -#define ATH_RXBUF 40 /* number of RX buffers */ -#define ATH_TXBUF 200 /* number of TX buffers */ -#define ATH_BCBUF 1 /* number of beacon buffers */ - -struct ath5k_buf { - struct list_head list; - unsigned int flags; /* rx descriptor flags */ - struct ath5k_desc *desc; /* virtual addr of desc */ - dma_addr_t daddr; /* physical addr of desc */ - struct sk_buff *skb; /* skbuff for buf */ - dma_addr_t skbaddr;/* physical addr of skb data */ -}; - -/* - * Data transmit queue state. One of these exists for each - * hardware transmit queue. Packets sent to us from above - * are assigned to queues based on their priority. Not all - * devices support a complete set of hardware transmit queues. - * For those devices the array sc_ac2q will map multiple - * priorities to fewer hardware queues (typically all to one - * hardware queue). - */ -struct ath5k_txq { - unsigned int qnum; /* hardware q number */ - u32 *link; /* link ptr in last TX desc */ - struct list_head q; /* transmit queue */ - spinlock_t lock; /* lock on q and link */ - bool setup; -}; - -#define ATH5K_LED_MAX_NAME_LEN 31 - -/* - * State for LED triggers - */ -struct ath5k_led -{ - char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ - struct ath5k_softc *sc; /* driver state */ - struct led_classdev led_dev; /* led classdev */ -}; - - -#if CHAN_DEBUG -#define ATH_CHAN_MAX (26+26+26+200+200) -#else -#define ATH_CHAN_MAX (14+14+14+252+20) -#endif - -/* Software Carrier, keeps track of the driver state - * associated with an instance of a device */ -struct ath5k_softc { - struct pci_dev *pdev; /* for dma mapping */ - void __iomem *iobase; /* address of the device */ - struct mutex lock; /* dev-level lock */ - /* FIXME: how many does it really need? */ - struct ieee80211_tx_queue_stats tx_stats[16]; - struct ieee80211_low_level_stats ll_stats; - struct ieee80211_hw *hw; /* IEEE 802.11 common */ - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - struct ieee80211_channel channels[ATH_CHAN_MAX]; - struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - enum nl80211_iftype opmode; - struct ath5k_hw *ah; /* Atheros HW */ - - struct ieee80211_supported_band *curband; - -#ifdef CONFIG_ATH5K_DEBUG - struct ath5k_dbg_info debug; /* debug info */ -#endif /* CONFIG_ATH5K_DEBUG */ - - struct ath5k_buf *bufptr; /* allocated buffer ptr */ - struct ath5k_desc *desc; /* TX/RX descriptors */ - dma_addr_t desc_daddr; /* DMA (physical) address */ - size_t desc_len; /* size of TX/RX descriptors */ - u16 cachelsz; /* cache line size */ - - DECLARE_BITMAP(status, 5); -#define ATH_STAT_INVALID 0 /* disable hardware accesses */ -#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ -#define ATH_STAT_PROMISC 2 -#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ -#define ATH_STAT_STARTED 4 /* opened & irqs enabled */ - - unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ - unsigned int curmode; /* current phy mode */ - struct ieee80211_channel *curchan; /* current h/w channel */ - - struct ieee80211_vif *vif; - - enum ath5k_int imask; /* interrupt mask copy */ - - DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ - - u8 bssidmask[ETH_ALEN]; - - unsigned int led_pin, /* GPIO pin for driving LED */ - led_on; /* pin setting for LED on */ - - struct tasklet_struct restq; /* reset tasklet */ - - unsigned int rxbufsize; /* rx size based on mtu */ - struct list_head rxbuf; /* receive buffer */ - spinlock_t rxbuflock; - u32 *rxlink; /* link ptr in last RX desc */ - struct tasklet_struct rxtq; /* rx intr tasklet */ - struct ath5k_led rx_led; /* rx led */ - - struct list_head txbuf; /* transmit buffer */ - spinlock_t txbuflock; - unsigned int txbuf_len; /* buf count in txbuf list */ - struct ath5k_txq txqs[2]; /* beacon and tx */ - - struct ath5k_txq *txq; /* beacon and tx*/ - struct tasklet_struct txtq; /* tx intr tasklet */ - struct ath5k_led tx_led; /* tx led */ - - spinlock_t block; /* protects beacon */ - struct tasklet_struct beacontq; /* beacon intr tasklet */ - struct ath5k_buf *bbuf; /* beacon buffer */ - unsigned int bhalq, /* SW q for outgoing beacons */ - bmisscount, /* missed beacon transmits */ - bintval, /* beacon interval in TU */ - bsent; - unsigned int nexttbtt; /* next beacon time in TU */ - - struct timer_list calib_tim; /* calibration timer */ - int power_level; /* Requested tx power in dbm */ - bool assoc; /* assocate state */ -}; - -#define ath5k_hw_hasbssidmask(_ah) \ - (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) -#define ath5k_hw_hasveol(_ah) \ - (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) - -#endif diff --git a/drivers/net/wireless/ath5k/caps.c b/drivers/net/wireless/ath5k/caps.c deleted file mode 100644 index 367a6c7d3cc7..000000000000 --- a/drivers/net/wireless/ath5k/caps.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/**************\ -* Capabilities * -\**************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Fill the capabilities struct - * TODO: Merge this with EEPROM code when we are done with it - */ -int ath5k_hw_set_capabilities(struct ath5k_hw *ah) -{ - u16 ee_header; - - ATH5K_TRACE(ah->ah_sc); - /* Capabilities stored in the EEPROM */ - ee_header = ah->ah_capabilities.cap_eeprom.ee_header; - - if (ah->ah_version == AR5K_AR5210) { - /* - * Set radio capabilities - * (The AR5110 only supports the middle 5GHz band) - */ - ah->ah_capabilities.cap_range.range_5ghz_min = 5120; - ah->ah_capabilities.cap_range.range_5ghz_max = 5430; - ah->ah_capabilities.cap_range.range_2ghz_min = 0; - ah->ah_capabilities.cap_range.range_2ghz_max = 0; - - /* Set supported modes */ - __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); - } else { - /* - * XXX The tranceiver supports frequencies from 4920 to 6100GHz - * XXX and from 2312 to 2732GHz. There are problems with the - * XXX current ieee80211 implementation because the IEEE - * XXX channel mapping does not support negative channel - * XXX numbers (2312MHz is channel -19). Of course, this - * XXX doesn't matter because these channels are out of range - * XXX but some regulation domains like MKK (Japan) will - * XXX support frequencies somewhere around 4.8GHz. - */ - - /* - * Set radio capabilities - */ - - if (AR5K_EEPROM_HDR_11A(ee_header)) { - /* 4920 */ - ah->ah_capabilities.cap_range.range_5ghz_min = 5005; - ah->ah_capabilities.cap_range.range_5ghz_max = 6100; - - /* Set supported modes */ - __set_bit(AR5K_MODE_11A, - ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, - ah->ah_capabilities.cap_mode); - if (ah->ah_version == AR5K_AR5212) - __set_bit(AR5K_MODE_11G_TURBO, - ah->ah_capabilities.cap_mode); - } - - /* Enable 802.11b if a 2GHz capable radio (2111/5112) is - * connected */ - if (AR5K_EEPROM_HDR_11B(ee_header) || - (AR5K_EEPROM_HDR_11G(ee_header) && - ah->ah_version != AR5K_AR5211)) { - /* 2312 */ - ah->ah_capabilities.cap_range.range_2ghz_min = 2412; - ah->ah_capabilities.cap_range.range_2ghz_max = 2732; - - if (AR5K_EEPROM_HDR_11B(ee_header)) - __set_bit(AR5K_MODE_11B, - ah->ah_capabilities.cap_mode); - - if (AR5K_EEPROM_HDR_11G(ee_header) && - ah->ah_version != AR5K_AR5211) - __set_bit(AR5K_MODE_11G, - ah->ah_capabilities.cap_mode); - } - } - - /* GPIO */ - ah->ah_gpio_npins = AR5K_NUM_GPIO; - - /* Set number of supported TX queues */ - if (ah->ah_version == AR5K_AR5210) - ah->ah_capabilities.cap_queues.q_tx_num = - AR5K_NUM_TX_QUEUES_NOQCU; - else - ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; - - return 0; -} - -/* Main function used by the driver part to check caps */ -int ath5k_hw_get_capability(struct ath5k_hw *ah, - enum ath5k_capability_type cap_type, - u32 capability, u32 *result) -{ - ATH5K_TRACE(ah->ah_sc); - - switch (cap_type) { - case AR5K_CAP_NUM_TXQUEUES: - if (result) { - if (ah->ah_version == AR5K_AR5210) - *result = AR5K_NUM_TX_QUEUES_NOQCU; - else - *result = AR5K_NUM_TX_QUEUES; - goto yes; - } - case AR5K_CAP_VEOL: - goto yes; - case AR5K_CAP_COMPRESSION: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - case AR5K_CAP_BURST: - goto yes; - case AR5K_CAP_TPC: - goto yes; - case AR5K_CAP_BSSIDMASK: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - case AR5K_CAP_XR: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - default: - goto no; - } - -no: - return -EINVAL; -yes: - return 0; -} - -/* - * TODO: Following functions should be part of a new function - * set_capability - */ - -int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, - u16 assoc_id) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); - return 0; - } - - return -EIO; -} - -int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); - return 0; - } - - return -EIO; -} diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c deleted file mode 100644 index 9770bb3d40f9..000000000000 --- a/drivers/net/wireless/ath5k/debug.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright (c) 2007-2008 Bruno Randolf - * - * This file is free software: you may copy, redistribute 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 file 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. If not, see . - * - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2006 Devicescape Software, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2007 Luis R. Rodriguez - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -#include "base.h" -#include "debug.h" - -static unsigned int ath5k_debug; -module_param_named(debug, ath5k_debug, uint, 0); - - -#ifdef CONFIG_ATH5K_DEBUG - -#include -#include "reg.h" - -static struct dentry *ath5k_global_debugfs; - -static int ath5k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - - -/* debugfs: registers */ - -struct reg { - const char *name; - int addr; -}; - -#define REG_STRUCT_INIT(r) { #r, r } - -/* just a few random registers, might want to add more */ -static const struct reg regs[] = { - REG_STRUCT_INIT(AR5K_CR), - REG_STRUCT_INIT(AR5K_RXDP), - REG_STRUCT_INIT(AR5K_CFG), - REG_STRUCT_INIT(AR5K_IER), - REG_STRUCT_INIT(AR5K_BCR), - REG_STRUCT_INIT(AR5K_RTSD0), - REG_STRUCT_INIT(AR5K_RTSD1), - REG_STRUCT_INIT(AR5K_TXCFG), - REG_STRUCT_INIT(AR5K_RXCFG), - REG_STRUCT_INIT(AR5K_RXJLA), - REG_STRUCT_INIT(AR5K_MIBC), - REG_STRUCT_INIT(AR5K_TOPS), - REG_STRUCT_INIT(AR5K_RXNOFRM), - REG_STRUCT_INIT(AR5K_TXNOFRM), - REG_STRUCT_INIT(AR5K_RPGTO), - REG_STRUCT_INIT(AR5K_RFCNT), - REG_STRUCT_INIT(AR5K_MISC), - REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT), - REG_STRUCT_INIT(AR5K_ISR), - REG_STRUCT_INIT(AR5K_PISR), - REG_STRUCT_INIT(AR5K_SISR0), - REG_STRUCT_INIT(AR5K_SISR1), - REG_STRUCT_INIT(AR5K_SISR2), - REG_STRUCT_INIT(AR5K_SISR3), - REG_STRUCT_INIT(AR5K_SISR4), - REG_STRUCT_INIT(AR5K_IMR), - REG_STRUCT_INIT(AR5K_PIMR), - REG_STRUCT_INIT(AR5K_SIMR0), - REG_STRUCT_INIT(AR5K_SIMR1), - REG_STRUCT_INIT(AR5K_SIMR2), - REG_STRUCT_INIT(AR5K_SIMR3), - REG_STRUCT_INIT(AR5K_SIMR4), - REG_STRUCT_INIT(AR5K_DCM_ADDR), - REG_STRUCT_INIT(AR5K_DCCFG), - REG_STRUCT_INIT(AR5K_CCFG), - REG_STRUCT_INIT(AR5K_CPC0), - REG_STRUCT_INIT(AR5K_CPC1), - REG_STRUCT_INIT(AR5K_CPC2), - REG_STRUCT_INIT(AR5K_CPC3), - REG_STRUCT_INIT(AR5K_CPCOVF), - REG_STRUCT_INIT(AR5K_RESET_CTL), - REG_STRUCT_INIT(AR5K_SLEEP_CTL), - REG_STRUCT_INIT(AR5K_INTPEND), - REG_STRUCT_INIT(AR5K_SFR), - REG_STRUCT_INIT(AR5K_PCICFG), - REG_STRUCT_INIT(AR5K_GPIOCR), - REG_STRUCT_INIT(AR5K_GPIODO), - REG_STRUCT_INIT(AR5K_SREV), -}; - -static void *reg_start(struct seq_file *seq, loff_t *pos) -{ - return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; -} - -static void reg_stop(struct seq_file *seq, void *p) -{ - /* nothing to do */ -} - -static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) -{ - ++*pos; - return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; -} - -static int reg_show(struct seq_file *seq, void *p) -{ - struct ath5k_softc *sc = seq->private; - struct reg *r = p; - seq_printf(seq, "%-25s0x%08x\n", r->name, - ath5k_hw_reg_read(sc->ah, r->addr)); - return 0; -} - -static const struct seq_operations register_seq_ops = { - .start = reg_start, - .next = reg_next, - .stop = reg_stop, - .show = reg_show -}; - -static int open_file_registers(struct inode *inode, struct file *file) -{ - struct seq_file *s; - int res; - res = seq_open(file, ®ister_seq_ops); - if (res == 0) { - s = file->private_data; - s->private = inode->i_private; - } - return res; -} - -static const struct file_operations fops_registers = { - .open = open_file_registers, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, - .owner = THIS_MODULE, -}; - - -/* debugfs: beacons */ - -static ssize_t read_file_beacon(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - struct ath5k_hw *ah = sc->ah; - char buf[500]; - unsigned int len = 0; - unsigned int v; - u64 tsf; - - v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); - len += snprintf(buf+len, sizeof(buf)-len, - "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", - "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, - (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); - - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n", - "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); - - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n", - "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT)); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER0 (TBTT)", v, v); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER1 (DMA)", v, v >> 3); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER2 (SWBA)", v, v >> 3); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER3 (ATIM)", v, v); - - tsf = ath5k_hw_get_tsf64(sc->ah); - len += snprintf(buf+len, sizeof(buf)-len, - "TSF\t\t0x%016llx\tTU: %08x\n", - (unsigned long long)tsf, TSF_TO_TU(tsf)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_beacon(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - struct ath5k_hw *ah = sc->ah; - char buf[20]; - - if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) - return -EFAULT; - - if (strncmp(buf, "disable", 7) == 0) { - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); - printk(KERN_INFO "debugfs disable beacons\n"); - } else if (strncmp(buf, "enable", 6) == 0) { - AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); - printk(KERN_INFO "debugfs enable beacons\n"); - } - return count; -} - -static const struct file_operations fops_beacon = { - .read = read_file_beacon, - .write = write_file_beacon, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - -/* debugfs: reset */ - -static ssize_t write_file_reset(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - tasklet_schedule(&sc->restq); - return count; -} - -static const struct file_operations fops_reset = { - .write = write_file_reset, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - -/* debugfs: debug level */ - -static const struct { - enum ath5k_debug_level level; - const char *name; - const char *desc; -} dbg_info[] = { - { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, - { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, - { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, - { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, - { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, - { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, - { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, - { ATH5K_DEBUG_LED, "led", "LED management" }, - { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, - { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, - { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, - { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, - { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, -}; - -static ssize_t read_file_debug(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - char buf[700]; - unsigned int len = 0; - unsigned int i; - - len += snprintf(buf+len, sizeof(buf)-len, - "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); - - for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { - len += snprintf(buf+len, sizeof(buf)-len, - "%10s %c 0x%08x - %s\n", dbg_info[i].name, - sc->debug.level & dbg_info[i].level ? '+' : ' ', - dbg_info[i].level, dbg_info[i].desc); - } - len += snprintf(buf+len, sizeof(buf)-len, - "%10s %c 0x%08x - %s\n", dbg_info[i].name, - sc->debug.level == dbg_info[i].level ? '+' : ' ', - dbg_info[i].level, dbg_info[i].desc); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_debug(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - unsigned int i; - char buf[20]; - - if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { - if (strncmp(buf, dbg_info[i].name, - strlen(dbg_info[i].name)) == 0) { - sc->debug.level ^= dbg_info[i].level; /* toggle bit */ - break; - } - } - return count; -} - -static const struct file_operations fops_debug = { - .read = read_file_debug, - .write = write_file_debug, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - -/* init */ - -void -ath5k_debug_init(void) -{ - ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); -} - -void -ath5k_debug_init_device(struct ath5k_softc *sc) -{ - sc->debug.level = ath5k_debug; - - sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath5k_global_debugfs); - - sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO, - sc->debug.debugfs_phydir, sc, &fops_debug); - - sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, - sc->debug.debugfs_phydir, sc, &fops_registers); - - sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, - sc->debug.debugfs_phydir, sc, &fops_beacon); - - sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, - sc->debug.debugfs_phydir, sc, &fops_reset); -} - -void -ath5k_debug_finish(void) -{ - debugfs_remove(ath5k_global_debugfs); -} - -void -ath5k_debug_finish_device(struct ath5k_softc *sc) -{ - debugfs_remove(sc->debug.debugfs_debug); - debugfs_remove(sc->debug.debugfs_registers); - debugfs_remove(sc->debug.debugfs_beacon); - debugfs_remove(sc->debug.debugfs_reset); - debugfs_remove(sc->debug.debugfs_phydir); -} - - -/* functions used in other places */ - -void -ath5k_debug_dump_bands(struct ath5k_softc *sc) -{ - unsigned int b, i; - - if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS))) - return; - - BUG_ON(!sc->sbands); - - for (b = 0; b < IEEE80211_NUM_BANDS; b++) { - struct ieee80211_supported_band *band = &sc->sbands[b]; - char bname[5]; - switch (band->band) { - case IEEE80211_BAND_2GHZ: - strcpy(bname, "2 GHz"); - break; - case IEEE80211_BAND_5GHZ: - strcpy(bname, "5 GHz"); - break; - default: - printk(KERN_DEBUG "Band not supported: %d\n", - band->band); - return; - } - printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname, - band->n_channels, band->n_bitrates); - printk(KERN_DEBUG " channels:\n"); - for (i = 0; i < band->n_channels; i++) - printk(KERN_DEBUG " %3d %d %.4x %.4x\n", - ieee80211_frequency_to_channel( - band->channels[i].center_freq), - band->channels[i].center_freq, - band->channels[i].hw_value, - band->channels[i].flags); - printk(KERN_DEBUG " rates:\n"); - for (i = 0; i < band->n_bitrates; i++) - printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", - band->bitrates[i].bitrate, - band->bitrates[i].hw_value, - band->bitrates[i].flags, - band->bitrates[i].hw_value_short); - } -} - -static inline void -ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, - struct ath5k_rx_status *rs) -{ - struct ath5k_desc *ds = bf->desc; - struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; - - printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", - ds, (unsigned long long)bf->daddr, - ds->ds_link, ds->ds_data, - rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, - rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, - !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); -} - -void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) -{ - struct ath5k_desc *ds; - struct ath5k_buf *bf; - struct ath5k_rx_status rs = {}; - int status; - - if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) - return; - - printk(KERN_DEBUG "rx queue %x, link %p\n", - ath5k_hw_get_rxdp(ah), sc->rxlink); - - spin_lock_bh(&sc->rxbuflock); - list_for_each_entry(bf, &sc->rxbuf, list) { - ds = bf->desc; - status = ah->ah_proc_rx_desc(ah, ds, &rs); - if (!status) - ath5k_debug_printrxbuf(bf, status == 0, &rs); - } - spin_unlock_bh(&sc->rxbuflock); -} - -void -ath5k_debug_dump_skb(struct ath5k_softc *sc, - struct sk_buff *skb, const char *prefix, int tx) -{ - char buf[16]; - - if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || - (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) - return; - - snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); - - print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, - min(200U, skb->len)); - - printk(KERN_DEBUG "\n"); -} - -void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct ath5k_desc *ds = bf->desc; - struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; - struct ath5k_tx_status ts = {}; - int done; - - if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) - return; - - done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); - - printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " - "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, - ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, - td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, - td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, - done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); -} - -#endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h deleted file mode 100644 index 66f69f04e55e..000000000000 --- a/drivers/net/wireless/ath5k/debug.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2007 Bruno Randolf - * - * This file is free software: you may copy, redistribute 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 file 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. If not, see . - * - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2006 Devicescape Software, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2007 Luis R. Rodriguez - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -#ifndef _ATH5K_DEBUG_H -#define _ATH5K_DEBUG_H - -struct ath5k_softc; -struct ath5k_hw; -struct sk_buff; -struct ath5k_buf; - -struct ath5k_dbg_info { - unsigned int level; /* debug level */ - /* debugfs entries */ - struct dentry *debugfs_phydir; - struct dentry *debugfs_debug; - struct dentry *debugfs_registers; - struct dentry *debugfs_beacon; - struct dentry *debugfs_reset; -}; - -/** - * enum ath5k_debug_level - ath5k debug level - * - * @ATH5K_DEBUG_RESET: reset processing - * @ATH5K_DEBUG_INTR: interrupt handling - * @ATH5K_DEBUG_MODE: mode init/setup - * @ATH5K_DEBUG_XMIT: basic xmit operation - * @ATH5K_DEBUG_BEACON: beacon handling - * @ATH5K_DEBUG_CALIBRATE: periodic calibration - * @ATH5K_DEBUG_TXPOWER: transmit power setting - * @ATH5K_DEBUG_LED: led management - * @ATH5K_DEBUG_DUMP_RX: print received skb content - * @ATH5K_DEBUG_DUMP_TX: print transmit skb content - * @ATH5K_DEBUG_DUMPBANDS: dump bands - * @ATH5K_DEBUG_TRACE: trace function calls - * @ATH5K_DEBUG_ANY: show at any debug level - * - * The debug level is used to control the amount and type of debugging output - * we want to see. The debug level is given in calls to ATH5K_DBG to specify - * where the message should appear, and the user can control the debugging - * messages he wants to see, either by the module parameter 'debug' on module - * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can - * be combined together by bitwise OR. - */ -enum ath5k_debug_level { - ATH5K_DEBUG_RESET = 0x00000001, - ATH5K_DEBUG_INTR = 0x00000002, - ATH5K_DEBUG_MODE = 0x00000004, - ATH5K_DEBUG_XMIT = 0x00000008, - ATH5K_DEBUG_BEACON = 0x00000010, - ATH5K_DEBUG_CALIBRATE = 0x00000020, - ATH5K_DEBUG_TXPOWER = 0x00000040, - ATH5K_DEBUG_LED = 0x00000080, - ATH5K_DEBUG_DUMP_RX = 0x00000100, - ATH5K_DEBUG_DUMP_TX = 0x00000200, - ATH5K_DEBUG_DUMPBANDS = 0x00000400, - ATH5K_DEBUG_TRACE = 0x00001000, - ATH5K_DEBUG_ANY = 0xffffffff -}; - -#ifdef CONFIG_ATH5K_DEBUG - -#define ATH5K_TRACE(_sc) do { \ - if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ - printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \ - } while (0) - -#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ - if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ - ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ - __func__, __LINE__, ##__VA_ARGS__); \ - } while (0) - -#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \ - if (unlikely((_sc)->debug.level & (_m))) \ - ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ - __func__, __LINE__, ##__VA_ARGS__); \ - } while (0) - -void -ath5k_debug_init(void); - -void -ath5k_debug_init_device(struct ath5k_softc *sc); - -void -ath5k_debug_finish(void); - -void -ath5k_debug_finish_device(struct ath5k_softc *sc); - -void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); - -void -ath5k_debug_dump_bands(struct ath5k_softc *sc); - -void -ath5k_debug_dump_skb(struct ath5k_softc *sc, - struct sk_buff *skb, const char *prefix, int tx); - -void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); - -#else /* no debugging */ - -#include - -#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc)) - -static inline void __attribute__ ((format (printf, 3, 4))) -ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} - -static inline void __attribute__ ((format (printf, 3, 4))) -ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) -{} - -static inline void -ath5k_debug_init(void) {} - -static inline void -ath5k_debug_init_device(struct ath5k_softc *sc) {} - -static inline void -ath5k_debug_finish(void) {} - -static inline void -ath5k_debug_finish_device(struct ath5k_softc *sc) {} - -static inline void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} - -static inline void -ath5k_debug_dump_bands(struct ath5k_softc *sc) {} - -static inline void -ath5k_debug_dump_skb(struct ath5k_softc *sc, - struct sk_buff *skb, const char *prefix, int tx) {} - -static inline void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} - -#endif /* ifdef CONFIG_ATH5K_DEBUG */ - -#endif /* ifndef _ATH5K_DEBUG_H */ diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c deleted file mode 100644 index dc30a2b70a6b..000000000000 --- a/drivers/net/wireless/ath5k/desc.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Pavel Roskin - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/******************************\ - Hardware Descriptor Functions -\******************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * TX Descriptors - */ - -/* - * Initialize the 2-word tx control descriptor on 5210/5211 - */ -static int -ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, - unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, - unsigned int key_index, unsigned int antenna_mode, unsigned int flags, - unsigned int rtscts_rate, unsigned int rtscts_duration) -{ - u32 frame_type; - struct ath5k_hw_2w_tx_ctl *tx_ctl; - unsigned int frame_len; - - tx_ctl = &desc->ud.ds_tx5210.tx_ctl; - - /* - * Validate input - * - Zero retries don't make sense. - * - A zero rate will put the HW into a mode where it continously sends - * noise on the channel, so it is important to avoid this. - */ - if (unlikely(tx_tries0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero retries\n"); - WARN_ON(1); - return -EINVAL; - } - if (unlikely(tx_rate0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); - WARN_ON(1); - return -EINVAL; - } - - /* Clear descriptor */ - memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); - - /* Setup control descriptor */ - - /* Verify and set frame length */ - - /* remove padding we might have added before */ - frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; - - if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) - return -EINVAL; - - tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; - - /* Verify and set buffer length */ - - /* NB: beacon's BufLen must be a multiple of 4 bytes */ - if (type == AR5K_PKT_TYPE_BEACON) - pkt_len = roundup(pkt_len, 4); - - if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) - return -EINVAL; - - tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; - - /* - * Verify and set header length - * XXX: I only found that on 5210 code, does it work on 5211 ? - */ - if (ah->ah_version == AR5K_AR5210) { - if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) - return -EINVAL; - tx_ctl->tx_control_0 |= - AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); - } - - /*Diferences between 5210-5211*/ - if (ah->ah_version == AR5K_AR5210) { - switch (type) { - case AR5K_PKT_TYPE_BEACON: - case AR5K_PKT_TYPE_PROBE_RESP: - frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; - case AR5K_PKT_TYPE_PIFS: - frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; - default: - frame_type = type /*<< 2 ?*/; - } - - tx_ctl->tx_control_0 |= - AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | - AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); - - } else { - tx_ctl->tx_control_0 |= - AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | - AR5K_REG_SM(antenna_mode, - AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_ctl->tx_control_1 |= - AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); - } -#define _TX_FLAGS(_c, _flag) \ - if (flags & AR5K_TXDESC_##_flag) { \ - tx_ctl->tx_control_##_c |= \ - AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ - } - - _TX_FLAGS(0, CLRDMASK); - _TX_FLAGS(0, VEOL); - _TX_FLAGS(0, INTREQ); - _TX_FLAGS(0, RTSENA); - _TX_FLAGS(1, NOACK); - -#undef _TX_FLAGS - - /* - * WEP crap - */ - if (key_index != AR5K_TXKEYIX_INVALID) { - tx_ctl->tx_control_0 |= - AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_ctl->tx_control_1 |= - AR5K_REG_SM(key_index, - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); - } - - /* - * RTS/CTS Duration [5210 ?] - */ - if ((ah->ah_version == AR5K_AR5210) && - (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) - tx_ctl->tx_control_1 |= rtscts_duration & - AR5K_2W_TX_DESC_CTL1_RTS_DURATION; - - return 0; -} - -/* - * Initialize the 4-word tx control descriptor on 5212 - */ -static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, - struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, - enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, - unsigned int tx_tries0, unsigned int key_index, - unsigned int antenna_mode, unsigned int flags, - unsigned int rtscts_rate, - unsigned int rtscts_duration) -{ - struct ath5k_hw_4w_tx_ctl *tx_ctl; - unsigned int frame_len; - - ATH5K_TRACE(ah->ah_sc); - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; - - /* - * Validate input - * - Zero retries don't make sense. - * - A zero rate will put the HW into a mode where it continously sends - * noise on the channel, so it is important to avoid this. - */ - if (unlikely(tx_tries0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero retries\n"); - WARN_ON(1); - return -EINVAL; - } - if (unlikely(tx_rate0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); - WARN_ON(1); - return -EINVAL; - } - - tx_power += ah->ah_txpower.txp_offset; - if (tx_power > AR5K_TUNE_MAX_TXPOWER) - tx_power = AR5K_TUNE_MAX_TXPOWER; - - /* Clear descriptor */ - memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); - - /* Setup control descriptor */ - - /* Verify and set frame length */ - - /* remove padding we might have added before */ - frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; - - if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) - return -EINVAL; - - tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; - - /* Verify and set buffer length */ - - /* NB: beacon's BufLen must be a multiple of 4 bytes */ - if (type == AR5K_PKT_TYPE_BEACON) - pkt_len = roundup(pkt_len, 4); - - if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) - return -EINVAL; - - tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; - - tx_ctl->tx_control_0 |= - AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | - AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_ctl->tx_control_1 |= AR5K_REG_SM(type, - AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); - tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); - tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; - -#define _TX_FLAGS(_c, _flag) \ - if (flags & AR5K_TXDESC_##_flag) { \ - tx_ctl->tx_control_##_c |= \ - AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ - } - - _TX_FLAGS(0, CLRDMASK); - _TX_FLAGS(0, VEOL); - _TX_FLAGS(0, INTREQ); - _TX_FLAGS(0, RTSENA); - _TX_FLAGS(0, CTSENA); - _TX_FLAGS(1, NOACK); - -#undef _TX_FLAGS - - /* - * WEP crap - */ - if (key_index != AR5K_TXKEYIX_INVALID) { - tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, - AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); - } - - /* - * RTS/CTS - */ - if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) { - if ((flags & AR5K_TXDESC_RTSENA) && - (flags & AR5K_TXDESC_CTSENA)) - return -EINVAL; - tx_ctl->tx_control_2 |= rtscts_duration & - AR5K_4W_TX_DESC_CTL2_RTS_DURATION; - tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, - AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); - } - - return 0; -} - -/* - * Initialize a 4-word multi rate retry tx control descriptor on 5212 - */ -static int -ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, - u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) -{ - struct ath5k_hw_4w_tx_ctl *tx_ctl; - - /* - * Rates can be 0 as long as the retry count is 0 too. - * A zero rate and nonzero retry count will put the HW into a mode where - * it continously sends noise on the channel, so it is important to - * avoid this. - */ - if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || - (tx_rate2 == 0 && tx_tries2 != 0) || - (tx_rate3 == 0 && tx_tries3 != 0))) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); - WARN_ON(1); - return -EINVAL; - } - - if (ah->ah_version == AR5K_AR5212) { - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; - -#define _XTX_TRIES(_n) \ - if (tx_tries##_n) { \ - tx_ctl->tx_control_2 |= \ - AR5K_REG_SM(tx_tries##_n, \ - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ - tx_ctl->tx_control_3 |= \ - AR5K_REG_SM(tx_rate##_n, \ - AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ - } - - _XTX_TRIES(1); - _XTX_TRIES(2); - _XTX_TRIES(3); - -#undef _XTX_TRIES - - return 1; - } - - return 0; -} - -/* no mrr support for cards older than 5212 */ -static int -ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, - u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) -{ - return 0; -} - -/* - * Proccess the tx status descriptor on 5210/5211 - */ -static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_tx_status *ts) -{ - struct ath5k_hw_2w_tx_ctl *tx_ctl; - struct ath5k_hw_tx_status *tx_status; - - ATH5K_TRACE(ah->ah_sc); - - tx_ctl = &desc->ud.ds_tx5210.tx_ctl; - tx_status = &desc->ud.ds_tx5210.tx_stat; - - /* No frame has been send or error */ - if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) - return -EINPROGRESS; - - /* - * Get descriptor status - */ - ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - /*TODO: ts->ts_virtcol + test*/ - ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_SEQ_NUM); - ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - ts->ts_antenna = 1; - ts->ts_status = 0; - ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, - AR5K_2W_TX_DESC_CTL0_XMIT_RATE); - ts->ts_retry[0] = ts->ts_longretry; - ts->ts_final_idx = 0; - - if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { - if (tx_status->tx_status_0 & - AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) - ts->ts_status |= AR5K_TXERR_XRETRY; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) - ts->ts_status |= AR5K_TXERR_FIFO; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) - ts->ts_status |= AR5K_TXERR_FILT; - } - - return 0; -} - -/* - * Proccess a tx status descriptor on 5212 - */ -static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_tx_status *ts) -{ - struct ath5k_hw_4w_tx_ctl *tx_ctl; - struct ath5k_hw_tx_status *tx_status; - - ATH5K_TRACE(ah->ah_sc); - - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; - tx_status = &desc->ud.ds_tx5212.tx_stat; - - /* No frame has been send or error */ - if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) - return -EINPROGRESS; - - /* - * Get descriptor status - */ - ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_SEQ_NUM); - ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - ts->ts_antenna = (tx_status->tx_status_1 & - AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; - ts->ts_status = 0; - - ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); - - /* The longretry counter has the number of un-acked retries - * for the final rate. To get the total number of retries - * we have to add the retry counters for the other rates - * as well - */ - ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; - switch (ts->ts_final_idx) { - case 3: - ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); - - ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); - ts->ts_longretry += ts->ts_retry[2]; - /* fall through */ - case 2: - ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); - - ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); - ts->ts_longretry += ts->ts_retry[1]; - /* fall through */ - case 1: - ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); - - ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); - ts->ts_longretry += ts->ts_retry[0]; - /* fall through */ - case 0: - ts->ts_rate[0] = tx_ctl->tx_control_3 & - AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; - break; - } - - /* TX error */ - if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { - if (tx_status->tx_status_0 & - AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) - ts->ts_status |= AR5K_TXERR_XRETRY; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) - ts->ts_status |= AR5K_TXERR_FIFO; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) - ts->ts_status |= AR5K_TXERR_FILT; - } - - return 0; -} - -/* - * RX Descriptors - */ - -/* - * Initialize an rx control descriptor - */ -static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - u32 size, unsigned int flags) -{ - struct ath5k_hw_rx_ctl *rx_ctl; - - ATH5K_TRACE(ah->ah_sc); - rx_ctl = &desc->ud.ds_rx.rx_ctl; - - /* - * Clear the descriptor - * If we don't clean the status descriptor, - * while scanning we get too many results, - * most of them virtual, after some secs - * of scanning system hangs. M.F. - */ - memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); - - /* Setup descriptor */ - rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; - if (unlikely(rx_ctl->rx_control_1 != size)) - return -EINVAL; - - if (flags & AR5K_RXDESC_INTREQ) - rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; - - return 0; -} - -/* - * Proccess the rx status descriptor on 5210/5211 - */ -static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_rx_status *rs) -{ - struct ath5k_hw_rx_status *rx_status; - - rx_status = &desc->ud.ds_rx.u.rx_stat; - - /* No frame received / not ready */ - if (unlikely(!(rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_DONE))) - return -EINPROGRESS; - - /* - * Frame receive status - */ - rs->rs_datalen = rx_status->rx_status_0 & - AR5K_5210_RX_DESC_STATUS0_DATA_LEN; - rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); - rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); - rs->rs_more = !!(rx_status->rx_status_0 & - AR5K_5210_RX_DESC_STATUS0_MORE); - /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ - rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - rs->rs_status = 0; - rs->rs_phyerr = 0; - - /* - * Key table status - */ - if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) - rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); - else - rs->rs_keyix = AR5K_RXKEYIX_INVALID; - - /* - * Receive/descriptor errors - */ - if (!(rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_CRC; - - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) - rs->rs_status |= AR5K_RXERR_FIFO; - - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { - rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); - } - - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_DECRYPT; - } - - return 0; -} - -/* - * Proccess the rx status descriptor on 5212 - */ -static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_rx_status *rs) -{ - struct ath5k_hw_rx_status *rx_status; - struct ath5k_hw_rx_error *rx_err; - - ATH5K_TRACE(ah->ah_sc); - rx_status = &desc->ud.ds_rx.u.rx_stat; - - /* Overlay on error */ - rx_err = &desc->ud.ds_rx.u.rx_err; - - /* No frame received / not ready */ - if (unlikely(!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DONE))) - return -EINPROGRESS; - - /* - * Frame receive status - */ - rs->rs_datalen = rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_DATA_LEN; - rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); - rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); - rs->rs_more = !!(rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_MORE); - rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - rs->rs_status = 0; - rs->rs_phyerr = 0; - - /* - * Key table status - */ - if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) - rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); - else - rs->rs_keyix = AR5K_RXKEYIX_INVALID; - - /* - * Receive/descriptor errors - */ - if (!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_CRC; - - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { - rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, - AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); - } - - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_DECRYPT; - - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) - rs->rs_status |= AR5K_RXERR_MIC; - } - - return 0; -} - -/* - * Init function pointers inside ath5k_hw struct - */ -int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) -{ - - if (ah->ah_version != AR5K_AR5210 && - ah->ah_version != AR5K_AR5211 && - ah->ah_version != AR5K_AR5212) - return -ENOTSUPP; - - /* XXX: What is this magic value and where is it used ? */ - if (ah->ah_version == AR5K_AR5212) - ah->ah_magic = AR5K_EEPROM_MAGIC_5212; - else if (ah->ah_version == AR5K_AR5211) - ah->ah_magic = AR5K_EEPROM_MAGIC_5211; - - if (ah->ah_version == AR5K_AR5212) { - ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; - ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; - ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; - ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; - } else { - ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; - ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; - ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; - ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; - } - - if (ah->ah_version == AR5K_AR5212) - ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; - else if (ah->ah_version <= AR5K_AR5211) - ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; - - return 0; -} - diff --git a/drivers/net/wireless/ath5k/desc.h b/drivers/net/wireless/ath5k/desc.h deleted file mode 100644 index 56158c804e3e..000000000000 --- a/drivers/net/wireless/ath5k/desc.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Internal RX/TX descriptor structures - * (rX: reserved fields possibily used by future versions of the ar5k chipset) - */ - -/* - * common hardware RX control descriptor - */ -struct ath5k_hw_rx_ctl { - u32 rx_control_0; /* RX control word 0 */ - u32 rx_control_1; /* RX control word 1 */ -} __packed; - -/* RX control word 0 field/sflags */ -#define AR5K_DESC_RX_CTL0 0x00000000 - -/* RX control word 1 fields/flags */ -#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff -#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 - -/* - * common hardware RX status descriptor - * 5210/11 and 5212 differ only in the flags defined below - */ -struct ath5k_hw_rx_status { - u32 rx_status_0; /* RX status word 0 */ - u32 rx_status_1; /* RX status word 1 */ -} __packed; - -/* 5210/5211 */ -/* RX status word 0 fields/flags */ -#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 - -/* RX status word 1 fields/flags */ -#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 -#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 -#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 -#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 -#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 -#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 - -/* 5212 */ -/* RX status word 0 fields/flags */ -#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 - -/* RX status word 1 fields/flags */ -#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 -#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 -#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 -#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 -#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 - -/* - * common hardware RX error descriptor - */ -struct ath5k_hw_rx_error { - u32 rx_error_0; /* RX status word 0 */ - u32 rx_error_1; /* RX status word 1 */ -} __packed; - -/* RX error word 0 fields/flags */ -#define AR5K_RX_DESC_ERROR0 0x00000000 - -/* RX error word 1 fields/flags */ -#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 -#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 - -/* PHY Error codes */ -#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 -#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 -#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 -#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 -#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 -#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 -#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 -#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 - -/* - * 5210/5211 hardware 2-word TX control descriptor - */ -struct ath5k_hw_2w_tx_ctl { - u32 tx_control_0; /* TX control word 0 */ - u32 tx_control_1; /* TX control word 1 */ -} __packed; - -/* TX control word 0 fields/flags */ -#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff -#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ -#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 -#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 -#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 -#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 -#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 -#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ -#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ -#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 - -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ - (ah->ah_version == AR5K_AR5210 ? \ - AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ - AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) - -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 -#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 -#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 - -/* TX control word 1 fields/flags */ -#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff -#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 - -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ - (ah->ah_version == AR5K_AR5210 ? \ - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) - -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 -#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 -#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ - -/* Frame types */ -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 - -/* - * 5212 hardware 4-word TX control descriptor - */ -struct ath5k_hw_4w_tx_ctl { - u32 tx_control_0; /* TX control word 0 */ - -#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff -#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 -#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 -#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 -#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 -#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 -#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 -#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 -#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 -#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 -#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 - - u32 tx_control_1; /* TX control word 1 */ - -#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff -#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 -#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 -#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 -#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 -#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 -#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 -#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 -#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 - - u32 tx_control_2; /* TX control word 2 */ - -#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff -#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 - - u32 tx_control_3; /* TX control word 3 */ - -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 -#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 -#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 -} __packed; - -/* - * Common TX status descriptor - */ -struct ath5k_hw_tx_status { - u32 tx_status_0; /* TX status word 0 */ - u32 tx_status_1; /* TX status word 1 */ -} __packed; - -/* TX status word 0 fields/flags */ -#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 -#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 -#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 -#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 -/*??? -#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 -#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 -*/ -#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 -#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 -/*??? -#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 -#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 -*/ -#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 -#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 -#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 -#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 -#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 -#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 - -/* TX status word 1 fields/flags */ -#define AR5K_DESC_TX_STATUS1_DONE 0x00000001 -#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe -#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 -#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 -#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 -#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 -#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 -#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 -#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 - -/* - * 5210/5211 hardware TX descriptor - */ -struct ath5k_hw_5210_tx_desc { - struct ath5k_hw_2w_tx_ctl tx_ctl; - struct ath5k_hw_tx_status tx_stat; -} __packed; - -/* - * 5212 hardware TX descriptor - */ -struct ath5k_hw_5212_tx_desc { - struct ath5k_hw_4w_tx_ctl tx_ctl; - struct ath5k_hw_tx_status tx_stat; -} __packed; - -/* - * common hardware RX descriptor - */ -struct ath5k_hw_all_rx_desc { - struct ath5k_hw_rx_ctl rx_ctl; - union { - struct ath5k_hw_rx_status rx_stat; - struct ath5k_hw_rx_error rx_err; - } u; -} __packed; - -/* - * Atheros hardware descriptor - * This is read and written to by the hardware - */ -struct ath5k_desc { - u32 ds_link; /* physical address of the next descriptor */ - u32 ds_data; /* physical address of data buffer (skb) */ - - union { - struct ath5k_hw_5210_tx_desc ds_tx5210; - struct ath5k_hw_5212_tx_desc ds_tx5212; - struct ath5k_hw_all_rx_desc ds_rx; - } ud; -} __packed; - -#define AR5K_RXDESC_INTREQ 0x0020 - -#define AR5K_TXDESC_CLRDMASK 0x0001 -#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/ -#define AR5K_TXDESC_RTSENA 0x0004 -#define AR5K_TXDESC_CTSENA 0x0008 -#define AR5K_TXDESC_INTREQ 0x0010 -#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ - diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c deleted file mode 100644 index b65b4feb2d28..000000000000 --- a/drivers/net/wireless/ath5k/dma.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*************************************\ -* DMA and interrupt masking functions * -\*************************************/ - -/* - * dma.c - DMA and interrupt masking functions - * - * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and - * handle queue setup for 5210 chipset (rest are handled on qcu.c). - * Also we setup interrupt mask register (IMR) and read the various iterrupt - * status registers (ISR). - * - * TODO: Handle SISR on 5211+ and introduce a function to return the queue - * number that resulted the interrupt. - */ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/*********\ -* Receive * -\*********/ - -/** - * ath5k_hw_start_rx_dma - Start DMA receive - * - * @ah: The &struct ath5k_hw - */ -void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); - ath5k_hw_reg_read(ah, AR5K_CR); -} - -/** - * ath5k_hw_stop_rx_dma - Stop DMA receive - * - * @ah: The &struct ath5k_hw - */ -int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) -{ - unsigned int i; - - ATH5K_TRACE(ah->ah_sc); - ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); - - /* - * It may take some time to disable the DMA receive unit - */ - for (i = 1000; i > 0 && - (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; - i--) - udelay(10); - - return i ? 0 : -EBUSY; -} - -/** - * ath5k_hw_get_rxdp - Get RX Descriptor's address - * - * @ah: The &struct ath5k_hw - * - * XXX: Is RXDP read and clear ? - */ -u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) -{ - return ath5k_hw_reg_read(ah, AR5K_RXDP); -} - -/** - * ath5k_hw_set_rxdp - Set RX Descriptor's address - * - * @ah: The &struct ath5k_hw - * @phys_addr: RX descriptor address - * - * XXX: Should we check if rx is enabled before setting rxdp ? - */ -void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) -{ - ATH5K_TRACE(ah->ah_sc); - - ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); -} - - -/**********\ -* Transmit * -\**********/ - -/** - * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Start DMA transmit for a specific queue and since 5210 doesn't have - * QCU/DCU, set up queue parameters for 5210 here based on queue type (one - * queue for normal data and one queue for beacons). For queue setup - * on newer chips check out qcu.c. Returns -EINVAL if queue number is out - * of range or if queue is already disabled. - * - * NOTE: Must be called after setting up tx control descriptor for that - * queue (see below). - */ -int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) -{ - u32 tx_queue; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; - - if (ah->ah_version == AR5K_AR5210) { - tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); - - /* - * Set the queue by type on 5210 - */ - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; - break; - case AR5K_TX_QUEUE_BEACON: - tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, - AR5K_BSR); - break; - case AR5K_TX_QUEUE_CAB: - tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | - AR5K_BCR_BDMAE, AR5K_BSR); - break; - default: - return -EINVAL; - } - /* Start queue */ - ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); - ath5k_hw_reg_read(ah, AR5K_CR); - } else { - /* Return if queue is disabled */ - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) - return -EIO; - - /* Start queue */ - AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); - } - - return 0; -} - -/** - * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Stop DMA transmit on a specific hw queue and drain queue so we don't - * have any pending frames. Returns -EBUSY if we still have pending frames, - * -EINVAL if queue number is out of range. - * - */ -int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) -{ - unsigned int i = 40; - u32 tx_queue, pending; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; - - if (ah->ah_version == AR5K_AR5210) { - tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); - - /* - * Set by queue type - */ - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - /* XXX Fix me... */ - tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; - ath5k_hw_reg_write(ah, 0, AR5K_BSR); - break; - default: - return -EINVAL; - } - - /* Stop queue */ - ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); - ath5k_hw_reg_read(ah, AR5K_CR); - } else { - /* - * Schedule TX disable and wait until queue is empty - */ - AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); - - /*Check for pending frames*/ - do { - pending = ath5k_hw_reg_read(ah, - AR5K_QUEUE_STATUS(queue)) & - AR5K_QCU_STS_FRMPENDCNT; - udelay(100); - } while (--i && pending); - - /* For 2413+ order PCU to drop packets using - * QUIET mechanism */ - if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && - pending){ - /* Set periodicity and duration */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| - AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), - AR5K_QUIET_CTL2); - - /* Enable quiet period for current TSF */ - ath5k_hw_reg_write(ah, - AR5K_QUIET_CTL1_QT_EN | - AR5K_REG_SM(ath5k_hw_reg_read(ah, - AR5K_TSF_L32_5211) >> 10, - AR5K_QUIET_CTL1_NEXT_QT_TSF), - AR5K_QUIET_CTL1); - - /* Force channel idle high */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_CHANEL_IDLE_HIGH); - - /* Wait a while and disable mechanism */ - udelay(200); - AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, - AR5K_QUIET_CTL1_QT_EN); - - /* Re-check for pending frames */ - i = 40; - do { - pending = ath5k_hw_reg_read(ah, - AR5K_QUEUE_STATUS(queue)) & - AR5K_QCU_STS_FRMPENDCNT; - udelay(100); - } while (--i && pending); - - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_CHANEL_IDLE_HIGH); - } - - /* Clear register */ - ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); - if (pending) - return -EBUSY; - } - - /* TODO: Check for success on 5210 else return error */ - return 0; -} - -/** - * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Get TX descriptor's address for a specific queue. For 5210 we ignore - * the queue number and use tx queue type since we only have 2 queues. - * We use TXDP0 for normal data queue and TXDP1 for beacon queue. - * For newer chips with QCU/DCU we just read the corresponding TXDP register. - * - * XXX: Is TXDP read and clear ? - */ -u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) -{ - u16 tx_reg; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* - * Get the transmit queue descriptor pointer from the selected queue - */ - /*5210 doesn't have QCU*/ - if (ah->ah_version == AR5K_AR5210) { - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_reg = AR5K_NOQCU_TXDP0; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - tx_reg = AR5K_NOQCU_TXDP1; - break; - default: - return 0xffffffff; - } - } else { - tx_reg = AR5K_QUEUE_TXDP(queue); - } - - return ath5k_hw_reg_read(ah, tx_reg); -} - -/** - * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Set TX descriptor's address for a specific queue. For 5210 we ignore - * the queue number and we use tx queue type since we only have 2 queues - * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue. - * For newer chips with QCU/DCU we just set the corresponding TXDP register. - * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still - * active. - */ -int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) -{ - u16 tx_reg; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* - * Set the transmit queue descriptor pointer register by type - * on 5210 - */ - if (ah->ah_version == AR5K_AR5210) { - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_reg = AR5K_NOQCU_TXDP0; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - tx_reg = AR5K_NOQCU_TXDP1; - break; - default: - return -EINVAL; - } - } else { - /* - * Set the transmit queue descriptor pointer for - * the selected queue on QCU for 5211+ - * (this won't work if the queue is still active) - */ - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - return -EIO; - - tx_reg = AR5K_QUEUE_TXDP(queue); - } - - /* Set descriptor pointer */ - ath5k_hw_reg_write(ah, phys_addr, tx_reg); - - return 0; -} - -/** - * ath5k_hw_update_tx_triglevel - Update tx trigger level - * - * @ah: The &struct ath5k_hw - * @increase: Flag to force increase of trigger level - * - * This function increases/decreases the tx trigger level for the tx fifo - * buffer (aka FIFO threshold) that is used to indicate when PCU flushes - * the buffer and transmits it's data. Lowering this results sending small - * frames more quickly but can lead to tx underruns, raising it a lot can - * result other problems (i think bmiss is related). Right now we start with - * the lowest possible (64Bytes) and if we get tx underrun we increase it using - * the increase flag. Returns -EIO if we have have reached maximum/minimum. - * - * XXX: Link this with tx DMA size ? - * XXX: Use it to save interrupts ? - * TODO: Needs testing, i think it's related to bmiss... - */ -int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) -{ - u32 trigger_level, imr; - int ret = -EIO; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Disable interrupts by setting the mask - */ - imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); - - trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), - AR5K_TXCFG_TXFULL); - - if (!increase) { - if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) - goto done; - } else - trigger_level += - ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); - - /* - * Update trigger level on success - */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); - else - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_TXFULL, trigger_level); - - ret = 0; - -done: - /* - * Restore interrupt mask - */ - ath5k_hw_set_imr(ah, imr); - - return ret; -} - -/*******************\ -* Interrupt masking * -\*******************/ - -/** - * ath5k_hw_is_intr_pending - Check if we have pending interrupts - * - * @ah: The &struct ath5k_hw - * - * Check if we have pending interrupts to process. Returns 1 if we - * have pending interrupts and 0 if we haven't. - */ -bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; -} - -/** - * ath5k_hw_get_isr - Get interrupt status - * - * @ah: The @struct ath5k_hw - * @interrupt_mask: Driver's interrupt mask used to filter out - * interrupts in sw. - * - * This function is used inside our interrupt handler to determine the reason - * for the interrupt by reading Primary Interrupt Status Register. Returns an - * abstract interrupt status mask which is mostly ISR with some uncommon bits - * being mapped on some standard non hw-specific positions - * (check out &ath5k_int). - * - * NOTE: We use read-and-clear register, so after this function is called ISR - * is zeroed. - */ -int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) -{ - u32 data; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Read interrupt status from the Interrupt Status register - * on 5210 - */ - if (ah->ah_version == AR5K_AR5210) { - data = ath5k_hw_reg_read(ah, AR5K_ISR); - if (unlikely(data == AR5K_INT_NOCARD)) { - *interrupt_mask = data; - return -ENODEV; - } - } else { - /* - * Read interrupt status from Interrupt - * Status Register shadow copy (Read And Clear) - * - * Note: PISR/SISR Not available on 5210 - */ - data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); - if (unlikely(data == AR5K_INT_NOCARD)) { - *interrupt_mask = data; - return -ENODEV; - } - } - - /* - * Get abstract interrupt mask (driver-compatible) - */ - *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; - - if (ah->ah_version != AR5K_AR5210) { - u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2); - - /*HIU = Host Interface Unit (PCI etc)*/ - if (unlikely(data & (AR5K_ISR_HIUERR))) - *interrupt_mask |= AR5K_INT_FATAL; - - /*Beacon Not Ready*/ - if (unlikely(data & (AR5K_ISR_BNR))) - *interrupt_mask |= AR5K_INT_BNR; - - if (unlikely(sisr2 & (AR5K_SISR2_SSERR | - AR5K_SISR2_DPERR | - AR5K_SISR2_MCABT))) - *interrupt_mask |= AR5K_INT_FATAL; - - if (data & AR5K_ISR_TIM) - *interrupt_mask |= AR5K_INT_TIM; - - if (data & AR5K_ISR_BCNMISC) { - if (sisr2 & AR5K_SISR2_TIM) - *interrupt_mask |= AR5K_INT_TIM; - if (sisr2 & AR5K_SISR2_DTIM) - *interrupt_mask |= AR5K_INT_DTIM; - if (sisr2 & AR5K_SISR2_DTIM_SYNC) - *interrupt_mask |= AR5K_INT_DTIM_SYNC; - if (sisr2 & AR5K_SISR2_BCN_TIMEOUT) - *interrupt_mask |= AR5K_INT_BCN_TIMEOUT; - if (sisr2 & AR5K_SISR2_CAB_TIMEOUT) - *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; - } - - if (data & AR5K_ISR_RXDOPPLER) - *interrupt_mask |= AR5K_INT_RX_DOPPLER; - if (data & AR5K_ISR_QCBRORN) { - *interrupt_mask |= AR5K_INT_QCBRORN; - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), - AR5K_SISR3_QCBRORN); - } - if (data & AR5K_ISR_QCBRURN) { - *interrupt_mask |= AR5K_INT_QCBRURN; - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), - AR5K_SISR3_QCBRURN); - } - if (data & AR5K_ISR_QTRIG) { - *interrupt_mask |= AR5K_INT_QTRIG; - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR4), - AR5K_SISR4_QTRIG); - } - - if (data & AR5K_ISR_TXOK) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), - AR5K_SISR0_QCU_TXOK); - - if (data & AR5K_ISR_TXDESC) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), - AR5K_SISR0_QCU_TXDESC); - - if (data & AR5K_ISR_TXERR) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), - AR5K_SISR1_QCU_TXERR); - - if (data & AR5K_ISR_TXEOL) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), - AR5K_SISR1_QCU_TXEOL); - - if (data & AR5K_ISR_TXURN) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR2), - AR5K_SISR2_QCU_TXURN); - } else { - if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT - | AR5K_ISR_HIUERR | AR5K_ISR_DPERR))) - *interrupt_mask |= AR5K_INT_FATAL; - - /* - * XXX: BMISS interrupts may occur after association. - * I found this on 5210 code but it needs testing. If this is - * true we should disable them before assoc and re-enable them - * after a successful assoc + some jiffies. - interrupt_mask &= ~AR5K_INT_BMISS; - */ - } - - /* - * In case we didn't handle anything, - * print the register value. - */ - if (unlikely(*interrupt_mask == 0 && net_ratelimit())) - ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr); - - return 0; -} - -/** - * ath5k_hw_set_imr - Set interrupt mask - * - * @ah: The &struct ath5k_hw - * @new_mask: The new interrupt mask to be set - * - * Set the interrupt mask in hw to save interrupts. We do that by mapping - * ath5k_int bits to hw-specific bits to remove abstraction and writing - * Interrupt Mask Register. - */ -enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) -{ - enum ath5k_int old_mask, int_mask; - - old_mask = ah->ah_imr; - - /* - * Disable card interrupts to prevent any race conditions - * (they will be re-enabled afterwards if AR5K_INT GLOBAL - * is set again on the new mask). - */ - if (old_mask & AR5K_INT_GLOBAL) { - ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); - ath5k_hw_reg_read(ah, AR5K_IER); - } - - /* - * Add additional, chipset-dependent interrupt mask flags - * and write them to the IMR (interrupt mask register). - */ - int_mask = new_mask & AR5K_INT_COMMON; - - if (ah->ah_version != AR5K_AR5210) { - /* Preserve per queue TXURN interrupt mask */ - u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) - & AR5K_SIMR2_QCU_TXURN; - - if (new_mask & AR5K_INT_FATAL) { - int_mask |= AR5K_IMR_HIUERR; - simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR - | AR5K_SIMR2_DPERR); - } - - /*Beacon Not Ready*/ - if (new_mask & AR5K_INT_BNR) - int_mask |= AR5K_INT_BNR; - - if (new_mask & AR5K_INT_TIM) - int_mask |= AR5K_IMR_TIM; - - if (new_mask & AR5K_INT_TIM) - simr2 |= AR5K_SISR2_TIM; - if (new_mask & AR5K_INT_DTIM) - simr2 |= AR5K_SISR2_DTIM; - if (new_mask & AR5K_INT_DTIM_SYNC) - simr2 |= AR5K_SISR2_DTIM_SYNC; - if (new_mask & AR5K_INT_BCN_TIMEOUT) - simr2 |= AR5K_SISR2_BCN_TIMEOUT; - if (new_mask & AR5K_INT_CAB_TIMEOUT) - simr2 |= AR5K_SISR2_CAB_TIMEOUT; - - if (new_mask & AR5K_INT_RX_DOPPLER) - int_mask |= AR5K_IMR_RXDOPPLER; - - /* Note: Per queue interrupt masks - * are set via reset_tx_queue (qcu.c) */ - ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); - ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); - - } else { - if (new_mask & AR5K_INT_FATAL) - int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT - | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); - - ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); - } - - /* If RXNOFRM interrupt is masked disable it - * by setting AR5K_RXNOFRM to zero */ - if (!(new_mask & AR5K_INT_RXNOFRM)) - ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM); - - /* Store new interrupt mask */ - ah->ah_imr = new_mask; - - /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */ - if (new_mask & AR5K_INT_GLOBAL) { - ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); - ath5k_hw_reg_read(ah, AR5K_IER); - } - - return old_mask; -} - diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c deleted file mode 100644 index c0fb3b09ba45..000000000000 --- a/drivers/net/wireless/ath5k/eeprom.c +++ /dev/null @@ -1,1769 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2008-2009 Felix Fietkau - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*************************************\ -* EEPROM access functions and helpers * -\*************************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Read from eeprom - */ -static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) -{ - u32 status, timeout; - - ATH5K_TRACE(ah->ah_sc); - /* - * Initialize EEPROM access - */ - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); - (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); - } else { - ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); - AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, - AR5K_EEPROM_CMD_READ); - } - - for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { - status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); - if (status & AR5K_EEPROM_STAT_RDDONE) { - if (status & AR5K_EEPROM_STAT_RDERR) - return -EIO; - *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & - 0xffff); - return 0; - } - udelay(15); - } - - return -ETIMEDOUT; -} - -/* - * Translate binary channel representation in EEPROM to frequency - */ -static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, - unsigned int mode) -{ - u16 val; - - if (bin == AR5K_EEPROM_CHANNEL_DIS) - return bin; - - if (mode == AR5K_EEPROM_MODE_11A) { - if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) - val = (5 * bin) + 4800; - else - val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : - (bin * 10) + 5100; - } else { - if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) - val = bin + 2300; - else - val = bin + 2400; - } - - return val; -} - -/* - * Initialize eeprom & capabilities structs - */ -static int -ath5k_eeprom_init_header(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - int ret; - u16 val; - - /* - * Read values from EEPROM and store them in the capability structure - */ - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); - - /* Return if we have an old EEPROM */ - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) - return 0; - -#ifdef notyet - /* - * Validate the checksum of the EEPROM date. There are some - * devices with invalid EEPROMs. - */ - for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { - AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); - cksum ^= val; - } - if (cksum != AR5K_EEPROM_INFO_CKSUM) { - ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); - return -EIO; - } -#endif - - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), - ee_ant_gain); - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); - - /* XXX: Don't know which versions include these two */ - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2); - - if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3); - - if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) { - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6); - } - } - - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { - AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); - ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; - ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; - - AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); - ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; - ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; - } - - return 0; -} - - -/* - * Read antenna infos from eeprom - */ -static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, - unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 o = *offset; - u16 val; - int ret, i = 0; - - AR5K_EEPROM_READ(o++, val); - ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; - ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f; - ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; - ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; - ee->ee_ant_control[mode][i++] = val & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; - ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; - ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; - ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; - ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; - ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; - ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; - ee->ee_ant_control[mode][i++] = val & 0x3f; - - /* Get antenna modes */ - ah->ah_antenna[mode][0] = - (ee->ee_ant_control[mode][0] << 4); - ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = - ee->ee_ant_control[mode][1] | - (ee->ee_ant_control[mode][2] << 6) | - (ee->ee_ant_control[mode][3] << 12) | - (ee->ee_ant_control[mode][4] << 18) | - (ee->ee_ant_control[mode][5] << 24); - ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = - ee->ee_ant_control[mode][6] | - (ee->ee_ant_control[mode][7] << 6) | - (ee->ee_ant_control[mode][8] << 12) | - (ee->ee_ant_control[mode][9] << 18) | - (ee->ee_ant_control[mode][10] << 24); - - /* return new offset */ - *offset = o; - - return 0; -} - -/* - * Read supported modes and some mode-specific calibration data - * from eeprom - */ -static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, - unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 o = *offset; - u16 val; - int ret; - - ee->ee_n_piers[mode] = 0; - AR5K_EEPROM_READ(o++, val); - ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); - switch(mode) { - case AR5K_EEPROM_MODE_11A: - ee->ee_ob[mode][3] = (val >> 5) & 0x7; - ee->ee_db[mode][3] = (val >> 2) & 0x7; - ee->ee_ob[mode][2] = (val << 1) & 0x7; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ob[mode][2] |= (val >> 15) & 0x1; - ee->ee_db[mode][2] = (val >> 12) & 0x7; - ee->ee_ob[mode][1] = (val >> 9) & 0x7; - ee->ee_db[mode][1] = (val >> 6) & 0x7; - ee->ee_ob[mode][0] = (val >> 3) & 0x7; - ee->ee_db[mode][0] = val & 0x7; - break; - case AR5K_EEPROM_MODE_11G: - case AR5K_EEPROM_MODE_11B: - ee->ee_ob[mode][1] = (val >> 4) & 0x7; - ee->ee_db[mode][1] = val & 0x7; - break; - } - - AR5K_EEPROM_READ(o++, val); - ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; - ee->ee_thr_62[mode] = val & 0xff; - - if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) - ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; - - AR5K_EEPROM_READ(o++, val); - ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; - ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; - - AR5K_EEPROM_READ(o++, val); - ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; - - if ((val & 0xff) & 0x80) - ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); - else - ee->ee_noise_floor_thr[mode] = val & 0xff; - - if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) - ee->ee_noise_floor_thr[mode] = - mode == AR5K_EEPROM_MODE_11A ? -54 : -1; - - AR5K_EEPROM_READ(o++, val); - ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; - ee->ee_x_gain[mode] = (val >> 1) & 0xf; - ee->ee_xpd[mode] = val & 0x1; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) - ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { - AR5K_EEPROM_READ(o++, val); - ee->ee_false_detect[mode] = (val >> 6) & 0x7f; - - if (mode == AR5K_EEPROM_MODE_11A) - ee->ee_xr_power[mode] = val & 0x3f; - else { - ee->ee_ob[mode][0] = val & 0x7; - ee->ee_db[mode][0] = (val >> 3) & 0x7; - } - } - - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { - ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; - ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; - } else { - ee->ee_i_gain[mode] = (val >> 13) & 0x7; - - AR5K_EEPROM_READ(o++, val); - ee->ee_i_gain[mode] |= (val << 3) & 0x38; - - if (mode == AR5K_EEPROM_MODE_11G) { - ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6) - ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; - } - } - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && - mode == AR5K_EEPROM_MODE_11A) { - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; - } - - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) - goto done; - - /* Note: >= v5 have bg freq piers on another location - * so these freq piers are ignored for >= v5 (should be 0xff - * anyway) */ - switch(mode) { - case AR5K_EEPROM_MODE_11A: - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) - break; - - AR5K_EEPROM_READ(o++, val); - ee->ee_margin_tx_rx[mode] = val & 0x3f; - break; - case AR5K_EEPROM_MODE_11B: - AR5K_EEPROM_READ(o++, val); - - ee->ee_pwr_cal_b[0].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - ee->ee_pwr_cal_b[1].freq = - ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); - if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - AR5K_EEPROM_READ(o++, val); - ee->ee_pwr_cal_b[2].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; - break; - case AR5K_EEPROM_MODE_11G: - AR5K_EEPROM_READ(o++, val); - - ee->ee_pwr_cal_g[0].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - ee->ee_pwr_cal_g[1].freq = - ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); - if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - AR5K_EEPROM_READ(o++, val); - ee->ee_turbo_max_power[mode] = val & 0x7f; - ee->ee_xr_power[mode] = (val >> 7) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_pwr_cal_g[2].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { - AR5K_EEPROM_READ(o++, val); - ee->ee_cck_ofdm_gain_delta = val & 0xff; - } - break; - } - -done: - /* return new offset */ - *offset = o; - - return 0; -} - -/* - * Read turbo mode information on newer EEPROM versions - */ -static int -ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, - u32 *offset, unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 o = *offset; - u16 val; - int ret; - - if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) - return 0; - - switch (mode){ - case AR5K_EEPROM_MODE_11A: - ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f; - - ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7; - AR5K_EEPROM_READ(o++, val); - ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3; - ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f; - - ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f; - AR5K_EEPROM_READ(o++, val); - ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7; - ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff; - - if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2) - ee->ee_pd_gain_overlap = (val >> 9) & 0xf; - break; - case AR5K_EEPROM_MODE_11G: - ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f; - - ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7; - AR5K_EEPROM_READ(o++, val); - ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1; - ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f; - - ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f; - AR5K_EEPROM_READ(o++, val); - ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5; - ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff; - break; - } - - /* return new offset */ - *offset = o; - - return 0; -} - -/* Read mode-specific data (except power calibration data) */ -static int -ath5k_eeprom_init_modes(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 mode_offset[3]; - unsigned int mode; - u32 offset; - int ret; - - /* - * Get values for all modes - */ - mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); - mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); - mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); - - ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] = - AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { - offset = mode_offset[mode]; - - ret = ath5k_eeprom_read_ants(ah, &offset, mode); - if (ret) - return ret; - - ret = ath5k_eeprom_read_modes(ah, &offset, mode); - if (ret) - return ret; - - ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode); - if (ret) - return ret; - } - - /* override for older eeprom versions for better performance */ - if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) { - ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15; - ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28; - ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28; - } - - return 0; -} - -/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff - * frequency mask) */ -static inline int -ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, - struct ath5k_chan_pcal_info *pc, unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - int o = *offset; - int i = 0; - u8 freq1, freq2; - int ret; - u16 val; - - ee->ee_n_piers[mode] = 0; - while(i < max) { - AR5K_EEPROM_READ(o++, val); - - freq1 = val & 0xff; - if (!freq1) - break; - - pc[i++].freq = ath5k_eeprom_bin2freq(ee, - freq1, mode); - ee->ee_n_piers[mode]++; - - freq2 = (val >> 8) & 0xff; - if (!freq2) - break; - - pc[i++].freq = ath5k_eeprom_bin2freq(ee, - freq2, mode); - ee->ee_n_piers[mode]++; - } - - /* return new offset */ - *offset = o; - - return 0; -} - -/* Read frequency piers for 802.11a */ -static int -ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; - int i, ret; - u16 val; - u8 mask; - - if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { - ath5k_eeprom_read_freq_list(ah, &offset, - AR5K_EEPROM_N_5GHZ_CHAN, pcal, - AR5K_EEPROM_MODE_11A); - } else { - mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); - - AR5K_EEPROM_READ(offset++, val); - pcal[0].freq = (val >> 9) & mask; - pcal[1].freq = (val >> 2) & mask; - pcal[2].freq = (val << 5) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[2].freq |= (val >> 11) & 0x1f; - pcal[3].freq = (val >> 4) & mask; - pcal[4].freq = (val << 3) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[4].freq |= (val >> 13) & 0x7; - pcal[5].freq = (val >> 6) & mask; - pcal[6].freq = (val << 1) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[6].freq |= (val >> 15) & 0x1; - pcal[7].freq = (val >> 8) & mask; - pcal[8].freq = (val >> 1) & mask; - pcal[9].freq = (val << 6) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[9].freq |= (val >> 10) & 0x3f; - - /* Fixed number of piers */ - ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; - - for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { - pcal[i].freq = ath5k_eeprom_bin2freq(ee, - pcal[i].freq, AR5K_EEPROM_MODE_11A); - } - } - - return 0; -} - -/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ -static inline int -ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcal; - - switch(mode) { - case AR5K_EEPROM_MODE_11B: - pcal = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - pcal = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - ath5k_eeprom_read_freq_list(ah, &offset, - AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, - mode); - - return 0; -} - -/* - * Read power calibration for RF5111 chips - * - * For RF5111 we have an XPD -eXternal Power Detector- curve - * for each calibrated channel. Each curve has 0,5dB Power steps - * on x axis and PCDAC steps (offsets) on y axis and looks like an - * exponential function. To recreate the curve we read 11 points - * here and interpolate later. - */ - -/* Used to match PCDAC steps with power values on RF5111 chips - * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC - * steps that match with the power values we read from eeprom. On - * older eeprom versions (< 3.2) these steps are equaly spaced at - * 10% of the pcdac curve -until the curve reaches it's maximum- - * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) - * these 11 steps are spaced in a different way. This function returns - * the pcdac steps based on eeprom version and curve min/max so that we - * can have pcdac/pwr points. - */ -static inline void -ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) -{ - const static u16 intercepts3[] = - { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; - const static u16 intercepts3_2[] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - const u16 *ip; - int i; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) - ip = intercepts3_2; - else - ip = intercepts3; - - for (i = 0; i < ARRAY_SIZE(intercepts3); i++) - vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; -} - -/* Convert RF5111 specific data to generic raw data - * used by interpolation code */ -static int -ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, - struct ath5k_chan_pcal_info *chinfo) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf5111 *pcinfo; - struct ath5k_pdgain_info *pd; - u8 pier, point, idx; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - - /* Fill raw data for each calibration pier */ - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - - pcinfo = &chinfo[pier].rf5111_info; - - /* Allocate pd_curves for this cal pier */ - chinfo[pier].pd_curves = - kcalloc(AR5K_EEPROM_N_PD_CURVES, - sizeof(struct ath5k_pdgain_info), - GFP_KERNEL); - - if (!chinfo[pier].pd_curves) - return -ENOMEM; - - /* Only one curve for RF5111 - * find out which one and place - * in in pd_curves. - * Note: ee_x_gain is reversed here */ - for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { - - if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) { - pdgain_idx[0] = idx; - break; - } - } - - ee->ee_pd_gains[mode] = 1; - - pd = &chinfo[pier].pd_curves[idx]; - - pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, - sizeof(u8), GFP_KERNEL); - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, - sizeof(s16), GFP_KERNEL); - if (!pd->pd_pwr) - return -ENOMEM; - - /* Fill raw dataset - * (convert power to 0.25dB units - * for RF5112 combatibility) */ - for (point = 0; point < pd->pd_points; point++) { - - /* Absolute values */ - pd->pd_pwr[point] = 2 * pcinfo->pwr[point]; - - /* Already sorted */ - pd->pd_step[point] = pcinfo->pcdac[point]; - } - - /* Set min/max pwr */ - chinfo[pier].min_pwr = pd->pd_pwr[0]; - chinfo[pier].max_pwr = pd->pd_pwr[10]; - - } - - return 0; -} - -/* Parse EEPROM data */ -static int -ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcal; - int offset, ret; - int i; - u16 val; - - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - switch(mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - - ret = ath5k_eeprom_init_11a_pcal_freq(ah, - offset + AR5K_EEPROM_GROUP1_OFFSET); - if (ret < 0) - return ret; - - offset += AR5K_EEPROM_GROUP2_OFFSET; - pcal = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header) && - !AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - - pcal = ee->ee_pwr_cal_b; - offset += AR5K_EEPROM_GROUP3_OFFSET; - - /* fixed piers */ - pcal[0].freq = 2412; - pcal[1].freq = 2447; - pcal[2].freq = 2484; - ee->ee_n_piers[mode] = 3; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - - pcal = ee->ee_pwr_cal_g; - offset += AR5K_EEPROM_GROUP4_OFFSET; - - /* fixed piers */ - pcal[0].freq = 2312; - pcal[1].freq = 2412; - pcal[2].freq = 2484; - ee->ee_n_piers[mode] = 3; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - struct ath5k_chan_pcal_info_rf5111 *cdata = - &pcal[i].rf5111_info; - - AR5K_EEPROM_READ(offset++, val); - cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M); - cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M); - cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[0] |= ((val >> 14) & 0x3); - cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M); - cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M); - cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[3] |= ((val >> 12) & 0xf); - cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M); - cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M); - cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M); - cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[8] |= ((val >> 14) & 0x3); - cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M); - cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M); - - ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, - cdata->pcdac_max, cdata->pcdac); - } - - return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal); -} - - -/* - * Read power calibration for RF5112 chips - * - * For RF5112 we have 4 XPD -eXternal Power Detector- curves - * for each calibrated channel on 0, -6, -12 and -18dbm but we only - * use the higher (3) and the lower (0) curves. Each curve has 0.5dB - * power steps on x axis and PCDAC steps on y axis and looks like a - * linear function. To recreate the curve and pass the power values - * on hw, we read 4 points for xpd 0 (lower gain -> max power) - * and 3 points for xpd 3 (higher gain -> lower power) here and - * interpolate later. - * - * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. - */ - -/* Convert RF5112 specific data to generic raw data - * used by interpolation code */ -static int -ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, - struct ath5k_chan_pcal_info *chinfo) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf5112 *pcinfo; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - unsigned int pier, pdg, point; - - /* Fill raw data for each calibration pier */ - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - - pcinfo = &chinfo[pier].rf5112_info; - - /* Allocate pd_curves for this cal pier */ - chinfo[pier].pd_curves = - kcalloc(AR5K_EEPROM_N_PD_CURVES, - sizeof(struct ath5k_pdgain_info), - GFP_KERNEL); - - if (!chinfo[pier].pd_curves) - return -ENOMEM; - - /* Fill pd_curves */ - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - - u8 idx = pdgain_idx[pdg]; - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[idx]; - - /* Lowest gain curve (max power) */ - if (pdg == 0) { - /* One more point for better accuracy */ - pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(pd->pd_points, - sizeof(u8), GFP_KERNEL); - - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(pd->pd_points, - sizeof(s16), GFP_KERNEL); - - if (!pd->pd_pwr) - return -ENOMEM; - - - /* Fill raw dataset - * (all power levels are in 0.25dB units) */ - pd->pd_step[0] = pcinfo->pcdac_x0[0]; - pd->pd_pwr[0] = pcinfo->pwr_x0[0]; - - for (point = 1; point < pd->pd_points; - point++) { - /* Absolute values */ - pd->pd_pwr[point] = - pcinfo->pwr_x0[point]; - - /* Deltas */ - pd->pd_step[point] = - pd->pd_step[point - 1] + - pcinfo->pcdac_x0[point]; - } - - /* Set min power for this frequency */ - chinfo[pier].min_pwr = pd->pd_pwr[0]; - - /* Highest gain curve (min power) */ - } else if (pdg == 1) { - - pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(pd->pd_points, - sizeof(u8), GFP_KERNEL); - - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(pd->pd_points, - sizeof(s16), GFP_KERNEL); - - if (!pd->pd_pwr) - return -ENOMEM; - - /* Fill raw dataset - * (all power levels are in 0.25dB units) */ - for (point = 0; point < pd->pd_points; - point++) { - /* Absolute values */ - pd->pd_pwr[point] = - pcinfo->pwr_x3[point]; - - /* Fixed points */ - pd->pd_step[point] = - pcinfo->pcdac_x3[point]; - } - - /* Since we have a higher gain curve - * override min power */ - chinfo[pier].min_pwr = pd->pd_pwr[0]; - } - } - } - - return 0; -} - -/* Parse EEPROM data */ -static int -ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; - struct ath5k_chan_pcal_info *gen_chan_info; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - u32 offset; - u8 i, c; - u16 val; - int ret; - u8 pd_gains = 0; - - /* Count how many curves we have and - * identify them (which one of the 4 - * available curves we have on each count). - * Curves are stored from lower (x0) to - * higher (x3) gain */ - for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) { - /* ee_x_gain[mode] is x gain mask */ - if ((ee->ee_x_gain[mode] >> i) & 0x1) - pdgain_idx[pd_gains++] = i; - } - ee->ee_pd_gains[mode] = pd_gains; - - if (pd_gains == 0 || pd_gains > 2) - return -EINVAL; - - switch (mode) { - case AR5K_EEPROM_MODE_11A: - /* - * Read 5GHz EEPROM channels - */ - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - ath5k_eeprom_init_11a_pcal_freq(ah, offset); - - offset += AR5K_EEPROM_GROUP2_OFFSET; - gen_chan_info = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += AR5K_EEPROM_GROUP3_OFFSET; - - /* NB: frequency piers parsed during mode init */ - gen_chan_info = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += AR5K_EEPROM_GROUP4_OFFSET; - else if (AR5K_EEPROM_HDR_11B(ee->ee_header)) - offset += AR5K_EEPROM_GROUP2_OFFSET; - - /* NB: frequency piers parsed during mode init */ - gen_chan_info = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - chan_pcal_info = &gen_chan_info[i].rf5112_info; - - /* Power values in quarter dB - * for the lower xpd gain curve - * (0 dBm -> higher output power) */ - for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff); - chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff); - } - - /* PCDAC steps - * corresponding to the above power - * measurements */ - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pcdac_x0[1] = (val & 0x1f); - chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); - chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); - - /* Power values in quarter dB - * for the higher xpd gain curve - * (18 dBm -> lower output power) */ - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff); - chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff); - - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x3[2] = (val & 0xff); - - /* PCDAC steps - * corresponding to the above power - * measurements (fixed) */ - chan_pcal_info->pcdac_x3[0] = 20; - chan_pcal_info->pcdac_x3[1] = 35; - chan_pcal_info->pcdac_x3[2] = 63; - - if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { - chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f); - - /* Last xpd0 power level is also channel maximum */ - gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; - } else { - chan_pcal_info->pcdac_x0[0] = 1; - gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff); - } - - } - - return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info); -} - - -/* - * Read power calibration for RF2413 chips - * - * For RF2413 we have a Power to PDDAC table (Power Detector) - * instead of a PCDAC and 4 pd gain curves for each calibrated channel. - * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y - * axis and looks like an exponential function like the RF5111 curve. - * - * To recreate the curves we read here the points and interpolate - * later. Note that in most cases only 2 (higher and lower) curves are - * used (like RF5112) but vendors have the oportunity to include all - * 4 curves on eeprom. The final curve (higher power) has an extra - * point for better accuracy like RF5112. - */ - -/* For RF2413 power calibration data doesn't start on a fixed location and - * if a mode is not supported, it's section is missing -not zeroed-. - * So we need to calculate the starting offset for each section by using - * these two functions */ - -/* Return the size of each section based on the mode and the number of pd - * gains available (maximum 4). */ -static inline unsigned int -ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) -{ - static const unsigned int pdgains_size[] = { 4, 6, 9, 12 }; - unsigned int sz; - - sz = pdgains_size[ee->ee_pd_gains[mode] - 1]; - sz *= ee->ee_n_piers[mode]; - - return sz; -} - -/* Return the starting offset for a section based on the modes supported - * and each section's size. */ -static unsigned int -ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) -{ - u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4); - - switch(mode) { - case AR5K_EEPROM_MODE_11G: - if (AR5K_EEPROM_HDR_11B(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, - AR5K_EEPROM_MODE_11B) + - AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - /* fall through */ - case AR5K_EEPROM_MODE_11B: - if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, - AR5K_EEPROM_MODE_11A) + - AR5K_EEPROM_N_5GHZ_CHAN / 2; - /* fall through */ - case AR5K_EEPROM_MODE_11A: - break; - default: - break; - } - - return offset; -} - -/* Convert RF2413 specific data to generic raw data - * used by interpolation code */ -static int -ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, - struct ath5k_chan_pcal_info *chinfo) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf2413 *pcinfo; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - unsigned int pier, pdg, point; - - /* Fill raw data for each calibration pier */ - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - - pcinfo = &chinfo[pier].rf2413_info; - - /* Allocate pd_curves for this cal pier */ - chinfo[pier].pd_curves = - kcalloc(AR5K_EEPROM_N_PD_CURVES, - sizeof(struct ath5k_pdgain_info), - GFP_KERNEL); - - if (!chinfo[pier].pd_curves) - return -ENOMEM; - - /* Fill pd_curves */ - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - - u8 idx = pdgain_idx[pdg]; - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[idx]; - - /* One more point for the highest power - * curve (lowest gain) */ - if (pdg == ee->ee_pd_gains[mode] - 1) - pd->pd_points = AR5K_EEPROM_N_PD_POINTS; - else - pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(pd->pd_points, - sizeof(u8), GFP_KERNEL); - - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(pd->pd_points, - sizeof(s16), GFP_KERNEL); - - if (!pd->pd_pwr) - return -ENOMEM; - - /* Fill raw dataset - * convert all pwr levels to - * quarter dB for RF5112 combatibility */ - pd->pd_step[0] = pcinfo->pddac_i[pdg]; - pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg]; - - for (point = 1; point < pd->pd_points; point++) { - - pd->pd_pwr[point] = pd->pd_pwr[point - 1] + - 2 * pcinfo->pwr[pdg][point - 1]; - - pd->pd_step[point] = pd->pd_step[point - 1] + - pcinfo->pddac[pdg][point - 1]; - - } - - /* Highest gain curve -> min power */ - if (pdg == 0) - chinfo[pier].min_pwr = pd->pd_pwr[0]; - - /* Lowest gain curve -> max power */ - if (pdg == ee->ee_pd_gains[mode] - 1) - chinfo[pier].max_pwr = - pd->pd_pwr[pd->pd_points - 1]; - } - } - - return 0; -} - -/* Parse EEPROM data */ -static int -ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf2413 *pcinfo; - struct ath5k_chan_pcal_info *chinfo; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - u32 offset; - int idx, i, ret; - u16 val; - u8 pd_gains = 0; - - /* Count how many curves we have and - * identify them (which one of the 4 - * available curves we have on each count). - * Curves are stored from higher to - * lower gain so we go backwards */ - for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) { - /* ee_x_gain[mode] is x gain mask */ - if ((ee->ee_x_gain[mode] >> idx) & 0x1) - pdgain_idx[pd_gains++] = idx; - - } - ee->ee_pd_gains[mode] = pd_gains; - - if (pd_gains == 0) - return -EINVAL; - - offset = ath5k_cal_data_offset_2413(ee, mode); - switch (mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - - ath5k_eeprom_init_11a_pcal_freq(ah, offset); - offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; - chinfo = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) - return 0; - - ath5k_eeprom_init_11bg_2413(ah, mode, offset); - offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - chinfo = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - - ath5k_eeprom_init_11bg_2413(ah, mode, offset); - offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - chinfo = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - pcinfo = &chinfo[i].rf2413_info; - - /* - * Read pwr_i, pddac_i and the first - * 2 pd points (pwr, pddac) - */ - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr_i[0] = val & 0x1f; - pcinfo->pddac_i[0] = (val >> 5) & 0x7f; - pcinfo->pwr[0][0] = (val >> 12) & 0xf; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[0][0] = val & 0x3f; - pcinfo->pwr[0][1] = (val >> 6) & 0xf; - pcinfo->pddac[0][1] = (val >> 10) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[0][2] = val & 0xf; - pcinfo->pddac[0][2] = (val >> 4) & 0x3f; - - pcinfo->pwr[0][3] = 0; - pcinfo->pddac[0][3] = 0; - - if (pd_gains > 1) { - /* - * Pd gain 0 is not the last pd gain - * so it only has 2 pd points. - * Continue wih pd gain 1. - */ - pcinfo->pwr_i[1] = (val >> 10) & 0x1f; - - pcinfo->pddac_i[1] = (val >> 15) & 0x1; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac_i[1] |= (val & 0x3F) << 1; - - pcinfo->pwr[1][0] = (val >> 6) & 0xf; - pcinfo->pddac[1][0] = (val >> 10) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[1][1] = val & 0xf; - pcinfo->pddac[1][1] = (val >> 4) & 0x3f; - pcinfo->pwr[1][2] = (val >> 10) & 0xf; - - pcinfo->pddac[1][2] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[1][2] |= (val & 0xF) << 2; - - pcinfo->pwr[1][3] = 0; - pcinfo->pddac[1][3] = 0; - } else if (pd_gains == 1) { - /* - * Pd gain 0 is the last one so - * read the extra point. - */ - pcinfo->pwr[0][3] = (val >> 10) & 0xf; - - pcinfo->pddac[0][3] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[0][3] |= (val & 0xF) << 2; - } - - /* - * Proceed with the other pd_gains - * as above. - */ - if (pd_gains > 2) { - pcinfo->pwr_i[2] = (val >> 4) & 0x1f; - pcinfo->pddac_i[2] = (val >> 9) & 0x7f; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[2][0] = (val >> 0) & 0xf; - pcinfo->pddac[2][0] = (val >> 4) & 0x3f; - pcinfo->pwr[2][1] = (val >> 10) & 0xf; - - pcinfo->pddac[2][1] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[2][1] |= (val & 0xF) << 2; - - pcinfo->pwr[2][2] = (val >> 4) & 0xf; - pcinfo->pddac[2][2] = (val >> 8) & 0x3f; - - pcinfo->pwr[2][3] = 0; - pcinfo->pddac[2][3] = 0; - } else if (pd_gains == 2) { - pcinfo->pwr[1][3] = (val >> 4) & 0xf; - pcinfo->pddac[1][3] = (val >> 8) & 0x3f; - } - - if (pd_gains > 3) { - pcinfo->pwr_i[3] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2; - - pcinfo->pddac_i[3] = (val >> 3) & 0x7f; - pcinfo->pwr[3][0] = (val >> 10) & 0xf; - pcinfo->pddac[3][0] = (val >> 14) & 0x3; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[3][0] |= (val & 0xF) << 2; - pcinfo->pwr[3][1] = (val >> 4) & 0xf; - pcinfo->pddac[3][1] = (val >> 8) & 0x3f; - - pcinfo->pwr[3][2] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2; - - pcinfo->pddac[3][2] = (val >> 2) & 0x3f; - pcinfo->pwr[3][3] = (val >> 8) & 0xf; - - pcinfo->pddac[3][3] = (val >> 12) & 0xF; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4; - } else if (pd_gains == 3) { - pcinfo->pwr[2][3] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2; - - pcinfo->pddac[2][3] = (val >> 2) & 0x3f; - } - } - - return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo); -} - - -/* - * Read per rate target power (this is the maximum tx power - * supported by the card). This info is used when setting - * tx power, no matter the channel. - * - * This also works for v5 EEPROMs. - */ -static int -ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_rate_pcal_info *rate_pcal_info; - u8 *rate_target_pwr_num; - u32 offset; - u16 val; - int ret, i; - - offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); - rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; - switch (mode) { - case AR5K_EEPROM_MODE_11A: - offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); - rate_pcal_info = ee->ee_rate_tpwr_a; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; - break; - case AR5K_EEPROM_MODE_11B: - offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); - rate_pcal_info = ee->ee_rate_tpwr_b; - ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */ - break; - case AR5K_EEPROM_MODE_11G: - offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version); - rate_pcal_info = ee->ee_rate_tpwr_g; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN; - break; - default: - return -EINVAL; - } - - /* Different freq mask for older eeproms (<= v3.2) */ - if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) { - for (i = 0; i < (*rate_target_pwr_num); i++) { - AR5K_EEPROM_READ(offset++, val); - rate_pcal_info[i].freq = - ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode); - - rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f); - rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - - if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || - val == 0) { - (*rate_target_pwr_num) = i; - break; - } - - rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7); - rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f); - rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f); - } - } else { - for (i = 0; i < (*rate_target_pwr_num); i++) { - AR5K_EEPROM_READ(offset++, val); - rate_pcal_info[i].freq = - ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); - - rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f); - rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - - if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || - val == 0) { - (*rate_target_pwr_num) = i; - break; - } - - rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf; - rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f); - rate_pcal_info[i].target_power_54 = (val & 0x3f); - } - } - - return 0; -} - -/* - * Read per channel calibration info from EEPROM - * - * This info is used to calibrate the baseband power table. Imagine - * that for each channel there is a power curve that's hw specific - * (depends on amplifier etc) and we try to "correct" this curve using - * offests we pass on to phy chip (baseband -> before amplifier) so that - * it can use accurate power values when setting tx power (takes amplifier's - * performance on each channel into account). - * - * EEPROM provides us with the offsets for some pre-calibrated channels - * and we have to interpolate to create the full table for these channels and - * also the table for any channel. - */ -static int -ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - int (*read_pcal)(struct ath5k_hw *hw, int mode); - int mode; - int err; - - if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) && - (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1)) - read_pcal = ath5k_eeprom_read_pcal_info_5112; - else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) && - (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2)) - read_pcal = ath5k_eeprom_read_pcal_info_2413; - else - read_pcal = ath5k_eeprom_read_pcal_info_5111; - - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; - mode++) { - err = read_pcal(ah, mode); - if (err) - return err; - - err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode); - if (err < 0) - return err; - } - - return 0; -} - -static int -ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *chinfo; - u8 pier, pdg; - - switch (mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - if (!chinfo[pier].pd_curves) - continue; - - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[pdg]; - - if (pd != NULL) { - kfree(pd->pd_step); - kfree(pd->pd_pwr); - } - } - - kfree(chinfo[pier].pd_curves); - } - - return 0; -} - -void -ath5k_eeprom_detach(struct ath5k_hw *ah) -{ - u8 mode; - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) - ath5k_eeprom_free_pcal_info(ah, mode); -} - -/* Read conformance test limits used for regulatory control */ -static int -ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_edge_power *rep; - unsigned int fmask, pmask; - unsigned int ctl_mode; - int ret, i, j; - u32 offset; - u16 val; - - pmask = AR5K_EEPROM_POWER_M; - fmask = AR5K_EEPROM_FREQ_M(ee->ee_version); - offset = AR5K_EEPROM_CTL(ee->ee_version); - ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version); - for (i = 0; i < ee->ee_ctls; i += 2) { - AR5K_EEPROM_READ(offset++, val); - ee->ee_ctl[i] = (val >> 8) & 0xff; - ee->ee_ctl[i + 1] = val & 0xff; - } - - offset = AR5K_EEPROM_GROUP8_OFFSET; - if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) - offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) - - AR5K_EEPROM_GROUP5_OFFSET; - else - offset += AR5K_EEPROM_GROUPS_START(ee->ee_version); - - rep = ee->ee_ctl_pwr; - for(i = 0; i < ee->ee_ctls; i++) { - switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) { - case AR5K_CTL_11A: - case AR5K_CTL_TURBO: - ctl_mode = AR5K_EEPROM_MODE_11A; - break; - default: - ctl_mode = AR5K_EEPROM_MODE_11G; - break; - } - if (ee->ee_ctl[i] == 0) { - if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) - offset += 8; - else - offset += 7; - rep += AR5K_EEPROM_N_EDGES; - continue; - } - if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { - for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { - AR5K_EEPROM_READ(offset++, val); - rep[j].freq = (val >> 8) & fmask; - rep[j + 1].freq = val & fmask; - } - for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { - AR5K_EEPROM_READ(offset++, val); - rep[j].edge = (val >> 8) & pmask; - rep[j].flag = (val >> 14) & 1; - rep[j + 1].edge = val & pmask; - rep[j + 1].flag = (val >> 6) & 1; - } - } else { - AR5K_EEPROM_READ(offset++, val); - rep[0].freq = (val >> 9) & fmask; - rep[1].freq = (val >> 2) & fmask; - rep[2].freq = (val << 5) & fmask; - - AR5K_EEPROM_READ(offset++, val); - rep[2].freq |= (val >> 11) & 0x1f; - rep[3].freq = (val >> 4) & fmask; - rep[4].freq = (val << 3) & fmask; - - AR5K_EEPROM_READ(offset++, val); - rep[4].freq |= (val >> 13) & 0x7; - rep[5].freq = (val >> 6) & fmask; - rep[6].freq = (val << 1) & fmask; - - AR5K_EEPROM_READ(offset++, val); - rep[6].freq |= (val >> 15) & 0x1; - rep[7].freq = (val >> 8) & fmask; - - rep[0].edge = (val >> 2) & pmask; - rep[1].edge = (val << 4) & pmask; - - AR5K_EEPROM_READ(offset++, val); - rep[1].edge |= (val >> 12) & 0xf; - rep[2].edge = (val >> 6) & pmask; - rep[3].edge = val & pmask; - - AR5K_EEPROM_READ(offset++, val); - rep[4].edge = (val >> 10) & pmask; - rep[5].edge = (val >> 4) & pmask; - rep[6].edge = (val << 2) & pmask; - - AR5K_EEPROM_READ(offset++, val); - rep[6].edge |= (val >> 14) & 0x3; - rep[7].edge = (val >> 8) & pmask; - } - for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) { - rep[j].freq = ath5k_eeprom_bin2freq(ee, - rep[j].freq, ctl_mode); - } - rep += AR5K_EEPROM_N_EDGES; - } - - return 0; -} - - -/* - * Initialize eeprom power tables - */ -int -ath5k_eeprom_init(struct ath5k_hw *ah) -{ - int err; - - err = ath5k_eeprom_init_header(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_init_modes(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_read_pcal_info(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_read_ctl_info(ah); - if (err < 0) - return err; - - return 0; -} - -/* - * Read the MAC address from eeprom - */ -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) -{ - u8 mac_d[ETH_ALEN] = {}; - u32 total, offset; - u16 data; - int octet, ret; - - ret = ath5k_hw_eeprom_read(ah, 0x20, &data); - if (ret) - return ret; - - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { - ret = ath5k_hw_eeprom_read(ah, offset, &data); - if (ret) - return ret; - - total += data; - mac_d[octet + 1] = data & 0xff; - mac_d[octet] = data >> 8; - octet += 2; - } - - if (!total || total == 3 * 0xffff) - return -EINVAL; - - memcpy(mac, mac_d, ETH_ALEN); - - return 0; -} - -bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah) -{ - u16 data; - - ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data); - - if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data) - return true; - else - return false; -} - diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h deleted file mode 100644 index b0c0606dea0b..000000000000 --- a/drivers/net/wireless/ath5k/eeprom.h +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) - */ -#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ -#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ -#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ -#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ -#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ - -#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ -#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ -#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ -#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ -#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) -#define AR5K_EEPROM_INFO_CKSUM 0xffff -#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) - -#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ -#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ -#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ -#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ -#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ -#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */ -#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ -#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ -#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ -#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */ -#define AR5K_EEPROM_VERSION_4_4 0x4004 -#define AR5K_EEPROM_VERSION_4_5 0x4005 -#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ -#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */ -#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */ -#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */ -#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */ -#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */ - -#define AR5K_EEPROM_MODE_11A 0 -#define AR5K_EEPROM_MODE_11B 1 -#define AR5K_EEPROM_MODE_11G 2 - -#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ -#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) -#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) -#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) -#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ -#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ -#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) -#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ -#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ - -#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c -#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 -#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 -#define AR5K_EEPROM_RFKILL_POLARITY_S 1 - -/* Newer EEPROMs are using a different offset */ -#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ - (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) - -#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) -#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff)) -#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff)) - -/* Misc values available since EEPROM 4.0 */ -#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4) -#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) -#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1) -#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1) -#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) - -#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) -#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) -#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) -#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) - -#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) -#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff) -#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff) - -#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7) -#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f) -#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff) - -#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) -#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) -#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) -#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) - -#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) -#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) -#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) -#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) -#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) -#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) -#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) -#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) - -#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) -#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) -#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) -#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) -#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) -#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) -#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) -#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) - -/* calibration settings */ -#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) -#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) -#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) -#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ -#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */ -#define AR5K_EEPROM_GROUP1_OFFSET 0x0 -#define AR5K_EEPROM_GROUP2_OFFSET 0x5 -#define AR5K_EEPROM_GROUP3_OFFSET 0x37 -#define AR5K_EEPROM_GROUP4_OFFSET 0x46 -#define AR5K_EEPROM_GROUP5_OFFSET 0x55 -#define AR5K_EEPROM_GROUP6_OFFSET 0x65 -#define AR5K_EEPROM_GROUP7_OFFSET 0x69 -#define AR5K_EEPROM_GROUP8_OFFSET 0x6f - -#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ - AR5K_EEPROM_GROUP5_OFFSET, 0x0000) -#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ - AR5K_EEPROM_GROUP6_OFFSET, 0x0010) -#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ - AR5K_EEPROM_GROUP7_OFFSET, 0x0014) - -/* [3.1 - 3.3] */ -#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec -#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed - -#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ -#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ -#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ -#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ -#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 -#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ -#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 -#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ -#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 -#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ -#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 -#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ -#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 -#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ -#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 -#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ -#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 - -/* Some EEPROM defines */ -#define AR5K_EEPROM_EEP_SCALE 100 -#define AR5K_EEPROM_EEP_DELTA 10 -#define AR5K_EEPROM_N_MODES 3 -#define AR5K_EEPROM_N_5GHZ_CHAN 10 -#define AR5K_EEPROM_N_2GHZ_CHAN 3 -#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 -#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 -#define AR5K_EEPROM_MAX_CHAN 10 -#define AR5K_EEPROM_N_PWR_POINTS_5111 11 -#define AR5K_EEPROM_N_PCDAC 11 -#define AR5K_EEPROM_N_PHASE_CAL 5 -#define AR5K_EEPROM_N_TEST_FREQ 8 -#define AR5K_EEPROM_N_EDGES 8 -#define AR5K_EEPROM_N_INTERCEPTS 11 -#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) -#define AR5K_EEPROM_PCDAC_M 0x3f -#define AR5K_EEPROM_PCDAC_START 1 -#define AR5K_EEPROM_PCDAC_STOP 63 -#define AR5K_EEPROM_PCDAC_STEP 1 -#define AR5K_EEPROM_NON_EDGE_M 0x40 -#define AR5K_EEPROM_CHANNEL_POWER 8 -#define AR5K_EEPROM_N_OBDB 4 -#define AR5K_EEPROM_OBDB_DIS 0xffff -#define AR5K_EEPROM_CHANNEL_DIS 0xff -#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) -#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) -#define AR5K_EEPROM_MAX_CTLS 32 -#define AR5K_EEPROM_N_PD_CURVES 4 -#define AR5K_EEPROM_N_XPD0_POINTS 4 -#define AR5K_EEPROM_N_XPD3_POINTS 3 -#define AR5K_EEPROM_N_PD_GAINS 4 -#define AR5K_EEPROM_N_PD_POINTS 5 -#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 -#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 -#define AR5K_EEPROM_POWER_M 0x3f -#define AR5K_EEPROM_POWER_MIN 0 -#define AR5K_EEPROM_POWER_MAX 3150 -#define AR5K_EEPROM_POWER_STEP 50 -#define AR5K_EEPROM_POWER_TABLE_SIZE 64 -#define AR5K_EEPROM_N_POWER_LOC_11B 4 -#define AR5K_EEPROM_N_POWER_LOC_11G 6 -#define AR5K_EEPROM_I_GAIN 10 -#define AR5K_EEPROM_CCK_OFDM_DELTA 15 -#define AR5K_EEPROM_N_IQ_CAL 2 - -#define AR5K_EEPROM_READ(_o, _v) do { \ - ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ - if (ret) \ - return ret; \ -} while (0) - -#define AR5K_EEPROM_READ_HDR(_o, _v) \ - AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ - -enum ath5k_ant_setting { - AR5K_ANT_VARIABLE = 0, /* variable by programming */ - AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ - AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ - AR5K_ANT_MAX = 3, -}; - -enum ath5k_ctl_mode { - AR5K_CTL_11A = 0, - AR5K_CTL_11B = 1, - AR5K_CTL_11G = 2, - AR5K_CTL_TURBO = 3, - AR5K_CTL_TURBOG = 4, - AR5K_CTL_2GHT20 = 5, - AR5K_CTL_5GHT20 = 6, - AR5K_CTL_2GHT40 = 7, - AR5K_CTL_5GHT40 = 8, - AR5K_CTL_MODE_M = 15, -}; - -/* Default CTL ids for the 3 main reg domains. - * Atheros only uses these by default but vendors - * can have up to 32 different CTLs for different - * scenarios. Note that theese values are ORed with - * the mode id (above) so we can have up to 24 CTL - * datasets out of these 3 main regdomains. That leaves - * 8 ids that can be used by vendors and since 0x20 is - * missing from HAL sources i guess this is the set of - * custom CTLs vendors can use. */ -#define AR5K_CTL_FCC 0x10 -#define AR5K_CTL_CUSTOM 0x20 -#define AR5K_CTL_ETSI 0x30 -#define AR5K_CTL_MKK 0x40 - -/* Indicates a CTL with only mode set and - * no reg domain mapping, such CTLs are used - * for world roaming domains or simply when - * a reg domain is not set */ -#define AR5K_CTL_NO_REGDOMAIN 0xf0 - -/* Indicates an empty (invalid) CTL */ -#define AR5K_CTL_NO_CTL 0xff - -/* Per channel calibration data, used for power table setup */ -struct ath5k_chan_pcal_info_rf5111 { - /* Power levels in half dbm units - * for one power curve. */ - u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111]; - /* PCDAC table steps - * for the above values */ - u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111]; - /* Starting PCDAC step */ - u8 pcdac_min; - /* Final PCDAC step */ - u8 pcdac_max; -}; - -struct ath5k_chan_pcal_info_rf5112 { - /* Power levels in quarter dBm units - * for lower (0) and higher (3) - * level curves in 0.25dB units */ - s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; - s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; - /* PCDAC table steps - * for the above values */ - u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; - u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; -}; - -struct ath5k_chan_pcal_info_rf2413 { - /* Starting pwr/pddac values */ - s8 pwr_i[AR5K_EEPROM_N_PD_GAINS]; - u8 pddac_i[AR5K_EEPROM_N_PD_GAINS]; - /* (pwr,pddac) points - * power levels in 0.5dB units */ - s8 pwr[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_N_PD_POINTS]; - u8 pddac[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_N_PD_POINTS]; -}; - -enum ath5k_powertable_type { - AR5K_PWRTABLE_PWR_TO_PCDAC = 0, - AR5K_PWRTABLE_LINEAR_PCDAC = 1, - AR5K_PWRTABLE_PWR_TO_PDADC = 2, -}; - -struct ath5k_pdgain_info { - u8 pd_points; - u8 *pd_step; - /* Power values are in - * 0.25dB units */ - s16 *pd_pwr; -}; - -struct ath5k_chan_pcal_info { - /* Frequency */ - u16 freq; - /* Tx power boundaries */ - s16 max_pwr; - s16 min_pwr; - union { - struct ath5k_chan_pcal_info_rf5111 rf5111_info; - struct ath5k_chan_pcal_info_rf5112 rf5112_info; - struct ath5k_chan_pcal_info_rf2413 rf2413_info; - }; - /* Raw values used by phy code - * Curves are stored in order from lower - * gain to higher gain (max txpower -> min txpower) */ - struct ath5k_pdgain_info *pd_curves; -}; - -/* Per rate calibration data for each mode, - * used for rate power table setup. - * Note: Values in 0.5dB units */ -struct ath5k_rate_pcal_info { - u16 freq; /* Frequency */ - /* Power level for 6-24Mbit/s rates or - * 1Mb rate */ - u16 target_power_6to24; - /* Power level for 36Mbit rate or - * 2Mb rate */ - u16 target_power_36; - /* Power level for 48Mbit rate or - * 5.5Mbit rate */ - u16 target_power_48; - /* Power level for 54Mbit rate or - * 11Mbit rate */ - u16 target_power_54; -}; - -/* Power edges for conformance test limits */ -struct ath5k_edge_power { - u16 freq; - u16 edge; /* in half dBm */ - bool flag; -}; - -/* EEPROM calibration data */ -struct ath5k_eeprom_info { - - /* Header information */ - u16 ee_magic; - u16 ee_protect; - u16 ee_regdomain; - u16 ee_version; - u16 ee_header; - u16 ee_ant_gain; - u16 ee_misc0; - u16 ee_misc1; - u16 ee_misc2; - u16 ee_misc3; - u16 ee_misc4; - u16 ee_misc5; - u16 ee_misc6; - u16 ee_cck_ofdm_gain_delta; - u16 ee_cck_ofdm_power_delta; - u16 ee_scaled_cck_delta; - - /* RF Calibration settings (reset, rfregs) */ - u16 ee_i_cal[AR5K_EEPROM_N_MODES]; - u16 ee_q_cal[AR5K_EEPROM_N_MODES]; - u16 ee_fixed_bias[AR5K_EEPROM_N_MODES]; - u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; - u16 ee_xr_power[AR5K_EEPROM_N_MODES]; - u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; - u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES]; - u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; - u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; - u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; - u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; - u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; - u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; - u16 ee_thr_62[AR5K_EEPROM_N_MODES]; - u16 ee_xlna_gain[AR5K_EEPROM_N_MODES]; - u16 ee_xpd[AR5K_EEPROM_N_MODES]; - u16 ee_x_gain[AR5K_EEPROM_N_MODES]; - u16 ee_i_gain[AR5K_EEPROM_N_MODES]; - u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; - u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES]; - u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES]; - u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES]; - - /* Power calibration data */ - u16 ee_false_detect[AR5K_EEPROM_N_MODES]; - - /* Number of pd gain curves per mode */ - u8 ee_pd_gains[AR5K_EEPROM_N_MODES]; - /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */ - u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS]; - - u8 ee_n_piers[AR5K_EEPROM_N_MODES]; - struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]; - struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - - /* Per rate target power levels */ - u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]; - struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]; - struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - - /* Conformance test limits (Unused) */ - u8 ee_ctls; - u8 ee_ctl[AR5K_EEPROM_MAX_CTLS]; - struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS]; - - /* Noise Floor Calibration settings */ - s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; - s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; - s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; - s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES]; - s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES]; - s8 ee_pd_gain_overlap; - - u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; -}; - diff --git a/drivers/net/wireless/ath5k/gpio.c b/drivers/net/wireless/ath5k/gpio.c deleted file mode 100644 index 64a27e73d02e..000000000000 --- a/drivers/net/wireless/ath5k/gpio.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/****************\ - GPIO Functions -\****************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Set led state - */ -void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) -{ - u32 led; - /*5210 has different led mode handling*/ - u32 led_5210; - - ATH5K_TRACE(ah->ah_sc); - - /*Reset led status*/ - if (ah->ah_version != AR5K_AR5210) - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); - - /* - * Some blinking values, define at your wish - */ - switch (state) { - case AR5K_LED_SCAN: - case AR5K_LED_AUTH: - led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; - led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; - break; - - case AR5K_LED_INIT: - led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; - led_5210 = AR5K_PCICFG_LED_PEND; - break; - - case AR5K_LED_ASSOC: - case AR5K_LED_RUN: - led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; - led_5210 = AR5K_PCICFG_LED_ASSOC; - break; - - default: - led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; - led_5210 = AR5K_PCICFG_LED_PEND; - break; - } - - /*Write new status to the register*/ - if (ah->ah_version != AR5K_AR5210) - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); - else - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); -} - -/* - * Set GPIO inputs - */ -int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) -{ - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return -EINVAL; - - ath5k_hw_reg_write(ah, - (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) - | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); - - return 0; -} - -/* - * Set GPIO outputs - */ -int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) -{ - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return -EINVAL; - - ath5k_hw_reg_write(ah, - (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) - | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); - - return 0; -} - -/* - * Get GPIO state - */ -u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) -{ - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return 0xffffffff; - - /* GPIO input magic */ - return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & - 0x1; -} - -/* - * Set GPIO state - */ -int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) -{ - u32 data; - ATH5K_TRACE(ah->ah_sc); - - if (gpio >= AR5K_NUM_GPIO) - return -EINVAL; - - /* GPIO output magic */ - data = ath5k_hw_reg_read(ah, AR5K_GPIODO); - - data &= ~(1 << gpio); - data |= (val & 1) << gpio; - - ath5k_hw_reg_write(ah, data, AR5K_GPIODO); - - return 0; -} - -/* - * Initialize the GPIO interrupt (RFKill switch) - */ -void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, - u32 interrupt_level) -{ - u32 data; - - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return; - - /* - * Set the GPIO interrupt - */ - data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & - ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | - AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | - (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); - - ath5k_hw_reg_write(ah, interrupt_level ? data : - (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); - - ah->ah_imr |= AR5K_IMR_GPIO; - - /* Enable GPIO interrupts */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); -} - diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c deleted file mode 100644 index 61fb621ed20d..000000000000 --- a/drivers/net/wireless/ath5k/initvals.c +++ /dev/null @@ -1,1557 +0,0 @@ -/* - * Initial register settings functions - * - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Mode-independent initial register writes - */ - -struct ath5k_ini { - u16 ini_register; - u32 ini_value; - - enum { - AR5K_INI_WRITE = 0, /* Default */ - AR5K_INI_READ = 1, /* Cleared on read */ - } ini_mode; -}; - -/* - * Mode specific initial register values - */ - -struct ath5k_ini_mode { - u16 mode_register; - u32 mode_value[5]; -}; - -/* Initial register settings for AR5210 */ -static const struct ath5k_ini ar5210_ini[] = { - /* PCU and MAC registers */ - { AR5K_NOQCU_TXDP0, 0 }, - { AR5K_NOQCU_TXDP1, 0 }, - { AR5K_RXDP, 0 }, - { AR5K_CR, 0 }, - { AR5K_ISR, 0, AR5K_INI_READ }, - { AR5K_IMR, 0 }, - { AR5K_IER, AR5K_IER_DISABLE }, - { AR5K_BSR, 0, AR5K_INI_READ }, - { AR5K_TXCFG, AR5K_DMASIZE_128B }, - { AR5K_RXCFG, AR5K_DMASIZE_128B }, - { AR5K_CFG, AR5K_INIT_CFG }, - { AR5K_TOPS, 8 }, - { AR5K_RXNOFRM, 8 }, - { AR5K_RPGTO, 0 }, - { AR5K_TXNOFRM, 0 }, - { AR5K_SFR, 0 }, - { AR5K_MIBC, 0 }, - { AR5K_MISC, 0 }, - { AR5K_RX_FILTER_5210, 0 }, - { AR5K_MCAST_FILTER0_5210, 0 }, - { AR5K_MCAST_FILTER1_5210, 0 }, - { AR5K_TX_MASK0, 0 }, - { AR5K_TX_MASK1, 0 }, - { AR5K_CLR_TMASK, 0 }, - { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES }, - { AR5K_DIAG_SW_5210, 0 }, - { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES }, - { AR5K_TSF_L32_5210, 0 }, - { AR5K_TIMER0_5210, 0 }, - { AR5K_TIMER1_5210, 0xffffffff }, - { AR5K_TIMER2_5210, 0xffffffff }, - { AR5K_TIMER3_5210, 1 }, - { AR5K_CFP_DUR_5210, 0 }, - { AR5K_CFP_PERIOD_5210, 0 }, - /* PHY registers */ - { AR5K_PHY(0), 0x00000047 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY(3), 0x09848ea6 }, - { AR5K_PHY(4), 0x3d32e000 }, - { AR5K_PHY(5), 0x0000076b }, - { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE }, - { AR5K_PHY(8), 0x02020200 }, - { AR5K_PHY(9), 0x00000e0e }, - { AR5K_PHY(10), 0x0a020201 }, - { AR5K_PHY(11), 0x00036ffc }, - { AR5K_PHY(12), 0x00000000 }, - { AR5K_PHY(13), 0x00000e0e }, - { AR5K_PHY(14), 0x00000007 }, - { AR5K_PHY(15), 0x00020100 }, - { AR5K_PHY(16), 0x89630000 }, - { AR5K_PHY(17), 0x1372169c }, - { AR5K_PHY(18), 0x0018b633 }, - { AR5K_PHY(19), 0x1284613c }, - { AR5K_PHY(20), 0x0de8b8e0 }, - { AR5K_PHY(21), 0x00074859 }, - { AR5K_PHY(22), 0x7e80beba }, - { AR5K_PHY(23), 0x313a665e }, - { AR5K_PHY_AGCCTL, 0x00001d08 }, - { AR5K_PHY(25), 0x0001ce00 }, - { AR5K_PHY(26), 0x409a4190 }, - { AR5K_PHY(28), 0x0000000f }, - { AR5K_PHY(29), 0x00000080 }, - { AR5K_PHY(30), 0x00000004 }, - { AR5K_PHY(31), 0x00000018 }, /* 0x987c */ - { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */ - { AR5K_PHY(65), 0x00000000 }, - { AR5K_PHY(66), 0x00000000 }, - { AR5K_PHY(67), 0x00800000 }, - { AR5K_PHY(68), 0x00000003 }, - /* BB gain table (64bytes) */ - { AR5K_BB_GAIN(0), 0x00000000 }, - { AR5K_BB_GAIN(1), 0x00000020 }, - { AR5K_BB_GAIN(2), 0x00000010 }, - { AR5K_BB_GAIN(3), 0x00000030 }, - { AR5K_BB_GAIN(4), 0x00000008 }, - { AR5K_BB_GAIN(5), 0x00000028 }, - { AR5K_BB_GAIN(6), 0x00000028 }, - { AR5K_BB_GAIN(7), 0x00000004 }, - { AR5K_BB_GAIN(8), 0x00000024 }, - { AR5K_BB_GAIN(9), 0x00000014 }, - { AR5K_BB_GAIN(10), 0x00000034 }, - { AR5K_BB_GAIN(11), 0x0000000c }, - { AR5K_BB_GAIN(12), 0x0000002c }, - { AR5K_BB_GAIN(13), 0x00000002 }, - { AR5K_BB_GAIN(14), 0x00000022 }, - { AR5K_BB_GAIN(15), 0x00000012 }, - { AR5K_BB_GAIN(16), 0x00000032 }, - { AR5K_BB_GAIN(17), 0x0000000a }, - { AR5K_BB_GAIN(18), 0x0000002a }, - { AR5K_BB_GAIN(19), 0x00000001 }, - { AR5K_BB_GAIN(20), 0x00000021 }, - { AR5K_BB_GAIN(21), 0x00000011 }, - { AR5K_BB_GAIN(22), 0x00000031 }, - { AR5K_BB_GAIN(23), 0x00000009 }, - { AR5K_BB_GAIN(24), 0x00000029 }, - { AR5K_BB_GAIN(25), 0x00000005 }, - { AR5K_BB_GAIN(26), 0x00000025 }, - { AR5K_BB_GAIN(27), 0x00000015 }, - { AR5K_BB_GAIN(28), 0x00000035 }, - { AR5K_BB_GAIN(29), 0x0000000d }, - { AR5K_BB_GAIN(30), 0x0000002d }, - { AR5K_BB_GAIN(31), 0x00000003 }, - { AR5K_BB_GAIN(32), 0x00000023 }, - { AR5K_BB_GAIN(33), 0x00000013 }, - { AR5K_BB_GAIN(34), 0x00000033 }, - { AR5K_BB_GAIN(35), 0x0000000b }, - { AR5K_BB_GAIN(36), 0x0000002b }, - { AR5K_BB_GAIN(37), 0x00000007 }, - { AR5K_BB_GAIN(38), 0x00000027 }, - { AR5K_BB_GAIN(39), 0x00000017 }, - { AR5K_BB_GAIN(40), 0x00000037 }, - { AR5K_BB_GAIN(41), 0x0000000f }, - { AR5K_BB_GAIN(42), 0x0000002f }, - { AR5K_BB_GAIN(43), 0x0000002f }, - { AR5K_BB_GAIN(44), 0x0000002f }, - { AR5K_BB_GAIN(45), 0x0000002f }, - { AR5K_BB_GAIN(46), 0x0000002f }, - { AR5K_BB_GAIN(47), 0x0000002f }, - { AR5K_BB_GAIN(48), 0x0000002f }, - { AR5K_BB_GAIN(49), 0x0000002f }, - { AR5K_BB_GAIN(50), 0x0000002f }, - { AR5K_BB_GAIN(51), 0x0000002f }, - { AR5K_BB_GAIN(52), 0x0000002f }, - { AR5K_BB_GAIN(53), 0x0000002f }, - { AR5K_BB_GAIN(54), 0x0000002f }, - { AR5K_BB_GAIN(55), 0x0000002f }, - { AR5K_BB_GAIN(56), 0x0000002f }, - { AR5K_BB_GAIN(57), 0x0000002f }, - { AR5K_BB_GAIN(58), 0x0000002f }, - { AR5K_BB_GAIN(59), 0x0000002f }, - { AR5K_BB_GAIN(60), 0x0000002f }, - { AR5K_BB_GAIN(61), 0x0000002f }, - { AR5K_BB_GAIN(62), 0x0000002f }, - { AR5K_BB_GAIN(63), 0x0000002f }, - /* 5110 RF gain table (64btes) */ - { AR5K_RF_GAIN(0), 0x0000001d }, - { AR5K_RF_GAIN(1), 0x0000005d }, - { AR5K_RF_GAIN(2), 0x0000009d }, - { AR5K_RF_GAIN(3), 0x000000dd }, - { AR5K_RF_GAIN(4), 0x0000011d }, - { AR5K_RF_GAIN(5), 0x00000021 }, - { AR5K_RF_GAIN(6), 0x00000061 }, - { AR5K_RF_GAIN(7), 0x000000a1 }, - { AR5K_RF_GAIN(8), 0x000000e1 }, - { AR5K_RF_GAIN(9), 0x00000031 }, - { AR5K_RF_GAIN(10), 0x00000071 }, - { AR5K_RF_GAIN(11), 0x000000b1 }, - { AR5K_RF_GAIN(12), 0x0000001c }, - { AR5K_RF_GAIN(13), 0x0000005c }, - { AR5K_RF_GAIN(14), 0x00000029 }, - { AR5K_RF_GAIN(15), 0x00000069 }, - { AR5K_RF_GAIN(16), 0x000000a9 }, - { AR5K_RF_GAIN(17), 0x00000020 }, - { AR5K_RF_GAIN(18), 0x00000019 }, - { AR5K_RF_GAIN(19), 0x00000059 }, - { AR5K_RF_GAIN(20), 0x00000099 }, - { AR5K_RF_GAIN(21), 0x00000030 }, - { AR5K_RF_GAIN(22), 0x00000005 }, - { AR5K_RF_GAIN(23), 0x00000025 }, - { AR5K_RF_GAIN(24), 0x00000065 }, - { AR5K_RF_GAIN(25), 0x000000a5 }, - { AR5K_RF_GAIN(26), 0x00000028 }, - { AR5K_RF_GAIN(27), 0x00000068 }, - { AR5K_RF_GAIN(28), 0x0000001f }, - { AR5K_RF_GAIN(29), 0x0000001e }, - { AR5K_RF_GAIN(30), 0x00000018 }, - { AR5K_RF_GAIN(31), 0x00000058 }, - { AR5K_RF_GAIN(32), 0x00000098 }, - { AR5K_RF_GAIN(33), 0x00000003 }, - { AR5K_RF_GAIN(34), 0x00000004 }, - { AR5K_RF_GAIN(35), 0x00000044 }, - { AR5K_RF_GAIN(36), 0x00000084 }, - { AR5K_RF_GAIN(37), 0x00000013 }, - { AR5K_RF_GAIN(38), 0x00000012 }, - { AR5K_RF_GAIN(39), 0x00000052 }, - { AR5K_RF_GAIN(40), 0x00000092 }, - { AR5K_RF_GAIN(41), 0x000000d2 }, - { AR5K_RF_GAIN(42), 0x0000002b }, - { AR5K_RF_GAIN(43), 0x0000002a }, - { AR5K_RF_GAIN(44), 0x0000006a }, - { AR5K_RF_GAIN(45), 0x000000aa }, - { AR5K_RF_GAIN(46), 0x0000001b }, - { AR5K_RF_GAIN(47), 0x0000001a }, - { AR5K_RF_GAIN(48), 0x0000005a }, - { AR5K_RF_GAIN(49), 0x0000009a }, - { AR5K_RF_GAIN(50), 0x000000da }, - { AR5K_RF_GAIN(51), 0x00000006 }, - { AR5K_RF_GAIN(52), 0x00000006 }, - { AR5K_RF_GAIN(53), 0x00000006 }, - { AR5K_RF_GAIN(54), 0x00000006 }, - { AR5K_RF_GAIN(55), 0x00000006 }, - { AR5K_RF_GAIN(56), 0x00000006 }, - { AR5K_RF_GAIN(57), 0x00000006 }, - { AR5K_RF_GAIN(58), 0x00000006 }, - { AR5K_RF_GAIN(59), 0x00000006 }, - { AR5K_RF_GAIN(60), 0x00000006 }, - { AR5K_RF_GAIN(61), 0x00000006 }, - { AR5K_RF_GAIN(62), 0x00000006 }, - { AR5K_RF_GAIN(63), 0x00000006 }, - /* PHY activation */ - { AR5K_PHY(53), 0x00000020 }, - { AR5K_PHY(51), 0x00000004 }, - { AR5K_PHY(50), 0x00060106 }, - { AR5K_PHY(39), 0x0000006d }, - { AR5K_PHY(48), 0x00000000 }, - { AR5K_PHY(52), 0x00000014 }, - { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE }, -}; - -/* Initial register settings for AR5211 */ -static const struct ath5k_ini ar5211_ini[] = { - { AR5K_RXDP, 0x00000000 }, - { AR5K_RTSD0, 0x84849c9c }, - { AR5K_RTSD1, 0x7c7c7c7c }, - { AR5K_RXCFG, 0x00000005 }, - { AR5K_MIBC, 0x00000000 }, - { AR5K_TOPS, 0x00000008 }, - { AR5K_RXNOFRM, 0x00000008 }, - { AR5K_TXNOFRM, 0x00000010 }, - { AR5K_RPGTO, 0x00000000 }, - { AR5K_RFCNT, 0x0000001f }, - { AR5K_QUEUE_TXDP(0), 0x00000000 }, - { AR5K_QUEUE_TXDP(1), 0x00000000 }, - { AR5K_QUEUE_TXDP(2), 0x00000000 }, - { AR5K_QUEUE_TXDP(3), 0x00000000 }, - { AR5K_QUEUE_TXDP(4), 0x00000000 }, - { AR5K_QUEUE_TXDP(5), 0x00000000 }, - { AR5K_QUEUE_TXDP(6), 0x00000000 }, - { AR5K_QUEUE_TXDP(7), 0x00000000 }, - { AR5K_QUEUE_TXDP(8), 0x00000000 }, - { AR5K_QUEUE_TXDP(9), 0x00000000 }, - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_STA_ID1, 0x00000000 }, - { AR5K_BSS_ID0, 0x00000000 }, - { AR5K_BSS_ID1, 0x00000000 }, - { AR5K_RSSI_THR, 0x00000000 }, - { AR5K_CFP_PERIOD_5211, 0x00000000 }, - { AR5K_TIMER0_5211, 0x00000030 }, - { AR5K_TIMER1_5211, 0x0007ffff }, - { AR5K_TIMER2_5211, 0x01ffffff }, - { AR5K_TIMER3_5211, 0x00000031 }, - { AR5K_CFP_DUR_5211, 0x00000000 }, - { AR5K_RX_FILTER_5211, 0x00000000 }, - { AR5K_MCAST_FILTER0_5211, 0x00000000 }, - { AR5K_MCAST_FILTER1_5211, 0x00000002 }, - { AR5K_DIAG_SW_5211, 0x00000000 }, - { AR5K_ADDAC_TEST, 0x00000000 }, - { AR5K_DEFAULT_ANTENNA, 0x00000000 }, - /* PHY registers */ - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY(3), 0x2d849093 }, - { AR5K_PHY(4), 0x7d32e000 }, - { AR5K_PHY(5), 0x00000f6b }, - { AR5K_PHY_ACT, 0x00000000 }, - { AR5K_PHY(11), 0x00026ffe }, - { AR5K_PHY(12), 0x00000000 }, - { AR5K_PHY(15), 0x00020100 }, - { AR5K_PHY(16), 0x206a017a }, - { AR5K_PHY(19), 0x1284613c }, - { AR5K_PHY(21), 0x00000859 }, - { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */ - { AR5K_PHY(27), 0x050cb081 }, - { AR5K_PHY(28), 0x0000000f }, - { AR5K_PHY(29), 0x00000080 }, - { AR5K_PHY(30), 0x0000000c }, - { AR5K_PHY(64), 0x00000000 }, - { AR5K_PHY(65), 0x00000000 }, - { AR5K_PHY(66), 0x00000000 }, - { AR5K_PHY(67), 0x00800000 }, - { AR5K_PHY(68), 0x00000001 }, - { AR5K_PHY(71), 0x0000092a }, - { AR5K_PHY_IQ, 0x00000000 }, - { AR5K_PHY(73), 0x00058a05 }, - { AR5K_PHY(74), 0x00000001 }, - { AR5K_PHY(75), 0x00000000 }, - { AR5K_PHY_PAPD_PROBE, 0x00000000 }, - { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */ - { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */ - { AR5K_PHY(79), 0x0000003f }, /* 0x993c */ - { AR5K_PHY(80), 0x00000004 }, - { AR5K_PHY(82), 0x00000000 }, - { AR5K_PHY(83), 0x00000000 }, - { AR5K_PHY(84), 0x00000000 }, - { AR5K_PHY_RADAR, 0x5d50f14c }, - { AR5K_PHY(86), 0x00000018 }, - { AR5K_PHY(87), 0x004b6a8e }, - /* Initial Power table (32bytes) - * common on all cards/modes. - * Note: Table is rewritten during - * txpower setup later using calibration - * data etc. so next write is non-common */ - { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff }, - { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff }, - { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff }, - { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff }, - { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff }, - { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff }, - { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff }, - { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff }, - { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff }, - { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff }, - { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff }, - { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff }, - { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff }, - { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff }, - { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff }, - { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff }, - { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff }, - { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff }, - { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff }, - { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff }, - { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff }, - { AR5K_PHY_CCKTXCTL, 0x00000000 }, - { AR5K_PHY(642), 0x503e4646 }, - { AR5K_PHY_GAIN_2GHZ, 0x6480416c }, - { AR5K_PHY(644), 0x0199a003 }, - { AR5K_PHY(645), 0x044cd610 }, - { AR5K_PHY(646), 0x13800040 }, - { AR5K_PHY(647), 0x1be00060 }, - { AR5K_PHY(648), 0x0c53800a }, - { AR5K_PHY(649), 0x0014df3b }, - { AR5K_PHY(650), 0x000001b5 }, - { AR5K_PHY(651), 0x00000020 }, -}; - -/* Initial mode-specific settings for AR5211 - * 5211 supports OFDM-only g (draft g) but we - * need to test it ! - */ -static const struct ath5k_ini_mode ar5211_ini_mode[] = { - { AR5K_TXCFG, - /* a aTurbo b g (OFDM) */ - { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(0), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, - { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, - { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, - { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, - { AR5K_TIME_OUT, - { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, - { AR5K_USEC_5211, - { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, - { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, - { AR5K_PHY(9), - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, - { AR5K_PHY(10), - { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, - { AR5K_PHY(13), - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY(14), - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, - { AR5K_PHY(17), - { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, - { AR5K_PHY(18), - { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, - { AR5K_PHY(20), - { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, - { AR5K_PHY_AGCCTL, - { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, - { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, - { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, - { AR5K_PHY(70), - { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, - { AR5K_PHY_PCDAC_TXPOWER_BASE, - { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, - { AR5K_RF_BUFFER_CONTROL_4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, -}; - -/* Initial register settings for AR5212 */ -static const struct ath5k_ini ar5212_ini_common_start[] = { - { AR5K_RXDP, 0x00000000 }, - { AR5K_RXCFG, 0x00000005 }, - { AR5K_MIBC, 0x00000000 }, - { AR5K_TOPS, 0x00000008 }, - { AR5K_RXNOFRM, 0x00000008 }, - { AR5K_TXNOFRM, 0x00000010 }, - { AR5K_RPGTO, 0x00000000 }, - { AR5K_RFCNT, 0x0000001f }, - { AR5K_QUEUE_TXDP(0), 0x00000000 }, - { AR5K_QUEUE_TXDP(1), 0x00000000 }, - { AR5K_QUEUE_TXDP(2), 0x00000000 }, - { AR5K_QUEUE_TXDP(3), 0x00000000 }, - { AR5K_QUEUE_TXDP(4), 0x00000000 }, - { AR5K_QUEUE_TXDP(5), 0x00000000 }, - { AR5K_QUEUE_TXDP(6), 0x00000000 }, - { AR5K_QUEUE_TXDP(7), 0x00000000 }, - { AR5K_QUEUE_TXDP(8), 0x00000000 }, - { AR5K_QUEUE_TXDP(9), 0x00000000 }, - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_DCU_TXP, 0x00000000 }, - /* Tx filter table 0 (32 entries) */ - { AR5K_DCU_TX_FILTER_0(0), 0x00000000 }, /* DCU 0 */ - { AR5K_DCU_TX_FILTER_0(1), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(2), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(3), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(4), 0x00000000 }, /* DCU 1 */ - { AR5K_DCU_TX_FILTER_0(5), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(6), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(7), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(8), 0x00000000 }, /* DCU 2 */ - { AR5K_DCU_TX_FILTER_0(9), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(10), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(11), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(12), 0x00000000 }, /* DCU 3 */ - { AR5K_DCU_TX_FILTER_0(13), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(14), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(15), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(16), 0x00000000 }, /* DCU 4 */ - { AR5K_DCU_TX_FILTER_0(17), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(18), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(19), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(20), 0x00000000 }, /* DCU 5 */ - { AR5K_DCU_TX_FILTER_0(21), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(22), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(23), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(24), 0x00000000 }, /* DCU 6 */ - { AR5K_DCU_TX_FILTER_0(25), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(26), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(27), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(28), 0x00000000 }, /* DCU 7 */ - { AR5K_DCU_TX_FILTER_0(29), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(30), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(31), 0x00000000 }, - /* Tx filter table 1 (16 entries) */ - { AR5K_DCU_TX_FILTER_1(0), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(1), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(2), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(3), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(4), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(5), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(6), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(7), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(8), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(9), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(10), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(11), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(12), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(13), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(14), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(15), 0x00000000 }, - { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, - { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, - { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, - { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, - { AR5K_STA_ID1, 0x00000000 }, - { AR5K_BSS_ID0, 0x00000000 }, - { AR5K_BSS_ID1, 0x00000000 }, - { AR5K_BEACON_5211, 0x00000000 }, - { AR5K_CFP_PERIOD_5211, 0x00000000 }, - { AR5K_TIMER0_5211, 0x00000030 }, - { AR5K_TIMER1_5211, 0x0007ffff }, - { AR5K_TIMER2_5211, 0x01ffffff }, - { AR5K_TIMER3_5211, 0x00000031 }, - { AR5K_CFP_DUR_5211, 0x00000000 }, - { AR5K_RX_FILTER_5211, 0x00000000 }, - { AR5K_DIAG_SW_5211, 0x00000000 }, - { AR5K_ADDAC_TEST, 0x00000000 }, - { AR5K_DEFAULT_ANTENNA, 0x00000000 }, - { AR5K_FRAME_CTL_QOSM, 0x000fc78f }, - { AR5K_XRMODE, 0x2a82301a }, - { AR5K_XRDELAY, 0x05dc01e0 }, - { AR5K_XRTIMEOUT, 0x1f402710 }, - { AR5K_XRCHIRP, 0x01f40000 }, - { AR5K_XRSTOMP, 0x00001e1c }, - { AR5K_SLEEP0, 0x0002aaaa }, - { AR5K_SLEEP1, 0x02005555 }, - { AR5K_SLEEP2, 0x00000000 }, - { AR5K_BSS_IDM0, 0xffffffff }, - { AR5K_BSS_IDM1, 0x0000ffff }, - { AR5K_TXPC, 0x00000000 }, - { AR5K_PROFCNT_TX, 0x00000000 }, - { AR5K_PROFCNT_RX, 0x00000000 }, - { AR5K_PROFCNT_RXCLR, 0x00000000 }, - { AR5K_PROFCNT_CYCLE, 0x00000000 }, - { AR5K_QUIET_CTL1, 0x00000088 }, - /* Initial rate duration table (32 entries )*/ - { AR5K_RATE_DUR(0), 0x00000000 }, - { AR5K_RATE_DUR(1), 0x0000008c }, - { AR5K_RATE_DUR(2), 0x000000e4 }, - { AR5K_RATE_DUR(3), 0x000002d5 }, - { AR5K_RATE_DUR(4), 0x00000000 }, - { AR5K_RATE_DUR(5), 0x00000000 }, - { AR5K_RATE_DUR(6), 0x000000a0 }, - { AR5K_RATE_DUR(7), 0x000001c9 }, - { AR5K_RATE_DUR(8), 0x0000002c }, - { AR5K_RATE_DUR(9), 0x0000002c }, - { AR5K_RATE_DUR(10), 0x00000030 }, - { AR5K_RATE_DUR(11), 0x0000003c }, - { AR5K_RATE_DUR(12), 0x0000002c }, - { AR5K_RATE_DUR(13), 0x0000002c }, - { AR5K_RATE_DUR(14), 0x00000030 }, - { AR5K_RATE_DUR(15), 0x0000003c }, - { AR5K_RATE_DUR(16), 0x00000000 }, - { AR5K_RATE_DUR(17), 0x00000000 }, - { AR5K_RATE_DUR(18), 0x00000000 }, - { AR5K_RATE_DUR(19), 0x00000000 }, - { AR5K_RATE_DUR(20), 0x00000000 }, - { AR5K_RATE_DUR(21), 0x00000000 }, - { AR5K_RATE_DUR(22), 0x00000000 }, - { AR5K_RATE_DUR(23), 0x00000000 }, - { AR5K_RATE_DUR(24), 0x000000d5 }, - { AR5K_RATE_DUR(25), 0x000000df }, - { AR5K_RATE_DUR(26), 0x00000102 }, - { AR5K_RATE_DUR(27), 0x0000013a }, - { AR5K_RATE_DUR(28), 0x00000075 }, - { AR5K_RATE_DUR(29), 0x0000007f }, - { AR5K_RATE_DUR(30), 0x000000a2 }, - { AR5K_RATE_DUR(31), 0x00000000 }, - { AR5K_QUIET_CTL2, 0x00010002 }, - { AR5K_TSF_PARM, 0x00000001 }, - { AR5K_QOS_NOACK, 0x000000c0 }, - { AR5K_PHY_ERR_FIL, 0x00000000 }, - { AR5K_XRLAT_TX, 0x00000168 }, - { AR5K_ACKSIFS, 0x00000000 }, - /* Rate -> db table - * notice ...03<-02<-01<-00 ! */ - { AR5K_RATE2DB(0), 0x03020100 }, - { AR5K_RATE2DB(1), 0x07060504 }, - { AR5K_RATE2DB(2), 0x0b0a0908 }, - { AR5K_RATE2DB(3), 0x0f0e0d0c }, - { AR5K_RATE2DB(4), 0x13121110 }, - { AR5K_RATE2DB(5), 0x17161514 }, - { AR5K_RATE2DB(6), 0x1b1a1918 }, - { AR5K_RATE2DB(7), 0x1f1e1d1c }, - /* Db -> Rate table */ - { AR5K_DB2RATE(0), 0x03020100 }, - { AR5K_DB2RATE(1), 0x07060504 }, - { AR5K_DB2RATE(2), 0x0b0a0908 }, - { AR5K_DB2RATE(3), 0x0f0e0d0c }, - { AR5K_DB2RATE(4), 0x13121110 }, - { AR5K_DB2RATE(5), 0x17161514 }, - { AR5K_DB2RATE(6), 0x1b1a1918 }, - { AR5K_DB2RATE(7), 0x1f1e1d1c }, - /* PHY registers (Common settings - * for all chips/modes) */ - { AR5K_PHY(3), 0xad848e19 }, - { AR5K_PHY(4), 0x7d28e000 }, - { AR5K_PHY_TIMING_3, 0x9c0a9f6b }, - { AR5K_PHY_ACT, 0x00000000 }, - { AR5K_PHY(16), 0x206a017a }, - { AR5K_PHY(21), 0x00000859 }, - { AR5K_PHY_BIN_MASK_1, 0x00000000 }, - { AR5K_PHY_BIN_MASK_2, 0x00000000 }, - { AR5K_PHY_BIN_MASK_3, 0x00000000 }, - { AR5K_PHY_BIN_MASK_CTL, 0x00800000 }, - { AR5K_PHY_ANT_CTL, 0x00000001 }, - /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */ - { AR5K_PHY_MAX_RX_LEN, 0x00000c80 }, - { AR5K_PHY_IQ, 0x05100000 }, - { AR5K_PHY_WARM_RESET, 0x00000001 }, - { AR5K_PHY_CTL, 0x00000004 }, - { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 }, - { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d }, - { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f }, - { AR5K_PHY(82), 0x9280b212 }, - { AR5K_PHY_RADAR, 0x5d50e188 }, - /*{ AR5K_PHY(86), 0x000000ff },*/ - { AR5K_PHY(87), 0x004b6a8e }, - { AR5K_PHY_NFTHRES, 0x000003ce }, - { AR5K_PHY_RESTART, 0x192fb515 }, - { AR5K_PHY(94), 0x00000001 }, - { AR5K_PHY_RFBUS_REQ, 0x00000000 }, - /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */ - /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */ - { AR5K_PHY(644), 0x00806333 }, - { AR5K_PHY(645), 0x00106c10 }, - { AR5K_PHY(646), 0x009c4060 }, - /* { AR5K_PHY(647), 0x1483800a }, */ - /* { AR5K_PHY(648), 0x01831061 }, */ /* Old value */ - { AR5K_PHY(648), 0x018830c6 }, - { AR5K_PHY(649), 0x00000400 }, - /*{ AR5K_PHY(650), 0x000001b5 },*/ - { AR5K_PHY(651), 0x00000000 }, - { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, - { AR5K_PHY_TXPOWER_RATE2, 0x20202020 }, - /*{ AR5K_PHY(655), 0x13c889af },*/ - { AR5K_PHY(656), 0x38490a20 }, - { AR5K_PHY(657), 0x00007bb6 }, - { AR5K_PHY(658), 0x0fff3ffc }, -}; - -/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ -static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { - { AR5K_QUEUE_DFS_LOCAL_IFS(0), - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, - { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, - { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, - { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, - { AR5K_TIME_OUT, - { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, - { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, - { AR5K_PHY_RF_CTL2, - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, - { AR5K_PHY_AGCCTL, - { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } }, - { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, - { AR5K_PHY_WEAK_OFDM_HIGH_THR, - { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, - { AR5K_PHY(70), - { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, - { AR5K_PHY_OFDM_SELFCORR, - { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, - { 0xa230, - { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, -}; - -/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ -static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, - { AR5K_USEC_5211, - { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_GAIN, - { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, - { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, -}; - -static const struct ath5k_ini rf5111_ini_common_end[] = { - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x00022ffe }, - { 0x983c, 0x00020100 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284613c }, - { AR5K_PHY_PAPD_PROBE, 0x00004883 }, - { 0x9940, 0x00000004 }, - { 0x9958, 0x000000ff }, - { 0x9974, 0x00000000 }, - { AR5K_PHY_SPENDING, 0x00000018 }, - { AR5K_PHY_CCKTXCTL, 0x00000000 }, - { AR5K_PHY_CCK_CROSSCORR, 0xd03e6788 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 }, - { 0xa23c, 0x13c889af }, -}; - -/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ -static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, -}; - -static const struct ath5k_ini rf5112_ini_common_end[] = { - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x00022ffe }, - { 0x983c, 0x00020100 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284613c }, - { AR5K_PHY_PAPD_PROBE, 0x00004882 }, - { 0x9940, 0x00000004 }, - { 0x9958, 0x000000ff }, - { 0x9974, 0x00000000 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 }, - { 0xa23c, 0x13c889af }, -}; - -/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ -static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, - { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, - { 0xa300, - { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, - { 0xa304, - { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, - { 0xa308, - { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, - { 0xa30c, - { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, - { 0xa310, - { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, - { 0xa314, - { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, - { 0xa318, - { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, - { 0xa31c, - { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, - { 0xa320, - { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, - { 0xa324, - { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, - { 0xa328, - { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, - { 0xa32c, - { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, - { 0xa330, - { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, - { 0xa334, - { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, -}; - -static const struct ath5k_ini rf5413_ini_common_end[] = { - { AR5K_DCU_FP, 0x000003e0 }, - { AR5K_5414_CBCFG, 0x00000010 }, - { AR5K_SEQ_MASK, 0x0000000f }, - { 0x809c, 0x00000000 }, - { 0x80a0, 0x00000000 }, - { AR5K_MIC_QOS_CTL, 0x00000000 }, - { AR5K_MIC_QOS_SEL, 0x00000000 }, - { AR5K_MISC_MODE, 0x00000000 }, - { AR5K_OFDM_FIL_CNT, 0x00000000 }, - { AR5K_CCK_FIL_CNT, 0x00000000 }, - { AR5K_PHYERR_CNT1, 0x00000000 }, - { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, - { AR5K_PHYERR_CNT2, 0x00000000 }, - { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, - { AR5K_TSF_THRES, 0x00000000 }, - { 0x8140, 0x800003f9 }, - { 0x8144, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x0000a000 }, - { 0x983c, 0x00200400 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, - { AR5K_PHY_SCR, 0x0000001f }, - { AR5K_PHY_SLMT, 0x00000080 }, - { AR5K_PHY_SCAL, 0x0000000e }, - { 0x9958, 0x00081fff }, - { AR5K_PHY_TIMING_7, 0x00000000 }, - { AR5K_PHY_TIMING_8, 0x02800000 }, - { AR5K_PHY_TIMING_11, 0x00000000 }, - { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, - { 0x99e4, 0xaaaaaaaa }, - { 0x99e8, 0x3c466478 }, - { 0x99ec, 0x000000aa }, - { AR5K_PHY_SCLOCK, 0x0000000c }, - { AR5K_PHY_SDELAY, 0x000000ff }, - { AR5K_PHY_SPENDING, 0x00000014 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, - { 0xa23c, 0x93c889af }, - { AR5K_PHY_FAST_ADC, 0x00000001 }, - { 0xa250, 0x0000a000 }, - { AR5K_PHY_BLUETOOTH, 0x00000000 }, - { AR5K_PHY_TPC_RG1, 0x0cc75380 }, - { 0xa25c, 0x0f0f0f01 }, - { 0xa260, 0x5f690f01 }, - { 0xa264, 0x00418a11 }, - { 0xa268, 0x00000000 }, - { AR5K_PHY_TPC_RG5, 0x0c30c16a }, - { 0xa270, 0x00820820 }, - { 0xa274, 0x081b7caa }, - { 0xa278, 0x1ce739ce }, - { 0xa27c, 0x051701ce }, - { 0xa338, 0x00000000 }, - { 0xa33c, 0x00000000 }, - { 0xa340, 0x00000000 }, - { 0xa344, 0x00000000 }, - { 0xa348, 0x3fffffff }, - { 0xa34c, 0x3fffffff }, - { 0xa350, 0x3fffffff }, - { 0xa354, 0x0003ffff }, - { 0xa358, 0x79a8aa1f }, - { 0xa35c, 0x066c420f }, - { 0xa360, 0x0f282207 }, - { 0xa364, 0x17601685 }, - { 0xa368, 0x1f801104 }, - { 0xa36c, 0x37a00c03 }, - { 0xa370, 0x3fc40883 }, - { 0xa374, 0x57c00803 }, - { 0xa378, 0x5fd80682 }, - { 0xa37c, 0x7fe00482 }, - { 0xa380, 0x7f3c7bba }, - { 0xa384, 0xf3307ff0 }, -}; - -/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ -/* XXX: a mode ? */ -static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } }, - { AR5K_PHY_PA_CTL, - { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } }, - { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, -}; - -static const struct ath5k_ini rf2413_ini_common_end[] = { - { AR5K_DCU_FP, 0x000003e0 }, - { AR5K_SEQ_MASK, 0x0000000f }, - { AR5K_MIC_QOS_CTL, 0x00000000 }, - { AR5K_MIC_QOS_SEL, 0x00000000 }, - { AR5K_MISC_MODE, 0x00000000 }, - { AR5K_OFDM_FIL_CNT, 0x00000000 }, - { AR5K_CCK_FIL_CNT, 0x00000000 }, - { AR5K_PHYERR_CNT1, 0x00000000 }, - { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, - { AR5K_PHYERR_CNT2, 0x00000000 }, - { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, - { AR5K_TSF_THRES, 0x00000000 }, - { 0x8140, 0x800000a8 }, - { 0x8144, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x0000a000 }, - { 0x983c, 0x00200400 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, - { AR5K_PHY_SCR, 0x0000001f }, - { AR5K_PHY_SLMT, 0x00000080 }, - { AR5K_PHY_SCAL, 0x0000000e }, - { 0x9958, 0x000000ff }, - { AR5K_PHY_TIMING_7, 0x00000000 }, - { AR5K_PHY_TIMING_8, 0x02800000 }, - { AR5K_PHY_TIMING_11, 0x00000000 }, - { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, - { 0x99e4, 0xaaaaaaaa }, - { 0x99e8, 0x3c466478 }, - { 0x99ec, 0x000000aa }, - { AR5K_PHY_SCLOCK, 0x0000000c }, - { AR5K_PHY_SDELAY, 0x000000ff }, - { AR5K_PHY_SPENDING, 0x00000014 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, - { 0xa23c, 0x93c889af }, - { AR5K_PHY_FAST_ADC, 0x00000001 }, - { 0xa250, 0x0000a000 }, - { AR5K_PHY_BLUETOOTH, 0x00000000 }, - { AR5K_PHY_TPC_RG1, 0x0cc75380 }, - { 0xa25c, 0x0f0f0f01 }, - { 0xa260, 0x5f690f01 }, - { 0xa264, 0x00418a11 }, - { 0xa268, 0x00000000 }, - { AR5K_PHY_TPC_RG5, 0x0c30c16a }, - { 0xa270, 0x00820820 }, - { 0xa274, 0x001b7caa }, - { 0xa278, 0x1ce739ce }, - { 0xa27c, 0x051701ce }, - { 0xa300, 0x18010000 }, - { 0xa304, 0x30032602 }, - { 0xa308, 0x48073e06 }, - { 0xa30c, 0x560b4c0a }, - { 0xa310, 0x641a600f }, - { 0xa314, 0x784f6e1b }, - { 0xa318, 0x868f7c5a }, - { 0xa31c, 0x8ecf865b }, - { 0xa320, 0x9d4f970f }, - { 0xa324, 0xa5cfa18f }, - { 0xa328, 0xb55faf1f }, - { 0xa32c, 0xbddfb99f }, - { 0xa330, 0xcd7fc73f }, - { 0xa334, 0xd5ffd1bf }, - { 0xa338, 0x00000000 }, - { 0xa33c, 0x00000000 }, - { 0xa340, 0x00000000 }, - { 0xa344, 0x00000000 }, - { 0xa348, 0x3fffffff }, - { 0xa34c, 0x3fffffff }, - { 0xa350, 0x3fffffff }, - { 0xa354, 0x0003ffff }, - { 0xa358, 0x79a8aa1f }, - { 0xa35c, 0x066c420f }, - { 0xa360, 0x0f282207 }, - { 0xa364, 0x17601685 }, - { 0xa368, 0x1f801104 }, - { 0xa36c, 0x37a00c03 }, - { 0xa370, 0x3fc40883 }, - { 0xa374, 0x57c00803 }, - { 0xa378, 0x5fd80682 }, - { 0xa37c, 0x7fe00482 }, - { 0xa380, 0x7f3c7bba }, - { 0xa384, 0xf3307ff0 }, -}; - -/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ -/* XXX: a mode ? */ -static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } }, - { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, - { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, - { 0xa324, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa328, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa32c, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa330, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa334, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, -}; - -static const struct ath5k_ini rf2425_ini_common_end[] = { - { AR5K_DCU_FP, 0x000003e0 }, - { AR5K_SEQ_MASK, 0x0000000f }, - { 0x809c, 0x00000000 }, - { 0x80a0, 0x00000000 }, - { AR5K_MIC_QOS_CTL, 0x00000000 }, - { AR5K_MIC_QOS_SEL, 0x00000000 }, - { AR5K_MISC_MODE, 0x00000000 }, - { AR5K_OFDM_FIL_CNT, 0x00000000 }, - { AR5K_CCK_FIL_CNT, 0x00000000 }, - { AR5K_PHYERR_CNT1, 0x00000000 }, - { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, - { AR5K_PHYERR_CNT2, 0x00000000 }, - { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, - { AR5K_TSF_THRES, 0x00000000 }, - { 0x8140, 0x800003f9 }, - { 0x8144, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x0000a000 }, - { 0x983c, 0x00200400 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, - { AR5K_PHY_SCR, 0x0000001f }, - { AR5K_PHY_SLMT, 0x00000080 }, - { AR5K_PHY_SCAL, 0x0000000e }, - { 0x9958, 0x00081fff }, - { AR5K_PHY_TIMING_7, 0x00000000 }, - { AR5K_PHY_TIMING_8, 0x02800000 }, - { AR5K_PHY_TIMING_11, 0x00000000 }, - { 0x99dc, 0xfebadbe8 }, - { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, - { 0x99e4, 0xaaaaaaaa }, - { 0x99e8, 0x3c466478 }, - { 0x99ec, 0x000000aa }, - { AR5K_PHY_SCLOCK, 0x0000000c }, - { AR5K_PHY_SDELAY, 0x000000ff }, - { AR5K_PHY_SPENDING, 0x00000014 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, - { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, - { AR5K_PHY_TXPOWER_RATE4, 0x20202020 }, - { 0xa23c, 0x93c889af }, - { AR5K_PHY_FAST_ADC, 0x00000001 }, - { 0xa250, 0x0000a000 }, - { AR5K_PHY_BLUETOOTH, 0x00000000 }, - { AR5K_PHY_TPC_RG1, 0x0cc75380 }, - { 0xa25c, 0x0f0f0f01 }, - { 0xa260, 0x5f690f01 }, - { 0xa264, 0x00418a11 }, - { 0xa268, 0x00000000 }, - { AR5K_PHY_TPC_RG5, 0x0c30c166 }, - { 0xa270, 0x00820820 }, - { 0xa274, 0x081a3caa }, - { 0xa278, 0x1ce739ce }, - { 0xa27c, 0x051701ce }, - { 0xa300, 0x16010000 }, - { 0xa304, 0x2c032402 }, - { 0xa308, 0x48433e42 }, - { 0xa30c, 0x5a0f500b }, - { 0xa310, 0x6c4b624a }, - { 0xa314, 0x7e8b748a }, - { 0xa318, 0x96cf8ccb }, - { 0xa31c, 0xa34f9d0f }, - { 0xa320, 0xa7cfa58f }, - { 0xa348, 0x3fffffff }, - { 0xa34c, 0x3fffffff }, - { 0xa350, 0x3fffffff }, - { 0xa354, 0x0003ffff }, - { 0xa358, 0x79a8aa1f }, - { 0xa35c, 0x066c420f }, - { 0xa360, 0x0f282207 }, - { 0xa364, 0x17601685 }, - { 0xa368, 0x1f801104 }, - { 0xa36c, 0x37a00c03 }, - { 0xa370, 0x3fc40883 }, - { 0xa374, 0x57c00803 }, - { 0xa378, 0x5fd80682 }, - { 0xa37c, 0x7fe00482 }, - { 0xa380, 0x7f3c7bba }, - { 0xa384, 0xf3307ff0 }, -}; - -/* - * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with - * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) - */ - -/* RF5111 Initial BaseBand Gain settings */ -static const struct ath5k_ini rf5111_ini_bbgain[] = { - { AR5K_BB_GAIN(0), 0x00000000 }, - { AR5K_BB_GAIN(1), 0x00000020 }, - { AR5K_BB_GAIN(2), 0x00000010 }, - { AR5K_BB_GAIN(3), 0x00000030 }, - { AR5K_BB_GAIN(4), 0x00000008 }, - { AR5K_BB_GAIN(5), 0x00000028 }, - { AR5K_BB_GAIN(6), 0x00000004 }, - { AR5K_BB_GAIN(7), 0x00000024 }, - { AR5K_BB_GAIN(8), 0x00000014 }, - { AR5K_BB_GAIN(9), 0x00000034 }, - { AR5K_BB_GAIN(10), 0x0000000c }, - { AR5K_BB_GAIN(11), 0x0000002c }, - { AR5K_BB_GAIN(12), 0x00000002 }, - { AR5K_BB_GAIN(13), 0x00000022 }, - { AR5K_BB_GAIN(14), 0x00000012 }, - { AR5K_BB_GAIN(15), 0x00000032 }, - { AR5K_BB_GAIN(16), 0x0000000a }, - { AR5K_BB_GAIN(17), 0x0000002a }, - { AR5K_BB_GAIN(18), 0x00000006 }, - { AR5K_BB_GAIN(19), 0x00000026 }, - { AR5K_BB_GAIN(20), 0x00000016 }, - { AR5K_BB_GAIN(21), 0x00000036 }, - { AR5K_BB_GAIN(22), 0x0000000e }, - { AR5K_BB_GAIN(23), 0x0000002e }, - { AR5K_BB_GAIN(24), 0x00000001 }, - { AR5K_BB_GAIN(25), 0x00000021 }, - { AR5K_BB_GAIN(26), 0x00000011 }, - { AR5K_BB_GAIN(27), 0x00000031 }, - { AR5K_BB_GAIN(28), 0x00000009 }, - { AR5K_BB_GAIN(29), 0x00000029 }, - { AR5K_BB_GAIN(30), 0x00000005 }, - { AR5K_BB_GAIN(31), 0x00000025 }, - { AR5K_BB_GAIN(32), 0x00000015 }, - { AR5K_BB_GAIN(33), 0x00000035 }, - { AR5K_BB_GAIN(34), 0x0000000d }, - { AR5K_BB_GAIN(35), 0x0000002d }, - { AR5K_BB_GAIN(36), 0x00000003 }, - { AR5K_BB_GAIN(37), 0x00000023 }, - { AR5K_BB_GAIN(38), 0x00000013 }, - { AR5K_BB_GAIN(39), 0x00000033 }, - { AR5K_BB_GAIN(40), 0x0000000b }, - { AR5K_BB_GAIN(41), 0x0000002b }, - { AR5K_BB_GAIN(42), 0x0000002b }, - { AR5K_BB_GAIN(43), 0x0000002b }, - { AR5K_BB_GAIN(44), 0x0000002b }, - { AR5K_BB_GAIN(45), 0x0000002b }, - { AR5K_BB_GAIN(46), 0x0000002b }, - { AR5K_BB_GAIN(47), 0x0000002b }, - { AR5K_BB_GAIN(48), 0x0000002b }, - { AR5K_BB_GAIN(49), 0x0000002b }, - { AR5K_BB_GAIN(50), 0x0000002b }, - { AR5K_BB_GAIN(51), 0x0000002b }, - { AR5K_BB_GAIN(52), 0x0000002b }, - { AR5K_BB_GAIN(53), 0x0000002b }, - { AR5K_BB_GAIN(54), 0x0000002b }, - { AR5K_BB_GAIN(55), 0x0000002b }, - { AR5K_BB_GAIN(56), 0x0000002b }, - { AR5K_BB_GAIN(57), 0x0000002b }, - { AR5K_BB_GAIN(58), 0x0000002b }, - { AR5K_BB_GAIN(59), 0x0000002b }, - { AR5K_BB_GAIN(60), 0x0000002b }, - { AR5K_BB_GAIN(61), 0x0000002b }, - { AR5K_BB_GAIN(62), 0x00000002 }, - { AR5K_BB_GAIN(63), 0x00000016 }, -}; - -/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */ -static const struct ath5k_ini rf5112_ini_bbgain[] = { - { AR5K_BB_GAIN(0), 0x00000000 }, - { AR5K_BB_GAIN(1), 0x00000001 }, - { AR5K_BB_GAIN(2), 0x00000002 }, - { AR5K_BB_GAIN(3), 0x00000003 }, - { AR5K_BB_GAIN(4), 0x00000004 }, - { AR5K_BB_GAIN(5), 0x00000005 }, - { AR5K_BB_GAIN(6), 0x00000008 }, - { AR5K_BB_GAIN(7), 0x00000009 }, - { AR5K_BB_GAIN(8), 0x0000000a }, - { AR5K_BB_GAIN(9), 0x0000000b }, - { AR5K_BB_GAIN(10), 0x0000000c }, - { AR5K_BB_GAIN(11), 0x0000000d }, - { AR5K_BB_GAIN(12), 0x00000010 }, - { AR5K_BB_GAIN(13), 0x00000011 }, - { AR5K_BB_GAIN(14), 0x00000012 }, - { AR5K_BB_GAIN(15), 0x00000013 }, - { AR5K_BB_GAIN(16), 0x00000014 }, - { AR5K_BB_GAIN(17), 0x00000015 }, - { AR5K_BB_GAIN(18), 0x00000018 }, - { AR5K_BB_GAIN(19), 0x00000019 }, - { AR5K_BB_GAIN(20), 0x0000001a }, - { AR5K_BB_GAIN(21), 0x0000001b }, - { AR5K_BB_GAIN(22), 0x0000001c }, - { AR5K_BB_GAIN(23), 0x0000001d }, - { AR5K_BB_GAIN(24), 0x00000020 }, - { AR5K_BB_GAIN(25), 0x00000021 }, - { AR5K_BB_GAIN(26), 0x00000022 }, - { AR5K_BB_GAIN(27), 0x00000023 }, - { AR5K_BB_GAIN(28), 0x00000024 }, - { AR5K_BB_GAIN(29), 0x00000025 }, - { AR5K_BB_GAIN(30), 0x00000028 }, - { AR5K_BB_GAIN(31), 0x00000029 }, - { AR5K_BB_GAIN(32), 0x0000002a }, - { AR5K_BB_GAIN(33), 0x0000002b }, - { AR5K_BB_GAIN(34), 0x0000002c }, - { AR5K_BB_GAIN(35), 0x0000002d }, - { AR5K_BB_GAIN(36), 0x00000030 }, - { AR5K_BB_GAIN(37), 0x00000031 }, - { AR5K_BB_GAIN(38), 0x00000032 }, - { AR5K_BB_GAIN(39), 0x00000033 }, - { AR5K_BB_GAIN(40), 0x00000034 }, - { AR5K_BB_GAIN(41), 0x00000035 }, - { AR5K_BB_GAIN(42), 0x00000035 }, - { AR5K_BB_GAIN(43), 0x00000035 }, - { AR5K_BB_GAIN(44), 0x00000035 }, - { AR5K_BB_GAIN(45), 0x00000035 }, - { AR5K_BB_GAIN(46), 0x00000035 }, - { AR5K_BB_GAIN(47), 0x00000035 }, - { AR5K_BB_GAIN(48), 0x00000035 }, - { AR5K_BB_GAIN(49), 0x00000035 }, - { AR5K_BB_GAIN(50), 0x00000035 }, - { AR5K_BB_GAIN(51), 0x00000035 }, - { AR5K_BB_GAIN(52), 0x00000035 }, - { AR5K_BB_GAIN(53), 0x00000035 }, - { AR5K_BB_GAIN(54), 0x00000035 }, - { AR5K_BB_GAIN(55), 0x00000035 }, - { AR5K_BB_GAIN(56), 0x00000035 }, - { AR5K_BB_GAIN(57), 0x00000035 }, - { AR5K_BB_GAIN(58), 0x00000035 }, - { AR5K_BB_GAIN(59), 0x00000035 }, - { AR5K_BB_GAIN(60), 0x00000035 }, - { AR5K_BB_GAIN(61), 0x00000035 }, - { AR5K_BB_GAIN(62), 0x00000010 }, - { AR5K_BB_GAIN(63), 0x0000001a }, -}; - - -/* - * Write initial register dump - */ -static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, - const struct ath5k_ini *ini_regs, bool change_channel) -{ - unsigned int i; - - /* Write initial registers */ - for (i = 0; i < size; i++) { - /* On channel change there is - * no need to mess with PCU */ - if (change_channel && - ini_regs[i].ini_register >= AR5K_PCU_MIN && - ini_regs[i].ini_register <= AR5K_PCU_MAX) - continue; - - switch (ini_regs[i].ini_mode) { - case AR5K_INI_READ: - /* Cleared on read */ - ath5k_hw_reg_read(ah, ini_regs[i].ini_register); - break; - case AR5K_INI_WRITE: - default: - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ini_regs[i].ini_value, - ini_regs[i].ini_register); - } - } -} - -static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, - unsigned int size, const struct ath5k_ini_mode *ini_mode, - u8 mode) -{ - unsigned int i; - - for (i = 0; i < size; i++) { - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode], - (u32)ini_mode[i].mode_register); - } - -} - -int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) -{ - /* - * Write initial register settings - */ - - /* For AR5212 and combatible */ - if (ah->ah_version == AR5K_AR5212) { - - /* First set of mode-specific settings */ - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(ar5212_ini_mode_start), - ar5212_ini_mode_start, mode); - - /* - * Write initial settings common for all modes - */ - ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), - ar5212_ini_common_start, change_channel); - - /* Second set of mode-specific settings */ - switch (ah->ah_radio) { - case AR5K_RF5111: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf5111_ini_mode_end), - rf5111_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5111_ini_common_end), - rf5111_ini_common_end, change_channel); - - /* Baseband gain table */ - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); - - break; - case AR5K_RF5112: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf5112_ini_mode_end), - rf5112_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_common_end), - rf5112_ini_common_end, change_channel); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - - break; - case AR5K_RF5413: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf5413_ini_mode_end), - rf5413_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5413_ini_common_end), - rf5413_ini_common_end, change_channel); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - - break; - case AR5K_RF2316: - case AR5K_RF2413: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf2413_ini_mode_end), - rf2413_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf2413_ini_common_end), - rf2413_ini_common_end, change_channel); - - /* Override settings from rf2413_ini_common_end */ - if (ah->ah_radio == AR5K_RF2316) { - ath5k_hw_reg_write(ah, 0x00004000, - AR5K_PHY_AGC); - ath5k_hw_reg_write(ah, 0x081b7caa, - 0xa274); - } - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - break; - case AR5K_RF2317: - case AR5K_RF2425: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf2425_ini_mode_end), - rf2425_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf2425_ini_common_end), - rf2425_ini_common_end, change_channel); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - break; - default: - return -EINVAL; - - } - - /* For AR5211 */ - } else if (ah->ah_version == AR5K_AR5211) { - - /* AR5K_MODE_11B */ - if (mode > 2) { - ATH5K_ERR(ah->ah_sc, - "unsupported channel mode: %d\n", mode); - return -EINVAL; - } - - /* Mode-specific settings */ - ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode), - ar5211_ini_mode, mode); - - /* - * Write initial settings common for all modes - */ - ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), - ar5211_ini, change_channel); - - /* AR5211 only comes with 5111 */ - - /* Baseband gain table */ - ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); - /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ - } else if (ah->ah_version == AR5K_AR5210) { - ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), - ar5210_ini, change_channel); - } - - return 0; -} diff --git a/drivers/net/wireless/ath5k/led.c b/drivers/net/wireless/ath5k/led.c deleted file mode 100644 index 19555fb79c9b..000000000000 --- a/drivers/net/wireless/ath5k/led.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2009 Bob Copeland - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -#include -#include "ath5k.h" -#include "base.h" - -#define ATH_SDEVICE(subv,subd) \ - .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ - .subvendor = (subv), .subdevice = (subd) - -#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity)) -#define ATH_PIN(data) ((data) >> 8) -#define ATH_POLARITY(data) ((data) & 0xff) - -/* Devices we match on for LED config info (typically laptops) */ -static const struct pci_device_id ath5k_led_devices[] = { - /* IBM-specific AR5212 */ - { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, - /* AR5211 */ - { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, - /* HP Compaq nc6xx, nc4000, nx6000 */ - { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, - /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, - /* Acer Ferrari 5000 (russ.dill@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, - /* E-machines E510 (tuliom@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, - /* Acer Extensa 5620z (nekoreeve@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, - { } -}; - -void ath5k_led_enable(struct ath5k_softc *sc) -{ - if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { - ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); - ath5k_led_off(sc); - } -} - -void ath5k_led_on(struct ath5k_softc *sc) -{ - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); -} - -void ath5k_led_off(struct ath5k_softc *sc) -{ - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); -} - -static void -ath5k_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct ath5k_led *led = container_of(led_dev, struct ath5k_led, - led_dev); - - if (brightness == LED_OFF) - ath5k_led_off(led->sc); - else - ath5k_led_on(led->sc); -} - -static int -ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, - const char *name, char *trigger) -{ - int err; - - led->sc = sc; - strncpy(led->name, name, sizeof(led->name)); - led->led_dev.name = led->name; - led->led_dev.default_trigger = trigger; - led->led_dev.brightness_set = ath5k_led_brightness_set; - - err = led_classdev_register(&sc->pdev->dev, &led->led_dev); - if (err) { - ATH5K_WARN(sc, "could not register LED %s\n", name); - led->sc = NULL; - } - return err; -} - -static void -ath5k_unregister_led(struct ath5k_led *led) -{ - if (!led->sc) - return; - led_classdev_unregister(&led->led_dev); - ath5k_led_off(led->sc); - led->sc = NULL; -} - -void ath5k_unregister_leds(struct ath5k_softc *sc) -{ - ath5k_unregister_led(&sc->rx_led); - ath5k_unregister_led(&sc->tx_led); -} - -int ath5k_init_leds(struct ath5k_softc *sc) -{ - int ret = 0; - struct ieee80211_hw *hw = sc->hw; - struct pci_dev *pdev = sc->pdev; - char name[ATH5K_LED_MAX_NAME_LEN + 1]; - const struct pci_device_id *match; - - match = pci_match_id(&ath5k_led_devices[0], pdev); - if (match) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = ATH_PIN(match->driver_data); - sc->led_on = ATH_POLARITY(match->driver_data); - } - - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - goto out; - - ath5k_led_enable(sc); - - snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->rx_led, name, - ieee80211_get_rx_led_name(hw)); - if (ret) - goto out; - - snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->tx_led, name, - ieee80211_get_tx_led_name(hw)); -out: - return ret; -} - diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c deleted file mode 100644 index 55122f1e1986..000000000000 --- a/drivers/net/wireless/ath5k/pcu.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Matthew W. S. Bell - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*********************************\ -* Protocol Control Unit Functions * -\*********************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/*******************\ -* Generic functions * -\*******************/ - -/** - * ath5k_hw_set_opmode - Set PCU operating mode - * - * @ah: The &struct ath5k_hw - * - * Initialize PCU for the various operating modes (AP/STA etc) - * - * NOTE: ah->ah_op_mode must be set before calling this. - */ -int ath5k_hw_set_opmode(struct ath5k_hw *ah) -{ - u32 pcu_reg, beacon_reg, low_id, high_id; - - - /* Preserve rest settings */ - pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; - pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP - | AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); - - beacon_reg = 0; - - ATH5K_TRACE(ah->ah_sc); - - switch (ah->ah_op_mode) { - case NL80211_IFTYPE_ADHOC: - pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_ADHOC; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; - - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_AP; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; - - case NL80211_IFTYPE_STATION: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_PWR_SV : 0); - case NL80211_IFTYPE_MONITOR: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_NO_PSPOLL : 0); - break; - - default: - return -EINVAL; - } - - /* - * Set PCU registers - */ - low_id = AR5K_LOW_ID(ah->ah_sta_id); - high_id = AR5K_HIGH_ID(ah->ah_sta_id); - ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); - ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); - - /* - * Set Beacon Control Register on 5210 - */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); - - return 0; -} - -/** - * ath5k_hw_update - Update mib counters (mac layer statistics) - * - * @ah: The &struct ath5k_hw - * @stats: The &struct ieee80211_low_level_stats we use to track - * statistics on the driver - * - * Reads MIB counters from PCU and updates sw statistics. Must be - * called after a MIB interrupt. - */ -void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, - struct ieee80211_low_level_stats *stats) -{ - ATH5K_TRACE(ah->ah_sc); - - /* Read-And-Clear */ - stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); - stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); - stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); - stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); - - /* XXX: Should we use this to track beacon count ? - * -we read it anyway to clear the register */ - ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); - - /* Reset profile count registers on 5212*/ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); - } - - /* TODO: Handle ANI stats */ -} - -/** - * ath5k_hw_set_ack_bitrate - set bitrate for ACKs - * - * @ah: The &struct ath5k_hw - * @high: Flag to determine if we want to use high transmition rate - * for ACKs or not - * - * If high flag is set, we tell hw to use a set of control rates based on - * the current transmition rate (check out control_rates array inside reset.c). - * If not hw just uses the lowest rate available for the current modulation - * scheme being used (1Mbit for CCK and 6Mbits for OFDM). - */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) -{ - if (ah->ah_version != AR5K_AR5212) - return; - else { - u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; - if (high) - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); - } -} - - -/******************\ -* ACK/CTS Timeouts * -\******************/ - -/** - * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec - * - * @ah: The &struct ath5k_hw - */ -unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); -} - -/** - * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU - * - * @ah: The &struct ath5k_hw - * @timeout: Timeout in usec - */ -int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) -{ - ATH5K_TRACE(ah->ah_sc); - if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), - ah->ah_turbo) <= timeout) - return -EINVAL; - - AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, - ath5k_hw_htoclock(timeout, ah->ah_turbo)); - - return 0; -} - -/** - * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec - * - * @ah: The &struct ath5k_hw - */ -unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); -} - -/** - * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU - * - * @ah: The &struct ath5k_hw - * @timeout: Timeout in usec - */ -int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) -{ - ATH5K_TRACE(ah->ah_sc); - if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), - ah->ah_turbo) <= timeout) - return -EINVAL; - - AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, - ath5k_hw_htoclock(timeout, ah->ah_turbo)); - - return 0; -} - - -/****************\ -* BSSID handling * -\****************/ - -/** - * ath5k_hw_get_lladdr - Get station id - * - * @ah: The &struct ath5k_hw - * @mac: The card's mac address - * - * Initialize ah->ah_sta_id using the mac address provided - * (just a memcpy). - * - * TODO: Remove it once we merge ath5k_softc and ath5k_hw - */ -void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) -{ - ATH5K_TRACE(ah->ah_sc); - memcpy(mac, ah->ah_sta_id, ETH_ALEN); -} - -/** - * ath5k_hw_set_lladdr - Set station id - * - * @ah: The &struct ath5k_hw - * @mac: The card's mac address - * - * Set station id on hw using the provided mac address - */ -int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) -{ - u32 low_id, high_id; - u32 pcu_reg; - - ATH5K_TRACE(ah->ah_sc); - /* Set new station ID */ - memcpy(ah->ah_sta_id, mac, ETH_ALEN); - - pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; - - low_id = AR5K_LOW_ID(mac); - high_id = AR5K_HIGH_ID(mac); - - ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); - ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); - - return 0; -} - -/** - * ath5k_hw_set_associd - Set BSSID for association - * - * @ah: The &struct ath5k_hw - * @bssid: BSSID - * @assoc_id: Assoc id - * - * Sets the BSSID which trigers the "SME Join" operation - */ -void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) -{ - u32 low_id, high_id; - u16 tim_offset = 0; - - /* - * Set simple BSSID mask on 5212 - */ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), - AR5K_BSS_IDM0); - ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), - AR5K_BSS_IDM1); - } - - /* - * Set BSSID which triggers the "SME Join" operation - */ - low_id = AR5K_LOW_ID(bssid); - high_id = AR5K_HIGH_ID(bssid); - ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); - ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << - AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); - - if (assoc_id == 0) { - ath5k_hw_disable_pspoll(ah); - return; - } - - AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, - tim_offset ? tim_offset + 4 : 0); - - ath5k_hw_enable_pspoll(ah, NULL, 0); -} - -/** - * ath5k_hw_set_bssid_mask - filter out bssids we listen - * - * @ah: the &struct ath5k_hw - * @mask: the bssid_mask, a u8 array of size ETH_ALEN - * - * BSSID masking is a method used by AR5212 and newer hardware to inform PCU - * which bits of the interface's MAC address should be looked at when trying - * to decide which packets to ACK. In station mode and AP mode with a single - * BSS every bit matters since we lock to only one BSS. In AP mode with - * multiple BSSes (virtual interfaces) not every bit matters because hw must - * accept frames for all BSSes and so we tweak some bits of our mac address - * in order to have multiple BSSes. - * - * NOTE: This is a simple filter and does *not* filter out all - * relevant frames. Some frames that are not for us might get ACKed from us - * by PCU because they just match the mask. - * - * When handling multiple BSSes you can get the BSSID mask by computing the - * set of ~ ( MAC XOR BSSID ) for all bssids we handle. - * - * When you do this you are essentially computing the common bits of all your - * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with - * the MAC address to obtain the relevant bits and compare the result with - * (frame's BSSID & mask) to see if they match. - */ -/* - * Simple example: on your card you have have two BSSes you have created with - * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. - * There is another BSSID-03 but you are not part of it. For simplicity's sake, - * assuming only 4 bits for a mac address and for BSSIDs you can then have: - * - * \ - * MAC: 0001 | - * BSSID-01: 0100 | --> Belongs to us - * BSSID-02: 1001 | - * / - * ------------------- - * BSSID-03: 0110 | --> External - * ------------------- - * - * Our bssid_mask would then be: - * - * On loop iteration for BSSID-01: - * ~(0001 ^ 0100) -> ~(0101) - * -> 1010 - * bssid_mask = 1010 - * - * On loop iteration for BSSID-02: - * bssid_mask &= ~(0001 ^ 1001) - * bssid_mask = (1010) & ~(0001 ^ 1001) - * bssid_mask = (1010) & ~(1001) - * bssid_mask = (1010) & (0110) - * bssid_mask = 0010 - * - * A bssid_mask of 0010 means "only pay attention to the second least - * significant bit". This is because its the only bit common - * amongst the MAC and all BSSIDs we support. To findout what the real - * common bit is we can simply "&" the bssid_mask now with any BSSID we have - * or our MAC address (we assume the hardware uses the MAC address). - * - * Now, suppose there's an incoming frame for BSSID-03: - * - * IFRAME-01: 0110 - * - * An easy eye-inspeciton of this already should tell you that this frame - * will not pass our check. This is beacuse the bssid_mask tells the - * hardware to only look at the second least significant bit and the - * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB - * as 1, which does not match 0. - * - * So with IFRAME-01 we *assume* the hardware will do: - * - * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; - * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; - * --> allow = (0010) == 0000 ? 1 : 0; - * --> allow = 0 - * - * Lets now test a frame that should work: - * - * IFRAME-02: 0001 (we should allow) - * - * allow = (0001 & 1010) == 1010 - * - * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; - * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; - * --> allow = (0010) == (0010) - * --> allow = 1 - * - * Other examples: - * - * IFRAME-03: 0100 --> allowed - * IFRAME-04: 1001 --> allowed - * IFRAME-05: 1101 --> allowed but its not for us!!! - * - */ -int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) -{ - u32 low_id, high_id; - ATH5K_TRACE(ah->ah_sc); - - /* Cache bssid mask so that we can restore it - * on reset */ - memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); - if (ah->ah_version == AR5K_AR5212) { - low_id = AR5K_LOW_ID(mask); - high_id = AR5K_HIGH_ID(mask); - - ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); - ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); - - return 0; - } - - return -EIO; -} - - -/************\ -* RX Control * -\************/ - -/** - * ath5k_hw_start_rx_pcu - Start RX engine - * - * @ah: The &struct ath5k_hw - * - * Starts RX engine on PCU so that hw can process RXed frames - * (ACK etc). - * - * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma - * TODO: Init ANI here - */ -void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - -/** - * at5k_hw_stop_rx_pcu - Stop RX engine - * - * @ah: The &struct ath5k_hw - * - * Stops RX engine on PCU - * - * TODO: Detach ANI here - */ -void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - -/* - * Set multicast filter - */ -void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) -{ - ATH5K_TRACE(ah->ah_sc); - /* Set the multicat filter */ - ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); - ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); -} - -/* - * Set multicast filter by index - */ -int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) -{ - - ATH5K_TRACE(ah->ah_sc); - if (index >= 64) - return -EINVAL; - else if (index >= 32) - AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, - (1 << (index - 32))); - else - AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); - - return 0; -} - -/* - * Clear Multicast filter by index - */ -int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) -{ - - ATH5K_TRACE(ah->ah_sc); - if (index >= 64) - return -EINVAL; - else if (index >= 32) - AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, - (1 << (index - 32))); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); - - return 0; -} - -/** - * ath5k_hw_get_rx_filter - Get current rx filter - * - * @ah: The &struct ath5k_hw - * - * Returns the RX filter by reading rx filter and - * phy error filter registers. RX filter is used - * to set the allowed frame types that PCU will accept - * and pass to the driver. For a list of frame types - * check out reg.h. - */ -u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) -{ - u32 data, filter = 0; - - ATH5K_TRACE(ah->ah_sc); - filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); - - /*Radar detection for 5212*/ - if (ah->ah_version == AR5K_AR5212) { - data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); - - if (data & AR5K_PHY_ERR_FIL_RADAR) - filter |= AR5K_RX_FILTER_RADARERR; - if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) - filter |= AR5K_RX_FILTER_PHYERR; - } - - return filter; -} - -/** - * ath5k_hw_set_rx_filter - Set rx filter - * - * @ah: The &struct ath5k_hw - * @filter: RX filter mask (see reg.h) - * - * Sets RX filter register and also handles PHY error filter - * register on 5212 and newer chips so that we have proper PHY - * error reporting. - */ -void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) -{ - u32 data = 0; - - ATH5K_TRACE(ah->ah_sc); - - /* Set PHY error filter register on 5212*/ - if (ah->ah_version == AR5K_AR5212) { - if (filter & AR5K_RX_FILTER_RADARERR) - data |= AR5K_PHY_ERR_FIL_RADAR; - if (filter & AR5K_RX_FILTER_PHYERR) - data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; - } - - /* - * The AR5210 uses promiscous mode to detect radar activity - */ - if (ah->ah_version == AR5K_AR5210 && - (filter & AR5K_RX_FILTER_RADARERR)) { - filter &= ~AR5K_RX_FILTER_RADARERR; - filter |= AR5K_RX_FILTER_PROM; - } - - /*Zero length DMA (phy error reporting) */ - if (data) - AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); - - /*Write RX Filter register*/ - ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); - - /*Write PHY error filter register on 5212*/ - if (ah->ah_version == AR5K_AR5212) - ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); - -} - - -/****************\ -* Beacon control * -\****************/ - -/** - * ath5k_hw_get_tsf32 - Get a 32bit TSF - * - * @ah: The &struct ath5k_hw - * - * Returns lower 32 bits of current TSF - */ -u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_TSF_L32); -} - -/** - * ath5k_hw_get_tsf64 - Get the full 64bit TSF - * - * @ah: The &struct ath5k_hw - * - * Returns the current TSF - */ -u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) -{ - u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - ATH5K_TRACE(ah->ah_sc); - - return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); -} - -/** - * ath5k_hw_set_tsf64 - Set a new 64bit TSF - * - * @ah: The &struct ath5k_hw - * @tsf64: The new 64bit TSF - * - * Sets the new TSF - */ -void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) -{ - ATH5K_TRACE(ah->ah_sc); - - ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); - ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); -} - -/** - * ath5k_hw_reset_tsf - Force a TSF reset - * - * @ah: The &struct ath5k_hw - * - * Forces a TSF reset on PCU - */ -void ath5k_hw_reset_tsf(struct ath5k_hw *ah) -{ - u32 val; - - ATH5K_TRACE(ah->ah_sc); - - val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; - - /* - * Each write to the RESET_TSF bit toggles a hardware internal - * signal to reset TSF, but if left high it will cause a TSF reset - * on the next chip reset as well. Thus we always write the value - * twice to clear the signal. - */ - ath5k_hw_reg_write(ah, val, AR5K_BEACON); - ath5k_hw_reg_write(ah, val, AR5K_BEACON); -} - -/* - * Initialize beacon timers - */ -void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) -{ - u32 timer1, timer2, timer3; - - ATH5K_TRACE(ah->ah_sc); - /* - * Set the additional timers by mode - */ - switch (ah->ah_op_mode) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_STATION: - /* In STA mode timer1 is used as next wakeup - * timer and timer2 as next CFP duration start - * timer. Both in 1/8TUs. */ - /* TODO: PCF handling */ - if (ah->ah_version == AR5K_AR5210) { - timer1 = 0xffffffff; - timer2 = 0xffffffff; - } else { - timer1 = 0x0000ffff; - timer2 = 0x0007ffff; - } - /* Mark associated AP as PCF incapable for now */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); - break; - case NL80211_IFTYPE_ADHOC: - AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); - default: - /* On non-STA modes timer1 is used as next DMA - * beacon alert (DBA) timer and timer2 as next - * software beacon alert. Both in 1/8TUs. */ - timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; - timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; - break; - } - - /* Timer3 marks the end of our ATIM window - * a zero length window is not allowed because - * we 'll get no beacons */ - timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); - - /* - * Set the beacon register and enable all timers. - */ - /* When in AP mode zero timer0 to start TSF */ - if (ah->ah_op_mode == NL80211_IFTYPE_AP) - ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - else - ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); - ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); - ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); - ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); - - /* Force a TSF reset if requested and enable beacons */ - if (interval & AR5K_BEACON_RESET_TSF) - ath5k_hw_reset_tsf(ah); - - ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | - AR5K_BEACON_ENABLE), - AR5K_BEACON); - - /* Flush any pending BMISS interrupts on ISR by - * performing a clear-on-write operation on PISR - * register for the BMISS bit (writing a bit on - * ISR togles a reset for that bit and leaves - * the rest bits intact) */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); - else - ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); - - /* TODO: Set enchanced sleep registers on AR5212 - * based on vif->bss_conf params, until then - * disable power save reporting.*/ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); - -} - -#if 0 -/* - * Set beacon timers - */ -int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, - const struct ath5k_beacon_state *state) -{ - u32 cfp_period, next_cfp, dtim, interval, next_beacon; - - /* - * TODO: should be changed through *state - * review struct ath5k_beacon_state struct - * - * XXX: These are used for cfp period bellow, are they - * ok ? Is it O.K. for tsf here to be 0 or should we use - * get_tsf ? - */ - u32 dtim_count = 0; /* XXX */ - u32 cfp_count = 0; /* XXX */ - u32 tsf = 0; /* XXX */ - - ATH5K_TRACE(ah->ah_sc); - /* Return on an invalid beacon state */ - if (state->bs_interval < 1) - return -EINVAL; - - interval = state->bs_interval; - dtim = state->bs_dtim_period; - - /* - * PCF support? - */ - if (state->bs_cfp_period > 0) { - /* - * Enable PCF mode and set the CFP - * (Contention Free Period) and timer registers - */ - cfp_period = state->bs_cfp_period * state->bs_dtim_period * - state->bs_interval; - next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * - state->bs_interval; - - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_PCF); - ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); - ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, - AR5K_CFP_DUR); - ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : - next_cfp)) << 3, AR5K_TIMER2); - } else { - /* Disable PCF mode */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_PCF); - } - - /* - * Enable the beacon timer register - */ - ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); - - /* - * Start the beacon timers - */ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & - ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | - AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, - AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, - AR5K_BEACON_PERIOD), AR5K_BEACON); - - /* - * Write new beacon miss threshold, if it appears to be valid - * XXX: Figure out right values for min <= bs_bmiss_threshold <= max - * and return if its not in range. We can test this by reading value and - * setting value to a largest value and seeing which values register. - */ - - AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, - state->bs_bmiss_threshold); - - /* - * Set sleep control register - * XXX: Didn't find this in 5210 code but since this register - * exists also in ar5k's 5210 headers i leave it as common code. - */ - AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, - (state->bs_sleep_duration - 3) << 3); - - /* - * Set enhanced sleep registers on 5212 - */ - if (ah->ah_version == AR5K_AR5212) { - if (state->bs_sleep_duration > state->bs_interval && - roundup(state->bs_sleep_duration, interval) == - state->bs_sleep_duration) - interval = state->bs_sleep_duration; - - if (state->bs_sleep_duration > dtim && (dtim == 0 || - roundup(state->bs_sleep_duration, dtim) == - state->bs_sleep_duration)) - dtim = state->bs_sleep_duration; - - if (interval > dtim) - return -EINVAL; - - next_beacon = interval == dtim ? state->bs_next_dtim : - state->bs_next_beacon; - - ath5k_hw_reg_write(ah, - AR5K_REG_SM((state->bs_next_dtim - 3) << 3, - AR5K_SLEEP0_NEXT_DTIM) | - AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | - AR5K_SLEEP0_ENH_SLEEP_EN | - AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); - - ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, - AR5K_SLEEP1_NEXT_TIM) | - AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); - - ath5k_hw_reg_write(ah, - AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | - AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); - } - - return 0; -} - -/* - * Reset beacon timers - */ -void ath5k_hw_reset_beacon(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - /* - * Disable beacon timer - */ - ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - - /* - * Disable some beacon register values - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); - ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); -} - -/* - * Wait for beacon queue to finish - */ -int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) -{ - unsigned int i; - int ret; - - ATH5K_TRACE(ah->ah_sc); - - /* 5210 doesn't have QCU*/ - if (ah->ah_version == AR5K_AR5210) { - /* - * Wait for beaconn queue to finish by checking - * Control Register and Beacon Status Register. - */ - for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { - if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) - || - !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) - break; - udelay(10); - } - - /* Timeout... */ - if (i <= 0) { - /* - * Re-schedule the beacon queue - */ - ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, - AR5K_BCR); - - return -EIO; - } - ret = 0; - } else { - /*5211/5212*/ - ret = ath5k_hw_register_timeout(ah, - AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), - AR5K_QCU_STS_FRMPENDCNT, 0, false); - - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) - return -EIO; - } - - return ret; -} -#endif - - -/*********************\ -* Key table functions * -\*********************/ - -/* - * Reset a key entry on the table - */ -int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) -{ - unsigned int i, type; - u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); - - for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) - ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); - - /* Reset associated MIC entry if TKIP - * is enabled located at offset (entry + 64) */ - if (type == AR5K_KEYTABLE_TYPE_TKIP) { - AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); - for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) - ath5k_hw_reg_write(ah, 0, - AR5K_KEYTABLE_OFF(micentry, i)); - } - - /* - * Set NULL encryption on AR5212+ - * - * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) - * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 - * - * Note2: Windows driver (ndiswrapper) sets this to - * 0x00000714 instead of 0x00000007 - */ - if (ah->ah_version > AR5K_AR5211) { - ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, - AR5K_KEYTABLE_TYPE(entry)); - - if (type == AR5K_KEYTABLE_TYPE_TKIP) { - ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, - AR5K_KEYTABLE_TYPE(micentry)); - } - } - - return 0; -} - -/* - * Check if a table entry is valid - */ -int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - /* Check the validation flag at the end of the entry */ - return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & - AR5K_KEYTABLE_VALID; -} - -static -int ath5k_keycache_type(const struct ieee80211_key_conf *key) -{ - switch (key->alg) { - case ALG_TKIP: - return AR5K_KEYTABLE_TYPE_TKIP; - case ALG_CCMP: - return AR5K_KEYTABLE_TYPE_CCM; - case ALG_WEP: - if (key->keylen == LEN_WEP40) - return AR5K_KEYTABLE_TYPE_40; - else if (key->keylen == LEN_WEP104) - return AR5K_KEYTABLE_TYPE_104; - return -EINVAL; - default: - return -EINVAL; - } - return -EINVAL; -} - -/* - * Set a key entry on the table - */ -int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, - const struct ieee80211_key_conf *key, const u8 *mac) -{ - unsigned int i; - int keylen; - __le32 key_v[5] = {}; - __le32 key0 = 0, key1 = 0; - __le32 *rxmic, *txmic; - int keytype; - u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; - bool is_tkip; - const u8 *key_ptr; - - ATH5K_TRACE(ah->ah_sc); - - is_tkip = (key->alg == ALG_TKIP); - - /* - * key->keylen comes in from mac80211 in bytes. - * TKIP is 128 bit + 128 bit mic - */ - keylen = (is_tkip) ? (128 / 8) : key->keylen; - - if (entry > AR5K_KEYTABLE_SIZE || - (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) - return -EOPNOTSUPP; - - if (unlikely(keylen > 16)) - return -EOPNOTSUPP; - - keytype = ath5k_keycache_type(key); - if (keytype < 0) - return keytype; - - /* - * each key block is 6 bytes wide, written as pairs of - * alternating 32 and 16 bit le values. - */ - key_ptr = key->key; - for (i = 0; keylen >= 6; keylen -= 6) { - memcpy(&key_v[i], key_ptr, 6); - i += 2; - key_ptr += 6; - } - if (keylen) - memcpy(&key_v[i], key_ptr, keylen); - - /* intentionally corrupt key until mic is installed */ - if (is_tkip) { - key0 = key_v[0] = ~key_v[0]; - key1 = key_v[1] = ~key_v[1]; - } - - for (i = 0; i < ARRAY_SIZE(key_v); i++) - ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), - AR5K_KEYTABLE_OFF(entry, i)); - - ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); - - if (is_tkip) { - /* Install rx/tx MIC */ - rxmic = (__le32 *) &key->key[16]; - txmic = (__le32 *) &key->key[24]; - - if (ah->ah_combined_mic) { - key_v[0] = rxmic[0]; - key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); - key_v[2] = rxmic[1]; - key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); - key_v[4] = txmic[1]; - } else { - key_v[0] = rxmic[0]; - key_v[1] = 0; - key_v[2] = rxmic[1]; - key_v[3] = 0; - key_v[4] = 0; - } - for (i = 0; i < ARRAY_SIZE(key_v); i++) - ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), - AR5K_KEYTABLE_OFF(micentry, i)); - - ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, - AR5K_KEYTABLE_TYPE(micentry)); - ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); - ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); - - /* restore first 2 words of key */ - ath5k_hw_reg_write(ah, le32_to_cpu(~key0), - AR5K_KEYTABLE_OFF(entry, 0)); - ath5k_hw_reg_write(ah, le32_to_cpu(~key1), - AR5K_KEYTABLE_OFF(entry, 1)); - } - - return ath5k_hw_set_key_lladdr(ah, entry, mac); -} - -int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) -{ - u32 low_id, high_id; - - ATH5K_TRACE(ah->ah_sc); - /* Invalid entry (key table overflow) */ - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - /* MAC may be NULL if it's a broadcast key. In this case no need to - * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ - if (!mac) { - low_id = 0xffffffff; - high_id = 0xffff | AR5K_KEYTABLE_VALID; - } else { - low_id = AR5K_LOW_ID(mac); - high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; - } - - ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); - ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); - - return 0; -} - diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c deleted file mode 100644 index 9e2faae5ae94..000000000000 --- a/drivers/net/wireless/ath5k/phy.c +++ /dev/null @@ -1,2599 +0,0 @@ -/* - * PHY functions - * - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * Copyright (c) 2008-2009 Felix Fietkau - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#define _ATH5K_PHY - -#include - -#include "ath5k.h" -#include "reg.h" -#include "base.h" -#include "rfbuffer.h" -#include "rfgain.h" - -/* - * Used to modify RF Banks before writing them to AR5K_RF_BUFFER - */ -static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, - const struct ath5k_rf_reg *rf_regs, - u32 val, u8 reg_id, bool set) -{ - const struct ath5k_rf_reg *rfreg = NULL; - u8 offset, bank, num_bits, col, position; - u16 entry; - u32 mask, data, last_bit, bits_shifted, first_bit; - u32 *rfb; - s32 bits_left; - int i; - - data = 0; - rfb = ah->ah_rf_banks; - - for (i = 0; i < ah->ah_rf_regs_count; i++) { - if (rf_regs[i].index == reg_id) { - rfreg = &rf_regs[i]; - break; - } - } - - if (rfb == NULL || rfreg == NULL) { - ATH5K_PRINTF("Rf register not found!\n"); - /* should not happen */ - return 0; - } - - bank = rfreg->bank; - num_bits = rfreg->field.len; - first_bit = rfreg->field.pos; - col = rfreg->field.col; - - /* first_bit is an offset from bank's - * start. Since we have all banks on - * the same array, we use this offset - * to mark each bank's start */ - offset = ah->ah_offset[bank]; - - /* Boundary check */ - if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) { - ATH5K_PRINTF("invalid values at offset %u\n", offset); - return 0; - } - - entry = ((first_bit - 1) / 8) + offset; - position = (first_bit - 1) % 8; - - if (set) - data = ath5k_hw_bitswap(val, num_bits); - - for (bits_shifted = 0, bits_left = num_bits; bits_left > 0; - position = 0, entry++) { - - last_bit = (position + bits_left > 8) ? 8 : - position + bits_left; - - mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) << - (col * 8); - - if (set) { - rfb[entry] &= ~mask; - rfb[entry] |= ((data << position) << (col * 8)) & mask; - data >>= (8 - position); - } else { - data |= (((rfb[entry] & mask) >> (col * 8)) >> position) - << bits_shifted; - bits_shifted += last_bit - position; - } - - bits_left -= 8 - position; - } - - data = set ? 1 : ath5k_hw_bitswap(data, num_bits); - - return data; -} - -/**********************\ -* RF Gain optimization * -\**********************/ - -/* - * This code is used to optimize rf gain on different environments - * (temprature mostly) based on feedback from a power detector. - * - * It's only used on RF5111 and RF5112, later RF chips seem to have - * auto adjustment on hw -notice they have a much smaller BANK 7 and - * no gain optimization ladder-. - * - * For more infos check out this patent doc - * http://www.freepatentsonline.com/7400691.html - * - * This paper describes power drops as seen on the receiver due to - * probe packets - * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues - * %20of%20Power%20Control.pdf - * - * And this is the MadWiFi bug entry related to the above - * http://madwifi-project.org/ticket/1659 - * with various measurements and diagrams - * - * TODO: Deal with power drops due to probes by setting an apropriate - * tx power on the probe packets ! Make this part of the calibration process. - */ - -/* Initialize ah_gain durring attach */ -int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) -{ - /* Initialize the gain optimization values */ - switch (ah->ah_radio) { - case AR5K_RF5111: - ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default; - ah->ah_gain.g_low = 20; - ah->ah_gain.g_high = 35; - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - break; - case AR5K_RF5112: - ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; - ah->ah_gain.g_low = 20; - ah->ah_gain.g_high = 85; - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* Schedule a gain probe check on the next transmited packet. - * That means our next packet is going to be sent with lower - * tx power and a Peak to Average Power Detector (PAPD) will try - * to measure the gain. - * - * TODO: Use propper tx power setting for the probe packet so - * that we don't observe a serious power drop on the receiver - * - * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) - * just after we enable the probe so that we don't mess with - * standard traffic ? Maybe it's time to use sw interrupts and - * a probe tasklet !!! - */ -static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) -{ - - /* Skip if gain calibration is inactive or - * we already handle a probe request */ - if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE) - return; - - /* Send the packet with 2dB below max power as - * patent doc suggest */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, - AR5K_PHY_PAPD_PROBE_TXPOWER) | - AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); - - ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED; - -} - -/* Calculate gain_F measurement correction - * based on the current step for RF5112 rev. 2 */ -static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) -{ - u32 mix, step; - u32 *rf; - const struct ath5k_gain_opt *go; - const struct ath5k_gain_opt_step *g_step; - const struct ath5k_rf_reg *rf_regs; - - /* Only RF5112 Rev. 2 supports it */ - if ((ah->ah_radio != AR5K_RF5112) || - (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A)) - return 0; - - go = &rfgain_opt_5112; - rf_regs = rf_regs_5112a; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); - - g_step = &go->go_step[ah->ah_gain.g_step_idx]; - - if (ah->ah_rf_banks == NULL) - return 0; - - rf = ah->ah_rf_banks; - ah->ah_gain.g_f_corr = 0; - - /* No VGA (Variable Gain Amplifier) override, skip */ - if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1) - return 0; - - /* Mix gain stepping */ - step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false); - - /* Mix gain override */ - mix = g_step->gos_param[0]; - - switch (mix) { - case 3: - ah->ah_gain.g_f_corr = step * 2; - break; - case 2: - ah->ah_gain.g_f_corr = (step - 5) * 2; - break; - case 1: - ah->ah_gain.g_f_corr = step; - break; - default: - ah->ah_gain.g_f_corr = 0; - break; - } - - return ah->ah_gain.g_f_corr; -} - -/* Check if current gain_F measurement is in the range of our - * power detector windows. If we get a measurement outside range - * we know it's not accurate (detectors can't measure anything outside - * their detection window) so we must ignore it */ -static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) -{ - const struct ath5k_rf_reg *rf_regs; - u32 step, mix_ovr, level[4]; - u32 *rf; - - if (ah->ah_rf_banks == NULL) - return false; - - rf = ah->ah_rf_banks; - - if (ah->ah_radio == AR5K_RF5111) { - - rf_regs = rf_regs_5111; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); - - step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP, - false); - - level[0] = 0; - level[1] = (step == 63) ? 50 : step + 4; - level[2] = (step != 63) ? 64 : level[0]; - level[3] = level[2] + 50 ; - - ah->ah_gain.g_high = level[3] - - (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5); - ah->ah_gain.g_low = level[0] + - (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0); - } else { - - rf_regs = rf_regs_5112; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); - - mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, - false); - - level[0] = level[2] = 0; - - if (mix_ovr == 1) { - level[1] = level[3] = 83; - } else { - level[1] = level[3] = 107; - ah->ah_gain.g_high = 55; - } - } - - return (ah->ah_gain.g_current >= level[0] && - ah->ah_gain.g_current <= level[1]) || - (ah->ah_gain.g_current >= level[2] && - ah->ah_gain.g_current <= level[3]); -} - -/* Perform gain_F adjustment by choosing the right set - * of parameters from rf gain optimization ladder */ -static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) -{ - const struct ath5k_gain_opt *go; - const struct ath5k_gain_opt_step *g_step; - int ret = 0; - - switch (ah->ah_radio) { - case AR5K_RF5111: - go = &rfgain_opt_5111; - break; - case AR5K_RF5112: - go = &rfgain_opt_5112; - break; - default: - return 0; - } - - g_step = &go->go_step[ah->ah_gain.g_step_idx]; - - if (ah->ah_gain.g_current >= ah->ah_gain.g_high) { - - /* Reached maximum */ - if (ah->ah_gain.g_step_idx == 0) - return -1; - - for (ah->ah_gain.g_target = ah->ah_gain.g_current; - ah->ah_gain.g_target >= ah->ah_gain.g_high && - ah->ah_gain.g_step_idx > 0; - g_step = &go->go_step[ah->ah_gain.g_step_idx]) - ah->ah_gain.g_target -= 2 * - (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain - - g_step->gos_gain); - - ret = 1; - goto done; - } - - if (ah->ah_gain.g_current <= ah->ah_gain.g_low) { - - /* Reached minimum */ - if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1)) - return -2; - - for (ah->ah_gain.g_target = ah->ah_gain.g_current; - ah->ah_gain.g_target <= ah->ah_gain.g_low && - ah->ah_gain.g_step_idx < go->go_steps_count-1; - g_step = &go->go_step[ah->ah_gain.g_step_idx]) - ah->ah_gain.g_target -= 2 * - (go->go_step[++ah->ah_gain.g_step_idx].gos_gain - - g_step->gos_gain); - - ret = 2; - goto done; - } - -done: - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, - "ret %d, gain step %u, current gain %u, target gain %u\n", - ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current, - ah->ah_gain.g_target); - - return ret; -} - -/* Main callback for thermal rf gain calibration engine - * Check for a new gain reading and schedule an adjustment - * if needed. - * - * TODO: Use sw interrupt to schedule reset if gain_F needs - * adjustment */ -enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) -{ - u32 data, type; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_rf_banks == NULL || - ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) - return AR5K_RFGAIN_INACTIVE; - - /* No check requested, either engine is inactive - * or an adjustment is already requested */ - if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED) - goto done; - - /* Read the PAPD (Peak to Average Power Detector) - * register */ - data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE); - - /* No probe is scheduled, read gain_F measurement */ - if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) { - ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S; - type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE); - - /* If tx packet is CCK correct the gain_F measurement - * by cck ofdm gain delta */ - if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) { - if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) - ah->ah_gain.g_current += - ee->ee_cck_ofdm_gain_delta; - else - ah->ah_gain.g_current += - AR5K_GAIN_CCK_PROBE_CORR; - } - - /* Further correct gain_F measurement for - * RF5112A radios */ - if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { - ath5k_hw_rf_gainf_corr(ah); - ah->ah_gain.g_current = - ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ? - (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) : - 0; - } - - /* Check if measurement is ok and if we need - * to adjust gain, schedule a gain adjustment, - * else switch back to the acive state */ - if (ath5k_hw_rf_check_gainf_readback(ah) && - AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) && - ath5k_hw_rf_gainf_adjust(ah)) { - ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE; - } else { - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - } - } - -done: - return ah->ah_gain.g_state; -} - -/* Write initial rf gain table to set the RF sensitivity - * this one works on all RF chips and has nothing to do - * with gain_F calibration */ -int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) -{ - const struct ath5k_ini_rfgain *ath5k_rfg; - unsigned int i, size; - - switch (ah->ah_radio) { - case AR5K_RF5111: - ath5k_rfg = rfgain_5111; - size = ARRAY_SIZE(rfgain_5111); - break; - case AR5K_RF5112: - ath5k_rfg = rfgain_5112; - size = ARRAY_SIZE(rfgain_5112); - break; - case AR5K_RF2413: - ath5k_rfg = rfgain_2413; - size = ARRAY_SIZE(rfgain_2413); - break; - case AR5K_RF2316: - ath5k_rfg = rfgain_2316; - size = ARRAY_SIZE(rfgain_2316); - break; - case AR5K_RF5413: - ath5k_rfg = rfgain_5413; - size = ARRAY_SIZE(rfgain_5413); - break; - case AR5K_RF2317: - case AR5K_RF2425: - ath5k_rfg = rfgain_2425; - size = ARRAY_SIZE(rfgain_2425); - break; - default: - return -EINVAL; - } - - switch (freq) { - case AR5K_INI_RFGAIN_2GHZ: - case AR5K_INI_RFGAIN_5GHZ: - break; - default: - return -EINVAL; - } - - for (i = 0; i < size; i++) { - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], - (u32)ath5k_rfg[i].rfg_register); - } - - return 0; -} - - - -/********************\ -* RF Registers setup * -\********************/ - - -/* - * Setup RF registers by writing rf buffer on hw - */ -int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - unsigned int mode) -{ - const struct ath5k_rf_reg *rf_regs; - const struct ath5k_ini_rfbuffer *ini_rfb; - const struct ath5k_gain_opt *go = NULL; - const struct ath5k_gain_opt_step *g_step; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u8 ee_mode = 0; - u32 *rfb; - int i, obdb = -1, bank = -1; - - switch (ah->ah_radio) { - case AR5K_RF5111: - rf_regs = rf_regs_5111; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); - ini_rfb = rfb_5111; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111); - go = &rfgain_opt_5111; - break; - case AR5K_RF5112: - if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { - rf_regs = rf_regs_5112a; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); - ini_rfb = rfb_5112a; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a); - } else { - rf_regs = rf_regs_5112; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); - ini_rfb = rfb_5112; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112); - } - go = &rfgain_opt_5112; - break; - case AR5K_RF2413: - rf_regs = rf_regs_2413; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413); - ini_rfb = rfb_2413; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413); - break; - case AR5K_RF2316: - rf_regs = rf_regs_2316; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316); - ini_rfb = rfb_2316; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316); - break; - case AR5K_RF5413: - rf_regs = rf_regs_5413; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413); - ini_rfb = rfb_5413; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413); - break; - case AR5K_RF2317: - rf_regs = rf_regs_2425; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); - ini_rfb = rfb_2317; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317); - break; - case AR5K_RF2425: - rf_regs = rf_regs_2425; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); - if (ah->ah_mac_srev < AR5K_SREV_AR2417) { - ini_rfb = rfb_2425; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425); - } else { - ini_rfb = rfb_2417; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417); - } - break; - default: - return -EINVAL; - } - - /* If it's the first time we set rf buffer, allocate - * ah->ah_rf_banks based on ah->ah_rf_banks_size - * we set above */ - if (ah->ah_rf_banks == NULL) { - ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size, - GFP_KERNEL); - if (ah->ah_rf_banks == NULL) { - ATH5K_ERR(ah->ah_sc, "out of memory\n"); - return -ENOMEM; - } - } - - /* Copy values to modify them */ - rfb = ah->ah_rf_banks; - - for (i = 0; i < ah->ah_rf_banks_size; i++) { - if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) { - ATH5K_ERR(ah->ah_sc, "invalid bank\n"); - return -EINVAL; - } - - /* Bank changed, write down the offset */ - if (bank != ini_rfb[i].rfb_bank) { - bank = ini_rfb[i].rfb_bank; - ah->ah_offset[bank] = i; - } - - rfb[i] = ini_rfb[i].rfb_mode_data[mode]; - } - - /* Set Output and Driver bias current (OB/DB) */ - if (channel->hw_value & CHANNEL_2GHZ) { - - if (channel->hw_value & CHANNEL_CCK) - ee_mode = AR5K_EEPROM_MODE_11B; - else - ee_mode = AR5K_EEPROM_MODE_11G; - - /* For RF511X/RF211X combination we - * use b_OB and b_DB parameters stored - * in eeprom on ee->ee_ob[ee_mode][0] - * - * For all other chips we use OB/DB for 2Ghz - * stored in the b/g modal section just like - * 802.11a on ee->ee_ob[ee_mode][1] */ - if ((ah->ah_radio == AR5K_RF5111) || - (ah->ah_radio == AR5K_RF5112)) - obdb = 0; - else - obdb = 1; - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], - AR5K_RF_OB_2GHZ, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], - AR5K_RF_DB_2GHZ, true); - - /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */ - } else if ((channel->hw_value & CHANNEL_5GHZ) || - (ah->ah_radio == AR5K_RF5111)) { - - /* For 11a, Turbo and XR we need to choose - * OB/DB based on frequency range */ - ee_mode = AR5K_EEPROM_MODE_11A; - obdb = channel->center_freq >= 5725 ? 3 : - (channel->center_freq >= 5500 ? 2 : - (channel->center_freq >= 5260 ? 1 : - (channel->center_freq > 4000 ? 0 : -1))); - - if (obdb < 0) - return -EINVAL; - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], - AR5K_RF_OB_5GHZ, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], - AR5K_RF_DB_5GHZ, true); - } - - g_step = &go->go_step[ah->ah_gain.g_step_idx]; - - /* Bank Modifications (chip-specific) */ - if (ah->ah_radio == AR5K_RF5111) { - - /* Set gain_F settings according to current step */ - if (channel->hw_value & CHANNEL_OFDM) { - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, - AR5K_PHY_FRAME_CTL_TX_CLIP, - g_step->gos_param[0]); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], - AR5K_RF_PWD_90, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], - AR5K_RF_PWD_84, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], - AR5K_RF_RFGAIN_SEL, true); - - /* We programmed gain_F parameters, switch back - * to active state */ - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - - } - - /* Bank 6/7 setup */ - - ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode], - AR5K_RF_PWD_XPD, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode], - AR5K_RF_XPD_GAIN, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], - AR5K_RF_GAIN_I, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], - AR5K_RF_PLO_SEL, true); - - /* TODO: Half/quarter channel support */ - } - - if (ah->ah_radio == AR5K_RF5112) { - - /* Set gain_F settings according to current step */ - if (channel->hw_value & CHANNEL_OFDM) { - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0], - AR5K_RF_MIXGAIN_OVR, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], - AR5K_RF_PWD_138, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], - AR5K_RF_PWD_137, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], - AR5K_RF_PWD_136, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4], - AR5K_RF_PWD_132, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5], - AR5K_RF_PWD_131, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6], - AR5K_RF_PWD_130, true); - - /* We programmed gain_F parameters, switch back - * to active state */ - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - } - - /* Bank 6/7 setup */ - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], - AR5K_RF_XPD_SEL, true); - - if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { - /* Rev. 1 supports only one xpd */ - ath5k_hw_rfb_op(ah, rf_regs, - ee->ee_x_gain[ee_mode], - AR5K_RF_XPD_GAIN, true); - - } else { - /* TODO: Set high and low gain bits */ - ath5k_hw_rfb_op(ah, rf_regs, - ee->ee_x_gain[ee_mode], - AR5K_RF_PD_GAIN_LO, true); - ath5k_hw_rfb_op(ah, rf_regs, - ee->ee_x_gain[ee_mode], - AR5K_RF_PD_GAIN_HI, true); - - /* Lower synth voltage on Rev 2 */ - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_HIGH_VC_CP, true); - - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_MID_VC_CP, true); - - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_LOW_VC_CP, true); - - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_PUSH_UP, true); - - /* Decrease power consumption on 5213+ BaseBand */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_PAD2GND, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_XB2_LVL, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_XB5_LVL, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_PWD_167, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_PWD_166, true); - } - } - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], - AR5K_RF_GAIN_I, true); - - /* TODO: Half/quarter channel support */ - - } - - if (ah->ah_radio == AR5K_RF5413 && - channel->hw_value & CHANNEL_2GHZ) { - - ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE, - true); - - /* Set optimum value for early revisions (on pci-e chips) */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5424 && - ah->ah_mac_srev < AR5K_SREV_AR5413) - ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3), - AR5K_RF_PWD_ICLOBUF_2G, true); - - } - - /* Write RF banks on hw */ - for (i = 0; i < ah->ah_rf_banks_size; i++) { - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register); - } - - return 0; -} - - -/**************************\ - PHY/RF channel functions -\**************************/ - -/* - * Check if a channel is supported - */ -bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) -{ - /* Check if the channel is in our supported range */ - if (flags & CHANNEL_2GHZ) { - if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) - return true; - } else if (flags & CHANNEL_5GHZ) - if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) - return true; - - return false; -} - -/* - * Convertion needed for RF5110 - */ -static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) -{ - u32 athchan; - - /* - * Convert IEEE channel/MHz to an internal channel value used - * by the AR5210 chipset. This has not been verified with - * newer chipsets like the AR5212A who have a completely - * different RF/PHY part. - */ - athchan = (ath5k_hw_bitswap( - (ieee80211_frequency_to_channel( - channel->center_freq) - 24) / 2, 5) - << 1) | (1 << 6) | 0x1; - return athchan; -} - -/* - * Set channel on RF5110 - */ -static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 data; - - /* - * Set the channel and wait - */ - data = ath5k_hw_rf5110_chan2athchan(channel); - ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); - mdelay(1); - - return 0; -} - -/* - * Convertion needed for 5111 - */ -static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, - struct ath5k_athchan_2ghz *athchan) -{ - int channel; - - /* Cast this value to catch negative channel numbers (>= -19) */ - channel = (int)ieee; - - /* - * Map 2GHz IEEE channel to 5GHz Atheros channel - */ - if (channel <= 13) { - athchan->a2_athchan = 115 + channel; - athchan->a2_flags = 0x46; - } else if (channel == 14) { - athchan->a2_athchan = 124; - athchan->a2_flags = 0x44; - } else if (channel >= 15 && channel <= 26) { - athchan->a2_athchan = ((channel - 14) * 4) + 132; - athchan->a2_flags = 0x46; - } else - return -EINVAL; - - return 0; -} - -/* - * Set channel on 5111 - */ -static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - struct ath5k_athchan_2ghz ath5k_channel_2ghz; - unsigned int ath5k_channel = - ieee80211_frequency_to_channel(channel->center_freq); - u32 data0, data1, clock; - int ret; - - /* - * Set the channel on the RF5111 radio - */ - data0 = data1 = 0; - - if (channel->hw_value & CHANNEL_2GHZ) { - /* Map 2GHz channel to 5GHz Atheros channel ID */ - ret = ath5k_hw_rf5111_chan2athchan( - ieee80211_frequency_to_channel(channel->center_freq), - &ath5k_channel_2ghz); - if (ret) - return ret; - - ath5k_channel = ath5k_channel_2ghz.a2_athchan; - data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff) - << 5) | (1 << 4); - } - - if (ath5k_channel < 145 || !(ath5k_channel & 1)) { - clock = 1; - data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) | - (clock << 1) | (1 << 10) | 1; - } else { - clock = 0; - data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff) - << 2) | (clock << 1) | (1 << 10) | 1; - } - - ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8), - AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00), - AR5K_RF_BUFFER_CONTROL_3); - - return 0; -} - -/* - * Set channel on 5112 and newer - */ -static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 data, data0, data1, data2; - u16 c; - - data = data0 = data1 = data2 = 0; - c = channel->center_freq; - - if (c < 4800) { - if (!((c - 2224) % 5)) { - data0 = ((2 * (c - 704)) - 3040) / 10; - data1 = 1; - } else if (!((c - 2192) % 5)) { - data0 = ((2 * (c - 672)) - 3040) / 10; - data1 = 0; - } else - return -EINVAL; - - data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); - } else if ((c - (c % 5)) != 2 || c > 5435) { - if (!(c % 20) && c >= 5120) { - data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); - data2 = ath5k_hw_bitswap(3, 2); - } else if (!(c % 10)) { - data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); - data2 = ath5k_hw_bitswap(2, 2); - } else if (!(c % 5)) { - data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); - data2 = ath5k_hw_bitswap(1, 2); - } else - return -EINVAL; - } else { - data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); - data2 = ath5k_hw_bitswap(0, 2); - } - - data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; - - ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); - - return 0; -} - -/* - * Set the channel on the RF2425 - */ -static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 data, data0, data2; - u16 c; - - data = data0 = data2 = 0; - c = channel->center_freq; - - if (c < 4800) { - data0 = ath5k_hw_bitswap((c - 2272), 8); - data2 = 0; - /* ? 5GHz ? */ - } else if ((c - (c % 5)) != 2 || c > 5435) { - if (!(c % 20) && c < 5120) - data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); - else if (!(c % 10)) - data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); - else if (!(c % 5)) - data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); - else - return -EINVAL; - data2 = ath5k_hw_bitswap(1, 2); - } else { - data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); - data2 = ath5k_hw_bitswap(0, 2); - } - - data = (data0 << 4) | data2 << 2 | 0x1001; - - ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); - - return 0; -} - -/* - * Set a channel on the radio chip - */ -int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) -{ - int ret; - /* - * Check bounds supported by the PHY (we don't care about regultory - * restrictions at this point). Note: hw_value already has the band - * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok() - * of the band by that */ - if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) { - ATH5K_ERR(ah->ah_sc, - "channel frequency (%u MHz) out of supported " - "band range\n", - channel->center_freq); - return -EINVAL; - } - - /* - * Set the channel and wait - */ - switch (ah->ah_radio) { - case AR5K_RF5110: - ret = ath5k_hw_rf5110_channel(ah, channel); - break; - case AR5K_RF5111: - ret = ath5k_hw_rf5111_channel(ah, channel); - break; - case AR5K_RF2425: - ret = ath5k_hw_rf2425_channel(ah, channel); - break; - default: - ret = ath5k_hw_rf5112_channel(ah, channel); - break; - } - - if (ret) - return ret; - - /* Set JAPAN setting for channel 14 */ - if (channel->center_freq == 2484) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, - AR5K_PHY_CCKTXCTL_JAPAN); - } else { - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, - AR5K_PHY_CCKTXCTL_WORLD); - } - - ah->ah_current_channel.center_freq = channel->center_freq; - ah->ah_current_channel.hw_value = channel->hw_value; - ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; - - return 0; -} - -/*****************\ - PHY calibration -\*****************/ - -/** - * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration - * - * @ah: struct ath5k_hw pointer we are operating on - * @freq: the channel frequency, just used for error logging - * - * This function performs a noise floor calibration of the PHY and waits for - * it to complete. Then the noise floor value is compared to some maximum - * noise floor we consider valid. - * - * Note that this is different from what the madwifi HAL does: it reads the - * noise floor and afterwards initiates the calibration. Since the noise floor - * calibration can take some time to finish, depending on the current channel - * use, that avoids the occasional timeout warnings we are seeing now. - * - * See the following link for an Atheros patent on noise floor calibration: - * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ - * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 - * - * XXX: Since during noise floor calibration antennas are detached according to - * the patent, we should stop tx queues here. - */ -int -ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) -{ - int ret; - unsigned int i; - s32 noise_floor; - - /* - * Enable noise floor calibration - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_NF); - - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_NF, 0, false); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "noise floor calibration timeout (%uMHz)\n", freq); - return -EAGAIN; - } - - /* Wait until the noise floor is calibrated and read the value */ - for (i = 20; i > 0; i--) { - mdelay(1); - noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); - noise_floor = AR5K_PHY_NF_RVAL(noise_floor); - if (noise_floor & AR5K_PHY_NF_ACTIVE) { - noise_floor = AR5K_PHY_NF_AVAL(noise_floor); - - if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) - break; - } - } - - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, - "noise floor %d\n", noise_floor); - - if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { - ATH5K_ERR(ah->ah_sc, - "noise floor calibration failed (%uMHz)\n", freq); - return -EAGAIN; - } - - ah->ah_noise_floor = noise_floor; - - return 0; -} - -/* - * Perform a PHY calibration on RF5110 - * -Fix BPSK/QAM Constellation (I/Q correction) - * -Calculate Noise Floor - */ -static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 phy_sig, phy_agc, phy_sat, beacon; - int ret; - - /* - * Disable beacons and RX/TX queues, wait - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); - beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); - ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); - - mdelay(2); - - /* - * Set the channel (with AGC turned off) - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - udelay(10); - ret = ath5k_hw_channel(ah, channel); - - /* - * Activate PHY and wait - */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - mdelay(1); - - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - - if (ret) - return ret; - - /* - * Calibrate the radio chip - */ - - /* Remember normal state */ - phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG); - phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE); - phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT); - - /* Update radio registers */ - ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) | - AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG); - - ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI | - AR5K_PHY_AGCCOARSE_LO)) | - AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) | - AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE); - - ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT | - AR5K_PHY_ADCSAT_THR)) | - AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) | - AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT); - - udelay(20); - - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - udelay(10); - ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - - mdelay(1); - - /* - * Enable calibration and wait until completion - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL); - - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false); - - /* Reset to normal state */ - ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG); - ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE); - ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT); - - if (ret) { - ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", - channel->center_freq); - return ret; - } - - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - - /* - * Re-enable RX/TX and beacons - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); - ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); - - return 0; -} - -/* - * Perform a PHY calibration on RF5111/5112 and newer chips - */ -static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 i_pwr, q_pwr; - s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; - int i; - ATH5K_TRACE(ah->ah_sc); - - if (!ah->ah_calibration || - ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) - goto done; - - /* Calibration has finished, get the results and re-run */ - for (i = 0; i <= 10; i++) { - iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); - i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); - q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); - } - - i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; - q_coffd = q_pwr >> 7; - - /* No correction */ - if (i_coffd == 0 || q_coffd == 0) - goto done; - - i_coff = ((-iq_corr) / i_coffd) & 0x3f; - - /* Boundary check */ - if (i_coff > 31) - i_coff = 31; - if (i_coff < -32) - i_coff = -32; - - q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; - - /* Boundary check */ - if (q_coff > 15) - q_coff = 15; - if (q_coff < -16) - q_coff = -16; - - /* Commit new I/Q value */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | - ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); - - /* Re-enable calibration -if we don't we'll commit - * the same values again and again */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); - -done: - - /* TODO: Separate noise floor calibration from I/Q calibration - * since noise floor calibration interrupts rx path while I/Q - * calibration doesn't. We don't need to run noise floor calibration - * as often as I/Q calibration.*/ - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - - /* Initiate a gain_F calibration */ - ath5k_hw_request_rfgain_probe(ah); - - return 0; -} - -/* - * Perform a PHY calibration - */ -int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - int ret; - - if (ah->ah_radio == AR5K_RF5110) - ret = ath5k_hw_rf5110_calibrate(ah, channel); - else - ret = ath5k_hw_rf511x_calibrate(ah, channel); - - return ret; -} - -int ath5k_hw_phy_disable(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - - return 0; -} - -/********************\ - Misc PHY functions -\********************/ - -/* - * Get the PHY Chip revision - */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) -{ - unsigned int i; - u32 srev; - u16 ret; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Set the radio chip access register - */ - switch (chan) { - case CHANNEL_2GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); - break; - case CHANNEL_5GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - break; - default: - return 0; - } - - mdelay(2); - - /* ...wait until PHY is ready and read the selected radio revision */ - ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); - - for (i = 0; i < 8; i++) - ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); - - if (ah->ah_version == AR5K_AR5210) { - srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; - ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; - } else { - srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; - ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | - ((srev & 0x0f) << 4), 8); - } - - /* Reset to the 5GHz mode */ - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - - return ret; -} - -void /*TODO:Boundary check*/ -ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) -{ - ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); -} - -unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ - if (ah->ah_version != AR5K_AR5210) - return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); - - return false; /*XXX: What do we return for 5210 ?*/ -} - - -/****************\ -* TX power setup * -\****************/ - -/* - * Helper functions - */ - -/* - * Do linear interpolation between two given (x, y) points - */ -static s16 -ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, - s16 y_left, s16 y_right) -{ - s16 ratio, result; - - /* Avoid divide by zero and skip interpolation - * if we have the same point */ - if ((x_left == x_right) || (y_left == y_right)) - return y_left; - - /* - * Since we use ints and not fps, we need to scale up in - * order to get a sane ratio value (or else we 'll eg. get - * always 1 instead of 1.25, 1.75 etc). We scale up by 100 - * to have some accuracy both for 0.5 and 0.25 steps. - */ - ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left)); - - /* Now scale down to be in range */ - result = y_left + (ratio * (target - x_left) / 100); - - return result; -} - -/* - * Find vertical boundary (min pwr) for the linear PCDAC curve. - * - * Since we have the top of the curve and we draw the line below - * until we reach 1 (1 pcdac step) we need to know which point - * (x value) that is so that we don't go below y axis and have negative - * pcdac values when creating the curve, or fill the table with zeroes. - */ -static s16 -ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, - const s16 *pwrL, const s16 *pwrR) -{ - s8 tmp; - s16 min_pwrL, min_pwrR; - s16 pwr_i = pwrL[0]; - - do { - pwr_i--; - tmp = (s8) ath5k_get_interpolated_value(pwr_i, - pwrL[0], pwrL[1], - stepL[0], stepL[1]); - - } while (tmp > 1); - - min_pwrL = pwr_i; - - pwr_i = pwrR[0]; - do { - pwr_i--; - tmp = (s8) ath5k_get_interpolated_value(pwr_i, - pwrR[0], pwrR[1], - stepR[0], stepR[1]); - - } while (tmp > 1); - - min_pwrR = pwr_i; - - /* Keep the right boundary so that it works for both curves */ - return max(min_pwrL, min_pwrR); -} - -/* - * Interpolate (pwr,vpd) points to create a Power to PDADC or a - * Power to PCDAC curve. - * - * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC - * steps (offsets) on y axis. Power can go up to 31.5dB and max - * PCDAC/PDADC step for each curve is 64 but we can write more than - * one curves on hw so we can go up to 128 (which is the max step we - * can write on the final table). - * - * We write y values (PCDAC/PDADC steps) on hw. - */ -static void -ath5k_create_power_curve(s16 pmin, s16 pmax, - const s16 *pwr, const u8 *vpd, - u8 num_points, - u8 *vpd_table, u8 type) -{ - u8 idx[2] = { 0, 1 }; - s16 pwr_i = 2*pmin; - int i; - - if (num_points < 2) - return; - - /* We want the whole line, so adjust boundaries - * to cover the entire power range. Note that - * power values are already 0.25dB so no need - * to multiply pwr_i by 2 */ - if (type == AR5K_PWRTABLE_LINEAR_PCDAC) { - pwr_i = pmin; - pmin = 0; - pmax = 63; - } - - /* Find surrounding turning points (TPs) - * and interpolate between them */ - for (i = 0; (i <= (u16) (pmax - pmin)) && - (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { - - /* We passed the right TP, move to the next set of TPs - * if we pass the last TP, extrapolate above using the last - * two TPs for ratio */ - if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) { - idx[0]++; - idx[1]++; - } - - vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i, - pwr[idx[0]], pwr[idx[1]], - vpd[idx[0]], vpd[idx[1]]); - - /* Increase by 0.5dB - * (0.25 dB units) */ - pwr_i += 2; - } -} - -/* - * Get the surrounding per-channel power calibration piers - * for a given frequency so that we can interpolate between - * them and come up with an apropriate dataset for our current - * channel. - */ -static void -ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - struct ath5k_chan_pcal_info **pcinfo_l, - struct ath5k_chan_pcal_info **pcinfo_r) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcinfo; - u8 idx_l, idx_r; - u8 mode, max, i; - u32 target = channel->center_freq; - - idx_l = 0; - idx_r = 0; - - if (!(channel->hw_value & CHANNEL_OFDM)) { - pcinfo = ee->ee_pwr_cal_b; - mode = AR5K_EEPROM_MODE_11B; - } else if (channel->hw_value & CHANNEL_2GHZ) { - pcinfo = ee->ee_pwr_cal_g; - mode = AR5K_EEPROM_MODE_11G; - } else { - pcinfo = ee->ee_pwr_cal_a; - mode = AR5K_EEPROM_MODE_11A; - } - max = ee->ee_n_piers[mode] - 1; - - /* Frequency is below our calibrated - * range. Use the lowest power curve - * we have */ - if (target < pcinfo[0].freq) { - idx_l = idx_r = 0; - goto done; - } - - /* Frequency is above our calibrated - * range. Use the highest power curve - * we have */ - if (target > pcinfo[max].freq) { - idx_l = idx_r = max; - goto done; - } - - /* Frequency is inside our calibrated - * channel range. Pick the surrounding - * calibration piers so that we can - * interpolate */ - for (i = 0; i <= max; i++) { - - /* Frequency matches one of our calibration - * piers, no need to interpolate, just use - * that calibration pier */ - if (pcinfo[i].freq == target) { - idx_l = idx_r = i; - goto done; - } - - /* We found a calibration pier that's above - * frequency, use this pier and the previous - * one to interpolate */ - if (target < pcinfo[i].freq) { - idx_r = i; - idx_l = idx_r - 1; - goto done; - } - } - -done: - *pcinfo_l = &pcinfo[idx_l]; - *pcinfo_r = &pcinfo[idx_r]; - - return; -} - -/* - * Get the surrounding per-rate power calibration data - * for a given frequency and interpolate between power - * values to set max target power supported by hw for - * each rate. - */ -static void -ath5k_get_rate_pcal_data(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - struct ath5k_rate_pcal_info *rates) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_rate_pcal_info *rpinfo; - u8 idx_l, idx_r; - u8 mode, max, i; - u32 target = channel->center_freq; - - idx_l = 0; - idx_r = 0; - - if (!(channel->hw_value & CHANNEL_OFDM)) { - rpinfo = ee->ee_rate_tpwr_b; - mode = AR5K_EEPROM_MODE_11B; - } else if (channel->hw_value & CHANNEL_2GHZ) { - rpinfo = ee->ee_rate_tpwr_g; - mode = AR5K_EEPROM_MODE_11G; - } else { - rpinfo = ee->ee_rate_tpwr_a; - mode = AR5K_EEPROM_MODE_11A; - } - max = ee->ee_rate_target_pwr_num[mode] - 1; - - /* Get the surrounding calibration - * piers - same as above */ - if (target < rpinfo[0].freq) { - idx_l = idx_r = 0; - goto done; - } - - if (target > rpinfo[max].freq) { - idx_l = idx_r = max; - goto done; - } - - for (i = 0; i <= max; i++) { - - if (rpinfo[i].freq == target) { - idx_l = idx_r = i; - goto done; - } - - if (target < rpinfo[i].freq) { - idx_r = i; - idx_l = idx_r - 1; - goto done; - } - } - -done: - /* Now interpolate power value, based on the frequency */ - rates->freq = target; - - rates->target_power_6to24 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_6to24, - rpinfo[idx_r].target_power_6to24); - - rates->target_power_36 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_36, - rpinfo[idx_r].target_power_36); - - rates->target_power_48 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_48, - rpinfo[idx_r].target_power_48); - - rates->target_power_54 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_54, - rpinfo[idx_r].target_power_54); -} - -/* - * Get the max edge power for this channel if - * we have such data from EEPROM's Conformance Test - * Limits (CTL), and limit max power if needed. - * - * FIXME: Only works for world regulatory domains - */ -static void -ath5k_get_max_ctl_power(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_edge_power *rep = ee->ee_ctl_pwr; - u8 *ctl_val = ee->ee_ctl; - s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4; - s16 edge_pwr = 0; - u8 rep_idx; - u8 i, ctl_mode; - u8 ctl_idx = 0xFF; - u32 target = channel->center_freq; - - /* Find out a CTL for our mode that's not mapped - * on a specific reg domain. - * - * TODO: Map our current reg domain to one of the 3 available - * reg domain ids so that we can support more CTLs. */ - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN; - break; - case CHANNEL_G: - ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN; - break; - case CHANNEL_B: - ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN; - break; - case CHANNEL_T: - ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN; - break; - case CHANNEL_TG: - ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN; - break; - case CHANNEL_XR: - /* Fall through */ - default: - return; - } - - for (i = 0; i < ee->ee_ctls; i++) { - if (ctl_val[i] == ctl_mode) { - ctl_idx = i; - break; - } - } - - /* If we have a CTL dataset available grab it and find the - * edge power for our frequency */ - if (ctl_idx == 0xFF) - return; - - /* Edge powers are sorted by frequency from lower - * to higher. Each CTL corresponds to 8 edge power - * measurements. */ - rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES; - - /* Don't do boundaries check because we - * might have more that one bands defined - * for this mode */ - - /* Get the edge power that's closer to our - * frequency */ - for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) { - rep_idx += i; - if (target <= rep[rep_idx].freq) - edge_pwr = (s16) rep[rep_idx].edge; - } - - if (edge_pwr) - ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr); -} - - -/* - * Power to PCDAC table functions - */ - -/* - * Fill Power to PCDAC table on RF5111 - * - * No further processing is needed for RF5111, the only thing we have to - * do is fill the values below and above calibration range since eeprom data - * may not cover the entire PCDAC table. - */ -static void -ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min, - s16 *table_max) -{ - u8 *pcdac_out = ah->ah_txpower.txp_pd_table; - u8 *pcdac_tmp = ah->ah_txpower.tmpL[0]; - u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i; - s16 min_pwr, max_pwr; - - /* Get table boundaries */ - min_pwr = table_min[0]; - pcdac_0 = pcdac_tmp[0]; - - max_pwr = table_max[0]; - pcdac_n = pcdac_tmp[table_max[0] - table_min[0]]; - - /* Extrapolate below minimum using pcdac_0 */ - pcdac_i = 0; - for (i = 0; i < min_pwr; i++) - pcdac_out[pcdac_i++] = pcdac_0; - - /* Copy values from pcdac_tmp */ - pwr_idx = min_pwr; - for (i = 0 ; pwr_idx <= max_pwr && - pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) { - pcdac_out[pcdac_i++] = pcdac_tmp[i]; - pwr_idx++; - } - - /* Extrapolate above maximum */ - while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE) - pcdac_out[pcdac_i++] = pcdac_n; - -} - -/* - * Combine available XPD Curves and fill Linear Power to PCDAC table - * on RF5112 - * - * RFX112 can have up to 2 curves (one for low txpower range and one for - * higher txpower range). We need to put them both on pcdac_out and place - * them in the correct location. In case we only have one curve available - * just fit it on pcdac_out (it's supposed to cover the entire range of - * available pwr levels since it's always the higher power curve). Extrapolate - * below and above final table if needed. - */ -static void -ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, - s16 *table_max, u8 pdcurves) -{ - u8 *pcdac_out = ah->ah_txpower.txp_pd_table; - u8 *pcdac_low_pwr; - u8 *pcdac_high_pwr; - u8 *pcdac_tmp; - u8 pwr; - s16 max_pwr_idx; - s16 min_pwr_idx; - s16 mid_pwr_idx = 0; - /* Edge flag turs on the 7nth bit on the PCDAC - * to delcare the higher power curve (force values - * to be greater than 64). If we only have one curve - * we don't need to set this, if we have 2 curves and - * fill the table backwards this can also be used to - * switch from higher power curve to lower power curve */ - u8 edge_flag; - int i; - - /* When we have only one curve available - * that's the higher power curve. If we have - * two curves the first is the high power curve - * and the next is the low power curve. */ - if (pdcurves > 1) { - pcdac_low_pwr = ah->ah_txpower.tmpL[1]; - pcdac_high_pwr = ah->ah_txpower.tmpL[0]; - mid_pwr_idx = table_max[1] - table_min[1] - 1; - max_pwr_idx = (table_max[0] - table_min[0]) / 2; - - /* If table size goes beyond 31.5dB, keep the - * upper 31.5dB range when setting tx power. - * Note: 126 = 31.5 dB in quarter dB steps */ - if (table_max[0] - table_min[1] > 126) - min_pwr_idx = table_max[0] - 126; - else - min_pwr_idx = table_min[1]; - - /* Since we fill table backwards - * start from high power curve */ - pcdac_tmp = pcdac_high_pwr; - - edge_flag = 0x40; -#if 0 - /* If both min and max power limits are in lower - * power curve's range, only use the low power curve. - * TODO: min/max levels are related to target - * power values requested from driver/user - * XXX: Is this really needed ? */ - if (min_pwr < table_max[1] && - max_pwr < table_max[1]) { - edge_flag = 0; - pcdac_tmp = pcdac_low_pwr; - max_pwr_idx = (table_max[1] - table_min[1])/2; - } -#endif - } else { - pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ - pcdac_high_pwr = ah->ah_txpower.tmpL[0]; - min_pwr_idx = table_min[0]; - max_pwr_idx = (table_max[0] - table_min[0]) / 2; - pcdac_tmp = pcdac_high_pwr; - edge_flag = 0; - } - - /* This is used when setting tx power*/ - ah->ah_txpower.txp_min_idx = min_pwr_idx/2; - - /* Fill Power to PCDAC table backwards */ - pwr = max_pwr_idx; - for (i = 63; i >= 0; i--) { - /* Entering lower power range, reset - * edge flag and set pcdac_tmp to lower - * power curve.*/ - if (edge_flag == 0x40 && - (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) { - edge_flag = 0x00; - pcdac_tmp = pcdac_low_pwr; - pwr = mid_pwr_idx/2; - } - - /* Don't go below 1, extrapolate below if we have - * already swithced to the lower power curve -or - * we only have one curve and edge_flag is zero - * anyway */ - if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) { - while (i >= 0) { - pcdac_out[i] = pcdac_out[i + 1]; - i--; - } - break; - } - - pcdac_out[i] = pcdac_tmp[pwr] | edge_flag; - - /* Extrapolate above if pcdac is greater than - * 126 -this can happen because we OR pcdac_out - * value with edge_flag on high power curve */ - if (pcdac_out[i] > 126) - pcdac_out[i] = 126; - - /* Decrease by a 0.5dB step */ - pwr--; - } -} - -/* Write PCDAC values on hw */ -static void -ath5k_setup_pcdac_table(struct ath5k_hw *ah) -{ - u8 *pcdac_out = ah->ah_txpower.txp_pd_table; - int i; - - /* - * Write TX power values - */ - for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { - ath5k_hw_reg_write(ah, - (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) | - (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16), - AR5K_PHY_PCDAC_TXPOWER(i)); - } -} - - -/* - * Power to PDADC table functions - */ - -/* - * Set the gain boundaries and create final Power to PDADC table - * - * We can have up to 4 pd curves, we need to do a simmilar process - * as we do for RF5112. This time we don't have an edge_flag but we - * set the gain boundaries on a separate register. - */ -static void -ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, - s16 *pwr_min, s16 *pwr_max, u8 pdcurves) -{ - u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS]; - u8 *pdadc_out = ah->ah_txpower.txp_pd_table; - u8 *pdadc_tmp; - s16 pdadc_0; - u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size; - u8 pd_gain_overlap; - - /* Note: Register value is initialized on initvals - * there is no feedback from hw. - * XXX: What about pd_gain_overlap from EEPROM ? */ - pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) & - AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP; - - /* Create final PDADC table */ - for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) { - pdadc_tmp = ah->ah_txpower.tmpL[pdg]; - - if (pdg == pdcurves - 1) - /* 2 dB boundary stretch for last - * (higher power) curve */ - gain_boundaries[pdg] = pwr_max[pdg] + 4; - else - /* Set gain boundary in the middle - * between this curve and the next one */ - gain_boundaries[pdg] = - (pwr_max[pdg] + pwr_min[pdg + 1]) / 2; - - /* Sanity check in case our 2 db stretch got out of - * range. */ - if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER) - gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER; - - /* For the first curve (lower power) - * start from 0 dB */ - if (pdg == 0) - pdadc_0 = 0; - else - /* For the other curves use the gain overlap */ - pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) - - pd_gain_overlap; - - /* Force each power step to be at least 0.5 dB */ - if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1) - pwr_step = pdadc_tmp[1] - pdadc_tmp[0]; - else - pwr_step = 1; - - /* If pdadc_0 is negative, we need to extrapolate - * below this pdgain by a number of pwr_steps */ - while ((pdadc_0 < 0) && (pdadc_i < 128)) { - s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step; - pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp; - pdadc_0++; - } - - /* Set last pwr level, using gain boundaries */ - pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg]; - /* Limit it to be inside pwr range */ - table_size = pwr_max[pdg] - pwr_min[pdg]; - max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; - - /* Fill pdadc_out table */ - while (pdadc_0 < max_idx) - pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; - - /* Need to extrapolate above this pdgain? */ - if (pdadc_n <= max_idx) - continue; - - /* Force each power step to be at least 0.5 dB */ - if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1) - pwr_step = pdadc_tmp[table_size - 1] - - pdadc_tmp[table_size - 2]; - else - pwr_step = 1; - - /* Extrapolate above */ - while ((pdadc_0 < (s16) pdadc_n) && - (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) { - s16 tmp = pdadc_tmp[table_size - 1] + - (pdadc_0 - max_idx) * pwr_step; - pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp; - pdadc_0++; - } - } - - while (pdg < AR5K_EEPROM_N_PD_GAINS) { - gain_boundaries[pdg] = gain_boundaries[pdg - 1]; - pdg++; - } - - while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) { - pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1]; - pdadc_i++; - } - - /* Set gain boundaries */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(pd_gain_overlap, - AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) | - AR5K_REG_SM(gain_boundaries[0], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) | - AR5K_REG_SM(gain_boundaries[1], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) | - AR5K_REG_SM(gain_boundaries[2], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) | - AR5K_REG_SM(gain_boundaries[3], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4), - AR5K_PHY_TPC_RG5); - - /* Used for setting rate power table */ - ah->ah_txpower.txp_min_idx = pwr_min[0]; - -} - -/* Write PDADC values on hw */ -static void -ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, - u8 pdcurves, u8 *pdg_to_idx) -{ - u8 *pdadc_out = ah->ah_txpower.txp_pd_table; - u32 reg; - u8 i; - - /* Select the right pdgain curves */ - - /* Clear current settings */ - reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1); - reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 | - AR5K_PHY_TPC_RG1_PDGAIN_2 | - AR5K_PHY_TPC_RG1_PDGAIN_3 | - AR5K_PHY_TPC_RG1_NUM_PD_GAIN); - - /* - * Use pd_gains curve from eeprom - * - * This overrides the default setting from initvals - * in case some vendors (e.g. Zcomax) don't use the default - * curves. If we don't honor their settings we 'll get a - * 5dB (1 * gain overlap ?) drop. - */ - reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN); - - switch (pdcurves) { - case 3: - reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3); - /* Fall through */ - case 2: - reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2); - /* Fall through */ - case 1: - reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1); - break; - } - ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1); - - /* - * Write TX power values - */ - for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { - ath5k_hw_reg_write(ah, - ((pdadc_out[4*i + 0] & 0xff) << 0) | - ((pdadc_out[4*i + 1] & 0xff) << 8) | - ((pdadc_out[4*i + 2] & 0xff) << 16) | - ((pdadc_out[4*i + 3] & 0xff) << 24), - AR5K_PHY_PDADC_TXPOWER(i)); - } -} - - -/* - * Common code for PCDAC/PDADC tables - */ - -/* - * This is the main function that uses all of the above - * to set PCDAC/PDADC table on hw for the current channel. - * This table is used for tx power calibration on the basband, - * without it we get weird tx power levels and in some cases - * distorted spectral mask - */ -static int -ath5k_setup_channel_powertable(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - u8 ee_mode, u8 type) -{ - struct ath5k_pdgain_info *pdg_L, *pdg_R; - struct ath5k_chan_pcal_info *pcinfo_L; - struct ath5k_chan_pcal_info *pcinfo_R; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode]; - s16 table_min[AR5K_EEPROM_N_PD_GAINS]; - s16 table_max[AR5K_EEPROM_N_PD_GAINS]; - u8 *tmpL; - u8 *tmpR; - u32 target = channel->center_freq; - int pdg, i; - - /* Get surounding freq piers for this channel */ - ath5k_get_chan_pcal_surrounding_piers(ah, channel, - &pcinfo_L, - &pcinfo_R); - - /* Loop over pd gain curves on - * surounding freq piers by index */ - for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { - - /* Fill curves in reverse order - * from lower power (max gain) - * to higher power. Use curve -> idx - * backmaping we did on eeprom init */ - u8 idx = pdg_curve_to_idx[pdg]; - - /* Grab the needed curves by index */ - pdg_L = &pcinfo_L->pd_curves[idx]; - pdg_R = &pcinfo_R->pd_curves[idx]; - - /* Initialize the temp tables */ - tmpL = ah->ah_txpower.tmpL[pdg]; - tmpR = ah->ah_txpower.tmpR[pdg]; - - /* Set curve's x boundaries and create - * curves so that they cover the same - * range (if we don't do that one table - * will have values on some range and the - * other one won't have any so interpolation - * will fail) */ - table_min[pdg] = min(pdg_L->pd_pwr[0], - pdg_R->pd_pwr[0]) / 2; - - table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1], - pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2; - - /* Now create the curves on surrounding channels - * and interpolate if needed to get the final - * curve for this gain on this channel */ - switch (type) { - case AR5K_PWRTABLE_LINEAR_PCDAC: - /* Override min/max so that we don't loose - * accuracy (don't divide by 2) */ - table_min[pdg] = min(pdg_L->pd_pwr[0], - pdg_R->pd_pwr[0]); - - table_max[pdg] = - max(pdg_L->pd_pwr[pdg_L->pd_points - 1], - pdg_R->pd_pwr[pdg_R->pd_points - 1]); - - /* Override minimum so that we don't get - * out of bounds while extrapolating - * below. Don't do this when we have 2 - * curves and we are on the high power curve - * because table_min is ok in this case */ - if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) { - - table_min[pdg] = - ath5k_get_linear_pcdac_min(pdg_L->pd_step, - pdg_R->pd_step, - pdg_L->pd_pwr, - pdg_R->pd_pwr); - - /* Don't go too low because we will - * miss the upper part of the curve. - * Note: 126 = 31.5dB (max power supported) - * in 0.25dB units */ - if (table_max[pdg] - table_min[pdg] > 126) - table_min[pdg] = table_max[pdg] - 126; - } - - /* Fall through */ - case AR5K_PWRTABLE_PWR_TO_PCDAC: - case AR5K_PWRTABLE_PWR_TO_PDADC: - - ath5k_create_power_curve(table_min[pdg], - table_max[pdg], - pdg_L->pd_pwr, - pdg_L->pd_step, - pdg_L->pd_points, tmpL, type); - - /* We are in a calibration - * pier, no need to interpolate - * between freq piers */ - if (pcinfo_L == pcinfo_R) - continue; - - ath5k_create_power_curve(table_min[pdg], - table_max[pdg], - pdg_R->pd_pwr, - pdg_R->pd_step, - pdg_R->pd_points, tmpR, type); - break; - default: - return -EINVAL; - } - - /* Interpolate between curves - * of surounding freq piers to - * get the final curve for this - * pd gain. Re-use tmpL for interpolation - * output */ - for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) && - (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { - tmpL[i] = (u8) ath5k_get_interpolated_value(target, - (s16) pcinfo_L->freq, - (s16) pcinfo_R->freq, - (s16) tmpL[i], - (s16) tmpR[i]); - } - } - - /* Now we have a set of curves for this - * channel on tmpL (x range is table_max - table_min - * and y values are tmpL[pdg][]) sorted in the same - * order as EEPROM (because we've used the backmaping). - * So for RF5112 it's from higher power to lower power - * and for RF2413 it's from lower power to higher power. - * For RF5111 we only have one curve. */ - - /* Fill min and max power levels for this - * channel by interpolating the values on - * surounding channels to complete the dataset */ - ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, - (s16) pcinfo_L->freq, - (s16) pcinfo_R->freq, - pcinfo_L->min_pwr, pcinfo_R->min_pwr); - - ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target, - (s16) pcinfo_L->freq, - (s16) pcinfo_R->freq, - pcinfo_L->max_pwr, pcinfo_R->max_pwr); - - /* We are ready to go, fill PCDAC/PDADC - * table and write settings on hardware */ - switch (type) { - case AR5K_PWRTABLE_LINEAR_PCDAC: - /* For RF5112 we can have one or two curves - * and each curve covers a certain power lvl - * range so we need to do some more processing */ - ath5k_combine_linear_pcdac_curves(ah, table_min, table_max, - ee->ee_pd_gains[ee_mode]); - - /* Set txp.offset so that we can - * match max power value with max - * table index */ - ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); - - /* Write settings on hw */ - ath5k_setup_pcdac_table(ah); - break; - case AR5K_PWRTABLE_PWR_TO_PCDAC: - /* We are done for RF5111 since it has only - * one curve, just fit the curve on the table */ - ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max); - - /* No rate powertable adjustment for RF5111 */ - ah->ah_txpower.txp_min_idx = 0; - ah->ah_txpower.txp_offset = 0; - - /* Write settings on hw */ - ath5k_setup_pcdac_table(ah); - break; - case AR5K_PWRTABLE_PWR_TO_PDADC: - /* Set PDADC boundaries and fill - * final PDADC table */ - ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, - ee->ee_pd_gains[ee_mode]); - - /* Write settings on hw */ - ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); - - /* Set txp.offset, note that table_min - * can be negative */ - ah->ah_txpower.txp_offset = table_min[0]; - break; - default: - return -EINVAL; - } - - return 0; -} - - -/* - * Per-rate tx power setting - * - * This is the code that sets the desired tx power (below - * maximum) on hw for each rate (we also have TPC that sets - * power per packet). We do that by providing an index on the - * PCDAC/PDADC table we set up. - */ - -/* - * Set rate power table - * - * For now we only limit txpower based on maximum tx power - * supported by hw (what's inside rate_info). We need to limit - * this even more, based on regulatory domain etc. - * - * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps) - * and is indexed as follows: - * rates[0] - rates[7] -> OFDM rates - * rates[8] - rates[14] -> CCK rates - * rates[15] -> XR rates (they all have the same power) - */ -static void -ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, - struct ath5k_rate_pcal_info *rate_info, - u8 ee_mode) -{ - unsigned int i; - u16 *rates; - - /* max_pwr is power level we got from driver/user in 0.5dB - * units, switch to 0.25dB units so we can compare */ - max_pwr *= 2; - max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2; - - /* apply rate limits */ - rates = ah->ah_txpower.txp_rates_power_table; - - /* OFDM rates 6 to 24Mb/s */ - for (i = 0; i < 5; i++) - rates[i] = min(max_pwr, rate_info->target_power_6to24); - - /* Rest OFDM rates */ - rates[5] = min(rates[0], rate_info->target_power_36); - rates[6] = min(rates[0], rate_info->target_power_48); - rates[7] = min(rates[0], rate_info->target_power_54); - - /* CCK rates */ - /* 1L */ - rates[8] = min(rates[0], rate_info->target_power_6to24); - /* 2L */ - rates[9] = min(rates[0], rate_info->target_power_36); - /* 2S */ - rates[10] = min(rates[0], rate_info->target_power_36); - /* 5L */ - rates[11] = min(rates[0], rate_info->target_power_48); - /* 5S */ - rates[12] = min(rates[0], rate_info->target_power_48); - /* 11L */ - rates[13] = min(rates[0], rate_info->target_power_54); - /* 11S */ - rates[14] = min(rates[0], rate_info->target_power_54); - - /* XR rates */ - rates[15] = min(rates[0], rate_info->target_power_6to24); - - /* CCK rates have different peak to average ratio - * so we have to tweak their power so that gainf - * correction works ok. For this we use OFDM to - * CCK delta from eeprom */ - if ((ee_mode == AR5K_EEPROM_MODE_11G) && - (ah->ah_phy_revision < AR5K_SREV_PHY_5212A)) - for (i = 8; i <= 15; i++) - rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; - - ah->ah_txpower.txp_min_pwr = rates[7]; - ah->ah_txpower.txp_max_pwr = rates[0]; - ah->ah_txpower.txp_ofdm = rates[7]; -} - - -/* - * Set transmition power - */ -int -ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 ee_mode, u8 txpower) -{ - struct ath5k_rate_pcal_info rate_info; - u8 type; - int ret; - - ATH5K_TRACE(ah->ah_sc); - if (txpower > AR5K_TUNE_MAX_TXPOWER) { - ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); - return -EINVAL; - } - if (txpower == 0) - txpower = AR5K_TUNE_DEFAULT_TXPOWER; - - /* Reset TX power values */ - memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); - ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; - ah->ah_txpower.txp_min_pwr = 0; - ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; - - /* Initialize TX power table */ - switch (ah->ah_radio) { - case AR5K_RF5111: - type = AR5K_PWRTABLE_PWR_TO_PCDAC; - break; - case AR5K_RF5112: - type = AR5K_PWRTABLE_LINEAR_PCDAC; - break; - case AR5K_RF2413: - case AR5K_RF5413: - case AR5K_RF2316: - case AR5K_RF2317: - case AR5K_RF2425: - type = AR5K_PWRTABLE_PWR_TO_PDADC; - break; - default: - return -EINVAL; - } - - /* FIXME: Only on channel/mode change */ - ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); - if (ret) - return ret; - - /* Limit max power if we have a CTL available */ - ath5k_get_max_ctl_power(ah, channel); - - /* FIXME: Tx power limit for this regdomain - * XXX: Mac80211/CRDA will do that anyway ? */ - - /* FIXME: Antenna reduction stuff */ - - /* FIXME: Limit power on turbo modes */ - - /* FIXME: TPC scale reduction */ - - /* Get surounding channels for per-rate power table - * calibration */ - ath5k_get_rate_pcal_data(ah, channel, &rate_info); - - /* Setup rate power table */ - ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode); - - /* Write rate power table on hw */ - ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) | - AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) | - AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1); - - ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) | - AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) | - AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2); - - ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) | - AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) | - AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3); - - ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) | - AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) | - AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4); - - /* FIXME: TPC support */ - if (ah->ah_txpower.txp_tpc) { - ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | - AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); - - ath5k_hw_reg_write(ah, - AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) | - AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) | - AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP), - AR5K_TPC); - } else { - ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX | - AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); - } - - return 0; -} - -int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) -{ - /*Just a try M.F.*/ - struct ieee80211_channel *channel = &ah->ah_current_channel; - - ATH5K_TRACE(ah->ah_sc); - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, - "changing txpower to %d\n", txpower); - - return ath5k_hw_txpower(ah, channel, mode, txpower); -} - -#undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c deleted file mode 100644 index 5094c394a4b2..000000000000 --- a/drivers/net/wireless/ath5k/qcu.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/********************************************\ -Queue Control Unit, DFS Control Unit Functions -\********************************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Get properties for a transmit queue - */ -int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, - struct ath5k_txq_info *queue_info) -{ - ATH5K_TRACE(ah->ah_sc); - memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); - return 0; -} - -/* - * Set properties for a transmit queue - */ -int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, - const struct ath5k_txq_info *queue_info) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; - - memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); - - /*XXX: Is this supported on 5210 ?*/ - if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && - ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || - (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || - queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) - ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; - - return 0; -} - -/* - * Initialize a transmit queue - */ -int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, - struct ath5k_txq_info *queue_info) -{ - unsigned int queue; - int ret; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Get queue by type - */ - /*5210 only has 2 queues*/ - if (ah->ah_version == AR5K_AR5210) { - switch (queue_type) { - case AR5K_TX_QUEUE_DATA: - queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; - break; - default: - return -EINVAL; - } - } else { - switch (queue_type) { - case AR5K_TX_QUEUE_DATA: - for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; - ah->ah_txq[queue].tqi_type != - AR5K_TX_QUEUE_INACTIVE; queue++) { - - if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) - return -EINVAL; - } - break; - case AR5K_TX_QUEUE_UAPSD: - queue = AR5K_TX_QUEUE_ID_UAPSD; - break; - case AR5K_TX_QUEUE_BEACON: - queue = AR5K_TX_QUEUE_ID_BEACON; - break; - case AR5K_TX_QUEUE_CAB: - queue = AR5K_TX_QUEUE_ID_CAB; - break; - case AR5K_TX_QUEUE_XR_DATA: - if (ah->ah_version != AR5K_AR5212) - ATH5K_ERR(ah->ah_sc, - "XR data queues only supported in" - " 5212!\n"); - queue = AR5K_TX_QUEUE_ID_XR_DATA; - break; - default: - return -EINVAL; - } - } - - /* - * Setup internal queue structure - */ - memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); - ah->ah_txq[queue].tqi_type = queue_type; - - if (queue_info != NULL) { - queue_info->tqi_type = queue_type; - ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info); - if (ret) - return ret; - } - - /* - * We use ah_txq_status to hold a temp value for - * the Secondary interrupt mask registers on 5211+ - * check out ath5k_hw_reset_tx_queue - */ - AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); - - return queue; -} - -/* - * Get number of pending frames - * for a specific queue [5211+] - */ -u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) -{ - u32 pending; - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return false; - - /* XXX: How about AR5K_CFG_TXCNT ? */ - if (ah->ah_version == AR5K_AR5210) - return false; - - pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); - - /* It's possible to have no frames pending even if TXE - * is set. To indicate that q has not stopped return - * true */ - if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - return true; - - return pending; -} - -/* - * Set a transmit queue inactive - */ -void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) -{ - ATH5K_TRACE(ah->ah_sc); - if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) - return; - - /* This queue will be skipped in further operations */ - ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; - /*For SIMR setup*/ - AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); -} - -/* - * Set DFS properties for a transmit queue on DCU - */ -int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) -{ - u32 cw_min, cw_max, retry_lg, retry_sh; - struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - tq = &ah->ah_txq[queue]; - - if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) - return 0; - - if (ah->ah_version == AR5K_AR5210) { - /* Only handle data queues, others will be ignored */ - if (tq->tqi_type != AR5K_TX_QUEUE_DATA) - return 0; - - /* Set Slot time */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, - AR5K_SLOT_TIME); - /* Set ACK_CTS timeout */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : - AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); - /* Set Transmit Latency */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_TRANSMIT_LATENCY_TURBO : - AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); - - /* Set IFS0 */ - if (ah->ah_turbo) { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + - (ah->ah_aifs + tq->tqi_aifs) * - AR5K_INIT_SLOT_TIME_TURBO) << - AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, - AR5K_IFS0); - } else { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + - (ah->ah_aifs + tq->tqi_aifs) * - AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | - AR5K_INIT_SIFS, AR5K_IFS0); - } - - /* Set IFS1 */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_PROTO_TIME_CNTRL_TURBO : - AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); - /* Set AR5K_PHY_SETTLING */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x38 : - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x1C, - AR5K_PHY_SETTLING); - /* Set Frame Control Register */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | - AR5K_PHY_TURBO_SHORT | 0x2020) : - (AR5K_PHY_FRAME_CTL_INI | 0x1020), - AR5K_PHY_FRAME_CTL_5210); - } - - /* - * Calculate cwmin/max by channel mode - */ - cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; - cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; - ah->ah_aifs = AR5K_TUNE_AIFS; - /*XR is only supported on 5212*/ - if (IS_CHAN_XR(ah->ah_current_channel) && - ah->ah_version == AR5K_AR5212) { - cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; - cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; - ah->ah_aifs = AR5K_TUNE_AIFS_XR; - /*B mode is not supported on 5210*/ - } else if (IS_CHAN_B(ah->ah_current_channel) && - ah->ah_version != AR5K_AR5210) { - cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; - cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; - ah->ah_aifs = AR5K_TUNE_AIFS_11B; - } - - cw_min = 1; - while (cw_min < ah->ah_cw_min) - cw_min = (cw_min << 1) | 1; - - cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : - ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); - cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : - ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); - - /* - * Calculate and set retry limits - */ - if (ah->ah_software_retry) { - /* XXX Need to test this */ - retry_lg = ah->ah_limit_tx_retries; - retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? - AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; - } else { - retry_lg = AR5K_INIT_LG_RETRY; - retry_sh = AR5K_INIT_SH_RETRY; - } - - /*No QCU/DCU [5210]*/ - if (ah->ah_version == AR5K_AR5210) { - ath5k_hw_reg_write(ah, - (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) - | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, - AR5K_NODCU_RETRY_LMT_SLG_RETRY) - | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, - AR5K_NODCU_RETRY_LMT_SSH_RETRY) - | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) - | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), - AR5K_NODCU_RETRY_LMT); - } else { - /*QCU/DCU [5211+]*/ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(AR5K_INIT_SLG_RETRY, - AR5K_DCU_RETRY_LMT_SLG_RETRY) | - AR5K_REG_SM(AR5K_INIT_SSH_RETRY, - AR5K_DCU_RETRY_LMT_SSH_RETRY) | - AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | - AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), - AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); - - /*===Rest is also for QCU/DCU only [5211+]===*/ - - /* - * Set initial content window (cw_min/cw_max) - * and arbitrated interframe space (aifs)... - */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | - AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | - AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, - AR5K_DCU_LCL_IFS_AIFS), - AR5K_QUEUE_DFS_LOCAL_IFS(queue)); - - /* - * Set misc registers - */ - /* Enable DCU early termination for this queue */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_DCU_EARLY); - - /* Enable DCU to wait for next fragment from QCU */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_FRAG_WAIT); - - /* On Maui and Spirit use the global seqnum on DCU */ - if (ah->ah_mac_version < AR5K_SREV_AR5211) - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_SEQNUM_CTL); - - if (tq->tqi_cbr_period) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, - AR5K_QCU_CBRCFG_INTVAL) | - AR5K_REG_SM(tq->tqi_cbr_overflow_limit, - AR5K_QCU_CBRCFG_ORN_THRES), - AR5K_QUEUE_CBRCFG(queue)); - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_CBR); - if (tq->tqi_cbr_overflow_limit) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBR_THRES_ENABLE); - } - - if (tq->tqi_ready_time && - (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, - AR5K_QCU_RDYTIMECFG_INTVAL) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); - - if (tq->tqi_burst_time) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, - AR5K_DCU_CHAN_TIME_DUR) | - AR5K_DCU_CHAN_TIME_ENABLE, - AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); - - if (tq->tqi_flags - & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_RDY_VEOL_POLICY); - } - - if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, - AR5K_QUEUE_DFS_MISC(queue)); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, - AR5K_QUEUE_DFS_MISC(queue)); - - /* - * Set registers by queue type - */ - switch (tq->tqi_type) { - case AR5K_TX_QUEUE_BEACON: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_BCN_DIS | - AR5K_QCU_MISC_BCN_ENABLE); - - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << - AR5K_DCU_MISC_ARBLOCK_CTL_S) | - AR5K_DCU_MISC_POST_FR_BKOFF_DIS | - AR5K_DCU_MISC_BCN_ENABLE); - break; - - case AR5K_TX_QUEUE_CAB: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_DIS | - AR5K_QCU_MISC_CBREXP_BCN_DIS); - - ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - - (AR5K_TUNE_SW_BEACON_RESP - - AR5K_TUNE_DMA_BEACON_RESP) - - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); - - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << - AR5K_DCU_MISC_ARBLOCK_CTL_S)); - break; - - case AR5K_TX_QUEUE_UAPSD: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBREXP_DIS); - break; - - case AR5K_TX_QUEUE_DATA: - default: - break; - } - - /* TODO: Handle frame compression */ - - /* - * Enable interrupts for this tx queue - * in the secondary interrupt mask registers - */ - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); - - /* Update secondary interrupt mask registers */ - - /* Filter out inactive queues */ - ah->ah_txq_imr_txok &= ah->ah_txq_status; - ah->ah_txq_imr_txerr &= ah->ah_txq_status; - ah->ah_txq_imr_txurn &= ah->ah_txq_status; - ah->ah_txq_imr_txdesc &= ah->ah_txq_status; - ah->ah_txq_imr_txeol &= ah->ah_txq_status; - ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; - ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; - ah->ah_txq_imr_qtrig &= ah->ah_txq_status; - ah->ah_txq_imr_nofrm &= ah->ah_txq_status; - - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, - AR5K_SIMR0_QCU_TXOK) | - AR5K_REG_SM(ah->ah_txq_imr_txdesc, - AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, - AR5K_SIMR1_QCU_TXERR) | - AR5K_REG_SM(ah->ah_txq_imr_txeol, - AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); - /* Update simr2 but don't overwrite rest simr2 settings */ - AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); - AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, - AR5K_REG_SM(ah->ah_txq_imr_txurn, - AR5K_SIMR2_QCU_TXURN)); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, - AR5K_SIMR3_QCBRORN) | - AR5K_REG_SM(ah->ah_txq_imr_cbrurn, - AR5K_SIMR3_QCBRURN), AR5K_SIMR3); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, - AR5K_SIMR4_QTRIG), AR5K_SIMR4); - /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, - AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); - /* No queue has TXNOFRM enabled, disable the interrupt - * by setting AR5K_TXNOFRM to zero */ - if (ah->ah_txq_imr_nofrm == 0) - ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); - - /* Set QCU mask for this DCU to save power */ - AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); - } - - return 0; -} - -/* - * Get slot time from DCU - */ -unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_version == AR5K_AR5210) - return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, - AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); - else - return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; -} - -/* - * Set slot time on DCU - */ -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) -{ - ATH5K_TRACE(ah->ah_sc); - if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) - return -EINVAL; - - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, - ah->ah_turbo), AR5K_SLOT_TIME); - else - ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); - - return 0; -} - diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h deleted file mode 100644 index 7070d1543cdc..000000000000 --- a/drivers/net/wireless/ath5k/reg.h +++ /dev/null @@ -1,2589 +0,0 @@ -/* - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2007-2008 Michael Taylor - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k - * maintained by Reyk Floeter - * - * I tried to document those registers by looking at ar5k code, some - * 802.11 (802.11e mostly) papers and by reading various public available - * Atheros presentations and papers like these: - * - * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf - * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf - * - * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf - * - * This file also contains register values found on a memory dump of - * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal - * released by Atheros and on various debug messages found on the net. - */ - - - -/*====MAC DMA REGISTERS====*/ - -/* - * AR5210-Specific TXDP registers - * 5210 has only 2 transmit queues so no DCU/QCU, just - * 2 transmit descriptor pointers... - */ -#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */ -#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */ - -/* - * Mac Control Register - */ -#define AR5K_CR 0x0008 /* Register Address */ -#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */ -#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */ -#define AR5K_CR_RXE 0x00000004 /* RX Enable */ -#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */ -#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */ -#define AR5K_CR_RXD 0x00000020 /* RX Disable */ -#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */ - -/* - * RX Descriptor Pointer register - */ -#define AR5K_RXDP 0x000c - -/* - * Configuration and status register - */ -#define AR5K_CFG 0x0014 /* Register Address */ -#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */ -#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */ -#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ -#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */ -#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */ -#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */ -#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ -#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ -#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */ -#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */ -#define AR5K_CFG_TXCNT_S 11 -#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */ -#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */ -#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */ -#define AR5K_CFG_PCI_THRES_S 17 - -/* - * Interrupt enable register - */ -#define AR5K_IER 0x0024 /* Register Address */ -#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */ -#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */ - - -/* - * 0x0028 is Beacon Control Register on 5210 - * and first RTS duration register on 5211 - */ - -/* - * Beacon control register [5210] - */ -#define AR5K_BCR 0x0028 /* Register Address */ -#define AR5K_BCR_AP 0x00000000 /* AP mode */ -#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */ -#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */ -#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */ -#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */ -#define AR5K_BCR_BCGET 0x00000010 - -/* - * First RTS duration register [5211] - */ -#define AR5K_RTSD0 0x0028 /* Register Address */ -#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */ -#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */ -#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/ -#define AR5K_RTSD0_9_S 8 -#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/ -#define AR5K_RTSD0_12_S 16 -#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/ -#define AR5K_RTSD0_18_S 24 - - -/* - * 0x002c is Beacon Status Register on 5210 - * and second RTS duration register on 5211 - */ - -/* - * Beacon status register [5210] - * - * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR - * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning - * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). - * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i - * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what - * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. - */ -#define AR5K_BSR 0x002c /* Register Address */ -#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */ -#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */ -#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */ -#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */ -#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */ -#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */ -#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */ -#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */ -#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */ -#define AR5K_BSR_SWBA_CNT 0x00ff0000 - -/* - * Second RTS duration register [5211] - */ -#define AR5K_RTSD1 0x002c /* Register Address */ -#define AR5K_RTSD1_24 0x000000ff /* 24Mb */ -#define AR5K_RTSD1_24_S 0 -#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */ -#define AR5K_RTSD1_36_S 8 -#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */ -#define AR5K_RTSD1_48_S 16 -#define AR5K_RTSD1_54 0xff000000 /* 54Mb */ -#define AR5K_RTSD1_54_S 24 - - -/* - * Transmit configuration register - */ -#define AR5K_TXCFG 0x0030 /* Register Address */ -#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */ -#define AR5K_TXCFG_SDMAMR_S 0 -#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */ -#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */ -#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */ -#define AR5K_TXCFG_TXFULL_S 4 -#define AR5K_TXCFG_TXFULL_0B 0x00000000 -#define AR5K_TXCFG_TXFULL_64B 0x00000010 -#define AR5K_TXCFG_TXFULL_128B 0x00000020 -#define AR5K_TXCFG_TXFULL_192B 0x00000030 -#define AR5K_TXCFG_TXFULL_256B 0x00000040 -#define AR5K_TXCFG_TXCONT_EN 0x00000080 -#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */ -#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */ -#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */ -#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */ -#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */ -#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ -#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */ -#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */ -#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */ -#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */ - -/* - * Receive configuration register - */ -#define AR5K_RXCFG 0x0034 /* Register Address */ -#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */ -#define AR5K_RXCFG_SDMAMW_S 0 -#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */ -#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */ -#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */ -#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */ -#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */ - -/* - * Receive jumbo descriptor last address register - * Only found in 5211 (?) - */ -#define AR5K_RXJLA 0x0038 - -/* - * MIB control register - */ -#define AR5K_MIBC 0x0040 /* Register Address */ -#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ -#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ -#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ -#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ - -/* - * Timeout prescale register - */ -#define AR5K_TOPS 0x0044 -#define AR5K_TOPS_M 0x0000ffff - -/* - * Receive timeout register (no frame received) - */ -#define AR5K_RXNOFRM 0x0048 -#define AR5K_RXNOFRM_M 0x000003ff - -/* - * Transmit timeout register (no frame sent) - */ -#define AR5K_TXNOFRM 0x004c -#define AR5K_TXNOFRM_M 0x000003ff -#define AR5K_TXNOFRM_QCU 0x000ffc00 -#define AR5K_TXNOFRM_QCU_S 10 - -/* - * Receive frame gap timeout register - */ -#define AR5K_RPGTO 0x0050 -#define AR5K_RPGTO_M 0x000003ff - -/* - * Receive frame count limit register - */ -#define AR5K_RFCNT 0x0054 -#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */ -#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */ - -/* - * Misc settings register - * (reserved0-3) - */ -#define AR5K_MISC 0x0058 /* Register Address */ -#define AR5K_MISC_DMA_OBS_M 0x000001e0 -#define AR5K_MISC_DMA_OBS_S 5 -#define AR5K_MISC_MISC_OBS_M 0x00000e00 -#define AR5K_MISC_MISC_OBS_S 9 -#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000 -#define AR5K_MISC_MAC_OBS_LSB_S 12 -#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000 -#define AR5K_MISC_MAC_OBS_MSB_S 15 -#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */ -#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */ - -/* - * QCU/DCU clock gating register (5311) - * (reserved4-5) - */ -#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */ -#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */ -#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */ - -/* - * Interrupt Status Registers - * - * For 5210 there is only one status register but for - * 5211/5212 we have one primary and 4 secondary registers. - * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. - * Most of these bits are common for all chipsets. - */ -#define AR5K_ISR 0x001c /* Register Address [5210] */ -#define AR5K_PISR 0x0080 /* Register Address [5211+] */ -#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */ -#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ -#define AR5K_ISR_RXERR 0x00000004 /* Receive error */ -#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ -#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */ -#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */ -#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */ -#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ -#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ -#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */ -#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ -#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ -#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ -#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */ -#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */ -#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */ -#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ -#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ -#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ -#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ -#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ -#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ -#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ -#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ -#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ -#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ -#define AR5K_ISR_TIM 0x00800000 /* [5211+] */ -#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, - CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ -#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ -#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ -#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ -#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ - -/* - * Secondary status registers [5211+] (0 - 4) - * - * These give the status for each QCU, only QCUs 0-9 are - * represented. - */ -#define AR5K_SISR0 0x0084 /* Register Address [5211+] */ -#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ -#define AR5K_SISR0_QCU_TXOK_S 0 -#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ -#define AR5K_SISR0_QCU_TXDESC_S 16 - -#define AR5K_SISR1 0x0088 /* Register Address [5211+] */ -#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ -#define AR5K_SISR1_QCU_TXERR_S 0 -#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ -#define AR5K_SISR1_QCU_TXEOL_S 16 - -#define AR5K_SISR2 0x008c /* Register Address [5211+] */ -#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ -#define AR5K_SISR2_QCU_TXURN_S 0 -#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ -#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */ -#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ -#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ -#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ -#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ -#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ -#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ -#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */ - -#define AR5K_SISR3 0x0090 /* Register Address [5211+] */ -#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ -#define AR5K_SISR3_QCBRORN_S 0 -#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ -#define AR5K_SISR3_QCBRURN_S 16 - -#define AR5K_SISR4 0x0094 /* Register Address [5211+] */ -#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */ -#define AR5K_SISR4_QTRIG_S 0 - -/* - * Shadow read-and-clear interrupt status registers [5211+] - */ -#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */ -#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */ -#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */ -#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */ -#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */ -#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */ - -/* - * Interrupt Mask Registers - * - * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary - * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. - */ -#define AR5K_IMR 0x0020 /* Register Address [5210] */ -#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ -#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/ -#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ -#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ -#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ -#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/ -#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/ -#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/ -#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/ -#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/ -#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/ -#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/ -#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/ -#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/ -#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */ -#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/ -#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */ -#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/ -#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ -#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/ -#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ -#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */ -#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ -#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/ -#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */ -#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */ -#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ -#define AR5K_IMR_TIM 0x00800000 /* [5211+] */ -#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, - CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ -#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/ -#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */ -#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */ -#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ - -/* - * Secondary interrupt mask registers [5211+] (0 - 4) - */ -#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */ -#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ -#define AR5K_SIMR0_QCU_TXOK_S 0 -#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ -#define AR5K_SIMR0_QCU_TXDESC_S 16 - -#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */ -#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ -#define AR5K_SIMR1_QCU_TXERR_S 0 -#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ -#define AR5K_SIMR1_QCU_TXEOL_S 16 - -#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ -#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ -#define AR5K_SIMR2_QCU_TXURN_S 0 -#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ -#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ -#define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */ -#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ -#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ -#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ -#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ -#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ -#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */ -#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */ - -#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */ -#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ -#define AR5K_SIMR3_QCBRORN_S 0 -#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ -#define AR5K_SIMR3_QCBRURN_S 16 - -#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */ -#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */ -#define AR5K_SIMR4_QTRIG_S 0 - -/* - * DMA Debug registers 0-7 - * 0xe0 - 0xfc - */ - -/* - * Decompression mask registers [5212+] - */ -#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */ -#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */ - -/* - * Wake On Wireless pattern control register [5212+] - */ -#define AR5K_WOW_PCFG 0x0410 /* Register Address */ -#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */ -#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */ -#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */ -#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */ -#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */ -#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */ -#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */ -#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */ -#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */ - -/* - * Wake On Wireless pattern index register (?) [5212+] - */ -#define AR5K_WOW_PAT_IDX 0x0414 - -/* - * Wake On Wireless pattern data register [5212+] - */ -#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */ -#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */ -#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */ -#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */ -#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */ -#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */ -#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */ - -/* - * Decompression configuration registers [5212+] - */ -#define AR5K_DCCFG 0x0420 /* Register Address */ -#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */ -#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */ -#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */ -#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */ - -/* - * Compression configuration registers [5212+] - */ -#define AR5K_CCFG 0x0600 /* Register Address */ -#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */ -#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */ - -#define AR5K_CCFG_CCU 0x0604 /* Register Address */ -#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */ -#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */ -#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */ -#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */ -#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */ - -/* - * Compression performance counter registers [5212+] - */ -#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */ -#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/ -#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */ -#define AR5K_CPC3 0x061c /* Compression performance counter 3 */ -#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */ - - -/* - * Queue control unit (QCU) registers [5211+] - * - * Card has 12 TX Queues but i see that only 0-9 are used (?) - * both in binary HAL (see ah.h) and ar5k. Each queue has it's own - * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate) - * configuration register (0x08c0 - 0x08ec), a ready time configuration - * register (0x0900 - 0x092c), a misc configuration register (0x09c0 - - * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some - * global registers, QCU transmit enable/disable and "one shot arm (?)" - * set/clear, which contain status for all queues (we shift by 1 for each - * queue). To access these registers easily we define some macros here - * that are used inside HAL. For more infos check out *_tx_queue functs. - */ - -/* - * Generic QCU Register access macros - */ -#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r) -#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q)) -#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q)) - -/* - * QCU Transmit descriptor pointer registers - */ -#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */ -#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q) - -/* - * QCU Transmit enable register - */ -#define AR5K_QCU_TXE 0x0840 -#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q) -#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q) - -/* - * QCU Transmit disable register - */ -#define AR5K_QCU_TXD 0x0880 -#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q) -#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q) - -/* - * QCU Constant Bit Rate configuration registers - */ -#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */ -#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */ -#define AR5K_QCU_CBRCFG_INTVAL_S 0 -#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */ -#define AR5K_QCU_CBRCFG_ORN_THRES_S 24 -#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q) - -/* - * QCU Ready time configuration registers - */ -#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */ -#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */ -#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0 -#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */ -#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q) - -/* - * QCU one shot arm set registers - */ -#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */ -#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff - -/* - * QCU one shot arm clear registers - */ -#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */ -#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff - -/* - * QCU misc registers - */ -#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */ -#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */ -#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ -#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ -#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */ -#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */ -#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */ -#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */ -#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */ -#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */ -#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */ -#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */ -#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */ -#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */ -#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */ -#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */ -#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q) - - -/* - * QCU status registers - */ -#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */ -#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */ -#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */ -#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q) - -/* - * QCU ready time shutdown register - */ -#define AR5K_QCU_RDYTIMESHDN 0x0a40 -#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff - -/* - * QCU compression buffer base registers [5212+] - */ -#define AR5K_QCU_CBB_SELECT 0x0b00 -#define AR5K_QCU_CBB_ADDR 0x0b04 -#define AR5K_QCU_CBB_ADDR_S 9 - -/* - * QCU compression buffer configuration register [5212+] - * (buffer size) - */ -#define AR5K_QCU_CBCFG 0x0b08 - - - -/* - * Distributed Coordination Function (DCF) control unit (DCU) - * registers [5211+] - * - * These registers control the various characteristics of each queue - * for 802.11e (WME) combatibility so they go together with - * QCU registers in pairs. For each queue we have a QCU mask register, - * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c), - * a retry limit register (0x1080 - 0x10ac), a channel time register - * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and - * a sequence number register (0x1140 - 0x116c). It seems that "global" - * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k). - * We use the same macros here for easier register access. - * - */ - -/* - * DCU QCU mask registers - */ -#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */ -#define AR5K_DCU_QCUMASK_M 0x000003ff -#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q) - -/* - * DCU local Inter Frame Space settings register - */ -#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */ -#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */ -#define AR5K_DCU_LCL_IFS_CW_MIN_S 0 -#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */ -#define AR5K_DCU_LCL_IFS_CW_MAX_S 10 -#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */ -#define AR5K_DCU_LCL_IFS_AIFS_S 20 -#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */ -#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q) - -/* - * DCU retry limit registers - */ -#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ -#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ -#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0 -#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */ -#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4 -#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */ -#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8 -#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */ -#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14 -#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) - -/* - * DCU channel time registers - */ -#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */ -#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */ -#define AR5K_DCU_CHAN_TIME_DUR_S 0 -#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */ -#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q) - -/* - * DCU misc registers [5211+] - * - * Note: Arbiter lockout control controls the - * behaviour on low priority queues when we have multiple queues - * with pending frames. Intra-frame lockout means we wait until - * the queue's current frame transmits (with post frame backoff and bursting) - * before we transmit anything else and global lockout means we - * wait for the whole queue to finish before higher priority queues - * can transmit (this is used on beacon and CAB queues). - * No lockout means there is no special handling. - */ -#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */ -#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */ -#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series - station RTS/data failure count - reset policy (?) */ -#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series - CW reset policy */ -#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */ -#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */ -#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */ -#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */ -#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */ -#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */ -#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 -#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1 -#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */ -#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */ -#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17 -#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */ -#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */ -#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */ -#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */ -#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */ -#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */ -#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */ -#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */ -#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */ -#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q) - -/* - * DCU frame sequence number registers - */ -#define AR5K_DCU_SEQNUM_BASE 0x1140 -#define AR5K_DCU_SEQNUM_M 0x00000fff -#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q) - -/* - * DCU global IFS SIFS register - */ -#define AR5K_DCU_GBL_IFS_SIFS 0x1030 -#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff - -/* - * DCU global IFS slot interval register - */ -#define AR5K_DCU_GBL_IFS_SLOT 0x1070 -#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff - -/* - * DCU global IFS EIFS register - */ -#define AR5K_DCU_GBL_IFS_EIFS 0x10b0 -#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff - -/* - * DCU global IFS misc register - * - * LFSR stands for Linear Feedback Shift Register - * and it's used for generating pseudo-random - * number sequences. - * - * (If i understand corectly, random numbers are - * used for idle sensing -multiplied with cwmin/max etc-) - */ -#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */ -#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ -#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ -#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ -#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ -#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 -#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ -#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */ -#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */ -#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */ - -/* - * DCU frame prefetch control register - */ -#define AR5K_DCU_FP 0x1230 /* Register Address */ -#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */ -#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */ -#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */ - -/* - * DCU transmit pause control/status register - */ -#define AR5K_DCU_TXP 0x1270 /* Register Address */ -#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */ -#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */ - -/* - * DCU transmit filter table 0 (32 entries) - * each entry contains a 32bit slice of the - * 128bit tx filter for each DCU (4 slices per DCU) - */ -#define AR5K_DCU_TX_FILTER_0_BASE 0x1038 -#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64)) - -/* - * DCU transmit filter table 1 (16 entries) - */ -#define AR5K_DCU_TX_FILTER_1_BASE 0x103c -#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + (_n * 64)) - -/* - * DCU clear transmit filter register - */ -#define AR5K_DCU_TX_FILTER_CLR 0x143c - -/* - * DCU set transmit filter register - */ -#define AR5K_DCU_TX_FILTER_SET 0x147c - -/* - * Reset control register - */ -#define AR5K_RESET_CTL 0x4000 /* Register Address */ -#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */ -#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */ -#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */ -#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ -#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ -#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ - -/* - * Sleep control register - */ -#define AR5K_SLEEP_CTL 0x4004 /* Register Address */ -#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */ -#define AR5K_SLEEP_CTL_SLDUR_S 0 -#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */ -#define AR5K_SLEEP_CTL_SLE_S 16 -#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */ -#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */ -#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */ -#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */ -#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */ -#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */ -#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */ - -/* - * Interrupt pending register - */ -#define AR5K_INTPEND 0x4008 -#define AR5K_INTPEND_M 0x00000001 - -/* - * Sleep force register - */ -#define AR5K_SFR 0x400c -#define AR5K_SFR_EN 0x00000001 - -/* - * PCI configuration register - * TODO: Fix LED stuff - */ -#define AR5K_PCICFG 0x4010 /* Register Address */ -#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ -#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */ -#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ -#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ -#define AR5K_PCICFG_EESIZE_S 3 -#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */ -#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */ -#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */ -#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */ -#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */ -#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */ -#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */ -#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */ -#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */ -#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */ -#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ -#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ -#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ -#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/ -#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ -#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ -#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ -#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */ -#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */ -#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */ -#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */ -#define AR5K_PCICFG_LEDBLINK_S 20 -#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */ -#define AR5K_PCICFG_LEDSTATE \ - (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \ - AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW) -#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */ -#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24 - -/* - * "General Purpose Input/Output" (GPIO) control register - * - * I'm not sure about this but after looking at the code - * for all chipsets here is what i got. - * - * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits) - * Mode 0 -> always input - * Mode 1 -> output when GPIODO for this GPIO is set to 0 - * Mode 2 -> output when GPIODO for this GPIO is set to 1 - * Mode 3 -> always output - * - * For more infos check out get_gpio/set_gpio and - * set_gpio_input/set_gpio_output functs. - * For more infos on gpio interrupt check out set_gpio_intr. - */ -#define AR5K_NUM_GPIO 6 - -#define AR5K_GPIOCR 0x4014 /* Register Address */ -#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ -#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */ -#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */ -#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */ -#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */ -#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */ -#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */ -#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */ - -/* - * "General Purpose Input/Output" (GPIO) data output register - */ -#define AR5K_GPIODO 0x4018 - -/* - * "General Purpose Input/Output" (GPIO) data input register - */ -#define AR5K_GPIODI 0x401c -#define AR5K_GPIODI_M 0x0000002f - -/* - * Silicon revision register - */ -#define AR5K_SREV 0x4020 /* Register Address */ -#define AR5K_SREV_REV 0x0000000f /* Mask for revision */ -#define AR5K_SREV_REV_S 0 -#define AR5K_SREV_VER 0x000000ff /* Mask for version */ -#define AR5K_SREV_VER_S 4 - -/* - * TXE write posting register - */ -#define AR5K_TXEPOST 0x4028 - -/* - * QCU sleep mask - */ -#define AR5K_QCU_SLEEP_MASK 0x402c - -/* 0x4068 is compression buffer configuration - * register on 5414 and pm configuration register - * on 5424 and newer pci-e chips. */ - -/* - * Compression buffer configuration - * register (enable/disable) [5414] - */ -#define AR5K_5414_CBCFG 0x4068 -#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */ - -/* - * PCI-E Power managment configuration - * and status register [5424+] - */ -#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */ -/* Only 5424 */ -#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1 - when d2_sleep_en is asserted */ -#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */ -#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */ -#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes - down */ -/* Wake On Wireless */ -#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */ -#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */ -#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */ -#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080 -#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100 -#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200 -#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400 - -/* - * PCI-E Workaround enable register - */ -#define AR5K_PCIE_WAEN 0x407c - -/* - * PCI-E Serializer/Desirializer - * registers - */ -#define AR5K_PCIE_SERDES 0x4080 -#define AR5K_PCIE_SERDES_RESET 0x4084 - -/*====EEPROM REGISTERS====*/ - -/* - * EEPROM access registers - * - * Here we got a difference between 5210/5211-12 - * read data register for 5210 is at 0x6800 and - * status register is at 0x6c00. There is also - * no eeprom command register on 5210 and the - * offsets are different. - * - * To read eeprom data for a specific offset: - * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) - * read AR5K_EEPROM_BASE +(4 * offset) - * check the eeprom status register - * and read eeprom data register. - * - * 5211 - write offset to AR5K_EEPROM_BASE - * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD - * check the eeprom status register - * and read eeprom data register. - * - * To write eeprom data for a specific offset: - * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) - * write data to AR5K_EEPROM_BASE +(4 * offset) - * check the eeprom status register - * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD - * 5212 write offset to AR5K_EEPROM_BASE - * write data to data register - * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD - * check the eeprom status register - * - * For more infos check eeprom_* functs and the ar5k.c - * file posted in madwifi-devel mailing list. - * http://sourceforge.net/mailarchive/message.php?msg_id=8966525 - * - */ -#define AR5K_EEPROM_BASE 0x6000 - -/* - * EEPROM data register - */ -#define AR5K_EEPROM_DATA_5211 0x6004 -#define AR5K_EEPROM_DATA_5210 0x6800 -#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \ - AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211) - -/* - * EEPROM command register - */ -#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ -#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ -#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ -#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ - -/* - * EEPROM status register - */ -#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */ -#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */ -#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \ - AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211) -#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */ -#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */ -#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */ -#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */ - -/* - * EEPROM config register - */ -#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ -#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ -#define AR5K_EEPROM_CFG_SIZE_AUTO 0 -#define AR5K_EEPROM_CFG_SIZE_4KBIT 1 -#define AR5K_EEPROM_CFG_SIZE_8KBIT 2 -#define AR5K_EEPROM_CFG_SIZE_16KBIT 3 -#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */ -#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */ -#define AR5K_EEPROM_CFG_CLK_RATE_S 3 -#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0 -#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1 -#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2 -#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */ -#define AR5K_EEPROM_CFG_PROT_KEY_S 8 -#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */ - - -/* - * TODO: Wake On Wireless registers - * Range 0x7000 - 0x7ce0 - */ - -/* - * Protocol Control Unit (PCU) registers - */ -/* - * Used for checking initial register writes - * during channel reset (see reset func) - */ -#define AR5K_PCU_MIN 0x8000 -#define AR5K_PCU_MAX 0x8fff - -/* - * First station id register (Lower 32 bits of MAC address) - */ -#define AR5K_STA_ID0 0x8000 -#define AR5K_STA_ID0_ARRD_L32 0xffffffff - -/* - * Second station id register (Upper 16 bits of MAC address + PCU settings) - */ -#define AR5K_STA_ID1 0x8004 /* Register Address */ -#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */ -#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ -#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ -#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ -#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */ -#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */ -#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */ -#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/ -#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \ - AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211) -#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ -#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ -#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ -#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ -#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */ -#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ -#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ -#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ -#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */ -#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ -#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ - -/* - * First BSSID register (MAC address, lower 32bits) - */ -#define AR5K_BSS_ID0 0x8008 - -/* - * Second BSSID register (MAC address in upper 16 bits) - * - * AID: Association ID - */ -#define AR5K_BSS_ID1 0x800c -#define AR5K_BSS_ID1_AID 0xffff0000 -#define AR5K_BSS_ID1_AID_S 16 - -/* - * Backoff slot time register - */ -#define AR5K_SLOT_TIME 0x8010 - -/* - * ACK/CTS timeout register - */ -#define AR5K_TIME_OUT 0x8014 /* Register Address */ -#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */ -#define AR5K_TIME_OUT_ACK_S 0 -#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */ -#define AR5K_TIME_OUT_CTS_S 16 - -/* - * RSSI threshold register - */ -#define AR5K_RSSI_THR 0x8018 /* Register Address */ -#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */ -#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */ -#define AR5K_RSSI_THR_BMISS_5210_S 8 -#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */ -#define AR5K_RSSI_THR_BMISS_5211_S 8 -#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211) -#define AR5K_RSSI_THR_BMISS_S 8 - -/* - * 5210 has more PCU registers because there is no QCU/DCU - * so queue parameters are set here, this way a lot common - * registers have different address for 5210. To make things - * easier we define a macro based on ah->ah_version for common - * registers with different addresses and common flags. - */ - -/* - * Retry limit register - * - * Retry limit register for 5210 (no QCU/DCU so it's done in PCU) - */ -#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */ -#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ -#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0 -#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */ -#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4 -#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */ -#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8 -#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */ -#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14 -#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */ -#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20 - -/* - * Transmit latency register - */ -#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */ -#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */ -#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \ - AR5K_USEC_5210 : AR5K_USEC_5211) -#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */ -#define AR5K_USEC_1_S 0 -#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */ -#define AR5K_USEC_32_S 7 -#define AR5K_USEC_TX_LATENCY_5211 0x007fc000 -#define AR5K_USEC_TX_LATENCY_5211_S 14 -#define AR5K_USEC_RX_LATENCY_5211 0x1f800000 -#define AR5K_USEC_RX_LATENCY_5211_S 23 -#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */ -#define AR5K_USEC_TX_LATENCY_5210_S 14 -#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */ -#define AR5K_USEC_RX_LATENCY_5210_S 20 - -/* - * PCU beacon control register - */ -#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */ -#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */ -#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \ - AR5K_BEACON_5210 : AR5K_BEACON_5211) -#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */ -#define AR5K_BEACON_PERIOD_S 0 -#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */ -#define AR5K_BEACON_TIM_S 16 -#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */ -#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */ - -/* - * CFP period register - */ -#define AR5K_CFP_PERIOD_5210 0x8028 -#define AR5K_CFP_PERIOD_5211 0x8024 -#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \ - AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211) - -/* - * Next beacon time register - */ -#define AR5K_TIMER0_5210 0x802c -#define AR5K_TIMER0_5211 0x8028 -#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER0_5210 : AR5K_TIMER0_5211) - -/* - * Next DMA beacon alert register - */ -#define AR5K_TIMER1_5210 0x8030 -#define AR5K_TIMER1_5211 0x802c -#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER1_5210 : AR5K_TIMER1_5211) - -/* - * Next software beacon alert register - */ -#define AR5K_TIMER2_5210 0x8034 -#define AR5K_TIMER2_5211 0x8030 -#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER2_5210 : AR5K_TIMER2_5211) - -/* - * Next ATIM window time register - */ -#define AR5K_TIMER3_5210 0x8038 -#define AR5K_TIMER3_5211 0x8034 -#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER3_5210 : AR5K_TIMER3_5211) - - -/* - * 5210 First inter frame spacing register (IFS) - */ -#define AR5K_IFS0 0x8040 -#define AR5K_IFS0_SIFS 0x000007ff -#define AR5K_IFS0_SIFS_S 0 -#define AR5K_IFS0_DIFS 0x007ff800 -#define AR5K_IFS0_DIFS_S 11 - -/* - * 5210 Second inter frame spacing register (IFS) - */ -#define AR5K_IFS1 0x8044 -#define AR5K_IFS1_PIFS 0x00000fff -#define AR5K_IFS1_PIFS_S 0 -#define AR5K_IFS1_EIFS 0x03fff000 -#define AR5K_IFS1_EIFS_S 12 -#define AR5K_IFS1_CS_EN 0x04000000 - - -/* - * CFP duration register - */ -#define AR5K_CFP_DUR_5210 0x8048 -#define AR5K_CFP_DUR_5211 0x8038 -#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \ - AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211) - -/* - * Receive filter register - */ -#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */ -#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */ -#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211) -#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */ -#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */ -#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */ -#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */ -#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */ -#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */ -#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */ -#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */ -#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */ -#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */ -#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */ -#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */ -#define AR5K_RX_FILTER_PHYERR \ - ((ah->ah_version == AR5K_AR5211 ? \ - AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212)) -#define AR5K_RX_FILTER_RADARERR \ - ((ah->ah_version == AR5K_AR5211 ? \ - AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212)) - -/* - * Multicast filter register (lower 32 bits) - */ -#define AR5K_MCAST_FILTER0_5210 0x8050 -#define AR5K_MCAST_FILTER0_5211 0x8040 -#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211) - -/* - * Multicast filter register (higher 16 bits) - */ -#define AR5K_MCAST_FILTER1_5210 0x8054 -#define AR5K_MCAST_FILTER1_5211 0x8044 -#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211) - - -/* - * Transmit mask register (lower 32 bits) [5210] - */ -#define AR5K_TX_MASK0 0x8058 - -/* - * Transmit mask register (higher 16 bits) [5210] - */ -#define AR5K_TX_MASK1 0x805c - -/* - * Clear transmit mask [5210] - */ -#define AR5K_CLR_TMASK 0x8060 - -/* - * Trigger level register (before transmission) [5210] - */ -#define AR5K_TRIG_LVL 0x8064 - - -/* - * PCU control register - * - * Only DIS_RX is used in the code, the rest i guess are - * for tweaking/diagnostics. - */ -#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ -#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ -#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211) -#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ -#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ -#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ -#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ -#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ -#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ -#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ -#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 -#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) -#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */ -#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 -#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) -#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */ -#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 -#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) -#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */ -#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 -#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */ -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 -#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211) -#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */ -#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ -#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ -#define AR5K_DIAG_SW_SCRAM_SEED_S 10 -#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ -#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 -#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ -#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) -#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ -#define AR5K_DIAG_SW_OBSPT_S 18 -#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ -#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ -#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ -#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ - -/* - * TSF (clock) register (lower 32 bits) - */ -#define AR5K_TSF_L32_5210 0x806c -#define AR5K_TSF_L32_5211 0x804c -#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211) - -/* - * TSF (clock) register (higher 32 bits) - */ -#define AR5K_TSF_U32_5210 0x8070 -#define AR5K_TSF_U32_5211 0x8050 -#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211) - -/* - * Last beacon timestamp register (Read Only) - */ -#define AR5K_LAST_TSTP 0x8080 - -/* - * ADDAC test register [5211+] - */ -#define AR5K_ADDAC_TEST 0x8054 /* Register Address */ -#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */ -#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */ -#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */ -#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */ -#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */ -#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */ -#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */ -#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */ -#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */ -#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */ -#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */ - -/* - * Default antenna register [5211+] - */ -#define AR5K_DEFAULT_ANTENNA 0x8058 - -/* - * Frame control QoS mask register (?) [5211+] - * (FC_QOS_MASK) - */ -#define AR5K_FRAME_CTL_QOSM 0x805c - -/* - * Seq mask register (?) [5211+] - */ -#define AR5K_SEQ_MASK 0x8060 - -/* - * Retry count register [5210] - */ -#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */ -#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */ -#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */ - -/* - * Back-off status register [5210] - */ -#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */ -#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */ -#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */ - - - -/* - * NAV register (current) - */ -#define AR5K_NAV_5210 0x808c -#define AR5K_NAV_5211 0x8084 -#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \ - AR5K_NAV_5210 : AR5K_NAV_5211) - -/* - * RTS success register - */ -#define AR5K_RTS_OK_5210 0x8090 -#define AR5K_RTS_OK_5211 0x8088 -#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) - -/* - * RTS failure register - */ -#define AR5K_RTS_FAIL_5210 0x8094 -#define AR5K_RTS_FAIL_5211 0x808c -#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) - -/* - * ACK failure register - */ -#define AR5K_ACK_FAIL_5210 0x8098 -#define AR5K_ACK_FAIL_5211 0x8090 -#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) - -/* - * FCS failure register - */ -#define AR5K_FCS_FAIL_5210 0x809c -#define AR5K_FCS_FAIL_5211 0x8094 -#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211) - -/* - * Beacon count register - */ -#define AR5K_BEACON_CNT_5210 0x80a0 -#define AR5K_BEACON_CNT_5211 0x8098 -#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \ - AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211) - - -/*===5212 Specific PCU registers===*/ - -/* - * Transmit power control register - */ -#define AR5K_TPC 0x80e8 -#define AR5K_TPC_ACK 0x0000003f /* ack frames */ -#define AR5K_TPC_ACK_S 0 -#define AR5K_TPC_CTS 0x00003f00 /* cts frames */ -#define AR5K_TPC_CTS_S 8 -#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */ -#define AR5K_TPC_CHIRP_S 16 -#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */ -#define AR5K_TPC_DOPPLER_S 24 - -/* - * XR (eXtended Range) mode register - */ -#define AR5K_XRMODE 0x80c0 /* Register Address */ -#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */ -#define AR5K_XRMODE_POLL_TYPE_S 0 -#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */ -#define AR5K_XRMODE_POLL_SUBTYPE_S 2 -#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */ -#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */ -#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */ -#define AR5K_XRMODE_FRAME_HOLD_S 20 - -/* - * XR delay register - */ -#define AR5K_XRDELAY 0x80c4 /* Register Address */ -#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */ -#define AR5K_XRDELAY_SLOT_DELAY_S 0 -#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */ -#define AR5K_XRDELAY_CHIRP_DELAY_S 16 - -/* - * XR timeout register - */ -#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */ -#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */ -#define AR5K_XRTIMEOUT_CHIRP_S 0 -#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */ -#define AR5K_XRTIMEOUT_POLL_S 16 - -/* - * XR chirp register - */ -#define AR5K_XRCHIRP 0x80cc /* Register Address */ -#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */ -#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */ - -/* - * XR stomp register - */ -#define AR5K_XRSTOMP 0x80d0 /* Register Address */ -#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */ -#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */ -#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */ -#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */ -#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/ -#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */ - -/* - * First enhanced sleep register - */ -#define AR5K_SLEEP0 0x80d4 /* Register Address */ -#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */ -#define AR5K_SLEEP0_NEXT_DTIM_S 0 -#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */ -#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */ -#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */ -#define AR5K_SLEEP0_CABTO_S 24 - -/* - * Second enhanced sleep register - */ -#define AR5K_SLEEP1 0x80d8 /* Register Address */ -#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */ -#define AR5K_SLEEP1_NEXT_TIM_S 0 -#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */ -#define AR5K_SLEEP1_BEACON_TO_S 24 - -/* - * Third enhanced sleep register - */ -#define AR5K_SLEEP2 0x80dc /* Register Address */ -#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */ -#define AR5K_SLEEP2_TIM_PER_S 0 -#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */ -#define AR5K_SLEEP2_DTIM_PER_S 16 - -/* - * BSSID mask registers - */ -#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */ -#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */ - -/* - * TX power control (TPC) register - * - * XXX: PCDAC steps (0.5dbm) or DBM ? - * - */ -#define AR5K_TXPC 0x80e8 /* Register Address */ -#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */ -#define AR5K_TXPC_ACK_S 0 -#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */ -#define AR5K_TXPC_CTS_S 8 -#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */ -#define AR5K_TXPC_CHIRP_S 16 -#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */ -#define AR5K_TXPC_DOPPLER_S 24 - -/* - * Profile count registers - */ -#define AR5K_PROFCNT_TX 0x80ec /* Tx count */ -#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ -#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ -#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ - -/* - * Quiet period control registers - */ -#define AR5K_QUIET_CTL1 0x80fc /* Register Address */ -#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ -#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0 -#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ -#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ - -#define AR5K_QUIET_CTL2 0x8100 /* Register Address */ -#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */ -#define AR5K_QUIET_CTL2_QT_PER_S 0 -#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */ -#define AR5K_QUIET_CTL2_QT_DUR_S 16 - -/* - * TSF parameter register - */ -#define AR5K_TSF_PARM 0x8104 /* Register Address */ -#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */ -#define AR5K_TSF_PARM_INC_S 0 - -/* - * QoS NOACK policy - */ -#define AR5K_QOS_NOACK 0x8108 /* Register Address */ -#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */ -#define AR5K_QOS_NOACK_2BIT_VALUES_S 0 -#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */ -#define AR5K_QOS_NOACK_BIT_OFFSET_S 4 -#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */ -#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7 - -/* - * PHY error filter register - */ -#define AR5K_PHY_ERR_FIL 0x810c -#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */ -#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */ -#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */ - -/* - * XR latency register - */ -#define AR5K_XRLAT_TX 0x8110 - -/* - * ACK SIFS register - */ -#define AR5K_ACKSIFS 0x8114 /* Register Address */ -#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */ - -/* - * MIC QoS control register (?) - */ -#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */ -#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2)) -#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */ - -/* - * MIC QoS select register (?) - */ -#define AR5K_MIC_QOS_SEL 0x811c -#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4)) - -/* - * Misc mode control register (?) - */ -#define AR5K_MISC_MODE 0x8120 /* Register Address */ -#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */ -#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */ -#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */ -/* more bits */ - -/* - * OFDM Filter counter - */ -#define AR5K_OFDM_FIL_CNT 0x8124 - -/* - * CCK Filter counter - */ -#define AR5K_CCK_FIL_CNT 0x8128 - -/* - * PHY Error Counters (?) - */ -#define AR5K_PHYERR_CNT1 0x812c -#define AR5K_PHYERR_CNT1_MASK 0x8130 - -#define AR5K_PHYERR_CNT2 0x8134 -#define AR5K_PHYERR_CNT2_MASK 0x8138 - -/* - * TSF Threshold register (?) - */ -#define AR5K_TSF_THRES 0x813c - -/* - * TODO: Wake On Wireless registers - * Range: 0x8147 - 0x818c - */ - -/* - * Rate -> ACK SIFS mapping table (32 entries) - */ -#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */ -#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2)) -#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */ -#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */ - -/* - * Rate -> duration mapping table (32 entries) - */ -#define AR5K_RATE_DUR_BASE 0x8700 -#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2)) - -/* - * Rate -> db mapping table - * (8 entries, each one has 4 8bit fields) - */ -#define AR5K_RATE2DB_BASE 0x87c0 -#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2)) - -/* - * db -> Rate mapping table - * (8 entries, each one has 4 8bit fields) - */ -#define AR5K_DB2RATE_BASE 0x87e0 -#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2)) - -/*===5212 end===*/ - -/* - * Key table (WEP) register - */ -#define AR5K_KEYTABLE_0_5210 0x9000 -#define AR5K_KEYTABLE_0_5211 0x8800 -#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5)) -#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) -#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \ - AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n)) -#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2)) -#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5) -#define AR5K_KEYTABLE_TYPE_40 0x00000000 -#define AR5K_KEYTABLE_TYPE_104 0x00000001 -#define AR5K_KEYTABLE_TYPE_128 0x00000003 -#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */ -#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */ -#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */ -#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */ -#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */ -#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6) -#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) -#define AR5K_KEYTABLE_VALID 0x00008000 - -/* If key type is TKIP and MIC is enabled - * MIC key goes in offset entry + 64 */ -#define AR5K_KEYTABLE_MIC_OFFSET 64 - -/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit - * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit - * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit - * - * Some vendors have introduced bigger WEP keys to address - * security vulnerabilities in WEP. This includes: - * - * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit - * - * We can expand this if we find ar5k Atheros cards with a larger - * key table size. - */ -#define AR5K_KEYTABLE_SIZE_5210 64 -#define AR5K_KEYTABLE_SIZE_5211 128 -#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \ - AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211) - - -/*===PHY REGISTERS===*/ - -/* - * PHY registers start - */ -#define AR5K_PHY_BASE 0x9800 -#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) - -/* - * TST_2 (Misc config parameters) - */ -#define AR5K_PHY_TST2 0x9800 /* Register Address */ -#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/ -#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */ -#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */ -#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */ -#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */ -#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */ -#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */ -#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */ -#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */ -#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */ -#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */ -#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */ -#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */ -#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */ -#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */ -#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */ -#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */ -#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */ - -/* - * PHY frame control register [5110] /turbo mode register [5111+] - * - * There is another frame control register for [5111+] - * at address 0x9944 (see below) but the 2 first flags - * are common here between 5110 frame control register - * and [5111+] turbo mode register, so this also works as - * a "turbo mode register" for 5110. We treat this one as - * a frame control register for 5110 below. - */ -#define AR5K_PHY_TURBO 0x9804 /* Register Address */ -#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ -#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ -#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ - -/* - * PHY agility command register - * (aka TST_1) - */ -#define AR5K_PHY_AGC 0x9808 /* Register Address */ -#define AR5K_PHY_TST1 0x9808 -#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/ -#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */ -#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */ -#define AR5K_PHY_TST1_TXSRC_SRC_S 1 -#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */ -#define AR5K_PHY_TST1_TXSRC_ALT_S 7 - - -/* - * PHY timing register 3 [5112+] - */ -#define AR5K_PHY_TIMING_3 0x9814 -#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000 -#define AR5K_PHY_TIMING_3_DSC_MAN_S 17 -#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000 -#define AR5K_PHY_TIMING_3_DSC_EXP_S 13 - -/* - * PHY chip revision register - */ -#define AR5K_PHY_CHIP_ID 0x9818 - -/* - * PHY activation register - */ -#define AR5K_PHY_ACT 0x981c /* Register Address */ -#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */ -#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */ - -/* - * PHY RF control registers - */ -#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */ -#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */ -#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0 - -#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */ -#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */ -#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8 - -#define AR5K_PHY_ADC_CTL 0x982c -#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003 -#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0 -#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000 -#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000 -#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000 -#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000 -#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16 - -#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */ -#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */ -#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */ -#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */ -#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */ - -/* - * Pre-Amplifier control register - * (XPA -> external pre-amplifier) - */ -#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */ -#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */ -#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */ -#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */ -#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */ - -/* - * PHY settling register - */ -#define AR5K_PHY_SETTLING 0x9844 /* Register Address */ -#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ -#define AR5K_PHY_SETTLING_AGC_S 0 -#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ -#define AR5K_PHY_SETTLING_SWITCH_S 7 - -/* - * PHY Gain registers - */ -#define AR5K_PHY_GAIN 0x9848 /* Register Address */ -#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */ -#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12 -#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000 -#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18 - -#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */ -#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ - -/* - * Desired ADC/PGA size register - * (for more infos read ANI patent) - */ -#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ -#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */ -#define AR5K_PHY_DESIRED_SIZE_ADC_S 0 -#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */ -#define AR5K_PHY_DESIRED_SIZE_PGA_S 8 -#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */ -#define AR5K_PHY_DESIRED_SIZE_TOT_S 20 - -/* - * PHY signal register - * (for more infos read ANI patent) - */ -#define AR5K_PHY_SIG 0x9858 /* Register Address */ -#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */ -#define AR5K_PHY_SIG_FIRSTEP_S 12 -#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */ -#define AR5K_PHY_SIG_FIRPWR_S 18 - -/* - * PHY coarse agility control register - * (for more infos read ANI patent) - */ -#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */ -#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */ -#define AR5K_PHY_AGCCOARSE_LO_S 7 -#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */ -#define AR5K_PHY_AGCCOARSE_HI_S 15 - -/* - * PHY agility control register - */ -#define AR5K_PHY_AGCCTL 0x9860 /* Register address */ -#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ -#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ -#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ -#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ - -/* - * PHY noise floor status register - */ -#define AR5K_PHY_NF 0x9864 /* Register address */ -#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ -#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ -#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) -#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) -#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) -#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ -#define AR5K_PHY_NF_THRESH62_S 12 -#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ -#define AR5K_PHY_NF_MINCCA_PWR_S 19 - -/* - * PHY ADC saturation register [5110] - */ -#define AR5K_PHY_ADCSAT 0x9868 -#define AR5K_PHY_ADCSAT_ICNT 0x0001f800 -#define AR5K_PHY_ADCSAT_ICNT_S 11 -#define AR5K_PHY_ADCSAT_THR 0x000007e0 -#define AR5K_PHY_ADCSAT_THR_S 5 - -/* - * PHY Weak ofdm signal detection threshold registers (ANI) [5212+] - */ - -/* High thresholds */ -#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24 - -/* Low thresholds */ -#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c -#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21 - - -/* - * PHY sleep registers [5112+] - */ -#define AR5K_PHY_SCR 0x9870 - -#define AR5K_PHY_SLMT 0x9874 -#define AR5K_PHY_SLMT_32MHZ 0x0000007f - -#define AR5K_PHY_SCAL 0x9878 -#define AR5K_PHY_SCAL_32MHZ 0x0000000e -#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a -#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 - -/* - * PHY PLL (Phase Locked Loop) control register - */ -#define AR5K_PHY_PLL 0x987c -#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */ -/* 40MHz -> 5GHz band */ -#define AR5K_PHY_PLL_40MHZ_5211 0x00000018 -#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa -#define AR5K_PHY_PLL_40MHZ_5413 0x00000004 -#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \ - AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212) -/* 44MHz -> 2.4GHz band */ -#define AR5K_PHY_PLL_44MHZ_5211 0x00000019 -#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab -#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \ - AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212) - -#define AR5K_PHY_PLL_RF5111 0x00000000 -#define AR5K_PHY_PLL_RF5112 0x00000040 -#define AR5K_PHY_PLL_HALF_RATE 0x00000100 -#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200 - -/* - * RF Buffer register - * - * It's obvious from the code that 0x989c is the buffer register but - * for the other special registers that we write to after sending each - * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers - * for now. It's interesting that they are also used for some other operations. - */ - -#define AR5K_RF_BUFFER 0x989c -#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */ -#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */ -#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */ - -#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */ - /* Channel set on 5111 */ - /* Used to read radio revision*/ - -#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */ - /* Bank 0,1,2,6 on 5111 */ - /* Bank 1 on 5112 */ - /* Used during activation on 5111 */ - -#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */ - /* Used during activation on 5111 */ - /* Channel on 5112 */ - /* Bank 6 on 5112 */ - -#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */ - -/* - * PHY RF stage register [5210] - */ -#define AR5K_PHY_RFSTG 0x98d4 -#define AR5K_PHY_RFSTG_DISABLE 0x00000021 - -/* - * BIN masks (?) - */ -#define AR5K_PHY_BIN_MASK_1 0x9900 -#define AR5K_PHY_BIN_MASK_2 0x9904 -#define AR5K_PHY_BIN_MASK_3 0x9908 - -#define AR5K_PHY_BIN_MASK_CTL 0x990c -#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff -#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0 -#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000 -#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24 - -/* - * PHY Antenna control register - */ -#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */ -#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */ -#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */ -#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */ -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */ -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4 - -/* - * PHY receiver delay register [5111+] - */ -#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */ -#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */ - -/* - * PHY max rx length register (?) [5111] - */ -#define AR5K_PHY_MAX_RX_LEN 0x991c - -/* - * PHY timing register 4 - * I(nphase)/Q(adrature) calibration register [5111+] - */ -#define AR5K_PHY_IQ 0x9920 /* Register Address */ -#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ -#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ -#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 -#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ -#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */ -#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12 -#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */ -#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */ -#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */ -#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */ -#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */ -#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */ -#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */ - -/* - * PHY timing register 5 - * OFDM Self-correlator Cyclic RSSI threshold params - * (Check out bb_cycpwr_thr1 on ANI patent) - */ -#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */ -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */ -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */ -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1 -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */ -#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */ -#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */ -#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */ - -/* - * PHY-only warm reset register - */ -#define AR5K_PHY_WARM_RESET 0x9928 - -/* - * PHY-only control register - */ -#define AR5K_PHY_CTL 0x992c /* Register Address */ -#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */ -#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */ -#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */ -#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */ -#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */ -#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */ -#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */ -#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */ - -/* - * PHY PAPD probe register [5111+] - */ -#define AR5K_PHY_PAPD_PROBE 0x9930 -#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001 -#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002 -#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040 -#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00 -#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9 -#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000 -#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000 -#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */ -#define AR5K_PHY_PAPD_PROBE_TYPE_S 23 -#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0 -#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1 -#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2 -#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000 -#define AR5K_PHY_PAPD_PROBE_GAINF_S 25 -#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */ -#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */ - -/* - * PHY TX rate power registers [5112+] - */ -#define AR5K_PHY_TXPOWER_RATE1 0x9934 -#define AR5K_PHY_TXPOWER_RATE2 0x9938 -#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c -#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040 -#define AR5K_PHY_TXPOWER_RATE3 0xa234 -#define AR5K_PHY_TXPOWER_RATE4 0xa238 - -/* - * PHY frame control register [5111+] - */ -#define AR5K_PHY_FRAME_CTL_5210 0x9804 -#define AR5K_PHY_FRAME_CTL_5211 0x9944 -#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) -/*---[5111+]---*/ -#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ -#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 -#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ -#define AR5K_PHY_FRAME_CTL_EMU 0x80000000 -#define AR5K_PHY_FRAME_CTL_EMU_S 31 -/*---[5110/5111]---*/ -#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */ -#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */ -#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */ -#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */ -#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000 -#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */ -#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ - AR5K_PHY_FRAME_CTL_TXURN_ERR | \ - AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ - AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \ - AR5K_PHY_FRAME_CTL_PARITY_ERR | \ - AR5K_PHY_FRAME_CTL_TIMING_ERR - -/* - * PHY Tx Power adjustment register [5212A+] - */ -#define AR5K_PHY_TX_PWR_ADJ 0x994c -#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0 -#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6 -#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000 -#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18 - -/* - * PHY radar detection register [5111+] - */ -#define AR5K_PHY_RADAR 0x9954 -#define AR5K_PHY_RADAR_ENABLE 0x00000001 -#define AR5K_PHY_RADAR_DISABLE 0x00000000 -#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold - 5-bits, units unknown {0..31} - (? MHz ?) */ -#define AR5K_PHY_RADAR_INBANDTHR_S 1 - -#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold - 6-bits, dBm range {0..63} - in dBm units. */ -#define AR5K_PHY_RADAR_PRSSI_THR_S 6 - -#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold - 6-bits, dBm range {0..63} - in dBm units. */ -#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12 - -#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold. - 6-bits, dBm range {0..63} - in dBm units. */ -#define AR5K_PHY_RADAR_RSSI_THR_S 18 - -#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response - filter power out threshold. - 7-bits, standard power range - {0..127} in 1/2 dBm units. */ -#define AR5K_PHY_RADAR_FIRPWR_THRS 24 - -/* - * PHY antenna switch table registers - */ -#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960 -#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964 - -/* - * PHY Noise floor threshold - */ -#define AR5K_PHY_NFTHRES 0x9968 - -/* - * Sigma Delta register (?) [5213] - */ -#define AR5K_PHY_SIGMA_DELTA 0x996C -#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 -#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0 -#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8 -#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3 -#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00 -#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8 -#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000 -#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13 - -/* - * RF restart register [5112+] (?) - */ -#define AR5K_PHY_RESTART 0x9970 /* restart */ -#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */ -#define AR5K_PHY_RESTART_DIV_GC_S 18 - -/* - * RF Bus access request register (for synth-oly channel switching) - */ -#define AR5K_PHY_RFBUS_REQ 0x997C -#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001 - -/* - * Spur mitigation masks (?) - */ -#define AR5K_PHY_TIMING_7 0x9980 -#define AR5K_PHY_TIMING_8 0x9984 -#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff -#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0 - -#define AR5K_PHY_BIN_MASK2_1 0x9988 -#define AR5K_PHY_BIN_MASK2_2 0x998c -#define AR5K_PHY_BIN_MASK2_3 0x9990 - -#define AR5K_PHY_BIN_MASK2_4 0x9994 -#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff -#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0 - -#define AR5K_PHY_TIMING_9 0x9998 -#define AR5K_PHY_TIMING_10 0x999c -#define AR5K_PHY_TIMING_10_PILOT_MASK_2 0x000fffff -#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S 0 - -/* - * Spur mitigation control - */ -#define AR5K_PHY_TIMING_11 0x99a0 /* Register address */ -#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */ -#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0 -#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */ -#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S 20 -#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */ -#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */ - -/* - * Gain tables - */ -#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ -#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2)) -#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */ -#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2)) - -/* - * PHY timing IQ calibration result register [5111+] - */ -#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */ -#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */ -#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */ - -/* - * PHY current RSSI register [5111+] - */ -#define AR5K_PHY_CURRENT_RSSI 0x9c1c - -/* - * PHY RF Bus grant register - */ -#define AR5K_PHY_RFBUS_GRANT 0x9c20 -#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001 - -/* - * PHY ADC test register - */ -#define AR5K_PHY_ADC_TEST 0x9c24 -#define AR5K_PHY_ADC_TEST_I 0x00000001 -#define AR5K_PHY_ADC_TEST_Q 0x00000200 - -/* - * PHY DAC test register - */ -#define AR5K_PHY_DAC_TEST 0x9c28 -#define AR5K_PHY_DAC_TEST_I 0x00000001 -#define AR5K_PHY_DAC_TEST_Q 0x00000200 - -/* - * PHY PTAT register (?) - */ -#define AR5K_PHY_PTAT 0x9c2c - -/* - * PHY Illegal TX rate register [5112+] - */ -#define AR5K_PHY_BAD_TX_RATE 0x9c30 - -/* - * PHY SPUR Power register [5112+] - */ -#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */ -#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */ -#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */ -#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */ - -/* - * PHY Channel status register [5112+] (?) - */ -#define AR5K_PHY_CHAN_STATUS 0x9c38 -#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001 -#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002 -#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004 -#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008 - -/* - * Heavy clip enable register - */ -#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0 - -/* - * PHY clock sleep registers [5112+] - */ -#define AR5K_PHY_SCLOCK 0x99f0 -#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c -#define AR5K_PHY_SDELAY 0x99f4 -#define AR5K_PHY_SDELAY_32MHZ 0x000000ff -#define AR5K_PHY_SPENDING 0x99f8 - - -/* - * PHY PAPD I (power?) table (?) - * (92! entries) - */ -#define AR5K_PHY_PAPD_I_BASE 0xa000 -#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2)) - -/* - * PHY PCDAC TX power table - */ -#define AR5K_PHY_PCDAC_TXPOWER_BASE 0xa180 -#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2)) - -/* - * PHY mode register [5111+] - */ -#define AR5K_PHY_MODE 0x0a200 /* Register Address */ -#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */ -#define AR5K_PHY_MODE_MOD_OFDM 0 -#define AR5K_PHY_MODE_MOD_CCK 1 -#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */ -#define AR5K_PHY_MODE_FREQ_5GHZ 0 -#define AR5K_PHY_MODE_FREQ_2GHZ 2 -#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */ -#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */ -#define AR5K_PHY_MODE_RAD_RF5111 0 -#define AR5K_PHY_MODE_RAD_RF5112 8 -#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */ -#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */ -#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */ - -/* - * PHY CCK transmit control register [5111+ (?)] - */ -#define AR5K_PHY_CCKTXCTL 0xa204 -#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000 -#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010 -#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001 -#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004 - -/* - * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] - */ -#define AR5K_PHY_CCK_CROSSCORR 0xa208 -#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f -#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 - -/* Same address is used for antenna diversity activation */ -#define AR5K_PHY_FAST_ANT_DIV 0xa208 -#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000 - -/* - * PHY 2GHz gain register [5111+] - */ -#define AR5K_PHY_GAIN_2GHZ 0xa20c -#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 -#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18 -#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c - -#define AR5K_PHY_CCK_RX_CTL_4 0xa21c -#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000 -#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19 - -#define AR5K_PHY_DAG_CCK_CTL 0xa228 -#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200 -#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00 -#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10 - -#define AR5K_PHY_FAST_ADC 0xa24c - -#define AR5K_PHY_BLUETOOTH 0xa254 - -/* - * Transmit Power Control register - * [2413+] - */ -#define AR5K_PHY_TPC_RG1 0xa258 -#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000 -#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14 -#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000 -#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16 -#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000 -#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18 -#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000 -#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20 - -#define AR5K_PHY_TPC_RG5 0xa26C -#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F -#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22 - -/* - * PHY PDADC Tx power table - */ -#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 -#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c deleted file mode 100644 index 775fdf78554b..000000000000 --- a/drivers/net/wireless/ath5k/reset.c +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#define _ATH5K_RESET - -/*****************************\ - Reset functions and helpers -\*****************************/ - -#include /* To determine if a card is pci-e */ -#include /* For get_bitmask_order */ -#include "ath5k.h" -#include "reg.h" -#include "base.h" -#include "debug.h" - -/** - * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 - * - * @ah: the &struct ath5k_hw - * @channel: the currently set channel upon reset - * - * Write the delta slope coefficient (used on pilot tracking ?) for OFDM - * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). - * - * Since delta slope is floating point we split it on its exponent and - * mantissa and provide these values on hw. - * - * For more infos i think this patent is related - * http://www.freepatentsonline.com/7184495.html - */ -static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - /* Get exponent and mantissa and set it */ - u32 coef_scaled, coef_exp, coef_man, - ds_coef_exp, ds_coef_man, clock; - - BUG_ON(!(ah->ah_version == AR5K_AR5212) || - !(channel->hw_value & CHANNEL_OFDM)); - - /* Get coefficient - * ALGO: coef = (5 * clock * carrier_freq) / 2) - * we scale coef by shifting clock value by 24 for - * better precision since we use integers */ - /* TODO: Half/quarter rate */ - clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); - - coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; - - /* Get exponent - * ALGO: coef_exp = 14 - highest set bit position */ - coef_exp = get_bitmask_order(coef_scaled); - - /* Doesn't make sense if it's zero*/ - if (!coef_exp) - return -EINVAL; - - /* Note: we've shifted coef_scaled by 24 */ - coef_exp = 14 - (coef_exp - 24); - - - /* Get mantissa (significant digits) - * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ - coef_man = coef_scaled + - (1 << (24 - coef_exp - 1)); - - /* Calculate delta slope coefficient exponent - * and mantissa (remove scaling) and set them on hw */ - ds_coef_man = coef_man >> (24 - coef_exp); - ds_coef_exp = coef_exp - 16; - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); - - return 0; -} - - -/* - * index into rates for control rates, we can set it up like this because - * this is only used for AR5212 and we know it supports G mode - */ -static const unsigned int control_rates[] = - { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; - -/** - * ath5k_hw_write_rate_duration - fill rate code to duration table - * - * @ah: the &struct ath5k_hw - * @mode: one of enum ath5k_driver_mode - * - * Write the rate code to duration table upon hw reset. This is a helper for - * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on - * the hardware, based on current mode, for each rate. The rates which are - * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have - * different rate code so we write their value twice (one for long preample - * and one for short). - * - * Note: Band doesn't matter here, if we set the values for OFDM it works - * on both a and g modes. So all we have to do is set values for all g rates - * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ - * quarter rate mode, we need to use another set of bitrates (that's why we - * need the mode parameter) but we don't handle these proprietary modes yet. - */ -static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, - unsigned int mode) -{ - struct ath5k_softc *sc = ah->ah_sc; - struct ieee80211_rate *rate; - unsigned int i; - - /* Write rate duration table */ - for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { - u32 reg; - u16 tx_time; - - rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; - - /* Set ACK timeout */ - reg = AR5K_RATE_DUR(rate->hw_value); - - /* An ACK frame consists of 10 bytes. If you add the FCS, - * which ieee80211_generic_frame_duration() adds, - * its 14 bytes. Note we use the control rate and not the - * actual rate for this rate. See mac80211 tx.c - * ieee80211_duration() for a brief description of - * what rate we should choose to TX ACKs. */ - tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, - sc->vif, 10, rate)); - - ath5k_hw_reg_write(ah, tx_time, reg); - - if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) - continue; - - /* - * We're not distinguishing short preamble here, - * This is true, all we'll get is a longer value here - * which is not necessarilly bad. We could use - * export ieee80211_frame_duration() but that needs to be - * fixed first to be properly used by mac802111 drivers: - * - * - remove erp stuff and let the routine figure ofdm - * erp rates - * - remove passing argument ieee80211_local as - * drivers don't have access to it - * - move drivers using ieee80211_generic_frame_duration() - * to this - */ - ath5k_hw_reg_write(ah, tx_time, - reg + (AR5K_SET_SHORT_PREAMBLE << 2)); - } -} - -/* - * Reset chipset - */ -static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) -{ - int ret; - u32 mask = val ? val : ~0U; - - ATH5K_TRACE(ah->ah_sc); - - /* Read-and-clear RX Descriptor Pointer*/ - ath5k_hw_reg_read(ah, AR5K_RXDP); - - /* - * Reset the device and wait until success - */ - ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); - - /* Wait at least 128 PCI clocks */ - udelay(15); - - if (ah->ah_version == AR5K_AR5210) { - val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA - | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; - mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA - | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; - } else { - val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; - mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; - } - - ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); - - /* - * Reset configuration register (for hw byte-swap). Note that this - * is only set for big endian. We do the necessary magic in - * AR5K_INIT_CFG. - */ - if ((val & AR5K_RESET_CTL_PCU) == 0) - ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); - - return ret; -} - -/* - * Sleep control - */ -int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, - bool set_chip, u16 sleep_duration) -{ - unsigned int i; - u32 staid, data; - - ATH5K_TRACE(ah->ah_sc); - staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); - - switch (mode) { - case AR5K_PM_AUTO: - staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; - /* fallthrough */ - case AR5K_PM_NETWORK_SLEEP: - if (set_chip) - ath5k_hw_reg_write(ah, - AR5K_SLEEP_CTL_SLE_ALLOW | - sleep_duration, - AR5K_SLEEP_CTL); - - staid |= AR5K_STA_ID1_PWR_SV; - break; - - case AR5K_PM_FULL_SLEEP: - if (set_chip) - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, - AR5K_SLEEP_CTL); - - staid |= AR5K_STA_ID1_PWR_SV; - break; - - case AR5K_PM_AWAKE: - - staid &= ~AR5K_STA_ID1_PWR_SV; - - if (!set_chip) - goto commit; - - /* Preserve sleep duration */ - data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); - if (data & 0xffc00000) - data = 0; - else - data = data & 0xfffcffff; - - ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); - udelay(15); - - for (i = 50; i > 0; i--) { - /* Check if the chip did wake up */ - if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & - AR5K_PCICFG_SPWR_DN) == 0) - break; - - /* Wait a bit and retry */ - udelay(200); - ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); - } - - /* Fail if the chip didn't wake up */ - if (i <= 0) - return -EIO; - - break; - - default: - return -EINVAL; - } - -commit: - ah->ah_power_mode = mode; - ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); - - return 0; -} - -/* - * Bring up MAC + PHY Chips and program PLL - * TODO: Half/Quarter rate support - */ -int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) -{ - struct pci_dev *pdev = ah->ah_sc->pdev; - u32 turbo, mode, clock, bus_flags; - int ret; - - turbo = 0; - mode = 0; - clock = 0; - - ATH5K_TRACE(ah->ah_sc); - - /* Wakeup the device */ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); - return ret; - } - - if (ah->ah_version != AR5K_AR5210) { - /* - * Get channel mode flags - */ - - if (ah->ah_radio >= AR5K_RF5112) { - mode = AR5K_PHY_MODE_RAD_RF5112; - clock = AR5K_PHY_PLL_RF5112; - } else { - mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ - clock = AR5K_PHY_PLL_RF5111; /*Zero*/ - } - - if (flags & CHANNEL_2GHZ) { - mode |= AR5K_PHY_MODE_FREQ_2GHZ; - clock |= AR5K_PHY_PLL_44MHZ; - - if (flags & CHANNEL_CCK) { - mode |= AR5K_PHY_MODE_MOD_CCK; - } else if (flags & CHANNEL_OFDM) { - /* XXX Dynamic OFDM/CCK is not supported by the - * AR5211 so we set MOD_OFDM for plain g (no - * CCK headers) operation. We need to test - * this, 5211 might support ofdm-only g after - * all, there are also initial register values - * in the code for g mode (see initvals.c). */ - if (ah->ah_version == AR5K_AR5211) - mode |= AR5K_PHY_MODE_MOD_OFDM; - else - mode |= AR5K_PHY_MODE_MOD_DYN; - } else { - ATH5K_ERR(ah->ah_sc, - "invalid radio modulation mode\n"); - return -EINVAL; - } - } else if (flags & CHANNEL_5GHZ) { - mode |= AR5K_PHY_MODE_FREQ_5GHZ; - - if (ah->ah_radio == AR5K_RF5413) - clock = AR5K_PHY_PLL_40MHZ_5413; - else - clock |= AR5K_PHY_PLL_40MHZ; - - if (flags & CHANNEL_OFDM) - mode |= AR5K_PHY_MODE_MOD_OFDM; - else { - ATH5K_ERR(ah->ah_sc, - "invalid radio modulation mode\n"); - return -EINVAL; - } - } else { - ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); - return -EINVAL; - } - - if (flags & CHANNEL_TURBO) - turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; - } else { /* Reset the device */ - - /* ...enable Atheros turbo mode if requested */ - if (flags & CHANNEL_TURBO) - ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, - AR5K_PHY_TURBO); - } - - /* reseting PCI on PCI-E cards results card to hang - * and always return 0xffff... so we ingore that flag - * for PCI-E cards */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; - - /* Reset chipset */ - if (ah->ah_version == AR5K_AR5210) { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | - AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - mdelay(2); - } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); - } - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); - return -EIO; - } - - /* ...wakeup again!*/ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); - return ret; - } - - /* ...final warm reset */ - if (ath5k_hw_nic_reset(ah, 0)) { - ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); - return -EIO; - } - - if (ah->ah_version != AR5K_AR5210) { - - /* ...update PLL if needed */ - if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { - ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); - udelay(300); - } - - /* ...set the PHY operating mode */ - ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); - ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); - } - - return 0; -} - -/* - * If there is an external 32KHz crystal available, use it - * as ref. clock instead of 32/40MHz clock and baseband clocks - * to save power during sleep or restore normal 32/40MHz - * operation. - * - * XXX: When operating on 32KHz certain PHY registers (27 - 31, - * 123 - 127) require delay on access. - */ -static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 scal, spending, usec32; - - /* Only set 32KHz settings if we have an external - * 32KHz crystal present */ - if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || - AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && - enable) { - - /* 1 usec/cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); - /* Set up tsf increment on each cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - - /* Set baseband sleep control registers - * and sleep control rate */ - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); - } else { - ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); - } - - /* Enable sleep clock operation */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - } else { - - /* Disable sleep clock operation and - * restore default parameters */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); - - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); - - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ath5k_eeprom_is_hb63(ah)) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - - ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413)) - usec32 = 39; - else - usec32 = 31; - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); - - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); - } - return; -} - -static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u8 refclk_freq; - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - refclk_freq = 40; - else - refclk_freq = 32; - - if ((channel->center_freq % refclk_freq != 0) && - ((channel->center_freq % refclk_freq < 10) || - (channel->center_freq % refclk_freq > 22))) - return true; - else - return false; -} - -/* TODO: Half/Quarter rate */ -static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - - /* Setup ADC control */ - ath5k_hw_reg_write(ah, - (AR5K_REG_SM(2, - AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) | - AR5K_REG_SM(2, - AR5K_PHY_ADC_CTL_INBUFGAIN_ON) | - AR5K_PHY_ADC_CTL_PWD_DAC_OFF | - AR5K_PHY_ADC_CTL_PWD_ADC_OFF), - AR5K_PHY_ADC_CTL); - - - - /* Disable barker RSSI threshold */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, - AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, - AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2); - - /* Set the mute mask */ - ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); - } - - /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B) - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH); - - /* Enable DCU double buffering */ - if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B) - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_DCU_DBL_BUF_DIS); - - /* Set DAC/ADC delays */ - if (ah->ah_version == AR5K_AR5212) { - u32 scal; - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ath5k_eeprom_is_hb63(ah)) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - } - - /* Set fast ADC */ - if ((ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - u32 fast_adc = true; - - if (channel->center_freq == 2462 || - channel->center_freq == 2467) - fast_adc = 0; - - /* Only update if needed */ - if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc) - ath5k_hw_reg_write(ah, fast_adc, - AR5K_PHY_FAST_ADC); - } - - /* Fix for first revision of the RF5112 RF chipset */ - if (ah->ah_radio == AR5K_RF5112 && - ah->ah_radio_5ghz_revision < - AR5K_SREV_RAD_5112A) { - u32 data; - ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, - AR5K_PHY_CCKTXCTL); - if (channel->hw_value & CHANNEL_5GHZ) - data = 0xffb81020; - else - data = 0xffb80d20; - ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); - } - - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - u32 usec_reg; - /* 5311 has different tx/rx latency masks - * from 5211, since we deal 5311 the same - * as 5211 when setting initvals, shift - * values here to their proper locations */ - usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); - ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | - AR5K_USEC_32 | - AR5K_USEC_TX_LATENCY_5211 | - AR5K_REG_SM(29, - AR5K_USEC_RX_LATENCY_5210)), - AR5K_USEC_5211); - /* Clear QCU/DCU clock gating register */ - ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); - /* Set DAC/ADC delays */ - ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); - /* Enable PCU FIFO corruption ECO */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_ECO_ENABLE); - } -} - -static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - s16 cck_ofdm_pwr_delta; - - /* Adjust power delta for channel 14 */ - if (channel->center_freq == 2484) - cck_ofdm_pwr_delta = - ((ee->ee_cck_ofdm_power_delta - - ee->ee_scaled_cck_delta) * 2) / 10; - else - cck_ofdm_pwr_delta = - (ee->ee_cck_ofdm_power_delta * 2) / 10; - - /* Set CCK to OFDM power delta on tx power - * adjustment register */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - if (channel->hw_value == CHANNEL_G) - ath5k_hw_reg_write(ah, - AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), - AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | - AR5K_REG_SM((cck_ofdm_pwr_delta * -1), - AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), - AR5K_PHY_TX_PWR_ADJ); - else - ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); - } else { - /* For older revs we scale power on sw during tx power - * setup */ - ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta; - ah->ah_txpower.txp_cck_ofdm_gainf_delta = - ee->ee_cck_ofdm_gain_delta; - } - - /* Set antenna idle switch table */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, - AR5K_PHY_ANT_CTL_SWTABLE_IDLE, - (ah->ah_antenna[ee_mode][0] | - AR5K_PHY_ANT_CTL_TXRX_EN)); - - /* Set antenna switch table */ - ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], - AR5K_PHY_ANT_SWITCH_TABLE_0); - ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], - AR5K_PHY_ANT_SWITCH_TABLE_1); - - /* Noise floor threshold */ - ath5k_hw_reg_write(ah, - AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), - AR5K_PHY_NFTHRES); - - if ((channel->hw_value & CHANNEL_TURBO) && - (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { - /* Switch settling time (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - ee->ee_switch_settling_turbo[ee_mode]); - - /* Tx/Rx attenuation (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, - AR5K_PHY_GAIN_TXRX_ATTEN, - ee->ee_atn_tx_rx_turbo[ee_mode]); - - /* ADC/PGA desired size (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_ADC, - ee->ee_adc_desired_size_turbo[ee_mode]); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_PGA, - ee->ee_pga_desired_size_turbo[ee_mode]); - - /* Tx/Rx margin (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, - AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, - ee->ee_margin_tx_rx_turbo[ee_mode]); - - } else { - /* Switch settling time */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - ee->ee_switch_settling[ee_mode]); - - /* Tx/Rx attenuation */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, - AR5K_PHY_GAIN_TXRX_ATTEN, - ee->ee_atn_tx_rx[ee_mode]); - - /* ADC/PGA desired size */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_ADC, - ee->ee_adc_desired_size[ee_mode]); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_PGA, - ee->ee_pga_desired_size[ee_mode]); - - /* Tx/Rx margin */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, - AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, - ee->ee_margin_tx_rx[ee_mode]); - } - - /* XPA delays */ - ath5k_hw_reg_write(ah, - (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | - (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | - (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | - (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); - - /* XLNA delay */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3, - AR5K_PHY_RF_CTL3_TXE2XLNA_ON, - ee->ee_tx_end2xlna_enable[ee_mode]); - - /* Thresh64 (ANI) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF, - AR5K_PHY_NF_THRESH62, - ee->ee_thr_62[ee_mode]); - - - /* False detect backoff for channels - * that have spur noise. Write the new - * cyclic power RSSI threshold. */ - if (ath5k_hw_chan_has_spur_noise(ah, channel)) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, - AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, - AR5K_INIT_CYCRSSI_THR1 + - ee->ee_false_detect[ee_mode]); - else - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, - AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, - AR5K_INIT_CYCRSSI_THR1); - - /* I/Q correction - * TODO: Per channel i/q infos ? */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CORR_ENABLE | - (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | - ee->ee_q_cal[ee_mode]); - - /* Heavy clipping -disable for now */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) - ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); - - return; -} - -/* - * Main reset function - */ -int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool change_channel) -{ - u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; - u32 phy_tst1; - u8 mode, freq, ee_mode, ant[2]; - int i, ret; - - ATH5K_TRACE(ah->ah_sc); - - s_ant = 0; - ee_mode = 0; - staid1_flags = 0; - tsf_up = 0; - tsf_lo = 0; - freq = 0; - mode = 0; - - /* - * Save some registers before a reset - */ - /*DCU/Antenna selection not available on 5210*/ - if (ah->ah_version != AR5K_AR5210) { - - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - mode = AR5K_MODE_11A; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - mode = AR5K_MODE_11G; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - mode = AR5K_MODE_11B; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11B; - break; - case CHANNEL_T: - mode = AR5K_MODE_11A_TURBO; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_TG: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "TurboG mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_11G_TURBO; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_XR: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "XR mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_XR; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - default: - ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); - return -EINVAL; - } - - if (change_channel) { - /* - * Save frame sequence count - * For revs. after Oahu, only save - * seq num for DCU 0 (Global seq num) - */ - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - - for (i = 0; i < 10; i++) - s_seq[i] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(i)); - - } else { - s_seq[0] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - /* TSF accelerates on AR5211 durring reset - * As a workaround save it here and restore - * it later so that it's back in time after - * reset. This way it'll get re-synced on the - * next beacon without breaking ad-hoc. - * - * On AR5212 TSF is almost preserved across a - * reset so it stays back in time anyway and - * we don't have to save/restore it. - * - * XXX: Since this breaks power saving we have - * to disable power saving until we receive the - * next beacon, so we can resync beacon timers */ - if (ah->ah_version == AR5K_AR5211) { - tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); - } - } - - /* Save default antenna */ - s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); - - if (ah->ah_version == AR5K_AR5212) { - /* Restore normal 32/40MHz clock operation - * to avoid register access delay on certain - * PHY registers */ - ath5k_hw_set_sleep_clock(ah, false); - - /* Since we are going to write rf buffer - * check if we have any pending gain_F - * optimization settings */ - if (change_channel && ah->ah_rf_banks != NULL) - ath5k_hw_gainf_calibrate(ah); - } - } - - /*GPIOs*/ - s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & - AR5K_PCICFG_LEDSTATE; - s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); - s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - - /* AR5K_STA_ID1 flags, only preserve antenna - * settings and ack/cts rate mode */ - staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & - (AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_DESC_ANTENNA | - AR5K_STA_ID1_RTS_DEF_ANTENNA | - AR5K_STA_ID1_ACKCTS_6MB | - AR5K_STA_ID1_BASE_RATE_11B | - AR5K_STA_ID1_SELFGEN_DEF_ANT); - - /* Wakeup the device */ - ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); - if (ret) - return ret; - - /* - * Initialize operating mode - */ - ah->ah_op_mode = op_mode; - - /* PHY access enable */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5211) - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - else - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40, - AR5K_PHY(0)); - - /* Write initial settings */ - ret = ath5k_hw_write_initvals(ah, mode, change_channel); - if (ret) - return ret; - - /* - * 5211/5212 Specific - */ - if (ah->ah_version != AR5K_AR5210) { - - /* - * Write initial RF gain settings - * This should work for both 5111/5112 - */ - ret = ath5k_hw_rfgain_init(ah, freq); - if (ret) - return ret; - - mdelay(1); - - /* - * Tweak initval settings for revised - * chipsets and add some more config - * bits - */ - ath5k_hw_tweak_initval_settings(ah, channel); - - /* - * Set TX power (FIXME) - */ - ret = ath5k_hw_txpower(ah, channel, ee_mode, - AR5K_TUNE_DEFAULT_TXPOWER); - if (ret) - return ret; - - /* Write rate duration table only on AR5212 and if - * virtual interface has already been brought up - * XXX: rethink this after new mode changes to - * mac80211 are integrated */ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_sc->vif != NULL) - ath5k_hw_write_rate_duration(ah, mode); - - /* - * Write RF buffer - */ - ret = ath5k_hw_rfregs_init(ah, channel, mode); - if (ret) - return ret; - - - /* Write OFDM timings on 5212*/ - if (ah->ah_version == AR5K_AR5212 && - channel->hw_value & CHANNEL_OFDM) { - ret = ath5k_hw_write_ofdm_timings(ah, channel); - if (ret) - return ret; - } - - /*Enable/disable 802.11b mode on 5111 - (enable 2111 frequency converter + CCK)*/ - if (ah->ah_radio == AR5K_RF5111) { - if (mode == AR5K_MODE_11B) - AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - } - - /* - * In case a fixed antenna was set as default - * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE - * registers. - */ - if (s_ant != 0) { - if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ - ant[0] = ant[1] = AR5K_ANT_FIXED_A; - else /* 2 - Aux */ - ant[0] = ant[1] = AR5K_ANT_FIXED_B; - } else { - ant[0] = AR5K_ANT_FIXED_A; - ant[1] = AR5K_ANT_FIXED_B; - } - - /* Commit values from EEPROM */ - ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode); - - } else { - /* - * For 5210 we do all initialization using - * initvals, so we don't have to modify - * any settings (5210 also only supports - * a/aturbo modes) - */ - mdelay(1); - /* Disable phy and wait */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - mdelay(1); - } - - /* - * Restore saved values - */ - - /*DCU/Antenna selection not available on 5210*/ - if (ah->ah_version != AR5K_AR5210) { - - if (change_channel) { - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - for (i = 0; i < 10; i++) - ath5k_hw_reg_write(ah, s_seq[i], - AR5K_QUEUE_DCU_SEQNUM(i)); - } else { - ath5k_hw_reg_write(ah, s_seq[0], - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - - if (ah->ah_version == AR5K_AR5211) { - ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); - ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); - } - } - - ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); - } - - /* Ledstate */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); - - /* Gpio settings */ - ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); - ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); - - /* Restore sta_id flags and preserve our mac address*/ - ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id), - AR5K_STA_ID0); - ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id), - AR5K_STA_ID1); - - - /* - * Configure PCU - */ - - /* Restore bssid and bssid mask */ - /* XXX: add ah->aid once mac80211 gives this to us */ - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - - /* Set PCU config */ - ath5k_hw_set_opmode(ah); - - /* Clear any pending interrupts - * PISR/SISR Not available on 5210 */ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); - - /* Set RSSI/BRSSI thresholds - * - * Note: If we decide to set this value - * dynamicaly, have in mind that when AR5K_RSSI_THR - * register is read it might return 0x40 if we haven't - * wrote anything to it plus BMISS RSSI threshold is zeroed. - * So doing a save/restore procedure here isn't the right - * choice. Instead store it on ath5k_hw */ - ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | - AR5K_TUNE_BMISS_THRES << - AR5K_RSSI_THR_BMISS_S), - AR5K_RSSI_THR); - - /* MIC QoS support */ - if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { - ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); - ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); - } - - /* QoS NOACK Policy */ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, - AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | - AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | - AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), - AR5K_QOS_NOACK); - } - - - /* - * Configure PHY - */ - - /* Set channel on PHY */ - ret = ath5k_hw_channel(ah, channel); - if (ret) - return ret; - - /* - * Enable the PHY and wait until completion - * This includes BaseBand and Synthesizer - * activation. - */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - - /* - * On 5211+ read activation -> rx delay - * and use it. - * - * TODO: Half/quarter rate support - */ - if (ah->ah_version != AR5K_AR5210) { - u32 delay; - delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & - AR5K_PHY_RX_DELAY_M; - delay = (channel->hw_value & CHANNEL_CCK) ? - ((delay << 2) / 22) : (delay / 10); - - udelay(100 + (2 * delay)); - } else { - mdelay(1); - } - - /* - * Perform ADC test to see if baseband is ready - * Set tx hold and check adc test register - */ - phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); - ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); - for (i = 0; i <= 20; i++) { - if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) - break; - udelay(200); - } - ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); - - /* - * Start automatic gain control calibration - * - * During AGC calibration RX path is re-routed to - * a power detector so we don't receive anything. - * - * This method is used to calibrate some static offsets - * used together with on-the fly I/Q calibration (the - * one performed via ath5k_hw_phy_calibrate), that doesn't - * interrupt rx path. - * - * While rx path is re-routed to the power detector we also - * start a noise floor calibration, to measure the - * card's noise floor (the noise we measure when we are not - * transmiting or receiving anything). - * - * If we are in a noisy environment AGC calibration may time - * out and/or noise floor calibration might timeout. - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL); - - /* At the same time start I/Q calibration for QAM constellation - * -no need for CCK- */ - ah->ah_calibration = false; - if (!(mode == AR5K_MODE_11B)) { - ah->ah_calibration = true; - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_RUN); - } - - /* Wait for gain calibration to finish (we check for I/Q calibration - * during ath5k_phy_calibrate) */ - if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", - channel->center_freq); - } - - /* - * If we run NF calibration before AGC, it always times out. - * Binary HAL starts NF and AGC calibration at the same time - * and only waits for AGC to finish. Also if AGC or NF cal. - * times out, reset doesn't fail on binary HAL. I believe - * that's wrong because since rx path is routed to a detector, - * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211 - * enables noise floor calibration after offset calibration and if noise - * floor calibration fails, reset fails. I believe that's - * a better approach, we just need to find a polling interval - * that suits best, even if reset continues we need to make - * sure that rx path is ready. - */ - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - - - /* - * Configure QCUs/DCUs - */ - - /* TODO: HW Compression support for data queues */ - /* TODO: Burst prefetch for data queues */ - - /* - * Reset queues and start beacon timers at the end of the reset routine - * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping - * Note: If we want we can assign multiple qcus on one dcu. - */ - for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { - ret = ath5k_hw_reset_tx_queue(ah, i); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "failed to reset TX queue #%d\n", i); - return ret; - } - } - - - /* - * Configure DMA/Interrupts - */ - - /* - * Set Rx/Tx DMA Configuration - * - * Set standard DMA size (128). Note that - * a DMA size of 512 causes rx overruns and tx errors - * on pci-e cards (tested on 5424 but since rx overruns - * also occur on 5416/5418 with madwifi we set 128 - * for all PCI-E cards to be safe). - * - * XXX: need to check 5210 for this - * TODO: Check out tx triger level, it's always 64 on dumps but I - * guess we can tweak it and see how it goes ;-) - */ - if (ah->ah_version != AR5K_AR5210) { - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); - AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, - AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); - } - - /* Pre-enable interrupts on 5211/5212*/ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_set_imr(ah, ah->ah_imr); - - /* - * Setup RFKill interrupt if rfkill flag is set on eeprom. - * TODO: Use gpio pin and polarity infos from eeprom - * TODO: Handle this in ath5k_intr because it'll result - * a nasty interrupt storm. - */ -#if 0 - if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) { - ath5k_hw_set_gpio_input(ah, 0); - ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0); - if (ah->ah_gpio[0] == 0) - ath5k_hw_set_gpio_intr(ah, 0, 1); - else - ath5k_hw_set_gpio_intr(ah, 0, 0); - } -#endif - - /* Enable 32KHz clock function for AR5212+ chips - * Set clocks to 32KHz operation and use an - * external 32KHz crystal when sleeping if one - * exists */ - if (ah->ah_version == AR5K_AR5212) - ath5k_hw_set_sleep_clock(ah, true); - - /* - * Disable beacons and reset the register - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | - AR5K_BEACON_RESET_TSF); - - return 0; -} - -#undef _ATH5K_RESET diff --git a/drivers/net/wireless/ath5k/rfbuffer.h b/drivers/net/wireless/ath5k/rfbuffer.h deleted file mode 100644 index e50baff66175..000000000000 --- a/drivers/net/wireless/ath5k/rfbuffer.h +++ /dev/null @@ -1,1181 +0,0 @@ -/* - * RF Buffer handling functions - * - * Copyright (c) 2009 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - - -/* - * There are some special registers on the RF chip - * that control various operation settings related mostly to - * the analog parts (channel, gain adjustment etc). - * - * We don't write on those registers directly but - * we send a data packet on the chip, using a special register, - * that holds all the settings we need. After we 've sent the - * data packet, we write on another special register to notify hw - * to apply the settings. This is done so that control registers - * can be dynamicaly programmed during operation and the settings - * are applied faster on the hw. - * - * We call each data packet an "RF Bank" and all the data we write - * (all RF Banks) "RF Buffer". This file holds initial RF Buffer - * data for the different RF chips, and various info to match RF - * Buffer offsets with specific RF registers so that we can access - * them. We tweak these settings on rfregs_init function. - * - * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer - * registers and control registers): - * - * http://www.google.com/patents?id=qNURAAAAEBAJ - */ - - -/* - * Struct to hold default mode specific RF - * register values (RF Banks) - */ -struct ath5k_ini_rfbuffer { - u8 rfb_bank; /* RF Bank number */ - u16 rfb_ctrl_register; /* RF Buffer control register */ - u32 rfb_mode_data[5]; /* RF Buffer data for each mode */ -}; - -/* - * Struct to hold RF Buffer field - * infos used to access certain RF - * analog registers - */ -struct ath5k_rfb_field { - u8 len; /* Field length */ - u16 pos; /* Offset on the raw packet */ - u8 col; /* Column -used for shifting */ -}; - -/* - * RF analog register definition - */ -struct ath5k_rf_reg { - u8 bank; /* RF Buffer Bank number */ - u8 index; /* Register's index on rf_regs_idx */ - struct ath5k_rfb_field field; /* RF Buffer field for this register */ -}; - -/* Map RF registers to indexes - * We do this to handle common bits and make our - * life easier by using an index for each register - * instead of a full rfb_field */ -enum ath5k_rf_regs_idx { - /* BANK 6 */ - AR5K_RF_OB_2GHZ = 0, - AR5K_RF_OB_5GHZ, - AR5K_RF_DB_2GHZ, - AR5K_RF_DB_5GHZ, - AR5K_RF_FIXED_BIAS_A, - AR5K_RF_FIXED_BIAS_B, - AR5K_RF_PWD_XPD, - AR5K_RF_XPD_SEL, - AR5K_RF_XPD_GAIN, - AR5K_RF_PD_GAIN_LO, - AR5K_RF_PD_GAIN_HI, - AR5K_RF_HIGH_VC_CP, - AR5K_RF_MID_VC_CP, - AR5K_RF_LOW_VC_CP, - AR5K_RF_PUSH_UP, - AR5K_RF_PAD2GND, - AR5K_RF_XB2_LVL, - AR5K_RF_XB5_LVL, - AR5K_RF_PWD_ICLOBUF_2G, - AR5K_RF_PWD_84, - AR5K_RF_PWD_90, - AR5K_RF_PWD_130, - AR5K_RF_PWD_131, - AR5K_RF_PWD_132, - AR5K_RF_PWD_136, - AR5K_RF_PWD_137, - AR5K_RF_PWD_138, - AR5K_RF_PWD_166, - AR5K_RF_PWD_167, - AR5K_RF_DERBY_CHAN_SEL_MODE, - /* BANK 7 */ - AR5K_RF_GAIN_I, - AR5K_RF_PLO_SEL, - AR5K_RF_RFGAIN_SEL, - AR5K_RF_RFGAIN_STEP, - AR5K_RF_WAIT_S, - AR5K_RF_WAIT_I, - AR5K_RF_MAX_TIME, - AR5K_RF_MIXVGA_OVR, - AR5K_RF_MIXGAIN_OVR, - AR5K_RF_MIXGAIN_STEP, - AR5K_RF_PD_DELAY_A, - AR5K_RF_PD_DELAY_B, - AR5K_RF_PD_DELAY_XR, - AR5K_RF_PD_PERIOD_A, - AR5K_RF_PD_PERIOD_B, - AR5K_RF_PD_PERIOD_XR, -}; - - -/*******************\ -* RF5111 (Sombrero) * -\*******************/ - -/* BANK 6 len pos col */ -#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } -#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } - -#define AR5K_RF5111_OB_5GHZ { 3, 104, 0 } -#define AR5K_RF5111_DB_5GHZ { 3, 107, 0 } - -#define AR5K_RF5111_PWD_XPD { 1, 95, 0 } -#define AR5K_RF5111_XPD_GAIN { 4, 96, 0 } - -/* Access to PWD registers */ -#define AR5K_RF5111_PWD(_n) { 1, (135 - _n), 3 } - -/* BANK 7 len pos col */ -#define AR5K_RF5111_GAIN_I { 6, 29, 0 } -#define AR5K_RF5111_PLO_SEL { 1, 4, 0 } -#define AR5K_RF5111_RFGAIN_SEL { 1, 36, 0 } -#define AR5K_RF5111_RFGAIN_STEP { 6, 37, 0 } -/* Only on AR5212 BaseBand and up */ -#define AR5K_RF5111_WAIT_S { 5, 19, 0 } -#define AR5K_RF5111_WAIT_I { 5, 24, 0 } -#define AR5K_RF5111_MAX_TIME { 2, 49, 0 } - -static const struct ath5k_rf_reg rf_regs_5111[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5111_DB_5GHZ}, - {6, AR5K_RF_PWD_XPD, AR5K_RF5111_PWD_XPD}, - {6, AR5K_RF_XPD_GAIN, AR5K_RF5111_XPD_GAIN}, - {6, AR5K_RF_PWD_84, AR5K_RF5111_PWD(84)}, - {6, AR5K_RF_PWD_90, AR5K_RF5111_PWD(90)}, - {7, AR5K_RF_GAIN_I, AR5K_RF5111_GAIN_I}, - {7, AR5K_RF_PLO_SEL, AR5K_RF5111_PLO_SEL}, - {7, AR5K_RF_RFGAIN_SEL, AR5K_RF5111_RFGAIN_SEL}, - {7, AR5K_RF_RFGAIN_STEP, AR5K_RF5111_RFGAIN_STEP}, - {7, AR5K_RF_WAIT_S, AR5K_RF5111_WAIT_S}, - {7, AR5K_RF_WAIT_I, AR5K_RF5111_WAIT_I}, - {7, AR5K_RF_MAX_TIME, AR5K_RF5111_MAX_TIME} -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5111[] = { - { 0, 0x989c, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, - { 0, 0x989c, - { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, - { 0, 0x98d4, - { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, - { 1, 0x98d4, - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, - { 3, 0x98d8, - { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, - { 6, 0x989c, - { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, - { 6, 0x989c, - { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, - { 6, 0x989c, - { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, - { 6, 0x989c, - { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, - { 6, 0x98d4, - { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, - { 7, 0x989c, - { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, - { 7, 0x989c, - { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, - { 7, 0x989c, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 7, 0x989c, - { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, - { 7, 0x989c, - { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, - { 7, 0x989c, - { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, - { 7, 0x989c, - { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, -}; - - - -/***********************\ -* RF5112/RF2112 (Derby) * -\***********************/ - -/* BANK 7 (Common) len pos col */ -#define AR5K_RF5112X_GAIN_I { 6, 14, 0 } -#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } -#define AR5K_RF5112X_MIXGAIN_OVR { 2, 37, 0 } -#define AR5K_RF5112X_MIXGAIN_STEP { 4, 32, 0 } -#define AR5K_RF5112X_PD_DELAY_A { 4, 58, 0 } -#define AR5K_RF5112X_PD_DELAY_B { 4, 62, 0 } -#define AR5K_RF5112X_PD_DELAY_XR { 4, 66, 0 } -#define AR5K_RF5112X_PD_PERIOD_A { 4, 70, 0 } -#define AR5K_RF5112X_PD_PERIOD_B { 4, 74, 0 } -#define AR5K_RF5112X_PD_PERIOD_XR { 4, 78, 0 } - -/* RFX112 (Derby 1) */ - -/* BANK 6 len pos col */ -#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 } -#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 } - -#define AR5K_RF5112_OB_5GHZ { 3, 261, 0 } -#define AR5K_RF5112_DB_5GHZ { 3, 264, 0 } - -#define AR5K_RF5112_FIXED_BIAS_A { 1, 260, 0 } -#define AR5K_RF5112_FIXED_BIAS_B { 1, 259, 0 } - -#define AR5K_RF5112_XPD_SEL { 1, 284, 0 } -#define AR5K_RF5112_XPD_GAIN { 2, 252, 0 } - -/* Access to PWD registers */ -#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } - -static const struct ath5k_rf_reg rf_regs_5112[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5112_DB_5GHZ}, - {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112_FIXED_BIAS_A}, - {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112_FIXED_BIAS_B}, - {6, AR5K_RF_XPD_SEL, AR5K_RF5112_XPD_SEL}, - {6, AR5K_RF_XPD_GAIN, AR5K_RF5112_XPD_GAIN}, - {6, AR5K_RF_PWD_130, AR5K_RF5112_PWD(130)}, - {6, AR5K_RF_PWD_131, AR5K_RF5112_PWD(131)}, - {6, AR5K_RF_PWD_132, AR5K_RF5112_PWD(132)}, - {6, AR5K_RF_PWD_136, AR5K_RF5112_PWD(136)}, - {6, AR5K_RF_PWD_137, AR5K_RF5112_PWD(137)}, - {6, AR5K_RF_PWD_138, AR5K_RF5112_PWD(138)}, - {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I}, - {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR}, - {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR}, - {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP}, - {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A}, - {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B}, - {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR}, - {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A}, - {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B}, - {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5112[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, - { 6, 0x989c, - { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, - { 6, 0x989c, - { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, - { 6, 0x989c, - { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, - { 6, 0x989c, - { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, - { 6, 0x989c, - { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, - { 6, 0x989c, - { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, - { 6, 0x989c, - { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, - { 6, 0x989c, - { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, - { 6, 0x989c, - { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, - { 6, 0x989c, - { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, - { 6, 0x989c, - { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, - { 6, 0x989c, - { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, - { 6, 0x98d0, - { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, - { 7, 0x989c, - { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, -}; - -/* RFX112A (Derby 2) */ - -/* BANK 6 len pos col */ -#define AR5K_RF5112A_OB_2GHZ { 3, 287, 0 } -#define AR5K_RF5112A_DB_2GHZ { 3, 290, 0 } - -#define AR5K_RF5112A_OB_5GHZ { 3, 279, 0 } -#define AR5K_RF5112A_DB_5GHZ { 3, 282, 0 } - -#define AR5K_RF5112A_FIXED_BIAS_A { 1, 278, 0 } -#define AR5K_RF5112A_FIXED_BIAS_B { 1, 277, 0 } - -#define AR5K_RF5112A_XPD_SEL { 1, 302, 0 } -#define AR5K_RF5112A_PDGAINLO { 2, 270, 0 } -#define AR5K_RF5112A_PDGAINHI { 2, 257, 0 } - -/* Access to PWD registers */ -#define AR5K_RF5112A_PWD(_n) { 1, (306 - _n), 3 } - -/* Voltage regulators */ -#define AR5K_RF5112A_HIGH_VC_CP { 2, 90, 2 } -#define AR5K_RF5112A_MID_VC_CP { 2, 92, 2 } -#define AR5K_RF5112A_LOW_VC_CP { 2, 94, 2 } -#define AR5K_RF5112A_PUSH_UP { 1, 254, 2 } - -/* Power consumption */ -#define AR5K_RF5112A_PAD2GND { 1, 281, 1 } -#define AR5K_RF5112A_XB2_LVL { 2, 1, 3 } -#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } - -static const struct ath5k_rf_reg rf_regs_5112a[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5112A_DB_5GHZ}, - {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112A_FIXED_BIAS_A}, - {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112A_FIXED_BIAS_B}, - {6, AR5K_RF_XPD_SEL, AR5K_RF5112A_XPD_SEL}, - {6, AR5K_RF_PD_GAIN_LO, AR5K_RF5112A_PDGAINLO}, - {6, AR5K_RF_PD_GAIN_HI, AR5K_RF5112A_PDGAINHI}, - {6, AR5K_RF_PWD_130, AR5K_RF5112A_PWD(130)}, - {6, AR5K_RF_PWD_131, AR5K_RF5112A_PWD(131)}, - {6, AR5K_RF_PWD_132, AR5K_RF5112A_PWD(132)}, - {6, AR5K_RF_PWD_136, AR5K_RF5112A_PWD(136)}, - {6, AR5K_RF_PWD_137, AR5K_RF5112A_PWD(137)}, - {6, AR5K_RF_PWD_138, AR5K_RF5112A_PWD(138)}, - {6, AR5K_RF_PWD_166, AR5K_RF5112A_PWD(166)}, - {6, AR5K_RF_PWD_167, AR5K_RF5112A_PWD(167)}, - {6, AR5K_RF_HIGH_VC_CP, AR5K_RF5112A_HIGH_VC_CP}, - {6, AR5K_RF_MID_VC_CP, AR5K_RF5112A_MID_VC_CP}, - {6, AR5K_RF_LOW_VC_CP, AR5K_RF5112A_LOW_VC_CP}, - {6, AR5K_RF_PUSH_UP, AR5K_RF5112A_PUSH_UP}, - {6, AR5K_RF_PAD2GND, AR5K_RF5112A_PAD2GND}, - {6, AR5K_RF_XB2_LVL, AR5K_RF5112A_XB2_LVL}, - {6, AR5K_RF_XB5_LVL, AR5K_RF5112A_XB5_LVL}, - {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I}, - {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR}, - {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR}, - {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP}, - {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A}, - {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B}, - {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR}, - {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A}, - {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B}, - {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5112a[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, - { 6, 0x989c, - { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, - { 6, 0x989c, - { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, - { 6, 0x989c, - { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, - { 6, 0x989c, - { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } }, - { 6, 0x989c, - { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, - { 6, 0x989c, - { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, - { 6, 0x989c, - { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, - { 6, 0x989c, - { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, - { 6, 0x989c, - { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, - { 6, 0x989c, - { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, - { 6, 0x989c, - { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } }, - { 6, 0x989c, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, - { 6, 0x989c, - { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, - { 6, 0x989c, - { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, - { 6, 0x989c, - { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, - { 6, 0x989c, - { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, - { 6, 0x98d8, - { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, - { 7, 0x989c, - { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, -}; - - - -/******************\ -* RF2413 (Griffin) * -\******************/ - -/* BANK 6 len pos col */ -#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } -#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } - -static const struct ath5k_rf_reg rf_regs_2413[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, -}; - -/* Default mode specific settings - * XXX: a/aTurbo ??? - */ -static const struct ath5k_ini_rfbuffer rfb_2413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } }, - { 6, 0x989c, - { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } }, - { 6, 0x989c, - { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } }, - { 6, 0x989c, - { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } }, - { 6, 0x989c, - { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } }, - { 6, 0x989c, - { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } }, - { 6, 0x989c, - { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, - { 6, 0x989c, - { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } }, - { 6, 0x989c, - { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } }, - { 6, 0x989c, - { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } }, - { 6, 0x989c, - { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } }, - { 6, 0x989c, - { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } }, - { 6, 0x989c, - { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } }, - { 6, 0x98d8, - { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - - - -/***************************\ -* RF2315/RF2316 (Cobra SoC) * -\***************************/ - -/* BANK 6 len pos col */ -#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } -#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } - -static const struct ath5k_rf_reg rf_regs_2316[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_2316[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } }, - { 6, 0x989c, - { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } }, - { 6, 0x989c, - { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } }, - { 6, 0x989c, - { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } }, - { 6, 0x989c, - { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } }, - { 6, 0x989c, - { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } }, - { 6, 0x989c, - { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } }, - { 6, 0x989c, - { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } }, - { 6, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 6, 0x989c, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 6, 0x989c, - { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } }, - { 6, 0x989c, - { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } }, - { 6, 0x98c0, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - - - -/******************************\ -* RF5413/RF5424 (Eagle/Condor) * -\******************************/ - -/* BANK 6 len pos col */ -#define AR5K_RF5413_OB_2GHZ { 3, 241, 0 } -#define AR5K_RF5413_DB_2GHZ { 3, 238, 0 } - -#define AR5K_RF5413_OB_5GHZ { 3, 247, 0 } -#define AR5K_RF5413_DB_5GHZ { 3, 244, 0 } - -#define AR5K_RF5413_PWD_ICLOBUF2G { 3, 131, 3 } -#define AR5K_RF5413_DERBY_CHAN_SEL_MODE { 1, 291, 2 } - -static const struct ath5k_rf_reg rf_regs_5413[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5413_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5413_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5413_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5413_DB_5GHZ}, - {6, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF5413_PWD_ICLOBUF2G}, - {6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 3, 0x98dc, - { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, - { 6, 0x989c, - { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, - { 6, 0x989c, - { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, - { 6, 0x989c, - { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, - { 6, 0x989c, - { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, - { 6, 0x989c, - { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, - { 6, 0x989c, - { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, - { 6, 0x989c, - { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, - { 6, 0x989c, - { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, - { 6, 0x989c, - { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, - { 6, 0x989c, - { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, - { 6, 0x989c, - { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, - { 6, 0x989c, - { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } }, - { 6, 0x989c, - { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, - { 6, 0x989c, - { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } }, - { 6, 0x98c8, - { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - - - -/***************************\ -* RF2425/RF2417 (Swan/Nala) * -* AR2317 (Spider SoC) * -\***************************/ - -/* BANK 6 len pos col */ -#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } -#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } - -static const struct ath5k_rf_reg rf_regs_2425[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, -}; - -/* Default mode specific settings - * XXX: a/aTurbo ? - */ -static const struct ath5k_ini_rfbuffer rfb_2425[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - -/* - * TODO: Handle the few differences with swan during - * bank modification and get rid of this - */ -static const struct ath5k_ini_rfbuffer rfb_2317[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - -/* - * TODO: Handle the few differences with swan during - * bank modification and get rid of this - * XXX: a/aTurbo ? - */ -static const struct ath5k_ini_rfbuffer rfb_2417[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; diff --git a/drivers/net/wireless/ath5k/rfgain.h b/drivers/net/wireless/ath5k/rfgain.h deleted file mode 100644 index 1354d8c392c8..000000000000 --- a/drivers/net/wireless/ath5k/rfgain.h +++ /dev/null @@ -1,516 +0,0 @@ -/* - * RF Gain optimization - * - * Copyright (c) 2004-2009 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Mode-specific RF Gain table (64bytes) for RF5111/5112 - * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial - * RF Gain values are included in AR5K_AR5210_INI) - */ -struct ath5k_ini_rfgain { - u16 rfg_register; /* RF Gain register address */ - u32 rfg_value[2]; /* [freq (see below)] */ -}; - -/* Initial RF Gain settings for RF5111 */ -static const struct ath5k_ini_rfgain rfgain_5111[] = { - /* 5Ghz 2Ghz */ - { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } }, - { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } }, - { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } }, - { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } }, - { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } }, - { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } }, - { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } }, - { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } }, - { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } }, - { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } }, - { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } }, - { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } }, - { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } }, - { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } }, - { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } }, - { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } }, - { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } }, - { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } }, - { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } }, - { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } }, - { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } }, - { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } }, - { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } }, - { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } }, - { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } }, - { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } }, - { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } }, - { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } }, - { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } }, - { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } }, - { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } }, - { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } }, - { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } }, - { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } }, - { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } }, - { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } }, - { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } }, - { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } }, - { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } }, - { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } }, - { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } }, - { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } }, - { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } }, - { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } }, - { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } }, - { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } }, - { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } }, - { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } }, -}; - -/* Initial RF Gain settings for RF5112 */ -static const struct ath5k_ini_rfgain rfgain_5112[] = { - /* 5Ghz 2Ghz */ - { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } }, - { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } }, - { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } }, - { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } }, - { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } }, - { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } }, - { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } }, - { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } }, - { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } }, - { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } }, - { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } }, - { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } }, - { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } }, - { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } }, - { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } }, - { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } }, - { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } }, - { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } }, - { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } }, - { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } }, - { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } }, - { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } }, - { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } }, - { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } }, - { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } }, - { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } }, - { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } }, - { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } }, - { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } }, - { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } }, - { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } }, - { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } }, - { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } }, - { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } }, - { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } }, - { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } }, - { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } }, - { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } }, - { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } }, - { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } }, - { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } }, - { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } }, - { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } }, - { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } }, - { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } }, - { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } }, - { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } }, - { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } }, - { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } }, - { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } }, - { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } }, - { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } }, - { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } }, - { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } }, - { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } }, -}; - -/* Initial RF Gain settings for RF2413 */ -static const struct ath5k_ini_rfgain rfgain_2413[] = { - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } }, - { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } }, - { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } }, - { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } }, - { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } }, - { AR5K_RF_GAIN(8), { 0x00000000, 0x00000168 } }, - { AR5K_RF_GAIN(9), { 0x00000000, 0x000001a8 } }, - { AR5K_RF_GAIN(10), { 0x00000000, 0x000001e8 } }, - { AR5K_RF_GAIN(11), { 0x00000000, 0x00000028 } }, - { AR5K_RF_GAIN(12), { 0x00000000, 0x00000068 } }, - { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } }, - { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } }, - { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } }, - { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } }, - { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } }, - { AR5K_RF_GAIN(18), { 0x00000000, 0x00000190 } }, - { AR5K_RF_GAIN(19), { 0x00000000, 0x000001d0 } }, - { AR5K_RF_GAIN(20), { 0x00000000, 0x00000010 } }, - { AR5K_RF_GAIN(21), { 0x00000000, 0x00000050 } }, - { AR5K_RF_GAIN(22), { 0x00000000, 0x00000090 } }, - { AR5K_RF_GAIN(23), { 0x00000000, 0x00000191 } }, - { AR5K_RF_GAIN(24), { 0x00000000, 0x000001d1 } }, - { AR5K_RF_GAIN(25), { 0x00000000, 0x00000011 } }, - { AR5K_RF_GAIN(26), { 0x00000000, 0x00000051 } }, - { AR5K_RF_GAIN(27), { 0x00000000, 0x00000091 } }, - { AR5K_RF_GAIN(28), { 0x00000000, 0x00000178 } }, - { AR5K_RF_GAIN(29), { 0x00000000, 0x000001b8 } }, - { AR5K_RF_GAIN(30), { 0x00000000, 0x000001f8 } }, - { AR5K_RF_GAIN(31), { 0x00000000, 0x00000038 } }, - { AR5K_RF_GAIN(32), { 0x00000000, 0x00000078 } }, - { AR5K_RF_GAIN(33), { 0x00000000, 0x00000199 } }, - { AR5K_RF_GAIN(34), { 0x00000000, 0x000001d9 } }, - { AR5K_RF_GAIN(35), { 0x00000000, 0x00000019 } }, - { AR5K_RF_GAIN(36), { 0x00000000, 0x00000059 } }, - { AR5K_RF_GAIN(37), { 0x00000000, 0x00000099 } }, - { AR5K_RF_GAIN(38), { 0x00000000, 0x000000d9 } }, - { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } }, -}; - -/* Initial RF Gain settings for AR2316 */ -static const struct ath5k_ini_rfgain rfgain_2316[] = { - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000000, 0x000000c0 } }, - { AR5K_RF_GAIN(4), { 0x00000000, 0x000000e0 } }, - { AR5K_RF_GAIN(5), { 0x00000000, 0x000000e0 } }, - { AR5K_RF_GAIN(6), { 0x00000000, 0x00000128 } }, - { AR5K_RF_GAIN(7), { 0x00000000, 0x00000128 } }, - { AR5K_RF_GAIN(8), { 0x00000000, 0x00000128 } }, - { AR5K_RF_GAIN(9), { 0x00000000, 0x00000168 } }, - { AR5K_RF_GAIN(10), { 0x00000000, 0x000001a8 } }, - { AR5K_RF_GAIN(11), { 0x00000000, 0x000001e8 } }, - { AR5K_RF_GAIN(12), { 0x00000000, 0x00000028 } }, - { AR5K_RF_GAIN(13), { 0x00000000, 0x00000068 } }, - { AR5K_RF_GAIN(14), { 0x00000000, 0x000000a8 } }, - { AR5K_RF_GAIN(15), { 0x00000000, 0x000000e8 } }, - { AR5K_RF_GAIN(16), { 0x00000000, 0x000000e8 } }, - { AR5K_RF_GAIN(17), { 0x00000000, 0x00000130 } }, - { AR5K_RF_GAIN(18), { 0x00000000, 0x00000130 } }, - { AR5K_RF_GAIN(19), { 0x00000000, 0x00000170 } }, - { AR5K_RF_GAIN(20), { 0x00000000, 0x000001b0 } }, - { AR5K_RF_GAIN(21), { 0x00000000, 0x000001f0 } }, - { AR5K_RF_GAIN(22), { 0x00000000, 0x00000030 } }, - { AR5K_RF_GAIN(23), { 0x00000000, 0x00000070 } }, - { AR5K_RF_GAIN(24), { 0x00000000, 0x000000b0 } }, - { AR5K_RF_GAIN(25), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(26), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(27), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(28), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(29), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(30), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(31), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(32), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(33), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(34), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(35), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(36), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f0 } }, -}; - - -/* Initial RF Gain settings for RF5413 */ -static const struct ath5k_ini_rfgain rfgain_5413[] = { - /* 5Ghz 2Ghz */ - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } }, - { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } }, - { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } }, - { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } }, - { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } }, - { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } }, - { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } }, - { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } }, - { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } }, - { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } }, - { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } }, - { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } }, - { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } }, - { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } }, - { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } }, - { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } }, - { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } }, - { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } }, - { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } }, - { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } }, - { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } }, - { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } }, - { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } }, - { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } }, - { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } }, - { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } }, - { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } }, - { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } }, - { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } }, - { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } }, - { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } }, - { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } }, - { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } }, - { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } }, - { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } }, - { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } }, - { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, -}; - - -/* Initial RF Gain settings for RF2425 */ -static const struct ath5k_ini_rfgain rfgain_2425[] = { - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } }, - { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } }, - { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } }, - { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } }, - { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } }, - { AR5K_RF_GAIN(8), { 0x00000000, 0x00000188 } }, - { AR5K_RF_GAIN(9), { 0x00000000, 0x000001c8 } }, - { AR5K_RF_GAIN(10), { 0x00000000, 0x00000008 } }, - { AR5K_RF_GAIN(11), { 0x00000000, 0x00000048 } }, - { AR5K_RF_GAIN(12), { 0x00000000, 0x00000088 } }, - { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } }, - { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } }, - { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } }, - { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } }, - { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } }, - { AR5K_RF_GAIN(18), { 0x00000000, 0x000001b0 } }, - { AR5K_RF_GAIN(19), { 0x00000000, 0x000001f0 } }, - { AR5K_RF_GAIN(20), { 0x00000000, 0x00000030 } }, - { AR5K_RF_GAIN(21), { 0x00000000, 0x00000070 } }, - { AR5K_RF_GAIN(22), { 0x00000000, 0x00000171 } }, - { AR5K_RF_GAIN(23), { 0x00000000, 0x000001b1 } }, - { AR5K_RF_GAIN(24), { 0x00000000, 0x000001f1 } }, - { AR5K_RF_GAIN(25), { 0x00000000, 0x00000031 } }, - { AR5K_RF_GAIN(26), { 0x00000000, 0x00000071 } }, - { AR5K_RF_GAIN(27), { 0x00000000, 0x000001b8 } }, - { AR5K_RF_GAIN(28), { 0x00000000, 0x000001f8 } }, - { AR5K_RF_GAIN(29), { 0x00000000, 0x00000038 } }, - { AR5K_RF_GAIN(30), { 0x00000000, 0x00000078 } }, - { AR5K_RF_GAIN(31), { 0x00000000, 0x000000b8 } }, - { AR5K_RF_GAIN(32), { 0x00000000, 0x000001b9 } }, - { AR5K_RF_GAIN(33), { 0x00000000, 0x000001f9 } }, - { AR5K_RF_GAIN(34), { 0x00000000, 0x00000039 } }, - { AR5K_RF_GAIN(35), { 0x00000000, 0x00000079 } }, - { AR5K_RF_GAIN(36), { 0x00000000, 0x000000b9 } }, - { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } }, -}; - -#define AR5K_GAIN_CRN_FIX_BITS_5111 4 -#define AR5K_GAIN_CRN_FIX_BITS_5112 7 -#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112 -#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15 -#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20 -#define AR5K_GAIN_CCK_PROBE_CORR 5 -#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15 -#define AR5K_GAIN_STEP_COUNT 10 - -/* Check if our current measurement is inside our - * current variable attenuation window */ -#define AR5K_GAIN_CHECK_ADJUST(_g) \ - ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) - -struct ath5k_gain_opt_step { - s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; - s8 gos_gain; -}; - -struct ath5k_gain_opt { - u8 go_default; - u8 go_steps_count; - const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; -}; - -/* - * Parameters on gos_param: - * 1) Tx clip PHY register - * 2) PWD 90 RF register - * 3) PWD 84 RF register - * 4) RFGainSel RF register - */ -static const struct ath5k_gain_opt rfgain_opt_5111 = { - 4, - 9, - { - { { 4, 1, 1, 1 }, 6 }, - { { 4, 0, 1, 1 }, 4 }, - { { 3, 1, 1, 1 }, 3 }, - { { 4, 0, 0, 1 }, 1 }, - { { 4, 1, 1, 0 }, 0 }, - { { 4, 0, 1, 0 }, -2 }, - { { 3, 1, 1, 0 }, -3 }, - { { 4, 0, 0, 0 }, -4 }, - { { 2, 1, 1, 0 }, -6 } - } -}; - -/* - * Parameters on gos_param: - * 1) Mixgain ovr RF register - * 2) PWD 138 RF register - * 3) PWD 137 RF register - * 4) PWD 136 RF register - * 5) PWD 132 RF register - * 6) PWD 131 RF register - * 7) PWD 130 RF register - */ -static const struct ath5k_gain_opt rfgain_opt_5112 = { - 1, - 8, - { - { { 3, 0, 0, 0, 0, 0, 0 }, 6 }, - { { 2, 0, 0, 0, 0, 0, 0 }, 0 }, - { { 1, 0, 0, 0, 0, 0, 0 }, -3 }, - { { 0, 0, 0, 0, 0, 0, 0 }, -6 }, - { { 0, 1, 1, 0, 0, 0, 0 }, -8 }, - { { 0, 1, 1, 0, 1, 1, 0 }, -10 }, - { { 0, 1, 0, 1, 1, 1, 0 }, -13 }, - { { 0, 1, 0, 1, 1, 0, 1 }, -16 }, - } -}; - diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig deleted file mode 100644 index 0ed1ac312aa6..000000000000 --- a/drivers/net/wireless/ath9k/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -config ATH9K - tristate "Atheros 802.11n wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 - depends on RFKILL || RFKILL=n - select ATH_COMMON - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS - ---help--- - This module adds support for wireless adapters based on - Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. - - If you choose to build a module, it'll be called ath9k. - -config ATH9K_DEBUG - bool "Atheros ath9k debugging" - depends on ATH9K - ---help--- - Say Y, if you need ath9k to display debug messages. - Pass the debug mask as a module parameter: - - modprobe ath9k debug=0x00002000 - - Look in ath9k/core.h for possible debug masks diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile deleted file mode 100644 index 783bc39eb2ff..000000000000 --- a/drivers/net/wireless/ath9k/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -ath9k-y += hw.o \ - eeprom.o \ - mac.o \ - calib.o \ - ani.o \ - phy.o \ - beacon.o \ - main.o \ - recv.o \ - xmit.o \ - virtual.o \ - rc.o - -ath9k-$(CONFIG_PCI) += pci.o -ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o -ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o - -obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c deleted file mode 100644 index 0e65c51ba176..000000000000 --- a/drivers/net/wireless/ath9k/ahb.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * Copyright (c) 2009 Gabor Juhos - * Copyright (c) 2009 Imre Kaloz - * - * 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 -#include -#include -#include "ath9k.h" - -/* return bus cachesize in 4B word units */ -static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz) -{ - *csz = L1_CACHE_BYTES >> 2; -} - -static void ath_ahb_cleanup(struct ath_softc *sc) -{ - iounmap(sc->mem); -} - -static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) -{ - struct ath_softc *sc = ah->ah_sc; - struct platform_device *pdev = to_platform_device(sc->dev); - struct ath9k_platform_data *pdata; - - pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; - if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "%s: flash read failed, offset %08x is out of range\n", - __func__, off); - return false; - } - - *data = pdata->eeprom_data[off]; - return true; -} - -static struct ath_bus_ops ath_ahb_bus_ops = { - .read_cachesize = ath_ahb_read_cachesize, - .cleanup = ath_ahb_cleanup, - - .eeprom_read = ath_ahb_eeprom_read, -}; - -static int ath_ahb_probe(struct platform_device *pdev) -{ - void __iomem *mem; - struct ath_wiphy *aphy; - struct ath_softc *sc; - struct ieee80211_hw *hw; - struct resource *res; - int irq; - int ret = 0; - struct ath_hw *ah; - - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "no platform data specified\n"); - ret = -EINVAL; - goto err_out; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no memory resource found\n"); - ret = -ENXIO; - goto err_out; - } - - mem = ioremap_nocache(res->start, res->end - res->start + 1); - if (mem == NULL) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto err_out; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no IRQ resource found\n"); - ret = -ENXIO; - goto err_iounmap; - } - - irq = res->start; - - hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + - sizeof(struct ath_softc), &ath9k_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); - ret = -ENOMEM; - goto err_iounmap; - } - - SET_IEEE80211_DEV(hw, &pdev->dev); - platform_set_drvdata(pdev, hw); - - aphy = hw->priv; - sc = (struct ath_softc *) (aphy + 1); - aphy->sc = sc; - aphy->hw = hw; - sc->pri_wiphy = aphy; - sc->hw = hw; - sc->dev = &pdev->dev; - sc->mem = mem; - sc->bus_ops = &ath_ahb_bus_ops; - sc->irq = irq; - - ret = ath_attach(AR5416_AR9100_DEVID, sc); - if (ret != 0) { - dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); - ret = -ENODEV; - goto err_free_hw; - } - - ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); - if (ret) { - dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret); - ret = -EIO; - goto err_detach; - } - - ah = sc->sc_ah; - printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x, " - "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev, - (unsigned long)mem, irq); - - return 0; - - err_detach: - ath_detach(sc); - err_free_hw: - ieee80211_free_hw(hw); - platform_set_drvdata(pdev, NULL); - err_iounmap: - iounmap(mem); - err_out: - return ret; -} - -static int ath_ahb_remove(struct platform_device *pdev) -{ - struct ieee80211_hw *hw = platform_get_drvdata(pdev); - - if (hw) { - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - ath_cleanup(sc); - platform_set_drvdata(pdev, NULL); - } - - return 0; -} - -static struct platform_driver ath_ahb_driver = { - .probe = ath_ahb_probe, - .remove = ath_ahb_remove, - .driver = { - .name = "ath9k", - .owner = THIS_MODULE, - }, -}; - -int ath_ahb_init(void) -{ - return platform_driver_register(&ath_ahb_driver); -} - -void ath_ahb_exit(void) -{ - platform_driver_unregister(&ath_ahb_driver); -} diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c deleted file mode 100644 index 1aeafb511ddd..000000000000 --- a/drivers/net/wireless/ath9k/ani.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * 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 "ath9k.h" - -static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { - if (ah->ani[i].c && - ah->ani[i].c->channel == chan->channel) - return i; - if (ah->ani[i].c == NULL) { - ah->ani[i].c = chan; - return i; - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "No more channel states left. Using channel 0\n"); - - return 0; -} - -static bool ath9k_hw_ani_control(struct ath_hw *ah, - enum ath9k_ani_cmd cmd, int param) -{ - struct ar5416AniState *aniState = ah->curani; - - switch (cmd & ah->ani_function) { - case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ - u32 level = param; - - if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); - return false; - } - - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_TOT_DES, - ah->totalSizeDesired[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, - AR_PHY_AGC_CTL1_COARSE_LOW, - ah->coarse_low[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, - AR_PHY_AGC_CTL1_COARSE_HIGH, - ah->coarse_high[level]); - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRPWR, - ah->firpwr[level]); - - if (level > aniState->noiseImmunityLevel) - ah->stats.ast_ani_niup++; - else if (level < aniState->noiseImmunityLevel) - ah->stats.ast_ani_nidown++; - aniState->noiseImmunityLevel = level; - break; - } - case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ - const int m1ThreshLow[] = { 127, 50 }; - const int m2ThreshLow[] = { 127, 40 }; - const int m1Thresh[] = { 127, 0x4d }; - const int m2Thresh[] = { 127, 0x40 }; - const int m2CountThr[] = { 31, 16 }; - const int m2CountThrLow[] = { 63, 48 }; - u32 on = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M1_THRESH_LOW, - m1ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M2_THRESH_LOW, - m2ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M1_THRESH, - m1Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2_THRESH, - m2Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2COUNT_THR, - m2CountThr[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, - m2CountThrLow[on]); - - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH_LOW, - m1ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH_LOW, - m2ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH, - m1Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH, - m2Thresh[on]); - - if (on) - REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - else - REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - - if (!on != aniState->ofdmWeakSigDetectOff) { - if (on) - ah->stats.ast_ani_ofdmon++; - else - ah->stats.ast_ani_ofdmoff++; - aniState->ofdmWeakSigDetectOff = !on; - } - break; - } - case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ - const int weakSigThrCck[] = { 8, 6 }; - u32 high = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, - AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, - weakSigThrCck[high]); - if (high != aniState->cckWeakSigThreshold) { - if (high) - ah->stats.ast_ani_cckhigh++; - else - ah->stats.ast_ani_ccklow++; - aniState->cckWeakSigThreshold = high; - } - break; - } - case ATH9K_ANI_FIRSTEP_LEVEL:{ - const int firstep[] = { 0, 4, 8 }; - u32 level = param; - - if (level >= ARRAY_SIZE(firstep)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(firstep)); - return false; - } - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRSTEP, - firstep[level]); - if (level > aniState->firstepLevel) - ah->stats.ast_ani_stepup++; - else if (level < aniState->firstepLevel) - ah->stats.ast_ani_stepdown++; - aniState->firstepLevel = level; - break; - } - case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - const int cycpwrThr1[] = - { 2, 4, 6, 8, 10, 12, 14, 16 }; - u32 level = param; - - if (level >= ARRAY_SIZE(cycpwrThr1)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) - ARRAY_SIZE(cycpwrThr1)); - return false; - } - REG_RMW_FIELD(ah, AR_PHY_TIMING5, - AR_PHY_TIMING5_CYCPWR_THR1, - cycpwrThr1[level]); - if (level > aniState->spurImmunityLevel) - ah->stats.ast_ani_spurup++; - else if (level < aniState->spurImmunityLevel) - ah->stats.ast_ani_spurdown++; - aniState->spurImmunityLevel = level; - break; - } - case ATH9K_ANI_PRESENT: - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "invalid cmd %u\n", cmd); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n"); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "noiseImmunityLevel=%d, spurImmunityLevel=%d, " - "ofdmWeakSigDetectOff=%d\n", - aniState->noiseImmunityLevel, aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "cckWeakSigThreshold=%d, " - "firstepLevel=%d, listenTime=%d\n", - aniState->cckWeakSigThreshold, aniState->firstepLevel, - aniState->listenTime); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", - aniState->cycleCount, aniState->ofdmPhyErrCount, - aniState->cckPhyErrCount); - - return true; -} - -static void ath9k_hw_update_mibstats(struct ath_hw *ah, - struct ath9k_mib_stats *stats) -{ - stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); - stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); - stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); - stats->rts_good += REG_READ(ah, AR_RTS_OK); - stats->beacons += REG_READ(ah, AR_BEACON_CNT); -} - -static void ath9k_ani_restart(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - - aniState->listenTime = 0; - if (ah->has_hw_phycounters) { - if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { - aniState->ofdmPhyErrBase = 0; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "OFDM Trigger is too high for hw counters\n"); - } else { - aniState->ofdmPhyErrBase = - AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; - } - if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { - aniState->cckPhyErrBase = 0; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "CCK Trigger is too high for hw counters\n"); - } else { - aniState->cckPhyErrBase = - AR_PHY_COUNTMAX - aniState->cckTrigHigh; - } - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Writing ofdmbase=%u cckbase=%u\n", - aniState->ofdmPhyErrBase, - aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); - - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - } - aniState->ofdmPhyErrCount = 0; - aniState->cckPhyErrCount = 0; -} - -static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct ar5416AniState *aniState; - int32_t rssi; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - - if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel + 1)) { - return; - } - } - - if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, - aniState->spurImmunityLevel + 1)) { - return; - } - } - - if (ah->opmode == NL80211_IFTYPE_AP) { - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - } - return; - } - rssi = BEACON_RSSI(ah); - if (rssi > aniState->rssiThrHigh) { - if (!aniState->ofdmWeakSigDetectOff) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - false)) { - ath9k_hw_ani_control(ah, - ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); - return; - } - } - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - return; - } - } else if (rssi > aniState->rssiThrLow) { - if (aniState->ofdmWeakSigDetectOff) - ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - true); - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - return; - } else { - if (conf->channel->band == IEEE80211_BAND_2GHZ) { - if (!aniState->ofdmWeakSigDetectOff) - ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - false); - if (aniState->firstepLevel > 0) - ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, 0); - return; - } - } -} - -static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct ar5416AniState *aniState; - int32_t rssi; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel + 1)) { - return; - } - } - if (ah->opmode == NL80211_IFTYPE_AP) { - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - } - return; - } - rssi = BEACON_RSSI(ah); - if (rssi > aniState->rssiThrLow) { - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - } else { - if (conf->channel->band == IEEE80211_BAND_2GHZ) { - if (aniState->firstepLevel > 0) - ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, 0); - } - } -} - -static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - int32_t rssi; - - aniState = ah->curani; - - if (ah->opmode == NL80211_IFTYPE_AP) { - if (aniState->firstepLevel > 0) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel - 1)) - return; - } - } else { - rssi = BEACON_RSSI(ah); - if (rssi > aniState->rssiThrHigh) { - /* XXX: Handle me */ - } else if (rssi > aniState->rssiThrLow) { - if (aniState->ofdmWeakSigDetectOff) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - true) == true) - return; - } - if (aniState->firstepLevel > 0) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel - 1) == true) - return; - } - } else { - if (aniState->firstepLevel > 0) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel - 1) == true) - return; - } - } - } - - if (aniState->spurImmunityLevel > 0) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, - aniState->spurImmunityLevel - 1)) - return; - } - - if (aniState->noiseImmunityLevel > 0) { - ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel - 1); - return; - } -} - -static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - u32 txFrameCount, rxFrameCount, cycleCount; - int32_t listenTime; - - txFrameCount = REG_READ(ah, AR_TFCNT); - rxFrameCount = REG_READ(ah, AR_RFCNT); - cycleCount = REG_READ(ah, AR_CCCNT); - - aniState = ah->curani; - if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { - - listenTime = 0; - ah->stats.ast_ani_lzero++; - } else { - int32_t ccdelta = cycleCount - aniState->cycleCount; - int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; - int32_t tfdelta = txFrameCount - aniState->txFrameCount; - listenTime = (ccdelta - rfdelta - tfdelta) / 44000; - } - aniState->cycleCount = cycleCount; - aniState->txFrameCount = txFrameCount; - aniState->rxFrameCount = rxFrameCount; - - return listenTime; -} - -void ath9k_ani_reset(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - struct ath9k_channel *chan = ah->curchan; - int index; - - if (!DO_ANI(ah)) - return; - - index = ath9k_hw_get_ani_channel_idx(ah, chan); - aniState = &ah->ani[index]; - ah->curani = aniState; - - if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION - && ah->opmode != NL80211_IFTYPE_ADHOC) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Reset ANI state opmode %u\n", ah->opmode); - ah->stats.ast_ani_reset++; - - ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); - ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); - ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - !ATH9K_ANI_USE_OFDM_WEAK_SIG); - ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, - ATH9K_ANI_CCK_WEAK_SIG_THR); - - ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | - ATH9K_RX_FILTER_PHYERR); - - if (ah->opmode == NL80211_IFTYPE_AP) { - ah->curani->ofdmTrigHigh = - ah->config.ofdm_trig_high; - ah->curani->ofdmTrigLow = - ah->config.ofdm_trig_low; - ah->curani->cckTrigHigh = - ah->config.cck_trig_high; - ah->curani->cckTrigLow = - ah->config.cck_trig_low; - } - ath9k_ani_restart(ah); - return; - } - - if (aniState->noiseImmunityLevel != 0) - ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel); - if (aniState->spurImmunityLevel != 0) - ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, - aniState->spurImmunityLevel); - if (aniState->ofdmWeakSigDetectOff) - ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - !aniState->ofdmWeakSigDetectOff); - if (aniState->cckWeakSigThreshold) - ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, - aniState->cckWeakSigThreshold); - if (aniState->firstepLevel != 0) - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel); - if (ah->has_hw_phycounters) { - ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & - ~ATH9K_RX_FILTER_PHYERR); - ath9k_ani_restart(ah); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); - - } else { - ath9k_ani_restart(ah); - ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | - ATH9K_RX_FILTER_PHYERR); - } -} - -void ath9k_hw_ani_monitor(struct ath_hw *ah, - const struct ath9k_node_stats *stats, - struct ath9k_channel *chan) -{ - struct ar5416AniState *aniState; - int32_t listenTime; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - ah->stats.ast_nodestats = *stats; - - listenTime = ath9k_hw_ani_get_listen_time(ah); - if (listenTime < 0) { - ah->stats.ast_ani_lneg++; - ath9k_ani_restart(ah); - return; - } - - aniState->listenTime += listenTime; - - if (ah->has_hw_phycounters) { - u32 phyCnt1, phyCnt2; - u32 ofdmPhyErrCnt, cckPhyErrCnt; - - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - - phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); - phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); - - if (phyCnt1 < aniState->ofdmPhyErrBase || - phyCnt2 < aniState->cckPhyErrBase) { - if (phyCnt1 < aniState->ofdmPhyErrBase) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "phyCnt1 0x%x, resetting " - "counter value to 0x%x\n", - phyCnt1, aniState->ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_1, - aniState->ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, - AR_PHY_ERR_OFDM_TIMING); - } - if (phyCnt2 < aniState->cckPhyErrBase) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "phyCnt2 0x%x, resetting " - "counter value to 0x%x\n", - phyCnt2, aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_2, - aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, - AR_PHY_ERR_CCK_TIMING); - } - return; - } - - ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; - ah->stats.ast_ani_ofdmerrs += - ofdmPhyErrCnt - aniState->ofdmPhyErrCount; - aniState->ofdmPhyErrCount = ofdmPhyErrCnt; - - cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; - ah->stats.ast_ani_cckerrs += - cckPhyErrCnt - aniState->cckPhyErrCount; - aniState->cckPhyErrCount = cckPhyErrCnt; - } - - if (aniState->listenTime > 5 * ah->aniperiod) { - if (aniState->ofdmPhyErrCount <= aniState->listenTime * - aniState->ofdmTrigLow / 1000 && - aniState->cckPhyErrCount <= aniState->listenTime * - aniState->cckTrigLow / 1000) - ath9k_hw_ani_lower_immunity(ah); - ath9k_ani_restart(ah); - } else if (aniState->listenTime > ah->aniperiod) { - if (aniState->ofdmPhyErrCount > aniState->listenTime * - aniState->ofdmTrigHigh / 1000) { - ath9k_hw_ani_ofdm_err_trigger(ah); - ath9k_ani_restart(ah); - } else if (aniState->cckPhyErrCount > - aniState->listenTime * aniState->cckTrigHigh / - 1000) { - ath9k_hw_ani_cck_err_trigger(ah); - ath9k_ani_restart(ah); - } - } -} - -bool ath9k_hw_phycounters(struct ath_hw *ah) -{ - return ah->has_hw_phycounters ? true : false; -} - -void ath9k_enable_mib_counters(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); - - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - - REG_WRITE(ah, AR_FILT_OFDM, 0); - REG_WRITE(ah, AR_FILT_CCK, 0); - REG_WRITE(ah, AR_MIBC, - ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) - & 0x0f); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); -} - -/* Freeze the MIB counters, get the stats and then clear them */ -void ath9k_hw_disable_mib_counters(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n"); - REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC); - REG_WRITE(ah, AR_FILT_OFDM, 0); - REG_WRITE(ah, AR_FILT_CCK, 0); -} - -u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, - u32 *rxc_pcnt, - u32 *rxf_pcnt, - u32 *txf_pcnt) -{ - static u32 cycles, rx_clear, rx_frame, tx_frame; - u32 good = 1; - - u32 rc = REG_READ(ah, AR_RCCNT); - u32 rf = REG_READ(ah, AR_RFCNT); - u32 tf = REG_READ(ah, AR_TFCNT); - u32 cc = REG_READ(ah, AR_CCCNT); - - if (cycles == 0 || cycles > cc) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "cycle counter wrap. ExtBusy = 0\n"); - good = 0; - } else { - u32 cc_d = cc - cycles; - u32 rc_d = rc - rx_clear; - u32 rf_d = rf - rx_frame; - u32 tf_d = tf - tx_frame; - - if (cc_d != 0) { - *rxc_pcnt = rc_d * 100 / cc_d; - *rxf_pcnt = rf_d * 100 / cc_d; - *txf_pcnt = tf_d * 100 / cc_d; - } else { - good = 0; - } - } - - cycles = cc; - rx_frame = rf; - rx_clear = rc; - tx_frame = tf; - - return good; -} - -/* - * Process a MIB interrupt. We may potentially be invoked because - * any of the MIB counters overflow/trigger so don't assume we're - * here because a PHY error counter triggered. - */ -void ath9k_hw_procmibevent(struct ath_hw *ah, - const struct ath9k_node_stats *stats) -{ - u32 phyCnt1, phyCnt2; - - /* Reset these counters regardless */ - REG_WRITE(ah, AR_FILT_OFDM, 0); - REG_WRITE(ah, AR_FILT_CCK, 0); - if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) - REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); - - /* Clear the mib counters and save them in the stats */ - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - ah->stats.ast_nodestats = *stats; - - if (!DO_ANI(ah)) - return; - - /* NB: these are not reset-on-read */ - phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); - phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); - if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || - ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { - struct ar5416AniState *aniState = ah->curani; - u32 ofdmPhyErrCnt, cckPhyErrCnt; - - /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ - ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; - ah->stats.ast_ani_ofdmerrs += - ofdmPhyErrCnt - aniState->ofdmPhyErrCount; - aniState->ofdmPhyErrCount = ofdmPhyErrCnt; - - cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; - ah->stats.ast_ani_cckerrs += - cckPhyErrCnt - aniState->cckPhyErrCount; - aniState->cckPhyErrCount = cckPhyErrCnt; - - /* - * NB: figure out which counter triggered. If both - * trigger we'll only deal with one as the processing - * clobbers the error counter so the trigger threshold - * check will never be true. - */ - if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) - ath9k_hw_ani_ofdm_err_trigger(ah); - if (aniState->cckPhyErrCount > aniState->cckTrigHigh) - ath9k_hw_ani_cck_err_trigger(ah); - /* NB: always restart to insure the h/w counters are reset */ - ath9k_ani_restart(ah); - } -} - -void ath9k_hw_ani_setup(struct ath_hw *ah) -{ - int i; - - const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; - const int coarseHigh[] = { -14, -14, -14, -14, -12 }; - const int coarseLow[] = { -64, -64, -64, -64, -70 }; - const int firpwr[] = { -78, -78, -78, -78, -80 }; - - for (i = 0; i < 5; i++) { - ah->totalSizeDesired[i] = totalSizeDesired[i]; - ah->coarse_high[i] = coarseHigh[i]; - ah->coarse_low[i] = coarseLow[i]; - ah->firpwr[i] = firpwr[i]; - } -} - -void ath9k_hw_ani_attach(struct ath_hw *ah) -{ - int i; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n"); - - ah->has_hw_phycounters = 1; - - memset(ah->ani, 0, sizeof(ah->ani)); - for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { - ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; - ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; - ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; - ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; - ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; - ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; - ah->ani[i].ofdmWeakSigDetectOff = - !ATH9K_ANI_USE_OFDM_WEAK_SIG; - ah->ani[i].cckWeakSigThreshold = - ATH9K_ANI_CCK_WEAK_SIG_THR; - ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; - ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - if (ah->has_hw_phycounters) { - ah->ani[i].ofdmPhyErrBase = - AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; - ah->ani[i].cckPhyErrBase = - AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; - } - } - if (ah->has_hw_phycounters) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Setting OfdmErrBase = 0x%08x\n", - ah->ani[0].ofdmPhyErrBase); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", - ah->ani[0].cckPhyErrBase); - - REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); - ath9k_enable_mib_counters(ah); - } - ah->aniperiod = ATH9K_ANI_PERIOD; - if (ah->config.enable_ani) - ah->proc_phyerr |= HAL_PROCESS_ANI; -} - -void ath9k_hw_ani_detach(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n"); - - if (ah->has_hw_phycounters) { - ath9k_hw_disable_mib_counters(ah); - REG_WRITE(ah, AR_PHY_ERR_1, 0); - REG_WRITE(ah, AR_PHY_ERR_2, 0); - } -} diff --git a/drivers/net/wireless/ath9k/ani.h b/drivers/net/wireless/ath9k/ani.h deleted file mode 100644 index 08b4e7ed5ff0..000000000000 --- a/drivers/net/wireless/ath9k/ani.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 ANI_H -#define ANI_H - -#define HAL_PROCESS_ANI 0x00000001 -#define ATH9K_RSSI_EP_MULTIPLIER (1<<7) - -#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) - -#define HAL_EP_RND(x, mul) \ - ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) -#define BEACON_RSSI(ahp) \ - HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi, \ - ATH9K_RSSI_EP_MULTIPLIER) - -#define ATH9K_ANI_OFDM_TRIG_HIGH 500 -#define ATH9K_ANI_OFDM_TRIG_LOW 200 -#define ATH9K_ANI_CCK_TRIG_HIGH 200 -#define ATH9K_ANI_CCK_TRIG_LOW 100 -#define ATH9K_ANI_NOISE_IMMUNE_LVL 4 -#define ATH9K_ANI_USE_OFDM_WEAK_SIG true -#define ATH9K_ANI_CCK_WEAK_SIG_THR false -#define ATH9K_ANI_SPUR_IMMUNE_LVL 7 -#define ATH9K_ANI_FIRSTEP_LVL 0 -#define ATH9K_ANI_RSSI_THR_HIGH 40 -#define ATH9K_ANI_RSSI_THR_LOW 7 -#define ATH9K_ANI_PERIOD 100 - -#define HAL_NOISE_IMMUNE_MAX 4 -#define HAL_SPUR_IMMUNE_MAX 7 -#define HAL_FIRST_STEP_MAX 2 - -enum ath9k_ani_cmd { - ATH9K_ANI_PRESENT = 0x1, - ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4, - ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8, - ATH9K_ANI_FIRSTEP_LEVEL = 0x10, - ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, - ATH9K_ANI_MODE = 0x40, - ATH9K_ANI_PHYERR_RESET = 0x80, - ATH9K_ANI_ALL = 0xff -}; - -struct ath9k_mib_stats { - u32 ackrcv_bad; - u32 rts_bad; - u32 rts_good; - u32 fcs_bad; - u32 beacons; -}; - -struct ath9k_node_stats { - u32 ns_avgbrssi; - u32 ns_avgrssi; - u32 ns_avgtxrssi; - u32 ns_avgtxrate; -}; - -struct ar5416AniState { - struct ath9k_channel *c; - u8 noiseImmunityLevel; - u8 spurImmunityLevel; - u8 firstepLevel; - u8 ofdmWeakSigDetectOff; - u8 cckWeakSigThreshold; - u32 listenTime; - u32 ofdmTrigHigh; - u32 ofdmTrigLow; - int32_t cckTrigHigh; - int32_t cckTrigLow; - int32_t rssiThrLow; - int32_t rssiThrHigh; - u32 noiseFloor; - u32 txFrameCount; - u32 rxFrameCount; - u32 cycleCount; - u32 ofdmPhyErrCount; - u32 cckPhyErrCount; - u32 ofdmPhyErrBase; - u32 cckPhyErrBase; - int16_t pktRssi[2]; - int16_t ofdmErrRssi[2]; - int16_t cckErrRssi[2]; -}; - -struct ar5416Stats { - u32 ast_ani_niup; - u32 ast_ani_nidown; - u32 ast_ani_spurup; - u32 ast_ani_spurdown; - u32 ast_ani_ofdmon; - u32 ast_ani_ofdmoff; - u32 ast_ani_cckhigh; - u32 ast_ani_ccklow; - u32 ast_ani_stepup; - u32 ast_ani_stepdown; - u32 ast_ani_ofdmerrs; - u32 ast_ani_cckerrs; - u32 ast_ani_reset; - u32 ast_ani_lzero; - u32 ast_ani_lneg; - struct ath9k_mib_stats ast_mibstats; - struct ath9k_node_stats ast_nodestats; -}; -#define ah_mibStats stats.ast_mibstats - -void ath9k_ani_reset(struct ath_hw *ah); -void ath9k_hw_ani_monitor(struct ath_hw *ah, - const struct ath9k_node_stats *stats, - struct ath9k_channel *chan); -bool ath9k_hw_phycounters(struct ath_hw *ah); -void ath9k_enable_mib_counters(struct ath_hw *ah); -void ath9k_hw_disable_mib_counters(struct ath_hw *ah); -u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, - u32 *rxf_pcnt, u32 *txf_pcnt); -void ath9k_hw_procmibevent(struct ath_hw *ah, - const struct ath9k_node_stats *stats); -void ath9k_hw_ani_setup(struct ath_hw *ah); -void ath9k_hw_ani_attach(struct ath_hw *ah); -void ath9k_hw_ani_detach(struct ath_hw *ah); - -#endif /* ANI_H */ diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h deleted file mode 100644 index c92d46fa9d51..000000000000 --- a/drivers/net/wireless/ath9k/ath9k.h +++ /dev/null @@ -1,730 +0,0 @@ -/* - * 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 ATH9K_H -#define ATH9K_H - -#include -#include -#include -#include -#include - -#include "hw.h" -#include "rc.h" -#include "debug.h" - -struct ath_node; - -/* Macro to expand scalars to 64-bit objects */ - -#define ito64(x) (sizeof(x) == 8) ? \ - (((unsigned long long int)(x)) & (0xff)) : \ - (sizeof(x) == 16) ? \ - (((unsigned long long int)(x)) & 0xffff) : \ - ((sizeof(x) == 32) ? \ - (((unsigned long long int)(x)) & 0xffffffff) : \ - (unsigned long long int)(x)) - -/* increment with wrap-around */ -#define INCR(_l, _sz) do { \ - (_l)++; \ - (_l) &= ((_sz) - 1); \ - } while (0) - -/* decrement with wrap-around */ -#define DECR(_l, _sz) do { \ - (_l)--; \ - (_l) &= ((_sz) - 1); \ - } while (0) - -#define A_MAX(a, b) ((a) > (b) ? (a) : (b)) - -#define ASSERT(exp) BUG_ON(!(exp)) - -#define TSF_TO_TU(_h,_l) \ - ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) - -#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<bf_stale = false; \ - (_bf)->bf_lastbf = NULL; \ - (_bf)->bf_next = NULL; \ - memset(&((_bf)->bf_state), 0, \ - sizeof(struct ath_buf_state)); \ - } while (0) - -#define ATH_RXBUF_RESET(_bf) do { \ - (_bf)->bf_stale = false; \ - } while (0) - -/** - * enum buffer_type - Buffer type flags - * - * @BUF_HT: Send this buffer using HT capabilities - * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) - * @BUF_AGGR: Indicates whether the buffer can be aggregated - * (used in aggregation scheduling) - * @BUF_RETRY: Indicates whether the buffer is retried - * @BUF_XRETRY: To denote excessive retries of the buffer - */ -enum buffer_type { - BUF_HT = BIT(1), - BUF_AMPDU = BIT(2), - BUF_AGGR = BIT(3), - BUF_RETRY = BIT(4), - BUF_XRETRY = BIT(5), -}; - -struct ath_buf_state { - int bfs_nframes; - u16 bfs_al; - u16 bfs_frmlen; - int bfs_seqno; - int bfs_tidno; - int bfs_retries; - u8 bf_type; - u32 bfs_keyix; - enum ath9k_key_type bfs_keytype; -}; - -#define bf_nframes bf_state.bfs_nframes -#define bf_al bf_state.bfs_al -#define bf_frmlen bf_state.bfs_frmlen -#define bf_retries bf_state.bfs_retries -#define bf_seqno bf_state.bfs_seqno -#define bf_tidno bf_state.bfs_tidno -#define bf_keyix bf_state.bfs_keyix -#define bf_keytype bf_state.bfs_keytype -#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) -#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) -#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) -#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) -#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) - -struct ath_buf { - struct list_head list; - struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or - an aggregate) */ - struct ath_buf *bf_next; /* next subframe in the aggregate */ - struct sk_buff *bf_mpdu; /* enclosing frame structure */ - struct ath_desc *bf_desc; /* virtual addr of desc */ - dma_addr_t bf_daddr; /* physical addr of desc */ - dma_addr_t bf_buf_addr; /* physical addr of data buffer */ - bool bf_stale; - u16 bf_flags; - struct ath_buf_state bf_state; - dma_addr_t bf_dmacontext; -}; - -struct ath_descdma { - struct ath_desc *dd_desc; - dma_addr_t dd_desc_paddr; - u32 dd_desc_len; - struct ath_buf *dd_bufptr; -}; - -int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head, const char *name, - int nbuf, int ndesc); -void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head); - -/***********/ -/* RX / TX */ -/***********/ - -#define ATH_MAX_ANTENNA 3 -#define ATH_RXBUF 512 -#define WME_NUM_TID 16 -#define ATH_TXBUF 512 -#define ATH_TXMAXTRY 13 -#define ATH_11N_TXMAXTRY 10 -#define ATH_MGT_TXMAXTRY 4 -#define WME_BA_BMP_SIZE 64 -#define WME_MAX_BA WME_BA_BMP_SIZE -#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) - -#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 WME_AC_BE 0 -#define WME_AC_BK 1 -#define WME_AC_VI 2 -#define WME_AC_VO 3 -#define WME_NUM_AC 4 - -#define ADDBA_EXCHANGE_ATTEMPTS 10 -#define ATH_AGGR_DELIM_SZ 4 -#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ -/* number of delimiters for encryption padding */ -#define ATH_AGGR_ENCRYPTDELIM 10 -/* minimum h/w qdepth to be sustained to maximize aggregation */ -#define ATH_AGGR_MIN_QDEPTH 2 -#define ATH_AMPDU_SUBFRAME_DEFAULT 32 -#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) -#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX - -#define IEEE80211_SEQ_SEQ_SHIFT 4 -#define IEEE80211_SEQ_MAX 4096 -#define IEEE80211_MIN_AMPDU_BUF 0x8 -#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 -#define IEEE80211_WEP_IVLEN 3 -#define IEEE80211_WEP_KIDLEN 1 -#define IEEE80211_WEP_CRCLEN 4 -#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \ - (IEEE80211_WEP_IVLEN + \ - IEEE80211_WEP_KIDLEN + \ - IEEE80211_WEP_CRCLEN)) - -/* return whether a bit at index _n in bitmap _bm is set - * _sz is the size of the bitmap */ -#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ - ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) - -/* return block-ack bitmap index given sequence and starting sequence */ -#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) - -/* returns delimiter padding required given the packet length */ -#define ATH_AGGR_GET_NDELIM(_len) \ - (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ - (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) - -#define BAW_WITHIN(_start, _bawsz, _seqno) \ - ((((_seqno) - (_start)) & 4095) < (_bawsz)) - -#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) -#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) -#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) -#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) - -enum ATH_AGGR_STATUS { - ATH_AGGR_DONE, - ATH_AGGR_BAW_CLOSED, - ATH_AGGR_LIMITED, -}; - -struct ath_txq { - u32 axq_qnum; - u32 *axq_link; - struct list_head axq_q; - spinlock_t axq_lock; - u32 axq_depth; - u8 axq_aggr_depth; - u32 axq_totalqueued; - bool stopped; - struct ath_buf *axq_linkbuf; - - /* first desc of the last descriptor that contains CTS */ - struct ath_desc *axq_lastdsWithCTS; - - /* final desc of the gating desc that determines whether - lastdsWithCTS has been DMA'ed or not */ - struct ath_desc *axq_gatingds; - - struct list_head axq_acq; -}; - -#define AGGR_CLEANUP BIT(1) -#define AGGR_ADDBA_COMPLETE BIT(2) -#define AGGR_ADDBA_PROGRESS BIT(3) - -struct ath_atx_tid { - struct list_head list; - struct list_head buf_q; - struct ath_node *an; - struct ath_atx_ac *ac; - struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; - u16 seq_start; - u16 seq_next; - u16 baw_size; - int tidno; - int baw_head; /* first un-acked tx buffer */ - int baw_tail; /* next unused tx buffer slot */ - int sched; - int paused; - u8 state; - int addba_exchangeattempts; -}; - -struct ath_atx_ac { - int sched; - int qnum; - struct list_head list; - struct list_head tid_q; -}; - -struct ath_tx_control { - struct ath_txq *txq; - int if_id; - enum ath9k_internal_frame_type frame_type; -}; - -#define ATH_TX_ERROR 0x01 -#define ATH_TX_XRETRY 0x02 -#define ATH_TX_BAR 0x04 - -struct ath_node { - struct ath_softc *an_sc; - struct ath_atx_tid tid[WME_NUM_TID]; - struct ath_atx_ac ac[WME_NUM_AC]; - u16 maxampdu; - u8 mpdudensity; -}; - -struct ath_tx { - u16 seq_no; - u32 txqsetup; - int hwq_map[ATH9K_WME_AC_VO+1]; - spinlock_t txbuflock; - struct list_head txbuf; - struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; - struct ath_descdma txdma; -}; - -struct ath_rx { - u8 defant; - u8 rxotherant; - u32 *rxlink; - int bufsize; - unsigned int rxfilter; - spinlock_t rxflushlock; - spinlock_t rxbuflock; - struct list_head rxbuf; - struct ath_descdma rxdma; -}; - -int ath_startrecv(struct ath_softc *sc); -bool ath_stoprecv(struct ath_softc *sc); -void ath_flushrecv(struct ath_softc *sc); -u32 ath_calcrxfilter(struct ath_softc *sc); -int ath_rx_init(struct ath_softc *sc, int nbufs); -void ath_rx_cleanup(struct ath_softc *sc); -int ath_rx_tasklet(struct ath_softc *sc, int flush); -struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); -void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); -int ath_tx_setup(struct ath_softc *sc, int haltype); -void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); -void ath_draintxq(struct ath_softc *sc, - struct ath_txq *txq, bool retry_tx); -void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); -void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); -void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); -int ath_tx_init(struct ath_softc *sc, int nbufs); -void ath_tx_cleanup(struct ath_softc *sc); -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); -int ath_txq_update(struct ath_softc *sc, int qnum, - struct ath9k_tx_queue_info *q); -int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath_tx_control *txctl); -void ath_tx_tasklet(struct ath_softc *sc); -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); -bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); -int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, - u16 tid, u16 *ssn); -int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); -void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); - -/********/ -/* VIFs */ -/********/ - -struct ath_vif { - int av_bslot; - __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ - enum nl80211_iftype av_opmode; - struct ath_buf *av_bcbuf; - struct ath_tx_control av_btxctl; - u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ -}; - -/*******************/ -/* Beacon Handling */ -/*******************/ - -/* - * Regardless of the number of beacons we stagger, (i.e. regardless of the - * number of BSSIDs) if a given beacon does not go out even after waiting this - * number of beacon intervals, the game's up. - */ -#define BSTUCK_THRESH (9 * ATH_BCBUF) -#define ATH_BCBUF 4 -#define ATH_DEFAULT_BINTVAL 100 /* TU */ -#define ATH_DEFAULT_BMISS_LIMIT 10 -#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) - -struct ath_beacon_config { - u16 beacon_interval; - u16 listen_interval; - u16 dtim_period; - u16 bmiss_timeout; - u8 dtim_count; -}; - -struct ath_beacon { - enum { - OK, /* no change needed */ - UPDATE, /* update pending */ - COMMIT /* beacon sent, commit change */ - } updateslot; /* slot time update fsm */ - - u32 beaconq; - u32 bmisscnt; - u32 ast_be_xmit; - u64 bc_tstamp; - struct ieee80211_vif *bslot[ATH_BCBUF]; - struct ath_wiphy *bslot_aphy[ATH_BCBUF]; - int slottime; - int slotupdate; - struct ath9k_tx_queue_info beacon_qi; - struct ath_descdma bdma; - struct ath_txq *cabq; - struct list_head bbuf; -}; - -void ath_beacon_tasklet(unsigned long data); -void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); -int ath_beaconq_setup(struct ath_hw *ah); -int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); -void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); - -/*******/ -/* ANI */ -/*******/ - -#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ -#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ -#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ -#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ -#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ - -struct ath_ani { - bool caldone; - int16_t noise_floor; - unsigned int longcal_timer; - unsigned int shortcal_timer; - unsigned int resetcal_timer; - unsigned int checkani_timer; - struct timer_list timer; -}; - -/********************/ -/* LED Control */ -/********************/ - -#define ATH_LED_PIN 1 -#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ -#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ - -enum ath_led_type { - ATH_LED_RADIO, - ATH_LED_ASSOC, - ATH_LED_TX, - ATH_LED_RX -}; - -struct ath_led { - struct ath_softc *sc; - struct led_classdev led_cdev; - enum ath_led_type led_type; - char name[32]; - bool registered; -}; - -/* Rfkill */ -#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */ - -struct ath_rfkill { - struct rfkill *rfkill; - struct delayed_work rfkill_poll; - char rfkill_name[32]; -}; - -/********************/ -/* Main driver core */ -/********************/ - -/* - * Default cache line size, in bytes. - * Used when PCI device not fully initialized by bootrom/BIOS -*/ -#define DEFAULT_CACHELINE 32 -#define ATH_DEFAULT_NOISE_FLOOR -95 -#define ATH_REGCLASSIDS_MAX 10 -#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ -#define ATH_MAX_SW_RETRIES 10 -#define ATH_CHAN_MAX 255 -#define IEEE80211_WEP_NKID 4 /* number of key ids */ - -/* - * The key cache is used for h/w cipher state and also for - * tracking station state such as the current tx antenna. - * We also setup a mapping table between key cache slot indices - * and station state to short-circuit node lookups on rx. - * Different parts have different size key caches. We handle - * up to ATH_KEYMAX entries (could dynamically allocate state). - */ -#define ATH_KEYMAX 128 /* max key cache size we handle */ - -#define ATH_TXPOWER_MAX 100 /* .5 dBm units */ -#define ATH_RSSI_DUMMY_MARKER 0x127 -#define ATH_RATE_DUMMY_MARKER 0 - -#define SC_OP_INVALID BIT(0) -#define SC_OP_BEACONS BIT(1) -#define SC_OP_RXAGGR BIT(2) -#define SC_OP_TXAGGR BIT(3) -#define SC_OP_FULL_RESET BIT(4) -#define SC_OP_PREAMBLE_SHORT BIT(5) -#define SC_OP_PROTECT_ENABLE BIT(6) -#define SC_OP_RXFLUSH BIT(7) -#define SC_OP_LED_ASSOCIATED BIT(8) -#define SC_OP_RFKILL_REGISTERED BIT(9) -#define SC_OP_RFKILL_SW_BLOCKED BIT(10) -#define SC_OP_RFKILL_HW_BLOCKED BIT(11) -#define SC_OP_WAIT_FOR_BEACON BIT(12) -#define SC_OP_LED_ON BIT(13) -#define SC_OP_SCANNING BIT(14) -#define SC_OP_TSF_RESET BIT(15) - -struct ath_bus_ops { - void (*read_cachesize)(struct ath_softc *sc, int *csz); - void (*cleanup)(struct ath_softc *sc); - bool (*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data); -}; - -struct ath_wiphy; - -struct ath_softc { - struct ieee80211_hw *hw; - struct device *dev; - - spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ - struct ath_wiphy *pri_wiphy; - struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may - * have NULL entries */ - int num_sec_wiphy; /* number of sec_wiphy pointers in the array */ - int chan_idx; - int chan_is_ht; - struct ath_wiphy *next_wiphy; - struct work_struct chan_work; - int wiphy_select_failures; - unsigned long wiphy_select_first_fail; - struct delayed_work wiphy_work; - unsigned long wiphy_scheduler_int; - int wiphy_scheduler_index; - - struct tasklet_struct intr_tq; - struct tasklet_struct bcon_tasklet; - struct ath_hw *sc_ah; - void __iomem *mem; - int irq; - spinlock_t sc_resetlock; - spinlock_t sc_serial_rw; - struct mutex mutex; - - u8 curbssid[ETH_ALEN]; - u8 bssidmask[ETH_ALEN]; - u32 intrstatus; - u32 sc_flags; /* SC_OP_* */ - u16 curtxpow; - u16 curaid; - u16 cachelsz; - u8 nbcnvifs; - u16 nvifs; - u8 tx_chainmask; - u8 rx_chainmask; - u32 keymax; - DECLARE_BITMAP(keymap, ATH_KEYMAX); - u8 splitmic; - atomic_t ps_usecount; - enum ath9k_int imask; - enum ath9k_ht_extprotspacing ht_extprotspacing; - enum ath9k_ht_macmode tx_chan_width; - - struct ath_config config; - struct ath_rx rx; - struct ath_tx tx; - struct ath_beacon beacon; - struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; - struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; - struct ath_rate_table *cur_rate_table; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - - struct ath_led radio_led; - struct ath_led assoc_led; - struct ath_led tx_led; - struct ath_led rx_led; - struct delayed_work ath_led_blink_work; - int led_on_duration; - int led_off_duration; - int led_on_cnt; - int led_off_cnt; - - struct ath_rfkill rf_kill; - struct ath_ani ani; - struct ath9k_node_stats nodestats; -#ifdef CONFIG_ATH9K_DEBUG - struct ath9k_debug debug; -#endif - struct ath_bus_ops *bus_ops; -}; - -struct ath_wiphy { - struct ath_softc *sc; /* shared for all virtual wiphys */ - struct ieee80211_hw *hw; - enum ath_wiphy_state { - ATH_WIPHY_INACTIVE, - ATH_WIPHY_ACTIVE, - ATH_WIPHY_PAUSING, - ATH_WIPHY_PAUSED, - ATH_WIPHY_SCAN, - } state; - int chan_idx; - int chan_is_ht; -}; - -int ath_reset(struct ath_softc *sc, bool retry_tx); -int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); -int ath_cabq_update(struct ath_softc *); - -static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) -{ - sc->bus_ops->read_cachesize(sc, csz); -} - -static inline void ath_bus_cleanup(struct ath_softc *sc) -{ - sc->bus_ops->cleanup(sc); -} - -extern struct ieee80211_ops ath9k_ops; - -irqreturn_t ath_isr(int irq, void *dev); -void ath_cleanup(struct ath_softc *sc); -int ath_attach(u16 devid, struct ath_softc *sc); -void ath_detach(struct ath_softc *sc); -const char *ath_mac_bb_name(u32 mac_bb_version); -const char *ath_rf_name(u16 rf_version); -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); -void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *ichan); -void ath_update_chainmask(struct ath_softc *sc, int is_ht); -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *hchan); -void ath_radio_enable(struct ath_softc *sc); -void ath_radio_disable(struct ath_softc *sc); - -#ifdef CONFIG_PCI -int ath_pci_init(void); -void ath_pci_exit(void); -#else -static inline int ath_pci_init(void) { return 0; }; -static inline void ath_pci_exit(void) {}; -#endif - -#ifdef CONFIG_ATHEROS_AR71XX -int ath_ahb_init(void); -void ath_ahb_exit(void); -#else -static inline int ath_ahb_init(void) { return 0; }; -static inline void ath_ahb_exit(void) {}; -#endif - -static inline void ath9k_ps_wakeup(struct ath_softc *sc) -{ - if (atomic_inc_return(&sc->ps_usecount) == 1) - if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { - sc->sc_ah->restore_mode = sc->sc_ah->power_mode; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - } -} - -static inline void ath9k_ps_restore(struct ath_softc *sc) -{ - if (atomic_dec_and_test(&sc->ps_usecount)) - if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && - !(sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) - ath9k_hw_setpower(sc->sc_ah, - sc->sc_ah->restore_mode); -} - - -void ath9k_set_bssid_mask(struct ieee80211_hw *hw); -int ath9k_wiphy_add(struct ath_softc *sc); -int ath9k_wiphy_del(struct ath_wiphy *aphy); -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); -int ath9k_wiphy_pause(struct ath_wiphy *aphy); -int ath9k_wiphy_unpause(struct ath_wiphy *aphy); -int ath9k_wiphy_select(struct ath_wiphy *aphy); -void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int); -void ath9k_wiphy_chan_work(struct work_struct *work); -bool ath9k_wiphy_started(struct ath_softc *sc); -void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, - struct ath_wiphy *selected); -bool ath9k_wiphy_scanning(struct ath_softc *sc); -void ath9k_wiphy_work(struct work_struct *work); - -/* - * Read and write, they both share the same lock. We do this to serialize - * reads and writes on Atheros 802.11n PCI devices only. This is required - * as the FIFO on these devices can only accept sanely 2 requests. After - * that the device goes bananas. Serializing the reads/writes prevents this - * from happening. - */ - -static inline void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) -{ - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - iowrite32(val, ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - iowrite32(val, ah->ah_sc->mem + reg_offset); -} - -static inline unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) -{ - u32 val; - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - val = ioread32(ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - val = ioread32(ah->ah_sc->mem + reg_offset); - return val; -} - -#endif /* ATH9K_H */ diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c deleted file mode 100644 index eb4759fc6a0d..000000000000 --- a/drivers/net/wireless/ath9k/beacon.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * 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 "ath9k.h" - -#define FUDGE 2 - -/* - * This function will modify certain transmit queue properties depending on - * the operating mode of the station (AP or AdHoc). Parameters are AIFS - * settings and channel width min/max -*/ -static int ath_beaconq_config(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_tx_queue_info qi; - - ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { - /* Always burst out beacon and CAB traffic. */ - qi.tqi_aifs = 1; - qi.tqi_cwmin = 0; - qi.tqi_cwmax = 0; - } else { - /* Adhoc mode; important thing is to use 2x cwmin. */ - qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs; - qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin; - qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax; - } - - if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to update h/w beacon queue parameters\n"); - return 0; - } else { - ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); - return 1; - } -} - -/* - * Associates the beacon frame buffer with a transmit descriptor. Will set - * up all required antenna switch parameters, rate codes, and channel flags. - * Beacons are always sent out at the lowest rate, and are not retried. -*/ -static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, - struct ath_buf *bf) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ath_hw *ah = sc->sc_ah; - struct ath_desc *ds; - struct ath9k_11n_rate_series series[4]; - struct ath_rate_table *rt; - int flags, antenna, ctsrate = 0, ctsduration = 0; - u8 rate; - - ds = bf->bf_desc; - flags = ATH9K_TXDESC_NOACK; - - if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && - (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { - ds->ds_link = bf->bf_daddr; /* self-linked */ - flags |= ATH9K_TXDESC_VEOL; - /* Let hardware handle antenna switching. */ - antenna = 0; - } else { - ds->ds_link = 0; - /* - * Switch antenna every beacon. - * Should only switch every beacon period, not for every SWBA - * XXX assumes two antennae - */ - antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); - } - - ds->ds_data = bf->bf_buf_addr; - - rt = sc->cur_rate_table; - rate = rt->info[0].ratecode; - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - rate |= rt->info[0].short_preamble; - - ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, - ATH9K_PKT_TYPE_BEACON, - MAX_RATE_POWER, - ATH9K_TXKEYIX_INVALID, - ATH9K_KEY_TYPE_CLEAR, - flags); - - /* NB: beacon's BufLen must be a multiple of 4 bytes */ - ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), - true, true, ds); - - memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - series[0].Tries = 1; - series[0].Rate = rate; - series[0].ChSel = sc->tx_chainmask; - series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; - ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, - series, 4, 0); -} - -static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_buf *bf; - struct ath_vif *avp; - struct sk_buff *skb; - struct ath_txq *cabq; - struct ieee80211_tx_info *info; - int cabq_depth; - - if (aphy->state != ATH_WIPHY_ACTIVE) - return NULL; - - avp = (void *)vif->drv_priv; - cabq = sc->beacon.cabq; - - if (avp->av_bcbuf == NULL) - return NULL; - - /* Release the old beacon first */ - - bf = avp->av_bcbuf; - skb = bf->bf_mpdu; - if (skb) { - dma_unmap_single(sc->dev, bf->bf_dmacontext, - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - } - - /* Get a new beacon from mac80211 */ - - skb = ieee80211_beacon_get(hw, vif); - bf->bf_mpdu = skb; - if (skb == NULL) - return NULL; - ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = - avp->tsf_adjust; - - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - /* - * TODO: make sure the seq# gets assigned properly (vs. other - * TX frames) - */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - bf->bf_buf_addr = bf->bf_dmacontext = - dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n"); - return NULL; - } - - skb = ieee80211_get_buffered_bc(hw, vif); - - /* - * if the CABQ traffic from previous DTIM is pending and the current - * beacon is also a DTIM. - * 1) if there is only one vif let the cab traffic continue. - * 2) if there are more than one vif and we are using staggered - * beacons, then drain the cabq by dropping all the frames in - * the cabq so that the current vifs cab traffic can be scheduled. - */ - spin_lock_bh(&cabq->axq_lock); - cabq_depth = cabq->axq_depth; - spin_unlock_bh(&cabq->axq_lock); - - if (skb && cabq_depth) { - if (sc->nvifs > 1) { - DPRINTF(sc, ATH_DBG_BEACON, - "Flushing previous cabq traffic\n"); - ath_draintxq(sc, cabq, false); - } - } - - ath_beacon_setup(sc, avp, bf); - - while (skb) { - ath_tx_cabq(hw, skb); - skb = ieee80211_get_buffered_bc(hw, vif); - } - - return bf; -} - -/* - * Startup beacon transmission for adhoc mode when they are sent entirely - * by the hardware using the self-linked descriptor + veol trick. -*/ -static void ath_beacon_start_adhoc(struct ath_softc *sc, - struct ieee80211_vif *vif) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf; - struct ath_vif *avp; - struct sk_buff *skb; - - avp = (void *)vif->drv_priv; - - if (avp->av_bcbuf == NULL) - return; - - bf = avp->av_bcbuf; - skb = bf->bf_mpdu; - - ath_beacon_setup(sc, avp, bf); - - /* NB: caller is known to have already stopped tx dma */ - ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); - ath9k_hw_txstart(ah, sc->beacon.beaconq); - DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", - sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); -} - -int ath_beaconq_setup(struct ath_hw *ah) -{ - struct ath9k_tx_queue_info qi; - - memset(&qi, 0, sizeof(qi)); - qi.tqi_aifs = 1; - qi.tqi_cwmin = 0; - qi.tqi_cwmax = 0; - /* NB: don't enable any interrupts */ - return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); -} - -int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) -{ - struct ath_softc *sc = aphy->sc; - struct ath_vif *avp; - struct ath_buf *bf; - struct sk_buff *skb; - __le64 tstamp; - - avp = (void *)vif->drv_priv; - - /* Allocate a beacon descriptor if we haven't done so. */ - if (!avp->av_bcbuf) { - /* Allocate beacon state for hostap/ibss. We know - * a buffer is available. */ - avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, - struct ath_buf, list); - list_del(&avp->av_bcbuf->list); - - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || - !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { - int slot; - /* - * Assign the vif to a beacon xmit slot. As - * above, this cannot fail to find one. - */ - avp->av_bslot = 0; - for (slot = 0; slot < ATH_BCBUF; slot++) - if (sc->beacon.bslot[slot] == NULL) { - /* - * XXX hack, space out slots to better - * deal with misses - */ - if (slot+1 < ATH_BCBUF && - sc->beacon.bslot[slot+1] == NULL) { - avp->av_bslot = slot+1; - break; - } - avp->av_bslot = slot; - /* NB: keep looking for a double slot */ - } - BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); - sc->beacon.bslot[avp->av_bslot] = vif; - sc->beacon.bslot_aphy[avp->av_bslot] = aphy; - sc->nbcnvifs++; - } - } - - /* release the previous beacon frame, if it already exists. */ - bf = avp->av_bcbuf; - if (bf->bf_mpdu != NULL) { - skb = bf->bf_mpdu; - dma_unmap_single(sc->dev, bf->bf_dmacontext, - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - } - - /* NB: the beacon data buffer must be 32-bit aligned. */ - skb = ieee80211_beacon_get(sc->hw, vif); - if (skb == NULL) { - DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n"); - return -ENOMEM; - } - - tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - sc->beacon.bc_tstamp = le64_to_cpu(tstamp); - /* Calculate a TSF adjustment factor required for staggered beacons. */ - if (avp->av_bslot > 0) { - u64 tsfadjust; - int intval; - - intval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; - - /* - * Calculate the TSF offset for this beacon slot, i.e., the - * number of usecs that need to be added to the timestamp field - * in Beacon and Probe Response frames. Beacon slot 0 is - * processed at the correct offset, so it does not require TSF - * adjustment. Other slots are adjusted to get the timestamp - * close to the TBTT for the BSS. - */ - tsfadjust = intval * avp->av_bslot / ATH_BCBUF; - avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); - - DPRINTF(sc, ATH_DBG_BEACON, - "stagger beacons, bslot %d intval %u tsfadjust %llu\n", - avp->av_bslot, intval, (unsigned long long)tsfadjust); - - ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = - avp->tsf_adjust; - } else - avp->tsf_adjust = cpu_to_le64(0); - - bf->bf_mpdu = skb; - bf->bf_buf_addr = bf->bf_dmacontext = - dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error on beacon alloc\n"); - return -ENOMEM; - } - - return 0; -} - -void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) -{ - if (avp->av_bcbuf != NULL) { - struct ath_buf *bf; - - if (avp->av_bslot != -1) { - sc->beacon.bslot[avp->av_bslot] = NULL; - sc->beacon.bslot_aphy[avp->av_bslot] = NULL; - sc->nbcnvifs--; - } - - bf = avp->av_bcbuf; - if (bf->bf_mpdu != NULL) { - struct sk_buff *skb = bf->bf_mpdu; - dma_unmap_single(sc->dev, bf->bf_dmacontext, - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - } - list_add_tail(&bf->list, &sc->beacon.bbuf); - - avp->av_bcbuf = NULL; - } -} - -void ath_beacon_tasklet(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf = NULL; - struct ieee80211_vif *vif; - struct ath_wiphy *aphy; - int slot; - u32 bfaddr, bc = 0, tsftu; - u64 tsf; - u16 intval; - - /* - * Check if the previous beacon has gone out. If - * not don't try to post another, skip this period - * and wait for the next. Missed beacons indicate - * a problem and should not occur. If we miss too - * many consecutive beacons reset the device. - */ - if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { - sc->beacon.bmisscnt++; - - if (sc->beacon.bmisscnt < BSTUCK_THRESH) { - DPRINTF(sc, ATH_DBG_BEACON, - "missed %u consecutive beacons\n", - sc->beacon.bmisscnt); - } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { - DPRINTF(sc, ATH_DBG_BEACON, - "beacon is officially stuck\n"); - ath_reset(sc, false); - } - - return; - } - - if (sc->beacon.bmisscnt != 0) { - DPRINTF(sc, ATH_DBG_BEACON, - "resume beacon xmit after %u misses\n", - sc->beacon.bmisscnt); - sc->beacon.bmisscnt = 0; - } - - /* - * Generate beacon frames. we are sending frames - * staggered so calculate the slot for this frame based - * on the tsf to safeguard against missing an swba. - */ - - intval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; - - tsf = ath9k_hw_gettsf64(ah); - tsftu = TSF_TO_TU(tsf>>32, tsf); - slot = ((tsftu % intval) * ATH_BCBUF) / intval; - /* - * Reverse the slot order to get slot 0 on the TBTT offset that does - * not require TSF adjustment and other slots adding - * slot/ATH_BCBUF * beacon_int to timestamp. For example, with - * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. - * and slot 0 is at correct offset to TBTT. - */ - slot = ATH_BCBUF - slot - 1; - vif = sc->beacon.bslot[slot]; - aphy = sc->beacon.bslot_aphy[slot]; - - DPRINTF(sc, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu, intval, vif); - - bfaddr = 0; - if (vif) { - bf = ath_beacon_generate(aphy->hw, vif); - if (bf != NULL) { - bfaddr = bf->bf_daddr; - bc = 1; - } - } - - /* - * Handle slot time change when a non-ERP station joins/leaves - * an 11g network. The 802.11 layer notifies us via callback, - * we mark updateslot, then wait one beacon before effecting - * the change. This gives associated stations at least one - * beacon interval to note the state change. - * - * NB: The slot time change state machine is clocked according - * to whether we are bursting or staggering beacons. We - * recognize the request to update and record the current - * slot then don't transition until that slot is reached - * again. If we miss a beacon for that slot then we'll be - * slow to transition but we'll be sure at least one beacon - * interval has passed. When bursting slot is always left - * set to ATH_BCBUF so this check is a noop. - */ - if (sc->beacon.updateslot == UPDATE) { - sc->beacon.updateslot = COMMIT; /* commit next beacon */ - sc->beacon.slotupdate = slot; - } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { - ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); - sc->beacon.updateslot = OK; - } - if (bfaddr != 0) { - /* - * Stop any current dma and put the new frame(s) on the queue. - * This should never fail since we check above that no frames - * are still pending on the queue. - */ - if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { - DPRINTF(sc, ATH_DBG_FATAL, - "beacon queue %u did not stop?\n", sc->beacon.beaconq); - } - - /* NB: cabq traffic should already be queued and primed */ - ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); - ath9k_hw_txstart(ah, sc->beacon.beaconq); - - sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ - } -} - -/* - * For multi-bss ap support beacons are either staggered evenly over N slots or - * burst together. For the former arrange for the SWBA to be delivered for each - * slot. Slots that are not occupied will generate nothing. - */ -static void ath_beacon_config_ap(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ath_vif *avp) -{ - u32 nexttbtt, intval; - - /* Configure the timers only when the TSF has to be reset */ - - if (!(sc->sc_flags & SC_OP_TSF_RESET)) - return; - - /* NB: the beacon interval is kept internally in TU's */ - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - intval /= ATH_BCBUF; /* for staggered beacons */ - nexttbtt = intval; - intval |= ATH9K_BEACON_RESET_TSF; - - /* - * In AP mode we enable the beacon timers and SWBA interrupts to - * prepare beacon frames. - */ - intval |= ATH9K_BEACON_ENA; - sc->imask |= ATH9K_INT_SWBA; - ath_beaconq_config(sc); - - /* Set the computed AP beacon timers */ - - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); - sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - /* Clear the reset TSF flag, so that subsequent beacon updation - will not reset the HW TSF. */ - - sc->sc_flags &= ~SC_OP_TSF_RESET; -} - -/* - * This sets up the beacon timers according to the timestamp of the last - * received beacon and the current TSF, configures PCF and DTIM - * handling, programs the sleep registers so the hardware will wakeup in - * time to receive beacons, and configures the beacon miss handling so - * we'll receive a BMISS interrupt when we stop seeing beacons from the AP - * we've associated with. - */ -static void ath_beacon_config_sta(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ath_vif *avp) -{ - struct ath9k_beacon_state bs; - int dtimperiod, dtimcount, sleepduration; - int cfpperiod, cfpcount; - u32 nexttbtt = 0, intval, tsftu; - u64 tsf; - - memset(&bs, 0, sizeof(bs)); - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - - /* - * Setup dtim and cfp parameters according to - * last beacon we received (which may be none). - */ - dtimperiod = conf->dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ - dtimperiod = 1; - dtimcount = conf->dtim_count; - if (dtimcount >= dtimperiod) /* NB: sanity check */ - dtimcount = 0; - cfpperiod = 1; /* NB: no PCF support yet */ - cfpcount = 0; - - sleepduration = conf->listen_interval * intval; - if (sleepduration <= 0) - sleepduration = intval; - - /* - * Pull nexttbtt forward to reflect the current - * TSF and calculate dtim+cfp state for the result. - */ - tsf = ath9k_hw_gettsf64(sc->sc_ah); - tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; - do { - nexttbtt += intval; - if (--dtimcount < 0) { - dtimcount = dtimperiod - 1; - if (--cfpcount < 0) - cfpcount = cfpperiod - 1; - } - } while (nexttbtt < tsftu); - - bs.bs_intval = intval; - bs.bs_nexttbtt = nexttbtt; - bs.bs_dtimperiod = dtimperiod*intval; - bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; - bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; - bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; - bs.bs_cfpmaxduration = 0; - - /* - * Calculate the number of consecutive beacons to miss* before taking - * a BMISS interrupt. The configuration is specified in TU so we only - * need calculate based on the beacon interval. Note that we clamp the - * result to at most 15 beacons. - */ - if (sleepduration > intval) { - bs.bs_bmissthreshold = conf->listen_interval * - ATH_DEFAULT_BMISS_LIMIT / 2; - } else { - bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval); - if (bs.bs_bmissthreshold > 15) - bs.bs_bmissthreshold = 15; - else if (bs.bs_bmissthreshold <= 0) - bs.bs_bmissthreshold = 1; - } - - /* - * Calculate sleep duration. The configuration is given in ms. - * We ensure a multiple of the beacon period is used. Also, if the sleep - * duration is greater than the DTIM period then it makes senses - * to make it a multiple of that. - * - * XXX fixed at 100ms - */ - - bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); - if (bs.bs_sleepduration > bs.bs_dtimperiod) - bs.bs_sleepduration = bs.bs_dtimperiod; - - /* TSF out of range threshold fixed at 1 second */ - bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; - - DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); - DPRINTF(sc, ATH_DBG_BEACON, - "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", - bs.bs_bmissthreshold, bs.bs_sleepduration, - bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); - - /* Set the computed STA beacon timers */ - - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); - sc->imask |= ATH9K_INT_BMISS; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); -} - -static void ath_beacon_config_adhoc(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ath_vif *avp, - struct ieee80211_vif *vif) -{ - u64 tsf; - u32 tsftu, intval, nexttbtt; - - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - - /* Pull nexttbtt forward to reflect the current TSF */ - - nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); - if (nexttbtt == 0) - nexttbtt = intval; - else if (intval) - nexttbtt = roundup(nexttbtt, intval); - - tsf = ath9k_hw_gettsf64(sc->sc_ah); - tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; - do { - nexttbtt += intval; - } while (nexttbtt < tsftu); - - DPRINTF(sc, ATH_DBG_BEACON, - "IBSS nexttbtt %u intval %u (%u)\n", - nexttbtt, intval, conf->beacon_interval); - - /* - * In IBSS mode enable the beacon timers but only enable SWBA interrupts - * if we need to manually prepare beacon frames. Otherwise we use a - * self-linked tx descriptor and let the hardware deal with things. - */ - intval |= ATH9K_BEACON_ENA; - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) - sc->imask |= ATH9K_INT_SWBA; - - ath_beaconq_config(sc); - - /* Set the computed ADHOC beacon timers */ - - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); - sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) - ath_beacon_start_adhoc(sc, vif); -} - -void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) -{ - struct ath_beacon_config conf; - - /* Setup the beacon configuration parameters */ - - memset(&conf, 0, sizeof(struct ath_beacon_config)); - conf.beacon_interval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; - conf.listen_interval = 1; - conf.dtim_period = conf.beacon_interval; - conf.dtim_count = 1; - conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; - - if (vif) { - struct ath_vif *avp = (struct ath_vif *)vif->drv_priv; - - switch(avp->av_opmode) { - case NL80211_IFTYPE_AP: - ath_beacon_config_ap(sc, &conf, avp); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - ath_beacon_config_adhoc(sc, &conf, avp, vif); - break; - case NL80211_IFTYPE_STATION: - ath_beacon_config_sta(sc, &conf, avp); - break; - default: - DPRINTF(sc, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); - return; - } - - sc->sc_flags |= SC_OP_BEACONS; - } -} diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c deleted file mode 100644 index e2d62e97131c..000000000000 --- a/drivers/net/wireless/ath9k/calib.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * 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 "ath9k.h" - -/* We can tune this as we go by monitoring really low values */ -#define ATH9K_NF_TOO_LOW -60 - -/* AR5416 may return very high value (like -31 dBm), in those cases the nf - * is incorrect and we should use the static NF value. Later we can try to - * find out why they are reporting these values */ - -static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) -{ - if (nf > ATH9K_NF_TOO_LOW) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "noise floor value detected (%d) is " - "lower than what we think is a " - "reasonable value (%d)\n", - nf, ATH9K_NF_TOO_LOW); - return false; - } - return true; -} - -static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) -{ - int16_t nfval; - int16_t sort[ATH9K_NF_CAL_HIST_MAX]; - int i, j; - - for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) - sort[i] = nfCalBuffer[i]; - - for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { - for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { - if (sort[j] > sort[j - 1]) { - nfval = sort[j]; - sort[j] = sort[j - 1]; - sort[j - 1] = nfval; - } - } - } - nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; - - return nfval; -} - -static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, - int16_t *nfarray) -{ - int i; - - for (i = 0; i < NUM_NF_READINGS; i++) { - h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; - - if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) - h[i].currIndex = 0; - - if (h[i].invalidNFcount > 0) { - if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || - nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { - h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; - } else { - h[i].invalidNFcount--; - h[i].privNF = nfarray[i]; - } - } else { - h[i].privNF = - ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); - } - } - return; -} - -static void ath9k_hw_do_getnf(struct ath_hw *ah, - int16_t nfarray[NUM_NF_READINGS]) -{ - int16_t nf; - - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 0] is %d\n", nf); - nfarray[0] = nf; - - if (!AR_SREV_9285(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR9280_PHY_CH1_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR_PHY_CH1_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 1] is %d\n", nf); - nfarray[1] = nf; - - if (!AR_SREV_9280(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), - AR_PHY_CH2_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[2] = nf; - } - } - - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), - AR9280_PHY_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), - AR_PHY_EXT_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 0] is %d\n", nf); - nfarray[3] = nf; - - if (!AR_SREV_9285(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR9280_PHY_CH1_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR_PHY_CH1_EXT_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 1] is %d\n", nf); - nfarray[4] = nf; - - if (!AR_SREV_9280(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), - AR_PHY_CH2_EXT_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 2] is %d\n", nf); - nfarray[5] = nf; - } - } -} - -static bool getNoiseFloorThresh(struct ath_hw *ah, - enum ieee80211_band band, - int16_t *nft) -{ - switch (band) { - case IEEE80211_BAND_5GHZ: - *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); - break; - case IEEE80211_BAND_2GHZ: - *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); - break; - default: - BUG_ON(1); - return false; - } - - return true; -} - -static void ath9k_hw_setup_calibration(struct ath_hw *ah, - struct hal_cal_list *currCal) -{ - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, - currCal->calData->calCountMax); - - switch (currCal->calData->calType) { - case IQ_MISMATCH_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting IQ Mismatch Calibration\n"); - break; - case ADC_GAIN_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting ADC Gain Calibration\n"); - break; - case ADC_DC_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting ADC DC Calibration\n"); - break; - case ADC_DC_INIT_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting Init ADC DC Calibration\n"); - break; - } - - REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_DO_CAL); -} - -static void ath9k_hw_reset_calibration(struct ath_hw *ah, - struct hal_cal_list *currCal) -{ - int i; - - ath9k_hw_setup_calibration(ah, currCal); - - currCal->calState = CAL_RUNNING; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->meas0.sign[i] = 0; - ah->meas1.sign[i] = 0; - ah->meas2.sign[i] = 0; - ah->meas3.sign[i] = 0; - } - - ah->cal_samples = 0; -} - -static void ath9k_hw_per_calibration(struct ath_hw *ah, - struct ath9k_channel *ichan, - u8 rxchainmask, - struct hal_cal_list *currCal, - bool *isCalDone) -{ - *isCalDone = false; - - if (currCal->calState == CAL_RUNNING) { - if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & - AR_PHY_TIMING_CTRL4_DO_CAL)) { - - currCal->calData->calCollect(ah); - ah->cal_samples++; - - if (ah->cal_samples >= currCal->calData->calNumSamples) { - int i, numChains = 0; - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (rxchainmask & (1 << i)) - numChains++; - } - - currCal->calData->calPostProc(ah, numChains); - ichan->CalValid |= currCal->calData->calType; - currCal->calState = CAL_DONE; - *isCalDone = true; - } else { - ath9k_hw_setup_calibration(ah, currCal); - } - } - } else if (!(ichan->CalValid & currCal->calData->calType)) { - ath9k_hw_reset_calibration(ah, currCal); - } -} - -/* Assumes you are talking about the currently configured channel */ -static bool ath9k_hw_iscal_supported(struct ath_hw *ah, - enum hal_cal_types calType) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - switch (calType & ah->supp_cals) { - case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ - return true; - case ADC_GAIN_CAL: - case ADC_DC_CAL: - if (conf->channel->band == IEEE80211_BAND_5GHZ && - conf_is_ht20(conf)) - return true; - break; - } - return false; -} - -static void ath9k_hw_iqcal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalPowerMeasI[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalPowerMeasQ[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalIqCorrMeas[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); - } -} - -static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalAdcIOddPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalAdcIEvenPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalAdcQOddPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ah->totalAdcQEvenPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcIOddPhase[i], - ah->totalAdcIEvenPhase[i], - ah->totalAdcQOddPhase[i], - ah->totalAdcQEvenPhase[i]); - } -} - -static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalAdcDcOffsetIOddPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalAdcDcOffsetIEvenPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalAdcDcOffsetQOddPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ah->totalAdcDcOffsetQEvenPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcDcOffsetIOddPhase[i], - ah->totalAdcDcOffsetIEvenPhase[i], - ah->totalAdcDcOffsetQOddPhase[i], - ah->totalAdcDcOffsetQEvenPhase[i]); - } -} - -static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) -{ - u32 powerMeasQ, powerMeasI, iqCorrMeas; - u32 qCoffDenom, iCoffDenom; - int32_t qCoff, iCoff; - int iqCorrNeg, i; - - for (i = 0; i < numChains; i++) { - powerMeasI = ah->totalPowerMeasI[i]; - powerMeasQ = ah->totalPowerMeasQ[i]; - iqCorrMeas = ah->totalIqCorrMeas[i]; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Starting IQ Cal and Correction for Chain %d\n", - i); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", - i, ah->totalIqCorrMeas[i]); - - iqCorrNeg = 0; - - if (iqCorrMeas > 0x80000000) { - iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; - iqCorrNeg = 1; - } - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", - iqCorrNeg); - - iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; - qCoffDenom = powerMeasQ / 64; - - if (powerMeasQ != 0) { - iCoff = iqCorrMeas / iCoffDenom; - qCoff = powerMeasI / qCoffDenom - 64; - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d iCoff = 0x%08x\n", i, iCoff); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d qCoff = 0x%08x\n", i, qCoff); - - iCoff = iCoff & 0x3f; - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "New: Chn %d iCoff = 0x%08x\n", i, iCoff); - if (iqCorrNeg == 0x0) - iCoff = 0x40 - iCoff; - - if (qCoff > 15) - qCoff = 15; - else if (qCoff <= -16) - qCoff = 16; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", - i, iCoff, qCoff); - - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, - iCoff); - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, - qCoff); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "IQ Cal and Correction done for Chain %d\n", - i); - } - } - - REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); -} - -static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) -{ - u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; - u32 qGainMismatch, iGainMismatch, val, i; - - for (i = 0; i < numChains; i++) { - iOddMeasOffset = ah->totalAdcIOddPhase[i]; - iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; - qOddMeasOffset = ah->totalAdcQOddPhase[i]; - qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Starting ADC Gain Cal for Chain %d\n", i); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = 0x%08x\n", i, - iOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = 0x%08x\n", i, - iEvenMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = 0x%08x\n", i, - qOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = 0x%08x\n", i, - qEvenMeasOffset); - - if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { - iGainMismatch = - ((iEvenMeasOffset * 32) / - iOddMeasOffset) & 0x3f; - qGainMismatch = - ((qOddMeasOffset * 32) / - qEvenMeasOffset) & 0x3f; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_i = 0x%08x\n", i, - iGainMismatch); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_q = 0x%08x\n", i, - qGainMismatch); - - val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xfffff000; - val |= (qGainMismatch) | (iGainMismatch << 6); - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "ADC Gain Cal done for Chain %d\n", i); - } - } - - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | - AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); -} - -static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) -{ - u32 iOddMeasOffset, iEvenMeasOffset, val, i; - int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; - const struct hal_percal_data *calData = - ah->cal_list_curr->calData; - u32 numSamples = - (1 << (calData->calCountMax + 5)) * calData->calNumSamples; - - for (i = 0; i < numChains; i++) { - iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; - iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; - qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; - qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Starting ADC DC Offset Cal for Chain %d\n", i); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = %d\n", i, - iOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = %d\n", i, - iEvenMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = %d\n", i, - qOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = %d\n", i, - qEvenMeasOffset); - - iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / - numSamples) & 0x1ff; - qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / - numSamples) & 0x1ff; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, - iDcMismatch); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, - qDcMismatch); - - val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xc0000fff; - val |= (qDcMismatch << 12) | (iDcMismatch << 21); - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "ADC DC Offset Cal done for Chain %d\n", i); - } - - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | - AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); -} - -/* This is done for the currently configured channel */ -bool ath9k_hw_reset_calvalid(struct ath_hw *ah) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct hal_cal_list *currCal = ah->cal_list_curr; - - if (!ah->curchan) - return true; - - if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) - return true; - - if (currCal == NULL) - return true; - - if (currCal->calState != CAL_DONE) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Calibration state incorrect, %d\n", - currCal->calState); - return true; - } - - if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) - return true; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Resetting Cal %d state for channel %u\n", - currCal->calData->calType, conf->channel->center_freq); - - ah->curchan->CalValid &= ~currCal->calData->calType; - currCal->calState = CAL_WAITING; - - return false; -} - -void ath9k_hw_start_nfcal(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_ENABLE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); -} - -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath9k_nfcal_hist *h; - int i, j; - int32_t val; - const u32 ar5416_cca_regs[6] = { - AR_PHY_CCA, - AR_PHY_CH1_CCA, - AR_PHY_CH2_CCA, - AR_PHY_EXT_CCA, - AR_PHY_CH1_EXT_CCA, - AR_PHY_CH2_EXT_CCA - }; - u8 chainmask; - - if (AR_SREV_9285(ah)) - chainmask = 0x9; - else if (AR_SREV_9280(ah)) - chainmask = 0x1B; - else - chainmask = 0x3F; - - h = ah->nfCalHist; - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (chainmask & (1 << i)) { - val = REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((u32) (h[i].privNF) << 1) & 0x1ff); - REG_WRITE(ah, ar5416_cca_regs[i], val); - } - } - - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_ENABLE_NF); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); - - for (j = 0; j < 1000; j++) { - if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & - AR_PHY_AGC_CONTROL_NF) == 0) - break; - udelay(10); - } - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (chainmask & (1 << i)) { - val = REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((u32) (-50) << 1) & 0x1ff); - REG_WRITE(ah, ar5416_cca_regs[i], val); - } - } -} - -int16_t ath9k_hw_getnf(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - int16_t nf, nfThresh; - int16_t nfarray[NUM_NF_READINGS] = { 0 }; - struct ath9k_nfcal_hist *h; - struct ieee80211_channel *c = chan->chan; - - chan->channelFlags &= (~CHANNEL_CW_INT); - if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF did not complete in calibration window\n"); - nf = 0; - chan->rawNoiseFloor = nf; - return chan->rawNoiseFloor; - } else { - ath9k_hw_do_getnf(ah, nfarray); - nf = nfarray[0]; - if (getNoiseFloorThresh(ah, c->band, &nfThresh) - && nf > nfThresh) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "noise floor failed detected; " - "detected %d, threshold %d\n", - nf, nfThresh); - chan->channelFlags |= CHANNEL_CW_INT; - } - } - - h = ah->nfCalHist; - - ath9k_hw_update_nfcal_hist_buffer(h, nfarray); - chan->rawNoiseFloor = h[0].privNF; - - return chan->rawNoiseFloor; -} - -void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) -{ - int i, j; - - for (i = 0; i < NUM_NF_READINGS; i++) { - ah->nfCalHist[i].currIndex = 0; - ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE; - ah->nfCalHist[i].invalidNFcount = - AR_PHY_CCA_FILTERWINDOW_LENGTH; - for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { - ah->nfCalHist[i].nfCalBuffer[j] = - AR_PHY_CCA_MAX_GOOD_VALUE; - } - } -} - -s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) -{ - s16 nf; - - if (chan->rawNoiseFloor == 0) - nf = -96; - else - nf = chan->rawNoiseFloor; - - if (!ath9k_hw_nf_in_range(ah, nf)) - nf = ATH_DEFAULT_NOISE_FLOOR; - - return nf; -} - -static void ath9k_olc_temp_compensation(struct ath_hw *ah) -{ - u32 rddata, i; - int delta, currPDADC, regval; - - rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); - - currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - - if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) - delta = (currPDADC - ah->initPDADC + 4) / 8; - else - delta = (currPDADC - ah->initPDADC + 5) / 10; - - if (delta != ah->PDADCdelta) { - ah->PDADCdelta = delta; - for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { - regval = ah->originalGain[i] - delta; - if (regval < 0) - regval = 0; - - REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, - AR_PHY_TX_GAIN, regval); - } - } -} - -static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) -{ - - u32 regVal; - int i, offset, offs_6_1, offs_0; - u32 ccomp_org, reg_field; - u32 regList[][2] = { - { 0x786c, 0 }, - { 0x7854, 0 }, - { 0x7820, 0 }, - { 0x7824, 0 }, - { 0x7868, 0 }, - { 0x783c, 0 }, - { 0x7838, 0 }, - }; - - if (AR_SREV_9285_11(ah)) { - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); - udelay(10); - } - - for (i = 0; i < ARRAY_SIZE(regList); i++) - regList[i][1] = REG_READ(ah, regList[i][0]); - - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1)); - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal |= (0x1 << 27); - REG_WRITE(ah, 0x9808, regVal); - - REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); - ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7); - - REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); - udelay(30); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); - - for (i = 6; i > 0; i--) { - regVal = REG_READ(ah, 0x7834); - regVal |= (1 << (19 + i)); - REG_WRITE(ah, 0x7834, regVal); - udelay(1); - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1 << (19 + i))); - reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); - regVal |= (reg_field << (19 + i)); - REG_WRITE(ah, 0x7834, regVal); - } - - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); - udelay(1); - reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); - offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); - offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); - - offset = (offs_6_1<<1) | offs_0; - offset = offset - 0; - offs_6_1 = offset>>1; - offs_0 = offset & 1; - - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); - - regVal = REG_READ(ah, 0x7834); - regVal |= 0x1; - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal &= (~(0x1 << 27)); - REG_WRITE(ah, 0x9808, regVal); - - for (i = 0; i < ARRAY_SIZE(regList); i++) - REG_WRITE(ah, regList[i][0], regList[i][1]); - - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - -} - -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone) -{ - struct hal_cal_list *currCal = ah->cal_list_curr; - - *isCalDone = true; - - if (currCal && - (currCal->calState == CAL_RUNNING || - currCal->calState == CAL_WAITING)) { - ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, - isCalDone); - if (*isCalDone) { - ah->cal_list_curr = currCal = currCal->calNext; - - if (currCal->calState == CAL_WAITING) { - *isCalDone = false; - ath9k_hw_reset_calibration(ah, currCal); - } - } - } - - if (longcal) { - if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) - ath9k_hw_9285_pa_cal(ah); - - if (OLC_FOR_AR9280_20_LATER) - ath9k_olc_temp_compensation(ah); - ath9k_hw_getnf(ah, chan); - ath9k_hw_loadnf(ah, ah->curchan); - ath9k_hw_start_nfcal(ah); - - if (chan->channelFlags & CHANNEL_CW_INT) - chan->channelFlags &= ~CHANNEL_CW_INT; - } - - return true; -} - -static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) -{ - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - if (chan->channelFlags & CHANNEL_HT20) { - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " - "calibration failed to complete in " - "1ms; noisy ??\n"); - return false; - } - REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - } - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " - "failed to complete in 1ms; noisy ??\n"); - return false; - } - - REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - - return true; -} - -bool ath9k_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { - if (!ar9285_clc(ah, chan)) - return false; - } else if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - - /* Kick off the cal */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); - - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, - AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; " - "noisy environment?\n"); - return false; - } - - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - } - - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); - - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; " - "noisy environment?\n"); - return false; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - } - - /* Do PA Calibration */ - if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) - ath9k_hw_9285_pa_cal(ah); - - /* Do NF Calibration */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_NF); - - ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; - - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { - if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { - INIT_CAL(&ah->adcgain_caldata); - INSERT_CAL(ah, &ah->adcgain_caldata); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); - } - if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { - INIT_CAL(&ah->adcdc_caldata); - INSERT_CAL(ah, &ah->adcdc_caldata); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); - } - if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { - INIT_CAL(&ah->iq_caldata); - INSERT_CAL(ah, &ah->iq_caldata); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); - } - - ah->cal_list_curr = ah->cal_list; - - if (ah->cal_list_curr) - ath9k_hw_reset_calibration(ah, ah->cal_list_curr); - } - - chan->CalValid = 0; - - return true; -} - -const struct hal_percal_data iq_cal_multi_sample = { - IQ_MISMATCH_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_iqcal_collect, - ath9k_hw_iqcalibrate -}; -const struct hal_percal_data iq_cal_single_sample = { - IQ_MISMATCH_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_iqcal_collect, - ath9k_hw_iqcalibrate -}; -const struct hal_percal_data adc_gain_cal_multi_sample = { - ADC_GAIN_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_adc_gaincal_collect, - ath9k_hw_adc_gaincal_calibrate -}; -const struct hal_percal_data adc_gain_cal_single_sample = { - ADC_GAIN_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_adc_gaincal_collect, - ath9k_hw_adc_gaincal_calibrate -}; -const struct hal_percal_data adc_dc_cal_multi_sample = { - ADC_DC_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; -const struct hal_percal_data adc_dc_cal_single_sample = { - ADC_DC_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; -const struct hal_percal_data adc_init_dc_cal = { - ADC_DC_INIT_CAL, - MIN_CAL_SAMPLES, - INIT_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; diff --git a/drivers/net/wireless/ath9k/calib.h b/drivers/net/wireless/ath9k/calib.h deleted file mode 100644 index 1c74bd50700d..000000000000 --- a/drivers/net/wireless/ath9k/calib.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 CALIB_H -#define CALIB_H - -extern const struct hal_percal_data iq_cal_multi_sample; -extern const struct hal_percal_data iq_cal_single_sample; -extern const struct hal_percal_data adc_gain_cal_multi_sample; -extern const struct hal_percal_data adc_gain_cal_single_sample; -extern const struct hal_percal_data adc_dc_cal_multi_sample; -extern const struct hal_percal_data adc_dc_cal_single_sample; -extern const struct hal_percal_data adc_init_dc_cal; - -#define AR_PHY_CCA_MAX_GOOD_VALUE -85 -#define AR_PHY_CCA_MAX_HIGH_VALUE -62 -#define AR_PHY_CCA_MIN_BAD_VALUE -140 -#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 -#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 - -#define NUM_NF_READINGS 6 -#define ATH9K_NF_CAL_HIST_MAX 5 - -struct ar5416IniArray { - u32 *ia_array; - u32 ia_rows; - u32 ia_columns; -}; - -#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ - (iniarray)->ia_array = (u32 *)(array); \ - (iniarray)->ia_rows = (rows); \ - (iniarray)->ia_columns = (columns); \ - } while (0) - -#define INI_RA(iniarray, row, column) \ - (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) - -#define INIT_CAL(_perCal) do { \ - (_perCal)->calState = CAL_WAITING; \ - (_perCal)->calNext = NULL; \ - } while (0) - -#define INSERT_CAL(_ahp, _perCal) \ - do { \ - if ((_ahp)->cal_list_last == NULL) { \ - (_ahp)->cal_list = \ - (_ahp)->cal_list_last = (_perCal); \ - ((_ahp)->cal_list_last)->calNext = (_perCal); \ - } else { \ - ((_ahp)->cal_list_last)->calNext = (_perCal); \ - (_ahp)->cal_list_last = (_perCal); \ - (_perCal)->calNext = (_ahp)->cal_list; \ - } \ - } while (0) - -enum hal_cal_types { - ADC_DC_INIT_CAL = 0x1, - ADC_GAIN_CAL = 0x2, - ADC_DC_CAL = 0x4, - IQ_MISMATCH_CAL = 0x8 -}; - -enum hal_cal_state { - CAL_INACTIVE, - CAL_WAITING, - CAL_RUNNING, - CAL_DONE -}; - -#define MIN_CAL_SAMPLES 1 -#define MAX_CAL_SAMPLES 64 -#define INIT_LOG_COUNT 5 -#define PER_MIN_LOG_COUNT 2 -#define PER_MAX_LOG_COUNT 10 - -struct hal_percal_data { - enum hal_cal_types calType; - u32 calNumSamples; - u32 calCountMax; - void (*calCollect) (struct ath_hw *); - void (*calPostProc) (struct ath_hw *, u8); -}; - -struct hal_cal_list { - const struct hal_percal_data *calData; - enum hal_cal_state calState; - struct hal_cal_list *calNext; -}; - -struct ath9k_nfcal_hist { - int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX]; - u8 currIndex; - int16_t privNF; - u8 invalidNFcount; -}; - -bool ath9k_hw_reset_calvalid(struct ath_hw *ah); -void ath9k_hw_start_nfcal(struct ath_hw *ah); -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); -int16_t ath9k_hw_getnf(struct ath_hw *ah, - struct ath9k_channel *chan); -void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); -s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone); -bool ath9k_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan); - -#endif /* CALIB_H */ diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c deleted file mode 100644 index 97df20cbf528..000000000000 --- a/drivers/net/wireless/ath9k/debug.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * 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 - -#include "ath9k.h" - -static unsigned int ath9k_debug = DBG_DEFAULT; -module_param_named(debug, ath9k_debug, uint, 0); - -static struct dentry *ath9k_debugfs_root; - -void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) -{ - if (!sc) - return; - - if (sc->debug.debug_mask & dbg_mask) { - va_list args; - - va_start(args, fmt); - printk(KERN_DEBUG "ath9k: "); - vprintk(fmt, args); - va_end(args); - } -} - -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t read_file_dma(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; - char buf[1024]; - unsigned int len = 0; - u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; - int i, qcuOffset = 0, dcuOffset = 0; - u32 *qcuBase = &val[0], *dcuBase = &val[4]; - - REG_WRITE(ah, AR_MACMISC, - ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | - (AR_MACMISC_MISC_OBS_BUS_1 << - AR_MACMISC_MISC_OBS_BUS_MSB_S))); - - len += snprintf(buf + len, sizeof(buf) - len, - "Raw DMA Debug values:\n"); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { - if (i % 4 == 0) - len += snprintf(buf + len, sizeof(buf) - len, "\n"); - - val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))); - len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", - i, val[i]); - } - - len += snprintf(buf + len, sizeof(buf) - len, "\n\n"); - len += snprintf(buf + len, sizeof(buf) - len, - "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); - - for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { - if (i == 8) { - qcuOffset = 0; - qcuBase++; - } - - if (i == 6) { - dcuOffset = 0; - dcuBase++; - } - - len += snprintf(buf + len, sizeof(buf) - len, - "%2d %2x %1x %2x %2x\n", - i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, - (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), - val[2] & (0x7 << (i * 3)) >> (i * 3), - (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); - } - - len += snprintf(buf + len, sizeof(buf) - len, "\n"); - - len += snprintf(buf + len, sizeof(buf) - len, - "qcu_stitch state: %2x qcu_fetch state: %2x\n", - (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); - len += snprintf(buf + len, sizeof(buf) - len, - "qcu_complete state: %2x dcu_complete state: %2x\n", - (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); - len += snprintf(buf + len, sizeof(buf) - len, - "dcu_arb state: %2x dcu_fp state: %2x\n", - (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); - len += snprintf(buf + len, sizeof(buf) - len, - "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", - (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); - len += snprintf(buf + len, sizeof(buf) - len, - "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", - (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); - len += snprintf(buf + len, sizeof(buf) - len, - "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", - (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); - - len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", - REG_READ(ah, AR_OBS_BUS_1)); - len += snprintf(buf + len, sizeof(buf) - len, - "AR_CR: 0x%x \n", REG_READ(ah, AR_CR)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_dma = { - .read = read_file_dma, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - - -void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) -{ - if (status) - sc->debug.stats.istats.total++; - if (status & ATH9K_INT_RX) - sc->debug.stats.istats.rxok++; - if (status & ATH9K_INT_RXEOL) - sc->debug.stats.istats.rxeol++; - if (status & ATH9K_INT_RXORN) - sc->debug.stats.istats.rxorn++; - if (status & ATH9K_INT_TX) - sc->debug.stats.istats.txok++; - if (status & ATH9K_INT_TXURN) - sc->debug.stats.istats.txurn++; - if (status & ATH9K_INT_MIB) - sc->debug.stats.istats.mib++; - if (status & ATH9K_INT_RXPHY) - sc->debug.stats.istats.rxphyerr++; - if (status & ATH9K_INT_RXKCM) - sc->debug.stats.istats.rx_keycache_miss++; - if (status & ATH9K_INT_SWBA) - sc->debug.stats.istats.swba++; - if (status & ATH9K_INT_BMISS) - sc->debug.stats.istats.bmiss++; - if (status & ATH9K_INT_BNR) - sc->debug.stats.istats.bnr++; - if (status & ATH9K_INT_CST) - sc->debug.stats.istats.cst++; - if (status & ATH9K_INT_GTT) - sc->debug.stats.istats.gtt++; - if (status & ATH9K_INT_TIM) - sc->debug.stats.istats.tim++; - if (status & ATH9K_INT_CABEND) - sc->debug.stats.istats.cabend++; - if (status & ATH9K_INT_DTIMSYNC) - sc->debug.stats.istats.dtimsync++; - if (status & ATH9K_INT_DTIM) - sc->debug.stats.istats.dtim++; -} - -static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TX", sc->debug.stats.istats.txok); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "CST", sc->debug.stats.istats.cst); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_interrupt = { - .read = read_file_interrupt, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_tx_info_priv *tx_info_priv = NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->status.rates; - int final_ts_idx, idx; - - tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - final_ts_idx = tx_info_priv->tx.ts_rateindex; - idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate; - - sc->debug.stats.n_rcstats[idx].success++; -} - -static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_tx_info_priv *tx_info_priv = NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->status.rates; - int final_ts_idx, idx; - - tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - final_ts_idx = tx_info_priv->tx.ts_rateindex; - idx = rates[final_ts_idx].idx; - - sc->debug.stats.legacy_rcstats[idx].success++; -} - -void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) -{ - if (conf_is_ht(&sc->hw->conf)) - ath_debug_stat_11n_rc(sc, skb); - else - ath_debug_stat_legacy_rc(sc, skb); -} - -/* FIXME: legacy rates, later on .. */ -void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per) -{ - if (conf_is_ht(&sc->hw->conf)) { - int idx = sc->cur_rate_table->info[rix].dot11rate; - - sc->debug.stats.n_rcstats[idx].xretries += xretries; - sc->debug.stats.n_rcstats[idx].retries += retries; - sc->debug.stats.n_rcstats[idx].per = per; - } -} - -static ssize_t ath_read_file_stat_11n_rc(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[1024]; - unsigned int len = 0; - int i = 0; - - len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success", - "Retries", "XRetries", "PER"); - - for (i = 0; i <= 15; i++) { - len += snprintf(buf + len, sizeof(buf) - len, - "%5s%3d: %8u %8u %8u %8u\n", "MCS", i, - sc->debug.stats.n_rcstats[i].success, - sc->debug.stats.n_rcstats[i].retries, - sc->debug.stats.n_rcstats[i].xretries, - sc->debug.stats.n_rcstats[i].per); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t ath_read_file_stat_legacy_rc(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[512]; - unsigned int len = 0; - int i = 0; - - len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); - - for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { - len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n", - sc->cur_rate_table->info[i].ratekbps / 1000, - sc->debug.stats.legacy_rcstats[i].success); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - - if (sc->cur_rate_table == NULL) - return 0; - - if (conf_is_ht(&sc->hw->conf)) - return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); - else - return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos); -} - -static const struct file_operations fops_rcstat = { - .read = read_file_rcstat, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -static const char * ath_wiphy_state_str(enum ath_wiphy_state state) -{ - switch (state) { - case ATH_WIPHY_INACTIVE: - return "INACTIVE"; - case ATH_WIPHY_ACTIVE: - return "ACTIVE"; - case ATH_WIPHY_PAUSING: - return "PAUSING"; - case ATH_WIPHY_PAUSED: - return "PAUSED"; - case ATH_WIPHY_SCAN: - return "SCAN"; - } - return "?"; -} - -static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[512]; - unsigned int len = 0; - int i; - u8 addr[ETH_ALEN]; - - len += snprintf(buf + len, sizeof(buf) - len, - "primary: %s (%s chan=%d ht=%d)\n", - wiphy_name(sc->pri_wiphy->hw->wiphy), - ath_wiphy_state_str(sc->pri_wiphy->state), - sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - len += snprintf(buf + len, sizeof(buf) - len, - "secondary: %s (%s chan=%d ht=%d)\n", - wiphy_name(aphy->hw->wiphy), - ath_wiphy_state_str(aphy->state), - aphy->chan_idx, aphy->chan_is_ht); - } - - put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr); - put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); - len += snprintf(buf + len, sizeof(buf) - len, - "addr: %pM\n", addr); - put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr); - put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); - len += snprintf(buf + len, sizeof(buf) - len, - "addrmask: %pM\n", addr); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name) -{ - int i; - if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0) - return sc->pri_wiphy; - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0) - return aphy; - } - return NULL; -} - -static int del_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_del(aphy); -} - -static int pause_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_pause(aphy); -} - -static int unpause_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_unpause(aphy); -} - -static int select_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_select(aphy); -} - -static int schedule_wiphy(struct ath_softc *sc, const char *msec) -{ - ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0)); - return 0; -} - -static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[50]; - size_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - buf[len] = '\0'; - if (len > 0 && buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - if (strncmp(buf, "add", 3) == 0) { - int res = ath9k_wiphy_add(sc); - if (res < 0) - return res; - } else if (strncmp(buf, "del=", 4) == 0) { - int res = del_wiphy(sc, buf + 4); - if (res < 0) - return res; - } else if (strncmp(buf, "pause=", 6) == 0) { - int res = pause_wiphy(sc, buf + 6); - if (res < 0) - return res; - } else if (strncmp(buf, "unpause=", 8) == 0) { - int res = unpause_wiphy(sc, buf + 8); - if (res < 0) - return res; - } else if (strncmp(buf, "select=", 7) == 0) { - int res = select_wiphy(sc, buf + 7); - if (res < 0) - return res; - } else if (strncmp(buf, "schedule=", 9) == 0) { - int res = schedule_wiphy(sc, buf + 9); - if (res < 0) - return res; - } else - return -EOPNOTSUPP; - - return count; -} - -static const struct file_operations fops_wiphy = { - .read = read_file_wiphy, - .write = write_file_wiphy, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - - -int ath9k_init_debug(struct ath_softc *sc) -{ - sc->debug.debug_mask = ath9k_debug; - - if (!ath9k_debugfs_root) - return -ENOENT; - - sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath9k_debugfs_root); - if (!sc->debug.debugfs_phy) - goto err; - - sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO, - sc->debug.debugfs_phy, sc, &fops_dma); - if (!sc->debug.debugfs_dma) - goto err; - - sc->debug.debugfs_interrupt = debugfs_create_file("interrupt", - S_IRUGO, - sc->debug.debugfs_phy, - sc, &fops_interrupt); - if (!sc->debug.debugfs_interrupt) - goto err; - - sc->debug.debugfs_rcstat = debugfs_create_file("rcstat", - S_IRUGO, - sc->debug.debugfs_phy, - sc, &fops_rcstat); - if (!sc->debug.debugfs_rcstat) - goto err; - - sc->debug.debugfs_wiphy = debugfs_create_file( - "wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc, - &fops_wiphy); - if (!sc->debug.debugfs_wiphy) - goto err; - - return 0; -err: - ath9k_exit_debug(sc); - return -ENOMEM; -} - -void ath9k_exit_debug(struct ath_softc *sc) -{ - debugfs_remove(sc->debug.debugfs_wiphy); - debugfs_remove(sc->debug.debugfs_rcstat); - debugfs_remove(sc->debug.debugfs_interrupt); - debugfs_remove(sc->debug.debugfs_dma); - debugfs_remove(sc->debug.debugfs_phy); -} - -int ath9k_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; - - return 0; -} - -void ath9k_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; -} diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath9k/debug.h deleted file mode 100644 index 23298b90b52b..000000000000 --- a/drivers/net/wireless/ath9k/debug.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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 DEBUG_H -#define DEBUG_H - -enum ATH_DEBUG { - ATH_DBG_RESET = 0x00000001, - ATH_DBG_QUEUE = 0x00000002, - ATH_DBG_EEPROM = 0x00000004, - ATH_DBG_CALIBRATE = 0x00000008, - ATH_DBG_INTERRUPT = 0x00000010, - ATH_DBG_REGULATORY = 0x00000020, - ATH_DBG_ANI = 0x00000040, - ATH_DBG_XMIT = 0x00000080, - ATH_DBG_BEACON = 0x00000100, - ATH_DBG_CONFIG = 0x00000200, - ATH_DBG_FATAL = 0x00000400, - ATH_DBG_ANY = 0xffffffff -}; - -#define DBG_DEFAULT (ATH_DBG_FATAL) - -#ifdef CONFIG_ATH9K_DEBUG - -/** - * struct ath_interrupt_stats - Contains statistics about interrupts - * @total: Total no. of interrupts generated so far - * @rxok: RX with no errors - * @rxeol: RX with no more RXDESC available - * @rxorn: RX FIFO overrun - * @txok: TX completed at the requested rate - * @txurn: TX FIFO underrun - * @mib: MIB regs reaching its threshold - * @rxphyerr: RX with phy errors - * @rx_keycache_miss: RX with key cache misses - * @swba: Software Beacon Alert - * @bmiss: Beacon Miss - * @bnr: Beacon Not Ready - * @cst: Carrier Sense TImeout - * @gtt: Global TX Timeout - * @tim: RX beacon TIM occurrence - * @cabend: RX End of CAB traffic - * @dtimsync: DTIM sync lossage - * @dtim: RX Beacon with DTIM - */ -struct ath_interrupt_stats { - u32 total; - u32 rxok; - u32 rxeol; - u32 rxorn; - u32 txok; - u32 txeol; - u32 txurn; - u32 mib; - u32 rxphyerr; - u32 rx_keycache_miss; - u32 swba; - u32 bmiss; - u32 bnr; - u32 cst; - u32 gtt; - u32 tim; - u32 cabend; - u32 dtimsync; - u32 dtim; -}; - -struct ath_legacy_rc_stats { - u32 success; -}; - -struct ath_11n_rc_stats { - u32 success; - u32 retries; - u32 xretries; - u8 per; -}; - -struct ath_stats { - struct ath_interrupt_stats istats; - struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */ - struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */ -}; - -struct ath9k_debug { - int debug_mask; - struct dentry *debugfs_phy; - struct dentry *debugfs_dma; - struct dentry *debugfs_interrupt; - struct dentry *debugfs_rcstat; - struct dentry *debugfs_wiphy; - struct ath_stats stats; -}; - -void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); -int ath9k_init_debug(struct ath_softc *sc); -void ath9k_exit_debug(struct ath_softc *sc); -int ath9k_debug_create_root(void); -void ath9k_debug_remove_root(void); -void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); -void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); -void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per); - -#else - -static inline void DPRINTF(struct ath_softc *sc, int dbg_mask, - const char *fmt, ...) -{ -} - -static inline int ath9k_init_debug(struct ath_softc *sc) -{ - return 0; -} - -static inline void ath9k_exit_debug(struct ath_softc *sc) -{ -} - -static inline int ath9k_debug_create_root(void) -{ - return 0; -} - -static inline void ath9k_debug_remove_root(void) -{ -} - -static inline void ath_debug_stat_interrupt(struct ath_softc *sc, - enum ath9k_int status) -{ -} - -static inline void ath_debug_stat_rc(struct ath_softc *sc, - struct sk_buff *skb) -{ -} - -static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per) -{ -} - -#endif /* CONFIG_ATH9K_DEBUG */ - -#endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c deleted file mode 100644 index 44fee5ae8925..000000000000 --- a/drivers/net/wireless/ath9k/eeprom.c +++ /dev/null @@ -1,2813 +0,0 @@ -/* - * 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 "ath9k.h" - -static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, - u32 reg, u32 mask, - u32 shift, u32 val) -{ - u32 regVal; - - regVal = REG_READ(ah, reg) & ~mask; - regVal |= (val << shift) & mask; - - REG_WRITE(ah, reg, regVal); - - if (ah->config.analog_shiftreg) - udelay(100); - - return; -} - -static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) -{ - - if (fbin == AR5416_BCHAN_UNUSED) - return fbin; - - return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); -} - -static inline int16_t ath9k_hw_interpolate(u16 target, - u16 srcLeft, u16 srcRight, - int16_t targetLeft, - int16_t targetRight) -{ - int16_t rv; - - if (srcRight == srcLeft) { - rv = targetLeft; - } else { - rv = (int16_t) (((target - srcLeft) * targetRight + - (srcRight - target) * targetLeft) / - (srcRight - srcLeft)); - } - return rv; -} - -static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, - u16 listSize, u16 *indexL, - u16 *indexR) -{ - u16 i; - - if (target <= pList[0]) { - *indexL = *indexR = 0; - return true; - } - if (target >= pList[listSize - 1]) { - *indexL = *indexR = (u16) (listSize - 1); - return true; - } - - for (i = 0; i < listSize - 1; i++) { - if (pList[i] == target) { - *indexL = *indexR = i; - return true; - } - if (target < pList[i + 1]) { - *indexL = i; - *indexR = (u16) (i + 1); - return false; - } - } - return false; -} - -static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) -{ - struct ath_softc *sc = ah->ah_sc; - - return sc->bus_ops->eeprom_read(ah, off, data); -} - -static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, - u8 *pVpdList, u16 numIntercepts, - u8 *pRetVpdList) -{ - u16 i, k; - u8 currPwr = pwrMin; - u16 idxL = 0, idxR = 0; - - for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { - ath9k_hw_get_lower_upper_index(currPwr, pPwrList, - numIntercepts, &(idxL), - &(idxR)); - if (idxR < 1) - idxR = 1; - if (idxL == numIntercepts - 1) - idxL = (u16) (numIntercepts - 2); - if (pPwrList[idxL] == pPwrList[idxR]) - k = pVpdList[idxL]; - else - k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] + - (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / - (pPwrList[idxR] - pPwrList[idxL])); - pRetVpdList[i] = (u8) k; - currPwr += 2; - } - - return true; -} - -static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_target_power_leg *powInfo, - u16 numChannels, - struct cal_target_power_leg *pNewPower, - u16 numRates, bool isExtTarget) -{ - struct chan_centers centers; - u16 clo, chi; - int i; - int matchIndex = -1, lowIndex = -1; - u16 freq; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = (isExtTarget) ? centers.ext_center : centers.ctl_center; - - if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, - IS_CHAN_2GHZ(chan))) { - matchIndex = 0; - } else { - for (i = 0; (i < numChannels) && - (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { - if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan))) { - matchIndex = i; - break; - } else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan))) && - (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, - IS_CHAN_2GHZ(chan)))) { - lowIndex = i - 1; - break; - } - } - if ((matchIndex == -1) && (lowIndex == -1)) - matchIndex = i - 1; - } - - if (matchIndex != -1) { - *pNewPower = powInfo[matchIndex]; - } else { - clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, - IS_CHAN_2GHZ(chan)); - chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, - IS_CHAN_2GHZ(chan)); - - for (i = 0; i < numRates; i++) { - pNewPower->tPow2x[i] = - (u8)ath9k_hw_interpolate(freq, clo, chi, - powInfo[lowIndex].tPow2x[i], - powInfo[lowIndex + 1].tPow2x[i]); - } - } -} - -static void ath9k_get_txgain_index(struct ath_hw *ah, - struct ath9k_channel *chan, - struct calDataPerFreqOpLoop *rawDatasetOpLoop, - u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) -{ - u8 pcdac, i = 0; - u16 idxL = 0, idxR = 0, numPiers; - bool match; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) - if (calChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), - calChans, numPiers, &idxL, &idxR); - if (match) { - pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; - *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; - } else { - pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; - *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + - rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; - } - - while (pcdac > ah->originalGain[i] && - i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) - i++; - - *pcdacIdx = i; - return; -} - -static void ath9k_olc_get_pdadcs(struct ath_hw *ah, - u32 initTxGain, - int txPower, - u8 *pPDADCValues) -{ - u32 i; - u32 offset; - - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, - AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, - AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); - - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, - AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); - - offset = txPower; - for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) - if (i < offset) - pPDADCValues[i] = 0x0; - else - pPDADCValues[i] = 0xFF; -} - - - - -static void ath9k_hw_get_target_powers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_target_power_ht *powInfo, - u16 numChannels, - struct cal_target_power_ht *pNewPower, - u16 numRates, bool isHt40Target) -{ - struct chan_centers centers; - u16 clo, chi; - int i; - int matchIndex = -1, lowIndex = -1; - u16 freq; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = isHt40Target ? centers.synth_center : centers.ctl_center; - - if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { - matchIndex = 0; - } else { - for (i = 0; (i < numChannels) && - (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { - if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan))) { - matchIndex = i; - break; - } else - if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan))) && - (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, - IS_CHAN_2GHZ(chan)))) { - lowIndex = i - 1; - break; - } - } - if ((matchIndex == -1) && (lowIndex == -1)) - matchIndex = i - 1; - } - - if (matchIndex != -1) { - *pNewPower = powInfo[matchIndex]; - } else { - clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, - IS_CHAN_2GHZ(chan)); - chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, - IS_CHAN_2GHZ(chan)); - - for (i = 0; i < numRates; i++) { - pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq, - clo, chi, - powInfo[lowIndex].tPow2x[i], - powInfo[lowIndex + 1].tPow2x[i]); - } - } -} - -static u16 ath9k_hw_get_max_edge_power(u16 freq, - struct cal_ctl_edges *pRdEdgesPower, - bool is2GHz, int num_band_edges) -{ - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - int i; - - for (i = 0; (i < num_band_edges) && - (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { - if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { - twiceMaxEdgePower = pRdEdgesPower[i].tPower; - break; - } else if ((i > 0) && - (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, - is2GHz))) { - if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel, - is2GHz) < freq && - pRdEdgesPower[i - 1].flag) { - twiceMaxEdgePower = - pRdEdgesPower[i - 1].tPower; - } - break; - } - } - - return twiceMaxEdgePower; -} - -/****************************************/ -/* EEPROM Operations for 4K sized cards */ -/****************************************/ - -static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) -{ - return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); -} - -static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) -{ - return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); -} - -static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) -{ -#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) - u16 *eep_data = (u16 *)&ah->eeprom.map4k; - int addr, eep_start_loc = 0; - - eep_start_loc = 64; - - if (!ath9k_hw_use_flash(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Reading from EEPROM, not flash\n"); - } - - for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { - if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Unable to read eeprom region \n"); - return false; - } - eep_data++; - } - - return true; -#undef SIZE_EEPROM_4K -} - -static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) -{ -#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) - struct ar5416_eeprom_4k *eep = - (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; - u16 *eepdata, temp, magic, magic2; - u32 sum = 0, el; - bool need_swap = false; - int i, addr; - - - if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, - &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Reading Magic # failed\n"); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); - - if (magic != AR5416_EEPROM_MAGIC) { - magic2 = swab16(magic); - - if (magic2 == AR5416_EEPROM_MAGIC) { - need_swap = true; - eepdata = (u16 *) (&ah->eeprom); - - for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { - temp = swab16(*eepdata); - *eepdata = temp; - eepdata++; - } - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "endianness mismatch.\n"); - return -EINVAL; - } - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); - - if (need_swap) - el = swab16(ah->eeprom.map4k.baseEepHeader.length); - else - el = ah->eeprom.map4k.baseEepHeader.length; - - if (el > sizeof(struct ar5416_eeprom_4k)) - el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); - else - el = el / sizeof(u16); - - eepdata = (u16 *)(&ah->eeprom); - - for (i = 0; i < el; i++) - sum ^= *eepdata++; - - if (need_swap) { - u32 integer; - u16 word; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing\n"); - - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - integer = swab32(eep->modalHeader.antCtrlCommon); - eep->modalHeader.antCtrlCommon = integer; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - integer = swab32(eep->modalHeader.antCtrlChain[i]); - eep->modalHeader.antCtrlChain[i] = integer; - } - - for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { - word = swab16(eep->modalHeader.spurChans[i].spurChan); - eep->modalHeader.spurChans[i].spurChan = word; - } - } - - if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || - ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); - return -EINVAL; - } - - return 0; -#undef EEPROM_4K_SIZE -} - -static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, - enum eeprom_param param) -{ - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &eep->modalHeader; - struct base_eep_header_4k *pBase = &eep->baseEepHeader; - - switch (param) { - case EEP_NFTHRESH_2: - return pModal->noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; - case EEP_REG_0: - return pBase->regDmn[0]; - case EEP_REG_1: - return pBase->regDmn[1]; - case EEP_OP_CAP: - return pBase->deviceCap; - case EEP_OP_MODE: - return pBase->opCapFlags; - case EEP_RF_SILENT: - return pBase->rfSilent; - case EEP_OB_2: - return pModal->ob_01; - case EEP_DB_2: - return pModal->db1_01; - case EEP_MINOR_REV: - return pBase->version & AR5416_EEP_VER_MINOR_MASK; - case EEP_TX_MASK: - return pBase->txMask; - case EEP_RX_MASK: - return pBase->rxMask; - case EEP_FRAC_N_5G: - return 0; - default: - return 0; - } -} - -static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq_4k *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ -#define TMP_VAL_VPD_TABLE \ - ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; - u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; -#define PD_GAIN_BOUNDARY_DEFAULT 58; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), bChans, numPiers, - &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableI[i]); - } - } else { - for (i = 0; i < numXpdGains; i++) { - pVpdL = pRawDataSet[idxL].vpdPdg[i]; - pPwrL = pRawDataSet[idxL].pwrPdg[i]; - pVpdR = pRawDataSet[idxR].vpdPdg[i]; - pPwrR = pRawDataSet[idxR].pwrPdg[i]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], - pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); - - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. - synth_center, - IS_CHAN_2GHZ - (chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); - - pPdGainBoundaries[i] = - min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else { - minDelta = 0; - } - - if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - ss = (int16_t)((pPdGainBoundaries[i - 1] - - (minPwrT4[i] / 2)) - - tPdGainOverlap + 1 + minDelta); - } - vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - - (minPwrT4[i] / 2)); - maxIndex = (tgtIndex < sizeCurrVpdTable) ? - tgtIndex : sizeCurrVpdTable; - - while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) - pPDADCValues[k++] = vpdTableI[i][ss++]; - - vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - - vpdTableI[i][sizeCurrVpdTable - 2]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - if (tgtIndex >= maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t) TMP_VAL_VPD_TABLE; - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; - i++; - } - - while (k < AR5416_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k - 1]; - k++; - } - - return; -#undef TMP_VAL_VPD_TABLE -} - -static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *pTxPowerIndexOffset) -{ - struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; - struct cal_data_per_freq_4k *pRawDataset; - u8 *pCalBChans = NULL; - u16 pdGainOverlap_t2; - static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; - u16 numPiers, i, j; - int16_t tMinCalPower; - u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; - u32 reg32, regOffset, regChainOffset; - - xpdMask = pEepData->modalHeader.xpdGain; - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - pdGainOverlap_t2 = - pEepData->modalHeader.pdGainOverlap; - } else { - pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); - } - - pCalBChans = pEepData->calFreqPier2G; - numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; - - numXpdGain = 0; - - for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) - break; - xpdGainValues[numXpdGain] = - (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); - numXpdGain++; - } - } - - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, - (numXpdGain - 1) & 0x3); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, - xpdGainValues[0]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, - xpdGainValues[1]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); - - for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { - if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) && - (i != 0)) { - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else - regChainOffset = i * 0x1000; - - if (pEepData->baseEepHeader.txMask & (1 << i)) { - pRawDataset = pEepData->calPierData2G[i]; - - ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, - pRawDataset, pCalBChans, - numPiers, pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, - pdadcValues, numXpdGain); - - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { - REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, - SM(pdGainOverlap_t2, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP) - | SM(gainBoundaries[0], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) - | SM(gainBoundaries[1], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) - | SM(gainBoundaries[2], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) - | SM(gainBoundaries[3], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); - } - - regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | - ((pdadcValues[4 * j + 1] & 0xFF) << 8) | - ((pdadcValues[4 * j + 2] & 0xFF) << 16)| - ((pdadcValues[4 * j + 3] & 0xFF) << 24); - REG_WRITE(ah, regOffset, reg32); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC: Chain %d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, pdadcValues[4 * j + 1], - 4 * j + 2, pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); - - regOffset += 4; - } - } - } - - *pTxPowerIndexOffset = 0; - - return true; -} - -static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *ratesArray, - u16 cfgCtl, - u16 AntennaReduction, - u16 twiceMaxRegulatoryPower, - u16 powerLimit) -{ - struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; - - int i; - int16_t twiceLargestAntenna; - struct cal_ctl_data_4k *rep; - struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { - 0, { 0, 0, 0, 0} - }; - struct cal_target_power_leg targetPowerOfdmExt = { - 0, { 0, 0, 0, 0} }, targetPowerCckExt = { - 0, { 0, 0, 0, 0 } - }; - struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { - 0, {0, 0, 0, 0} - }; - u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; - struct chan_centers centers; - int tx_chainmask; - u16 twiceMinEdgePower; - - tx_chainmask = ah->txchainmask; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; - - twiceLargestAntenna = (int16_t)min(AntennaReduction - - twiceLargestAntenna, 0); - - maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - - if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { - maxRegAllowedPower -= - (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); - } - - scaledPower = min(powerLimit, maxRegAllowedPower); - scaledPower = max((u16)0, scaledPower); - - numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; - pCtlMode = ctlModesFor11g; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCck, 4, false); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT20, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT40, - AR5416_NUM_2G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCckExt, 4, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - - for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || - (pCtlMode[ctlMode] == CTL_2GHT40); - if (isHt40CtlMode) - freq = centers.synth_center; - else if (pCtlMode[ctlMode] & EXT_ADDITIVE) - freq = centers.ext_center; - else - freq = centers.ctl_center; - - if (ah->eep_ops->get_eeprom_ver(ah) == 14 && - ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " - "EXT_ADDITIVE %d\n", - ctlMode, numCtlModes, isHt40CtlMode, - (pCtlMode[ctlMode] & EXT_ADDITIVE)); - - for (i = 0; (i < AR5416_NUM_CTLS) && - pEepData->ctlIndex[i]; i++) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " - "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " - "chan %d\n", - i, cfgCtl, pCtlMode[ctlMode], - pEepData->ctlIndex[i], chan->channel); - - if ((((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - pEepData->ctlIndex[i]) || - (((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ((pEepData->ctlIndex[i] & CTL_MODE_M) | - SD_NO_CTL))) { - rep = &(pEepData->ctlData[i]); - - twiceMinEdgePower = - ath9k_hw_get_max_edge_power(freq, - rep->ctlEdges[ar5416_get_ntxchains - (tx_chainmask) - 1], - IS_CHAN_2GHZ(chan), - AR5416_EEP4K_NUM_BAND_EDGES); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - " MATCH-EE_IDX %d: ch %d is2 %d " - "2xMinEdge %d chainmask %d chains %d\n", - i, freq, IS_CHAN_2GHZ(chan), - twiceMinEdgePower, tx_chainmask, - ar5416_get_ntxchains - (tx_chainmask)); - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { - twiceMaxEdgePower = - min(twiceMaxEdgePower, - twiceMinEdgePower); - } else { - twiceMaxEdgePower = twiceMinEdgePower; - break; - } - } - } - - minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - " SEL-Min ctlMode %d pCtlMode %d " - "2xMaxEdge %d sP %d minCtlPwr %d\n", - ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, - scaledPower, minCtlPower); - - switch (pCtlMode[ctlMode]) { - case CTL_11B: - for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); - i++) { - targetPowerCck.tPow2x[i] = - min((u16)targetPowerCck.tPow2x[i], - minCtlPower); - } - break; - case CTL_11G: - for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); - i++) { - targetPowerOfdm.tPow2x[i] = - min((u16)targetPowerOfdm.tPow2x[i], - minCtlPower); - } - break; - case CTL_2GHT20: - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); - i++) { - targetPowerHt20.tPow2x[i] = - min((u16)targetPowerHt20.tPow2x[i], - minCtlPower); - } - break; - case CTL_11B_EXT: - targetPowerCckExt.tPow2x[0] = min((u16) - targetPowerCckExt.tPow2x[0], - minCtlPower); - break; - case CTL_11G_EXT: - targetPowerOfdmExt.tPow2x[0] = min((u16) - targetPowerOfdmExt.tPow2x[0], - minCtlPower); - break; - case CTL_2GHT40: - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); - i++) { - targetPowerHt40.tPow2x[i] = - min((u16)targetPowerHt40.tPow2x[i], - minCtlPower); - } - break; - default: - break; - } - } - - ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = - ratesArray[rate18mb] = ratesArray[rate24mb] = - targetPowerOfdm.tPow2x[0]; - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; - - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; - - if (IS_CHAN_HT40(chan)) { - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - ratesArray[rateHt40_0 + i] = - targetPowerHt40.tPow2x[i]; - } - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; - } - return true; -} - -static int ath9k_hw_4k_set_txpower(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 cfgCtl, - u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, - u8 powerLimit) -{ - struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &pEepData->modalHeader; - int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; - u8 ht40PowerIncForPdadc = 2; - int i; - - memset(ratesArray, 0, sizeof(ratesArray)); - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } - - if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan, - &ratesArray[0], cfgCtl, - twiceAntennaReduction, - twiceMaxRegulatoryPower, - powerLimit)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set " - "tx power per rate table\n"); - return -EIO; - } - - if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set power table\n"); - return -EIO; - } - - for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { - ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - for (i = 0; i < Ar5416RateSize; i++) - ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) - | ATH9K_POW_SM(ratesArray[rate12mb], 16) - | ATH9K_POW_SM(ratesArray[rate9mb], 8) - | ATH9K_POW_SM(ratesArray[rate6mb], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, - ATH9K_POW_SM(ratesArray[rate54mb], 24) - | ATH9K_POW_SM(ratesArray[rate48mb], 16) - | ATH9K_POW_SM(ratesArray[rate36mb], 8) - | ATH9K_POW_SM(ratesArray[rate24mb], 0)); - - if (IS_CHAN_2GHZ(chan)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(ratesArray[rate2s], 24) - | ATH9K_POW_SM(ratesArray[rate2l], 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(ratesArray[rate1l], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(ratesArray[rate11s], 24) - | ATH9K_POW_SM(ratesArray[rate11l], 16) - | ATH9K_POW_SM(ratesArray[rate5_5s], 8) - | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, - ATH9K_POW_SM(ratesArray[rateHt20_3], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, - ATH9K_POW_SM(ratesArray[rateHt20_7], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); - - if (IS_CHAN_HT40(chan)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - ATH9K_POW_SM(ratesArray[rateHt40_3] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_2] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_1] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_0] + - ht40PowerIncForPdadc, 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - ATH9K_POW_SM(ratesArray[rateHt40_7] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_6] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_5] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_4] + - ht40PowerIncForPdadc, 0)); - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(ratesArray[rateExtCck], 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); - } - - i = rate6mb; - - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - if (AR_SREV_9280_10_OR_LATER(ah)) - ah->regulatory.max_power_level = - ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; - else - ah->regulatory.max_power_level = ratesArray[i]; - - return 0; -} - -static void ath9k_hw_4k_set_addac(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct modal_eep_4k_header *pModal; - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - u8 biaslevel; - - if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) - return; - - if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) - return; - - pModal = &eep->modalHeader; - - if (pModal->xpaBiasLvl != 0xff) { - biaslevel = pModal->xpaBiasLvl; - INI_RA(&ah->iniAddac, 7, 1) = - (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; - } -} - -static void ath9k_hw_4k_set_gain(struct ath_hw *ah, - struct modal_eep_4k_header *pModal, - struct ar5416_eeprom_4k *eep, - u8 txRxAttenLocal, int regChainOffset) -{ - REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, - pModal->antCtrlChain[0]); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, - (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & - ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { - txRxAttenLocal = pModal->txRxAttenCh[0]; - - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal->xatten2Margin[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); - } - - REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); - REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); -} - -static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct modal_eep_4k_header *pModal; - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - u8 txRxAttenLocal; - u8 ob[5], db1[5], db2[5]; - u8 ant_div_control1, ant_div_control2; - u32 regVal; - - pModal = &eep->modalHeader; - txRxAttenLocal = 23; - - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); - - /* Single chain for 4K EEPROM*/ - ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); - - /* Initialize Ant Diversity settings from EEPROM */ - if (pModal->version == 3) { - ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); - ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); - regVal = REG_READ(ah, 0x99ac); - regVal &= (~(0x7f000000)); - regVal |= ((ant_div_control1 & 0x1) << 24); - regVal |= (((ant_div_control1 >> 1) & 0x1) << 29); - regVal |= (((ant_div_control1 >> 2) & 0x1) << 30); - regVal |= ((ant_div_control2 & 0x3) << 25); - regVal |= (((ant_div_control2 >> 2) & 0x3) << 27); - REG_WRITE(ah, 0x99ac, regVal); - regVal = REG_READ(ah, 0x99ac); - regVal = REG_READ(ah, 0xa208); - regVal &= (~(0x1 << 13)); - regVal |= (((ant_div_control1 >> 3) & 0x1) << 13); - REG_WRITE(ah, 0xa208, regVal); - regVal = REG_READ(ah, 0xa208); - } - - if (pModal->version >= 2) { - ob[0] = (pModal->ob_01 & 0xf); - ob[1] = (pModal->ob_01 >> 4) & 0xf; - ob[2] = (pModal->ob_234 & 0xf); - ob[3] = ((pModal->ob_234 >> 4) & 0xf); - ob[4] = ((pModal->ob_234 >> 8) & 0xf); - - db1[0] = (pModal->db1_01 & 0xf); - db1[1] = ((pModal->db1_01 >> 4) & 0xf); - db1[2] = (pModal->db1_234 & 0xf); - db1[3] = ((pModal->db1_234 >> 4) & 0xf); - db1[4] = ((pModal->db1_234 >> 8) & 0xf); - - db2[0] = (pModal->db2_01 & 0xf); - db2[1] = ((pModal->db2_01 >> 4) & 0xf); - db2[2] = (pModal->db2_234 & 0xf); - db2[3] = ((pModal->db2_234 >> 4) & 0xf); - db2[4] = ((pModal->db2_234 >> 8) & 0xf); - - } else if (pModal->version == 1) { - ob[0] = (pModal->ob_01 & 0xf); - ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; - db1[0] = (pModal->db1_01 & 0xf); - db1[1] = db1[2] = db1[3] = - db1[4] = ((pModal->db1_01 >> 4) & 0xf); - db2[0] = (pModal->db2_01 & 0xf); - db2[1] = db2[2] = db2[3] = - db2[4] = ((pModal->db2_01 >> 4) & 0xf); - } else { - int i; - for (i = 0; i < 5; i++) { - ob[i] = pModal->ob_01; - db1[i] = pModal->db1_01; - db2[i] = pModal->db1_01; - } - } - - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]); - - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3, - AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]); - - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]); - ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]); - - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - - REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, - pModal->switchSettling); - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, - pModal->adcDesiredSize); - - REG_WRITE(ah, AR_PHY_RF_CTL4, - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | - SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | - SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - - REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, - pModal->txEndToRxOn); - REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, - pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, - pModal->thresh62); - - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, - pModal->txFrameToDataStart); - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, - pModal->txFrameToPaOn); - } - - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { - if (IS_CHAN_HT40(chan)) - REG_RMW_FIELD(ah, AR_PHY_SETTLING, - AR_PHY_SETTLING_SWITCH, - pModal->swSettleHt40); - } -} - -static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &eep->modalHeader; - - return pModal->antCtrlCommon & 0xFFFF; -} - -static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, - enum ieee80211_band freq_band) -{ - return 1; -} - -static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -{ -#define EEP_MAP4K_SPURCHAN \ - (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) - - u16 spur_val = AR_NO_SPUR; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); - - switch (ah->config.spurmode) { - case SPUR_DISABLE: - break; - case SPUR_ENABLE_IOCTL: - spur_val = ah->config.spurchans[i][is2GHz]; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); - break; - case SPUR_ENABLE_EEPROM: - spur_val = EEP_MAP4K_SPURCHAN; - break; - } - - return spur_val; - -#undef EEP_MAP4K_SPURCHAN -} - -static struct eeprom_ops eep_4k_ops = { - .check_eeprom = ath9k_hw_4k_check_eeprom, - .get_eeprom = ath9k_hw_4k_get_eeprom, - .fill_eeprom = ath9k_hw_4k_fill_eeprom, - .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, - .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, - .set_board_values = ath9k_hw_4k_set_board_values, - .set_addac = ath9k_hw_4k_set_addac, - .set_txpower = ath9k_hw_4k_set_txpower, - .get_spur_channel = ath9k_hw_4k_get_spur_channel -}; - -/************************************************/ -/* EEPROM Operations for non-4K (Default) cards */ -/************************************************/ - -static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) -{ - return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF); -} - -static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) -{ - return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); -} - -static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) -{ -#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) - u16 *eep_data = (u16 *)&ah->eeprom.def; - int addr, ar5416_eep_start_loc = 0x100; - - for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { - if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, - eep_data)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unable to read eeprom region\n"); - return false; - } - eep_data++; - } - return true; -#undef SIZE_EEPROM_DEF -} - -static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) -{ - struct ar5416_eeprom_def *eep = - (struct ar5416_eeprom_def *) &ah->eeprom.def; - u16 *eepdata, temp, magic, magic2; - u32 sum = 0, el; - bool need_swap = false; - int i, addr, size; - - if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); - return false; - } - - if (!ath9k_hw_use_flash(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); - - if (magic != AR5416_EEPROM_MAGIC) { - magic2 = swab16(magic); - - if (magic2 == AR5416_EEPROM_MAGIC) { - size = sizeof(struct ar5416_eeprom_def); - need_swap = true; - eepdata = (u16 *) (&ah->eeprom); - - for (addr = 0; addr < size / sizeof(u16); addr++) { - temp = swab16(*eepdata); - *eepdata = temp; - eepdata++; - } - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "Endianness mismatch.\n"); - return -EINVAL; - } - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); - - if (need_swap) - el = swab16(ah->eeprom.def.baseEepHeader.length); - else - el = ah->eeprom.def.baseEepHeader.length; - - if (el > sizeof(struct ar5416_eeprom_def)) - el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); - else - el = el / sizeof(u16); - - eepdata = (u16 *)(&ah->eeprom); - - for (i = 0; i < el; i++) - sum ^= *eepdata++; - - if (need_swap) { - u32 integer, j; - u16 word; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing.\n"); - - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { - struct modal_eep_header *pModal = - &eep->modalHeader[j]; - integer = swab32(pModal->antCtrlCommon); - pModal->antCtrlCommon = integer; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - integer = swab32(pModal->antCtrlChain[i]); - pModal->antCtrlChain[i] = integer; - } - - for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { - word = swab16(pModal->spurChans[i].spurChan); - pModal->spurChans[i].spurChan = word; - } - } - } - - if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || - ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); - return -EINVAL; - } - - return 0; -} - -static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, - enum eeprom_param param) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = eep->modalHeader; - struct base_eep_header *pBase = &eep->baseEepHeader; - - switch (param) { - case EEP_NFTHRESH_5: - return pModal[0].noiseFloorThreshCh[0]; - case EEP_NFTHRESH_2: - return pModal[1].noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; - case EEP_REG_0: - return pBase->regDmn[0]; - case EEP_REG_1: - return pBase->regDmn[1]; - case EEP_OP_CAP: - return pBase->deviceCap; - case EEP_OP_MODE: - return pBase->opCapFlags; - case EEP_RF_SILENT: - return pBase->rfSilent; - case EEP_OB_5: - return pModal[0].ob; - case EEP_DB_5: - return pModal[0].db; - case EEP_OB_2: - return pModal[1].ob; - case EEP_DB_2: - return pModal[1].db; - case EEP_MINOR_REV: - return AR5416_VER_MASK; - case EEP_TX_MASK: - return pBase->txMask; - case EEP_RX_MASK: - return pBase->rxMask; - case EEP_RXGAIN_TYPE: - return pBase->rxGainType; - case EEP_TXGAIN_TYPE: - return pBase->txGainType; - case EEP_OL_PWRCTRL: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) - return pBase->openLoopPwrCntl ? true : false; - else - return false; - case EEP_RC_CHAIN_MASK: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) - return pBase->rcChainMask; - else - return 0; - case EEP_DAC_HPWR_5G: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) - return pBase->dacHiPwrMode_5G; - else - return 0; - case EEP_FRAC_N_5G: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22) - return pBase->frac_n_5g; - else - return 0; - default: - return 0; - } -} - -static void ath9k_hw_def_set_gain(struct ath_hw *ah, - struct modal_eep_header *pModal, - struct ar5416_eeprom_def *eep, - u8 txRxAttenLocal, int regChainOffset, int i) -{ - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { - txRxAttenLocal = pModal->txRxAttenCh[i]; - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, - pModal->bswMargin[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, - pModal->bswAtten[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal->xatten2Margin[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, - pModal->xatten2Db[i]); - } else { - REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & - ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) - | SM(pModal-> bswMargin[i], - AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & - ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) - | SM(pModal->bswAtten[i], - AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - } - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, - AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); - REG_RMW_FIELD(ah, - AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); - } else { - REG_WRITE(ah, - AR_PHY_RXGAIN + regChainOffset, - (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & - ~AR_PHY_RXGAIN_TXRX_ATTEN) - | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); - REG_WRITE(ah, - AR_PHY_GAIN_2GHZ + regChainOffset, - (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & - ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | - SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); - } -} - -static void ath9k_hw_def_set_board_values(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct modal_eep_header *pModal; - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - int i, regChainOffset; - u8 txRxAttenLocal; - - pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; - - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (AR_SREV_9280(ah)) { - if (i >= 2) - break; - } - - if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - else - regChainOffset = i * 0x1000; - - REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, - pModal->antCtrlChain[i]); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, - (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & - ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[i], - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[i], - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) - ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, - regChainOffset, i); - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (IS_CHAN_2GHZ(chan)) { - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, - AR_AN_RF2G1_CH0_OB, - AR_AN_RF2G1_CH0_OB_S, - pModal->ob); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, - AR_AN_RF2G1_CH0_DB, - AR_AN_RF2G1_CH0_DB_S, - pModal->db); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, - AR_AN_RF2G1_CH1_OB, - AR_AN_RF2G1_CH1_OB_S, - pModal->ob_ch1); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, - AR_AN_RF2G1_CH1_DB, - AR_AN_RF2G1_CH1_DB_S, - pModal->db_ch1); - } else { - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, - AR_AN_RF5G1_CH0_OB5, - AR_AN_RF5G1_CH0_OB5_S, - pModal->ob); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, - AR_AN_RF5G1_CH0_DB5, - AR_AN_RF5G1_CH0_DB5_S, - pModal->db); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, - AR_AN_RF5G1_CH1_OB5, - AR_AN_RF5G1_CH1_OB5_S, - pModal->ob_ch1); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, - AR_AN_RF5G1_CH1_DB5, - AR_AN_RF5G1_CH1_DB5_S, - pModal->db_ch1); - } - ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, - AR_AN_TOP2_XPABIAS_LVL, - AR_AN_TOP2_XPABIAS_LVL_S, - pModal->xpaBiasLvl); - ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, - AR_AN_TOP2_LOCALBIAS, - AR_AN_TOP2_LOCALBIAS_S, - pModal->local_bias); - REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, - pModal->force_xpaon); - } - - REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, - pModal->switchSettling); - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, - pModal->adcDesiredSize); - - if (!AR_SREV_9280_10_OR_LATER(ah)) - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_PGA, - pModal->pgaDesiredSize); - - REG_WRITE(ah, AR_PHY_RF_CTL4, - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) - | SM(pModal->txEndToXpaOff, - AR_PHY_RF_CTL4_TX_END_XPAB_OFF) - | SM(pModal->txFrameToXpaOn, - AR_PHY_RF_CTL4_FRAME_XPAA_ON) - | SM(pModal->txFrameToXpaOn, - AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - - REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, - pModal->txEndToRxOn); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, - pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, - AR_PHY_EXT_CCA0_THRESH62, - pModal->thresh62); - } else { - REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, - pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, - AR_PHY_EXT_CCA_THRESH62, - pModal->thresh62); - } - - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, - AR_PHY_TX_END_DATA_START, - pModal->txFrameToDataStart); - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, - pModal->txFrameToPaOn); - } - - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { - if (IS_CHAN_HT40(chan)) - REG_RMW_FIELD(ah, AR_PHY_SETTLING, - AR_PHY_SETTLING_SWITCH, - pModal->swSettleHt40); - } - - if (AR_SREV_9280_20_OR_LATER(ah) && - AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) - REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, - AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, - pModal->miscBits); - - - if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { - if (IS_CHAN_2GHZ(chan)) - REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, - eep->baseEepHeader.dacLpMode); - else if (eep->baseEepHeader.dacHiPwrMode_5G) - REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); - else - REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, - eep->baseEepHeader.dacLpMode); - - REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, - pModal->miscBits >> 2); - - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, - AR_PHY_TX_DESIRED_SCALE_CCK, - eep->baseEepHeader.desiredScaleCCK); - } -} - -static void ath9k_hw_def_set_addac(struct ath_hw *ah, - struct ath9k_channel *chan) -{ -#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) - struct modal_eep_header *pModal; - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - u8 biaslevel; - - if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) - return; - - if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) - return; - - pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - - if (pModal->xpaBiasLvl != 0xff) { - biaslevel = pModal->xpaBiasLvl; - } else { - u16 resetFreqBin, freqBin, freqCount = 0; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - resetFreqBin = FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)); - freqBin = XPA_LVL_FREQ(0) & 0xff; - biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14); - - freqCount++; - - while (freqCount < 3) { - if (XPA_LVL_FREQ(freqCount) == 0x0) - break; - - freqBin = XPA_LVL_FREQ(freqCount) & 0xff; - if (resetFreqBin >= freqBin) - biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14); - else - break; - freqCount++; - } - } - - if (IS_CHAN_2GHZ(chan)) { - INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac, - 7, 1) & (~0x18)) | biaslevel << 3; - } else { - INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac, - 6, 1) & (~0xc0)) | biaslevel << 6; - } -#undef XPA_LVL_FREQ -} - -static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - static u8 vpdTableL[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR5416_NUM_PD_GAINS]; - u8 maxPwrT4[AR5416_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), - bChans, numPiers, &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR5416_PD_GAIN_ICEPTS, - vpdTableI[i]); - } - } else { - for (i = 0; i < numXpdGains; i++) { - pVpdL = pRawDataSet[idxL].vpdPdg[i]; - pPwrL = pRawDataSet[idxL].pwrPdg[i]; - pVpdR = pRawDataSet[idxR].vpdPdg[i]; - pPwrR = pRawDataSet[idxR].pwrPdg[i]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], - pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); - - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR5416_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR5416_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. - synth_center, - IS_CHAN_2GHZ - (chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); - - pPdGainBoundaries[i] = - min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else { - minDelta = 0; - } - - if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - ss = (int16_t)((pPdGainBoundaries[i - 1] - - (minPwrT4[i] / 2)) - - tPdGainOverlap + 1 + minDelta); - } - vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - - (minPwrT4[i] / 2)); - maxIndex = (tgtIndex < sizeCurrVpdTable) ? - tgtIndex : sizeCurrVpdTable; - - while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - pPDADCValues[k++] = vpdTableI[i][ss++]; - } - - vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - - vpdTableI[i][sizeCurrVpdTable - 2]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - if (tgtIndex > maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + - (ss - maxIndex + 1) * vpdStep)); - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - while (i < AR5416_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; - i++; - } - - while (k < AR5416_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k - 1]; - k++; - } - - return; -} - -static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *pTxPowerIndexOffset) -{ -#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) -#define SM_PDGAIN_B(x, y) \ - SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) - - struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - struct cal_data_per_freq *pRawDataset; - u8 *pCalBChans = NULL; - u16 pdGainOverlap_t2; - static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; - u16 numPiers, i, j; - int16_t tMinCalPower; - u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; - u32 reg32, regOffset, regChainOffset; - int16_t modalIdx; - - modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; - xpdMask = pEepData->modalHeader[modalIdx].xpdGain; - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - pdGainOverlap_t2 = - pEepData->modalHeader[modalIdx].pdGainOverlap; - } else { - pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); - } - - if (IS_CHAN_2GHZ(chan)) { - pCalBChans = pEepData->calFreqPier2G; - numPiers = AR5416_NUM_2G_CAL_PIERS; - } else { - pCalBChans = pEepData->calFreqPier5G; - numPiers = AR5416_NUM_5G_CAL_PIERS; - } - - if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { - pRawDataset = pEepData->calPierData2G[0]; - ah->initPDADC = ((struct calDataPerFreqOpLoop *) - pRawDataset)->vpdPdg[0][0]; - } - - numXpdGain = 0; - - for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR5416_NUM_PD_GAINS) - break; - xpdGainValues[numXpdGain] = - (u16)(AR5416_PD_GAINS_IN_MASK - i); - numXpdGain++; - } - } - - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, - (numXpdGain - 1) & 0x3); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, - xpdGainValues[0]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, - xpdGainValues[1]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, - xpdGainValues[2]); - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) && - (i != 0)) { - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else - regChainOffset = i * 0x1000; - - if (pEepData->baseEepHeader.txMask & (1 << i)) { - if (IS_CHAN_2GHZ(chan)) - pRawDataset = pEepData->calPierData2G[i]; - else - pRawDataset = pEepData->calPierData5G[i]; - - - if (OLC_FOR_AR9280_20_LATER) { - u8 pcdacIdx; - u8 txPower; - - ath9k_get_txgain_index(ah, chan, - (struct calDataPerFreqOpLoop *)pRawDataset, - pCalBChans, numPiers, &txPower, &pcdacIdx); - ath9k_olc_get_pdadcs(ah, pcdacIdx, - txPower/2, pdadcValues); - } else { - ath9k_hw_get_def_gain_boundaries_pdadcs(ah, - chan, pRawDataset, - pCalBChans, numPiers, - pdGainOverlap_t2, - &tMinCalPower, - gainBoundaries, - pdadcValues, - numXpdGain); - } - - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { - if (OLC_FOR_AR9280_20_LATER) { - REG_WRITE(ah, - AR_PHY_TPCRG5 + regChainOffset, - SM(0x6, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | - SM_PD_GAIN(1) | SM_PD_GAIN(2) | - SM_PD_GAIN(3) | SM_PD_GAIN(4)); - } else { - REG_WRITE(ah, - AR_PHY_TPCRG5 + regChainOffset, - SM(pdGainOverlap_t2, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| - SM_PDGAIN_B(0, 1) | - SM_PDGAIN_B(1, 2) | - SM_PDGAIN_B(2, 3) | - SM_PDGAIN_B(3, 4)); - } - } - - regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | - ((pdadcValues[4 * j + 1] & 0xFF) << 8) | - ((pdadcValues[4 * j + 2] & 0xFF) << 16)| - ((pdadcValues[4 * j + 3] & 0xFF) << 24); - REG_WRITE(ah, regOffset, reg32); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC: Chain %d | PDADC %3d " - "Value %3d | PDADC %3d Value %3d | " - "PDADC %3d Value %3d | PDADC %3d " - "Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, pdadcValues[4 * j + 1], - 4 * j + 2, pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); - - regOffset += 4; - } - } - } - - *pTxPowerIndexOffset = 0; - - return true; -#undef SM_PD_GAIN -#undef SM_PDGAIN_B -} - -static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *ratesArray, - u16 cfgCtl, - u16 AntennaReduction, - u16 twiceMaxRegulatoryPower, - u16 powerLimit) -{ -#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ -#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ - - struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; - - int i; - int16_t twiceLargestAntenna; - struct cal_ctl_data *rep; - struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { - 0, { 0, 0, 0, 0} - }; - struct cal_target_power_leg targetPowerOfdmExt = { - 0, { 0, 0, 0, 0} }, targetPowerCckExt = { - 0, { 0, 0, 0, 0 } - }; - struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { - 0, {0, 0, 0, 0} - }; - u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = - { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; - struct chan_centers centers; - int tx_chainmask; - u16 twiceMinEdgePower; - - tx_chainmask = ah->txchainmask; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - twiceLargestAntenna = max( - pEepData->modalHeader - [IS_CHAN_2GHZ(chan)].antennaGainCh[0], - pEepData->modalHeader - [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); - - twiceLargestAntenna = max((u8)twiceLargestAntenna, - pEepData->modalHeader - [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); - - twiceLargestAntenna = (int16_t)min(AntennaReduction - - twiceLargestAntenna, 0); - - maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - - if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { - maxRegAllowedPower -= - (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); - } - - scaledPower = min(powerLimit, maxRegAllowedPower); - - switch (ar5416_get_ntxchains(tx_chainmask)) { - case 1: - break; - case 2: - scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; - break; - case 3: - scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; - break; - } - - scaledPower = max((u16)0, scaledPower); - - if (IS_CHAN_2GHZ(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g) - - SUB_NUM_CTL_MODES_AT_2G_40; - pCtlMode = ctlModesFor11g; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCck, 4, false); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT20, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT40, - AR5416_NUM_2G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCckExt, 4, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - } else { - numCtlModes = ARRAY_SIZE(ctlModesFor11a) - - SUB_NUM_CTL_MODES_AT_5G_40; - pCtlMode = ctlModesFor11a; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower5G, - AR5416_NUM_5G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower5GHT20, - AR5416_NUM_5G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11a); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower5GHT40, - AR5416_NUM_5G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower5G, - AR5416_NUM_5G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - } - - for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || - (pCtlMode[ctlMode] == CTL_2GHT40); - if (isHt40CtlMode) - freq = centers.synth_center; - else if (pCtlMode[ctlMode] & EXT_ADDITIVE) - freq = centers.ext_center; - else - freq = centers.ctl_center; - - if (ah->eep_ops->get_eeprom_ver(ah) == 14 && - ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " - "EXT_ADDITIVE %d\n", - ctlMode, numCtlModes, isHt40CtlMode, - (pCtlMode[ctlMode] & EXT_ADDITIVE)); - - for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " - "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " - "chan %d\n", - i, cfgCtl, pCtlMode[ctlMode], - pEepData->ctlIndex[i], chan->channel); - - if ((((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - pEepData->ctlIndex[i]) || - (((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { - rep = &(pEepData->ctlData[i]); - - twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, - rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], - IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - " MATCH-EE_IDX %d: ch %d is2 %d " - "2xMinEdge %d chainmask %d chains %d\n", - i, freq, IS_CHAN_2GHZ(chan), - twiceMinEdgePower, tx_chainmask, - ar5416_get_ntxchains - (tx_chainmask)); - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { - twiceMaxEdgePower = min(twiceMaxEdgePower, - twiceMinEdgePower); - } else { - twiceMaxEdgePower = twiceMinEdgePower; - break; - } - } - } - - minCtlPower = min(twiceMaxEdgePower, scaledPower); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - " SEL-Min ctlMode %d pCtlMode %d " - "2xMaxEdge %d sP %d minCtlPwr %d\n", - ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, - scaledPower, minCtlPower); - - switch (pCtlMode[ctlMode]) { - case CTL_11B: - for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { - targetPowerCck.tPow2x[i] = - min((u16)targetPowerCck.tPow2x[i], - minCtlPower); - } - break; - case CTL_11A: - case CTL_11G: - for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { - targetPowerOfdm.tPow2x[i] = - min((u16)targetPowerOfdm.tPow2x[i], - minCtlPower); - } - break; - case CTL_5GHT20: - case CTL_2GHT20: - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { - targetPowerHt20.tPow2x[i] = - min((u16)targetPowerHt20.tPow2x[i], - minCtlPower); - } - break; - case CTL_11B_EXT: - targetPowerCckExt.tPow2x[0] = min((u16) - targetPowerCckExt.tPow2x[0], - minCtlPower); - break; - case CTL_11A_EXT: - case CTL_11G_EXT: - targetPowerOfdmExt.tPow2x[0] = min((u16) - targetPowerOfdmExt.tPow2x[0], - minCtlPower); - break; - case CTL_5GHT40: - case CTL_2GHT40: - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - targetPowerHt40.tPow2x[i] = - min((u16)targetPowerHt40.tPow2x[i], - minCtlPower); - } - break; - default: - break; - } - } - - ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = - ratesArray[rate18mb] = ratesArray[rate24mb] = - targetPowerOfdm.tPow2x[0]; - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; - - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - - if (IS_CHAN_2GHZ(chan)) { - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = - targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = - targetPowerCck.tPow2x[2]; - ; - ratesArray[rate11s] = ratesArray[rate11l] = - targetPowerCck.tPow2x[3]; - ; - } - if (IS_CHAN_HT40(chan)) { - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - ratesArray[rateHt40_0 + i] = - targetPowerHt40.tPow2x[i]; - } - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - if (IS_CHAN_2GHZ(chan)) { - ratesArray[rateExtCck] = - targetPowerCckExt.tPow2x[0]; - } - } - return true; -} - -static int ath9k_hw_def_set_txpower(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 cfgCtl, - u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, - u8 powerLimit) -{ -#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) - struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); - int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; - u8 ht40PowerIncForPdadc = 2; - int i, cck_ofdm_delta = 0; - - memset(ratesArray, 0, sizeof(ratesArray)); - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } - - if (!ath9k_hw_set_def_power_per_rate_table(ah, chan, - &ratesArray[0], cfgCtl, - twiceAntennaReduction, - twiceMaxRegulatoryPower, - powerLimit)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set " - "tx power per rate table\n"); - return -EIO; - } - - if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ath9k_hw_set_txpower: unable to set power table\n"); - return -EIO; - } - - for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { - ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - for (i = 0; i < Ar5416RateSize; i++) - ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) - | ATH9K_POW_SM(ratesArray[rate12mb], 16) - | ATH9K_POW_SM(ratesArray[rate9mb], 8) - | ATH9K_POW_SM(ratesArray[rate6mb], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, - ATH9K_POW_SM(ratesArray[rate54mb], 24) - | ATH9K_POW_SM(ratesArray[rate48mb], 16) - | ATH9K_POW_SM(ratesArray[rate36mb], 8) - | ATH9K_POW_SM(ratesArray[rate24mb], 0)); - - if (IS_CHAN_2GHZ(chan)) { - if (OLC_FOR_AR9280_20_LATER) { - cck_ofdm_delta = 2; - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) - | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) - | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) - | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) - | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); - } else { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(ratesArray[rate2s], 24) - | ATH9K_POW_SM(ratesArray[rate2l], 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(ratesArray[rate1l], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(ratesArray[rate11s], 24) - | ATH9K_POW_SM(ratesArray[rate11l], 16) - | ATH9K_POW_SM(ratesArray[rate5_5s], 8) - | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); - } - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, - ATH9K_POW_SM(ratesArray[rateHt20_3], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, - ATH9K_POW_SM(ratesArray[rateHt20_7], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); - - if (IS_CHAN_HT40(chan)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - ATH9K_POW_SM(ratesArray[rateHt40_3] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_2] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_1] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_0] + - ht40PowerIncForPdadc, 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - ATH9K_POW_SM(ratesArray[rateHt40_7] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_6] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_5] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_4] + - ht40PowerIncForPdadc, 0)); - if (OLC_FOR_AR9280_20_LATER) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); - } else { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(ratesArray[rateExtCck], 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); - } - } - - REG_WRITE(ah, AR_PHY_POWER_TX_SUB, - ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) - | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); - - i = rate6mb; - - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - if (AR_SREV_9280_10_OR_LATER(ah)) - ah->regulatory.max_power_level = - ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; - else - ah->regulatory.max_power_level = ratesArray[i]; - - switch(ar5416_get_ntxchains(ah->txchainmask)) { - case 1: - break; - case 2: - ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; - break; - case 3: - ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } - - return 0; -} - -static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, - enum ieee80211_band freq_band) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); - struct base_eep_header *pBase = &eep->baseEepHeader; - u8 num_ant_config; - - num_ant_config = 1; - - if (pBase->version >= 0x0E0D) - if (pModal->useAnt1) - num_ant_config += 1; - - return num_ant_config; -} - -static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - - return pModal->antCtrlCommon & 0xFFFF; -} - -static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -{ -#define EEP_DEF_SPURCHAN \ - (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) - - u16 spur_val = AR_NO_SPUR; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); - - switch (ah->config.spurmode) { - case SPUR_DISABLE: - break; - case SPUR_ENABLE_IOCTL: - spur_val = ah->config.spurchans[i][is2GHz]; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); - break; - case SPUR_ENABLE_EEPROM: - spur_val = EEP_DEF_SPURCHAN; - break; - } - - return spur_val; - -#undef EEP_DEF_SPURCHAN -} - -static struct eeprom_ops eep_def_ops = { - .check_eeprom = ath9k_hw_def_check_eeprom, - .get_eeprom = ath9k_hw_def_get_eeprom, - .fill_eeprom = ath9k_hw_def_fill_eeprom, - .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, - .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_def_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, - .set_board_values = ath9k_hw_def_set_board_values, - .set_addac = ath9k_hw_def_set_addac, - .set_txpower = ath9k_hw_def_set_txpower, - .get_spur_channel = ath9k_hw_def_get_spur_channel -}; - -int ath9k_hw_eeprom_attach(struct ath_hw *ah) -{ - int status; - - if (AR_SREV_9285(ah)) { - ah->eep_map = EEP_MAP_4KBITS; - ah->eep_ops = &eep_4k_ops; - } else { - ah->eep_map = EEP_MAP_DEFAULT; - ah->eep_ops = &eep_def_ops; - } - - if (!ah->eep_ops->fill_eeprom(ah)) - return -EIO; - - status = ah->eep_ops->check_eeprom(ah); - - return status; -} diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h deleted file mode 100644 index 9a7715df5cff..000000000000 --- a/drivers/net/wireless/ath9k/eeprom.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * 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 EEPROM_H -#define EEPROM_H - -#include - -#define AH_USE_EEPROM 0x1 - -#ifdef __BIG_ENDIAN -#define AR5416_EEPROM_MAGIC 0x5aa5 -#else -#define AR5416_EEPROM_MAGIC 0xa55a -#endif - -#define CTRY_DEBUG 0x1ff -#define CTRY_DEFAULT 0 - -#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 -#define AR_EEPROM_EEPCAP_AES_DIS 0x0002 -#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 -#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 -#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 -#define AR_EEPROM_EEPCAP_MAXQCU_S 4 -#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 -#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 -#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 - -#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 -#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 -#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 -#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 -#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 -#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 - -#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 -#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 - -#define AR5416_EEPROM_MAGIC_OFFSET 0x0 -#define AR5416_EEPROM_S 2 -#define AR5416_EEPROM_OFFSET 0x2000 -#define AR5416_EEPROM_MAX 0xae0 - -#define AR5416_EEPROM_START_ADDR \ - (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 - -#define SD_NO_CTL 0xE0 -#define NO_CTL 0xff -#define CTL_MODE_M 7 -#define CTL_11A 0 -#define CTL_11B 1 -#define CTL_11G 2 -#define CTL_2GHT20 5 -#define CTL_5GHT20 6 -#define CTL_2GHT40 7 -#define CTL_5GHT40 8 - -#define EXT_ADDITIVE (0x8000) -#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) -#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) -#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) - -#define SUB_NUM_CTL_MODES_AT_5G_40 2 -#define SUB_NUM_CTL_MODES_AT_2G_40 3 - -#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ -#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ - -/* - * For AR9285 and later chipsets, the following bits are not being programmed - * in EEPROM and so need to be enabled always. - * - * Bit 0: en_fcc_mid - * Bit 1: en_jap_mid - * Bit 2: en_fcc_dfs_ht40 - * Bit 3: en_jap_ht40 - * Bit 4: en_jap_dfs_ht40 - */ -#define AR9285_RDEXT_DEFAULT 0x1F - -#define AR_EEPROM_MAC(i) (0x1d+(i)) -#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) -#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) -#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) - -#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) -#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ - ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) - -#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c -#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 -#define AR_EEPROM_RFSILENT_POLARITY 0x0002 -#define AR_EEPROM_RFSILENT_POLARITY_S 1 - -#define EEP_RFSILENT_ENABLED 0x0001 -#define EEP_RFSILENT_ENABLED_S 0 -#define EEP_RFSILENT_POLARITY 0x0002 -#define EEP_RFSILENT_POLARITY_S 1 -#define EEP_RFSILENT_GPIO_SEL 0x001c -#define EEP_RFSILENT_GPIO_SEL_S 2 - -#define AR5416_OPFLAGS_11A 0x01 -#define AR5416_OPFLAGS_11G 0x02 -#define AR5416_OPFLAGS_N_5G_HT40 0x04 -#define AR5416_OPFLAGS_N_2G_HT40 0x08 -#define AR5416_OPFLAGS_N_5G_HT20 0x10 -#define AR5416_OPFLAGS_N_2G_HT20 0x20 - -#define AR5416_EEP_NO_BACK_VER 0x1 -#define AR5416_EEP_VER 0xE -#define AR5416_EEP_VER_MINOR_MASK 0x0FFF -#define AR5416_EEP_MINOR_VER_2 0x2 -#define AR5416_EEP_MINOR_VER_3 0x3 -#define AR5416_EEP_MINOR_VER_7 0x7 -#define AR5416_EEP_MINOR_VER_9 0x9 -#define AR5416_EEP_MINOR_VER_16 0x10 -#define AR5416_EEP_MINOR_VER_17 0x11 -#define AR5416_EEP_MINOR_VER_19 0x13 -#define AR5416_EEP_MINOR_VER_20 0x14 -#define AR5416_EEP_MINOR_VER_22 0x16 - -#define AR5416_NUM_5G_CAL_PIERS 8 -#define AR5416_NUM_2G_CAL_PIERS 4 -#define AR5416_NUM_5G_20_TARGET_POWERS 8 -#define AR5416_NUM_5G_40_TARGET_POWERS 8 -#define AR5416_NUM_2G_CCK_TARGET_POWERS 3 -#define AR5416_NUM_2G_20_TARGET_POWERS 4 -#define AR5416_NUM_2G_40_TARGET_POWERS 4 -#define AR5416_NUM_CTLS 24 -#define AR5416_NUM_BAND_EDGES 8 -#define AR5416_NUM_PD_GAINS 4 -#define AR5416_PD_GAINS_IN_MASK 4 -#define AR5416_PD_GAIN_ICEPTS 5 -#define AR5416_EEPROM_MODAL_SPURS 5 -#define AR5416_MAX_RATE_POWER 63 -#define AR5416_NUM_PDADC_VALUES 128 -#define AR5416_BCHAN_UNUSED 0xFF -#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 -#define AR5416_MAX_CHAINS 3 -#define AR5416_PWR_TABLE_OFFSET -5 - -/* Rx gain type values */ -#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 -#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1 -#define AR5416_EEP_RXGAIN_ORIG 2 - -/* Tx gain type values */ -#define AR5416_EEP_TXGAIN_ORIGINAL 0 -#define AR5416_EEP_TXGAIN_HIGH_POWER 1 - -#define AR5416_EEP4K_START_LOC 64 -#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3 -#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3 -#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3 -#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3 -#define AR5416_EEP4K_NUM_CTLS 12 -#define AR5416_EEP4K_NUM_BAND_EDGES 4 -#define AR5416_EEP4K_NUM_PD_GAINS 2 -#define AR5416_EEP4K_PD_GAINS_IN_MASK 4 -#define AR5416_EEP4K_PD_GAIN_ICEPTS 5 -#define AR5416_EEP4K_MAX_CHAINS 1 - -#define AR9280_TX_GAIN_TABLE_SIZE 22 - -enum eeprom_param { - EEP_NFTHRESH_5, - EEP_NFTHRESH_2, - EEP_MAC_MSW, - EEP_MAC_MID, - EEP_MAC_LSW, - EEP_REG_0, - EEP_REG_1, - EEP_OP_CAP, - EEP_OP_MODE, - EEP_RF_SILENT, - EEP_OB_5, - EEP_DB_5, - EEP_OB_2, - EEP_DB_2, - EEP_MINOR_REV, - EEP_TX_MASK, - EEP_RX_MASK, - EEP_RXGAIN_TYPE, - EEP_TXGAIN_TYPE, - EEP_OL_PWRCTRL, - EEP_RC_CHAIN_MASK, - EEP_DAC_HPWR_5G, - EEP_FRAC_N_5G -}; - -enum ar5416_rates { - rate6mb, rate9mb, rate12mb, rate18mb, - rate24mb, rate36mb, rate48mb, rate54mb, - rate1l, rate2l, rate2s, rate5_5l, - rate5_5s, rate11l, rate11s, rateXr, - rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, - rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, - rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, - rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, - rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, - Ar5416RateSize -}; - -enum ath9k_hal_freq_band { - ATH9K_HAL_FREQ_BAND_5GHZ = 0, - ATH9K_HAL_FREQ_BAND_2GHZ = 1 -}; - -struct base_eep_header { - u16 length; - u16 checksum; - u16 version; - u8 opCapFlags; - u8 eepMisc; - u16 regDmn[2]; - u8 macAddr[6]; - u8 rxMask; - u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; - u8 deviceType; - u8 pwdclkind; - u8 futureBase_1[2]; - u8 rxGainType; - u8 dacHiPwrMode_5G; - u8 openLoopPwrCntl; - u8 dacLpMode; - u8 txGainType; - u8 rcChainMask; - u8 desiredScaleCCK; - u8 power_table_offset; - u8 frac_n_5g; - u8 futureBase_3[21]; -} __packed; - -struct base_eep_header_4k { - u16 length; - u16 checksum; - u16 version; - u8 opCapFlags; - u8 eepMisc; - u16 regDmn[2]; - u8 macAddr[6]; - u8 rxMask; - u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; - u8 deviceType; - u8 txGainType; -} __packed; - - -struct spur_chan { - u16 spurChan; - u8 spurRangeLow; - u8 spurRangeHigh; -} __packed; - -struct modal_eep_header { - u32 antCtrlChain[AR5416_MAX_CHAINS]; - u32 antCtrlCommon; - u8 antennaGainCh[AR5416_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR5416_MAX_CHAINS]; - u8 rxTxMarginCh[AR5416_MAX_CHAINS]; - u8 adcDesiredSize; - u8 pgaDesiredSize; - u8 xlnaGainCh[AR5416_MAX_CHAINS]; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - u8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - u8 iqCalICh[AR5416_MAX_CHAINS]; - u8 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 xatten2Db[AR5416_MAX_CHAINS]; - u8 xatten2Margin[AR5416_MAX_CHAINS]; - u8 ob_ch1; - u8 db_ch1; - u8 useAnt1:1, - force_xpaon:1, - local_bias:1, - femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1; - u8 miscBits; - u16 xpaBiasLvlFreq[3]; - u8 futureModal[6]; - - struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; -} __packed; - -struct calDataPerFreqOpLoop { - u8 pwrPdg[2][5]; - u8 vpdPdg[2][5]; - u8 pcdac[2][5]; - u8 empty[2][5]; -} __packed; - -struct modal_eep_4k_header { - u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; - u32 antCtrlCommon; - u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; - u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS]; - u8 adcDesiredSize; - u8 pgaDesiredSize; - u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS]; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS]; - u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS]; - u8 pdGainOverlap; - u8 ob_01; - u8 db1_01; - u8 xpaBiasLvl; - u8 txFrameToDataStart; - u8 txFrameToPaOn; - u8 ht40PowerIncForPdadc; - u8 bswAtten[AR5416_EEP4K_MAX_CHAINS]; - u8 bswMargin[AR5416_EEP4K_MAX_CHAINS]; - u8 swSettleHt40; - u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS]; - u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS]; - u8 db2_01; - u8 version; - u16 ob_234; - u16 db1_234; - u16 db2_234; - u8 futureModal[4]; - - struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; -} __packed; - - -struct cal_data_per_freq { - u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; -} __packed; - -struct cal_data_per_freq_4k { - u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; -} __packed; - -struct cal_target_power_leg { - u8 bChannel; - u8 tPow2x[4]; -} __packed; - -struct cal_target_power_ht { - u8 bChannel; - u8 tPow2x[8]; -} __packed; - - -#ifdef __BIG_ENDIAN_BITFIELD -struct cal_ctl_edges { - u8 bChannel; - u8 flag:2, tPower:6; -} __packed; -#else -struct cal_ctl_edges { - u8 bChannel; - u8 tPower:6, flag:2; -} __packed; -#endif - -struct cal_ctl_data { - struct cal_ctl_edges - ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; -} __packed; - -struct cal_ctl_data_4k { - struct cal_ctl_edges - ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES]; -} __packed; - -struct ar5416_eeprom_def { - struct base_eep_header baseEepHeader; - u8 custData[64]; - struct modal_eep_header modalHeader[2]; - u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; - u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; - struct cal_data_per_freq - calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS]; - struct cal_data_per_freq - calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; - struct cal_target_power_leg - calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; - u8 ctlIndex[AR5416_NUM_CTLS]; - struct cal_ctl_data ctlData[AR5416_NUM_CTLS]; - u8 padding; -} __packed; - -struct ar5416_eeprom_4k { - struct base_eep_header_4k baseEepHeader; - u8 custData[20]; - struct modal_eep_4k_header modalHeader; - u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS]; - struct cal_data_per_freq_4k - calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS]; - struct cal_target_power_leg - calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS]; - u8 ctlIndex[AR5416_EEP4K_NUM_CTLS]; - struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS]; - u8 padding; -} __packed; - -enum reg_ext_bitmap { - REG_EXT_JAPAN_MIDBAND = 1, - REG_EXT_FCC_DFS_HT40 = 2, - REG_EXT_JAPAN_NONDFS_HT40 = 3, - REG_EXT_JAPAN_DFS_HT40 = 4 -}; - -struct ath9k_country_entry { - u16 countryCode; - u16 regDmnEnum; - u16 regDmn5G; - u16 regDmn2G; - u8 isMultidomain; - u8 iso[3]; -}; - -enum ath9k_eep_map { - EEP_MAP_DEFAULT = 0x0, - EEP_MAP_4KBITS, - EEP_MAP_MAX -}; - -struct eeprom_ops { - int (*check_eeprom)(struct ath_hw *hw); - u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param); - bool (*fill_eeprom)(struct ath_hw *hw); - int (*get_eeprom_ver)(struct ath_hw *hw); - int (*get_eeprom_rev)(struct ath_hw *hw); - u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); - u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, - struct ath9k_channel *chan); - void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); - void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); - int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, - u16 cfgCtl, u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, u8 powerLimit); - u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); -}; - -#define ar5416_get_ntxchains(_txchainmask) \ - (((_txchainmask >> 2) & 1) + \ - ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) - -int ath9k_hw_eeprom_attach(struct ath_hw *ah); - -#endif /* EEPROM_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c deleted file mode 100644 index 24299e65fdcf..000000000000 --- a/drivers/net/wireless/ath9k/hw.c +++ /dev/null @@ -1,3861 +0,0 @@ -/* - * 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 -#include - -#include "ath9k.h" -#include "initvals.h" - -static int btcoex_enable; -module_param(btcoex_enable, bool, 0); -MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support"); - -#define ATH9K_CLOCK_RATE_CCK 22 -#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 -#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 - -static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode); -static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value); -static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); -static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -/********************/ -/* Helper Functions */ -/********************/ - -static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (!ah->curchan) /* should really check for CCK instead */ - return clks / ATH9K_CLOCK_RATE_CCK; - if (conf->channel->band == IEEE80211_BAND_2GHZ) - return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; - - return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; -} - -static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (conf_is_ht40(conf)) - return ath9k_hw_mac_usec(ah, clks) / 2; - else - return ath9k_hw_mac_usec(ah, clks); -} - -static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (!ah->curchan) /* should really check for CCK instead */ - return usecs *ATH9K_CLOCK_RATE_CCK; - if (conf->channel->band == IEEE80211_BAND_2GHZ) - return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; - return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM; -} - -static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (conf_is_ht40(conf)) - return ath9k_hw_mac_clks(ah, usecs) * 2; - else - return ath9k_hw_mac_clks(ah, usecs); -} - -bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) -{ - int i; - - BUG_ON(timeout < AH_TIME_QUANTUM); - - for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) { - if ((REG_READ(ah, reg) & mask) == val) - return true; - - udelay(AH_TIME_QUANTUM); - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", - timeout, reg, REG_READ(ah, reg), mask, val); - - return false; -} - -u32 ath9k_hw_reverse_bits(u32 val, u32 n) -{ - u32 retval; - int i; - - for (i = 0, retval = 0; i < n; i++) { - retval = (retval << 1) | (val & 1); - val >>= 1; - } - return retval; -} - -bool ath9k_get_channel_edges(struct ath_hw *ah, - u16 flags, u16 *low, - u16 *high) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - - if (flags & CHANNEL_5GHZ) { - *low = pCap->low_5ghz_chan; - *high = pCap->high_5ghz_chan; - return true; - } - if ((flags & CHANNEL_2GHZ)) { - *low = pCap->low_2ghz_chan; - *high = pCap->high_2ghz_chan; - return true; - } - return false; -} - -u16 ath9k_hw_computetxtime(struct ath_hw *ah, - struct ath_rate_table *rates, - u32 frameLen, u16 rateix, - bool shortPreamble) -{ - u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; - u32 kbps; - - kbps = rates->info[rateix].ratekbps; - - if (kbps == 0) - return 0; - - switch (rates->info[rateix].phy) { - case WLAN_RC_PHY_CCK: - phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; - if (shortPreamble && rates->info[rateix].short_preamble) - phyTime >>= 1; - numBits = frameLen << 3; - txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); - break; - case WLAN_RC_PHY_OFDM: - if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { - bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; - numBits = OFDM_PLCP_BITS + (frameLen << 3); - numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME_QUARTER - + OFDM_PREAMBLE_TIME_QUARTER - + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); - } else if (ah->curchan && - IS_CHAN_HALF_RATE(ah->curchan)) { - bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; - numBits = OFDM_PLCP_BITS + (frameLen << 3); - numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME_HALF + - OFDM_PREAMBLE_TIME_HALF - + (numSymbols * OFDM_SYMBOL_TIME_HALF); - } else { - bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; - numBits = OFDM_PLCP_BITS + (frameLen << 3); - numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME - + (numSymbols * OFDM_SYMBOL_TIME); - } - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unknown phy %u (rate ix %u)\n", - rates->info[rateix].phy, rateix); - txTime = 0; - break; - } - - return txTime; -} - -void ath9k_hw_get_channel_centers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct chan_centers *centers) -{ - int8_t extoff; - - if (!IS_CHAN_HT40(chan)) { - centers->ctl_center = centers->ext_center = - centers->synth_center = chan->channel; - return; - } - - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || - (chan->chanmode == CHANNEL_G_HT40PLUS)) { - centers->synth_center = - chan->channel + HT40_CHANNEL_CENTER_SHIFT; - extoff = 1; - } else { - centers->synth_center = - chan->channel - HT40_CHANNEL_CENTER_SHIFT; - extoff = -1; - } - - centers->ctl_center = - centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); - centers->ext_center = - centers->synth_center + (extoff * - ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ? - HT40_CHANNEL_CENTER_SHIFT : 15)); -} - -/******************/ -/* Chip Revisions */ -/******************/ - -static void ath9k_hw_read_revisions(struct ath_hw *ah) -{ - u32 val; - - val = REG_READ(ah, AR_SREV) & AR_SREV_ID; - - if (val == 0xFF) { - val = REG_READ(ah, AR_SREV); - ah->hw_version.macVersion = - (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; - ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); - ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; - } else { - if (!AR_SREV_9100(ah)) - ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); - - ah->hw_version.macRev = val & AR_SREV_REVISION; - - if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) - ah->is_pciexpress = true; - } -} - -static int ath9k_hw_get_radiorev(struct ath_hw *ah) -{ - u32 val; - int i; - - REG_WRITE(ah, AR_PHY(0x36), 0x00007058); - - for (i = 0; i < 8; i++) - REG_WRITE(ah, AR_PHY(0x20), 0x00010000); - val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; - val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); - - return ath9k_hw_reverse_bits(val, 8); -} - -/************************************/ -/* HW Attach, Detach, Init Routines */ -/************************************/ - -static void ath9k_hw_disablepcie(struct ath_hw *ah) -{ - if (AR_SREV_9100(ah)) - return; - - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); - REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); - REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); - - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); -} - -static bool ath9k_hw_chip_test(struct ath_hw *ah) -{ - u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; - u32 regHold[2]; - u32 patternData[4] = { 0x55555555, - 0xaaaaaaaa, - 0x66666666, - 0x99999999 }; - int i, j; - - for (i = 0; i < 2; i++) { - u32 addr = regAddr[i]; - u32 wrData, rdData; - - regHold[i] = REG_READ(ah, addr); - for (j = 0; j < 0x100; j++) { - wrData = (j << 16) | j; - REG_WRITE(ah, addr, wrData); - rdData = REG_READ(ah, addr); - if (rdData != wrData) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", - addr, wrData, rdData); - return false; - } - } - for (j = 0; j < 4; j++) { - wrData = patternData[j]; - REG_WRITE(ah, addr, wrData); - rdData = REG_READ(ah, addr); - if (wrData != rdData) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", - addr, wrData, rdData); - return false; - } - } - REG_WRITE(ah, regAddr[i], regHold[i]); - } - udelay(100); - - return true; -} - -static const char *ath9k_hw_devname(u16 devid) -{ - switch (devid) { - case AR5416_DEVID_PCI: - return "Atheros 5416"; - case AR5416_DEVID_PCIE: - return "Atheros 5418"; - case AR9160_DEVID_PCI: - return "Atheros 9160"; - case AR5416_AR9100_DEVID: - return "Atheros 9100"; - case AR9280_DEVID_PCI: - case AR9280_DEVID_PCIE: - return "Atheros 9280"; - case AR9285_DEVID_PCIE: - return "Atheros 9285"; - } - - return NULL; -} - -static void ath9k_hw_set_defaults(struct ath_hw *ah) -{ - int i; - - ah->config.dma_beacon_response_time = 2; - ah->config.sw_beacon_response_time = 10; - ah->config.additional_swba_backoff = 0; - ah->config.ack_6mb = 0x0; - ah->config.cwm_ignore_extcca = 0; - ah->config.pcie_powersave_enable = 0; - ah->config.pcie_clock_req = 0; - ah->config.pcie_waen = 0; - ah->config.analog_shiftreg = 1; - ah->config.ht_enable = 1; - ah->config.ofdm_trig_low = 200; - ah->config.ofdm_trig_high = 500; - ah->config.cck_trig_high = 200; - ah->config.cck_trig_low = 100; - ah->config.enable_ani = 1; - ah->config.diversity_control = 0; - ah->config.antenna_switch_swap = 0; - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - ah->config.spurchans[i][0] = AR_NO_SPUR; - ah->config.spurchans[i][1] = AR_NO_SPUR; - } - - ah->config.intr_mitigation = true; - - /* - * We need this for PCI devices only (Cardbus, PCI, miniPCI) - * _and_ if on non-uniprocessor systems (Multiprocessor/HT). - * This means we use it for all AR5416 devices, and the few - * minor PCI AR9280 devices out there. - * - * Serialization is required because these devices do not handle - * well the case of two concurrent reads/writes due to the latency - * involved. During one read/write another read/write can be issued - * on another CPU while the previous read/write may still be working - * on our hardware, if we hit this case the hardware poops in a loop. - * We prevent this by serializing reads and writes. - * - * This issue is not present on PCI-Express devices or pre-AR5416 - * devices (legacy, 802.11abg). - */ - if (num_possible_cpus() > 1) - ah->config.serialize_regmode = SER_REG_MODE_AUTO; -} - -static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc, - int *status) -{ - struct ath_hw *ah; - - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); - if (ah == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, - "Cannot allocate memory for state block\n"); - *status = -ENOMEM; - return NULL; - } - - ah->ah_sc = sc; - ah->hw_version.magic = AR5416_MAGIC; - ah->regulatory.country_code = CTRY_DEFAULT; - ah->hw_version.devid = devid; - ah->hw_version.subvendorid = 0; - - ah->ah_flags = 0; - if ((devid == AR5416_AR9100_DEVID)) - ah->hw_version.macVersion = AR_SREV_VERSION_9100; - if (!AR_SREV_9100(ah)) - ah->ah_flags = AH_USE_EEPROM; - - ah->regulatory.power_limit = MAX_RATE_POWER; - ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; - ah->atim_window = 0; - ah->diversity_control = ah->config.diversity_control; - ah->antenna_switch_swap = - ah->config.antenna_switch_swap; - ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; - ah->beacon_interval = 100; - ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = (u32) -1; - ah->acktimeout = (u32) -1; - ah->ctstimeout = (u32) -1; - ah->globaltxtimeout = (u32) -1; - - ah->gbeacon_rate = 0; - - return ah; -} - -static int ath9k_hw_rfattach(struct ath_hw *ah) -{ - bool rfStatus = false; - int ecode = 0; - - rfStatus = ath9k_hw_init_rf(ah, &ecode); - if (!rfStatus) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "RF setup failed, status: %u\n", ecode); - return ecode; - } - - return 0; -} - -static int ath9k_hw_rf_claim(struct ath_hw *ah) -{ - u32 val; - - REG_WRITE(ah, AR_PHY(0), 0x00000007); - - val = ath9k_hw_get_radiorev(ah); - switch (val & AR_RADIO_SREV_MAJOR) { - case 0: - val = AR_RAD5133_SREV_MAJOR; - break; - case AR_RAD5133_SREV_MAJOR: - case AR_RAD5122_SREV_MAJOR: - case AR_RAD2133_SREV_MAJOR: - case AR_RAD2122_SREV_MAJOR: - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Radio Chip Rev 0x%02X not supported\n", - val & AR_RADIO_SREV_MAJOR); - return -EOPNOTSUPP; - } - - ah->hw_version.analog5GhzRev = val; - - return 0; -} - -static int ath9k_hw_init_macaddr(struct ath_hw *ah) -{ - u32 sum; - int i; - u16 eeval; - - sum = 0; - for (i = 0; i < 3; i++) { - eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); - sum += eeval; - ah->macaddr[2 * i] = eeval >> 8; - ah->macaddr[2 * i + 1] = eeval & 0xff; - } - if (sum == 0 || sum == 0xffff * 3) - return -EADDRNOTAVAIL; - - return 0; -} - -static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah) -{ - u32 rxgain_type; - - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) { - rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); - - if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_backoff_13db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); - else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_backoff_23db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); - } -} - -static void ath9k_hw_init_txgain_ini(struct ath_hw *ah) -{ - u32 txgain_type; - - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) { - txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - - if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_high_power_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); - } -} - -static int ath9k_hw_post_attach(struct ath_hw *ah) -{ - int ecode; - - if (!ath9k_hw_chip_test(ah)) - return -ENODEV; - - ecode = ath9k_hw_rf_claim(ah); - if (ecode != 0) - return ecode; - - ecode = ath9k_hw_eeprom_attach(ah); - if (ecode != 0) - return ecode; - - DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", - ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - - ecode = ath9k_hw_rfattach(ah); - if (ecode != 0) - return ecode; - - if (!AR_SREV_9100(ah)) { - ath9k_hw_ani_setup(ah); - ath9k_hw_ani_attach(ah); - } - - return 0; -} - -static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, - int *status) -{ - struct ath_hw *ah; - int ecode; - u32 i, j; - - ah = ath9k_hw_newstate(devid, sc, status); - if (ah == NULL) - return NULL; - - ath9k_hw_set_defaults(ah); - - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); - ecode = -EIO; - goto bad; - } - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); - ecode = -EIO; - goto bad; - } - - if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { - if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || - (AR_SREV_9280(ah) && !ah->is_pciexpress)) { - ah->config.serialize_regmode = - SER_REG_MODE_ON; - } else { - ah->config.serialize_regmode = - SER_REG_MODE_OFF; - } - } - - DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n", - ah->config.serialize_regmode); - - if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) && - (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && - (ah->hw_version.macVersion != AR_SREV_VERSION_9160) && - (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) { - DPRINTF(sc, ATH_DBG_FATAL, - "Mac Chip Rev 0x%02x.%x is not supported by " - "this driver\n", ah->hw_version.macVersion, - ah->hw_version.macRev); - ecode = -EOPNOTSUPP; - goto bad; - } - - if (AR_SREV_9100(ah)) { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->supp_cals = IQ_MISMATCH_CAL; - ah->is_pciexpress = false; - } - ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); - - if (AR_SREV_9160_10_OR_LATER(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) { - ah->iq_caldata.calData = &iq_cal_single_sample; - ah->adcgain_caldata.calData = - &adc_gain_cal_single_sample; - ah->adcdc_caldata.calData = - &adc_dc_cal_single_sample; - ah->adcdc_calinitdata.calData = - &adc_init_dc_cal; - } else { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->adcgain_caldata.calData = - &adc_gain_cal_multi_sample; - ah->adcdc_caldata.calData = - &adc_dc_cal_multi_sample; - ah->adcdc_calinitdata.calData = - &adc_init_dc_cal; - } - ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; - } - - ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) - ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - - if (AR_SREV_9285_12_OR_LATER(ah)) { - - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, - ARRAY_SIZE(ar9285Modes_9285_1_2), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, - ARRAY_SIZE(ar9285Common_9285_1_2), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285_1_2, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285_1_2, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), - 2); - } - } else if (AR_SREV_9285_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, - ARRAY_SIZE(ar9285Modes_9285), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, - ARRAY_SIZE(ar9285Common_9285), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); - } - } else if (AR_SREV_9280_20_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, - ARRAY_SIZE(ar9280Modes_9280_2), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, - ARRAY_SIZE(ar9280Common_9280_2), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9280PciePhy_clkreq_off_L1_9280, - ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9280PciePhy_clkreq_always_on_L1_9280, - ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); - } - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9280Modes_fast_clock_9280_2, - ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); - } else if (AR_SREV_9280_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, - ARRAY_SIZE(ar9280Modes_9280), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, - ARRAY_SIZE(ar9280Common_9280), 2); - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, - ARRAY_SIZE(ar5416Modes_9160), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, - ARRAY_SIZE(ar5416Common_9160), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, - ARRAY_SIZE(ar5416Bank0_9160), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, - ARRAY_SIZE(ar5416BB_RfGain_9160), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, - ARRAY_SIZE(ar5416Bank1_9160), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, - ARRAY_SIZE(ar5416Bank2_9160), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, - ARRAY_SIZE(ar5416Bank3_9160), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, - ARRAY_SIZE(ar5416Bank6_9160), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, - ARRAY_SIZE(ar5416Bank6TPC_9160), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, - ARRAY_SIZE(ar5416Bank7_9160), 2); - if (AR_SREV_9160_11(ah)) { - INIT_INI_ARRAY(&ah->iniAddac, - ar5416Addac_91601_1, - ARRAY_SIZE(ar5416Addac_91601_1), 2); - } else { - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, - ARRAY_SIZE(ar5416Addac_9160), 2); - } - } else if (AR_SREV_9100_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, - ARRAY_SIZE(ar5416Modes_9100), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, - ARRAY_SIZE(ar5416Common_9100), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, - ARRAY_SIZE(ar5416Bank0_9100), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, - ARRAY_SIZE(ar5416BB_RfGain_9100), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, - ARRAY_SIZE(ar5416Bank1_9100), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, - ARRAY_SIZE(ar5416Bank2_9100), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, - ARRAY_SIZE(ar5416Bank3_9100), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, - ARRAY_SIZE(ar5416Bank6_9100), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, - ARRAY_SIZE(ar5416Bank6TPC_9100), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, - ARRAY_SIZE(ar5416Bank7_9100), 2); - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, - ARRAY_SIZE(ar5416Addac_9100), 2); - } else { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, - ARRAY_SIZE(ar5416Modes), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, - ARRAY_SIZE(ar5416Common), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, - ARRAY_SIZE(ar5416Bank0), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, - ARRAY_SIZE(ar5416BB_RfGain), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, - ARRAY_SIZE(ar5416Bank1), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, - ARRAY_SIZE(ar5416Bank2), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, - ARRAY_SIZE(ar5416Bank3), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, - ARRAY_SIZE(ar5416Bank6), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, - ARRAY_SIZE(ar5416Bank6TPC), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, - ARRAY_SIZE(ar5416Bank7), 2); - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, - ARRAY_SIZE(ar5416Addac), 2); - } - - if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, 0); - else - ath9k_hw_disablepcie(ah); - - ecode = ath9k_hw_post_attach(ah); - if (ecode != 0) - goto bad; - - if (AR_SREV_9285_12_OR_LATER(ah)) { - u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - - /* txgain table */ - if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_high_power_tx_gain_9285_1_2, - ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_original_tx_gain_9285_1_2, - ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); - } - - } - - /* rxgain table */ - if (AR_SREV_9280_20(ah)) - ath9k_hw_init_rxgain_ini(ah); - - /* txgain table */ - if (AR_SREV_9280_20(ah)) - ath9k_hw_init_txgain_ini(ah); - - ath9k_hw_fill_cap_info(ah); - - if ((ah->hw_version.devid == AR9280_DEVID_PCI) && - test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { - - /* EEPROM Fixup */ - for (i = 0; i < ah->iniModes.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniModes, i, 0); - - for (j = 1; j < ah->iniModes.ia_columns; j++) { - u32 val = INI_RA(&ah->iniModes, i, j); - - INI_RA(&ah->iniModes, i, j) = - ath9k_hw_ini_fixup(ah, - &ah->eeprom.def, - reg, val); - } - } - } - - ecode = ath9k_hw_init_macaddr(ah); - if (ecode != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to initialize MAC address\n"); - goto bad; - } - - if (AR_SREV_9285(ah)) - ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); - else - ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); - - ath9k_init_nfcal_hist_buffer(ah); - - return ah; -bad: - if (ah) - ath9k_hw_detach(ah); - if (status) - *status = ecode; - - return NULL; -} - -static void ath9k_hw_init_bb(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 synthDelay; - - synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; - if (IS_CHAN_B(chan)) - synthDelay = (4 * synthDelay) / 22; - else - synthDelay /= 10; - - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - - udelay(synthDelay + BASE_ACTIVATE_DELAY); -} - -static void ath9k_hw_init_qos(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); - REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); - - REG_WRITE(ah, AR_QOS_NO_ACK, - SM(2, AR_QOS_NO_ACK_TWO_BIT) | - SM(5, AR_QOS_NO_ACK_BIT_OFF) | - SM(0, AR_QOS_NO_ACK_BYTE_OFF)); - - REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); - REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); - REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); - REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); - REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); -} - -static void ath9k_hw_init_pll(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 pll; - - if (AR_SREV_9100(ah)) { - if (chan && IS_CHAN_5GHZ(chan)) - pll = 0x1450; - else - pll = 0x1458; - } else { - if (AR_SREV_9280_10_OR_LATER(ah)) { - pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) { - pll |= SM(0x28, AR_RTC_9160_PLL_DIV); - - - if (AR_SREV_9280_20(ah)) { - if (((chan->channel % 20) == 0) - || ((chan->channel % 10) == 0)) - pll = 0x2850; - else - pll = 0x142c; - } - } else { - pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); - } - - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - - pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) - pll |= SM(0x50, AR_RTC_9160_PLL_DIV); - else - pll |= SM(0x58, AR_RTC_9160_PLL_DIV); - } else { - pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) - pll |= SM(0xa, AR_RTC_PLL_DIV); - else - pll |= SM(0xb, AR_RTC_PLL_DIV); - } - } - REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - - udelay(RTC_PLL_SETTLE_DELAY); - - REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); -} - -static void ath9k_hw_init_chain_masks(struct ath_hw *ah) -{ - int rx_chainmask, tx_chainmask; - - rx_chainmask = ah->rxchainmask; - tx_chainmask = ah->txchainmask; - - switch (rx_chainmask) { - case 0x5: - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - case 0x3: - if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) { - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); - break; - } - case 0x1: - case 0x2: - case 0x7: - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); - break; - default: - break; - } - - REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); - if (tx_chainmask == 0x5) { - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - } - if (AR_SREV_9100(ah)) - REG_WRITE(ah, AR_PHY_ANALOG_SWAP, - REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); -} - -static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, - enum nl80211_iftype opmode) -{ - ah->mask_reg = AR_IMR_TXERR | - AR_IMR_TXURN | - AR_IMR_RXERR | - AR_IMR_RXORN | - AR_IMR_BCNMISC; - - if (ah->config.intr_mitigation) - ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; - else - ah->mask_reg |= AR_IMR_RXOK; - - ah->mask_reg |= AR_IMR_TXOK; - - if (opmode == NL80211_IFTYPE_AP) - ah->mask_reg |= AR_IMR_MIB; - - REG_WRITE(ah, AR_IMR, ah->mask_reg); - REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); - - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); - } -} - -static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) -{ - if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us); - ah->acktimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_TIME_OUT, - AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); - ah->acktimeout = us; - return true; - } -} - -static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) -{ - if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us); - ah->ctstimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_TIME_OUT, - AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); - ah->ctstimeout = us; - return true; - } -} - -static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) -{ - if (tu > 0xFFFF) { - DPRINTF(ah->ah_sc, ATH_DBG_XMIT, - "bad global tx timeout %u\n", tu); - ah->globaltxtimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); - ah->globaltxtimeout = tu; - return true; - } -} - -static void ath9k_hw_init_user_settings(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n", - ah->misc_mode); - - if (ah->misc_mode != 0) - REG_WRITE(ah, AR_PCU_MISC, - REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); - if (ah->slottime != (u32) -1) - ath9k_hw_setslottime(ah, ah->slottime); - if (ah->acktimeout != (u32) -1) - ath9k_hw_set_ack_timeout(ah, ah->acktimeout); - if (ah->ctstimeout != (u32) -1) - ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); - if (ah->globaltxtimeout != (u32) -1) - ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); -} - -const char *ath9k_hw_probe(u16 vendorid, u16 devid) -{ - return vendorid == ATHEROS_VENDOR_ID ? - ath9k_hw_devname(devid) : NULL; -} - -void ath9k_hw_detach(struct ath_hw *ah) -{ - if (!AR_SREV_9100(ah)) - ath9k_hw_ani_detach(ah); - - ath9k_hw_rfdetach(ah); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); - kfree(ah); -} - -struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error) -{ - struct ath_hw *ah = NULL; - - switch (devid) { - case AR5416_DEVID_PCI: - case AR5416_DEVID_PCIE: - case AR5416_AR9100_DEVID: - case AR9160_DEVID_PCI: - case AR9280_DEVID_PCI: - case AR9280_DEVID_PCIE: - case AR9285_DEVID_PCIE: - ah = ath9k_hw_do_attach(devid, sc, error); - break; - default: - *error = -ENXIO; - break; - } - - return ah; -} - -/*******/ -/* INI */ -/*******/ - -static void ath9k_hw_override_ini(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - /* - * Set the RX_ABORT and RX_DIS and clear if off only after - * RXE is set for MAC. This prevents frames with corrupted - * descriptor status. - */ - REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - - - if (!AR_SREV_5416_20_OR_LATER(ah) || - AR_SREV_9280_10_OR_LATER(ah)) - return; - - REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); -} - -static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value) -{ - struct base_eep_header *pBase = &(pEepData->baseEepHeader); - - switch (ah->hw_version.devid) { - case AR9280_DEVID_PCI: - if (reg == 0x7894) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ini VAL: %x EEPROM: %x\n", value, - (pBase->version & 0xff)); - - if ((pBase->version & 0xff) > 0x0a) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PWDCLKIND: %d\n", - pBase->pwdclkind); - value &= ~AR_AN_TOP2_PWDCLKIND; - value |= AR_AN_TOP2_PWDCLKIND & - (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); - } else { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PWDCLKIND Earlier Rev\n"); - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "final ini VAL: %x\n", value); - } - break; - } - - return value; -} - -static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value) -{ - if (ah->eep_map == EEP_MAP_4KBITS) - return value; - else - return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); -} - -static void ath9k_olc_init(struct ath_hw *ah) -{ - u32 i; - - for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) - ah->originalGain[i] = - MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), - AR_PHY_TX_GAIN); - ah->PDADCdelta = 0; -} - -static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, - struct ath9k_channel *chan) -{ - u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); - - if (IS_CHAN_B(chan)) - ctl |= CTL_11B; - else if (IS_CHAN_G(chan)) - ctl |= CTL_11G; - else - ctl |= CTL_11A; - - return ctl; -} - -static int ath9k_hw_process_ini(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) -{ - int i, regWrites = 0; - struct ieee80211_channel *channel = chan->chan; - u32 modesIndex, freqIndex; - int status; - - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - modesIndex = 1; - freqIndex = 1; - break; - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - modesIndex = 2; - freqIndex = 1; - break; - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_B: - modesIndex = 4; - freqIndex = 2; - break; - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - modesIndex = 3; - freqIndex = 2; - break; - - default: - return -EINVAL; - } - - REG_WRITE(ah, AR_PHY(0), 0x00000007); - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); - ah->eep_ops->set_addac(ah, chan); - - if (AR_SREV_5416_22_OR_LATER(ah)) { - REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); - } else { - struct ar5416IniArray temp; - u32 addacSize = - sizeof(u32) * ah->iniAddac.ia_rows * - ah->iniAddac.ia_columns; - - memcpy(ah->addac5416_21, - ah->iniAddac.ia_array, addacSize); - - (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; - - temp.ia_array = ah->addac5416_21; - temp.ia_columns = ah->iniAddac.ia_columns; - temp.ia_rows = ah->iniAddac.ia_rows; - REG_WRITE_ARRAY(&temp, 1, regWrites); - } - - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); - - for (i = 0; i < ah->iniModes.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniModes, i, 0); - u32 val = INI_RA(&ah->iniModes, i, modesIndex); - - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { - udelay(100); - } - - DO_DELAY(regWrites); - } - - if (AR_SREV_9280(ah)) - REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - - if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) && - AR_SREV_9285_12_OR_LATER(ah))) - REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); - - for (i = 0; i < ah->iniCommon.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniCommon, i, 0); - u32 val = INI_RA(&ah->iniCommon, i, 1); - - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { - udelay(100); - } - - DO_DELAY(regWrites); - } - - ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); - - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { - REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, - regWrites); - } - - ath9k_hw_override_ini(ah, chan); - ath9k_hw_set_regs(ah, chan, macmode); - ath9k_hw_init_chain_masks(ah); - - if (OLC_FOR_AR9280_20_LATER) - ath9k_olc_init(ah); - - status = ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(&ah->regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)); - if (status != 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Error initializing transmit power\n"); - return -EIO; - } - - if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "ar5416SetRfRegs failed\n"); - return -EIO; - } - - return 0; -} - -/****************************************/ -/* Reset and Channel Switching Routines */ -/****************************************/ - -static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u32 rfMode = 0; - - if (chan == NULL) - return; - - rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) - ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - - if (!AR_SREV_9280_10_OR_LATER(ah)) - rfMode |= (IS_CHAN_5GHZ(chan)) ? - AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; - - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) - rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); - - REG_WRITE(ah, AR_PHY_MODE, rfMode); -} - -static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -} - -static inline void ath9k_hw_set_dma(struct ath_hw *ah) -{ - u32 regval; - - regval = REG_READ(ah, AR_AHB_MODE); - REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); - - regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); - - REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); - - regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); - - REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); - - if (AR_SREV_9285(ah)) { - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); - } else { - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_PCU_TXBUF_CTRL_USABLE_SIZE); - } -} - -static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) -{ - u32 val; - - val = REG_READ(ah, AR_STA_ID1); - val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); - switch (opmode) { - case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP - | AR_STA_ID1_KSRCH_MODE); - REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC - | AR_STA_ID1_KSRCH_MODE); - REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_MONITOR: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); - break; - } -} - -static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, - u32 coef_scaled, - u32 *coef_mantissa, - u32 *coef_exponent) -{ - u32 coef_exp, coef_man; - - for (coef_exp = 31; coef_exp > 0; coef_exp--) - if ((coef_scaled >> coef_exp) & 0x1) - break; - - coef_exp = 14 - (coef_exp - COEF_SCALE_S); - - coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); - - *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); - *coef_exponent = coef_exp - 16; -} - -static void ath9k_hw_set_delta_slope(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 coef_scaled, ds_coef_exp, ds_coef_man; - u32 clockMhzScaled = 0x64000000; - struct chan_centers centers; - - if (IS_CHAN_HALF_RATE(chan)) - clockMhzScaled = clockMhzScaled >> 1; - else if (IS_CHAN_QUARTER_RATE(chan)) - clockMhzScaled = clockMhzScaled >> 2; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - coef_scaled = clockMhzScaled / centers.synth_center; - - ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, - &ds_coef_exp); - - REG_RMW_FIELD(ah, AR_PHY_TIMING3, - AR_PHY_TIMING3_DSC_MAN, ds_coef_man); - REG_RMW_FIELD(ah, AR_PHY_TIMING3, - AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); - - coef_scaled = (9 * coef_scaled) / 10; - - ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, - &ds_coef_exp); - - REG_RMW_FIELD(ah, AR_PHY_HALFGI, - AR_PHY_HALFGI_DSC_MAN, ds_coef_man); - REG_RMW_FIELD(ah, AR_PHY_HALFGI, - AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); -} - -static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) -{ - u32 rst_flags; - u32 tmpReg; - - if (AR_SREV_9100(ah)) { - u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); - val &= ~AR_RTC_DERIVED_CLK_PERIOD; - val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); - REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); - (void)REG_READ(ah, AR_RTC_DERIVED_CLK); - } - - REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | - AR_RTC_FORCE_WAKE_ON_INT); - - if (AR_SREV_9100(ah)) { - rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | - AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; - } else { - tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if (tmpReg & - (AR_INTR_SYNC_LOCAL_TIMEOUT | - AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - } else { - REG_WRITE(ah, AR_RC, AR_RC_AHB); - } - - rst_flags = AR_RTC_RC_MAC_WARM; - if (type == ATH9K_RESET_COLD) - rst_flags |= AR_RTC_RC_MAC_COLD; - } - - REG_WRITE(ah, AR_RTC_RC, rst_flags); - udelay(50); - - REG_WRITE(ah, AR_RTC_RC, 0); - if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "RTC stuck in MAC reset\n"); - return false; - } - - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, 0); - - ath9k_hw_init_pll(ah, NULL); - - if (AR_SREV_9100(ah)) - udelay(50); - - return true; -} - -static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | - AR_RTC_FORCE_WAKE_ON_INT); - - REG_WRITE(ah, AR_RTC_RESET, 0); - udelay(2); - REG_WRITE(ah, AR_RTC_RESET, 1); - - if (!ath9k_hw_wait(ah, - AR_RTC_STATUS, - AR_RTC_STATUS_M, - AR_RTC_STATUS_ON, - AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); - return false; - } - - ath9k_hw_read_revisions(ah); - - return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); -} - -static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) -{ - REG_WRITE(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); - - switch (type) { - case ATH9K_RESET_POWER_ON: - return ath9k_hw_set_reset_power_on(ah); - break; - case ATH9K_RESET_WARM: - case ATH9K_RESET_COLD: - return ath9k_hw_set_reset(ah, type); - break; - default: - return false; - } -} - -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) -{ - u32 phymode; - u32 enableDacFifo = 0; - - if (AR_SREV_9285_10_OR_LATER(ah)) - enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & - AR_PHY_FC_ENABLE_DAC_FIFO); - - phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 - | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; - - if (IS_CHAN_HT40(chan)) { - phymode |= AR_PHY_FC_DYN2040_EN; - - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || - (chan->chanmode == CHANNEL_G_HT40PLUS)) - phymode |= AR_PHY_FC_DYN2040_PRI_CH; - - if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25) - phymode |= AR_PHY_FC_DYN2040_EXT_CH; - } - REG_WRITE(ah, AR_PHY_TURBO, phymode); - - ath9k_hw_set11nmac2040(ah, macmode); - - REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); - REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); -} - -static bool ath9k_hw_chip_reset(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - if (OLC_FOR_AR9280_20_LATER) { - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) - return false; - } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) - return false; - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return false; - - ah->chip_fullsleep = false; - ath9k_hw_init_pll(ah, chan); - ath9k_hw_set_rfmode(ah, chan); - - return true; -} - -static bool ath9k_hw_channel_change(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) -{ - struct ieee80211_channel *channel = chan->chan; - u32 synthDelay, qnum; - - for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { - if (ath9k_hw_numtxpending(ah, qnum)) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "Transmit frames pending on queue %d\n", qnum); - return false; - } - } - - REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); - if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, - AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Could not kill baseband RX\n"); - return false; - } - - ath9k_hw_set_regs(ah, chan, macmode); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to set channel\n"); - return false; - } - } else { - if (!(ath9k_hw_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to set channel\n"); - return false; - } - } - - if (ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(&ah->regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)) != 0) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Error initializing transmit power\n"); - return false; - } - - synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; - if (IS_CHAN_B(chan)) - synthDelay = (4 * synthDelay) / 22; - else - synthDelay /= 10; - - udelay(synthDelay + BASE_ACTIVATE_DELAY); - - REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); - - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) - ath9k_hw_set_delta_slope(ah, chan); - - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_9280_spur_mitigate(ah, chan); - else - ath9k_hw_spur_mitigate(ah, chan); - - if (!chan->oneTimeCalsDone) - chan->oneTimeCalsDone = true; - - return true; -} - -static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int freq; - int bin, cur_bin; - int bb_spur_off, spur_subchannel_sd; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, newVal; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - struct chan_centers centers; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - ah->config.spurmode = SPUR_ENABLE_EEPROM; - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - - if (is2GHz) - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; - else - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; - - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - freq; - - if (IS_CHAN_HT40(chan)) { - if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { - bb_spur = cur_bb_spur; - break; - } - } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - return; - } else { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - } - - bin = bb_spur * 320; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - - newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); - - newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); - - if (IS_CHAN_HT40(chan)) { - if (bb_spur < 0) { - spur_subchannel_sd = 1; - bb_spur_off = bb_spur + 10; - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur - 10; - } - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur; - } - - if (IS_CHAN_HT40(chan)) - spur_delta_phase = - ((bb_spur * 262144) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - else - spur_delta_phase = - ((bb_spur * 524288) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; - spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; - - newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, newVal); - - newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; - REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int bin, cur_bin; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, new; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - (chan->channel * 10); - if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) - return; - - bin = bb_spur * 32; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); - - new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, new); - - spur_delta_phase = ((bb_spur * 524288) / 100) & - AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; - spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; - - new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, new); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, - bool bChannelChange) -{ - u32 saveLedState; - struct ath_softc *sc = ah->ah_sc; - struct ath9k_channel *curchan = ah->curchan; - u32 saveDefAntenna; - u32 macStaId1; - int i, rx_chainmask, r; - - ah->extprotspacing = sc->ht_extprotspacing; - ah->txchainmask = sc->tx_chainmask; - ah->rxchainmask = sc->rx_chainmask; - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return -EIO; - - if (curchan) - ath9k_hw_getnf(ah, curchan); - - if (bChannelChange && - (ah->chip_fullsleep != true) && - (ah->curchan != NULL) && - (chan->channel != ah->curchan->channel) && - ((chan->channelFlags & CHANNEL_ALL) == - (ah->curchan->channelFlags & CHANNEL_ALL)) && - (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && - !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) { - - if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { - ath9k_hw_loadnf(ah, ah->curchan); - ath9k_hw_start_nfcal(ah); - return 0; - } - } - - saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); - if (saveDefAntenna == 0) - saveDefAntenna = 1; - - macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; - - saveLedState = REG_READ(ah, AR_CFG_LED) & - (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | - AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); - - ath9k_hw_mark_phy_inactive(ah); - - if (!ath9k_hw_chip_reset(ah, chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); - return -EINVAL; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); - - r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); - if (r) - return r; - - /* Setup MFP options for CCMP */ - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt - * frames when constructing CCMP AAD. */ - REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, - 0xc7ff); - ah->sw_mgmt_crypto = false; - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - /* Disable hardware crypto for management frames */ - REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); - REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); - ah->sw_mgmt_crypto = true; - } else - ah->sw_mgmt_crypto = true; - - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) - ath9k_hw_set_delta_slope(ah, chan); - - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_9280_spur_mitigate(ah, chan); - else - ath9k_hw_spur_mitigate(ah, chan); - - ah->eep_ops->set_board_values(ah, chan); - - ath9k_hw_decrease_chain_power(ah, chan); - - REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr)); - REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4) - | macStaId1 - | AR_STA_ID1_RTS_USE_DEF - | (ah->config. - ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) - | ah->sta_id1_defaults); - ath9k_hw_set_operating_mode(ah, ah->opmode); - - REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); - REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); - - REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); - - REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); - REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | - ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); - - REG_WRITE(ah, AR_ISR, ~0); - - REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) - return -EIO; - } else { - if (!(ath9k_hw_set_channel(ah, chan))) - return -EIO; - } - - for (i = 0; i < AR_NUM_DCU; i++) - REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); - - ah->intr_txqs = 0; - for (i = 0; i < ah->caps.total_queues; i++) - ath9k_hw_resettxqueue(ah, i); - - ath9k_hw_init_interrupt_masks(ah, ah->opmode); - ath9k_hw_init_qos(ah); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - ath9k_enable_rfkill(ah); -#endif - ath9k_hw_init_user_settings(ah); - - REG_WRITE(ah, AR_STA_ID1, - REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); - - ath9k_hw_set_dma(ah); - - REG_WRITE(ah, AR_OBS, 8); - - if (ah->config.intr_mitigation) { - REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); - REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); - } - - ath9k_hw_init_bb(ah, chan); - - if (!ath9k_hw_init_cal(ah, chan)) - return -EIO;; - - rx_chainmask = ah->rxchainmask; - if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); - } - - REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); - - if (AR_SREV_9100(ah)) { - u32 mask; - mask = REG_READ(ah, AR_CFG); - if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "CFG Byte Swap Set 0x%x\n", mask); - } else { - mask = - INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; - REG_WRITE(ah, AR_CFG, mask); - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); - } - } else { -#ifdef __BIG_ENDIAN - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); -#endif - } - - return 0; -} - -/************************/ -/* Key Cache Management */ -/************************/ - -bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) -{ - u32 keyType; - - if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); - return false; - } - - keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); - - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); - REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); - - if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { - u16 micentry = entry + 64; - - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); - - } - - if (ah->curchan == NULL) - return true; - - return true; -} - -bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) -{ - u32 macHi, macLo; - - if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); - return false; - } - - if (mac != NULL) { - macHi = (mac[5] << 8) | mac[4]; - macLo = (mac[3] << 24) | - (mac[2] << 16) | - (mac[1] << 8) | - mac[0]; - macLo >>= 1; - macLo |= (macHi & 1) << 31; - macHi >>= 1; - } else { - macLo = macHi = 0; - } - REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); - REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); - - return true; -} - -bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, - const struct ath9k_keyval *k, - const u8 *mac) -{ - const struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 key0, key1, key2, key3, key4; - u32 keyType; - - if (entry >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keycache entry %u out of range\n", entry); - return false; - } - - switch (k->kv_type) { - case ATH9K_CIPHER_AES_OCB: - keyType = AR_KEYTABLE_TYPE_AES; - break; - case ATH9K_CIPHER_AES_CCM: - if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "AES-CCM not supported by mac rev 0x%x\n", - ah->hw_version.macRev); - return false; - } - keyType = AR_KEYTABLE_TYPE_CCM; - break; - case ATH9K_CIPHER_TKIP: - keyType = AR_KEYTABLE_TYPE_TKIP; - if (ATH9K_IS_MIC_ENABLED(ah) - && entry + 64 >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "entry %u inappropriate for TKIP\n", entry); - return false; - } - break; - case ATH9K_CIPHER_WEP: - if (k->kv_len < LEN_WEP40) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "WEP key length %u too small\n", k->kv_len); - return false; - } - if (k->kv_len <= LEN_WEP40) - keyType = AR_KEYTABLE_TYPE_40; - else if (k->kv_len <= LEN_WEP104) - keyType = AR_KEYTABLE_TYPE_104; - else - keyType = AR_KEYTABLE_TYPE_128; - break; - case ATH9K_CIPHER_CLR: - keyType = AR_KEYTABLE_TYPE_CLR; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "cipher %u not supported\n", k->kv_type); - return false; - } - - key0 = get_unaligned_le32(k->kv_val + 0); - key1 = get_unaligned_le16(k->kv_val + 4); - key2 = get_unaligned_le32(k->kv_val + 6); - key3 = get_unaligned_le16(k->kv_val + 10); - key4 = get_unaligned_le32(k->kv_val + 12); - if (k->kv_len <= LEN_WEP104) - key4 &= 0xff; - - /* - * Note: Key cache registers access special memory area that requires - * two 32-bit writes to actually update the values in the internal - * memory. Consequently, the exact order and pairs used here must be - * maintained. - */ - - if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { - u16 micentry = entry + 64; - - /* - * Write inverted key[47:0] first to avoid Michael MIC errors - * on frames that could be sent or received at the same time. - * The correct key will be written in the end once everything - * else is ready. - */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); - - /* Write key[95:48] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); - - /* Write key[127:96] and key type */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); - - /* Write MAC address for the entry */ - (void) ath9k_hw_keysetmac(ah, entry, mac); - - if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { - /* - * TKIP uses two key cache entries: - * Michael MIC TX/RX keys in the same key cache entry - * (idx = main index + 64): - * key0 [31:0] = RX key [31:0] - * key1 [15:0] = TX key [31:16] - * key1 [31:16] = reserved - * key2 [31:0] = RX key [63:32] - * key3 [15:0] = TX key [15:0] - * key3 [31:16] = reserved - * key4 [31:0] = TX key [63:32] - */ - u32 mic0, mic1, mic2, mic3, mic4; - - mic0 = get_unaligned_le32(k->kv_mic + 0); - mic2 = get_unaligned_le32(k->kv_mic + 4); - mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; - mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; - mic4 = get_unaligned_le32(k->kv_txmic + 4); - - /* Write RX[31:0] and TX[31:16] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); - - /* Write RX[63:32] and TX[15:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); - - /* Write TX[63:32] and keyType(reserved) */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), - AR_KEYTABLE_TYPE_CLR); - - } else { - /* - * TKIP uses four key cache entries (two for group - * keys): - * Michael MIC TX/RX keys are in different key cache - * entries (idx = main index + 64 for TX and - * main index + 32 + 96 for RX): - * key0 [31:0] = TX/RX MIC key [31:0] - * key1 [31:0] = reserved - * key2 [31:0] = TX/RX MIC key [63:32] - * key3 [31:0] = reserved - * key4 [31:0] = reserved - * - * Upper layer code will call this function separately - * for TX and RX keys when these registers offsets are - * used. - */ - u32 mic0, mic2; - - mic0 = get_unaligned_le32(k->kv_mic + 0); - mic2 = get_unaligned_le32(k->kv_mic + 4); - - /* Write MIC key[31:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); - - /* Write MIC key[63:32] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); - - /* Write TX[63:32] and keyType(reserved) */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), - AR_KEYTABLE_TYPE_CLR); - } - - /* MAC address registers are reserved for the MIC entry */ - REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); - - /* - * Write the correct (un-inverted) key[47:0] last to enable - * TKIP now that all other registers are set with correct - * values. - */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); - } else { - /* Write key[47:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); - - /* Write key[95:48] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); - - /* Write key[127:96] and key type */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); - - /* Write MAC address for the entry */ - (void) ath9k_hw_keysetmac(ah, entry, mac); - } - - return true; -} - -bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) -{ - if (entry < ah->caps.keycache_size) { - u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry)); - if (val & AR_KEYTABLE_VALID) - return true; - } - return false; -} - -/******************************/ -/* Power Management (Chipset) */ -/******************************/ - -static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) -{ - REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - if (setChip) { - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - - REG_CLR_BIT(ah, (AR_RTC_RESET), - AR_RTC_RESET_EN); - } -} - -static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) -{ - REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - if (setChip) { - struct ath9k_hw_capabilities *pCap = &ah->caps; - - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - REG_WRITE(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_ON_INT); - } else { - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - } - } -} - -static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) -{ - u32 val; - int i; - - if (setChip) { - if ((REG_READ(ah, AR_RTC_STATUS) & - AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { - if (ath9k_hw_set_reset_reg(ah, - ATH9K_RESET_POWER_ON) != true) { - return false; - } - } - if (AR_SREV_9100(ah)) - REG_SET_BIT(ah, AR_RTC_RESET, - AR_RTC_RESET_EN); - - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - udelay(50); - - for (i = POWER_UP_TIME / 50; i > 0; i--) { - val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; - if (val == AR_RTC_STATUS_ON) - break; - udelay(50); - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - } - if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); - return false; - } - } - - REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - - return true; -} - -bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) -{ - int status = true, setChip = true; - static const char *modes[] = { - "AWAKE", - "FULL-SLEEP", - "NETWORK SLEEP", - "UNDEFINED" - }; - - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", - modes[ah->power_mode], modes[mode]); - - switch (mode) { - case ATH9K_PM_AWAKE: - status = ath9k_hw_set_power_awake(ah, setChip); - break; - case ATH9K_PM_FULL_SLEEP: - ath9k_set_power_sleep(ah, setChip); - ah->chip_fullsleep = true; - break; - case ATH9K_PM_NETWORK_SLEEP: - ath9k_set_power_network_sleep(ah, setChip); - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unknown power mode %u\n", mode); - return false; - } - ah->power_mode = mode; - - return status; -} - -/* - * Helper for ASPM support. - * - * Disable PLL when in L0s as well as receiver clock when in L1. - * This power saving option must be enabled through the SerDes. - * - * Programming the SerDes must go through the same 288 bit serial shift - * register as the other analog registers. Hence the 9 writes. - */ -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) -{ - u8 i; - - if (ah->is_pciexpress != true) - return; - - /* Do not touch SerDes registers */ - if (ah->config.pcie_powersave_enable == 2) - return; - - /* Nothing to do on restore for 11N */ - if (restore) - return; - - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* - * AR9280 2.0 or later chips use SerDes values from the - * initvals.h initialized depending on chipset during - * ath9k_hw_do_attach() - */ - for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { - REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), - INI_RA(&ah->iniPcieSerdes, i, 1)); - } - } else if (AR_SREV_9280(ah) && - (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); - REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); - - /* Shut off CLKREQ active in L1 */ - if (ah->config.pcie_clock_req) - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); - else - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - - } else { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); - REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); - - /* - * Ignore ah->ah_config.pcie_clock_req setting for - * pre-AR9280 11n - */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - } - - udelay(1000); - - /* set bit 19 to allow forcing of pcie core into L1 state */ - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); - - /* Several PCIe massages to ensure proper behaviour */ - if (ah->config.pcie_waen) { - REG_WRITE(ah, AR_WA, ah->config.pcie_waen); - } else { - if (AR_SREV_9285(ah)) - REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); - /* - * On AR9280 chips bit 22 of 0x4004 needs to be set to - * otherwise card may disappear. - */ - else if (AR_SREV_9280(ah)) - REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); - else - REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); - } -} - -/**********************/ -/* Interrupt Handling */ -/**********************/ - -bool ath9k_hw_intrpend(struct ath_hw *ah) -{ - u32 host_isr; - - if (AR_SREV_9100(ah)) - return true; - - host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); - if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) - return true; - - host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if ((host_isr & AR_INTR_SYNC_DEFAULT) - && (host_isr != AR_INTR_SPURIOUS)) - return true; - - return false; -} - -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) -{ - u32 isr = 0; - u32 mask2 = 0; - struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 sync_cause = 0; - bool fatal_int = false; - - if (!AR_SREV_9100(ah)) { - if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { - if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) - == AR_RTC_STATUS_ON) { - isr = REG_READ(ah, AR_ISR); - } - } - - sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & - AR_INTR_SYNC_DEFAULT; - - *masked = 0; - - if (!isr && !sync_cause) - return false; - } else { - *masked = 0; - isr = REG_READ(ah, AR_ISR); - } - - if (isr) { - if (isr & AR_ISR_BCNMISC) { - u32 isr2; - isr2 = REG_READ(ah, AR_ISR_S2); - if (isr2 & AR_ISR_S2_TIM) - mask2 |= ATH9K_INT_TIM; - if (isr2 & AR_ISR_S2_DTIM) - mask2 |= ATH9K_INT_DTIM; - if (isr2 & AR_ISR_S2_DTIMSYNC) - mask2 |= ATH9K_INT_DTIMSYNC; - if (isr2 & (AR_ISR_S2_CABEND)) - mask2 |= ATH9K_INT_CABEND; - if (isr2 & AR_ISR_S2_GTT) - mask2 |= ATH9K_INT_GTT; - if (isr2 & AR_ISR_S2_CST) - mask2 |= ATH9K_INT_CST; - if (isr2 & AR_ISR_S2_TSFOOR) - mask2 |= ATH9K_INT_TSFOOR; - } - - isr = REG_READ(ah, AR_ISR_RAC); - if (isr == 0xffffffff) { - *masked = 0; - return false; - } - - *masked = isr & ATH9K_INT_COMMON; - - if (ah->config.intr_mitigation) { - if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) - *masked |= ATH9K_INT_RX; - } - - if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) - *masked |= ATH9K_INT_RX; - if (isr & - (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | - AR_ISR_TXEOL)) { - u32 s0_s, s1_s; - - *masked |= ATH9K_INT_TX; - - s0_s = REG_READ(ah, AR_ISR_S0_S); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - - s1_s = REG_READ(ah, AR_ISR_S1_S); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); - } - - if (isr & AR_ISR_RXORN) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "receive FIFO overrun interrupt\n"); - } - - if (!AR_SREV_9100(ah)) { - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - u32 isr5 = REG_READ(ah, AR_ISR_S5_S); - if (isr5 & AR_ISR_S5_TIM_TIMER) - *masked |= ATH9K_INT_TIM_TIMER; - } - } - - *masked |= mask2; - } - - if (AR_SREV_9100(ah)) - return true; - - if (sync_cause) { - fatal_int = - (sync_cause & - (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) - ? true : false; - - if (fatal_int) { - if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "received PCI FATAL interrupt\n"); - } - if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "received PCI PERR interrupt\n"); - } - } - if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); - REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); - REG_WRITE(ah, AR_RC, 0); - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); - } - - REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); - (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); - } - - return true; -} - -enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah) -{ - return ah->mask_reg; -} - -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) -{ - u32 omask = ah->mask_reg; - u32 mask, mask2; - struct ath9k_hw_capabilities *pCap = &ah->caps; - - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); - - if (omask & ATH9K_INT_GLOBAL) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_DISABLE); - (void) REG_READ(ah, AR_IER); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); - } - } - - mask = ints & ATH9K_INT_COMMON; - mask2 = 0; - - if (ints & ATH9K_INT_TX) { - if (ah->txok_interrupt_mask) - mask |= AR_IMR_TXOK; - if (ah->txdesc_interrupt_mask) - mask |= AR_IMR_TXDESC; - if (ah->txerr_interrupt_mask) - mask |= AR_IMR_TXERR; - if (ah->txeol_interrupt_mask) - mask |= AR_IMR_TXEOL; - } - if (ints & ATH9K_INT_RX) { - mask |= AR_IMR_RXERR; - if (ah->config.intr_mitigation) - mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; - else - mask |= AR_IMR_RXOK | AR_IMR_RXDESC; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - mask |= AR_IMR_GENTMR; - } - - if (ints & (ATH9K_INT_BMISC)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_TIM) - mask2 |= AR_IMR_S2_TIM; - if (ints & ATH9K_INT_DTIM) - mask2 |= AR_IMR_S2_DTIM; - if (ints & ATH9K_INT_DTIMSYNC) - mask2 |= AR_IMR_S2_DTIMSYNC; - if (ints & ATH9K_INT_CABEND) - mask2 |= AR_IMR_S2_CABEND; - if (ints & ATH9K_INT_TSFOOR) - mask2 |= AR_IMR_S2_TSFOOR; - } - - if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_GTT) - mask2 |= AR_IMR_S2_GTT; - if (ints & ATH9K_INT_CST) - mask2 |= AR_IMR_S2_CST; - } - - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); - REG_WRITE(ah, AR_IMR, mask); - mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | - AR_IMR_S2_DTIM | - AR_IMR_S2_DTIMSYNC | - AR_IMR_S2_CABEND | - AR_IMR_S2_CABTO | - AR_IMR_S2_TSFOOR | - AR_IMR_S2_GTT | AR_IMR_S2_CST); - REG_WRITE(ah, AR_IMR_S2, mask | mask2); - ah->mask_reg = ints; - - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - if (ints & ATH9K_INT_TIM_TIMER) - REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); - else - REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); - } - - if (ints & ATH9K_INT_GLOBAL) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, - AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); - } - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); - } - - return omask; -} - -/*******************/ -/* Beacon Handling */ -/*******************/ - -void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) -{ - int flags = 0; - - ah->beacon_interval = beacon_period; - - switch (ah->opmode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_MONITOR: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); - REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); - flags |= AR_TBTT_TIMER_EN; - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - REG_SET_BIT(ah, AR_TXCFG, - AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); - REG_WRITE(ah, AR_NEXT_NDP_TIMER, - TU_TO_USEC(next_beacon + - (ah->atim_window ? ah-> - atim_window : 1))); - flags |= AR_NDP_TIMER_EN; - case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, - TU_TO_USEC(next_beacon - - ah->config. - dma_beacon_response_time)); - REG_WRITE(ah, AR_NEXT_SWBA, - TU_TO_USEC(next_beacon - - ah->config. - sw_beacon_response_time)); - flags |= - AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, - "%s: unsupported opmode: %d\n", - __func__, ah->opmode); - return; - break; - } - - REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); - - beacon_period &= ~ATH9K_BEACON_ENA; - if (beacon_period & ATH9K_BEACON_RESET_TSF) { - beacon_period &= ~ATH9K_BEACON_RESET_TSF; - ath9k_hw_reset_tsf(ah); - } - - REG_SET_BIT(ah, AR_TIMER_MODE, flags); -} - -void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, - const struct ath9k_beacon_state *bs) -{ - u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; - struct ath9k_hw_capabilities *pCap = &ah->caps; - - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); - - REG_WRITE(ah, AR_BEACON_PERIOD, - TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, - TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); - - REG_RMW_FIELD(ah, AR_RSSI_THR, - AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); - - beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; - - if (bs->bs_sleepduration > beaconintval) - beaconintval = bs->bs_sleepduration; - - dtimperiod = bs->bs_dtimperiod; - if (bs->bs_sleepduration > dtimperiod) - dtimperiod = bs->bs_sleepduration; - - if (beaconintval == dtimperiod) - nextTbtt = bs->bs_nextdtim; - else - nextTbtt = bs->bs_nexttbtt; - - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); - - REG_WRITE(ah, AR_NEXT_DTIM, - TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); - REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); - - REG_WRITE(ah, AR_SLEEP1, - SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) - | AR_SLEEP1_ASSUME_DTIM); - - if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP) - beacontimeout = (BEACON_TIMEOUT_VAL << 3); - else - beacontimeout = MIN_BEACON_TIMEOUT_VAL; - - REG_WRITE(ah, AR_SLEEP2, - SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); - - REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); - REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); - - REG_SET_BIT(ah, AR_TIMER_MODE, - AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | - AR_DTIM_TIMER_EN); - - /* TSF Out of Range Threshold */ - REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); -} - -/*******************/ -/* HW Capabilities */ -/*******************/ - -void ath9k_hw_fill_cap_info(struct ath_hw *ah) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - u16 capField = 0, eeval; - - eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); - ah->regulatory.current_rd = eeval; - - eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); - if (AR_SREV_9285_10_OR_LATER(ah)) - eeval |= AR9285_RDEXT_DEFAULT; - ah->regulatory.current_rd_ext = eeval; - - capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); - - if (ah->opmode != NL80211_IFTYPE_AP && - ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { - if (ah->regulatory.current_rd == 0x64 || - ah->regulatory.current_rd == 0x65) - ah->regulatory.current_rd += 5; - else if (ah->regulatory.current_rd == 0x41) - ah->regulatory.current_rd = 0x43; - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "regdomain mapped to 0x%x\n", ah->regulatory.current_rd); - } - - eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); - bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); - - if (eeval & AR5416_OPFLAGS_11A) { - set_bit(ATH9K_MODE_11A, pCap->wireless_modes); - if (ah->config.ht_enable) { - if (!(eeval & AR5416_OPFLAGS_N_5G_HT20)) - set_bit(ATH9K_MODE_11NA_HT20, - pCap->wireless_modes); - if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) { - set_bit(ATH9K_MODE_11NA_HT40PLUS, - pCap->wireless_modes); - set_bit(ATH9K_MODE_11NA_HT40MINUS, - pCap->wireless_modes); - } - } - } - - if (eeval & AR5416_OPFLAGS_11G) { - set_bit(ATH9K_MODE_11B, pCap->wireless_modes); - set_bit(ATH9K_MODE_11G, pCap->wireless_modes); - if (ah->config.ht_enable) { - if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) - set_bit(ATH9K_MODE_11NG_HT20, - pCap->wireless_modes); - if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) { - set_bit(ATH9K_MODE_11NG_HT40PLUS, - pCap->wireless_modes); - set_bit(ATH9K_MODE_11NG_HT40MINUS, - pCap->wireless_modes); - } - } - } - - pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); - if ((ah->hw_version.devid == AR5416_DEVID_PCI) && - !(eeval & AR5416_OPFLAGS_11A)) - pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; - else - pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); - - if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) - ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; - - pCap->low_2ghz_chan = 2312; - pCap->high_2ghz_chan = 2732; - - pCap->low_5ghz_chan = 4920; - pCap->high_5ghz_chan = 6100; - - pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; - pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; - pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; - - pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; - pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; - pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; - - if (ah->config.ht_enable) - pCap->hw_caps |= ATH9K_HW_CAP_HT; - else - pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - - pCap->hw_caps |= ATH9K_HW_CAP_GTT; - pCap->hw_caps |= ATH9K_HW_CAP_VEOL; - pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; - pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; - - if (capField & AR_EEPROM_EEPCAP_MAXQCU) - pCap->total_queues = - MS(capField, AR_EEPROM_EEPCAP_MAXQCU); - else - pCap->total_queues = ATH9K_NUM_TX_QUEUES; - - if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) - pCap->keycache_size = - 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); - else - pCap->keycache_size = AR_KEYTABLE_SIZE; - - pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; - - if (AR_SREV_9285_10_OR_LATER(ah)) - pCap->num_gpio_pins = AR9285_NUM_GPIO; - else if (AR_SREV_9280_10_OR_LATER(ah)) - pCap->num_gpio_pins = AR928X_NUM_GPIO; - else - pCap->num_gpio_pins = AR_NUM_GPIO; - - if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_CST; - pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; - } else { - pCap->rts_aggr_limit = (8 * 1024); - } - - pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); - if (ah->rfsilent & EEP_RFSILENT_ENABLED) { - ah->rfkill_gpio = - MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL); - ah->rfkill_polarity = - MS(ah->rfsilent, EEP_RFSILENT_POLARITY); - - pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; - } -#endif - - if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || - (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || - (ah->hw_version.macVersion == AR_SREV_VERSION_9160) || - (ah->hw_version.macVersion == AR_SREV_VERSION_9100) || - (ah->hw_version.macVersion == AR_SREV_VERSION_9280)) - pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; - else - pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; - - if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) - pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; - else - pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - - if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | - AR_EEPROM_EEREGCAP_EN_KK_U2 | - AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; - } else { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; - } - - pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; - - pCap->num_antcfg_5ghz = - ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); - pCap->num_antcfg_2ghz = - ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); - - if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) { - pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX; - ah->btactive_gpio = 6; - ah->wlanactive_gpio = 5; - } -} - -bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result) -{ - switch (type) { - case ATH9K_CAP_CIPHER: - switch (capability) { - case ATH9K_CIPHER_AES_CCM: - case ATH9K_CIPHER_AES_OCB: - case ATH9K_CIPHER_TKIP: - case ATH9K_CIPHER_WEP: - case ATH9K_CIPHER_MIC: - case ATH9K_CIPHER_CLR: - return true; - default: - return false; - } - case ATH9K_CAP_TKIP_MIC: - switch (capability) { - case 0: - return true; - case 1: - return (ah->sta_id1_defaults & - AR_STA_ID1_CRPT_MIC_ENABLE) ? true : - false; - } - case ATH9K_CAP_TKIP_SPLIT: - return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? - false : true; - case ATH9K_CAP_DIVERSITY: - return (REG_READ(ah, AR_PHY_CCK_DETECT) & - AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? - true : false; - case ATH9K_CAP_MCAST_KEYSRCH: - switch (capability) { - case 0: - return true; - case 1: - if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { - return false; - } else { - return (ah->sta_id1_defaults & - AR_STA_ID1_MCAST_KSRCH) ? true : - false; - } - } - return false; - case ATH9K_CAP_TXPOW: - switch (capability) { - case 0: - return 0; - case 1: - *result = ah->regulatory.power_limit; - return 0; - case 2: - *result = ah->regulatory.max_power_level; - return 0; - case 3: - *result = ah->regulatory.tp_scale; - return 0; - } - return false; - case ATH9K_CAP_DS: - return (AR_SREV_9280_20_OR_LATER(ah) && - (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) - ? false : true; - default: - return false; - } -} - -bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 setting, int *status) -{ - u32 v; - - switch (type) { - case ATH9K_CAP_TKIP_MIC: - if (setting) - ah->sta_id1_defaults |= - AR_STA_ID1_CRPT_MIC_ENABLE; - else - ah->sta_id1_defaults &= - ~AR_STA_ID1_CRPT_MIC_ENABLE; - return true; - case ATH9K_CAP_DIVERSITY: - v = REG_READ(ah, AR_PHY_CCK_DETECT); - if (setting) - v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - else - v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - REG_WRITE(ah, AR_PHY_CCK_DETECT, v); - return true; - case ATH9K_CAP_MCAST_KEYSRCH: - if (setting) - ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; - else - ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; - return true; - default: - return false; - } -} - -/****************************/ -/* GPIO / RFKILL / Antennae */ -/****************************/ - -static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, - u32 gpio, u32 type) -{ - int addr; - u32 gpio_shift, tmp; - - if (gpio > 11) - addr = AR_GPIO_OUTPUT_MUX3; - else if (gpio > 5) - addr = AR_GPIO_OUTPUT_MUX2; - else - addr = AR_GPIO_OUTPUT_MUX1; - - gpio_shift = (gpio % 6) * 5; - - if (AR_SREV_9280_20_OR_LATER(ah) - || (addr != AR_GPIO_OUTPUT_MUX1)) { - REG_RMW(ah, addr, (type << gpio_shift), - (0x1f << gpio_shift)); - } else { - tmp = REG_READ(ah, addr); - tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); - tmp &= ~(0x1f << gpio_shift); - tmp |= (type << gpio_shift); - REG_WRITE(ah, addr, tmp); - } -} - -void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) -{ - u32 gpio_shift; - - ASSERT(gpio < ah->caps.num_gpio_pins); - - gpio_shift = gpio << 1; - - REG_RMW(ah, - AR_GPIO_OE_OUT, - (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), - (AR_GPIO_OE_OUT_DRV << gpio_shift)); -} - -u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) -{ -#define MS_REG_READ(x, y) \ - (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y))) - - if (gpio >= ah->caps.num_gpio_pins) - return 0xffffffff; - - if (AR_SREV_9285_10_OR_LATER(ah)) - return MS_REG_READ(AR9285, gpio) != 0; - else if (AR_SREV_9280_10_OR_LATER(ah)) - return MS_REG_READ(AR928X, gpio) != 0; - else - return MS_REG_READ(AR, gpio) != 0; -} - -void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, - u32 ah_signal_type) -{ - u32 gpio_shift; - - ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); - - gpio_shift = 2 * gpio; - - REG_RMW(ah, - AR_GPIO_OE_OUT, - (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), - (AR_GPIO_OE_OUT_DRV << gpio_shift)); -} - -void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) -{ - REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), - AR_GPIO_BIT(gpio)); -} - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) -void ath9k_enable_rfkill(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); - - REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, - AR_GPIO_INPUT_MUX2_RFSILENT); - - ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); - REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); -} -#endif - -u32 ath9k_hw_getdefantenna(struct ath_hw *ah) -{ - return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; -} - -void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) -{ - REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); -} - -bool ath9k_hw_setantennaswitch(struct ath_hw *ah, - enum ath9k_ant_setting settings, - struct ath9k_channel *chan, - u8 *tx_chainmask, - u8 *rx_chainmask, - u8 *antenna_cfgd) -{ - static u8 tx_chainmask_cfg, rx_chainmask_cfg; - - if (AR_SREV_9280(ah)) { - if (!tx_chainmask_cfg) { - - tx_chainmask_cfg = *tx_chainmask; - rx_chainmask_cfg = *rx_chainmask; - } - - switch (settings) { - case ATH9K_ANT_FIXED_A: - *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK; - *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK; - *antenna_cfgd = true; - break; - case ATH9K_ANT_FIXED_B: - if (ah->caps.tx_chainmask > - ATH9K_ANTENNA1_CHAINMASK) { - *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK; - } - *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK; - *antenna_cfgd = true; - break; - case ATH9K_ANT_VARIABLE: - *tx_chainmask = tx_chainmask_cfg; - *rx_chainmask = rx_chainmask_cfg; - *antenna_cfgd = true; - break; - default: - break; - } - } else { - ah->diversity_control = settings; - } - - return true; -} - -/*********************/ -/* General Operation */ -/*********************/ - -u32 ath9k_hw_getrxfilter(struct ath_hw *ah) -{ - u32 bits = REG_READ(ah, AR_RX_FILTER); - u32 phybits = REG_READ(ah, AR_PHY_ERR); - - if (phybits & AR_PHY_ERR_RADAR) - bits |= ATH9K_RX_FILTER_PHYRADAR; - if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) - bits |= ATH9K_RX_FILTER_PHYERR; - - return bits; -} - -void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) -{ - u32 phybits; - - REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR); - phybits = 0; - if (bits & ATH9K_RX_FILTER_PHYRADAR) - phybits |= AR_PHY_ERR_RADAR; - if (bits & ATH9K_RX_FILTER_PHYERR) - phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; - REG_WRITE(ah, AR_PHY_ERR, phybits); - - if (phybits) - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); - else - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); -} - -bool ath9k_hw_phy_disable(struct ath_hw *ah) -{ - return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); -} - -bool ath9k_hw_disable(struct ath_hw *ah) -{ - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return false; - - return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); -} - -bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) -{ - struct ath9k_channel *chan = ah->curchan; - struct ieee80211_channel *channel = chan->chan; - - ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); - - if (ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(&ah->regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) ah->regulatory.power_limit)) != 0) - return false; - - return true; -} - -void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) -{ - memcpy(ah->macaddr, mac, ETH_ALEN); -} - -void ath9k_hw_setopmode(struct ath_hw *ah) -{ - ath9k_hw_set_operating_mode(ah, ah->opmode); -} - -void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) -{ - REG_WRITE(ah, AR_MCAST_FIL0, filter0); - REG_WRITE(ah, AR_MCAST_FIL1, filter1); -} - -void ath9k_hw_setbssidmask(struct ath_softc *sc) -{ - REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); - REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); -} - -void ath9k_hw_write_associd(struct ath_softc *sc) -{ - REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); - REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | - ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); -} - -u64 ath9k_hw_gettsf64(struct ath_hw *ah) -{ - u64 tsf; - - tsf = REG_READ(ah, AR_TSF_U32); - tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); - - return tsf; -} - -void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) -{ - REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); - REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); -} - -void ath9k_hw_reset_tsf(struct ath_hw *ah) -{ - int count; - - count = 0; - while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { - count++; - if (count > 10) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); - break; - } - udelay(10); - } - REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); -} - -bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) -{ - if (setting) - ah->misc_mode |= AR_PCU_TX_ADD_TSF; - else - ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; - - return true; -} - -bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) -{ - if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us); - ah->slottime = (u32) -1; - return false; - } else { - REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); - ah->slottime = us; - return true; - } -} - -void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode) -{ - u32 macmode; - - if (mode == ATH9K_HT_MACMODE_2040 && - !ah->config.cwm_ignore_extcca) - macmode = AR_2040_JOINED_RX_CLEAR; - else - macmode = 0; - - REG_WRITE(ah, AR_2040_MODE, macmode); -} - -/***************************/ -/* Bluetooth Coexistence */ -/***************************/ - -void ath9k_hw_btcoex_enable(struct ath_hw *ah) -{ - /* connect bt_active to baseband */ - REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, - (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | - AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); - - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); - - /* Set input mux for bt_active to gpio pin */ - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_ACTIVE, - ah->btactive_gpio); - - /* Configure the desired gpio port for input */ - ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio); - - /* Configure the desired GPIO port for TX_FRAME output */ - ath9k_hw_cfg_output(ah, ah->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); -} diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h deleted file mode 100644 index 984ac7da09d6..000000000000 --- a/drivers/net/wireless/ath9k/hw.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * 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 HW_H -#define HW_H - -#include -#include -#include - -#include "mac.h" -#include "ani.h" -#include "eeprom.h" -#include "calib.h" -#include "reg.h" -#include "phy.h" - -#include "../ath/regd.h" - -#define ATHEROS_VENDOR_ID 0x168c -#define AR5416_DEVID_PCI 0x0023 -#define AR5416_DEVID_PCIE 0x0024 -#define AR9160_DEVID_PCI 0x0027 -#define AR9280_DEVID_PCI 0x0029 -#define AR9280_DEVID_PCIE 0x002a -#define AR9285_DEVID_PCIE 0x002b -#define AR5416_AR9100_DEVID 0x000b -#define AR_SUBVENDOR_ID_NOG 0x0e11 -#define AR_SUBVENDOR_ID_NEW_A 0x7065 -#define AR5416_MAGIC 0x19641014 - -/* Register read/write primitives */ -#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) -#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) - -#define SM(_v, _f) (((_v) << _f##_S) & _f) -#define MS(_v, _f) (((_v) & _f) >> _f##_S) -#define REG_RMW(_a, _r, _set, _clr) \ - REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) -#define REG_RMW_FIELD(_a, _r, _f, _v) \ - REG_WRITE(_a, _r, \ - (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) -#define REG_SET_BIT(_a, _r, _f) \ - REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) -#define REG_CLR_BIT(_a, _r, _f) \ - REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) - -#define DO_DELAY(x) do { \ - if ((++(x) % 64) == 0) \ - udelay(1); \ - } while (0) - -#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ - int r; \ - for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ - INI_RA((iniarray), r, (column))); \ - DO_DELAY(regWr); \ - } \ - } while (0) - -#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 -#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 -#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 -#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 - -#define AR_GPIOD_MASK 0x00001FFF -#define AR_GPIO_BIT(_gpio) (1 << (_gpio)) - -#define BASE_ACTIVATE_DELAY 100 -#define RTC_PLL_SETTLE_DELAY 1000 -#define COEF_SCALE_S 24 -#define HT40_CHANNEL_CENTER_SHIFT 10 - -#define ATH9K_ANTENNA0_CHAINMASK 0x1 -#define ATH9K_ANTENNA1_CHAINMASK 0x2 - -#define ATH9K_NUM_DMA_DEBUG_REGS 8 -#define ATH9K_NUM_QUEUES 10 - -#define MAX_RATE_POWER 63 -#define AH_WAIT_TIMEOUT 100000 /* (us) */ -#define AH_TIME_QUANTUM 10 -#define AR_KEYTABLE_SIZE 128 -#define POWER_UP_TIME 200000 -#define SPUR_RSSI_THRESH 40 - -#define CAB_TIMEOUT_VAL 10 -#define BEACON_TIMEOUT_VAL 10 -#define MIN_BEACON_TIMEOUT_VAL 1 -#define SLEEP_SLOP 3 - -#define INIT_CONFIG_STATUS 0x00000000 -#define INIT_RSSI_THR 0x00000700 -#define INIT_BCON_CNTRL_REG 0x00000000 - -#define TU_TO_USEC(_tu) ((_tu) << 10) - -enum wireless_mode { - ATH9K_MODE_11A = 0, - ATH9K_MODE_11B = 2, - ATH9K_MODE_11G = 3, - ATH9K_MODE_11NA_HT20 = 6, - ATH9K_MODE_11NG_HT20 = 7, - ATH9K_MODE_11NA_HT40PLUS = 8, - ATH9K_MODE_11NA_HT40MINUS = 9, - ATH9K_MODE_11NG_HT40PLUS = 10, - ATH9K_MODE_11NG_HT40MINUS = 11, - ATH9K_MODE_MAX -}; - -enum ath9k_hw_caps { - ATH9K_HW_CAP_MIC_AESCCM = BIT(0), - ATH9K_HW_CAP_MIC_CKIP = BIT(1), - ATH9K_HW_CAP_MIC_TKIP = BIT(2), - ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), - ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), - ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), - ATH9K_HW_CAP_VEOL = BIT(6), - ATH9K_HW_CAP_BSSIDMASK = BIT(7), - ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), - ATH9K_HW_CAP_HT = BIT(9), - ATH9K_HW_CAP_GTT = BIT(10), - ATH9K_HW_CAP_FASTCC = BIT(11), - ATH9K_HW_CAP_RFSILENT = BIT(12), - ATH9K_HW_CAP_CST = BIT(13), - ATH9K_HW_CAP_ENHANCEDPM = BIT(14), - ATH9K_HW_CAP_AUTOSLEEP = BIT(15), - ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), - ATH9K_HW_CAP_BT_COEX = BIT(17) -}; - -enum ath9k_capability_type { - ATH9K_CAP_CIPHER = 0, - ATH9K_CAP_TKIP_MIC, - ATH9K_CAP_TKIP_SPLIT, - ATH9K_CAP_DIVERSITY, - ATH9K_CAP_TXPOW, - ATH9K_CAP_MCAST_KEYSRCH, - ATH9K_CAP_DS -}; - -struct ath9k_hw_capabilities { - u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ - DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */ - u16 total_queues; - u16 keycache_size; - u16 low_5ghz_chan, high_5ghz_chan; - u16 low_2ghz_chan, high_2ghz_chan; - u16 rts_aggr_limit; - u8 tx_chainmask; - u8 rx_chainmask; - u16 tx_triglevel_max; - u16 reg_cap; - u8 num_gpio_pins; - u8 num_antcfg_2ghz; - u8 num_antcfg_5ghz; -}; - -struct ath9k_ops_config { - int dma_beacon_response_time; - int sw_beacon_response_time; - int additional_swba_backoff; - int ack_6mb; - int cwm_ignore_extcca; - u8 pcie_powersave_enable; - u8 pcie_clock_req; - u32 pcie_waen; - u8 analog_shiftreg; - u8 ht_enable; - u32 ofdm_trig_low; - u32 ofdm_trig_high; - u32 cck_trig_high; - u32 cck_trig_low; - u32 enable_ani; - u16 diversity_control; - u16 antenna_switch_swap; - int serialize_regmode; - bool intr_mitigation; -#define SPUR_DISABLE 0 -#define SPUR_ENABLE_IOCTL 1 -#define SPUR_ENABLE_EEPROM 2 -#define AR_EEPROM_MODAL_SPURS 5 -#define AR_SPUR_5413_1 1640 -#define AR_SPUR_5413_2 1200 -#define AR_NO_SPUR 0x8000 -#define AR_BASE_FREQ_2GHZ 2300 -#define AR_BASE_FREQ_5GHZ 4900 -#define AR_SPUR_FEEQ_BOUND_HT40 19 -#define AR_SPUR_FEEQ_BOUND_HT20 10 - int spurmode; - u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; -}; - -enum ath9k_int { - ATH9K_INT_RX = 0x00000001, - ATH9K_INT_RXDESC = 0x00000002, - ATH9K_INT_RXNOFRM = 0x00000008, - ATH9K_INT_RXEOL = 0x00000010, - ATH9K_INT_RXORN = 0x00000020, - ATH9K_INT_TX = 0x00000040, - ATH9K_INT_TXDESC = 0x00000080, - ATH9K_INT_TIM_TIMER = 0x00000100, - ATH9K_INT_TXURN = 0x00000800, - ATH9K_INT_MIB = 0x00001000, - ATH9K_INT_RXPHY = 0x00004000, - ATH9K_INT_RXKCM = 0x00008000, - ATH9K_INT_SWBA = 0x00010000, - ATH9K_INT_BMISS = 0x00040000, - ATH9K_INT_BNR = 0x00100000, - ATH9K_INT_TIM = 0x00200000, - ATH9K_INT_DTIM = 0x00400000, - ATH9K_INT_DTIMSYNC = 0x00800000, - ATH9K_INT_GPIO = 0x01000000, - ATH9K_INT_CABEND = 0x02000000, - ATH9K_INT_TSFOOR = 0x04000000, - ATH9K_INT_CST = 0x10000000, - ATH9K_INT_GTT = 0x20000000, - ATH9K_INT_FATAL = 0x40000000, - ATH9K_INT_GLOBAL = 0x80000000, - ATH9K_INT_BMISC = ATH9K_INT_TIM | - ATH9K_INT_DTIM | - ATH9K_INT_DTIMSYNC | - ATH9K_INT_TSFOOR | - ATH9K_INT_CABEND, - ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM | - ATH9K_INT_RXDESC | - ATH9K_INT_RXEOL | - ATH9K_INT_RXORN | - ATH9K_INT_TXURN | - ATH9K_INT_TXDESC | - ATH9K_INT_MIB | - ATH9K_INT_RXPHY | - ATH9K_INT_RXKCM | - ATH9K_INT_SWBA | - ATH9K_INT_BMISS | - ATH9K_INT_GPIO, - ATH9K_INT_NOCARD = 0xffffffff -}; - -#define CHANNEL_CW_INT 0x00002 -#define CHANNEL_CCK 0x00020 -#define CHANNEL_OFDM 0x00040 -#define CHANNEL_2GHZ 0x00080 -#define CHANNEL_5GHZ 0x00100 -#define CHANNEL_PASSIVE 0x00200 -#define CHANNEL_DYN 0x00400 -#define CHANNEL_HALF 0x04000 -#define CHANNEL_QUARTER 0x08000 -#define CHANNEL_HT20 0x10000 -#define CHANNEL_HT40PLUS 0x20000 -#define CHANNEL_HT40MINUS 0x40000 - -#define CHANNEL_INTERFERENCE 0x01 -#define CHANNEL_DFS 0x02 -#define CHANNEL_4MS_LIMIT 0x04 -#define CHANNEL_DFS_CLEAR 0x08 -#define CHANNEL_DISALLOW_ADHOC 0x10 -#define CHANNEL_PER_11D_ADHOC 0x20 - -#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) -#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) -#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) -#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) -#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) -#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) -#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) -#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) -#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) -#define CHANNEL_ALL \ - (CHANNEL_OFDM| \ - CHANNEL_CCK| \ - CHANNEL_2GHZ | \ - CHANNEL_5GHZ | \ - CHANNEL_HT20 | \ - CHANNEL_HT40PLUS | \ - CHANNEL_HT40MINUS) - -struct ath9k_channel { - struct ieee80211_channel *chan; - u16 channel; - u32 channelFlags; - u32 chanmode; - int32_t CalValid; - bool oneTimeCalsDone; - int8_t iCoff; - int8_t qCoff; - int16_t rawNoiseFloor; -}; - -#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ - (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ - (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ - (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) -#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ - (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ - (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ - (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) -#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) -#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) -#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) -#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) -#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) -#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) -#define IS_CHAN_A_5MHZ_SPACED(_c) \ - ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ - (((_c)->channel % 20) != 0) && \ - (((_c)->channel % 10) != 0)) - -/* These macros check chanmode and not channelFlags */ -#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) -#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ - ((_c)->chanmode == CHANNEL_G_HT20)) -#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ - ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ - ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ - ((_c)->chanmode == CHANNEL_G_HT40MINUS)) -#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) - -enum ath9k_power_mode { - ATH9K_PM_AWAKE = 0, - ATH9K_PM_FULL_SLEEP, - ATH9K_PM_NETWORK_SLEEP, - ATH9K_PM_UNDEFINED -}; - -enum ath9k_ant_setting { - ATH9K_ANT_VARIABLE = 0, - ATH9K_ANT_FIXED_A, - ATH9K_ANT_FIXED_B -}; - -enum ath9k_tp_scale { - ATH9K_TP_SCALE_MAX = 0, - ATH9K_TP_SCALE_50, - ATH9K_TP_SCALE_25, - ATH9K_TP_SCALE_12, - ATH9K_TP_SCALE_MIN -}; - -enum ser_reg_mode { - SER_REG_MODE_OFF = 0, - SER_REG_MODE_ON = 1, - SER_REG_MODE_AUTO = 2, -}; - -struct ath9k_beacon_state { - u32 bs_nexttbtt; - u32 bs_nextdtim; - u32 bs_intval; -#define ATH9K_BEACON_PERIOD 0x0000ffff -#define ATH9K_BEACON_ENA 0x00800000 -#define ATH9K_BEACON_RESET_TSF 0x01000000 -#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ - u32 bs_dtimperiod; - u16 bs_cfpperiod; - u16 bs_cfpmaxduration; - u32 bs_cfpnext; - u16 bs_timoffset; - u16 bs_bmissthreshold; - u32 bs_sleepduration; - u32 bs_tsfoor_threshold; -}; - -struct chan_centers { - u16 synth_center; - u16 ctl_center; - u16 ext_center; -}; - -enum { - ATH9K_RESET_POWER_ON, - ATH9K_RESET_WARM, - ATH9K_RESET_COLD, -}; - -struct ath9k_hw_version { - u32 magic; - u16 devid; - u16 subvendorid; - u32 macVersion; - u16 macRev; - u16 phyRev; - u16 analog5GhzRev; - u16 analog2GhzRev; -}; - -struct ath_hw { - struct ath_softc *ah_sc; - struct ath9k_hw_version hw_version; - struct ath9k_ops_config config; - struct ath9k_hw_capabilities caps; - struct ath_regulatory regulatory; - struct ath9k_channel channels[38]; - struct ath9k_channel *curchan; - - union { - struct ar5416_eeprom_def def; - struct ar5416_eeprom_4k map4k; - } eeprom; - const struct eeprom_ops *eep_ops; - enum ath9k_eep_map eep_map; - - bool sw_mgmt_crypto; - bool is_pciexpress; - u8 macaddr[ETH_ALEN]; - u16 tx_trig_level; - u16 rfsilent; - u32 rfkill_gpio; - u32 rfkill_polarity; - u32 btactive_gpio; - u32 wlanactive_gpio; - u32 ah_flags; - - enum nl80211_iftype opmode; - enum ath9k_power_mode power_mode; - enum ath9k_power_mode restore_mode; - - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; - struct ar5416Stats stats; - struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; - - int16_t curchan_rad_index; - u32 mask_reg; - u32 txok_interrupt_mask; - u32 txerr_interrupt_mask; - u32 txdesc_interrupt_mask; - u32 txeol_interrupt_mask; - u32 txurn_interrupt_mask; - bool chip_fullsleep; - u32 atim_window; - u16 antenna_switch_swap; - enum ath9k_ant_setting diversity_control; - - /* Calibration */ - enum hal_cal_types supp_cals; - struct hal_cal_list iq_caldata; - struct hal_cal_list adcgain_caldata; - struct hal_cal_list adcdc_calinitdata; - struct hal_cal_list adcdc_caldata; - struct hal_cal_list *cal_list; - struct hal_cal_list *cal_list_last; - struct hal_cal_list *cal_list_curr; -#define totalPowerMeasI meas0.unsign -#define totalPowerMeasQ meas1.unsign -#define totalIqCorrMeas meas2.sign -#define totalAdcIOddPhase meas0.unsign -#define totalAdcIEvenPhase meas1.unsign -#define totalAdcQOddPhase meas2.unsign -#define totalAdcQEvenPhase meas3.unsign -#define totalAdcDcOffsetIOddPhase meas0.sign -#define totalAdcDcOffsetIEvenPhase meas1.sign -#define totalAdcDcOffsetQOddPhase meas2.sign -#define totalAdcDcOffsetQEvenPhase meas3.sign - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas0; - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas1; - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas2; - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas3; - u16 cal_samples; - - u32 sta_id1_defaults; - u32 misc_mode; - enum { - AUTO_32KHZ, - USE_32KHZ, - DONT_USE_32KHZ, - } enable_32kHz_clock; - - /* RF */ - u32 *analogBank0Data; - u32 *analogBank1Data; - u32 *analogBank2Data; - u32 *analogBank3Data; - u32 *analogBank6Data; - u32 *analogBank6TPCData; - u32 *analogBank7Data; - u32 *addac5416_21; - u32 *bank6Temp; - - int16_t txpower_indexoffset; - u32 beacon_interval; - u32 slottime; - u32 acktimeout; - u32 ctstimeout; - u32 globaltxtimeout; - u8 gbeacon_rate; - - /* ANI */ - u32 proc_phyerr; - bool has_hw_phycounters; - u32 aniperiod; - struct ar5416AniState *curani; - struct ar5416AniState ani[255]; - int totalSizeDesired[5]; - int coarse_high[5]; - int coarse_low[5]; - int firpwr[5]; - enum ath9k_ani_cmd ani_function; - - u32 intr_txqs; - enum ath9k_ht_extprotspacing extprotspacing; - u8 txchainmask; - u8 rxchainmask; - - u32 originalGain[22]; - int initPDADC; - int PDADCdelta; - - struct ar5416IniArray iniModes; - struct ar5416IniArray iniCommon; - struct ar5416IniArray iniBank0; - struct ar5416IniArray iniBB_RfGain; - struct ar5416IniArray iniBank1; - struct ar5416IniArray iniBank2; - struct ar5416IniArray iniBank3; - struct ar5416IniArray iniBank6; - struct ar5416IniArray iniBank6TPC; - struct ar5416IniArray iniBank7; - struct ar5416IniArray iniAddac; - struct ar5416IniArray iniPcieSerdes; - struct ar5416IniArray iniModesAdditional; - struct ar5416IniArray iniModesRxGain; - struct ar5416IniArray iniModesTxGain; -}; - -/* Attach, Detach, Reset */ -const char *ath9k_hw_probe(u16 vendorid, u16 devid); -void ath9k_hw_detach(struct ath_hw *ah); -struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error); -void ath9k_hw_rfdetach(struct ath_hw *ah); -int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, - bool bChannelChange); -void ath9k_hw_fill_cap_info(struct ath_hw *ah); -bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result); -bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 setting, int *status); - -/* Key Cache Management */ -bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); -bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac); -bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, - const struct ath9k_keyval *k, - const u8 *mac); -bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry); - -/* GPIO / RFKILL / Antennae */ -void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); -u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); -void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, - u32 ah_signal_type); -void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) -void ath9k_enable_rfkill(struct ath_hw *ah); -#endif -u32 ath9k_hw_getdefantenna(struct ath_hw *ah); -void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); -bool ath9k_hw_setantennaswitch(struct ath_hw *ah, - enum ath9k_ant_setting settings, - struct ath9k_channel *chan, - u8 *tx_chainmask, u8 *rx_chainmask, - u8 *antenna_cfgd); - -/* General Operation */ -bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); -u32 ath9k_hw_reverse_bits(u32 val, u32 n); -bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); -u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, - u32 frameLen, u16 rateix, bool shortPreamble); -void ath9k_hw_get_channel_centers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct chan_centers *centers); -u32 ath9k_hw_getrxfilter(struct ath_hw *ah); -void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); -bool ath9k_hw_phy_disable(struct ath_hw *ah); -bool ath9k_hw_disable(struct ath_hw *ah); -bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); -void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); -void ath9k_hw_setopmode(struct ath_hw *ah); -void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); -void ath9k_hw_setbssidmask(struct ath_softc *sc); -void ath9k_hw_write_associd(struct ath_softc *sc); -u64 ath9k_hw_gettsf64(struct ath_hw *ah); -void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); -void ath9k_hw_reset_tsf(struct ath_hw *ah); -bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); -bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); -void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); -void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); -void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, - const struct ath9k_beacon_state *bs); -bool ath9k_hw_setpower(struct ath_hw *ah, - enum ath9k_power_mode mode); -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); - -/* Interrupt Handling */ -bool ath9k_hw_intrpend(struct ath_hw *ah); -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); -enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); - -void ath9k_hw_btcoex_enable(struct ath_hw *ah); - -#endif diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h deleted file mode 100644 index e2f0a34b79a1..000000000000 --- a/drivers/net/wireless/ath9k/initvals.h +++ /dev/null @@ -1,4848 +0,0 @@ -/* - * 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. - */ - -static const u32 ar5416Modes[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, - { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, - { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, - { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, - { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00007010, 0x00000000 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00070000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a002e }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5d50e188 }, - { 0x00009958, 0x00081fff }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x001fff00 }, - { 0x000099ac, 0x00000000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x000000aa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x00000bb5 }, - { 0x0000a22c, 0x00000011 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x051701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa1f }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x08000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1[][2] = { - { 0x000098b0, 0x02108421 }, - { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2[][2] = { - { 0x000098b0, 0x0e73ff17 }, - { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014008f, 0x0014008f }, - { 0x0000989c, 0x00c40003, 0x00c40003 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000f1, 0x000000f1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x201400df, 0x201400df }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007081, 0x00007081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000003 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x0000000c }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000030 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000060 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000058 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9100[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, - { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, - { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, - { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, -#ifdef TB243 - { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, -#else - { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, -#endif - { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9100[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00020010, 0x00000003 }, - { 0x00020038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00004000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x001a0bb5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889ae }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000001 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa33 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9100[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9100[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9100[][2] = { - { 0x000098b0, 0x02108421}, - { 0x000098ec, 0x00000008}, -}; - -static const u32 ar5416Bank2_9100[][2] = { - { 0x000098b0, 0x0e73ff17}, - { 0x000098e0, 0x00000420}, -}; - -static const u32 ar5416Bank3_9100[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9100[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014000f, 0x0014000f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x000180d6, 0x000180d6 }, - { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, - { 0x0000989c, 0x000000b1, 0x000000b1 }, - { 0x0000989c, 0x00002000, 0x00002000 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - - -static const u32 ar5416Bank6TPC_9100[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x2014008f, 0x2014008f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007080, 0x00007080 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9100[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac_9100[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000010 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000015 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9160[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, - { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, - { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9160[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00007010, 0x00000020 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009940, 0x00750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x001a0bb5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000e000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000001 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79bfaa03 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9160[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9160[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9160[][2] = { - { 0x000098b0, 0x02108421 }, - { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2_9160[][2] = { - { 0x000098b0, 0x0e73ff17 }, - { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3_9160[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9160[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014008f, 0x0014008f }, - { 0x0000989c, 0x00c40003, 0x00c40003 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000f1, 0x000000f1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC_9160[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x2014008f, 0x2014008f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007080, 0x00007080 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9160[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static u32 ar5416Addac_9160[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000018 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000019 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000003 }, - {0x0000989c, 0x00000008 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static u32 ar5416Addac_91601_1[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000018 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000019 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -/* XXX 9280 1 */ -static const u32 ar9280Modes_9280[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, - { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, - { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, - { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, - { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, - { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, - { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, - { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, - { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, - { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, - { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, - { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, - { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, - { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, - { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, -}; - -static const u32 ar9280Common_9280[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00007010, 0x00000033 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xaf268e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0xe250a51e }, - { 0x00009958, 0x3388ffff }, - { 0x00009940, 0x00781204 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f00c4 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x23277200 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x001da000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a358, 0x7999aa0f }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f38081 }, - { 0x00007800, 0x00040000 }, - { 0x00007804, 0xdb005012 }, - { 0x00007808, 0x04924914 }, - { 0x0000780c, 0x21084210 }, - { 0x00007810, 0x6d801300 }, - { 0x00007814, 0x0019beff }, - { 0x00007818, 0x07e40000 }, - { 0x0000781c, 0x00492000 }, - { 0x00007820, 0x92492480 }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb005012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x6d801300 }, - { 0x00007838, 0x0019beff }, - { 0x0000783c, 0x07e40000 }, - { 0x00007840, 0x00492000 }, - { 0x00007844, 0x92492480 }, - { 0x00007848, 0x00120000 }, - { 0x00007850, 0x54214514 }, - { 0x00007858, 0x92592692 }, - { 0x00007860, 0x52802000 }, - { 0x00007864, 0x0a8e370e }, - { 0x00007868, 0xc0102850 }, - { 0x0000786c, 0x812d4000 }, - { 0x00007874, 0x001b6db0 }, - { 0x00007878, 0x00376b63 }, - { 0x0000787c, 0x06db6db6 }, - { 0x00007880, 0x006d8000 }, - { 0x00007884, 0xffeffffe }, - { 0x00007888, 0xffeffffe }, - { 0x00007890, 0x00060aeb }, - { 0x00007894, 0x5a108000 }, - { 0x00007898, 0x2a850160 }, -}; - -/* XXX 9280 2 */ -static const u32 ar9280Modes_9280_2[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, - { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, - { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, -}; - -static const u32 ar9280Common_9280_2[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00581043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafa68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c88000 }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00040000 }, - { 0x00007804, 0xdb005012 }, - { 0x00007808, 0x04924914 }, - { 0x0000780c, 0x21084210 }, - { 0x00007810, 0x6d801300 }, - { 0x00007818, 0x07e41000 }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb005012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x6d801300 }, - { 0x0000783c, 0x07e40000 }, - { 0x00007848, 0x00100000 }, - { 0x0000784c, 0x773f0567 }, - { 0x00007850, 0x54214514 }, - { 0x00007854, 0x12035828 }, - { 0x00007858, 0x9259269a }, - { 0x00007860, 0x52802000 }, - { 0x00007864, 0x0a8e370e }, - { 0x00007868, 0xc0102850 }, - { 0x0000786c, 0x812d4000 }, - { 0x00007870, 0x807ec400 }, - { 0x00007874, 0x001b6db0 }, - { 0x00007878, 0x00376b63 }, - { 0x0000787c, 0x06db6db6 }, - { 0x00007880, 0x006d8000 }, - { 0x00007884, 0xffeffffe }, - { 0x00007888, 0xffeffffe }, - { 0x0000788c, 0x00010000 }, - { 0x00007890, 0x02060aeb }, - { 0x00007898, 0x2a850160 }, -}; - -static const u32 ar9280Modes_fast_clock_9280_2[][3] = { - { 0x00001030, 0x00000268, 0x000004d0 }, - { 0x00001070, 0x0000018c, 0x00000318 }, - { 0x000010b0, 0x00000fd0, 0x00001fa0 }, - { 0x00008014, 0x044c044c, 0x08980898 }, - { 0x0000801c, 0x148ec02b, 0x148ec057 }, - { 0x00008318, 0x000044c0, 0x00008980 }, - { 0x00009820, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000f0f, 0x00000f0f }, - { 0x00009828, 0x0b020001, 0x0b020001 }, - { 0x00009834, 0x00000f0f, 0x00000f0f }, - { 0x00009844, 0x03721821, 0x03721821 }, - { 0x00009914, 0x00000898, 0x00001130 }, - { 0x00009918, 0x0000000b, 0x00000016 }, -}; - -static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, -}; - -static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, -}; - -static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, - { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, -}; - -static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, - { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, - { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, - { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, - { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, - { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, - { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, - { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, - { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, - { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, - { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, - { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, - { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, - { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, - { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, - { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, - { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, - { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, -}; - -static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, - { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, - { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, - { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, - { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, -}; - -static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9285 */ -static const u_int32_t ar9285Modes_9285[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 }, - { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 }, - { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 }, - { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9285Common_9285[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000031 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00581043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x1927b515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0a00 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e6788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000a278, 0x39ce739c }, - { 0x0000a27c, 0x050e039c }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x39ce739c }, - { 0x0000a398, 0x0000039c }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025820 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, - { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96c }, - { 0x00007834, 0x71400086 }, - { 0x00007838, 0xfac68800 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x0000786c, 0x48609eb4 }, - { 0x00007870, 0x10142c00 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */ -static const u_int32_t ar9285Modes_9285_1_2[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9285Common_9285_1_2[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000031 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04810 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x0000320a }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0xa8a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00581043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0400 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e68c8 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025820 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, - { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96e }, - { 0x00007834, 0x71400087 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x00007870, 0x10142c00 }, -}; - -static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, - { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, - { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, - { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, - { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, - { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, - { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, -}; - -static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, - { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, - { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, - { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, - { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, - { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c deleted file mode 100644 index 8ae4ec21667b..000000000000 --- a/drivers/net/wireless/ath9k/mac.c +++ /dev/null @@ -1,976 +0,0 @@ -/* - * 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 "ath9k.h" - -static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, - struct ath9k_tx_queue_info *qi) -{ - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", - ah->txok_interrupt_mask, ah->txerr_interrupt_mask, - ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, - ah->txurn_interrupt_mask); - - REG_WRITE(ah, AR_IMR_S0, - SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) - | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); - REG_WRITE(ah, AR_IMR_S1, - SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) - | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); - REG_RMW_FIELD(ah, AR_IMR_S2, - AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask); -} - -u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) -{ - return REG_READ(ah, AR_QTXDP(q)); -} - -bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) -{ - REG_WRITE(ah, AR_QTXDP(q), txdp); - - return true; -} - -bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) -{ - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); - - REG_WRITE(ah, AR_Q_TXE, 1 << q); - - return true; -} - -u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) -{ - u32 npend; - - npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; - if (npend == 0) { - - if (REG_READ(ah, AR_Q_TXE) & (1 << q)) - npend = 1; - } - - return npend; -} - -bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) -{ - u32 txcfg, curLevel, newLevel; - enum ath9k_int omask; - - if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) - return false; - - omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); - - txcfg = REG_READ(ah, AR_TXCFG); - curLevel = MS(txcfg, AR_FTRIG); - newLevel = curLevel; - if (bIncTrigLevel) { - if (curLevel < MAX_TX_FIFO_THRESHOLD) - newLevel++; - } else if (curLevel > MIN_TX_FIFO_THRESHOLD) - newLevel--; - if (newLevel != curLevel) - REG_WRITE(ah, AR_TXCFG, - (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); - - ath9k_hw_set_interrupts(ah, omask); - - ah->tx_trig_level = newLevel; - - return newLevel != curLevel; -} - -bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) -{ -#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ -#define ATH9K_TIME_QUANTUM 100 /* usec */ - - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - u32 tsfLow, j, wait; - u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " - "inactive queue: %u\n", q); - return false; - } - - REG_WRITE(ah, AR_Q_TXD, 1 << q); - - for (wait = wait_time; wait != 0; wait--) { - if (ath9k_hw_numtxpending(ah, q) == 0) - break; - udelay(ATH9K_TIME_QUANTUM); - } - - if (ath9k_hw_numtxpending(ah, q)) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "%s: Num of pending TX Frames %d on Q %d\n", - __func__, ath9k_hw_numtxpending(ah, q), q); - - for (j = 0; j < 2; j++) { - tsfLow = REG_READ(ah, AR_TSF_L32); - REG_WRITE(ah, AR_QUIET2, - SM(10, AR_QUIET2_QUIET_DUR)); - REG_WRITE(ah, AR_QUIET_PERIOD, 100); - REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); - REG_SET_BIT(ah, AR_TIMER_MODE, - AR_QUIET_TIMER_EN); - - if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) - break; - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "TSF has moved while trying to set " - "quiet time TSF: 0x%08x\n", tsfLow); - } - - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); - - udelay(200); - REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); - - wait = wait_time; - while (ath9k_hw_numtxpending(ah, q)) { - if ((--wait) == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "Failed to stop TX DMA in 100 " - "msec after killing last frame\n"); - break; - } - udelay(ATH9K_TIME_QUANTUM); - } - - REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); - } - - REG_WRITE(ah, AR_Q_TXD, 0); - return wait != 0; - -#undef ATH9K_TX_STOP_DMA_TIMEOUT -#undef ATH9K_TIME_QUANTUM -} - -bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (firstSeg) { - ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); - } else if (lastSeg) { - ads->ds_ctl0 = 0; - ads->ds_ctl1 = segLen; - ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; - ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; - } else { - ads->ds_ctl0 = 0; - ads->ds_ctl1 = segLen | AR_TxMore; - ads->ds_ctl2 = 0; - ads->ds_ctl3 = 0; - } - ads->ds_txstatus0 = ads->ds_txstatus1 = 0; - ads->ds_txstatus2 = ads->ds_txstatus3 = 0; - ads->ds_txstatus4 = ads->ds_txstatus5 = 0; - ads->ds_txstatus6 = ads->ds_txstatus7 = 0; - ads->ds_txstatus8 = ads->ds_txstatus9 = 0; - - return true; -} - -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_txstatus0 = ads->ds_txstatus1 = 0; - ads->ds_txstatus2 = ads->ds_txstatus3 = 0; - ads->ds_txstatus4 = ads->ds_txstatus5 = 0; - ads->ds_txstatus6 = ads->ds_txstatus7 = 0; - ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} - -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if ((ads->ds_txstatus9 & AR_TxDone) == 0) - return -EINPROGRESS; - - ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); - ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; - ds->ds_txstat.ts_status = 0; - ds->ds_txstat.ts_flags = 0; - - if (ads->ds_txstatus1 & AR_ExcessiveRetries) - ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; - if (ads->ds_txstatus1 & AR_Filtered) - ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; - if (ads->ds_txstatus1 & AR_FIFOUnderrun) { - ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus9 & AR_TxOpExceeded) - ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; - if (ads->ds_txstatus1 & AR_TxTimerExpired) - ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->ds_txstatus1 & AR_DescCfgErr) - ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->ds_txstatus1 & AR_TxDataUnderrun) { - ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { - ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus0 & AR_TxBaStatus) { - ds->ds_txstat.ts_flags |= ATH9K_TX_BA; - ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; - ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; - } - - ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); - switch (ds->ds_txstat.ts_rateindex) { - case 0: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); - break; - case 1: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); - break; - case 2: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); - break; - case 3: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); - break; - } - - ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); - ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); - ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); - ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); - ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); - ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); - ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); - ds->ds_txstat.evm0 = ads->AR_TxEVM0; - ds->ds_txstat.evm1 = ads->AR_TxEVM1; - ds->ds_txstat.evm2 = ads->AR_TxEVM2; - ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); - ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); - ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); - ds->ds_txstat.ts_antenna = 0; - - return 0; -} - -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - txPower += ah->txpower_indexoffset; - if (txPower > 63) - txPower = 63; - - ads->ds_ctl0 = (pktLen & AR_FrameLen) - | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) - | SM(txPower, AR_XmitPower) - | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) - | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) - | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); - - ads->ds_ctl1 = - (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) - | SM(type, AR_FrameType) - | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) - | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) - | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); - - ads->ds_ctl6 = SM(keyType, AR_EncrType); - - if (AR_SREV_9285(ah)) { - ads->ds_ctl8 = 0; - ads->ds_ctl9 = 0; - ads->ds_ctl10 = 0; - ads->ds_ctl11 = 0; - } -} - -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, - struct ath_desc *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - struct ar5416_desc *last_ads = AR5416DESC(lastds); - u32 ds_ctl0; - - if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { - ds_ctl0 = ads->ds_ctl0; - - if (flags & ATH9K_TXDESC_RTSENA) { - ds_ctl0 &= ~AR_CTSEnable; - ds_ctl0 |= AR_RTSEnable; - } else { - ds_ctl0 &= ~AR_RTSEnable; - ds_ctl0 |= AR_CTSEnable; - } - - ads->ds_ctl0 = ds_ctl0; - } else { - ads->ds_ctl0 = - (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); - } - - ads->ds_ctl2 = set11nTries(series, 0) - | set11nTries(series, 1) - | set11nTries(series, 2) - | set11nTries(series, 3) - | (durUpdateEn ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); - - ads->ds_ctl3 = set11nRate(series, 0) - | set11nRate(series, 1) - | set11nRate(series, 2) - | set11nRate(series, 3); - - ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) - | set11nPktDurRTSCTS(series, 1); - - ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) - | set11nPktDurRTSCTS(series, 3); - - ads->ds_ctl7 = set11nRateFlags(series, 0) - | set11nRateFlags(series, 1) - | set11nRateFlags(series, 2) - | set11nRateFlags(series, 3) - | SM(rtsctsRate, AR_RTSCTSRate); - last_ads->ds_ctl2 = ads->ds_ctl2; - last_ads->ds_ctl3 = ads->ds_ctl3; -} - -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, - u32 aggrLen) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - ads->ds_ctl6 &= ~AR_AggrLen; - ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); -} - -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, - u32 numDelims) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - unsigned int ctl6; - - ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - - ctl6 = ads->ds_ctl6; - ctl6 &= ~AR_PadDelim; - ctl6 |= SM(numDelims, AR_PadDelim); - ads->ds_ctl6 = ctl6; -} - -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 |= AR_IsAggr; - ads->ds_ctl1 &= ~AR_MoreAggr; - ads->ds_ctl6 &= ~AR_PadDelim; -} - -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); -} - -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, - u32 burstDuration) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl2 &= ~AR_BurstDur; - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); -} - -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, - u32 vmf) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (vmf) - ads->ds_ctl0 |= AR_VirtMoreFrag; - else - ads->ds_ctl0 &= ~AR_VirtMoreFrag; -} - -void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) -{ - *txqs &= ah->intr_txqs; - ah->intr_txqs &= ~(*txqs); -} - -bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, - const struct ath9k_tx_queue_info *qinfo) -{ - u32 cw; - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " - "inactive queue: %u\n", q); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); - - qi->tqi_ver = qinfo->tqi_ver; - qi->tqi_subtype = qinfo->tqi_subtype; - qi->tqi_qflags = qinfo->tqi_qflags; - qi->tqi_priority = qinfo->tqi_priority; - if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT) - qi->tqi_aifs = min(qinfo->tqi_aifs, 255U); - else - qi->tqi_aifs = INIT_AIFS; - if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) { - cw = min(qinfo->tqi_cwmin, 1024U); - qi->tqi_cwmin = 1; - while (qi->tqi_cwmin < cw) - qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; - } else - qi->tqi_cwmin = qinfo->tqi_cwmin; - if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) { - cw = min(qinfo->tqi_cwmax, 1024U); - qi->tqi_cwmax = 1; - while (qi->tqi_cwmax < cw) - qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; - } else - qi->tqi_cwmax = INIT_CWMAX; - - if (qinfo->tqi_shretry != 0) - qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U); - else - qi->tqi_shretry = INIT_SH_RETRY; - if (qinfo->tqi_lgretry != 0) - qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U); - else - qi->tqi_lgretry = INIT_LG_RETRY; - qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod; - qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit; - qi->tqi_burstTime = qinfo->tqi_burstTime; - qi->tqi_readyTime = qinfo->tqi_readyTime; - - switch (qinfo->tqi_subtype) { - case ATH9K_WME_UPSD: - if (qi->tqi_type == ATH9K_TX_QUEUE_DATA) - qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS; - break; - default: - break; - } - - return true; -} - -bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, - struct ath9k_tx_queue_info *qinfo) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " - "inactive queue: %u\n", q); - return false; - } - - qinfo->tqi_qflags = qi->tqi_qflags; - qinfo->tqi_ver = qi->tqi_ver; - qinfo->tqi_subtype = qi->tqi_subtype; - qinfo->tqi_qflags = qi->tqi_qflags; - qinfo->tqi_priority = qi->tqi_priority; - qinfo->tqi_aifs = qi->tqi_aifs; - qinfo->tqi_cwmin = qi->tqi_cwmin; - qinfo->tqi_cwmax = qi->tqi_cwmax; - qinfo->tqi_shretry = qi->tqi_shretry; - qinfo->tqi_lgretry = qi->tqi_lgretry; - qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; - qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; - qinfo->tqi_burstTime = qi->tqi_burstTime; - qinfo->tqi_readyTime = qi->tqi_readyTime; - - return true; -} - -int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, - const struct ath9k_tx_queue_info *qinfo) -{ - struct ath9k_tx_queue_info *qi; - struct ath9k_hw_capabilities *pCap = &ah->caps; - int q; - - switch (type) { - case ATH9K_TX_QUEUE_BEACON: - q = pCap->total_queues - 1; - break; - case ATH9K_TX_QUEUE_CAB: - q = pCap->total_queues - 2; - break; - case ATH9K_TX_QUEUE_PSPOLL: - q = 1; - break; - case ATH9K_TX_QUEUE_UAPSD: - q = pCap->total_queues - 3; - break; - case ATH9K_TX_QUEUE_DATA: - for (q = 0; q < pCap->total_queues; q++) - if (ah->txq[q].tqi_type == - ATH9K_TX_QUEUE_INACTIVE) - break; - if (q == pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "No available TX queue\n"); - return -1; - } - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", - type); - return -1; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); - - qi = &ah->txq[q]; - if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "TX queue: %u already active\n", q); - return -1; - } - memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); - qi->tqi_type = type; - if (qinfo == NULL) { - qi->tqi_qflags = - TXQ_FLAG_TXOKINT_ENABLE - | TXQ_FLAG_TXERRINT_ENABLE - | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; - qi->tqi_aifs = INIT_AIFS; - qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi->tqi_cwmax = INIT_CWMAX; - qi->tqi_shretry = INIT_SH_RETRY; - qi->tqi_lgretry = INIT_LG_RETRY; - qi->tqi_physCompBuf = 0; - } else { - qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; - (void) ath9k_hw_set_txq_props(ah, q, qinfo); - } - - return q; -} - -bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " - "invalid queue: %u\n", q); - return false; - } - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " - "inactive queue: %u\n", q); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); - - qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; - ah->txok_interrupt_mask &= ~(1 << q); - ah->txerr_interrupt_mask &= ~(1 << q); - ah->txdesc_interrupt_mask &= ~(1 << q); - ah->txeol_interrupt_mask &= ~(1 << q); - ah->txurn_interrupt_mask &= ~(1 << q); - ath9k_hw_set_txq_interrupts(ah, qi); - - return true; -} - -bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_channel *chan = ah->curchan; - struct ath9k_tx_queue_info *qi; - u32 cwMin, chanCwMin, value; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " - "inactive queue: %u\n", q); - return true; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); - - if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { - if (chan && IS_CHAN_B(chan)) - chanCwMin = INIT_CWMIN_11B; - else - chanCwMin = INIT_CWMIN; - - for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); - } else - cwMin = qi->tqi_cwmin; - - REG_WRITE(ah, AR_DLCL_IFS(q), - SM(cwMin, AR_D_LCL_IFS_CWMIN) | - SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | - SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); - - REG_WRITE(ah, AR_DRETRY_LIMIT(q), - SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | - SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | - SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); - - REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); - REG_WRITE(ah, AR_DMISC(q), - AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); - - if (qi->tqi_cbrPeriod) { - REG_WRITE(ah, AR_QCBRCFG(q), - SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | - SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | - (qi->tqi_cbrOverflowLimit ? - AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); - } - if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { - REG_WRITE(ah, AR_QRDYTIMECFG(q), - SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | - AR_Q_RDYTIMECFG_EN); - } - - REG_WRITE(ah, AR_DCHNTIME(q), - SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | - (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); - - if (qi->tqi_burstTime - && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | - AR_Q_MISC_RDYTIME_EXP_POLICY); - - } - - if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_POST_FR_BKOFF_DIS); - } - if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_FRAG_BKOFF_EN); - } - switch (qi->tqi_type) { - case ATH9K_TX_QUEUE_BEACON: - REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) - | AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_BEACON_USE - | AR_Q_MISC_CBR_INCR_DIS1); - - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) - | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << - AR_D_MISC_ARB_LOCKOUT_CNTRL_S) - | AR_D_MISC_BEACON_USE - | AR_D_MISC_POST_FR_BKOFF_DIS); - break; - case ATH9K_TX_QUEUE_CAB: - REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) - | AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_CBR_INCR_DIS1 - | AR_Q_MISC_CBR_INCR_DIS0); - value = (qi->tqi_readyTime - - (ah->config.sw_beacon_response_time - - ah->config.dma_beacon_response_time) - - ah->config.additional_swba_backoff) * 1024; - REG_WRITE(ah, AR_QRDYTIMECFG(q), - value | AR_Q_RDYTIMECFG_EN); - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) - | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << - AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); - break; - case ATH9K_TX_QUEUE_PSPOLL: - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); - break; - case ATH9K_TX_QUEUE_UAPSD: - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_POST_FR_BKOFF_DIS); - break; - default: - break; - } - - if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, - AR_D_MISC_ARB_LOCKOUT_CNTRL) | - AR_D_MISC_POST_FR_BKOFF_DIS); - } - - if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) - ah->txok_interrupt_mask |= 1 << q; - else - ah->txok_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE) - ah->txerr_interrupt_mask |= 1 << q; - else - ah->txerr_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) - ah->txdesc_interrupt_mask |= 1 << q; - else - ah->txdesc_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) - ah->txeol_interrupt_mask |= 1 << q; - else - ah->txeol_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) - ah->txurn_interrupt_mask |= 1 << q; - else - ah->txurn_interrupt_mask &= ~(1 << q); - ath9k_hw_set_txq_interrupts(ah, qi); - - return true; -} - -int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pa, struct ath_desc *nds, u64 tsf) -{ - struct ar5416_desc ads; - struct ar5416_desc *adsp = AR5416DESC(ds); - u32 phyerr; - - if ((adsp->ds_rxstatus8 & AR_RxDone) == 0) - return -EINPROGRESS; - - ads.u.rx = adsp->u.rx; - - ds->ds_rxstat.rs_status = 0; - ds->ds_rxstat.rs_flags = 0; - - ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; - ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; - - ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); - ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); - ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); - ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); - ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); - ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); - ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); - if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) - ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); - else - ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; - - ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); - ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; - - ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; - ds->ds_rxstat.rs_moreaggr = - (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; - ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); - ds->ds_rxstat.rs_flags = - (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; - ds->ds_rxstat.rs_flags |= - (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; - - if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; - if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; - if (ads.ds_rxstatus8 & AR_DecryptBusyErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; - - if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { - if (ads.ds_rxstatus8 & AR_CRCErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; - else if (ads.ds_rxstatus8 & AR_PHYErr) { - ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; - phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); - ds->ds_rxstat.rs_phyerr = phyerr; - } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; - else if (ads.ds_rxstatus8 & AR_MichaelErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; - } - - return 0; -} - -bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 size, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - struct ath9k_hw_capabilities *pCap = &ah->caps; - - ads->ds_ctl1 = size & AR_BufLen; - if (flags & ATH9K_RXDESC_INTREQ) - ads->ds_ctl1 |= AR_RxIntrReq; - - ads->ds_rxstatus8 &= ~AR_RxDone; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - memset(&(ads->u), 0, sizeof(ads->u)); - - return true; -} - -bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) -{ - u32 reg; - - if (set) { - REG_SET_BIT(ah, AR_DIAG_SW, - (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - - if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, - 0, AH_WAIT_TIMEOUT)) { - REG_CLR_BIT(ah, AR_DIAG_SW, - (AR_DIAG_RX_DIS | - AR_DIAG_RX_ABORT)); - - reg = REG_READ(ah, AR_OBS_BUS_1); - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); - - return false; - } - } else { - REG_CLR_BIT(ah, AR_DIAG_SW, - (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - } - - return true; -} - -void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) -{ - REG_WRITE(ah, AR_RXDP, rxdp); -} - -void ath9k_hw_rxena(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_CR, AR_CR_RXE); -} - -void ath9k_hw_startpcureceive(struct ath_hw *ah) -{ - ath9k_enable_mib_counters(ah); - - ath9k_ani_reset(ah); - - REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); -} - -void ath9k_hw_stoppcurecv(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); - - ath9k_hw_disable_mib_counters(ah); -} - -bool ath9k_hw_stopdmarecv(struct ath_hw *ah) -{ -#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ -#define AH_RX_TIME_QUANTUM 100 /* usec */ - - int i; - - REG_WRITE(ah, AR_CR, AR_CR_RXD); - - /* Wait for rx enable bit to go low */ - for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { - if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) - break; - udelay(AH_TIME_QUANTUM); - } - - if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "DMA failed to stop in %d ms " - "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", - AH_RX_STOP_DMA_TIMEOUT / 1000, - REG_READ(ah, AR_CR), - REG_READ(ah, AR_DIAG_SW)); - return false; - } else { - return true; - } - -#undef AH_RX_TIME_QUANTUM -#undef AH_RX_STOP_DMA_TIMEOUT -} diff --git a/drivers/net/wireless/ath9k/mac.h b/drivers/net/wireless/ath9k/mac.h deleted file mode 100644 index 1176bce8b76c..000000000000 --- a/drivers/net/wireless/ath9k/mac.h +++ /dev/null @@ -1,680 +0,0 @@ -/* - * 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 MAC_H -#define MAC_H - -#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ - MS(ads->ds_rxstatus0, AR_RxRate) : \ - (ads->ds_rxstatus3 >> 2) & 0xFF) - -#define set11nTries(_series, _index) \ - (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) - -#define set11nRate(_series, _index) \ - (SM((_series)[_index].Rate, AR_XmitRate##_index)) - -#define set11nPktDurRTSCTS(_series, _index) \ - (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \ - ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \ - AR_RTSCTSQual##_index : 0)) - -#define set11nRateFlags(_series, _index) \ - (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ - AR_2040_##_index : 0) \ - |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ - AR_GI##_index : 0) \ - |SM((_series)[_index].ChSel, AR_ChainSel##_index)) - -#define CCK_SIFS_TIME 10 -#define CCK_PREAMBLE_BITS 144 -#define CCK_PLCP_BITS 48 - -#define OFDM_SIFS_TIME 16 -#define OFDM_PREAMBLE_TIME 20 -#define OFDM_PLCP_BITS 22 -#define OFDM_SYMBOL_TIME 4 - -#define OFDM_SIFS_TIME_HALF 32 -#define OFDM_PREAMBLE_TIME_HALF 40 -#define OFDM_PLCP_BITS_HALF 22 -#define OFDM_SYMBOL_TIME_HALF 8 - -#define OFDM_SIFS_TIME_QUARTER 64 -#define OFDM_PREAMBLE_TIME_QUARTER 80 -#define OFDM_PLCP_BITS_QUARTER 22 -#define OFDM_SYMBOL_TIME_QUARTER 16 - -#define INIT_AIFS 2 -#define INIT_CWMIN 15 -#define INIT_CWMIN_11B 31 -#define INIT_CWMAX 1023 -#define INIT_SH_RETRY 10 -#define INIT_LG_RETRY 10 -#define INIT_SSH_RETRY 32 -#define INIT_SLG_RETRY 32 - -#define ATH9K_SLOT_TIME_6 6 -#define ATH9K_SLOT_TIME_9 9 -#define ATH9K_SLOT_TIME_20 20 - -#define ATH9K_TXERR_XRETRY 0x01 -#define ATH9K_TXERR_FILT 0x02 -#define ATH9K_TXERR_FIFO 0x04 -#define ATH9K_TXERR_XTXOP 0x08 -#define ATH9K_TXERR_TIMER_EXPIRED 0x10 - -#define ATH9K_TX_BA 0x01 -#define ATH9K_TX_PWRMGMT 0x02 -#define ATH9K_TX_DESC_CFG_ERR 0x04 -#define ATH9K_TX_DATA_UNDERRUN 0x08 -#define ATH9K_TX_DELIM_UNDERRUN 0x10 -#define ATH9K_TX_SW_ABORTED 0x40 -#define ATH9K_TX_SW_FILTERED 0x80 - -#define MIN_TX_FIFO_THRESHOLD 0x1 -#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) -#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD - -struct ath_tx_status { - u32 ts_tstamp; - u16 ts_seqnum; - u8 ts_status; - u8 ts_ratecode; - u8 ts_rateindex; - int8_t ts_rssi; - u8 ts_shortretry; - u8 ts_longretry; - u8 ts_virtcol; - u8 ts_antenna; - u8 ts_flags; - int8_t ts_rssi_ctl0; - int8_t ts_rssi_ctl1; - int8_t ts_rssi_ctl2; - int8_t ts_rssi_ext0; - int8_t ts_rssi_ext1; - int8_t ts_rssi_ext2; - u8 pad[3]; - u32 ba_low; - u32 ba_high; - u32 evm0; - u32 evm1; - u32 evm2; -}; - -struct ath_rx_status { - u32 rs_tstamp; - u16 rs_datalen; - u8 rs_status; - u8 rs_phyerr; - int8_t rs_rssi; - u8 rs_keyix; - u8 rs_rate; - u8 rs_antenna; - u8 rs_more; - int8_t rs_rssi_ctl0; - int8_t rs_rssi_ctl1; - int8_t rs_rssi_ctl2; - int8_t rs_rssi_ext0; - int8_t rs_rssi_ext1; - int8_t rs_rssi_ext2; - u8 rs_isaggr; - u8 rs_moreaggr; - u8 rs_num_delims; - u8 rs_flags; - u32 evm0; - u32 evm1; - u32 evm2; -}; - -#define ATH9K_RXERR_CRC 0x01 -#define ATH9K_RXERR_PHY 0x02 -#define ATH9K_RXERR_FIFO 0x04 -#define ATH9K_RXERR_DECRYPT 0x08 -#define ATH9K_RXERR_MIC 0x10 - -#define ATH9K_RX_MORE 0x01 -#define ATH9K_RX_MORE_AGGR 0x02 -#define ATH9K_RX_GI 0x04 -#define ATH9K_RX_2040 0x08 -#define ATH9K_RX_DELIM_CRC_PRE 0x10 -#define ATH9K_RX_DELIM_CRC_POST 0x20 -#define ATH9K_RX_DECRYPT_BUSY 0x40 - -#define ATH9K_RXKEYIX_INVALID ((u8)-1) -#define ATH9K_TXKEYIX_INVALID ((u32)-1) - -struct ath_desc { - u32 ds_link; - u32 ds_data; - u32 ds_ctl0; - u32 ds_ctl1; - u32 ds_hw[20]; - union { - struct ath_tx_status tx; - struct ath_rx_status rx; - void *stats; - } ds_us; - void *ds_vdata; -} __packed; - -#define ds_txstat ds_us.tx -#define ds_rxstat ds_us.rx -#define ds_stat ds_us.stats - -#define ATH9K_TXDESC_CLRDMASK 0x0001 -#define ATH9K_TXDESC_NOACK 0x0002 -#define ATH9K_TXDESC_RTSENA 0x0004 -#define ATH9K_TXDESC_CTSENA 0x0008 -/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for - * the descriptor its marked on. We take a tx interrupt to reap - * descriptors when the h/w hits an EOL condition or - * when the descriptor is specifically marked to generate - * an interrupt with this flag. Descriptors should be - * marked periodically to insure timely replenishing of the - * supply needed for sending frames. Defering interrupts - * reduces system load and potentially allows more concurrent - * work to be done but if done to aggressively can cause - * senders to backup. When the hardware queue is left too - * large rate control information may also be too out of - * date. An Alternative for this is TX interrupt mitigation - * but this needs more testing. */ -#define ATH9K_TXDESC_INTREQ 0x0010 -#define ATH9K_TXDESC_VEOL 0x0020 -#define ATH9K_TXDESC_EXT_ONLY 0x0040 -#define ATH9K_TXDESC_EXT_AND_CTL 0x0080 -#define ATH9K_TXDESC_VMF 0x0100 -#define ATH9K_TXDESC_FRAG_IS_ON 0x0200 -#define ATH9K_TXDESC_CAB 0x0400 - -#define ATH9K_RXDESC_INTREQ 0x0020 - -struct ar5416_desc { - u32 ds_link; - u32 ds_data; - u32 ds_ctl0; - u32 ds_ctl1; - union { - struct { - u32 ctl2; - u32 ctl3; - u32 ctl4; - u32 ctl5; - u32 ctl6; - u32 ctl7; - u32 ctl8; - u32 ctl9; - u32 ctl10; - u32 ctl11; - u32 status0; - u32 status1; - u32 status2; - u32 status3; - u32 status4; - u32 status5; - u32 status6; - u32 status7; - u32 status8; - u32 status9; - } tx; - struct { - u32 status0; - u32 status1; - u32 status2; - u32 status3; - u32 status4; - u32 status5; - u32 status6; - u32 status7; - u32 status8; - } rx; - } u; -} __packed; - -#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) -#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) - -#define ds_ctl2 u.tx.ctl2 -#define ds_ctl3 u.tx.ctl3 -#define ds_ctl4 u.tx.ctl4 -#define ds_ctl5 u.tx.ctl5 -#define ds_ctl6 u.tx.ctl6 -#define ds_ctl7 u.tx.ctl7 -#define ds_ctl8 u.tx.ctl8 -#define ds_ctl9 u.tx.ctl9 -#define ds_ctl10 u.tx.ctl10 -#define ds_ctl11 u.tx.ctl11 - -#define ds_txstatus0 u.tx.status0 -#define ds_txstatus1 u.tx.status1 -#define ds_txstatus2 u.tx.status2 -#define ds_txstatus3 u.tx.status3 -#define ds_txstatus4 u.tx.status4 -#define ds_txstatus5 u.tx.status5 -#define ds_txstatus6 u.tx.status6 -#define ds_txstatus7 u.tx.status7 -#define ds_txstatus8 u.tx.status8 -#define ds_txstatus9 u.tx.status9 - -#define ds_rxstatus0 u.rx.status0 -#define ds_rxstatus1 u.rx.status1 -#define ds_rxstatus2 u.rx.status2 -#define ds_rxstatus3 u.rx.status3 -#define ds_rxstatus4 u.rx.status4 -#define ds_rxstatus5 u.rx.status5 -#define ds_rxstatus6 u.rx.status6 -#define ds_rxstatus7 u.rx.status7 -#define ds_rxstatus8 u.rx.status8 - -#define AR_FrameLen 0x00000fff -#define AR_VirtMoreFrag 0x00001000 -#define AR_TxCtlRsvd00 0x0000e000 -#define AR_XmitPower 0x003f0000 -#define AR_XmitPower_S 16 -#define AR_RTSEnable 0x00400000 -#define AR_VEOL 0x00800000 -#define AR_ClrDestMask 0x01000000 -#define AR_TxCtlRsvd01 0x1e000000 -#define AR_TxIntrReq 0x20000000 -#define AR_DestIdxValid 0x40000000 -#define AR_CTSEnable 0x80000000 - -#define AR_BufLen 0x00000fff -#define AR_TxMore 0x00001000 -#define AR_DestIdx 0x000fe000 -#define AR_DestIdx_S 13 -#define AR_FrameType 0x00f00000 -#define AR_FrameType_S 20 -#define AR_NoAck 0x01000000 -#define AR_InsertTS 0x02000000 -#define AR_CorruptFCS 0x04000000 -#define AR_ExtOnly 0x08000000 -#define AR_ExtAndCtl 0x10000000 -#define AR_MoreAggr 0x20000000 -#define AR_IsAggr 0x40000000 - -#define AR_BurstDur 0x00007fff -#define AR_BurstDur_S 0 -#define AR_DurUpdateEna 0x00008000 -#define AR_XmitDataTries0 0x000f0000 -#define AR_XmitDataTries0_S 16 -#define AR_XmitDataTries1 0x00f00000 -#define AR_XmitDataTries1_S 20 -#define AR_XmitDataTries2 0x0f000000 -#define AR_XmitDataTries2_S 24 -#define AR_XmitDataTries3 0xf0000000 -#define AR_XmitDataTries3_S 28 - -#define AR_XmitRate0 0x000000ff -#define AR_XmitRate0_S 0 -#define AR_XmitRate1 0x0000ff00 -#define AR_XmitRate1_S 8 -#define AR_XmitRate2 0x00ff0000 -#define AR_XmitRate2_S 16 -#define AR_XmitRate3 0xff000000 -#define AR_XmitRate3_S 24 - -#define AR_PacketDur0 0x00007fff -#define AR_PacketDur0_S 0 -#define AR_RTSCTSQual0 0x00008000 -#define AR_PacketDur1 0x7fff0000 -#define AR_PacketDur1_S 16 -#define AR_RTSCTSQual1 0x80000000 - -#define AR_PacketDur2 0x00007fff -#define AR_PacketDur2_S 0 -#define AR_RTSCTSQual2 0x00008000 -#define AR_PacketDur3 0x7fff0000 -#define AR_PacketDur3_S 16 -#define AR_RTSCTSQual3 0x80000000 - -#define AR_AggrLen 0x0000ffff -#define AR_AggrLen_S 0 -#define AR_TxCtlRsvd60 0x00030000 -#define AR_PadDelim 0x03fc0000 -#define AR_PadDelim_S 18 -#define AR_EncrType 0x0c000000 -#define AR_EncrType_S 26 -#define AR_TxCtlRsvd61 0xf0000000 - -#define AR_2040_0 0x00000001 -#define AR_GI0 0x00000002 -#define AR_ChainSel0 0x0000001c -#define AR_ChainSel0_S 2 -#define AR_2040_1 0x00000020 -#define AR_GI1 0x00000040 -#define AR_ChainSel1 0x00000380 -#define AR_ChainSel1_S 7 -#define AR_2040_2 0x00000400 -#define AR_GI2 0x00000800 -#define AR_ChainSel2 0x00007000 -#define AR_ChainSel2_S 12 -#define AR_2040_3 0x00008000 -#define AR_GI3 0x00010000 -#define AR_ChainSel3 0x000e0000 -#define AR_ChainSel3_S 17 -#define AR_RTSCTSRate 0x0ff00000 -#define AR_RTSCTSRate_S 20 -#define AR_TxCtlRsvd70 0xf0000000 - -#define AR_TxRSSIAnt00 0x000000ff -#define AR_TxRSSIAnt00_S 0 -#define AR_TxRSSIAnt01 0x0000ff00 -#define AR_TxRSSIAnt01_S 8 -#define AR_TxRSSIAnt02 0x00ff0000 -#define AR_TxRSSIAnt02_S 16 -#define AR_TxStatusRsvd00 0x3f000000 -#define AR_TxBaStatus 0x40000000 -#define AR_TxStatusRsvd01 0x80000000 - -#define AR_FrmXmitOK 0x00000001 -#define AR_ExcessiveRetries 0x00000002 -#define AR_FIFOUnderrun 0x00000004 -#define AR_Filtered 0x00000008 -#define AR_RTSFailCnt 0x000000f0 -#define AR_RTSFailCnt_S 4 -#define AR_DataFailCnt 0x00000f00 -#define AR_DataFailCnt_S 8 -#define AR_VirtRetryCnt 0x0000f000 -#define AR_VirtRetryCnt_S 12 -#define AR_TxDelimUnderrun 0x00010000 -#define AR_TxDataUnderrun 0x00020000 -#define AR_DescCfgErr 0x00040000 -#define AR_TxTimerExpired 0x00080000 -#define AR_TxStatusRsvd10 0xfff00000 - -#define AR_SendTimestamp ds_txstatus2 -#define AR_BaBitmapLow ds_txstatus3 -#define AR_BaBitmapHigh ds_txstatus4 - -#define AR_TxRSSIAnt10 0x000000ff -#define AR_TxRSSIAnt10_S 0 -#define AR_TxRSSIAnt11 0x0000ff00 -#define AR_TxRSSIAnt11_S 8 -#define AR_TxRSSIAnt12 0x00ff0000 -#define AR_TxRSSIAnt12_S 16 -#define AR_TxRSSICombined 0xff000000 -#define AR_TxRSSICombined_S 24 - -#define AR_TxEVM0 ds_txstatus5 -#define AR_TxEVM1 ds_txstatus6 -#define AR_TxEVM2 ds_txstatus7 - -#define AR_TxDone 0x00000001 -#define AR_SeqNum 0x00001ffe -#define AR_SeqNum_S 1 -#define AR_TxStatusRsvd80 0x0001e000 -#define AR_TxOpExceeded 0x00020000 -#define AR_TxStatusRsvd81 0x001c0000 -#define AR_FinalTxIdx 0x00600000 -#define AR_FinalTxIdx_S 21 -#define AR_TxStatusRsvd82 0x01800000 -#define AR_PowerMgmt 0x02000000 -#define AR_TxStatusRsvd83 0xfc000000 - -#define AR_RxCTLRsvd00 0xffffffff - -#define AR_BufLen 0x00000fff -#define AR_RxCtlRsvd00 0x00001000 -#define AR_RxIntrReq 0x00002000 -#define AR_RxCtlRsvd01 0xffffc000 - -#define AR_RxRSSIAnt00 0x000000ff -#define AR_RxRSSIAnt00_S 0 -#define AR_RxRSSIAnt01 0x0000ff00 -#define AR_RxRSSIAnt01_S 8 -#define AR_RxRSSIAnt02 0x00ff0000 -#define AR_RxRSSIAnt02_S 16 -#define AR_RxRate 0xff000000 -#define AR_RxRate_S 24 -#define AR_RxStatusRsvd00 0xff000000 - -#define AR_DataLen 0x00000fff -#define AR_RxMore 0x00001000 -#define AR_NumDelim 0x003fc000 -#define AR_NumDelim_S 14 -#define AR_RxStatusRsvd10 0xff800000 - -#define AR_RcvTimestamp ds_rxstatus2 - -#define AR_GI 0x00000001 -#define AR_2040 0x00000002 -#define AR_Parallel40 0x00000004 -#define AR_Parallel40_S 2 -#define AR_RxStatusRsvd30 0x000000f8 -#define AR_RxAntenna 0xffffff00 -#define AR_RxAntenna_S 8 - -#define AR_RxRSSIAnt10 0x000000ff -#define AR_RxRSSIAnt10_S 0 -#define AR_RxRSSIAnt11 0x0000ff00 -#define AR_RxRSSIAnt11_S 8 -#define AR_RxRSSIAnt12 0x00ff0000 -#define AR_RxRSSIAnt12_S 16 -#define AR_RxRSSICombined 0xff000000 -#define AR_RxRSSICombined_S 24 - -#define AR_RxEVM0 ds_rxstatus4 -#define AR_RxEVM1 ds_rxstatus5 -#define AR_RxEVM2 ds_rxstatus6 - -#define AR_RxDone 0x00000001 -#define AR_RxFrameOK 0x00000002 -#define AR_CRCErr 0x00000004 -#define AR_DecryptCRCErr 0x00000008 -#define AR_PHYErr 0x00000010 -#define AR_MichaelErr 0x00000020 -#define AR_PreDelimCRCErr 0x00000040 -#define AR_RxStatusRsvd70 0x00000080 -#define AR_RxKeyIdxValid 0x00000100 -#define AR_KeyIdx 0x0000fe00 -#define AR_KeyIdx_S 9 -#define AR_PHYErrCode 0x0000ff00 -#define AR_PHYErrCode_S 8 -#define AR_RxMoreAggr 0x00010000 -#define AR_RxAggr 0x00020000 -#define AR_PostDelimCRCErr 0x00040000 -#define AR_RxStatusRsvd71 0x3ff80000 -#define AR_DecryptBusyErr 0x40000000 -#define AR_KeyMiss 0x80000000 - -enum ath9k_tx_queue { - ATH9K_TX_QUEUE_INACTIVE = 0, - ATH9K_TX_QUEUE_DATA, - ATH9K_TX_QUEUE_BEACON, - ATH9K_TX_QUEUE_CAB, - ATH9K_TX_QUEUE_UAPSD, - ATH9K_TX_QUEUE_PSPOLL -}; - -#define ATH9K_NUM_TX_QUEUES 10 - -enum ath9k_tx_queue_subtype { - ATH9K_WME_AC_BK = 0, - ATH9K_WME_AC_BE, - ATH9K_WME_AC_VI, - ATH9K_WME_AC_VO, - ATH9K_WME_UPSD -}; - -enum ath9k_tx_queue_flags { - TXQ_FLAG_TXOKINT_ENABLE = 0x0001, - TXQ_FLAG_TXERRINT_ENABLE = 0x0001, - TXQ_FLAG_TXDESCINT_ENABLE = 0x0002, - TXQ_FLAG_TXEOLINT_ENABLE = 0x0004, - TXQ_FLAG_TXURNINT_ENABLE = 0x0008, - TXQ_FLAG_BACKOFF_DISABLE = 0x0010, - TXQ_FLAG_COMPRESSION_ENABLE = 0x0020, - TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040, - TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080, -}; - -#define ATH9K_TXQ_USEDEFAULT ((u32) -1) -#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 - -#define ATH9K_DECOMP_MASK_SIZE 128 -#define ATH9K_READY_TIME_LO_BOUND 50 -#define ATH9K_READY_TIME_HI_BOUND 96 - -enum ath9k_pkt_type { - ATH9K_PKT_TYPE_NORMAL = 0, - ATH9K_PKT_TYPE_ATIM, - ATH9K_PKT_TYPE_PSPOLL, - ATH9K_PKT_TYPE_BEACON, - ATH9K_PKT_TYPE_PROBE_RESP, - ATH9K_PKT_TYPE_CHIRP, - ATH9K_PKT_TYPE_GRP_POLL, -}; - -struct ath9k_tx_queue_info { - u32 tqi_ver; - enum ath9k_tx_queue tqi_type; - enum ath9k_tx_queue_subtype tqi_subtype; - enum ath9k_tx_queue_flags tqi_qflags; - u32 tqi_priority; - u32 tqi_aifs; - u32 tqi_cwmin; - u32 tqi_cwmax; - u16 tqi_shretry; - u16 tqi_lgretry; - u32 tqi_cbrPeriod; - u32 tqi_cbrOverflowLimit; - u32 tqi_burstTime; - u32 tqi_readyTime; - u32 tqi_physCompBuf; - u32 tqi_intFlags; -}; - -enum ath9k_rx_filter { - ATH9K_RX_FILTER_UCAST = 0x00000001, - ATH9K_RX_FILTER_MCAST = 0x00000002, - ATH9K_RX_FILTER_BCAST = 0x00000004, - ATH9K_RX_FILTER_CONTROL = 0x00000008, - ATH9K_RX_FILTER_BEACON = 0x00000010, - ATH9K_RX_FILTER_PROM = 0x00000020, - ATH9K_RX_FILTER_PROBEREQ = 0x00000080, - ATH9K_RX_FILTER_PHYERR = 0x00000100, - ATH9K_RX_FILTER_MYBEACON = 0x00000200, - ATH9K_RX_FILTER_PSPOLL = 0x00004000, - ATH9K_RX_FILTER_PHYRADAR = 0x00002000, - ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, -}; - -#define ATH9K_RATESERIES_RTS_CTS 0x0001 -#define ATH9K_RATESERIES_2040 0x0002 -#define ATH9K_RATESERIES_HALFGI 0x0004 - -struct ath9k_11n_rate_series { - u32 Tries; - u32 Rate; - u32 PktDuration; - u32 ChSel; - u32 RateFlags; -}; - -struct ath9k_keyval { - u8 kv_type; - u8 kv_pad; - u16 kv_len; - u8 kv_val[16]; /* TK */ - u8 kv_mic[8]; /* Michael MIC key */ - u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware - * supports both MIC keys in the same key cache entry; - * in that case, kv_mic is the RX key) */ -}; - -enum ath9k_key_type { - ATH9K_KEY_TYPE_CLEAR, - ATH9K_KEY_TYPE_WEP, - ATH9K_KEY_TYPE_AES, - ATH9K_KEY_TYPE_TKIP, -}; - -enum ath9k_cipher { - ATH9K_CIPHER_WEP = 0, - ATH9K_CIPHER_AES_OCB = 1, - ATH9K_CIPHER_AES_CCM = 2, - ATH9K_CIPHER_CKIP = 3, - ATH9K_CIPHER_TKIP = 4, - ATH9K_CIPHER_CLR = 5, - ATH9K_CIPHER_MIC = 127 -}; - -enum ath9k_ht_macmode { - ATH9K_HT_MACMODE_20 = 0, - ATH9K_HT_MACMODE_2040 = 1, -}; - -enum ath9k_ht_extprotspacing { - ATH9K_HT_EXTPROTSPACING_20 = 0, - ATH9K_HT_EXTPROTSPACING_25 = 1, -}; - -struct ath_hw; -struct ath9k_channel; -struct ath_rate_table; - -u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); -bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); -bool ath9k_hw_txstart(struct ath_hw *ah, u32 q); -u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); -bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); -bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); -bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0); -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags); -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, - struct ath_desc *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags); -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, - u32 aggrLen); -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, - u32 numDelims); -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, - u32 burstDuration); -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, - u32 vmf); -void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); -bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, - const struct ath9k_tx_queue_info *qinfo); -bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, - struct ath9k_tx_queue_info *qinfo); -int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, - const struct ath9k_tx_queue_info *qinfo); -bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); -bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); -int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pa, struct ath_desc *nds, u64 tsf); -bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 size, u32 flags); -bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); -void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); -void ath9k_hw_rxena(struct ath_hw *ah); -void ath9k_hw_startpcureceive(struct ath_hw *ah); -void ath9k_hw_stoppcurecv(struct ath_hw *ah); -bool ath9k_hw_stopdmarecv(struct ath_hw *ah); - -#endif /* MAC_H */ diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c deleted file mode 100644 index 8b6a7ea4e59b..000000000000 --- a/drivers/net/wireless/ath9k/main.c +++ /dev/null @@ -1,2890 +0,0 @@ -/* - * 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 -#include "ath9k.h" - -#define ATH_PCI_VERSION "0.1" - -static char *dev_info = "ath9k"; - -MODULE_AUTHOR("Atheros Communications"); -MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); -MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); -MODULE_LICENSE("Dual BSD/GPL"); - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); - -/* We use the hw_value as an index into our private channel structure */ - -#define CHAN2G(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 30, \ -} - -#define CHAN5G(_freq, _idx) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 30, \ -} - -/* Some 2 GHz radios are actually tunable on 2312-2732 - * on 5 MHz steps, we support the channels which we know - * we have calibration data for all cards though to make - * this static */ -static struct ieee80211_channel ath9k_2ghz_chantable[] = { - CHAN2G(2412, 0), /* Channel 1 */ - CHAN2G(2417, 1), /* Channel 2 */ - CHAN2G(2422, 2), /* Channel 3 */ - CHAN2G(2427, 3), /* Channel 4 */ - CHAN2G(2432, 4), /* Channel 5 */ - CHAN2G(2437, 5), /* Channel 6 */ - CHAN2G(2442, 6), /* Channel 7 */ - CHAN2G(2447, 7), /* Channel 8 */ - CHAN2G(2452, 8), /* Channel 9 */ - CHAN2G(2457, 9), /* Channel 10 */ - CHAN2G(2462, 10), /* Channel 11 */ - CHAN2G(2467, 11), /* Channel 12 */ - CHAN2G(2472, 12), /* Channel 13 */ - CHAN2G(2484, 13), /* Channel 14 */ -}; - -/* Some 5 GHz radios are actually tunable on XXXX-YYYY - * on 5 MHz steps, we support the channels which we know - * we have calibration data for all cards though to make - * this static */ -static struct ieee80211_channel ath9k_5ghz_chantable[] = { - /* _We_ call this UNII 1 */ - CHAN5G(5180, 14), /* Channel 36 */ - CHAN5G(5200, 15), /* Channel 40 */ - CHAN5G(5220, 16), /* Channel 44 */ - CHAN5G(5240, 17), /* Channel 48 */ - /* _We_ call this UNII 2 */ - CHAN5G(5260, 18), /* Channel 52 */ - CHAN5G(5280, 19), /* Channel 56 */ - CHAN5G(5300, 20), /* Channel 60 */ - CHAN5G(5320, 21), /* Channel 64 */ - /* _We_ call this "Middle band" */ - CHAN5G(5500, 22), /* Channel 100 */ - CHAN5G(5520, 23), /* Channel 104 */ - CHAN5G(5540, 24), /* Channel 108 */ - CHAN5G(5560, 25), /* Channel 112 */ - CHAN5G(5580, 26), /* Channel 116 */ - CHAN5G(5600, 27), /* Channel 120 */ - CHAN5G(5620, 28), /* Channel 124 */ - CHAN5G(5640, 29), /* Channel 128 */ - CHAN5G(5660, 30), /* Channel 132 */ - CHAN5G(5680, 31), /* Channel 136 */ - CHAN5G(5700, 32), /* Channel 140 */ - /* _We_ call this UNII 3 */ - CHAN5G(5745, 33), /* Channel 149 */ - CHAN5G(5765, 34), /* Channel 153 */ - CHAN5G(5785, 35), /* Channel 157 */ - CHAN5G(5805, 36), /* Channel 161 */ - CHAN5G(5825, 37), /* Channel 165 */ -}; - -static void ath_cache_conf_rate(struct ath_softc *sc, - struct ieee80211_conf *conf) -{ - switch (conf->channel->band) { - case IEEE80211_BAND_2GHZ: - if (conf_is_ht20(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; - else if (conf_is_ht40_minus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; - else if (conf_is_ht40_plus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; - else - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11G]; - break; - case IEEE80211_BAND_5GHZ: - if (conf_is_ht20(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; - else if (conf_is_ht40_minus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; - else if (conf_is_ht40_plus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; - else - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11A]; - break; - default: - BUG_ON(1); - break; - } -} - -static void ath_update_txpow(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - u32 txpow; - - if (sc->curtxpow != sc->config.txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); - /* read back in case value is clamped */ - ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); - sc->curtxpow = txpow; - } -} - -static u8 parse_mpdudensity(u8 mpdudensity) -{ - /* - * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": - * 0 for no restriction - * 1 for 1/4 us - * 2 for 1/2 us - * 3 for 1 us - * 4 for 2 us - * 5 for 4 us - * 6 for 8 us - * 7 for 16 us - */ - switch (mpdudensity) { - case 0: - return 0; - case 1: - case 2: - case 3: - /* Our lower layer calculations limit our precision to - 1 microsecond */ - return 1; - case 4: - return 2; - case 5: - return 4; - case 6: - return 8; - case 7: - return 16; - default: - return 0; - } -} - -static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) -{ - struct ath_rate_table *rate_table = NULL; - struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate; - int i, maxrates; - - switch (band) { - case IEEE80211_BAND_2GHZ: - rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; - break; - case IEEE80211_BAND_5GHZ: - rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; - break; - default: - break; - } - - if (rate_table == NULL) - return; - - sband = &sc->sbands[band]; - rate = sc->rates[band]; - - if (rate_table->rate_cnt > ATH_RATE_MAX) - maxrates = ATH_RATE_MAX; - else - maxrates = rate_table->rate_cnt; - - for (i = 0; i < maxrates; i++) { - rate[i].bitrate = rate_table->info[i].ratekbps / 100; - rate[i].hw_value = rate_table->info[i].ratecode; - if (rate_table->info[i].short_preamble) { - rate[i].hw_value_short = rate_table->info[i].ratecode | - rate_table->info[i].short_preamble; - rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE; - } - sband->n_bitrates++; - - DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n", - rate[i].bitrate / 10, rate[i].hw_value); - } -} - -/* - * Set/change channels. If the channel is really being changed, it's done - * by reseting the chip. To accomplish this we must first cleanup any pending - * DMA, then restart stuff. -*/ -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *hchan) -{ - struct ath_hw *ah = sc->sc_ah; - bool fastcc = true, stopped; - struct ieee80211_channel *channel = hw->conf.channel; - int r; - - if (sc->sc_flags & SC_OP_INVALID) - return -EIO; - - ath9k_ps_wakeup(sc); - - /* - * This is only performed if the channel settings have - * actually changed. - * - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the - * hardware at the new frequency, and then re-enable - * the relevant bits of the h/w. - */ - ath9k_hw_set_interrupts(ah, 0); - ath_drain_all_txq(sc, false); - stopped = ath_stoprecv(sc); - - /* XXX: do not flush receive queue here. We don't want - * to flush data frames already in queue because of - * changing channel. */ - - if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) - fastcc = false; - - DPRINTF(sc, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), chanwidth: %d\n", - sc->sc_ah->curchan->channel, - channel->center_freq, sc->tx_chan_width); - - spin_lock_bh(&sc->sc_resetlock); - - r = ath9k_hw_reset(ah, hchan, fastcc); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %u\n", - channel->center_freq, r); - spin_unlock_bh(&sc->sc_resetlock); - return r; - } - spin_unlock_bh(&sc->sc_resetlock); - - sc->sc_flags &= ~SC_OP_FULL_RESET; - - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - return -EIO; - } - - ath_cache_conf_rate(sc, &hw->conf); - ath_update_txpow(sc); - ath9k_hw_set_interrupts(ah, sc->imask); - ath9k_ps_restore(sc); - return 0; -} - -/* - * This routine performs the periodic noise floor calibration function - * that is used to adjust and optimize the chip performance. This - * takes environmental changes (location, temperature) into account. - * When the task is complete, it reschedules itself depending on the - * appropriate interval that was calculated. - */ -static void ath_ani_calibrate(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - struct ath_hw *ah = sc->sc_ah; - bool longcal = false; - bool shortcal = false; - bool aniflag = false; - unsigned int timestamp = jiffies_to_msecs(jiffies); - u32 cal_interval, short_cal_interval; - - short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? - ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; - - /* - * don't calibrate when we're scanning. - * we are most likely not on our home channel. - */ - if (sc->sc_flags & SC_OP_SCANNING) - goto set_timer; - - /* Long calibration runs independently of short calibration. */ - if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { - longcal = true; - DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies); - sc->ani.longcal_timer = timestamp; - } - - /* Short calibration applies only while caldone is false */ - if (!sc->ani.caldone) { - if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) { - shortcal = true; - DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies); - sc->ani.shortcal_timer = timestamp; - sc->ani.resetcal_timer = timestamp; - } - } else { - if ((timestamp - sc->ani.resetcal_timer) >= - ATH_RESTART_CALINTERVAL) { - sc->ani.caldone = ath9k_hw_reset_calvalid(ah); - if (sc->ani.caldone) - sc->ani.resetcal_timer = timestamp; - } - } - - /* Verify whether we must check ANI */ - if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { - aniflag = true; - sc->ani.checkani_timer = timestamp; - } - - /* Skip all processing if there's nothing to do. */ - if (longcal || shortcal || aniflag) { - /* Call ANI routine if necessary */ - if (aniflag) - ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan); - - /* Perform calibration if necessary */ - if (longcal || shortcal) { - bool iscaldone = false; - - if (ath9k_hw_calibrate(ah, ah->curchan, - sc->rx_chainmask, longcal, - &iscaldone)) { - if (longcal) - sc->ani.noise_floor = - ath9k_hw_getchan_noise(ah, - ah->curchan); - - DPRINTF(sc, ATH_DBG_ANI, - "calibrate chan %u/%x nf: %d\n", - ah->curchan->channel, - ah->curchan->channelFlags, - sc->ani.noise_floor); - } else { - DPRINTF(sc, ATH_DBG_ANY, - "calibrate chan %u/%x failed\n", - ah->curchan->channel, - ah->curchan->channelFlags); - } - sc->ani.caldone = iscaldone; - } - } - -set_timer: - /* - * Set timer interval based on previous results. - * The interval must be the shortest necessary to satisfy ANI, - * short calibration and long calibration. - */ - cal_interval = ATH_LONG_CALINTERVAL; - if (sc->sc_ah->config.enable_ani) - cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); - if (!sc->ani.caldone) - cal_interval = min(cal_interval, (u32)short_cal_interval); - - mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); -} - -/* - * Update tx/rx chainmask. For legacy association, - * hard code chainmask to 1x1, for 11n association, use - * the chainmask configuration, for bt coexistence, use - * the chainmask configuration even in legacy mode. - */ -void ath_update_chainmask(struct ath_softc *sc, int is_ht) -{ - if (is_ht || - (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { - sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; - sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask; - } else { - sc->tx_chainmask = 1; - sc->rx_chainmask = 1; - } - - DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n", - sc->tx_chainmask, sc->rx_chainmask); -} - -static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) -{ - struct ath_node *an; - - an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) { - ath_tx_node_init(sc, an); - an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + - sta->ht_cap.ampdu_factor); - an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); - } -} - -static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) - ath_tx_node_cleanup(sc, an); -} - -static void ath9k_tasklet(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - u32 status = sc->intrstatus; - - if (status & ATH9K_INT_FATAL) { - ath_reset(sc, false); - return; - } - - if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { - spin_lock_bh(&sc->rx.rxflushlock); - ath_rx_tasklet(sc, 0); - spin_unlock_bh(&sc->rx.rxflushlock); - } - - if (status & ATH9K_INT_TX) - ath_tx_tasklet(sc); - - /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); -} - -irqreturn_t ath_isr(int irq, void *dev) -{ -#define SCHED_INTR ( \ - ATH9K_INT_FATAL | \ - ATH9K_INT_RXORN | \ - ATH9K_INT_RXEOL | \ - ATH9K_INT_RX | \ - ATH9K_INT_TX | \ - ATH9K_INT_BMISS | \ - ATH9K_INT_CST | \ - ATH9K_INT_TSFOOR) - - struct ath_softc *sc = dev; - struct ath_hw *ah = sc->sc_ah; - enum ath9k_int status; - bool sched = false; - - /* - * The hardware is not ready/present, don't - * touch anything. Note this can happen early - * on if the IRQ is shared. - */ - if (sc->sc_flags & SC_OP_INVALID) - return IRQ_NONE; - - ath9k_ps_wakeup(sc); - - /* shared irq, not for us */ - - if (!ath9k_hw_intrpend(ah)) { - ath9k_ps_restore(sc); - return IRQ_NONE; - } - - /* - * Figure out the reason(s) for the interrupt. Note - * that the hal returns a pseudo-ISR that may include - * bits we haven't explicitly enabled so we mask the - * value to insure we only process bits we requested. - */ - ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ - status &= sc->imask; /* discard unasked-for bits */ - - /* - * If there are no status bits set, then this interrupt was not - * for me (should have been caught above). - */ - if (!status) { - ath9k_ps_restore(sc); - return IRQ_NONE; - } - - /* Cache the status */ - sc->intrstatus = status; - - if (status & SCHED_INTR) - sched = true; - - /* - * If a FATAL or RXORN interrupt is received, we have to reset the - * chip immediately. - */ - if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) - goto chip_reset; - - if (status & ATH9K_INT_SWBA) - tasklet_schedule(&sc->bcon_tasklet); - - if (status & ATH9K_INT_TXURN) - ath9k_hw_updatetxtriglevel(ah, true); - - if (status & ATH9K_INT_MIB) { - /* - * Disable interrupts until we service the MIB - * interrupt; otherwise it will continue to - * fire. - */ - ath9k_hw_set_interrupts(ah, 0); - /* - * Let the hal handle the event. We assume - * it will clear whatever condition caused - * the interrupt. - */ - ath9k_hw_procmibevent(ah, &sc->nodestats); - ath9k_hw_set_interrupts(ah, sc->imask); - } - - if (status & ATH9K_INT_TIM_TIMER) { - if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - /* Clear RxAbort bit so that we can - * receive frames */ - ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); - ath9k_hw_setrxabort(ah, 0); - sched = true; - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; - } - } - -chip_reset: - - ath9k_ps_restore(sc); - ath_debug_stat_interrupt(sc, status); - - if (sched) { - /* turn off every interrupt except SWBA */ - ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA)); - tasklet_schedule(&sc->intr_tq); - } - - return IRQ_HANDLED; - -#undef SCHED_INTR -} - -static u32 ath_get_extchanmode(struct ath_softc *sc, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - u32 chanmode = 0; - - switch (chan->band) { - case IEEE80211_BAND_2GHZ: - switch(channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chanmode = CHANNEL_G_HT20; - break; - case NL80211_CHAN_HT40PLUS: - chanmode = CHANNEL_G_HT40PLUS; - break; - case NL80211_CHAN_HT40MINUS: - chanmode = CHANNEL_G_HT40MINUS; - break; - } - break; - case IEEE80211_BAND_5GHZ: - switch(channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chanmode = CHANNEL_A_HT20; - break; - case NL80211_CHAN_HT40PLUS: - chanmode = CHANNEL_A_HT40PLUS; - break; - case NL80211_CHAN_HT40MINUS: - chanmode = CHANNEL_A_HT40MINUS; - break; - } - break; - default: - break; - } - - return chanmode; -} - -static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, - struct ath9k_keyval *hk, const u8 *addr, - bool authenticator) -{ - const u8 *key_rxmic; - const u8 *key_txmic; - - key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; - key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; - - if (addr == NULL) { - /* - * Group key installation - only two key cache entries are used - * regardless of splitmic capability since group key is only - * used either for TX or RX. - */ - if (authenticator) { - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); - } else { - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); - } - return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr); - } - if (!sc->splitmic) { - /* TX and RX keys share the same key cache entry. */ - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); - return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr); - } - - /* Separate key cache entries for TX and RX */ - - /* TX key goes at first index, RX key at +32. */ - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { - /* TX MIC entry failed. No need to proceed further */ - DPRINTF(sc, ATH_DBG_FATAL, - "Setting TX MIC Key Failed\n"); - return 0; - } - - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - /* XXX delete tx key on failure? */ - return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr); -} - -static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc) -{ - int i; - - for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) { - if (test_bit(i, sc->keymap) || - test_bit(i + 64, sc->keymap)) - continue; /* At least one part of TKIP key allocated */ - if (sc->splitmic && - (test_bit(i + 32, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - continue; /* At least one part of TKIP key allocated */ - - /* Found a free slot for a TKIP key */ - return i; - } - return -1; -} - -static int ath_reserve_key_cache_slot(struct ath_softc *sc) -{ - int i; - - /* First, try to find slots that would not be available for TKIP. */ - if (sc->splitmic) { - for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) { - if (!test_bit(i, sc->keymap) && - (test_bit(i + 32, sc->keymap) || - test_bit(i + 64, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - return i; - if (!test_bit(i + 32, sc->keymap) && - (test_bit(i, sc->keymap) || - test_bit(i + 64, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - return i + 32; - if (!test_bit(i + 64, sc->keymap) && - (test_bit(i , sc->keymap) || - test_bit(i + 32, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - return i + 64; - if (!test_bit(i + 64 + 32, sc->keymap) && - (test_bit(i, sc->keymap) || - test_bit(i + 32, sc->keymap) || - test_bit(i + 64, sc->keymap))) - return i + 64 + 32; - } - } else { - for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) { - if (!test_bit(i, sc->keymap) && - test_bit(i + 64, sc->keymap)) - return i; - if (test_bit(i, sc->keymap) && - !test_bit(i + 64, sc->keymap)) - return i + 64; - } - } - - /* No partially used TKIP slots, pick any available slot */ - for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) { - /* Do not allow slots that could be needed for TKIP group keys - * to be used. This limitation could be removed if we know that - * TKIP will not be used. */ - if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) - continue; - if (sc->splitmic) { - if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) - continue; - if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) - continue; - } - - if (!test_bit(i, sc->keymap)) - return i; /* Found a free slot for a key */ - } - - /* No free slot found */ - return -1; -} - -static int ath_key_config(struct ath_softc *sc, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath9k_keyval hk; - const u8 *mac = NULL; - int ret = 0; - int idx; - - memset(&hk, 0, sizeof(hk)); - - switch (key->alg) { - case ALG_WEP: - hk.kv_type = ATH9K_CIPHER_WEP; - break; - case ALG_TKIP: - hk.kv_type = ATH9K_CIPHER_TKIP; - break; - case ALG_CCMP: - hk.kv_type = ATH9K_CIPHER_AES_CCM; - break; - default: - return -EOPNOTSUPP; - } - - hk.kv_len = key->keylen; - memcpy(hk.kv_val, key->key, key->keylen); - - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* For now, use the default keys for broadcast keys. This may - * need to change with virtual interfaces. */ - idx = key->keyidx; - } else if (key->keyidx) { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (vif->type != NL80211_IFTYPE_AP) { - /* Only keyidx 0 should be used with unicast key, but - * allow this for client mode for now. */ - idx = key->keyidx; - } else - return -EIO; - } else { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (key->alg == ALG_TKIP) - idx = ath_reserve_key_cache_slot_tkip(sc); - else - idx = ath_reserve_key_cache_slot(sc); - if (idx < 0) - return -ENOSPC; /* no free key cache entries */ - } - - if (key->alg == ALG_TKIP) - ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac, - vif->type == NL80211_IFTYPE_AP); - else - ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac); - - if (!ret) - return -EIO; - - set_bit(idx, sc->keymap); - if (key->alg == ALG_TKIP) { - set_bit(idx + 64, sc->keymap); - if (sc->splitmic) { - set_bit(idx + 32, sc->keymap); - set_bit(idx + 64 + 32, sc->keymap); - } - } - - return idx; -} - -static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) -{ - ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx); - if (key->hw_key_idx < IEEE80211_WEP_NKID) - return; - - clear_bit(key->hw_key_idx, sc->keymap); - if (key->alg != ALG_TKIP) - return; - - clear_bit(key->hw_key_idx + 64, sc->keymap); - if (sc->splitmic) { - clear_bit(key->hw_key_idx + 32, sc->keymap); - clear_bit(key->hw_key_idx + 64 + 32, sc->keymap); - } -} - -static void setup_ht_cap(struct ath_softc *sc, - struct ieee80211_sta_ht_cap *ht_info) -{ -#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ -#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ - - ht_info->ht_supported = true; - ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SM_PS | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; - - ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; - ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; - - /* set up supported mcs set */ - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - - switch(sc->rx_chainmask) { - case 1: - ht_info->mcs.rx_mask[0] = 0xff; - break; - case 3: - case 5: - case 7: - default: - ht_info->mcs.rx_mask[0] = 0xff; - ht_info->mcs.rx_mask[1] = 0xff; - break; - } - - ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; -} - -static void ath9k_bss_assoc_info(struct ath_softc *sc, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf) -{ - struct ath_vif *avp = (void *)vif->drv_priv; - - if (bss_conf->assoc) { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, sc->curbssid); - - /* New association, store aid */ - if (avp->av_opmode == NL80211_IFTYPE_STATION) { - sc->curaid = bss_conf->aid; - ath9k_hw_write_associd(sc); - } - - /* Configure the beacon */ - ath_beacon_config(sc, vif); - - /* Reset rssi stats */ - sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; - sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; - sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; - sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; - - /* Start ANI */ - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); - } else { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); - sc->curaid = 0; - } -} - -/********************************/ -/* LED functions */ -/********************************/ - -static void ath_led_blink_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - ath_led_blink_work.work); - - if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) - return; - - if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || - (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); - else - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, - (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); - - queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, - (sc->sc_flags & SC_OP_LED_ON) ? - msecs_to_jiffies(sc->led_off_duration) : - msecs_to_jiffies(sc->led_on_duration)); - - sc->led_on_duration = sc->led_on_cnt ? - max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : - ATH_LED_ON_DURATION_IDLE; - sc->led_off_duration = sc->led_off_cnt ? - max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : - ATH_LED_OFF_DURATION_IDLE; - sc->led_on_cnt = sc->led_off_cnt = 0; - if (sc->sc_flags & SC_OP_LED_ON) - sc->sc_flags &= ~SC_OP_LED_ON; - else - sc->sc_flags |= SC_OP_LED_ON; -} - -static void ath_led_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); - struct ath_softc *sc = led->sc; - - switch (brightness) { - case LED_OFF: - if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, - (led->led_type == ATH_LED_RADIO)); - sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - if (led->led_type == ATH_LED_RADIO) - sc->sc_flags &= ~SC_OP_LED_ON; - } else { - sc->led_off_cnt++; - } - break; - case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) { - sc->sc_flags |= SC_OP_LED_ASSOCIATED; - queue_delayed_work(sc->hw->workqueue, - &sc->ath_led_blink_work, 0); - } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); - sc->sc_flags |= SC_OP_LED_ON; - } else { - sc->led_on_cnt++; - } - break; - default: - break; - } -} - -static int ath_register_led(struct ath_softc *sc, struct ath_led *led, - char *trigger) -{ - int ret; - - led->sc = sc; - led->led_cdev.name = led->name; - led->led_cdev.default_trigger = trigger; - led->led_cdev.brightness_set = ath_led_brightness; - - ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); - if (ret) - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to register led:%s", led->name); - else - led->registered = 1; - return ret; -} - -static void ath_unregister_led(struct ath_led *led) -{ - if (led->registered) { - led_classdev_unregister(&led->led_cdev); - led->registered = 0; - } -} - -static void ath_deinit_leds(struct ath_softc *sc) -{ - cancel_delayed_work_sync(&sc->ath_led_blink_work); - ath_unregister_led(&sc->assoc_led); - sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - ath_unregister_led(&sc->tx_led); - ath_unregister_led(&sc->rx_led); - ath_unregister_led(&sc->radio_led); - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -} - -static void ath_init_leds(struct ath_softc *sc) -{ - char *trigger; - int ret; - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - /* LED off, active low */ - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); - - INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); - - trigger = ieee80211_get_radio_led_name(sc->hw); - snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), - "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->radio_led, trigger); - sc->radio_led.led_type = ATH_LED_RADIO; - if (ret) - goto fail; - - trigger = ieee80211_get_assoc_led_name(sc->hw); - snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), - "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->assoc_led, trigger); - sc->assoc_led.led_type = ATH_LED_ASSOC; - if (ret) - goto fail; - - trigger = ieee80211_get_tx_led_name(sc->hw); - snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), - "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->tx_led, trigger); - sc->tx_led.led_type = ATH_LED_TX; - if (ret) - goto fail; - - trigger = ieee80211_get_rx_led_name(sc->hw); - snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), - "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->rx_led, trigger); - sc->rx_led.led_type = ATH_LED_RX; - if (ret) - goto fail; - - return; - -fail: - ath_deinit_leds(sc); -} - -void ath_radio_enable(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_channel *channel = sc->hw->conf.channel; - int r; - - ath9k_ps_wakeup(sc); - spin_lock_bh(&sc->sc_resetlock); - - r = ath9k_hw_reset(ah, ah->curchan, false); - - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) ", - "reset status %u\n", - channel->center_freq, r); - } - spin_unlock_bh(&sc->sc_resetlock); - - ath_update_txpow(sc); - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - return; - } - - if (sc->sc_flags & SC_OP_BEACONS) - ath_beacon_config(sc, NULL); /* restart beacons */ - - /* Re-Enable interrupts */ - ath9k_hw_set_interrupts(ah, sc->imask); - - /* Enable LED */ - ath9k_hw_cfg_output(ah, ATH_LED_PIN, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); - - ieee80211_wake_queues(sc->hw); - ath9k_ps_restore(sc); -} - -void ath_radio_disable(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_channel *channel = sc->hw->conf.channel; - int r; - - ath9k_ps_wakeup(sc); - ieee80211_stop_queues(sc->hw); - - /* Disable LED */ - ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1); - ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN); - - /* Disable interrupts */ - ath9k_hw_set_interrupts(ah, 0); - - ath_drain_all_txq(sc, false); /* clear pending tx frames */ - ath_stoprecv(sc); /* turn off frame recv */ - ath_flushrecv(sc); /* flush recv queue */ - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, ah->curchan, false); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) " - "reset status %u\n", - channel->center_freq, r); - } - spin_unlock_bh(&sc->sc_resetlock); - - ath9k_hw_phy_disable(ah); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); - ath9k_ps_restore(sc); -} - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - -/*******************/ -/* Rfkill */ -/*******************/ - -static bool ath_is_rfkill_set(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == - ah->rfkill_polarity; -} - -/* h/w rfkill poll function */ -static void ath_rfkill_poll(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - rf_kill.rfkill_poll.work); - bool radio_on; - - if (sc->sc_flags & SC_OP_INVALID) - return; - - radio_on = !ath_is_rfkill_set(sc); - - /* - * enable/disable radio only when there is a - * state change in RF switch - */ - if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) { - enum rfkill_state state; - - if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) { - state = radio_on ? RFKILL_STATE_SOFT_BLOCKED - : RFKILL_STATE_HARD_BLOCKED; - } else if (radio_on) { - ath_radio_enable(sc); - state = RFKILL_STATE_UNBLOCKED; - } else { - ath_radio_disable(sc); - state = RFKILL_STATE_HARD_BLOCKED; - } - - if (state == RFKILL_STATE_HARD_BLOCKED) - sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED; - else - sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED; - - rfkill_force_state(sc->rf_kill.rfkill, state); - } - - queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, - msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL)); -} - -/* s/w rfkill handler */ -static int ath_sw_toggle_radio(void *data, enum rfkill_state state) -{ - struct ath_softc *sc = data; - - switch (state) { - case RFKILL_STATE_SOFT_BLOCKED: - if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED | - SC_OP_RFKILL_SW_BLOCKED))) - ath_radio_disable(sc); - sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED; - return 0; - case RFKILL_STATE_UNBLOCKED: - if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) { - sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED; - if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) { - DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the" - "radio as it is disabled by h/w\n"); - return -EPERM; - } - ath_radio_enable(sc); - } - return 0; - default: - return -EINVAL; - } -} - -/* Init s/w rfkill */ -static int ath_init_sw_rfkill(struct ath_softc *sc) -{ - sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy), - RFKILL_TYPE_WLAN); - if (!sc->rf_kill.rfkill) { - DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n"); - return -ENOMEM; - } - - snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), - "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy)); - sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name; - sc->rf_kill.rfkill->data = sc; - sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; - sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED; - - return 0; -} - -/* Deinitialize rfkill */ -static void ath_deinit_rfkill(struct ath_softc *sc) -{ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); - - if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) { - rfkill_unregister(sc->rf_kill.rfkill); - sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED; - sc->rf_kill.rfkill = NULL; - } -} - -static int ath_start_rfkill_poll(struct ath_softc *sc) -{ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - queue_delayed_work(sc->hw->workqueue, - &sc->rf_kill.rfkill_poll, 0); - - if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { - if (rfkill_register(sc->rf_kill.rfkill)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to register rfkill\n"); - rfkill_free(sc->rf_kill.rfkill); - - /* Deinitialize the device */ - ath_cleanup(sc); - return -EIO; - } else { - sc->sc_flags |= SC_OP_RFKILL_REGISTERED; - } - } - - return 0; -} -#endif /* CONFIG_RFKILL */ - -void ath_cleanup(struct ath_softc *sc) -{ - ath_detach(sc); - free_irq(sc->irq, sc); - ath_bus_cleanup(sc); - kfree(sc->sec_wiphy); - ieee80211_free_hw(sc->hw); -} - -void ath_detach(struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - int i = 0; - - ath9k_ps_wakeup(sc); - - DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - ath_deinit_rfkill(sc); -#endif - ath_deinit_leds(sc); - cancel_work_sync(&sc->chan_work); - cancel_delayed_work_sync(&sc->wiphy_work); - - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - sc->sec_wiphy[i] = NULL; - ieee80211_unregister_hw(aphy->hw); - ieee80211_free_hw(aphy->hw); - } - ieee80211_unregister_hw(hw); - ath_rx_cleanup(sc); - ath_tx_cleanup(sc); - - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - - if (!(sc->sc_flags & SC_OP_INVALID)) - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - ath9k_hw_detach(sc->sc_ah); - ath9k_exit_debug(sc); - ath9k_ps_restore(sc); -} - -static int ath9k_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_regulatory *reg = &sc->sc_ah->regulatory; - - return ath_reg_notifier_apply(wiphy, request, reg); -} - -static int ath_init(u16 devid, struct ath_softc *sc) -{ - struct ath_hw *ah = NULL; - int status; - int error = 0, i; - int csz = 0; - - /* XXX: hardware will not be ready until ath_open() being called */ - sc->sc_flags |= SC_OP_INVALID; - - if (ath9k_init_debug(sc) < 0) - printk(KERN_ERR "Unable to create debugfs files\n"); - - spin_lock_init(&sc->wiphy_lock); - spin_lock_init(&sc->sc_resetlock); - spin_lock_init(&sc->sc_serial_rw); - mutex_init(&sc->mutex); - tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); - tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, - (unsigned long)sc); - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - ath_read_cachesize(sc, &csz); - /* XXX assert csz is non-zero */ - sc->cachelsz = csz << 2; /* convert to bytes */ - - ah = ath9k_hw_attach(devid, sc, &status); - if (ah == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to attach hardware; HAL status %d\n", status); - error = -ENXIO; - goto bad; - } - sc->sc_ah = ah; - - /* Get the hardware key cache size. */ - sc->keymax = ah->caps.keycache_size; - if (sc->keymax > ATH_KEYMAX) { - DPRINTF(sc, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, sc->keymax); - sc->keymax = ATH_KEYMAX; - } - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < sc->keymax; i++) - ath9k_hw_keyreset(ah, (u16) i); - - if (ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, - ath9k_reg_notifier)) - goto bad; - - /* default to MONITOR mode */ - sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; - - /* Setup rate tables */ - - ath_rate_attach(sc); - ath_setup_rates(sc, IEEE80211_BAND_2GHZ); - ath_setup_rates(sc, IEEE80211_BAND_5GHZ); - - /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS - * priority. Note that the hal handles reseting - * these queues at the needed time. - */ - sc->beacon.beaconq = ath_beaconq_setup(ah); - if (sc->beacon.beaconq == -1) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup a beacon xmit queue\n"); - error = -EIO; - goto bad2; - } - sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); - if (sc->beacon.cabq == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); - error = -EIO; - goto bad2; - } - - sc->config.cabqReadytime = ATH_CABQ_READY_TIME; - ath_cabq_update(sc); - - for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) - sc->tx.hwq_map[i] = -1; - - /* Setup data queues */ - /* NB: ensure BK queue is the lowest priority h/w queue */ - if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); - error = -EIO; - goto bad2; - } - - if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); - error = -EIO; - goto bad2; - } - if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); - error = -EIO; - goto bad2; - } - if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); - error = -EIO; - goto bad2; - } - - /* Initializes the noise floor to a reasonable default value. - * Later on this will be updated during ANI processing. */ - - sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; - setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc); - - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, - 0, 1, NULL); - } - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) - sc->splitmic = 1; - - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, - 1, NULL); - - sc->config.txpowlimit = ATH_TXPOWER_MAX; - - /* 11n Capabilities */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - sc->sc_flags |= SC_OP_TXAGGR; - sc->sc_flags |= SC_OP_RXAGGR; - } - - sc->tx_chainmask = ah->caps.tx_chainmask; - sc->rx_chainmask = ah->caps.rx_chainmask; - - ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); - sc->rx.defant = ath9k_hw_getdefantenna(ah); - - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); - - sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ - - /* initialize beacon slots */ - for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - sc->beacon.bslot[i] = NULL; - sc->beacon.bslot_aphy[i] = NULL; - } - - /* setup channels and rates */ - - sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; - sc->sbands[IEEE80211_BAND_2GHZ].bitrates = - sc->rates[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - sc->sbands[IEEE80211_BAND_2GHZ].n_channels = - ARRAY_SIZE(ath9k_2ghz_chantable); - - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; - sc->sbands[IEEE80211_BAND_5GHZ].bitrates = - sc->rates[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - sc->sbands[IEEE80211_BAND_5GHZ].n_channels = - ARRAY_SIZE(ath9k_5ghz_chantable); - } - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX) - ath9k_hw_btcoex_enable(sc->sc_ah); - - return 0; -bad2: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); -bad: - if (ah) - ath9k_hw_detach(ah); - ath9k_exit_debug(sc); - - return error; -} - -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) -{ - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_SPECTRUM_MGMT; - - if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) - hw->flags |= IEEE80211_HW_MFP_CAPABLE; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->queues = 4; - hw->max_rates = 4; - hw->channel_change_time = 5000; - hw->max_listen_interval = 10; - hw->max_rate_tries = ATH_11N_TXMAXTRY; - hw->sta_data_size = sizeof(struct ath_node); - hw->vif_data_size = sizeof(struct ath_vif); - - hw->rate_control_algorithm = "ath9k_rate_control"; - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &sc->sbands[IEEE80211_BAND_2GHZ]; - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; -} - -int ath_attach(u16 devid, struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - int error = 0, i; - struct ath_regulatory *reg; - - DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); - - error = ath_init(devid, sc); - if (error != 0) - return error; - - reg = &sc->sc_ah->regulatory; - - /* get mac address from hardware and set in mac80211 */ - - SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); - - ath_set_hw_capab(sc, hw); - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) - setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); - } - - /* initialize tx/rx engine */ - error = ath_tx_init(sc, ATH_TXBUF); - if (error != 0) - goto error_attach; - - error = ath_rx_init(sc, ATH_RXBUF); - if (error != 0) - goto error_attach; - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - /* Initialze h/w Rfkill */ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); - - /* Initialize s/w rfkill */ - error = ath_init_sw_rfkill(sc); - if (error) - goto error_attach; -#endif - - INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); - INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); - sc->wiphy_scheduler_int = msecs_to_jiffies(500); - - error = ieee80211_register_hw(hw); - - if (!ath_is_world_regd(reg)) { - error = regulatory_hint(hw->wiphy, reg->alpha2); - if (error) - goto error_attach; - } - - /* Initialize LED control */ - ath_init_leds(sc); - - - return 0; - -error_attach: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - ath9k_hw_detach(sc->sc_ah); - ath9k_exit_debug(sc); - - return error; -} - -int ath_reset(struct ath_softc *sc, bool retry_tx) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_hw *hw = sc->hw; - int r; - - ath9k_hw_set_interrupts(ah, 0); - ath_drain_all_txq(sc, retry_tx); - ath_stoprecv(sc); - ath_flushrecv(sc); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); - if (r) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u\n", r); - spin_unlock_bh(&sc->sc_resetlock); - - if (ath_startrecv(sc) != 0) - DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); - - /* - * We may be doing a reset in response to a request - * that changes the channel so update any state that - * might change as a result. - */ - ath_cache_conf_rate(sc, &hw->conf); - - ath_update_txpow(sc); - - if (sc->sc_flags & SC_OP_BEACONS) - ath_beacon_config(sc, NULL); /* restart beacons */ - - ath9k_hw_set_interrupts(ah, sc->imask); - - if (retry_tx) { - int i; - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - spin_lock_bh(&sc->tx.txq[i].axq_lock); - ath_txq_schedule(sc, &sc->tx.txq[i]); - spin_unlock_bh(&sc->tx.txq[i].axq_lock); - } - } - } - - return r; -} - -/* - * This function will allocate both the DMA descriptor structure, and the - * buffers it contains. These are used to contain the descriptors used - * by the system. -*/ -int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head, const char *name, - int nbuf, int ndesc) -{ -#define DS2PHYS(_dd, _ds) \ - ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) -#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) -#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) - - struct ath_desc *ds; - struct ath_buf *bf; - int i, bsize, error; - - DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", - name, nbuf, ndesc); - - INIT_LIST_HEAD(head); - /* ath_desc must be a multiple of DWORDs */ - if ((sizeof(struct ath_desc) % 4) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); - ASSERT((sizeof(struct ath_desc) % 4) == 0); - error = -ENOMEM; - goto fail; - } - - dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; - - /* - * Need additional DMA memory because we can't use - * descriptors that cross the 4K page boundary. Assume - * one skipped descriptor per 4K page. - */ - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { - u32 ndesc_skipped = - ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); - u32 dma_len; - - while (ndesc_skipped) { - dma_len = ndesc_skipped * sizeof(struct ath_desc); - dd->dd_desc_len += dma_len; - - ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); - }; - } - - /* allocate descriptors */ - dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, - &dd->dd_desc_paddr, GFP_KERNEL); - if (dd->dd_desc == NULL) { - error = -ENOMEM; - goto fail; - } - ds = dd->dd_desc; - DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - name, ds, (u32) dd->dd_desc_len, - ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); - - /* allocate buffers */ - bsize = sizeof(struct ath_buf) * nbuf; - bf = kzalloc(bsize, GFP_KERNEL); - if (bf == NULL) { - error = -ENOMEM; - goto fail2; - } - dd->dd_bufptr = bf; - - for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(dd, ds); - - if (!(sc->sc_ah->caps.hw_caps & - ATH9K_HW_CAP_4KB_SPLITTRANS)) { - /* - * Skip descriptor addresses which can cause 4KB - * boundary crossing (addr + length) with a 32 dword - * descriptor fetch. - */ - while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { - ASSERT((caddr_t) bf->bf_desc < - ((caddr_t) dd->dd_desc + - dd->dd_desc_len)); - - ds += ndesc; - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(dd, ds); - } - } - list_add_tail(&bf->list, head); - } - return 0; -fail2: - dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, - dd->dd_desc_paddr); -fail: - memset(dd, 0, sizeof(*dd)); - return error; -#undef ATH_DESC_4KB_BOUND_CHECK -#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED -#undef DS2PHYS -} - -void ath_descdma_cleanup(struct ath_softc *sc, - struct ath_descdma *dd, - struct list_head *head) -{ - dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, - dd->dd_desc_paddr); - - INIT_LIST_HEAD(head); - kfree(dd->dd_bufptr); - memset(dd, 0, sizeof(*dd)); -} - -int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case 0: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO]; - break; - case 1: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI]; - break; - case 2: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; - break; - case 3: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK]; - break; - default: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; - break; - } - - return qnum; -} - -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case ATH9K_WME_AC_VO: - qnum = 0; - break; - case ATH9K_WME_AC_VI: - qnum = 1; - break; - case ATH9K_WME_AC_BE: - qnum = 2; - break; - case ATH9K_WME_AC_BK: - qnum = 3; - break; - default: - qnum = -1; - break; - } - - return qnum; -} - -/* XXX: Remove me once we don't depend on ath9k_channel for all - * this redundant data */ -void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *ichan) -{ - struct ieee80211_channel *chan = hw->conf.channel; - struct ieee80211_conf *conf = &hw->conf; - - ichan->channel = chan->center_freq; - ichan->chan = chan; - - if (chan->band == IEEE80211_BAND_2GHZ) { - ichan->chanmode = CHANNEL_G; - ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; - } else { - ichan->chanmode = CHANNEL_A; - ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; - } - - sc->tx_chan_width = ATH9K_HT_MACMODE_20; - - if (conf_is_ht(conf)) { - if (conf_is_ht40(conf)) - sc->tx_chan_width = ATH9K_HT_MACMODE_2040; - - ichan->chanmode = ath_get_extchanmode(sc, chan, - conf->channel_type); - } -} - -/**********************/ -/* mac80211 callbacks */ -/**********************/ - -static int ath9k_start(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel *init_channel; - int r, pos; - - DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " - "initial channel: %d MHz\n", curchan->center_freq); - - mutex_lock(&sc->mutex); - - if (ath9k_wiphy_started(sc)) { - if (sc->chan_idx == curchan->hw_value) { - /* - * Already on the operational channel, the new wiphy - * can be marked active. - */ - aphy->state = ATH_WIPHY_ACTIVE; - ieee80211_wake_queues(hw); - } else { - /* - * Another wiphy is on another channel, start the new - * wiphy in paused state. - */ - aphy->state = ATH_WIPHY_PAUSED; - ieee80211_stop_queues(hw); - } - mutex_unlock(&sc->mutex); - return 0; - } - aphy->state = ATH_WIPHY_ACTIVE; - - /* setup initial channel */ - - pos = curchan->hw_value; - - sc->chan_idx = pos; - init_channel = &sc->sc_ah->channels[pos]; - ath9k_update_ichannel(sc, hw, init_channel); - - /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(sc->sc_ah, 0); - - /* - * The basic interface to setting the hardware in a good - * state is ``reset''. On return the hardware is known to - * be powered up and with interrupts disabled. This must - * be followed by initialization of the appropriate bits - * and then setup of the interrupt mask. - */ - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(sc->sc_ah, init_channel, false); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u " - "(freq %u MHz)\n", r, - curchan->center_freq); - spin_unlock_bh(&sc->sc_resetlock); - goto mutex_unlock; - } - spin_unlock_bh(&sc->sc_resetlock); - - /* - * This is needed only to setup initial state - * but it's best done after a reset. - */ - ath_update_txpow(sc); - - /* - * Setup the hardware after reset: - * The receive engine is set going. - * Frame transmit is handled entirely - * in the frame output path; there's nothing to do - * here except setup the interrupt mask. - */ - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); - r = -EIO; - goto mutex_unlock; - } - - /* Setup our intr mask. */ - sc->imask = ATH9K_INT_RX | ATH9K_INT_TX - | ATH9K_INT_RXEOL | ATH9K_INT_RXORN - | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT) - sc->imask |= ATH9K_INT_GTT; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) - sc->imask |= ATH9K_INT_CST; - - ath_cache_conf_rate(sc, &hw->conf); - - sc->sc_flags &= ~SC_OP_INVALID; - - /* Disable BMISS interrupt when we're not associated */ - sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - ieee80211_wake_queues(hw); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - r = ath_start_rfkill_poll(sc); -#endif - -mutex_unlock: - mutex_unlock(&sc->mutex); - - return r; -} - -static int ath9k_tx(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_tx_control txctl; - int hdrlen, padsize; - - if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { - printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " - "%d\n", wiphy_name(hw->wiphy), aphy->state); - goto exit; - } - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - if (hdrlen & 3) { - padsize = hdrlen % 4; - if (skb_headroom(skb) < padsize) - return -1; - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, hdrlen); - } - - /* Check if a tx queue is available */ - - txctl.txq = ath_test_get_txq(sc, skb); - if (!txctl.txq) - goto exit; - - DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n"); - goto exit; - } - - return 0; -exit: - dev_kfree_skb_any(skb); - return 0; -} - -static void ath9k_stop(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - aphy->state = ATH_WIPHY_INACTIVE; - - if (sc->sc_flags & SC_OP_INVALID) { - DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); - return; - } - - mutex_lock(&sc->mutex); - - ieee80211_stop_queues(hw); - - if (ath9k_wiphy_started(sc)) { - mutex_unlock(&sc->mutex); - return; /* another wiphy still in use */ - } - - /* make sure h/w will not generate any interrupt - * before setting the invalid flag. */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); - - if (!(sc->sc_flags & SC_OP_INVALID)) { - ath_drain_all_txq(sc, false); - ath_stoprecv(sc); - ath9k_hw_phy_disable(sc->sc_ah); - } else - sc->rx.rxlink = NULL; - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); -#endif - /* disable HAL and put h/w to sleep */ - ath9k_hw_disable(sc->sc_ah); - ath9k_hw_configpcipowersave(sc->sc_ah, 1); - - sc->sc_flags |= SC_OP_INVALID; - - mutex_unlock(&sc->mutex); - - DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n"); -} - -static int ath9k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_vif *avp = (void *)conf->vif->drv_priv; - enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; - int ret = 0; - - mutex_lock(&sc->mutex); - - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && - sc->nvifs > 0) { - ret = -ENOBUFS; - goto out; - } - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - ic_opmode = NL80211_IFTYPE_STATION; - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - if (sc->nbcnvifs >= ATH_BCBUF) { - ret = -ENOBUFS; - goto out; - } - ic_opmode = conf->type; - break; - default: - DPRINTF(sc, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", conf->type); - ret = -EOPNOTSUPP; - goto out; - } - - DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); - - /* Set the VIF opmode */ - avp->av_opmode = ic_opmode; - avp->av_bslot = -1; - - sc->nvifs++; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - ath9k_set_bssid_mask(hw); - - if (sc->nvifs > 1) - goto out; /* skip global settings for secondary vif */ - - if (ic_opmode == NL80211_IFTYPE_AP) { - ath9k_hw_set_tsfadjust(sc->sc_ah, 1); - sc->sc_flags |= SC_OP_TSF_RESET; - } - - /* Set the device opmode */ - sc->sc_ah->opmode = ic_opmode; - - /* - * Enable MIB interrupts when there are hardware phy counters. - * Note we only do this (at the moment) for station mode. - */ - if ((conf->type == NL80211_IFTYPE_STATION) || - (conf->type == NL80211_IFTYPE_ADHOC) || - (conf->type == NL80211_IFTYPE_MESH_POINT)) { - if (ath9k_hw_phycounters(sc->sc_ah)) - sc->imask |= ATH9K_INT_MIB; - sc->imask |= ATH9K_INT_TSFOOR; - } - - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - if (conf->type == NL80211_IFTYPE_AP) { - /* TODO: is this a suitable place to start ANI for AP mode? */ - /* Start ANI */ - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); - } - -out: - mutex_unlock(&sc->mutex); - return ret; -} - -static void ath9k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_vif *avp = (void *)conf->vif->drv_priv; - int i; - - DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); - - mutex_lock(&sc->mutex); - - /* Stop ANI */ - del_timer_sync(&sc->ani.timer); - - /* Reclaim beacon resources */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || - (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - ath_beacon_return(sc, avp); - } - - sc->sc_flags &= ~SC_OP_BEACONS; - - for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - if (sc->beacon.bslot[i] == conf->vif) { - printk(KERN_DEBUG "%s: vif had allocated beacon " - "slot\n", __func__); - sc->beacon.bslot[i] = NULL; - sc->beacon.bslot_aphy[i] = NULL; - } - } - - sc->nvifs--; - - mutex_unlock(&sc->mutex); -} - -static int ath9k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ieee80211_conf *conf = &hw->conf; - struct ath_hw *ah = sc->sc_ah; - - mutex_lock(&sc->mutex); - - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) { - if (!(ah->caps.hw_caps & - ATH9K_HW_CAP_AUTOSLEEP)) { - if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { - sc->imask |= ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); - } - ath9k_hw_setrxabort(sc->sc_ah, 1); - } - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); - } else { - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - if (!(ah->caps.hw_caps & - ATH9K_HW_CAP_AUTOSLEEP)) { - ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; - if (sc->imask & ATH9K_INT_TIM_TIMER) { - sc->imask &= ~ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); - } - } - } - } - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - struct ieee80211_channel *curchan = hw->conf.channel; - int pos = curchan->hw_value; - - aphy->chan_idx = pos; - aphy->chan_is_ht = conf_is_ht(conf); - - if (aphy->state == ATH_WIPHY_SCAN || - aphy->state == ATH_WIPHY_ACTIVE) - ath9k_wiphy_pause_all_forced(sc, aphy); - else { - /* - * Do not change operational channel based on a paused - * wiphy changes. - */ - goto skip_chan_change; - } - - DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); - - /* XXX: remove me eventualy */ - ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); - - ath_update_chainmask(sc, conf_is_ht(conf)); - - if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { - DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); - mutex_unlock(&sc->mutex); - return -EINVAL; - } - } - -skip_chan_change: - if (changed & IEEE80211_CONF_CHANGE_POWER) - sc->config.txpowlimit = 2 * conf->power_level; - - /* - * The HW TSF has to be reset when the beacon interval changes. - * We set the flag here, and ath_beacon_config_ap() would take this - * into account when it gets called through the subsequent - * config_interface() call - with IFCC_BEACON in the changed field. - */ - - if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - sc->sc_flags |= SC_OP_TSF_RESET; - - mutex_unlock(&sc->mutex); - - return 0; -} - -static int ath9k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; - struct ath_vif *avp = (void *)vif->drv_priv; - u32 rfilt = 0; - int error, i; - - mutex_lock(&sc->mutex); - - /* TODO: Need to decide which hw opmode to use for multi-interface - * cases */ - if (vif->type == NL80211_IFTYPE_AP && - ah->opmode != NL80211_IFTYPE_AP) { - ah->opmode = NL80211_IFTYPE_STATION; - ath9k_hw_setopmode(ah); - memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - /* Request full reset to get hw opmode changed properly */ - sc->sc_flags |= SC_OP_FULL_RESET; - } - - if ((conf->changed & IEEE80211_IFCC_BSSID) && - !is_zero_ether_addr(conf->bssid)) { - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - /* Set BSSID */ - memcpy(sc->curbssid, conf->bssid, ETH_ALEN); - memcpy(avp->bssid, conf->bssid, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - - /* Set aggregation protection mode parameters */ - sc->config.ath_aggr_prot = 0; - - DPRINTF(sc, ATH_DBG_CONFIG, - "RX filter 0x%x bssid %pM aid 0x%x\n", - rfilt, sc->curbssid, sc->curaid); - - /* need to reconfigure the beacon */ - sc->sc_flags &= ~SC_OP_BEACONS ; - - break; - default: - break; - } - } - - if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((conf->changed & IEEE80211_IFCC_BEACON) || - (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && - conf->enable_beacon)) { - /* - * Allocate and setup the beacon frame. - * - * Stop any previous beacon DMA. This may be - * necessary, for example, when an ibss merge - * causes reconfiguration; we may be called - * with beacon transmission active. - */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - error = ath_beacon_alloc(aphy, vif); - if (error != 0) { - mutex_unlock(&sc->mutex); - return error; - } - - ath_beacon_config(sc, vif); - } - } - - /* Check for WLAN_CAPABILITY_PRIVACY ? */ - if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { - for (i = 0; i < IEEE80211_WEP_NKID; i++) - if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) - ath9k_hw_keysetmac(sc->sc_ah, - (u16)i, - sc->curbssid); - } - - /* Only legacy IBSS for now */ - if (vif->type == NL80211_IFTYPE_ADHOC) - ath_update_chainmask(sc, 0); - - mutex_unlock(&sc->mutex); - - return 0; -} - -#define SUPPORTED_FILTERS \ - (FIF_PROMISC_IN_BSS | \ - FIF_ALLMULTI | \ - FIF_CONTROL | \ - FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC | \ - FIF_FCSFAIL) - -/* FIXME: sc->sc_full_reset ? */ -static void ath9k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_mc_list *mclist) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - u32 rfilt; - - changed_flags &= SUPPORTED_FILTERS; - *total_flags &= SUPPORTED_FILTERS; - - sc->rx.rxfilter = *total_flags; - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(sc->sc_ah, rfilt); - - DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter); -} - -static void ath9k_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - switch (cmd) { - case STA_NOTIFY_ADD: - ath_node_attach(sc, sta); - break; - case STA_NOTIFY_REMOVE: - ath_node_detach(sc, sta); - break; - default: - break; - } -} - -static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath9k_tx_queue_info qi; - int ret = 0, qnum; - - if (queue >= WME_NUM_AC) - return 0; - - mutex_lock(&sc->mutex); - - memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); - - qi.tqi_aifs = params->aifs; - qi.tqi_cwmin = params->cw_min; - qi.tqi_cwmax = params->cw_max; - qi.tqi_burstTime = params->txop; - qnum = ath_get_hal_qnum(queue, sc); - - DPRINTF(sc, ATH_DBG_CONFIG, - "Configure tx [queue/halq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); - - ret = ath_txq_update(sc, qnum, &qi); - if (ret) - DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n"); - - mutex_unlock(&sc->mutex); - - return ret; -} - -static int ath9k_set_key(struct ieee80211_hw *hw, - enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int ret = 0; - - if (modparam_nohwcrypt) - return -ENOSPC; - - mutex_lock(&sc->mutex); - ath9k_ps_wakeup(sc); - DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); - - switch (cmd) { - case SET_KEY: - ret = ath_key_config(sc, vif, sta, key); - if (ret >= 0) { - key->hw_key_idx = ret; - /* push IV and Michael MIC generation to stack */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (key->alg == ALG_TKIP) - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; - ret = 0; - } - break; - case DISABLE_KEY: - ath_key_delete(sc, key); - break; - default: - ret = -EINVAL; - } - - ath9k_ps_restore(sc); - mutex_unlock(&sc->mutex); - - return ret; -} - -static void ath9k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - sc->sc_flags |= SC_OP_PREAMBLE_SHORT; - else - sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && - hw->conf.channel->band != IEEE80211_BAND_5GHZ) - sc->sc_flags |= SC_OP_PROTECT_ENABLE; - else - sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; - } - - if (changed & BSS_CHANGED_ASSOC) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", - bss_conf->assoc); - ath9k_bss_assoc_info(sc, vif, bss_conf); - } - - mutex_unlock(&sc->mutex); -} - -static u64 ath9k_get_tsf(struct ieee80211_hw *hw) -{ - u64 tsf; - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - tsf = ath9k_hw_gettsf64(sc->sc_ah); - mutex_unlock(&sc->mutex); - - return tsf; -} - -static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - ath9k_hw_settsf64(sc->sc_ah, tsf); - mutex_unlock(&sc->mutex); -} - -static void ath9k_reset_tsf(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - ath9k_hw_reset_tsf(sc->sc_ah); - mutex_unlock(&sc->mutex); -} - -static int ath9k_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int ret = 0; - - switch (action) { - case IEEE80211_AMPDU_RX_START: - if (!(sc->sc_flags & SC_OP_RXAGGR)) - ret = -ENOTSUPP; - break; - case IEEE80211_AMPDU_RX_STOP: - break; - case IEEE80211_AMPDU_TX_START: - ret = ath_tx_aggr_start(sc, sta, tid, ssn); - if (ret < 0) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to start TX aggregation\n"); - else - ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); - break; - case IEEE80211_AMPDU_TX_STOP: - ret = ath_tx_aggr_stop(sc, sta, tid); - if (ret < 0) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to stop TX aggregation\n"); - - ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - ath_tx_aggr_resume(sc, sta, tid); - break; - default: - DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); - } - - return ret; -} - -static void ath9k_sw_scan_start(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - if (ath9k_wiphy_scanning(sc)) { - printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the " - "same time\n"); - /* - * Do not allow the concurrent scanning state for now. This - * could be improved with scanning control moved into ath9k. - */ - return; - } - - aphy->state = ATH_WIPHY_SCAN; - ath9k_wiphy_pause_all_forced(sc, aphy); - - mutex_lock(&sc->mutex); - sc->sc_flags |= SC_OP_SCANNING; - mutex_unlock(&sc->mutex); -} - -static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - aphy->state = ATH_WIPHY_ACTIVE; - sc->sc_flags &= ~SC_OP_SCANNING; - mutex_unlock(&sc->mutex); -} - -struct ieee80211_ops ath9k_ops = { - .tx = ath9k_tx, - .start = ath9k_start, - .stop = ath9k_stop, - .add_interface = ath9k_add_interface, - .remove_interface = ath9k_remove_interface, - .config = ath9k_config, - .config_interface = ath9k_config_interface, - .configure_filter = ath9k_configure_filter, - .sta_notify = ath9k_sta_notify, - .conf_tx = ath9k_conf_tx, - .bss_info_changed = ath9k_bss_info_changed, - .set_key = ath9k_set_key, - .get_tsf = ath9k_get_tsf, - .set_tsf = ath9k_set_tsf, - .reset_tsf = ath9k_reset_tsf, - .ampdu_action = ath9k_ampdu_action, - .sw_scan_start = ath9k_sw_scan_start, - .sw_scan_complete = ath9k_sw_scan_complete, -}; - -static struct { - u32 version; - const char * name; -} ath_mac_bb_names[] = { - { AR_SREV_VERSION_5416_PCI, "5416" }, - { AR_SREV_VERSION_5416_PCIE, "5418" }, - { AR_SREV_VERSION_9100, "9100" }, - { AR_SREV_VERSION_9160, "9160" }, - { AR_SREV_VERSION_9280, "9280" }, - { AR_SREV_VERSION_9285, "9285" } -}; - -static struct { - u16 version; - const char * name; -} ath_rf_names[] = { - { 0, "5133" }, - { AR_RAD5133_SREV_MAJOR, "5133" }, - { AR_RAD5122_SREV_MAJOR, "5122" }, - { AR_RAD2133_SREV_MAJOR, "2133" }, - { AR_RAD2122_SREV_MAJOR, "2122" } -}; - -/* - * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. - */ -const char * -ath_mac_bb_name(u32 mac_bb_version) -{ - int i; - - for (i=0; i -#include -#include "ath9k.h" - -static struct pci_device_id ath_pci_id_table[] __devinitdata = { - { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ - { 0 } -}; - -/* return bus cachesize in 4B word units */ -static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) -{ - u8 u8tmp; - - pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, - (u8 *)&u8tmp); - *csz = (int)u8tmp; - - /* - * This check was put in to avoid "unplesant" consequences if - * the bootrom has not fully initialized all PCI devices. - * Sometimes the cache line size register is not set - */ - - if (*csz == 0) - *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ -} - -static void ath_pci_cleanup(struct ath_softc *sc) -{ - struct pci_dev *pdev = to_pci_dev(sc->dev); - - pci_iounmap(pdev, sc->mem); - pci_disable_device(pdev); - pci_release_region(pdev, 0); -} - -static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) -{ - (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); - - if (!ath9k_hw_wait(ah, - AR_EEPROM_STATUS_DATA, - AR_EEPROM_STATUS_DATA_BUSY | - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, - AH_WAIT_TIMEOUT)) { - return false; - } - - *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), - AR_EEPROM_STATUS_DATA_VAL); - - return true; -} - -static struct ath_bus_ops ath_pci_bus_ops = { - .read_cachesize = ath_pci_read_cachesize, - .cleanup = ath_pci_cleanup, - .eeprom_read = ath_pci_eeprom_read, -}; - -static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath_wiphy *aphy; - struct ath_softc *sc; - struct ieee80211_hw *hw; - u8 csz; - int ret = 0; - struct ath_hw *ah; - - if (pci_enable_device(pdev)) - return -EIO; - - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - - if (ret) { - printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); - goto bad; - } - - ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - - if (ret) { - printk(KERN_ERR "ath9k: 32-bit DMA consistent " - "DMA enable failed\n"); - goto bad; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES / sizeof(u32); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - pci_set_master(pdev); - - ret = pci_request_region(pdev, 0, "ath9k"); - if (ret) { - dev_err(&pdev->dev, "PCI memory region reserve error\n"); - ret = -ENODEV; - goto bad; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - printk(KERN_ERR "PCI memory map error\n") ; - ret = -EIO; - goto bad1; - } - - hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + - sizeof(struct ath_softc), &ath9k_ops); - if (hw == NULL) { - printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); - goto bad2; - } - - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); - - aphy = hw->priv; - sc = (struct ath_softc *) (aphy + 1); - aphy->sc = sc; - aphy->hw = hw; - sc->pri_wiphy = aphy; - sc->hw = hw; - sc->dev = &pdev->dev; - sc->mem = mem; - sc->bus_ops = &ath_pci_bus_ops; - - if (ath_attach(id->device, sc) != 0) { - ret = -ENODEV; - goto bad3; - } - - /* setup interrupt service routine */ - - if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { - printk(KERN_ERR "%s: request_irq failed\n", - wiphy_name(hw->wiphy)); - ret = -EIO; - goto bad4; - } - - sc->irq = pdev->irq; - - ah = sc->sc_ah; - printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x " - "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev, - (unsigned long)mem, pdev->irq); - - return 0; -bad4: - ath_detach(sc); -bad3: - ieee80211_free_hw(hw); -bad2: - pci_iounmap(pdev, mem); -bad1: - pci_release_region(pdev, 0); -bad: - pci_disable_device(pdev); - return ret; -} - -static void ath_pci_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - ath_cleanup(sc); -} - -#ifdef CONFIG_PM - -static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); -#endif - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int ath_pci_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int err; - - err = pci_enable_device(pdev); - if (err) - return err; - pci_restore_state(pdev); - - /* Enable LED */ - ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - /* - * check the h/w rfkill state on resume - * and start the rfkill poll timer - */ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - queue_delayed_work(sc->hw->workqueue, - &sc->rf_kill.rfkill_poll, 0); -#endif - - return 0; -} - -#endif /* CONFIG_PM */ - -MODULE_DEVICE_TABLE(pci, ath_pci_id_table); - -static struct pci_driver ath_pci_driver = { - .name = "ath9k", - .id_table = ath_pci_id_table, - .probe = ath_pci_probe, - .remove = ath_pci_remove, -#ifdef CONFIG_PM - .suspend = ath_pci_suspend, - .resume = ath_pci_resume, -#endif /* CONFIG_PM */ -}; - -int ath_pci_init(void) -{ - return pci_register_driver(&ath_pci_driver); -} - -void ath_pci_exit(void) -{ - pci_unregister_driver(&ath_pci_driver); -} diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c deleted file mode 100644 index 5ec9ce91d979..000000000000 --- a/drivers/net/wireless/ath9k/phy.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * 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 "ath9k.h" - -void -ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, - int regWrites) -{ - REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); -} - -bool -ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u32 channelSel = 0; - u32 bModeSynth = 0; - u32 aModeRefSel = 0; - u32 reg32 = 0; - u16 freq; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - if (freq < 4800) { - u32 txctl; - - if (((freq - 2192) % 5) == 0) { - channelSel = ((freq - 672) * 2 - 3040) / 10; - bModeSynth = 0; - } else if (((freq - 2224) % 5) == 0) { - channelSel = ((freq - 704) * 2 - 3040) / 10; - bModeSynth = 1; - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return false; - } - - channelSel = (channelSel << 2) & 0xff; - channelSel = ath9k_hw_reverse_bits(channelSel, 8); - - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - - } else if ((freq % 20) == 0 && freq >= 5120) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 10) == 0) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) - aModeRefSel = ath9k_hw_reverse_bits(2, 2); - else - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 5) == 0) { - channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return false; - } - - reg32 = - (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | - (1 << 5) | 0x1; - - REG_WRITE(ah, AR_PHY(0x37), reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return true; -} - -bool -ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u16 bMode, fracMode, aModeRefSel = 0; - u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; - struct chan_centers centers; - u32 refDivA = 24; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); - reg32 &= 0xc0000000; - - if (freq < 4800) { - u32 txctl; - - bMode = 1; - fracMode = 1; - aModeRefSel = 0; - channelSel = (freq * 0x10000) / 15; - - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - } else { - bMode = 0; - fracMode = 0; - - switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { - case 0: - if ((freq % 20) == 0) { - aModeRefSel = 3; - } else if ((freq % 10) == 0) { - aModeRefSel = 2; - } - if (aModeRefSel) - break; - case 1: - default: - aModeRefSel = 0; - fracMode = 1; - refDivA = 1; - channelSel = (freq * 0x8000) / 15; - - REG_RMW_FIELD(ah, AR_AN_SYNTH9, - AR_AN_SYNTH9_REFDIVA, refDivA); - - } - - if (!fracMode) { - ndiv = (freq * (refDivA >> aModeRefSel)) / 60; - channelSel = ndiv & 0x1ff; - channelFrac = (ndiv & 0xfffffe00) * 2; - channelSel = (channelSel << 17) | channelFrac; - } - } - - reg32 = reg32 | - (bMode << 29) | - (fracMode << 28) | (aModeRefSel << 26) | (channelSel); - - REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return true; -} - -static void -ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, - u32 numBits, u32 firstBit, - u32 column) -{ - u32 tmp32, mask, arrayEntry, lastBit; - int32_t bitPosition, bitsLeft; - - tmp32 = ath9k_hw_reverse_bits(reg32, numBits); - arrayEntry = (firstBit - 1) / 8; - bitPosition = (firstBit - 1) % 8; - bitsLeft = numBits; - while (bitsLeft > 0) { - lastBit = (bitPosition + bitsLeft > 8) ? - 8 : bitPosition + bitsLeft; - mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << - (column * 8); - rfBuf[arrayEntry] &= ~mask; - rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << - (column * 8)) & mask; - bitsLeft -= 8 - bitPosition; - tmp32 = tmp32 >> (8 - bitPosition); - bitPosition = 0; - arrayEntry++; - } -} - -bool -ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, - u16 modesIndex) -{ - u32 eepMinorRev; - u32 ob5GHz = 0, db5GHz = 0; - u32 ob2GHz = 0, db2GHz = 0; - int regWrites = 0; - - if (AR_SREV_9280_10_OR_LATER(ah)) - return true; - - eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); - - RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); - - RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); - - RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); - - RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, - modesIndex); - { - int i; - for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { - ah->analogBank6Data[i] = - INI_RA(&ah->iniBank6TPC, i, modesIndex); - } - } - - if (eepMinorRev >= 2) { - if (IS_CHAN_2GHZ(chan)) { - ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); - db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - ob2GHz, 3, 197, 0); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - db2GHz, 3, 194, 0); - } else { - ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); - db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - ob5GHz, 3, 203, 0); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - db5GHz, 3, 200, 0); - } - } - - RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); - - REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, - regWrites); - - return true; -} - -void -ath9k_hw_rfdetach(struct ath_hw *ah) -{ - if (ah->analogBank0Data != NULL) { - kfree(ah->analogBank0Data); - ah->analogBank0Data = NULL; - } - if (ah->analogBank1Data != NULL) { - kfree(ah->analogBank1Data); - ah->analogBank1Data = NULL; - } - if (ah->analogBank2Data != NULL) { - kfree(ah->analogBank2Data); - ah->analogBank2Data = NULL; - } - if (ah->analogBank3Data != NULL) { - kfree(ah->analogBank3Data); - ah->analogBank3Data = NULL; - } - if (ah->analogBank6Data != NULL) { - kfree(ah->analogBank6Data); - ah->analogBank6Data = NULL; - } - if (ah->analogBank6TPCData != NULL) { - kfree(ah->analogBank6TPCData); - ah->analogBank6TPCData = NULL; - } - if (ah->analogBank7Data != NULL) { - kfree(ah->analogBank7Data); - ah->analogBank7Data = NULL; - } - if (ah->addac5416_21 != NULL) { - kfree(ah->addac5416_21); - ah->addac5416_21 = NULL; - } - if (ah->bank6Temp != NULL) { - kfree(ah->bank6Temp); - ah->bank6Temp = NULL; - } -} - -bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) -{ - if (!AR_SREV_9280_10_OR_LATER(ah)) { - ah->analogBank0Data = - kzalloc((sizeof(u32) * - ah->iniBank0.ia_rows), GFP_KERNEL); - ah->analogBank1Data = - kzalloc((sizeof(u32) * - ah->iniBank1.ia_rows), GFP_KERNEL); - ah->analogBank2Data = - kzalloc((sizeof(u32) * - ah->iniBank2.ia_rows), GFP_KERNEL); - ah->analogBank3Data = - kzalloc((sizeof(u32) * - ah->iniBank3.ia_rows), GFP_KERNEL); - ah->analogBank6Data = - kzalloc((sizeof(u32) * - ah->iniBank6.ia_rows), GFP_KERNEL); - ah->analogBank6TPCData = - kzalloc((sizeof(u32) * - ah->iniBank6TPC.ia_rows), GFP_KERNEL); - ah->analogBank7Data = - kzalloc((sizeof(u32) * - ah->iniBank7.ia_rows), GFP_KERNEL); - - if (ah->analogBank0Data == NULL - || ah->analogBank1Data == NULL - || ah->analogBank2Data == NULL - || ah->analogBank3Data == NULL - || ah->analogBank6Data == NULL - || ah->analogBank6TPCData == NULL - || ah->analogBank7Data == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate RF banks\n"); - *status = -ENOMEM; - return false; - } - - ah->addac5416_21 = - kzalloc((sizeof(u32) * - ah->iniAddac.ia_rows * - ah->iniAddac.ia_columns), GFP_KERNEL); - if (ah->addac5416_21 == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate addac5416_21\n"); - *status = -ENOMEM; - return false; - } - - ah->bank6Temp = - kzalloc((sizeof(u32) * - ah->iniBank6.ia_rows), GFP_KERNEL); - if (ah->bank6Temp == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate bank6Temp\n"); - *status = -ENOMEM; - return false; - } - } - - return true; -} - -void -ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int i, regWrites = 0; - u32 bank6SelMask; - u32 *bank6Temp = ah->bank6Temp; - - switch (ah->diversity_control) { - case ATH9K_ANT_FIXED_A: - bank6SelMask = - (ah-> - antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 : - REDUCE_CHAIN_1; - break; - case ATH9K_ANT_FIXED_B: - bank6SelMask = - (ah-> - antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 : - REDUCE_CHAIN_0; - break; - case ATH9K_ANT_VARIABLE: - return; - break; - default: - return; - break; - } - - for (i = 0; i < ah->iniBank6.ia_rows; i++) - bank6Temp[i] = ah->analogBank6Data[i]; - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); - - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); - - REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); -#ifdef ALTER_SWITCH - REG_WRITE(ah, PHY_SWITCH_CHAIN_0, - (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) - | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); -#endif -} diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h deleted file mode 100644 index 296d0e985f25..000000000000 --- a/drivers/net/wireless/ath9k/phy.h +++ /dev/null @@ -1,576 +0,0 @@ -/* - * 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 PHY_H -#define PHY_H - -bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel - *chan); -bool ath9k_hw_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan); -void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, - u32 freqIndex, int regWrites); -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 modesIndex); -void ath9k_hw_decrease_chain_power(struct ath_hw *ah, - struct ath9k_channel *chan); -bool ath9k_hw_init_rf(struct ath_hw *ah, - int *status); - -#define AR_PHY_BASE 0x9800 -#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) - -#define AR_PHY_TEST 0x9800 -#define PHY_AGC_CLR 0x10000000 -#define RFSILENT_BB 0x00002000 - -#define AR_PHY_TURBO 0x9804 -#define AR_PHY_FC_TURBO_MODE 0x00000001 -#define AR_PHY_FC_TURBO_SHORT 0x00000002 -#define AR_PHY_FC_DYN2040_EN 0x00000004 -#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 -#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 -#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 -#define AR_PHY_FC_HT_EN 0x00000040 -#define AR_PHY_FC_SHORT_GI_40 0x00000080 -#define AR_PHY_FC_WALSH 0x00000100 -#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 -#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800 - -#define AR_PHY_TEST2 0x9808 - -#define AR_PHY_TIMING2 0x9810 -#define AR_PHY_TIMING3 0x9814 -#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 -#define AR_PHY_TIMING3_DSC_MAN_S 17 -#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 -#define AR_PHY_TIMING3_DSC_EXP_S 13 - -#define AR_PHY_CHIP_ID 0x9818 -#define AR_PHY_CHIP_ID_REV_0 0x80 -#define AR_PHY_CHIP_ID_REV_1 0x81 -#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 - -#define AR_PHY_ACTIVE 0x981C -#define AR_PHY_ACTIVE_EN 0x00000001 -#define AR_PHY_ACTIVE_DIS 0x00000000 - -#define AR_PHY_RF_CTL2 0x9824 -#define AR_PHY_TX_END_DATA_START 0x000000FF -#define AR_PHY_TX_END_DATA_START_S 0 -#define AR_PHY_TX_END_PA_ON 0x0000FF00 -#define AR_PHY_TX_END_PA_ON_S 8 - -#define AR_PHY_RF_CTL3 0x9828 -#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 -#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 - -#define AR_PHY_ADC_CTL 0x982C -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 -#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 -#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 -#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 - -#define AR_PHY_ADC_SERIAL_CTL 0x9830 -#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 -#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 - -#define AR_PHY_RF_CTL4 0x9834 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 - -#define AR_PHY_TSTDAC_CONST 0x983c - -#define AR_PHY_SETTLING 0x9844 -#define AR_PHY_SETTLING_SWITCH 0x00003F80 -#define AR_PHY_SETTLING_SWITCH_S 7 - -#define AR_PHY_RXGAIN 0x9848 -#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 -#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 -#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 -#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 - -#define AR_PHY_DESIRED_SZ 0x9850 -#define AR_PHY_DESIRED_SZ_ADC 0x000000FF -#define AR_PHY_DESIRED_SZ_ADC_S 0 -#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 -#define AR_PHY_DESIRED_SZ_PGA_S 8 -#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 -#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 - -#define AR_PHY_FIND_SIG 0x9858 -#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 -#define AR_PHY_FIND_SIG_FIRSTEP_S 12 -#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 -#define AR_PHY_FIND_SIG_FIRPWR_S 18 - -#define AR_PHY_AGC_CTL1 0x985C -#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 -#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 -#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 -#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 - -#define AR_PHY_AGC_CONTROL 0x9860 -#define AR_PHY_AGC_CONTROL_CAL 0x00000001 -#define AR_PHY_AGC_CONTROL_NF 0x00000002 -#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 -#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 -#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 - -#define AR_PHY_CCA 0x9864 -#define AR_PHY_MINCCA_PWR 0x0FF80000 -#define AR_PHY_MINCCA_PWR_S 19 -#define AR_PHY_CCA_THRESH62 0x0007F000 -#define AR_PHY_CCA_THRESH62_S 12 -#define AR9280_PHY_MINCCA_PWR 0x1FF00000 -#define AR9280_PHY_MINCCA_PWR_S 20 -#define AR9280_PHY_CCA_THRESH62 0x000FF000 -#define AR9280_PHY_CCA_THRESH62_S 12 - -#define AR_PHY_SFCORR_LOW 0x986C -#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 - -#define AR_PHY_SFCORR 0x9868 -#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F -#define AR_PHY_SFCORR_M2COUNT_THR_S 0 -#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 -#define AR_PHY_SFCORR_M1_THRESH_S 17 -#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 -#define AR_PHY_SFCORR_M2_THRESH_S 24 - -#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 -#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 -#define AR_PHY_SYNTH_CONTROL 0x9874 -#define AR_PHY_SLEEP_SCAL 0x9878 - -#define AR_PHY_PLL_CTL 0x987c -#define AR_PHY_PLL_CTL_40 0xaa -#define AR_PHY_PLL_CTL_40_5413 0x04 -#define AR_PHY_PLL_CTL_44 0xab -#define AR_PHY_PLL_CTL_44_2133 0xeb -#define AR_PHY_PLL_CTL_40_2133 0xea - -#define AR_PHY_RX_DELAY 0x9914 -#define AR_PHY_SEARCH_START_DELAY 0x9918 -#define AR_PHY_RX_DELAY_DELAY 0x00003FFF - -#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12)) -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 -#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 -#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 - -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 - -#define AR_PHY_TIMING5 0x9924 -#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE -#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 - -#define AR_PHY_POWER_TX_RATE1 0x9934 -#define AR_PHY_POWER_TX_RATE2 0x9938 -#define AR_PHY_POWER_TX_RATE_MAX 0x993c -#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 - -#define AR_PHY_FRAME_CTL 0x9944 -#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 -#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 - -#define AR_PHY_TXPWRADJ 0x994C -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 - -#define AR_PHY_RADAR_EXT 0x9940 -#define AR_PHY_RADAR_EXT_ENA 0x00004000 - -#define AR_PHY_RADAR_0 0x9954 -#define AR_PHY_RADAR_0_ENA 0x00000001 -#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 -#define AR_PHY_RADAR_0_INBAND 0x0000003e -#define AR_PHY_RADAR_0_INBAND_S 1 -#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 -#define AR_PHY_RADAR_0_PRSSI_S 6 -#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 -#define AR_PHY_RADAR_0_HEIGHT_S 12 -#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 -#define AR_PHY_RADAR_0_RRSSI_S 18 -#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 -#define AR_PHY_RADAR_0_FIRPWR_S 24 - -#define AR_PHY_RADAR_1 0x9958 -#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 -#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 -#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 -#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 -#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 -#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 -#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 -#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 -#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 -#define AR_PHY_RADAR_1_MAXLEN 0x000000FF -#define AR_PHY_RADAR_1_MAXLEN_S 0 - -#define AR_PHY_SWITCH_CHAIN_0 0x9960 -#define AR_PHY_SWITCH_COM 0x9964 - -#define AR_PHY_SIGMA_DELTA 0x996C -#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 -#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 -#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 -#define AR_PHY_SIGMA_DELTA_FILT2_S 3 -#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 -#define AR_PHY_SIGMA_DELTA_FILT1_S 8 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 - -#define AR_PHY_RESTART 0x9970 -#define AR_PHY_RESTART_DIV_GC 0x001C0000 -#define AR_PHY_RESTART_DIV_GC_S 18 - -#define AR_PHY_RFBUS_REQ 0x997C -#define AR_PHY_RFBUS_REQ_EN 0x00000001 - -#define AR_PHY_TIMING7 0x9980 -#define AR_PHY_TIMING8 0x9984 -#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF -#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 - -#define AR_PHY_BIN_MASK2_1 0x9988 -#define AR_PHY_BIN_MASK2_2 0x998c -#define AR_PHY_BIN_MASK2_3 0x9990 -#define AR_PHY_BIN_MASK2_4 0x9994 - -#define AR_PHY_BIN_MASK_1 0x9900 -#define AR_PHY_BIN_MASK_2 0x9904 -#define AR_PHY_BIN_MASK_3 0x9908 - -#define AR_PHY_MASK_CTL 0x990c - -#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF -#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 - -#define AR_PHY_TIMING9 0x9998 -#define AR_PHY_TIMING10 0x999c -#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF -#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 - -#define AR_PHY_TIMING11 0x99a0 -#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF -#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 -#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 -#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 -#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 -#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 - -#define AR_PHY_RX_CHAINMASK 0x99a4 -#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) -#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 -#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 -#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac - -#define AR_PHY_EXT_CCA0 0x99b8 -#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF -#define AR_PHY_EXT_CCA0_THRESH62_S 0 - -#define AR_PHY_EXT_CCA 0x99bc -#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 -#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 -#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 -#define AR_PHY_EXT_CCA_THRESH62_S 16 -#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 -#define AR9280_PHY_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_SFCORR_EXT 0x99c0 -#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F -#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 -#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 -#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 -#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 - -#define AR_PHY_HALFGI 0x99D0 -#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 -#define AR_PHY_HALFGI_DSC_MAN_S 4 -#define AR_PHY_HALFGI_DSC_EXP 0x0000000F -#define AR_PHY_HALFGI_DSC_EXP_S 0 - -#define AR_PHY_CHAN_INFO_MEMORY 0x99DC -#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 - -#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 - -#define AR_PHY_M_SLEEP 0x99f0 -#define AR_PHY_REFCLKDLY 0x99f4 -#define AR_PHY_REFCLKPD 0x99f8 - -#define AR_PHY_CALMODE 0x99f0 - -#define AR_PHY_CALMODE_IQ 0x00000000 -#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 -#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 -#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 - -#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) - -#define AR_PHY_CURRENT_RSSI 0x9c1c -#define AR9280_PHY_CURRENT_RSSI 0x9c3c - -#define AR_PHY_RFBUS_GRANT 0x9C20 -#define AR_PHY_RFBUS_GRANT_EN 0x00000001 - -#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 -#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 - -#define AR_PHY_CHAN_INFO_GAIN 0x9CFC - -#define AR_PHY_MODE 0xA200 -#define AR_PHY_MODE_AR2133 0x08 -#define AR_PHY_MODE_AR5111 0x00 -#define AR_PHY_MODE_AR5112 0x08 -#define AR_PHY_MODE_DYNAMIC 0x04 -#define AR_PHY_MODE_RF2GHZ 0x02 -#define AR_PHY_MODE_RF5GHZ 0x00 -#define AR_PHY_MODE_CCK 0x01 -#define AR_PHY_MODE_OFDM 0x00 -#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 - -#define AR_PHY_CCK_TX_CTRL 0xA204 -#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 - -#define AR_PHY_CCK_DETECT 0xA208 -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 -/* [12:6] settling time for antenna switch */ -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 - -#define AR_PHY_GAIN_2GHZ 0xA20C -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 - -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 - -#define AR_PHY_CCK_RXCTRL4 0xA21C -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 - -#define AR_PHY_DAG_CTRLCCK 0xA228 -#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 - -#define AR_PHY_FORCE_CLKEN_CCK 0xA22C -#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 - -#define AR_PHY_POWER_TX_RATE3 0xA234 -#define AR_PHY_POWER_TX_RATE4 0xA238 - -#define AR_PHY_SCRM_SEQ_XR 0xA23C -#define AR_PHY_HEADER_DETECT_XR 0xA240 -#define AR_PHY_CHIRP_DETECTED_XR 0xA244 -#define AR_PHY_BLUETOOTH 0xA254 - -#define AR_PHY_TPCRG1 0xA258 -#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 -#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 - -#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 -#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 -#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 -#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 -#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 -#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 - -#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 -#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 - -#define AR_PHY_TX_PWRCTRL4 0xa264 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 - -#define AR_PHY_TX_PWRCTRL6_0 0xa270 -#define AR_PHY_TX_PWRCTRL6_1 0xb270 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 - -#define AR_PHY_TX_PWRCTRL7 0xa274 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 - -#define AR_PHY_TX_PWRCTRL9 0xa27C -#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 -#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 - -#define AR_PHY_TX_GAIN_TBL1 0xa300 -#define AR_PHY_TX_GAIN 0x0007F000 -#define AR_PHY_TX_GAIN_S 12 - -#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 -#define AR_PHY_MASK2_M_31_45 0xa3a4 -#define AR_PHY_MASK2_M_16_30 0xa3a8 -#define AR_PHY_MASK2_M_00_15 0xa3ac -#define AR_PHY_MASK2_P_15_01 0xa3b8 -#define AR_PHY_MASK2_P_30_16 0xa3bc -#define AR_PHY_MASK2_P_45_31 0xa3c0 -#define AR_PHY_MASK2_P_61_45 0xa3c4 -#define AR_PHY_SPUR_REG 0x994c - -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 - -#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 -#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 - -#define AR_PHY_PILOT_MASK_01_30 0xa3b0 -#define AR_PHY_PILOT_MASK_31_60 0xa3b4 - -#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 -#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 - -#define AR_PHY_ANALOG_SWAP 0xa268 -#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 - -#define AR_PHY_TPCRG5 0xA26C -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 - -/* Carrier leak calibration control, do it after AGC calibration */ -#define AR_PHY_CL_CAL_CTL 0xA358 -#define AR_PHY_CL_CAL_ENABLE 0x00000002 -#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 - -#define AR_PHY_POWER_TX_RATE5 0xA38C -#define AR_PHY_POWER_TX_RATE6 0xA390 - -#define AR_PHY_CAL_CHAINMASK 0xA39C - -#define AR_PHY_POWER_TX_SUB 0xA3C8 -#define AR_PHY_POWER_TX_RATE7 0xA3CC -#define AR_PHY_POWER_TX_RATE8 0xA3D0 -#define AR_PHY_POWER_TX_RATE9 0xA3D4 - -#define AR_PHY_XPA_CFG 0xA3D8 -#define AR_PHY_FORCE_XPA_CFG 0x000000001 -#define AR_PHY_FORCE_XPA_CFG_S 0 - -#define AR_PHY_CH1_CCA 0xa864 -#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 -#define AR_PHY_CH1_MINCCA_PWR_S 19 -#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 -#define AR9280_PHY_CH1_MINCCA_PWR_S 20 - -#define AR_PHY_CH2_CCA 0xb864 -#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 -#define AR_PHY_CH2_MINCCA_PWR_S 19 - -#define AR_PHY_CH1_EXT_CCA 0xa9bc -#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_CH2_EXT_CCA 0xb9bc -#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 - -#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ - int r; \ - for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ - DO_DELAY(regWr); \ - } \ - } while (0) - -#define ATH9K_IS_MIC_ENABLED(ah) \ - ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) - -#define ANTSWAP_AB 0x0001 -#define REDUCE_CHAIN_0 0x00000050 -#define REDUCE_CHAIN_1 0x00000051 - -#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ - int i; \ - for (i = 0; i < (_iniarray)->ia_rows; i++) \ - (_bank)[i] = INI_RA((_iniarray), i, _col);; \ - } while (0) - -#endif diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c deleted file mode 100644 index a13668b9b6dc..000000000000 --- a/drivers/net/wireless/ath9k/rc.c +++ /dev/null @@ -1,1752 +0,0 @@ -/* - * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2004-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 "ath9k.h" - -static struct ath_rate_table ar5416_11na_ratetable = { - 42, - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, 12, - 0, 2, 1, 0, 0, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 0, 3, 1, 1, 1, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 0x0a, 0x00, 24, - 2, 4, 2, 2, 2, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 0x0e, 0x00, 36, - 2, 6, 2, 3, 3, 3, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 0x09, 0x00, 48, - 4, 10, 3, 4, 4, 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 0x0d, 0x00, 72, - 4, 14, 3, 5, 5, 5, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 4, 20, 3, 6, 6, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 0x0c, 0x00, 108, - 4, 23, 3, 7, 7, 7, 7, 0 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0x80, 0x00, 0, - 0, 2, 3, 8, 24, 8, 24, 3216 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 0x81, 0x00, 1, - 2, 4, 3, 9, 25, 9, 25, 6434 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 0x82, 0x00, 2, - 2, 6, 3, 10, 26, 10, 26, 9650 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 0x83, 0x00, 3, - 4, 10, 3, 11, 27, 11, 27, 12868 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 0x84, 0x00, 4, - 4, 14, 3, 12, 28, 12, 28, 19304 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 0x85, 0x00, 5, - 4, 20, 3, 13, 29, 13, 29, 25740 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 0x86, 0x00, 6, - 4, 23, 3, 14, 30, 14, 30, 28956 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 0x87, 0x00, 7, - 4, 25, 3, 15, 31, 15, 32, 32180 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 0x88, 0x00, - 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 0x89, 0x00, 9, - 2, 4, 3, 17, 34, 17, 34, 12860 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 0x8a, 0x00, 10, - 2, 6, 3, 18, 35, 18, 35, 19300 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 0x8b, 0x00, 11, - 4, 10, 3, 19, 36, 19, 36, 25736 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 0x8c, 0x00, 12, - 4, 14, 3, 20, 37, 20, 37, 38600 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 0x8d, 0x00, 13, - 4, 20, 3, 21, 38, 21, 38, 51472 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 0x8e, 0x00, 14, - 4, 23, 3, 22, 39, 22, 39, 57890 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 0x8f, 0x00, 15, - 4, 25, 3, 23, 40, 23, 41, 64320 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0x80, 0x00, 0, - 0, 2, 3, 8, 24, 24, 24, 6684 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 0x81, 0x00, 1, - 2, 4, 3, 9, 25, 25, 25, 13368 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 0x82, 0x00, 2, - 2, 6, 3, 10, 26, 26, 26, 20052 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 0x83, 0x00, 3, - 4, 10, 3, 11, 27, 27, 27, 26738 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 0x84, 0x00, 4, - 4, 14, 3, 12, 28, 28, 28, 40104 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 0x85, 0x00, 5, - 4, 20, 3, 13, 29, 29, 29, 53476 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 0x86, 0x00, 6, - 4, 23, 3, 14, 30, 30, 30, 60156 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 0x87, 0x00, 7, - 4, 25, 3, 15, 31, 32, 32, 66840 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 0x87, 0x00, 7, - 4, 25, 3, 15, 31, 32, 32, 74200 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 0x88, 0x00, 8, - 0, 2, 3, 16, 33, 33, 33, 13360 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 0x89, 0x00, 9, - 2, 4, 3, 17, 34, 34, 34, 26720 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 0x8a, 0x00, 10, - 2, 6, 3, 18, 35, 35, 35, 40080 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 0x8b, 0x00, 11, - 4, 10, 3, 19, 36, 36, 36, 53440 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 0x8c, 0x00, 12, - 4, 14, 3, 20, 37, 37, 37, 80160 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 0x8d, 0x00, 13, - 4, 20, 3, 21, 38, 38, 38, 106880 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 0x8e, 0x00, 14, - 4, 23, 3, 22, 39, 39, 39, 120240 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 0x8f, 0x00, 15, - 4, 25, 3, 23, 40, 41, 41, 133600 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 0x8f, 0x00, 15, - 4, 25, 3, 23, 40, 41, 41, 148400 }, - }, - 50, /* probe interval */ - 50, /* rssi reduce interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -}; - -/* 4ms frame limit not used for NG mode. The values filled - * for HT are the 64K max aggregate limit */ - -static struct ath_rate_table ar5416_11ng_ratetable = { - 46, - { - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0x1b, 0x00, 2, - 0, 0, 1, 0, 0, 0, 0, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 0x1a, 0x04, 4, - 1, 1, 1, 1, 1, 1, 1, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 0x19, 0x04, 11, - 2, 2, 2, 2, 2, 2, 2, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 0x18, 0x04, 22, - 3, 3, 2, 3, 3, 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, 12, - 4, 2, 1, 4, 4, 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 4, 3, 1, 5, 5, 5, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10100, 0x0a, 0x00, 24, - 6, 4, 1, 6, 6, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 14100, 0x0e, 0x00, 36, - 6, 6, 2, 7, 7, 7, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17700, 0x09, 0x00, 48, - 8, 10, 3, 8, 8, 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23700, 0x0d, 0x00, 72, - 8, 14, 3, 9, 9, 9, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 8, 20, 3, 10, 10, 10, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 30900, 0x0c, 0x00, 108, - 8, 23, 3, 11, 11, 11, 11, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0x80, 0x00, 0, - 4, 2, 3, 12, 28, 12, 28, 3216 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 0x81, 0x00, 1, - 6, 4, 3, 13, 29, 13, 29, 6434 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 0x82, 0x00, 2, - 6, 6, 3, 14, 30, 14, 30, 9650 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 0x83, 0x00, 3, - 8, 10, 3, 15, 31, 15, 31, 12868 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 0x84, 0x00, 4, - 8, 14, 3, 16, 32, 16, 32, 19304 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 0x85, 0x00, 5, - 8, 20, 3, 17, 33, 17, 33, 25740 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 0x86, 0x00, 6, - 8, 23, 3, 18, 34, 18, 34, 28956 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 0x87, 0x00, 7, - 8, 25, 3, 19, 35, 19, 36, 32180 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 0x88, 0x00, 8, - 4, 2, 3, 20, 37, 20, 37, 6430 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 0x89, 0x00, 9, - 6, 4, 3, 21, 38, 21, 38, 12860 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 0x8a, 0x00, 10, - 6, 6, 3, 22, 39, 22, 39, 19300 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 0x8b, 0x00, 11, - 8, 10, 3, 23, 40, 23, 40, 25736 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 0x8c, 0x00, 12, - 8, 14, 3, 24, 41, 24, 41, 38600 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 0x8d, 0x00, 13, - 8, 20, 3, 25, 42, 25, 42, 51472 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 0x8e, 0x00, 14, - 8, 23, 3, 26, 43, 26, 44, 57890 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 0x8f, 0x00, 15, - 8, 25, 3, 27, 44, 27, 45, 64320 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0x80, 0x00, 0, - 8, 2, 3, 12, 28, 28, 28, 6684 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 0x81, 0x00, 1, - 8, 4, 3, 13, 29, 29, 29, 13368 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 0x82, 0x00, 2, - 8, 6, 3, 14, 30, 30, 30, 20052 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 0x83, 0x00, 3, - 8, 10, 3, 15, 31, 31, 31, 26738 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 0x84, 0x00, 4, - 8, 14, 3, 16, 32, 32, 32, 40104 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 0x85, 0x00, 5, - 8, 20, 3, 17, 33, 33, 33, 53476 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 0x86, 0x00, 6, - 8, 23, 3, 18, 34, 34, 34, 60156 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 0x87, 0x00, 7, - 8, 23, 3, 19, 35, 36, 36, 66840 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 0x87, 0x00, 7, - 8, 25, 3, 19, 35, 36, 36, 74200 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 0x88, 0x00, 8, - 8, 2, 3, 20, 37, 37, 37, 13360 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 0x89, 0x00, 9, - 8, 4, 3, 21, 38, 38, 38, 26720 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 0x8a, 0x00, 10, - 8, 6, 3, 22, 39, 39, 39, 40080 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 0x8b, 0x00, 11, - 8, 10, 3, 23, 40, 40, 40, 53440 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 0x8c, 0x00, 12, - 8, 14, 3, 24, 41, 41, 41, 80160 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 0x8d, 0x00, 13, - 8, 20, 3, 25, 42, 42, 42, 106880 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 0x8e, 0x00, 14, - 8, 23, 3, 26, 43, 43, 43, 120240 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 0x8f, 0x00, 15, - 8, 23, 3, 27, 44, 45, 45, 133600 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 0x8f, 0x00, 15, - 8, 25, 3, 27, 44, 45, 45, 148400 }, - }, - 50, /* probe interval */ - 50, /* rssi reduce interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -}; - -static struct ath_rate_table ar5416_11a_ratetable = { - 8, - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, (0x80|12), - 0, 2, 1, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 0, 3, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 0x0a, 0x00, (0x80|24), - 2, 4, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 0x0e, 0x00, 36, - 2, 6, 2, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 0x09, 0x00, (0x80|48), - 4, 10, 3, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 0x0d, 0x00, 72, - 4, 14, 3, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 4, 19, 3, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 0x0c, 0x00, 108, - 4, 23, 3, 7, 0 }, - }, - 50, /* probe interval */ - 50, /* rssi reduce interval */ - 0, /* Phy rates allowed initially */ -}; - -static struct ath_rate_table ar5416_11g_ratetable = { - 12, - { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0x1b, 0x00, 2, - 0, 0, 1, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 0x1a, 0x04, 4, - 1, 1, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 0x19, 0x04, 11, - 2, 2, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 0x18, 0x04, 22, - 3, 3, 2, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, 12, - 4, 2, 1, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 4, 3, 1, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 0x0a, 0x00, 24, - 6, 4, 1, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 0x0e, 0x00, 36, - 6, 6, 2, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 0x09, 0x00, 48, - 8, 10, 3, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 0x0d, 0x00, 72, - 8, 14, 3, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 8, 19, 3, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 0x0c, 0x00, 108, - 8, 23, 3, 11, 0 }, - }, - 50, /* probe interval */ - 50, /* rssi reduce interval */ - 0, /* Phy rates allowed initially */ -}; - -static struct ath_rate_table ar5416_11b_ratetable = { - 4, - { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0x1b, 0x00, (0x80|2), - 0, 0, 1, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1800, 0x1a, 0x04, (0x80|4), - 1, 1, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4300, 0x19, 0x04, (0x80|11), - 1, 2, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 7100, 0x18, 0x04, (0x80|22), - 1, 4, 100, 3, 0 }, - }, - 100, /* probe interval */ - 100, /* rssi reduce interval */ - 0, /* Phy rates allowed initially */ -}; - -static inline int8_t median(int8_t a, int8_t b, int8_t c) -{ - if (a >= b) { - if (b >= c) - return b; - else if (a > c) - return c; - else - return a; - } else { - if (a >= c) - return a; - else if (b >= c) - return c; - else - return b; - } -} - -static void ath_rc_sort_validrates(struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv) -{ - u8 i, j, idx, idx_next; - - for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { - for (j = 0; j <= i-1; j++) { - idx = ath_rc_priv->valid_rate_index[j]; - idx_next = ath_rc_priv->valid_rate_index[j+1]; - - if (rate_table->info[idx].ratekbps > - rate_table->info[idx_next].ratekbps) { - ath_rc_priv->valid_rate_index[j] = idx_next; - ath_rc_priv->valid_rate_index[j+1] = idx; - } - } - } -} - -static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) -{ - u8 i; - - for (i = 0; i < ath_rc_priv->rate_table_size; i++) - ath_rc_priv->valid_rate_index[i] = 0; -} - -static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, - u8 index, int valid_tx_rate) -{ - ASSERT(index <= ath_rc_priv->rate_table_size); - ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; -} - -static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, - u8 index) -{ - ASSERT(index <= ath_rc_priv->rate_table_size); - return ath_rc_priv->valid_rate_index[index]; -} - -static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, - u8 *next_idx) -{ - u8 i; - - for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) { - if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { - *next_idx = ath_rc_priv->valid_rate_index[i+1]; - return 1; - } - } - - /* No more valid rates */ - *next_idx = 0; - - return 0; -} - -/* Return true only for single stream */ - -static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) -{ - if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) - return 0; - if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) - return 0; - if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) - return 0; - if (!ignore_cw && WLAN_RC_PHY_HT(phy)) - if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) - return 0; - if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) - return 0; - return 1; -} - -static inline int -ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, u8 *next_idx) -{ - int8_t i; - - for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) { - if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { - *next_idx = ath_rc_priv->valid_rate_index[i-1]; - return 1; - } - } - - return 0; -} - -static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, - u32 capflag) -{ - u8 i, hi = 0; - u32 valid; - - for (i = 0; i < rate_table->rate_cnt; i++) { - valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[i].valid_single_stream : - rate_table->info[i].valid); - if (valid == 1) { - u32 phy = rate_table->info[i].phy; - u8 valid_rate_count = 0; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; - - ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, i, 1); - hi = A_MAX(hi, i); - } - } - - return hi; -} - -static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, - struct ath_rateset *rateset, - u32 capflag) -{ - u8 i, j, hi = 0; - - /* Use intersection of working rates and valid rates */ - for (i = 0; i < rateset->rs_nrates; i++) { - for (j = 0; j < rate_table->rate_cnt; j++) { - u32 phy = rate_table->info[j].phy; - u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; - - /* We allow a rate only if its valid and the - * capflag matches one of the validity - * (VALID/VALID_20/VALID_40) flags */ - - if (((rate & 0x7F) == (dot11rate & 0x7F)) && - ((valid & WLAN_RC_CAP_MODE(capflag)) == - WLAN_RC_CAP_MODE(capflag)) && - !WLAN_RC_PHY_HT(phy)) { - u8 valid_rate_count = 0; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = - ath_rc_priv->valid_phy_ratecnt[phy]; - - ath_rc_priv->valid_phy_rateidx[phy] - [valid_rate_count] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, j, 1); - hi = A_MAX(hi, j); - } - } - } - - return hi; -} - -static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, - u8 *mcs_set, u32 capflag) -{ - struct ath_rateset *rateset = (struct ath_rateset *)mcs_set; - - u8 i, j, hi = 0; - - /* Use intersection of working rates and valid rates */ - for (i = 0; i < rateset->rs_nrates; i++) { - for (j = 0; j < rate_table->rate_cnt; j++) { - u32 phy = rate_table->info[j].phy; - u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; - - if (((rate & 0x7F) != (dot11rate & 0x7F)) || - !WLAN_RC_PHY_HT(phy) || - !WLAN_RC_PHY_HT_VALID(valid, capflag)) - continue; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - ath_rc_priv->valid_phy_rateidx[phy] - [ath_rc_priv->valid_phy_ratecnt[phy]] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, j, 1); - hi = A_MAX(hi, j); - } - } - - return hi; -} - -static u8 ath_rc_ratefind_ht(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, - int *is_probing) -{ - u32 dt, best_thruput, this_thruput, now_msec; - u8 rate, next_rate, best_rate, maxindex, minindex; - int8_t rssi_last, rssi_reduce = 0, index = 0; - - *is_probing = 0; - - rssi_last = median(ath_rc_priv->rssi_last, - ath_rc_priv->rssi_last_prev, - ath_rc_priv->rssi_last_prev2); - - /* - * Age (reduce) last ack rssi based on how old it is. - * The bizarre numbers are so the delta is 160msec, - * meaning we divide by 16. - * 0msec <= dt <= 25msec: don't derate - * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB - * 185msec <= dt: derate by 10dB - */ - - now_msec = jiffies_to_msecs(jiffies); - dt = now_msec - ath_rc_priv->rssi_time; - - if (dt >= 185) - rssi_reduce = 10; - else if (dt >= 25) - rssi_reduce = (u8)((dt - 25) >> 4); - - /* Now reduce rssi_last by rssi_reduce */ - if (rssi_last < rssi_reduce) - rssi_last = 0; - else - rssi_last -= rssi_reduce; - - /* - * Now look up the rate in the rssi table and return it. - * If no rates match then we return 0 (lowest rate) - */ - - best_thruput = 0; - maxindex = ath_rc_priv->max_valid_rate-1; - - minindex = 0; - best_rate = minindex; - - /* - * Try the higher rate first. It will reduce memory moving time - * if we have very good channel characteristics. - */ - for (index = maxindex; index >= minindex ; index--) { - u8 per_thres; - - rate = ath_rc_priv->valid_rate_index[index]; - if (rate > ath_rc_priv->rate_max_phy) - continue; - - /* - * For TCP the average collision rate is around 11%, - * so we ignore PERs less than this. This is to - * prevent the rate we are currently using (whose - * PER might be in the 10-15 range because of TCP - * collisions) looking worse than the next lower - * rate whose PER has decayed close to 0. If we - * used to next lower rate, its PER would grow to - * 10-15 and we would be worse off then staying - * at the current rate. - */ - per_thres = ath_rc_priv->state[rate].per; - if (per_thres < 12) - per_thres = 12; - - this_thruput = rate_table->info[rate].user_ratekbps * - (100 - per_thres); - - if (best_thruput <= this_thruput) { - best_thruput = this_thruput; - best_rate = rate; - } - } - - rate = best_rate; - ath_rc_priv->rssi_last_lookup = rssi_last; - - /* - * Must check the actual rate (ratekbps) to account for - * non-monoticity of 11g's rate table - */ - - if (rate >= ath_rc_priv->rate_max_phy) { - rate = ath_rc_priv->rate_max_phy; - - /* Probe the next allowed phy state */ - if (ath_rc_get_nextvalid_txrate(rate_table, - ath_rc_priv, rate, &next_rate) && - (now_msec - ath_rc_priv->probe_time > - rate_table->probe_interval) && - (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { - rate = next_rate; - ath_rc_priv->probe_rate = rate; - ath_rc_priv->probe_time = now_msec; - ath_rc_priv->hw_maxretry_pktcnt = 0; - *is_probing = 1; - } - } - - if (rate > (ath_rc_priv->rate_table_size - 1)) - rate = ath_rc_priv->rate_table_size - 1; - - ASSERT((rate_table->info[rate].valid && - (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) || - (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))); - - return rate; -} - -static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, - struct ieee80211_tx_rate *rate, - struct ieee80211_tx_rate_control *txrc, - u8 tries, u8 rix, int rtsctsenable) -{ - rate->count = tries; - rate->idx = rix; - - if (txrc->short_preamble) - rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (txrc->rts || rtsctsenable) - rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; - if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_SHORT_GI; - if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_MCS; -} - -static void ath_rc_rate_set_rtscts(struct ath_softc *sc, - struct ath_rate_table *rate_table, - struct ieee80211_tx_info *tx_info) -{ - struct ieee80211_tx_rate *rates = tx_info->control.rates; - int i = 0, rix = 0, cix, enable_g_protection = 0; - - /* get the cix for the lowest valid rix */ - for (i = 3; i >= 0; i--) { - if (rates[i].count && (rates[i].idx >= 0)) { - rix = rates[i].idx; - break; - } - } - cix = rate_table->info[rix].ctrl_rate; - - /* All protection frames are transmited at 2Mb/s for 802.11g, - * otherwise we transmit them at 1Mb/s */ - if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ && - !conf_is_ht(&sc->hw->conf)) - enable_g_protection = 1; - - /* - * If 802.11g protection is enabled, determine whether to use RTS/CTS or - * just CTS. Note that this is only done for OFDM/HT unicast frames. - */ - if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && - !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && - (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || - WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { - rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; - cix = rate_table->info[enable_g_protection].ctrl_rate; - } - - tx_info->control.rts_cts_rate_idx = cix; -} - -static u8 ath_rc_rate_getidx(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, - u8 rix, u16 stepdown, - u16 min_rate) -{ - u32 j; - u8 nextindex; - - if (min_rate) { - for (j = RATE_TABLE_SIZE; j > 0; j--) { - if (ath_rc_get_nextlowervalid_txrate(rate_table, - ath_rc_priv, rix, &nextindex)) - rix = nextindex; - else - break; - } - } else { - for (j = stepdown; j > 0; j--) { - if (ath_rc_get_nextlowervalid_txrate(rate_table, - ath_rc_priv, rix, &nextindex)) - rix = nextindex; - else - break; - } - } - return rix; -} - -static void ath_rc_ratefind(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_rate_control *txrc) -{ - struct ath_rate_table *rate_table; - struct sk_buff *skb = txrc->skb; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->control.rates; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc = hdr->frame_control; - u8 try_per_rate = 0, i = 0, rix, nrix; - int is_probe = 0; - - rate_table = sc->cur_rate_table; - rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe); - nrix = rix; - - if (is_probe) { - /* set one try for probe rates. For the - * probes don't enable rts */ - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - 1, nrix, 0); - - try_per_rate = (ATH_11N_TXMAXTRY/4); - /* Get the next tried/allowed rate. No RTS for the next series - * after the probe rate - */ - nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1, 0); - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, nrix, 0); - - tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; - } else { - try_per_rate = (ATH_11N_TXMAXTRY/4); - /* Set the choosen rate. No RTS for first series entry. */ - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, nrix, 0); - } - - /* Fill in the other rates for multirate retry */ - for ( ; i < 4; i++) { - u8 try_num; - u8 min_rate; - - try_num = ((i + 1) == 4) ? - ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ; - min_rate = (((i + 1) == 4) && 0); - - nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1, min_rate); - /* All other rates in the series have RTS enabled */ - ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_num, nrix, 1); - } - - /* - * NB:Change rate series to enable aggregation when operating - * at lower MCS rates. When first rate in series is MCS2 - * in HT40 @ 2.4GHz, series should look like: - * - * {MCS2, MCS1, MCS0, MCS0}. - * - * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should - * look like: - * - * {MCS3, MCS2, MCS1, MCS1} - * - * So, set fourth rate in series to be same as third one for - * above conditions. - */ - if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) && - (conf_is_ht(&sc->hw->conf))) { - u8 dot11rate = rate_table->info[rix].dot11rate; - u8 phy = rate_table->info[rix].phy; - if (i == 4 && - ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || - (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { - rates[3].idx = rates[2].idx; - rates[3].flags = rates[2].flags; - } - } - - /* - * Force hardware to use computed duration for next - * fragment by disabling multi-rate retry, which - * updates duration based on the multi-rate duration table. - * - * FIXME: Fix duration - */ - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && - (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) { - rates[1].count = rates[2].count = rates[3].count = 0; - rates[1].idx = rates[2].idx = rates[3].idx = 0; - rates[0].count = ATH_TXMAXTRY; - } - - /* Setup RTS/CTS */ - ath_rc_rate_set_rtscts(sc, rate_table, tx_info); -} - -static bool ath_rc_update_per(struct ath_softc *sc, - struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - struct ath_tx_info_priv *tx_info_priv, - int tx_rate, int xretries, int retries, - u32 now_msec) -{ - bool state_change = false; - int count; - u8 last_per; - static u32 nretry_to_per_lookup[10] = { - 100 * 0 / 1, - 100 * 1 / 4, - 100 * 1 / 2, - 100 * 3 / 4, - 100 * 4 / 5, - 100 * 5 / 6, - 100 * 6 / 7, - 100 * 7 / 8, - 100 * 8 / 9, - 100 * 9 / 10 - }; - - last_per = ath_rc_priv->state[tx_rate].per; - - if (xretries) { - if (xretries == 1) { - ath_rc_priv->state[tx_rate].per += 30; - if (ath_rc_priv->state[tx_rate].per > 100) - ath_rc_priv->state[tx_rate].per = 100; - } else { - /* xretries == 2 */ - count = ARRAY_SIZE(nretry_to_per_lookup); - if (retries >= count) - retries = count - 1; - - /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ - ath_rc_priv->state[tx_rate].per = - (u8)(last_per - (last_per >> 3) + (100 >> 3)); - } - - /* xretries == 1 or 2 */ - - if (ath_rc_priv->probe_rate == tx_rate) - ath_rc_priv->probe_rate = 0; - - } else { /* xretries == 0 */ - count = ARRAY_SIZE(nretry_to_per_lookup); - if (retries >= count) - retries = count - 1; - - if (tx_info_priv->n_bad_frames) { - /* new_PER = 7/8*old_PER + 1/8*(currentPER) - * Assuming that n_frames is not 0. The current PER - * from the retries is 100 * retries / (retries+1), - * since the first retries attempts failed, and the - * next one worked. For the one that worked, - * n_bad_frames subframes out of n_frames wored, - * so the PER for that part is - * 100 * n_bad_frames / n_frames, and it contributes - * 100 * n_bad_frames / (n_frames * (retries+1)) to - * the above PER. The expression below is a - * simplified version of the sum of these two terms. - */ - if (tx_info_priv->n_frames > 0) { - int n_frames, n_bad_frames; - u8 cur_per, new_per; - - n_bad_frames = retries * tx_info_priv->n_frames + - tx_info_priv->n_bad_frames; - n_frames = tx_info_priv->n_frames * (retries + 1); - cur_per = (100 * n_bad_frames / n_frames) >> 3; - new_per = (u8)(last_per - (last_per >> 3) + cur_per); - ath_rc_priv->state[tx_rate].per = new_per; - } - } else { - ath_rc_priv->state[tx_rate].per = - (u8)(last_per - (last_per >> 3) + - (nretry_to_per_lookup[retries] >> 3)); - } - - ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev; - ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last; - ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi; - ath_rc_priv->rssi_time = now_msec; - - /* - * If we got at most one retry then increase the max rate if - * this was a probe. Otherwise, ignore the probe. - */ - if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { - if (retries > 0 || 2 * tx_info_priv->n_bad_frames > - tx_info_priv->n_frames) { - /* - * Since we probed with just a single attempt, - * any retries means the probe failed. Also, - * if the attempt worked, but more than half - * the subframes were bad then also consider - * the probe a failure. - */ - ath_rc_priv->probe_rate = 0; - } else { - u8 probe_rate = 0; - - ath_rc_priv->rate_max_phy = - ath_rc_priv->probe_rate; - probe_rate = ath_rc_priv->probe_rate; - - if (ath_rc_priv->state[probe_rate].per > 30) - ath_rc_priv->state[probe_rate].per = 20; - - ath_rc_priv->probe_rate = 0; - - /* - * Since this probe succeeded, we allow the next - * probe twice as soon. This allows the maxRate - * to move up faster if the probes are - * succesful. - */ - ath_rc_priv->probe_time = - now_msec - rate_table->probe_interval / 2; - } - } - - if (retries > 0) { - /* - * Don't update anything. We don't know if - * this was because of collisions or poor signal. - * - * Later: if rssi_ack is close to - * ath_rc_priv->state[txRate].rssi_thres and we see lots - * of retries, then we could increase - * ath_rc_priv->state[txRate].rssi_thres. - */ - ath_rc_priv->hw_maxretry_pktcnt = 0; - } else { - int32_t rssi_ackAvg; - int8_t rssi_thres; - int8_t rssi_ack_vmin; - - /* - * It worked with no retries. First ignore bogus (small) - * rssi_ack values. - */ - if (tx_rate == ath_rc_priv->rate_max_phy && - ath_rc_priv->hw_maxretry_pktcnt < 255) { - ath_rc_priv->hw_maxretry_pktcnt++; - } - - if (tx_info_priv->tx.ts_rssi < - rate_table->info[tx_rate].rssi_ack_validmin) - goto exit; - - /* Average the rssi */ - if (tx_rate != ath_rc_priv->rssi_sum_rate) { - ath_rc_priv->rssi_sum_rate = tx_rate; - ath_rc_priv->rssi_sum = - ath_rc_priv->rssi_sum_cnt = 0; - } - - ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi; - ath_rc_priv->rssi_sum_cnt++; - - if (ath_rc_priv->rssi_sum_cnt < 4) - goto exit; - - rssi_ackAvg = - (ath_rc_priv->rssi_sum + 2) / 4; - rssi_thres = - ath_rc_priv->state[tx_rate].rssi_thres; - rssi_ack_vmin = - rate_table->info[tx_rate].rssi_ack_validmin; - - ath_rc_priv->rssi_sum = - ath_rc_priv->rssi_sum_cnt = 0; - - /* Now reduce the current rssi threshold */ - if ((rssi_ackAvg < rssi_thres + 2) && - (rssi_thres > rssi_ack_vmin)) { - ath_rc_priv->state[tx_rate].rssi_thres--; - } - - state_change = true; - } - } -exit: - return state_change; -} - -/* Update PER, RSSI and whatever else that the code thinks it is doing. - If you can make sense of all this, you really need to go out more. */ - -static void ath_rc_update_ht(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ath_tx_info_priv *tx_info_priv, - int tx_rate, int xretries, int retries) -{ -#define CHK_RSSI(rate) \ - ((ath_rc_priv->state[(rate)].rssi_thres + \ - rate_table->info[(rate)].rssi_ack_deltamin) > \ - ath_rc_priv->state[(rate)+1].rssi_thres) - - u32 now_msec = jiffies_to_msecs(jiffies); - int rate; - u8 last_per; - bool state_change = false; - struct ath_rate_table *rate_table = sc->cur_rate_table; - int size = ath_rc_priv->rate_table_size; - - if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) - return; - - /* To compensate for some imbalance between ctrl and ext. channel */ - - if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) - tx_info_priv->tx.ts_rssi = - tx_info_priv->tx.ts_rssi < 3 ? 0 : - tx_info_priv->tx.ts_rssi - 3; - - last_per = ath_rc_priv->state[tx_rate].per; - - /* Update PER first */ - state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, - tx_info_priv, tx_rate, xretries, - retries, now_msec); - - /* - * If this rate looks bad (high PER) then stop using it for - * a while (except if we are probing). - */ - if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 && - rate_table->info[tx_rate].ratekbps <= - rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { - ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, - (u8)tx_rate, &ath_rc_priv->rate_max_phy); - - /* Don't probe for a little while. */ - ath_rc_priv->probe_time = now_msec; - } - - if (state_change) { - /* - * Make sure the rates above this have higher rssi thresholds. - * (Note: Monotonicity is kept within the OFDM rates and - * within the CCK rates. However, no adjustment is - * made to keep the rssi thresholds monotonically - * increasing between the CCK and OFDM rates.) - */ - for (rate = tx_rate; rate < size - 1; rate++) { - if (rate_table->info[rate+1].phy != - rate_table->info[tx_rate].phy) - break; - - if (CHK_RSSI(rate)) { - ath_rc_priv->state[rate+1].rssi_thres = - ath_rc_priv->state[rate].rssi_thres + - rate_table->info[rate].rssi_ack_deltamin; - } - } - - /* Make sure the rates below this have lower rssi thresholds. */ - for (rate = tx_rate - 1; rate >= 0; rate--) { - if (rate_table->info[rate].phy != - rate_table->info[tx_rate].phy) - break; - - if (CHK_RSSI(rate)) { - if (ath_rc_priv->state[rate+1].rssi_thres < - rate_table->info[rate].rssi_ack_deltamin) - ath_rc_priv->state[rate].rssi_thres = 0; - else { - ath_rc_priv->state[rate].rssi_thres = - ath_rc_priv->state[rate+1].rssi_thres - - rate_table->info[rate].rssi_ack_deltamin; - } - - if (ath_rc_priv->state[rate].rssi_thres < - rate_table->info[rate].rssi_ack_validmin) { - ath_rc_priv->state[rate].rssi_thres = - rate_table->info[rate].rssi_ack_validmin; - } - } - } - } - - /* Make sure the rates below this have lower PER */ - /* Monotonicity is kept only for rates below the current rate. */ - if (ath_rc_priv->state[tx_rate].per < last_per) { - for (rate = tx_rate - 1; rate >= 0; rate--) { - if (rate_table->info[rate].phy != - rate_table->info[tx_rate].phy) - break; - - if (ath_rc_priv->state[rate].per > - ath_rc_priv->state[rate+1].per) { - ath_rc_priv->state[rate].per = - ath_rc_priv->state[rate+1].per; - } - } - } - - /* Maintain monotonicity for rates above the current rate */ - for (rate = tx_rate; rate < size - 1; rate++) { - if (ath_rc_priv->state[rate+1].per < - ath_rc_priv->state[rate].per) - ath_rc_priv->state[rate+1].per = - ath_rc_priv->state[rate].per; - } - - /* Every so often, we reduce the thresholds and - * PER (different for CCK and OFDM). */ - if (now_msec - ath_rc_priv->rssi_down_time >= - rate_table->rssi_reduce_interval) { - - for (rate = 0; rate < size; rate++) { - if (ath_rc_priv->state[rate].rssi_thres > - rate_table->info[rate].rssi_ack_validmin) - ath_rc_priv->state[rate].rssi_thres -= 1; - } - ath_rc_priv->rssi_down_time = now_msec; - } - - /* Every so often, we reduce the thresholds - * and PER (different for CCK and OFDM). */ - if (now_msec - ath_rc_priv->per_down_time >= - rate_table->rssi_reduce_interval) { - for (rate = 0; rate < size; rate++) { - ath_rc_priv->state[rate].per = - 7 * ath_rc_priv->state[rate].per / 8; - } - - ath_rc_priv->per_down_time = now_msec; - } - - ath_debug_stat_retries(sc, tx_rate, xretries, retries, - ath_rc_priv->state[tx_rate].per); - -#undef CHK_RSSI -} - -static int ath_rc_get_rateindex(struct ath_rate_table *rate_table, - struct ieee80211_tx_rate *rate) -{ - int rix; - - if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (rate->flags & IEEE80211_TX_RC_SHORT_GI)) - rix = rate_table->info[rate->idx].ht_index; - else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - rix = rate_table->info[rate->idx].sgi_index; - else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - rix = rate_table->info[rate->idx].cw40index; - else - rix = rate_table->info[rate->idx].base_index; - - return rix; -} - -static void ath_rc_tx_status(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_info *tx_info, - int final_ts_idx, int xretries, int long_retry) -{ - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - struct ath_rate_table *rate_table; - struct ieee80211_tx_rate *rates = tx_info->status.rates; - u8 flags; - u32 i = 0, rix; - - rate_table = sc->cur_rate_table; - - /* - * If the first rate is not the final index, there - * are intermediate rate failures to be processed. - */ - if (final_ts_idx != 0) { - /* Process intermediate rates that failed.*/ - for (i = 0; i < final_ts_idx ; i++) { - if (rates[i].count != 0 && (rates[i].idx >= 0)) { - flags = rates[i].flags; - - /* If HT40 and we have switched mode from - * 40 to 20 => don't update */ - - if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) - return; - - rix = ath_rc_get_rateindex(rate_table, &rates[i]); - ath_rc_update_ht(sc, ath_rc_priv, - tx_info_priv, rix, - xretries ? 1 : 2, - rates[i].count); - } - } - } else { - /* - * Handle the special case of MIMO PS burst, where the second - * aggregate is sent out with only one rate and one try. - * Treating it as an excessive retry penalizes the rate - * inordinately. - */ - if (rates[0].count == 1 && xretries == 1) - xretries = 2; - } - - flags = rates[i].flags; - - /* If HT40 and we have switched mode from 40 to 20 => don't update */ - if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) - return; - - rix = ath_rc_get_rateindex(rate_table, &rates[i]); - ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, - xretries, long_retry); -} - -static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, - enum ieee80211_band band, - bool is_ht, bool is_cw_40) -{ - int mode = 0; - - switch(band) { - case IEEE80211_BAND_2GHZ: - mode = ATH9K_MODE_11G; - if (is_ht) - mode = ATH9K_MODE_11NG_HT20; - if (is_cw_40) - mode = ATH9K_MODE_11NG_HT40PLUS; - break; - case IEEE80211_BAND_5GHZ: - mode = ATH9K_MODE_11A; - if (is_ht) - mode = ATH9K_MODE_11NA_HT20; - if (is_cw_40) - mode = ATH9K_MODE_11NA_HT40PLUS; - break; - default: - DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n"); - return NULL; - } - - BUG_ON(mode >= ATH9K_MODE_MAX); - - DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode); - return sc->hw_rate_table[mode]; -} - -static void ath_rc_init(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, - struct ath_rate_table *rate_table) -{ - struct ath_rateset *rateset = &ath_rc_priv->neg_rates; - u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; - u8 i, j, k, hi = 0, hthi = 0; - - if (!rate_table) { - DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n"); - return; - } - - /* Initial rate table size. Will change depending - * on the working rate set */ - ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; - - /* Initialize thresholds according to the global rate table */ - for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { - ath_rc_priv->state[i].rssi_thres = - rate_table->info[i].rssi_ack_validmin; - ath_rc_priv->state[i].per = 0; - } - - /* Determine the valid rates */ - ath_rc_init_valid_txmask(ath_rc_priv); - - for (i = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < MAX_TX_RATE_PHY; j++) - ath_rc_priv->valid_phy_rateidx[i][j] = 0; - ath_rc_priv->valid_phy_ratecnt[i] = 0; - } - - if (!rateset->rs_nrates) { - /* No working rate, just initialize valid rates */ - hi = ath_rc_init_validrates(ath_rc_priv, rate_table, - ath_rc_priv->ht_cap); - } else { - /* Use intersection of working rates and valid rates */ - hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table, - rateset, ath_rc_priv->ht_cap); - if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) { - hthi = ath_rc_setvalid_htrates(ath_rc_priv, - rate_table, - ht_mcs, - ath_rc_priv->ht_cap); - } - hi = A_MAX(hi, hthi); - } - - ath_rc_priv->rate_table_size = hi + 1; - ath_rc_priv->rate_max_phy = 0; - ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); - - for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { - ath_rc_priv->valid_rate_index[k++] = - ath_rc_priv->valid_phy_rateidx[i][j]; - } - - if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) - || !ath_rc_priv->valid_phy_ratecnt[i]) - continue; - - ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; - } - ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); - ASSERT(k <= RATE_TABLE_SIZE); - - ath_rc_priv->max_valid_rate = k; - ath_rc_sort_validrates(rate_table, ath_rc_priv); - ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; - sc->cur_rate_table = rate_table; - - DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n", - ath_rc_priv->ht_cap); -} - -static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, - bool is_cw40, bool is_sgi40) -{ - u8 caps = 0; - - if (sta->ht_cap.ht_supported) { - caps = WLAN_RC_HT_FLAG; - if (sc->sc_ah->caps.tx_chainmask != 1 && - ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { - if (sta->ht_cap.mcs.rx_mask[1]) - caps |= WLAN_RC_DS_FLAG; - } - if (is_cw40) - caps |= WLAN_RC_40_FLAG; - if (is_sgi40) - caps |= WLAN_RC_SGI_FLAG; - } - - return caps; -} - -/***********************************/ -/* mac80211 Rate Control callbacks */ -/***********************************/ - -static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_tx_info_priv *tx_info_priv = NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; - int final_ts_idx, tx_status = 0, is_underrun = 0; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - final_ts_idx = tx_info_priv->tx.ts_rateindex; - - if (!priv_sta || !ieee80211_is_data(fc) || - !tx_info_priv->update_rc) - goto exit; - - if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT) - goto exit; - - /* - * If underrun error is seen assume it as an excessive retry only - * if prefetch trigger level have reached the max (0x3f for 5416) - * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY - * times. This affects how ratectrl updates PER for the failed rate. - */ - if (tx_info_priv->tx.ts_flags & - (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && - ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) { - tx_status = 1; - is_underrun = 1; - } - - if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || - (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) - tx_status = 1; - - ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, - (is_underrun) ? ATH_11N_TXMAXTRY : - tx_info_priv->tx.ts_longretry); - - /* Check if aggregation has to be enabled for this tid */ - if (conf_is_ht(&sc->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - struct ath_node *an; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - an = (struct ath_node *)sta->drv_priv; - - if(ath_tx_aggr_check(sc, an, tid)) - ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); - } - } - - ath_debug_stat_rc(sc, skb); -exit: - kfree(tx_info_priv); -} - -static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, - struct ieee80211_tx_rate_control *txrc) -{ - struct ieee80211_supported_band *sband = txrc->sband; - struct sk_buff *skb = txrc->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - __le16 fc = hdr->frame_control; - - /* lowest rate for management and multicast/broadcast frames */ - if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta) { - tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); - tx_info->control.rates[0].count = - is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; - return; - } - - /* Find tx rate for unicast frames */ - ath_rc_ratefind(sc, ath_rc_priv, txrc); -} - -static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_rate_table *rate_table = NULL; - bool is_cw40, is_sgi40; - int i, j = 0; - - for (i = 0; i < sband->n_bitrates; i++) { - if (sta->supp_rates[sband->band] & BIT(i)) { - ath_rc_priv->neg_rates.rs_rates[j] - = (sband->bitrates[i].bitrate * 2) / 10; - j++; - } - } - ath_rc_priv->neg_rates.rs_nrates = j; - - if (sta->ht_cap.ht_supported) { - for (i = 0, j = 0; i < 77; i++) { - if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) - ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; - if (j == ATH_RATE_MAX) - break; - } - ath_rc_priv->neg_ht_rates.rs_nrates = j; - } - - is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; - is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; - - /* Choose rate table first */ - - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || - (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, - is_cw40); - } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { - /* cur_rate_table would be set on init through config() */ - rate_table = sc->cur_rate_table; - } - - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); -} - -static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - u32 changed) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_rate_table *rate_table = NULL; - bool oper_cw40 = false, oper_sgi40; - bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? - true : false; - bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? - true : false; - - /* FIXME: Handle AP mode later when we support CWM */ - - if (changed & IEEE80211_RC_HT_CHANGED) { - if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) - return; - - if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || - sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) - oper_cw40 = true; - - oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - true : false; - - if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, - oper_cw40); - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, - oper_cw40, oper_sgi40); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); - - DPRINTF(sc, ATH_DBG_CONFIG, - "Operating HT Bandwidth changed to: %d\n", - sc->hw->conf.channel_type); - } - } -} - -static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -{ - struct ath_wiphy *aphy = hw->priv; - return aphy->sc; -} - -static void ath_rate_free(void *priv) -{ - return; -} - -static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *rate_priv; - - rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); - if (!rate_priv) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to allocate private rc structure\n"); - return NULL; - } - - rate_priv->rssi_down_time = jiffies_to_msecs(jiffies); - rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; - - return rate_priv; -} - -static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, - void *priv_sta) -{ - struct ath_rate_priv *rate_priv = priv_sta; - kfree(rate_priv); -} - -static struct rate_control_ops ath_rate_ops = { - .module = NULL, - .name = "ath9k_rate_control", - .tx_status = ath_tx_status, - .get_rate = ath_get_rate, - .rate_init = ath_rate_init, - .rate_update = ath_rate_update, - .alloc = ath_rate_alloc, - .free = ath_rate_free, - .alloc_sta = ath_rate_alloc_sta, - .free_sta = ath_rate_free_sta, -}; - -void ath_rate_attach(struct ath_softc *sc) -{ - sc->hw_rate_table[ATH9K_MODE_11B] = - &ar5416_11b_ratetable; - sc->hw_rate_table[ATH9K_MODE_11A] = - &ar5416_11a_ratetable; - sc->hw_rate_table[ATH9K_MODE_11G] = - &ar5416_11g_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = - &ar5416_11ng_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = - &ar5416_11ng_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = - &ar5416_11ng_ratetable; -} - -int ath_rate_control_register(void) -{ - return ieee80211_rate_control_register(&ath_rate_ops); -} - -void ath_rate_control_unregister(void) -{ - ieee80211_rate_control_unregister(&ath_rate_ops); -} diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h deleted file mode 100644 index e3abd76103fd..000000000000 --- a/drivers/net/wireless/ath9k/rc.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2004 Sam Leffler, Errno Consulting - * Copyright (c) 2004 Video54 Technologies, Inc. - * 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 RC_H -#define RC_H - -struct ath_softc; - -#define ATH_RATE_MAX 30 -#define RATE_TABLE_SIZE 64 -#define MAX_TX_RATE_PHY 48 - -/* VALID_ALL - valid for 20/40/Legacy, - * VALID - Legacy only, - * VALID_20 - HT 20 only, - * VALID_40 - HT 40 only */ - -#define INVALID 0x0 -#define VALID 0x1 -#define VALID_20 0x2 -#define VALID_40 0x4 -#define VALID_2040 (VALID_20|VALID_40) -#define VALID_ALL (VALID_2040|VALID) - -enum { - WLAN_RC_PHY_OFDM, - WLAN_RC_PHY_CCK, - WLAN_RC_PHY_HT_20_SS, - WLAN_RC_PHY_HT_20_DS, - WLAN_RC_PHY_HT_40_SS, - WLAN_RC_PHY_HT_40_DS, - WLAN_RC_PHY_HT_20_SS_HGI, - WLAN_RC_PHY_HT_20_DS_HGI, - WLAN_RC_PHY_HT_40_SS_HGI, - WLAN_RC_PHY_HT_40_DS_HGI, - WLAN_RC_PHY_MAX -}; - -#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) -#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) -#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) - -#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) - -#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ - (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID)) - -/* Return TRUE if flag supports HT20 && client supports HT20 or - * return TRUE if flag supports HT40 && client supports HT40. - * This is used becos some rates overlap between HT20/HT40. - */ -#define WLAN_RC_PHY_HT_VALID(flag, capflag) \ - (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \ - ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG))) - -#define WLAN_RC_DS_FLAG (0x01) -#define WLAN_RC_40_FLAG (0x02) -#define WLAN_RC_SGI_FLAG (0x04) -#define WLAN_RC_HT_FLAG (0x08) - -/** - * struct ath_rate_table - Rate Control table - * @valid: valid for use in rate control - * @valid_single_stream: valid for use in rate control for - * single stream operation - * @phy: CCK/OFDM - * @ratekbps: rate in Kbits per second - * @user_ratekbps: user rate in Kbits per second - * @ratecode: rate that goes into HW descriptors - * @short_preamble: Mask for enabling short preamble in ratecode for CCK - * @dot11rate: value that goes into supported - * rates info element of MLME - * @ctrl_rate: Index of next lower basic rate, used for duration computation - * @max_4ms_framelen: maximum frame length(bytes) for tx duration - * @probe_interval: interval for rate control to probe for other rates - * @rssi_reduce_interval: interval for rate control to reduce rssi - * @initial_ratemax: initial ratemax value - */ -struct ath_rate_table { - int rate_cnt; - struct { - int valid; - int valid_single_stream; - u8 phy; - u32 ratekbps; - u32 user_ratekbps; - u8 ratecode; - u8 short_preamble; - u8 dot11rate; - u8 ctrl_rate; - int8_t rssi_ack_validmin; - int8_t rssi_ack_deltamin; - u8 base_index; - u8 cw40index; - u8 sgi_index; - u8 ht_index; - u32 max_4ms_framelen; - } info[RATE_TABLE_SIZE]; - u32 probe_interval; - u32 rssi_reduce_interval; - u8 initial_ratemax; -}; - -struct ath_tx_ratectrl_state { - int8_t rssi_thres; /* required rssi for this rate (dB) */ - u8 per; /* recent estimate of packet error rate (%) */ -}; - -struct ath_rateset { - u8 rs_nrates; - u8 rs_rates[ATH_RATE_MAX]; -}; - -/** - * struct ath_rate_priv - Rate Control priv data - * @state: RC state - * @rssi_last: last ACK rssi - * @rssi_last_lookup: last ACK rssi used for lookup - * @rssi_last_prev: previous last ACK rssi - * @rssi_last_prev2: 2nd previous last ACK rssi - * @rssi_sum_cnt: count of rssi_sum for averaging - * @rssi_sum_rate: rate that we are averaging - * @rssi_sum: running sum of rssi for averaging - * @probe_rate: rate we are probing at - * @rssi_time: msec timestamp for last ack rssi - * @rssi_down_time: msec timestamp for last down step - * @probe_time: msec timestamp for last probe - * @hw_maxretry_pktcnt: num of packets since we got HW max retry error - * @max_valid_rate: maximum number of valid rate - * @per_down_time: msec timestamp for last PER down step - * @valid_phy_ratecnt: valid rate count - * @rate_max_phy: phy index for the max rate - * @probe_interval: interval for ratectrl to probe for other rates - * @prev_data_rix: rate idx of last data frame - * @ht_cap: HT capabilities - * @neg_rates: Negotatied rates - * @neg_ht_rates: Negotiated HT rates - */ -struct ath_rate_priv { - int8_t rssi_last; - int8_t rssi_last_lookup; - int8_t rssi_last_prev; - int8_t rssi_last_prev2; - int32_t rssi_sum_cnt; - int32_t rssi_sum_rate; - int32_t rssi_sum; - u8 rate_table_size; - u8 probe_rate; - u8 hw_maxretry_pktcnt; - u8 max_valid_rate; - u8 valid_rate_index[RATE_TABLE_SIZE]; - u8 ht_cap; - u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; - u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; - u8 rate_max_phy; - u32 rssi_time; - u32 rssi_down_time; - u32 probe_time; - u32 per_down_time; - u32 probe_interval; - u32 prev_data_rix; - u32 tx_triglevel_max; - struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE]; - struct ath_rateset neg_rates; - struct ath_rateset neg_ht_rates; - struct ath_rate_softc *asc; -}; - -enum ath9k_internal_frame_type { - ATH9K_NOT_INTERNAL, - ATH9K_INT_PAUSE, - ATH9K_INT_UNPAUSE -}; - -struct ath_tx_info_priv { - struct ath_wiphy *aphy; - struct ath_tx_status tx; - int n_frames; - int n_bad_frames; - bool update_rc; - enum ath9k_internal_frame_type frame_type; -}; - -#define ATH_TX_INFO_PRIV(tx_info) \ - ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0])) - -void ath_rate_attach(struct ath_softc *sc); -u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); -int ath_rate_control_register(void); -void ath_rate_control_unregister(void); - -#endif /* RC_H */ diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c deleted file mode 100644 index b46badd21f73..000000000000 --- a/drivers/net/wireless/ath9k/recv.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * 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 "ath9k.h" - -static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, - struct ieee80211_hdr *hdr) -{ - struct ieee80211_hw *hw = sc->pri_wiphy->hw; - int i; - - spin_lock_bh(&sc->wiphy_lock); - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) - == 0) { - hw = aphy->hw; - break; - } - } - spin_unlock_bh(&sc->wiphy_lock); - return hw; -} - -/* - * Setup and link descriptors. - * - * 11N: we can no longer afford to self link the last descriptor. - * MAC acknowledges BA status as long as it copies frames to host - * buffer (or rx fifo). This can incorrectly acknowledge packets - * to a sender if last desc is self-linked. - */ -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_desc *ds; - struct sk_buff *skb; - - ATH_RXBUF_RESET(bf); - - ds = bf->bf_desc; - ds->ds_link = 0; /* link to null */ - ds->ds_data = bf->bf_buf_addr; - - /* virtual addr of the beginning of the buffer. */ - skb = bf->bf_mpdu; - ASSERT(skb != NULL); - ds->ds_vdata = skb->data; - - /* setup rx descriptors. The rx.bufsize here tells the harware - * how much data it can DMA to us and that we are prepared - * to process */ - ath9k_hw_setuprxdesc(ah, ds, - sc->rx.bufsize, - 0); - - if (sc->rx.rxlink == NULL) - ath9k_hw_putrxbuf(ah, bf->bf_daddr); - else - *sc->rx.rxlink = bf->bf_daddr; - - sc->rx.rxlink = &ds->ds_link; - ath9k_hw_rxena(ah); -} - -static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) -{ - /* XXX block beacon interrupts */ - ath9k_hw_setantenna(sc->sc_ah, antenna); - sc->rx.defant = antenna; - sc->rx.rxotherant = 0; -} - -/* - * Extend 15-bit time stamp from rx descriptor to - * a full 64-bit TSF using the current h/w TSF. -*/ -static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) -{ - u64 tsf; - - tsf = ath9k_hw_gettsf64(sc->sc_ah); - if ((tsf & 0x7fff) < rstamp) - tsf -= 0x8000; - return (tsf & ~0x7fff) | rstamp; -} - -static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask) -{ - struct sk_buff *skb; - u32 off; - - /* - * Cache-line-align. This is important (for the - * 5210 at least) as not doing so causes bogus data - * in rx'd frames. - */ - - /* Note: the kernel can allocate a value greater than - * what we ask it to give us. We really only need 4 KB as that - * is this hardware supports and in fact we need at least 3849 - * as that is the MAX AMSDU size this hardware supports. - * Unfortunately this means we may get 8 KB here from the - * kernel... and that is actually what is observed on some - * systems :( */ - skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask); - if (skb != NULL) { - off = ((unsigned long) skb->data) % sc->cachelsz; - if (off != 0) - skb_reserve(skb, sc->cachelsz - off); - } else { - DPRINTF(sc, ATH_DBG_FATAL, - "skbuff alloc of size %u failed\n", len); - return NULL; - } - - return skb; -} - -/* - * For Decrypt or Demic errors, we only mark packet status here and always push - * up the frame up to let mac80211 handle the actual error case, be it no - * decryption key or real decryption error. This let us keep statistics there. - */ -static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, - struct ieee80211_rx_status *rx_status, bool *decrypt_error, - struct ath_softc *sc) -{ - struct ieee80211_hdr *hdr; - u8 ratecode; - __le16 fc; - struct ieee80211_hw *hw; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); - hw = ath_get_virt_hw(sc, hdr); - - if (ds->ds_rxstat.rs_more) { - /* - * Frame spans multiple descriptors; this cannot happen yet - * as we don't support jumbograms. If not in monitor mode, - * discard the frame. Enable this if you want to see - * error frames in Monitor mode. - */ - if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR) - goto rx_next; - } else if (ds->ds_rxstat.rs_status != 0) { - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) - goto rx_next; - - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) { - *decrypt_error = true; - } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) { - if (ieee80211_is_ctl(fc)) - /* - * Sometimes, we get invalid - * MIC failures on valid control frames. - * Remove these mic errors. - */ - ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC; - else - rx_status->flag |= RX_FLAG_MMIC_ERROR; - } - /* - * Reject error frames with the exception of - * decryption and MIC failures. For monitor mode, - * we also ignore the CRC error. - */ - if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) { - if (ds->ds_rxstat.rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | - ATH9K_RXERR_CRC)) - goto rx_next; - } else { - if (ds->ds_rxstat.rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { - goto rx_next; - } - } - } - - ratecode = ds->ds_rxstat.rs_rate; - - if (ratecode & 0x80) { - /* HT rate */ - rx_status->flag |= RX_FLAG_HT; - if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) - rx_status->flag |= RX_FLAG_40MHZ; - if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) - rx_status->flag |= RX_FLAG_SHORT_GI; - rx_status->rate_idx = ratecode & 0x7f; - } else { - int i = 0, cur_band, n_rates; - - cur_band = hw->conf.channel->band; - n_rates = sc->sbands[cur_band].n_bitrates; - - for (i = 0; i < n_rates; i++) { - if (sc->sbands[cur_band].bitrates[i].hw_value == - ratecode) { - rx_status->rate_idx = i; - break; - } - - if (sc->sbands[cur_band].bitrates[i].hw_value_short == - ratecode) { - rx_status->rate_idx = i; - rx_status->flag |= RX_FLAG_SHORTPRE; - break; - } - } - } - - rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); - rx_status->band = hw->conf.channel->band; - rx_status->freq = hw->conf.channel->center_freq; - rx_status->noise = sc->ani.noise_floor; - rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; - rx_status->antenna = ds->ds_rxstat.rs_antenna; - - /* at 45 you will be able to use MCS 15 reliably. A more elaborate - * scheme can be used here but it requires tables of SNR/throughput for - * each possible mode used. */ - rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45; - - /* rssi can be more than 45 though, anything above that - * should be considered at 100% */ - if (rx_status->qual > 100) - rx_status->qual = 100; - - rx_status->flag |= RX_FLAG_TSFT; - - return 1; -rx_next: - return 0; -} - -static void ath_opmode_init(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - u32 rfilt, mfilt[2]; - - /* configure rx filter */ - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(ah, rfilt); - - /* configure bssid mask */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - ath9k_hw_setbssidmask(sc); - - /* configure operational mode */ - ath9k_hw_setopmode(ah); - - /* Handle any link-level address change. */ - ath9k_hw_setmac(ah, sc->sc_ah->macaddr); - - /* calculate and install multicast filter */ - mfilt[0] = mfilt[1] = ~0; - ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); -} - -int ath_rx_init(struct ath_softc *sc, int nbufs) -{ - struct sk_buff *skb; - struct ath_buf *bf; - int error = 0; - - spin_lock_init(&sc->rx.rxflushlock); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_lock_init(&sc->rx.rxbuflock); - - sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, - min(sc->cachelsz, (u16)64)); - - DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - sc->cachelsz, sc->rx.bufsize); - - /* Initialize rx descriptors */ - - error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, - "rx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", error); - goto err; - } - - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); - if (skb == NULL) { - error = -ENOMEM; - goto err; - } - - bf->bf_mpdu = skb; - bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, - sc->rx.bufsize, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error() on RX init\n"); - error = -ENOMEM; - goto err; - } - bf->bf_dmacontext = bf->bf_buf_addr; - } - sc->rx.rxlink = NULL; - -err: - if (error) - ath_rx_cleanup(sc); - - return error; -} - -void ath_rx_cleanup(struct ath_softc *sc) -{ - struct sk_buff *skb; - struct ath_buf *bf; - - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = bf->bf_mpdu; - if (skb) { - dma_unmap_single(sc->dev, bf->bf_buf_addr, - sc->rx.bufsize, DMA_FROM_DEVICE); - dev_kfree_skb(skb); - } - } - - if (sc->rx.rxdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); -} - -/* - * Calculate the receive filter according to the - * operating mode and state: - * - * o always accept unicast, broadcast, and multicast traffic - * o maintain current state of phy error reception (the hal - * may enable phy error frames for noise immunity work) - * o probe request frames are accepted only when operating in - * hostap, adhoc, or monitor modes - * o enable promiscuous mode according to the interface state - * o accept beacons: - * - when operating in adhoc mode so the 802.11 layer creates - * node table entries for peers, - * - when operating in station mode for collecting rssi data when - * the station is otherwise quiet, or - * - when operating as a repeater so we see repeater-sta beacons - * - when scanning - */ - -u32 ath_calcrxfilter(struct ath_softc *sc) -{ -#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) - - u32 rfilt; - - rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) - | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST - | ATH9K_RX_FILTER_MCAST; - - /* If not a STA, enable processing of Probe Requests */ - if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) - rfilt |= ATH9K_RX_FILTER_PROBEREQ; - - /* - * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station - * mode interface or when in monitor mode. AP mode does not need this - * since it receives all in-BSS frames anyway. - */ - if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && - (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) - rfilt |= ATH9K_RX_FILTER_PROM; - - if (sc->rx.rxfilter & FIF_CONTROL) - rfilt |= ATH9K_RX_FILTER_CONTROL; - - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && - !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) - rfilt |= ATH9K_RX_FILTER_MYBEACON; - else - rfilt |= ATH9K_RX_FILTER_BEACON; - - /* If in HOSTAP mode, want to enable reception of PSPOLL frames */ - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) - rfilt |= ATH9K_RX_FILTER_PSPOLL; - - if (sc->sec_wiphy) { - /* TODO: only needed if more than one BSSID is in use in - * station/adhoc mode */ - /* TODO: for older chips, may need to add ATH9K_RX_FILTER_PROM - */ - rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; - } - - return rfilt; - -#undef RX_FILTER_PRESERVE -} - -int ath_startrecv(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf, *tbf; - - spin_lock_bh(&sc->rx.rxbuflock); - if (list_empty(&sc->rx.rxbuf)) - goto start_recv; - - sc->rx.rxlink = NULL; - list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { - ath_rx_buf_link(sc, bf); - } - - /* We could have deleted elements so the list may be empty now */ - if (list_empty(&sc->rx.rxbuf)) - goto start_recv; - - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); - ath9k_hw_putrxbuf(ah, bf->bf_daddr); - ath9k_hw_rxena(ah); - -start_recv: - spin_unlock_bh(&sc->rx.rxbuflock); - ath_opmode_init(sc); - ath9k_hw_startpcureceive(ah); - - return 0; -} - -bool ath_stoprecv(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - bool stopped; - - ath9k_hw_stoppcurecv(ah); - ath9k_hw_setrxfilter(ah, 0); - stopped = ath9k_hw_stopdmarecv(ah); - sc->rx.rxlink = NULL; - - return stopped; -} - -void ath_flushrecv(struct ath_softc *sc) -{ - spin_lock_bh(&sc->rx.rxflushlock); - sc->sc_flags |= SC_OP_RXFLUSH; - ath_rx_tasklet(sc, 1); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_unlock_bh(&sc->rx.rxflushlock); -} - -int ath_rx_tasklet(struct ath_softc *sc, int flush) -{ -#define PA2DESC(_sc, _pa) \ - ((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \ - ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr))) - - struct ath_buf *bf; - struct ath_desc *ds; - struct sk_buff *skb = NULL, *requeue_skb; - struct ieee80211_rx_status rx_status; - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_hdr *hdr; - int hdrlen, padsize, retval; - bool decrypt_error = false; - u8 keyix; - __le16 fc; - - spin_lock_bh(&sc->rx.rxbuflock); - - do { - /* If handling rx interrupt and flush is in progress => exit */ - if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) - break; - - if (list_empty(&sc->rx.rxbuf)) { - sc->rx.rxlink = NULL; - break; - } - - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); - ds = bf->bf_desc; - - /* - * Must provide the virtual address of the current - * descriptor, the physical address, and the virtual - * address of the next descriptor in the h/w chain. - * This allows the HAL to look ahead to see if the - * hardware is done with a descriptor by checking the - * done bit in the following descriptor and the address - * of the current descriptor the DMA engine is working - * on. All this is necessary because of our use of - * a self-linked list to avoid rx overruns. - */ - retval = ath9k_hw_rxprocdesc(ah, ds, - bf->bf_daddr, - PA2DESC(sc, ds->ds_link), - 0); - if (retval == -EINPROGRESS) { - struct ath_buf *tbf; - struct ath_desc *tds; - - if (list_is_last(&bf->list, &sc->rx.rxbuf)) { - sc->rx.rxlink = NULL; - break; - } - - tbf = list_entry(bf->list.next, struct ath_buf, list); - - /* - * On some hardware the descriptor status words could - * get corrupted, including the done bit. Because of - * this, check if the next descriptor's done bit is - * set or not. - * - * If the next descriptor's done bit is set, the current - * descriptor has been corrupted. Force s/w to discard - * this descriptor and continue... - */ - - tds = tbf->bf_desc; - retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, - PA2DESC(sc, tds->ds_link), 0); - if (retval == -EINPROGRESS) { - break; - } - } - - skb = bf->bf_mpdu; - if (!skb) - continue; - - /* - * Synchronize the DMA transfer with CPU before - * 1. accessing the frame - * 2. requeueing the same buffer to h/w - */ - dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, - sc->rx.bufsize, - DMA_FROM_DEVICE); - - /* - * If we're asked to flush receive queue, directly - * chain it back at the queue without processing it. - */ - if (flush) - goto requeue; - - if (!ds->ds_rxstat.rs_datalen) - goto requeue; - - /* The status portion of the descriptor could get corrupted. */ - if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen) - goto requeue; - - if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc)) - goto requeue; - - /* Ensure we always have an skb to requeue once we are done - * processing the current buffer's skb */ - requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); - - /* If there is no memory we ignore the current RX'd frame, - * tell hardware it can give us a new frame using the old - * skb and put it at the tail of the sc->rx.rxbuf list for - * processing. */ - if (!requeue_skb) - goto requeue; - - /* Unmap the frame */ - dma_unmap_single(sc->dev, bf->bf_buf_addr, - sc->rx.bufsize, - DMA_FROM_DEVICE); - - skb_put(skb, ds->ds_rxstat.rs_datalen); - skb->protocol = cpu_to_be16(ETH_P_CONTROL); - - /* see if any padding is done by the hw and remove it */ - hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; - - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - hdrlen % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ - padsize = hdrlen & 3; - if (padsize && hdrlen >= 24) { - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - keyix = ds->ds_rxstat.rs_keyix; - - if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { - rx_status.flag |= RX_FLAG_DECRYPTED; - } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) - && !decrypt_error && skb->len >= hdrlen + 4) { - keyix = skb->data[hdrlen + 3] >> 6; - - if (test_bit(keyix, sc->keymap)) - rx_status.flag |= RX_FLAG_DECRYPTED; - } - if (ah->sw_mgmt_crypto && - (rx_status.flag & RX_FLAG_DECRYPTED) && - ieee80211_is_mgmt(hdr->frame_control)) { - /* Use software decrypt for management frames. */ - rx_status.flag &= ~RX_FLAG_DECRYPTED; - } - - /* Send the frame to mac80211 */ - if (hdr->addr1[5] & 0x01) { - int i; - /* - * Deliver broadcast/multicast frames to all suitable - * virtual wiphys. - */ - /* TODO: filter based on channel configuration */ - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - struct sk_buff *nskb; - if (aphy == NULL) - continue; - nskb = skb_copy(skb, GFP_ATOMIC); - if (nskb) - __ieee80211_rx(aphy->hw, nskb, - &rx_status); - } - __ieee80211_rx(sc->hw, skb, &rx_status); - } else { - /* Deliver unicast frames based on receiver address */ - __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, - &rx_status); - } - - /* We will now give hardware our shiny new allocated skb */ - bf->bf_mpdu = requeue_skb; - bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, - sc->rx.bufsize, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(requeue_skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error() on RX\n"); - break; - } - bf->bf_dmacontext = bf->bf_buf_addr; - - /* - * change the default rx antenna if rx diversity chooses the - * other antenna 3 times in a row. - */ - if (sc->rx.defant != ds->ds_rxstat.rs_antenna) { - if (++sc->rx.rxotherant >= 3) - ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna); - } else { - sc->rx.rxotherant = 0; - } - - if (ieee80211_is_beacon(fc) && - (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); - } -requeue: - list_move_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_buf_link(sc, bf); - } while (1); - - spin_unlock_bh(&sc->rx.rxbuflock); - - return 0; -#undef PA2DESC -} diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h deleted file mode 100644 index 52605246679f..000000000000 --- a/drivers/net/wireless/ath9k/reg.h +++ /dev/null @@ -1,1511 +0,0 @@ -/* - * 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 REG_H -#define REG_H - -#define AR_CR 0x0008 -#define AR_CR_RXE 0x00000004 -#define AR_CR_RXD 0x00000020 -#define AR_CR_SWI 0x00000040 - -#define AR_RXDP 0x000C - -#define AR_CFG 0x0014 -#define AR_CFG_SWTD 0x00000001 -#define AR_CFG_SWTB 0x00000002 -#define AR_CFG_SWRD 0x00000004 -#define AR_CFG_SWRB 0x00000008 -#define AR_CFG_SWRG 0x00000010 -#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 -#define AR_CFG_PHOK 0x00000100 -#define AR_CFG_CLK_GATE_DIS 0x00000400 -#define AR_CFG_EEBS 0x00000200 -#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 -#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 - -#define AR_MIRT 0x0020 -#define AR_MIRT_VAL 0x0000ffff -#define AR_MIRT_VAL_S 16 - -#define AR_IER 0x0024 -#define AR_IER_ENABLE 0x00000001 -#define AR_IER_DISABLE 0x00000000 - -#define AR_TIMT 0x0028 -#define AR_TIMT_LAST 0x0000ffff -#define AR_TIMT_LAST_S 0 -#define AR_TIMT_FIRST 0xffff0000 -#define AR_TIMT_FIRST_S 16 - -#define AR_RIMT 0x002C -#define AR_RIMT_LAST 0x0000ffff -#define AR_RIMT_LAST_S 0 -#define AR_RIMT_FIRST 0xffff0000 -#define AR_RIMT_FIRST_S 16 - -#define AR_DMASIZE_4B 0x00000000 -#define AR_DMASIZE_8B 0x00000001 -#define AR_DMASIZE_16B 0x00000002 -#define AR_DMASIZE_32B 0x00000003 -#define AR_DMASIZE_64B 0x00000004 -#define AR_DMASIZE_128B 0x00000005 -#define AR_DMASIZE_256B 0x00000006 -#define AR_DMASIZE_512B 0x00000007 - -#define AR_TXCFG 0x0030 -#define AR_TXCFG_DMASZ_MASK 0x00000007 -#define AR_TXCFG_DMASZ_4B 0 -#define AR_TXCFG_DMASZ_8B 1 -#define AR_TXCFG_DMASZ_16B 2 -#define AR_TXCFG_DMASZ_32B 3 -#define AR_TXCFG_DMASZ_64B 4 -#define AR_TXCFG_DMASZ_128B 5 -#define AR_TXCFG_DMASZ_256B 6 -#define AR_TXCFG_DMASZ_512B 7 -#define AR_FTRIG 0x000003F0 -#define AR_FTRIG_S 4 -#define AR_FTRIG_IMMED 0x00000000 -#define AR_FTRIG_64B 0x00000010 -#define AR_FTRIG_128B 0x00000020 -#define AR_FTRIG_192B 0x00000030 -#define AR_FTRIG_256B 0x00000040 -#define AR_FTRIG_512B 0x00000080 -#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800 - -#define AR_RXCFG 0x0034 -#define AR_RXCFG_CHIRP 0x00000008 -#define AR_RXCFG_ZLFDMA 0x00000010 -#define AR_RXCFG_DMASZ_MASK 0x00000007 -#define AR_RXCFG_DMASZ_4B 0 -#define AR_RXCFG_DMASZ_8B 1 -#define AR_RXCFG_DMASZ_16B 2 -#define AR_RXCFG_DMASZ_32B 3 -#define AR_RXCFG_DMASZ_64B 4 -#define AR_RXCFG_DMASZ_128B 5 -#define AR_RXCFG_DMASZ_256B 6 -#define AR_RXCFG_DMASZ_512B 7 - -#define AR_MIBC 0x0040 -#define AR_MIBC_COW 0x00000001 -#define AR_MIBC_FMC 0x00000002 -#define AR_MIBC_CMC 0x00000004 -#define AR_MIBC_MCS 0x00000008 - -#define AR_TOPS 0x0044 -#define AR_TOPS_MASK 0x0000FFFF - -#define AR_RXNPTO 0x0048 -#define AR_RXNPTO_MASK 0x000003FF - -#define AR_TXNPTO 0x004C -#define AR_TXNPTO_MASK 0x000003FF -#define AR_TXNPTO_QCU_MASK 0x000FFC00 - -#define AR_RPGTO 0x0050 -#define AR_RPGTO_MASK 0x000003FF - -#define AR_RPCNT 0x0054 -#define AR_RPCNT_MASK 0x0000001F - -#define AR_MACMISC 0x0058 -#define AR_MACMISC_PCI_EXT_FORCE 0x00000010 -#define AR_MACMISC_DMA_OBS 0x000001E0 -#define AR_MACMISC_DMA_OBS_S 5 -#define AR_MACMISC_DMA_OBS_LINE_0 0 -#define AR_MACMISC_DMA_OBS_LINE_1 1 -#define AR_MACMISC_DMA_OBS_LINE_2 2 -#define AR_MACMISC_DMA_OBS_LINE_3 3 -#define AR_MACMISC_DMA_OBS_LINE_4 4 -#define AR_MACMISC_DMA_OBS_LINE_5 5 -#define AR_MACMISC_DMA_OBS_LINE_6 6 -#define AR_MACMISC_DMA_OBS_LINE_7 7 -#define AR_MACMISC_DMA_OBS_LINE_8 8 -#define AR_MACMISC_MISC_OBS 0x00000E00 -#define AR_MACMISC_MISC_OBS_S 9 -#define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000 -#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12 -#define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000 -#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15 -#define AR_MACMISC_MISC_OBS_BUS_1 1 - -#define AR_GTXTO 0x0064 -#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF -#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 -#define AR_GTXTO_TIMEOUT_LIMIT_S 16 - -#define AR_GTTM 0x0068 -#define AR_GTTM_USEC 0x00000001 -#define AR_GTTM_IGNORE_IDLE 0x00000002 -#define AR_GTTM_RESET_IDLE 0x00000004 -#define AR_GTTM_CST_USEC 0x00000008 - -#define AR_CST 0x006C -#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF -#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 -#define AR_CST_TIMEOUT_LIMIT_S 16 - -#define AR_ISR 0x0080 -#define AR_ISR_RXOK 0x00000001 -#define AR_ISR_RXDESC 0x00000002 -#define AR_ISR_RXERR 0x00000004 -#define AR_ISR_RXNOPKT 0x00000008 -#define AR_ISR_RXEOL 0x00000010 -#define AR_ISR_RXORN 0x00000020 -#define AR_ISR_TXOK 0x00000040 -#define AR_ISR_TXDESC 0x00000080 -#define AR_ISR_TXERR 0x00000100 -#define AR_ISR_TXNOPKT 0x00000200 -#define AR_ISR_TXEOL 0x00000400 -#define AR_ISR_TXURN 0x00000800 -#define AR_ISR_MIB 0x00001000 -#define AR_ISR_SWI 0x00002000 -#define AR_ISR_RXPHY 0x00004000 -#define AR_ISR_RXKCM 0x00008000 -#define AR_ISR_SWBA 0x00010000 -#define AR_ISR_BRSSI 0x00020000 -#define AR_ISR_BMISS 0x00040000 -#define AR_ISR_BNR 0x00100000 -#define AR_ISR_RXCHIRP 0x00200000 -#define AR_ISR_BCNMISC 0x00800000 -#define AR_ISR_TIM 0x00800000 -#define AR_ISR_QCBROVF 0x02000000 -#define AR_ISR_QCBRURN 0x04000000 -#define AR_ISR_QTRIG 0x08000000 -#define AR_ISR_GENTMR 0x10000000 - -#define AR_ISR_TXMINTR 0x00080000 -#define AR_ISR_RXMINTR 0x01000000 -#define AR_ISR_TXINTM 0x40000000 -#define AR_ISR_RXINTM 0x80000000 - -#define AR_ISR_S0 0x0084 -#define AR_ISR_S0_QCU_TXOK 0x000003FF -#define AR_ISR_S0_QCU_TXOK_S 0 -#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 -#define AR_ISR_S0_QCU_TXDESC_S 16 - -#define AR_ISR_S1 0x0088 -#define AR_ISR_S1_QCU_TXERR 0x000003FF -#define AR_ISR_S1_QCU_TXERR_S 0 -#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 -#define AR_ISR_S1_QCU_TXEOL_S 16 - -#define AR_ISR_S2 0x008c -#define AR_ISR_S2_QCU_TXURN 0x000003FF -#define AR_ISR_S2_CST 0x00400000 -#define AR_ISR_S2_GTT 0x00800000 -#define AR_ISR_S2_TIM 0x01000000 -#define AR_ISR_S2_CABEND 0x02000000 -#define AR_ISR_S2_DTIMSYNC 0x04000000 -#define AR_ISR_S2_BCNTO 0x08000000 -#define AR_ISR_S2_CABTO 0x10000000 -#define AR_ISR_S2_DTIM 0x20000000 -#define AR_ISR_S2_TSFOOR 0x40000000 -#define AR_ISR_S2_TBTT_TIME 0x80000000 - -#define AR_ISR_S3 0x0090 -#define AR_ISR_S3_QCU_QCBROVF 0x000003FF -#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 - -#define AR_ISR_S4 0x0094 -#define AR_ISR_S4_QCU_QTRIG 0x000003FF -#define AR_ISR_S4_RESV0 0xFFFFFC00 - -#define AR_ISR_S5 0x0098 -#define AR_ISR_S5_TIMER_TRIG 0x000000FF -#define AR_ISR_S5_TIMER_THRESH 0x0007FE00 -#define AR_ISR_S5_TIM_TIMER 0x00000010 -#define AR_ISR_S5_DTIM_TIMER 0x00000020 -#define AR_ISR_S5_S 0x00d8 -#define AR_IMR_S5 0x00b8 -#define AR_IMR_S5_TIM_TIMER 0x00000010 -#define AR_IMR_S5_DTIM_TIMER 0x00000020 - - -#define AR_IMR 0x00a0 -#define AR_IMR_RXOK 0x00000001 -#define AR_IMR_RXDESC 0x00000002 -#define AR_IMR_RXERR 0x00000004 -#define AR_IMR_RXNOPKT 0x00000008 -#define AR_IMR_RXEOL 0x00000010 -#define AR_IMR_RXORN 0x00000020 -#define AR_IMR_TXOK 0x00000040 -#define AR_IMR_TXDESC 0x00000080 -#define AR_IMR_TXERR 0x00000100 -#define AR_IMR_TXNOPKT 0x00000200 -#define AR_IMR_TXEOL 0x00000400 -#define AR_IMR_TXURN 0x00000800 -#define AR_IMR_MIB 0x00001000 -#define AR_IMR_SWI 0x00002000 -#define AR_IMR_RXPHY 0x00004000 -#define AR_IMR_RXKCM 0x00008000 -#define AR_IMR_SWBA 0x00010000 -#define AR_IMR_BRSSI 0x00020000 -#define AR_IMR_BMISS 0x00040000 -#define AR_IMR_BNR 0x00100000 -#define AR_IMR_RXCHIRP 0x00200000 -#define AR_IMR_BCNMISC 0x00800000 -#define AR_IMR_TIM 0x00800000 -#define AR_IMR_QCBROVF 0x02000000 -#define AR_IMR_QCBRURN 0x04000000 -#define AR_IMR_QTRIG 0x08000000 -#define AR_IMR_GENTMR 0x10000000 - -#define AR_IMR_TXMINTR 0x00080000 -#define AR_IMR_RXMINTR 0x01000000 -#define AR_IMR_TXINTM 0x40000000 -#define AR_IMR_RXINTM 0x80000000 - -#define AR_IMR_S0 0x00a4 -#define AR_IMR_S0_QCU_TXOK 0x000003FF -#define AR_IMR_S0_QCU_TXOK_S 0 -#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 -#define AR_IMR_S0_QCU_TXDESC_S 16 - -#define AR_IMR_S1 0x00a8 -#define AR_IMR_S1_QCU_TXERR 0x000003FF -#define AR_IMR_S1_QCU_TXERR_S 0 -#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 -#define AR_IMR_S1_QCU_TXEOL_S 16 - -#define AR_IMR_S2 0x00ac -#define AR_IMR_S2_QCU_TXURN 0x000003FF -#define AR_IMR_S2_QCU_TXURN_S 0 -#define AR_IMR_S2_CST 0x00400000 -#define AR_IMR_S2_GTT 0x00800000 -#define AR_IMR_S2_TIM 0x01000000 -#define AR_IMR_S2_CABEND 0x02000000 -#define AR_IMR_S2_DTIMSYNC 0x04000000 -#define AR_IMR_S2_BCNTO 0x08000000 -#define AR_IMR_S2_CABTO 0x10000000 -#define AR_IMR_S2_DTIM 0x20000000 -#define AR_IMR_S2_TSFOOR 0x40000000 - -#define AR_IMR_S3 0x00b0 -#define AR_IMR_S3_QCU_QCBROVF 0x000003FF -#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 -#define AR_IMR_S3_QCU_QCBRURN_S 16 - -#define AR_IMR_S4 0x00b4 -#define AR_IMR_S4_QCU_QTRIG 0x000003FF -#define AR_IMR_S4_RESV0 0xFFFFFC00 - -#define AR_IMR_S5 0x00b8 -#define AR_IMR_S5_TIMER_TRIG 0x000000FF -#define AR_IMR_S5_TIMER_THRESH 0x0000FF00 - - -#define AR_ISR_RAC 0x00c0 -#define AR_ISR_S0_S 0x00c4 -#define AR_ISR_S0_QCU_TXOK 0x000003FF -#define AR_ISR_S0_QCU_TXOK_S 0 -#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 -#define AR_ISR_S0_QCU_TXDESC_S 16 - -#define AR_ISR_S1_S 0x00c8 -#define AR_ISR_S1_QCU_TXERR 0x000003FF -#define AR_ISR_S1_QCU_TXERR_S 0 -#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 -#define AR_ISR_S1_QCU_TXEOL_S 16 - -#define AR_ISR_S2_S 0x00cc -#define AR_ISR_S3_S 0x00d0 -#define AR_ISR_S4_S 0x00d4 -#define AR_ISR_S5_S 0x00d8 -#define AR_DMADBG_0 0x00e0 -#define AR_DMADBG_1 0x00e4 -#define AR_DMADBG_2 0x00e8 -#define AR_DMADBG_3 0x00ec -#define AR_DMADBG_4 0x00f0 -#define AR_DMADBG_5 0x00f4 -#define AR_DMADBG_6 0x00f8 -#define AR_DMADBG_7 0x00fc - -#define AR_NUM_QCU 10 -#define AR_QCU_0 0x0001 -#define AR_QCU_1 0x0002 -#define AR_QCU_2 0x0004 -#define AR_QCU_3 0x0008 -#define AR_QCU_4 0x0010 -#define AR_QCU_5 0x0020 -#define AR_QCU_6 0x0040 -#define AR_QCU_7 0x0080 -#define AR_QCU_8 0x0100 -#define AR_QCU_9 0x0200 - -#define AR_Q0_TXDP 0x0800 -#define AR_Q1_TXDP 0x0804 -#define AR_Q2_TXDP 0x0808 -#define AR_Q3_TXDP 0x080c -#define AR_Q4_TXDP 0x0810 -#define AR_Q5_TXDP 0x0814 -#define AR_Q6_TXDP 0x0818 -#define AR_Q7_TXDP 0x081c -#define AR_Q8_TXDP 0x0820 -#define AR_Q9_TXDP 0x0824 -#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) - -#define AR_Q_TXE 0x0840 -#define AR_Q_TXE_M 0x000003FF - -#define AR_Q_TXD 0x0880 -#define AR_Q_TXD_M 0x000003FF - -#define AR_Q0_CBRCFG 0x08c0 -#define AR_Q1_CBRCFG 0x08c4 -#define AR_Q2_CBRCFG 0x08c8 -#define AR_Q3_CBRCFG 0x08cc -#define AR_Q4_CBRCFG 0x08d0 -#define AR_Q5_CBRCFG 0x08d4 -#define AR_Q6_CBRCFG 0x08d8 -#define AR_Q7_CBRCFG 0x08dc -#define AR_Q8_CBRCFG 0x08e0 -#define AR_Q9_CBRCFG 0x08e4 -#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) -#define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF -#define AR_Q_CBRCFG_INTERVAL_S 0 -#define AR_Q_CBRCFG_OVF_THRESH 0xFF000000 -#define AR_Q_CBRCFG_OVF_THRESH_S 24 - -#define AR_Q0_RDYTIMECFG 0x0900 -#define AR_Q1_RDYTIMECFG 0x0904 -#define AR_Q2_RDYTIMECFG 0x0908 -#define AR_Q3_RDYTIMECFG 0x090c -#define AR_Q4_RDYTIMECFG 0x0910 -#define AR_Q5_RDYTIMECFG 0x0914 -#define AR_Q6_RDYTIMECFG 0x0918 -#define AR_Q7_RDYTIMECFG 0x091c -#define AR_Q8_RDYTIMECFG 0x0920 -#define AR_Q9_RDYTIMECFG 0x0924 -#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) -#define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF -#define AR_Q_RDYTIMECFG_DURATION_S 0 -#define AR_Q_RDYTIMECFG_EN 0x01000000 - -#define AR_Q_ONESHOTARM_SC 0x0940 -#define AR_Q_ONESHOTARM_SC_M 0x000003FF -#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00 - -#define AR_Q_ONESHOTARM_CC 0x0980 -#define AR_Q_ONESHOTARM_CC_M 0x000003FF -#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00 - -#define AR_Q0_MISC 0x09c0 -#define AR_Q1_MISC 0x09c4 -#define AR_Q2_MISC 0x09c8 -#define AR_Q3_MISC 0x09cc -#define AR_Q4_MISC 0x09d0 -#define AR_Q5_MISC 0x09d4 -#define AR_Q6_MISC 0x09d8 -#define AR_Q7_MISC 0x09dc -#define AR_Q8_MISC 0x09e0 -#define AR_Q9_MISC 0x09e4 -#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) -#define AR_Q_MISC_FSP 0x0000000F -#define AR_Q_MISC_FSP_ASAP 0 -#define AR_Q_MISC_FSP_CBR 1 -#define AR_Q_MISC_FSP_DBA_GATED 2 -#define AR_Q_MISC_FSP_TIM_GATED 3 -#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 -#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5 -#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 -#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 -#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 -#define AR_Q_MISC_BEACON_USE 0x00000080 -#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100 -#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 -#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 -#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 -#define AR_Q_MISC_RESV0 0xFFFFF000 - -#define AR_Q0_STS 0x0a00 -#define AR_Q1_STS 0x0a04 -#define AR_Q2_STS 0x0a08 -#define AR_Q3_STS 0x0a0c -#define AR_Q4_STS 0x0a10 -#define AR_Q5_STS 0x0a14 -#define AR_Q6_STS 0x0a18 -#define AR_Q7_STS 0x0a1c -#define AR_Q8_STS 0x0a20 -#define AR_Q9_STS 0x0a24 -#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) -#define AR_Q_STS_PEND_FR_CNT 0x00000003 -#define AR_Q_STS_RESV0 0x000000FC -#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 -#define AR_Q_STS_RESV1 0xFFFF0000 - -#define AR_Q_RDYTIMESHDN 0x0a40 -#define AR_Q_RDYTIMESHDN_M 0x000003FF - - -#define AR_NUM_DCU 10 -#define AR_DCU_0 0x0001 -#define AR_DCU_1 0x0002 -#define AR_DCU_2 0x0004 -#define AR_DCU_3 0x0008 -#define AR_DCU_4 0x0010 -#define AR_DCU_5 0x0020 -#define AR_DCU_6 0x0040 -#define AR_DCU_7 0x0080 -#define AR_DCU_8 0x0100 -#define AR_DCU_9 0x0200 - -#define AR_D0_QCUMASK 0x1000 -#define AR_D1_QCUMASK 0x1004 -#define AR_D2_QCUMASK 0x1008 -#define AR_D3_QCUMASK 0x100c -#define AR_D4_QCUMASK 0x1010 -#define AR_D5_QCUMASK 0x1014 -#define AR_D6_QCUMASK 0x1018 -#define AR_D7_QCUMASK 0x101c -#define AR_D8_QCUMASK 0x1020 -#define AR_D9_QCUMASK 0x1024 -#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) -#define AR_D_QCUMASK 0x000003FF -#define AR_D_QCUMASK_RESV0 0xFFFFFC00 - -#define AR_D_TXBLK_CMD 0x1038 -#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) - -#define AR_D0_LCL_IFS 0x1040 -#define AR_D1_LCL_IFS 0x1044 -#define AR_D2_LCL_IFS 0x1048 -#define AR_D3_LCL_IFS 0x104c -#define AR_D4_LCL_IFS 0x1050 -#define AR_D5_LCL_IFS 0x1054 -#define AR_D6_LCL_IFS 0x1058 -#define AR_D7_LCL_IFS 0x105c -#define AR_D8_LCL_IFS 0x1060 -#define AR_D9_LCL_IFS 0x1064 -#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) -#define AR_D_LCL_IFS_CWMIN 0x000003FF -#define AR_D_LCL_IFS_CWMIN_S 0 -#define AR_D_LCL_IFS_CWMAX 0x000FFC00 -#define AR_D_LCL_IFS_CWMAX_S 10 -#define AR_D_LCL_IFS_AIFS 0x0FF00000 -#define AR_D_LCL_IFS_AIFS_S 20 - -#define AR_D_LCL_IFS_RESV0 0xF0000000 - -#define AR_D0_RETRY_LIMIT 0x1080 -#define AR_D1_RETRY_LIMIT 0x1084 -#define AR_D2_RETRY_LIMIT 0x1088 -#define AR_D3_RETRY_LIMIT 0x108c -#define AR_D4_RETRY_LIMIT 0x1090 -#define AR_D5_RETRY_LIMIT 0x1094 -#define AR_D6_RETRY_LIMIT 0x1098 -#define AR_D7_RETRY_LIMIT 0x109c -#define AR_D8_RETRY_LIMIT 0x10a0 -#define AR_D9_RETRY_LIMIT 0x10a4 -#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) -#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F -#define AR_D_RETRY_LIMIT_FR_SH_S 0 -#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 -#define AR_D_RETRY_LIMIT_STA_SH_S 8 -#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 -#define AR_D_RETRY_LIMIT_STA_LG_S 14 -#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 - -#define AR_D0_CHNTIME 0x10c0 -#define AR_D1_CHNTIME 0x10c4 -#define AR_D2_CHNTIME 0x10c8 -#define AR_D3_CHNTIME 0x10cc -#define AR_D4_CHNTIME 0x10d0 -#define AR_D5_CHNTIME 0x10d4 -#define AR_D6_CHNTIME 0x10d8 -#define AR_D7_CHNTIME 0x10dc -#define AR_D8_CHNTIME 0x10e0 -#define AR_D9_CHNTIME 0x10e4 -#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) -#define AR_D_CHNTIME_DUR 0x000FFFFF -#define AR_D_CHNTIME_DUR_S 0 -#define AR_D_CHNTIME_EN 0x00100000 -#define AR_D_CHNTIME_RESV0 0xFFE00000 - -#define AR_D0_MISC 0x1100 -#define AR_D1_MISC 0x1104 -#define AR_D2_MISC 0x1108 -#define AR_D3_MISC 0x110c -#define AR_D4_MISC 0x1110 -#define AR_D5_MISC 0x1114 -#define AR_D6_MISC 0x1118 -#define AR_D7_MISC 0x111c -#define AR_D8_MISC 0x1120 -#define AR_D9_MISC 0x1124 -#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) -#define AR_D_MISC_BKOFF_THRESH 0x0000003F -#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040 -#define AR_D_MISC_CW_RESET_EN 0x00000080 -#define AR_D_MISC_FRAG_WAIT_EN 0x00000100 -#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 -#define AR_D_MISC_CW_BKOFF_EN 0x00001000 -#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 -#define AR_D_MISC_VIR_COL_HANDLING_S 14 -#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 -#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 -#define AR_D_MISC_BEACON_USE 0x00010000 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 -#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 -#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 -#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 -#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000 -#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000 -#define AR_D_MISC_RESV0 0xFF000000 - -#define AR_D_SEQNUM 0x1140 - -#define AR_D_GBL_IFS_SIFS 0x1030 -#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF -#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF - -#define AR_D_TXBLK_BASE 0x1038 -#define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF -#define AR_D_TXBLK_WRITE_BITMASK_S 0 -#define AR_D_TXBLK_WRITE_SLICE 0x000F0000 -#define AR_D_TXBLK_WRITE_SLICE_S 16 -#define AR_D_TXBLK_WRITE_DCU 0x00F00000 -#define AR_D_TXBLK_WRITE_DCU_S 20 -#define AR_D_TXBLK_WRITE_COMMAND 0x0F000000 -#define AR_D_TXBLK_WRITE_COMMAND_S 24 - -#define AR_D_GBL_IFS_SLOT 0x1070 -#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF -#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 - -#define AR_D_GBL_IFS_EIFS 0x10b0 -#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF -#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 - -#define AR_D_GBL_IFS_MISC 0x10f0 -#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 -#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 -#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 -#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 -#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000 -#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000 -#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000 -#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000 - -#define AR_D_FPCTL 0x1230 -#define AR_D_FPCTL_DCU 0x0000000F -#define AR_D_FPCTL_DCU_S 0 -#define AR_D_FPCTL_PREFETCH_EN 0x00000010 -#define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0 -#define AR_D_FPCTL_BURST_PREFETCH_S 5 - -#define AR_D_TXPSE 0x1270 -#define AR_D_TXPSE_CTRL 0x000003FF -#define AR_D_TXPSE_RESV0 0x0000FC00 -#define AR_D_TXPSE_STATUS 0x00010000 -#define AR_D_TXPSE_RESV1 0xFFFE0000 - -#define AR_D_TXSLOTMASK 0x12f0 -#define AR_D_TXSLOTMASK_NUM 0x0000000F - -#define AR_CFG_LED 0x1f04 -#define AR_CFG_SCLK_RATE_IND 0x00000003 -#define AR_CFG_SCLK_RATE_IND_S 0 -#define AR_CFG_SCLK_32MHZ 0x00000000 -#define AR_CFG_SCLK_4MHZ 0x00000001 -#define AR_CFG_SCLK_1MHZ 0x00000002 -#define AR_CFG_SCLK_32KHZ 0x00000003 -#define AR_CFG_LED_BLINK_SLOW 0x00000008 -#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 -#define AR_CFG_LED_MODE_SEL 0x00000380 -#define AR_CFG_LED_MODE_SEL_S 7 -#define AR_CFG_LED_POWER 0x00000280 -#define AR_CFG_LED_POWER_S 7 -#define AR_CFG_LED_NETWORK 0x00000300 -#define AR_CFG_LED_NETWORK_S 7 -#define AR_CFG_LED_MODE_PROP 0x0 -#define AR_CFG_LED_MODE_RPROP 0x1 -#define AR_CFG_LED_MODE_SPLIT 0x2 -#define AR_CFG_LED_MODE_RAND 0x3 -#define AR_CFG_LED_MODE_POWER_OFF 0x4 -#define AR_CFG_LED_MODE_POWER_ON 0x5 -#define AR_CFG_LED_MODE_NETWORK_OFF 0x4 -#define AR_CFG_LED_MODE_NETWORK_ON 0x6 -#define AR_CFG_LED_ASSOC_CTL 0x00000c00 -#define AR_CFG_LED_ASSOC_CTL_S 10 -#define AR_CFG_LED_ASSOC_NONE 0x0 -#define AR_CFG_LED_ASSOC_ACTIVE 0x1 -#define AR_CFG_LED_ASSOC_PENDING 0x2 - -#define AR_CFG_LED_BLINK_SLOW 0x00000008 -#define AR_CFG_LED_BLINK_SLOW_S 3 - -#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 -#define AR_CFG_LED_BLINK_THRESH_SEL_S 4 - -#define AR_MAC_SLEEP 0x1f00 -#define AR_MAC_SLEEP_MAC_AWAKE 0x00000000 -#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001 - -#define AR_RC 0x4000 -#define AR_RC_AHB 0x00000001 -#define AR_RC_APB 0x00000002 -#define AR_RC_HOSTIF 0x00000100 - -#define AR_WA 0x4004 -#define AR9285_WA_DEFAULT 0x004a05cb -#define AR9280_WA_DEFAULT 0x0040073f -#define AR_WA_DEFAULT 0x0000073f - - -#define AR_PM_STATE 0x4008 -#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 - -#define AR_HOST_TIMEOUT 0x4018 -#define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF -#define AR_HOST_TIMEOUT_APB_CNTR_S 0 -#define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 -#define AR_HOST_TIMEOUT_LCL_CNTR_S 16 - -#define AR_EEPROM 0x401c -#define AR_EEPROM_ABSENT 0x00000100 -#define AR_EEPROM_CORRUPT 0x00000200 -#define AR_EEPROM_PROT_MASK 0x03FFFC00 -#define AR_EEPROM_PROT_MASK_S 10 - -#define EEPROM_PROTECT_RP_0_31 0x0001 -#define EEPROM_PROTECT_WP_0_31 0x0002 -#define EEPROM_PROTECT_RP_32_63 0x0004 -#define EEPROM_PROTECT_WP_32_63 0x0008 -#define EEPROM_PROTECT_RP_64_127 0x0010 -#define EEPROM_PROTECT_WP_64_127 0x0020 -#define EEPROM_PROTECT_RP_128_191 0x0040 -#define EEPROM_PROTECT_WP_128_191 0x0080 -#define EEPROM_PROTECT_RP_192_255 0x0100 -#define EEPROM_PROTECT_WP_192_255 0x0200 -#define EEPROM_PROTECT_RP_256_511 0x0400 -#define EEPROM_PROTECT_WP_256_511 0x0800 -#define EEPROM_PROTECT_RP_512_1023 0x1000 -#define EEPROM_PROTECT_WP_512_1023 0x2000 -#define EEPROM_PROTECT_RP_1024_2047 0x4000 -#define EEPROM_PROTECT_WP_1024_2047 0x8000 - -#define AR_SREV \ - ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) - -#define AR_SREV_ID \ - ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) -#define AR_SREV_VERSION 0x000000F0 -#define AR_SREV_VERSION_S 4 -#define AR_SREV_REVISION 0x00000007 - -#define AR_SREV_ID2 0xFFFFFFFF -#define AR_SREV_VERSION2 0xFFFC0000 -#define AR_SREV_VERSION2_S 18 -#define AR_SREV_TYPE2 0x0003F000 -#define AR_SREV_TYPE2_S 12 -#define AR_SREV_TYPE2_CHAIN 0x00001000 -#define AR_SREV_TYPE2_HOST_MODE 0x00002000 -#define AR_SREV_REVISION2 0x00000F00 -#define AR_SREV_REVISION2_S 8 - -#define AR_SREV_VERSION_5416_PCI 0xD -#define AR_SREV_VERSION_5416_PCIE 0xC -#define AR_SREV_REVISION_5416_10 0 -#define AR_SREV_REVISION_5416_20 1 -#define AR_SREV_REVISION_5416_22 2 -#define AR_SREV_VERSION_9100 0x14 -#define AR_SREV_VERSION_9160 0x40 -#define AR_SREV_REVISION_9160_10 0 -#define AR_SREV_REVISION_9160_11 1 -#define AR_SREV_VERSION_9280 0x80 -#define AR_SREV_REVISION_9280_10 0 -#define AR_SREV_REVISION_9280_20 1 -#define AR_SREV_REVISION_9280_21 2 -#define AR_SREV_VERSION_9285 0xC0 -#define AR_SREV_REVISION_9285_10 0 -#define AR_SREV_REVISION_9285_11 1 -#define AR_SREV_REVISION_9285_12 2 - -#define AR_SREV_5416(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ - ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) -#define AR_SREV_5416_20_OR_LATER(_ah) \ - (((AR_SREV_5416(_ah)) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ - ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) -#define AR_SREV_5416_22_OR_LATER(_ah) \ - (((AR_SREV_5416(_ah)) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ - ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) - -#define AR_SREV_9100(ah) \ - ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) -#define AR_SREV_9100_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) - -#define AR_SREV_9160(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) -#define AR_SREV_9160_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160)) -#define AR_SREV_9160_11(_ah) \ - (AR_SREV_9160(_ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) -#define AR_SREV_9280(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) -#define AR_SREV_9280_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280)) -#define AR_SREV_9280_20(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)) -#define AR_SREV_9280_20_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))) - -#define AR_SREV_9285(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) -#define AR_SREV_9285_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) -#define AR_SREV_9285_11(_ah) \ - (AR_SREV_9285(ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) -#define AR_SREV_9285_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ - (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ - AR_SREV_REVISION_9285_11))) -#define AR_SREV_9285_12(_ah) \ - (AR_SREV_9285(ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) -#define AR_SREV_9285_12_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ - (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ - AR_SREV_REVISION_9285_12))) - -#define AR_RADIO_SREV_MAJOR 0xf0 -#define AR_RAD5133_SREV_MAJOR 0xc0 -#define AR_RAD2133_SREV_MAJOR 0xd0 -#define AR_RAD5122_SREV_MAJOR 0xe0 -#define AR_RAD2122_SREV_MAJOR 0xf0 - -#define AR_AHB_MODE 0x4024 -#define AR_AHB_EXACT_WR_EN 0x00000000 -#define AR_AHB_BUF_WR_EN 0x00000001 -#define AR_AHB_EXACT_RD_EN 0x00000000 -#define AR_AHB_CACHELINE_RD_EN 0x00000002 -#define AR_AHB_PREFETCH_RD_EN 0x00000004 -#define AR_AHB_PAGE_SIZE_1K 0x00000000 -#define AR_AHB_PAGE_SIZE_2K 0x00000008 -#define AR_AHB_PAGE_SIZE_4K 0x00000010 - -#define AR_INTR_RTC_IRQ 0x00000001 -#define AR_INTR_MAC_IRQ 0x00000002 -#define AR_INTR_EEP_PROT_ACCESS 0x00000004 -#define AR_INTR_MAC_AWAKE 0x00020000 -#define AR_INTR_MAC_ASLEEP 0x00040000 -#define AR_INTR_SPURIOUS 0xFFFFFFFF - - -#define AR_INTR_SYNC_CAUSE_CLR 0x4028 - -#define AR_INTR_SYNC_CAUSE 0x4028 - -#define AR_INTR_SYNC_ENABLE 0x402c -#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 -#define AR_INTR_SYNC_ENABLE_GPIO_S 18 - -enum { - AR_INTR_SYNC_RTC_IRQ = 0x00000001, - AR_INTR_SYNC_MAC_IRQ = 0x00000002, - AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004, - AR_INTR_SYNC_APB_TIMEOUT = 0x00000008, - AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010, - AR_INTR_SYNC_HOST1_FATAL = 0x00000020, - AR_INTR_SYNC_HOST1_PERR = 0x00000040, - AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080, - AR_INTR_SYNC_RADM_CPL_EP = 0x00000100, - AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200, - AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400, - AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800, - AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000, - AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000, - AR_INTR_SYNC_PM_ACCESS = 0x00004000, - AR_INTR_SYNC_MAC_AWAKE = 0x00008000, - AR_INTR_SYNC_MAC_ASLEEP = 0x00010000, - AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000, - AR_INTR_SYNC_ALL = 0x0003FFFF, - - - AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL | - AR_INTR_SYNC_HOST1_PERR | - AR_INTR_SYNC_RADM_CPL_EP | - AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | - AR_INTR_SYNC_RADM_CPL_TLP_ABORT | - AR_INTR_SYNC_RADM_CPL_ECRC_ERR | - AR_INTR_SYNC_RADM_CPL_TIMEOUT | - AR_INTR_SYNC_LOCAL_TIMEOUT | - AR_INTR_SYNC_MAC_SLEEP_ACCESS), - - AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, - -}; - -#define AR_INTR_ASYNC_MASK 0x4030 -#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 -#define AR_INTR_ASYNC_MASK_GPIO_S 18 - -#define AR_INTR_SYNC_MASK 0x4034 -#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 -#define AR_INTR_SYNC_MASK_GPIO_S 18 - -#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 -#define AR_INTR_ASYNC_CAUSE 0x4038 - -#define AR_INTR_ASYNC_ENABLE 0x403c -#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 -#define AR_INTR_ASYNC_ENABLE_GPIO_S 18 - -#define AR_PCIE_SERDES 0x4040 -#define AR_PCIE_SERDES2 0x4044 -#define AR_PCIE_PM_CTRL 0x4014 -#define AR_PCIE_PM_CTRL_ENA 0x00080000 - -#define AR_NUM_GPIO 14 -#define AR928X_NUM_GPIO 10 -#define AR9285_NUM_GPIO 12 - -#define AR_GPIO_IN_OUT 0x4048 -#define AR_GPIO_IN_VAL 0x0FFFC000 -#define AR_GPIO_IN_VAL_S 14 -#define AR928X_GPIO_IN_VAL 0x000FFC00 -#define AR928X_GPIO_IN_VAL_S 10 -#define AR9285_GPIO_IN_VAL 0x00FFF000 -#define AR9285_GPIO_IN_VAL_S 12 - -#define AR_GPIO_OE_OUT 0x404c -#define AR_GPIO_OE_OUT_DRV 0x3 -#define AR_GPIO_OE_OUT_DRV_NO 0x0 -#define AR_GPIO_OE_OUT_DRV_LOW 0x1 -#define AR_GPIO_OE_OUT_DRV_HI 0x2 -#define AR_GPIO_OE_OUT_DRV_ALL 0x3 - -#define AR_GPIO_INTR_POL 0x4050 -#define AR_GPIO_INTR_POL_VAL 0x00001FFF -#define AR_GPIO_INTR_POL_VAL_S 0 - -#define AR_GPIO_INPUT_EN_VAL 0x4054 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 -#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 -#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 -#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 -#define AR_GPIO_JTAG_DISABLE 0x00020000 - -#define AR_GPIO_INPUT_MUX1 0x4058 -#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 -#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 - -#define AR_GPIO_INPUT_MUX2 0x405c -#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f -#define AR_GPIO_INPUT_MUX2_CLK25_S 0 -#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 -#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4 -#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 -#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 - -#define AR_GPIO_OUTPUT_MUX1 0x4060 -#define AR_GPIO_OUTPUT_MUX2 0x4064 -#define AR_GPIO_OUTPUT_MUX3 0x4068 - -#define AR_INPUT_STATE 0x406c - -#define AR_EEPROM_STATUS_DATA 0x407c -#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff -#define AR_EEPROM_STATUS_DATA_VAL_S 0 -#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 -#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 -#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 -#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 - -#define AR_OBS 0x4080 - -#define AR_PCIE_MSI 0x4094 -#define AR_PCIE_MSI_ENABLE 0x00000001 - - -#define AR_RTC_9160_PLL_DIV 0x000003ff -#define AR_RTC_9160_PLL_DIV_S 0 -#define AR_RTC_9160_PLL_REFDIV 0x00003C00 -#define AR_RTC_9160_PLL_REFDIV_S 10 -#define AR_RTC_9160_PLL_CLKSEL 0x0000C000 -#define AR_RTC_9160_PLL_CLKSEL_S 14 - -#define AR_RTC_BASE 0x00020000 -#define AR_RTC_RC \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000) -#define AR_RTC_RC_M 0x00000003 -#define AR_RTC_RC_MAC_WARM 0x00000001 -#define AR_RTC_RC_MAC_COLD 0x00000002 -#define AR_RTC_RC_COLD_RESET 0x00000004 -#define AR_RTC_RC_WARM_RESET 0x00000008 - -#define AR_RTC_PLL_CONTROL \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) - -#define AR_RTC_PLL_DIV 0x0000001f -#define AR_RTC_PLL_DIV_S 0 -#define AR_RTC_PLL_DIV2 0x00000020 -#define AR_RTC_PLL_REFDIV_5 0x000000c0 -#define AR_RTC_PLL_CLKSEL 0x00000300 -#define AR_RTC_PLL_CLKSEL_S 8 - -#define AR_RTC_RESET \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) -#define AR_RTC_RESET_EN (0x00000001) - -#define AR_RTC_STATUS \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044) - -#define AR_RTC_STATUS_M \ - ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f) - -#define AR_RTC_PM_STATUS_M 0x0000000f - -#define AR_RTC_STATUS_SHUTDOWN 0x00000001 -#define AR_RTC_STATUS_ON 0x00000002 -#define AR_RTC_STATUS_SLEEP 0x00000004 -#define AR_RTC_STATUS_WAKEUP 0x00000008 - -#define AR_RTC_SLEEP_CLK \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048) -#define AR_RTC_FORCE_DERIVED_CLK 0x2 - -#define AR_RTC_FORCE_WAKE \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c) -#define AR_RTC_FORCE_WAKE_EN 0x00000001 -#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 - - -#define AR_RTC_INTR_CAUSE \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050) - -#define AR_RTC_INTR_ENABLE \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054) - -#define AR_RTC_INTR_MASK \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) - -/* RTC_DERIVED_* - only for AR9100 */ - -#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) -#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe -#define AR_RTC_DERIVED_CLK_PERIOD_S 1 - -#define AR_SEQ_MASK 0x8060 - -#define AR_AN_RF2G1_CH0 0x7810 -#define AR_AN_RF2G1_CH0_OB 0x03800000 -#define AR_AN_RF2G1_CH0_OB_S 23 -#define AR_AN_RF2G1_CH0_DB 0x1C000000 -#define AR_AN_RF2G1_CH0_DB_S 26 - -#define AR_AN_RF5G1_CH0 0x7818 -#define AR_AN_RF5G1_CH0_OB5 0x00070000 -#define AR_AN_RF5G1_CH0_OB5_S 16 -#define AR_AN_RF5G1_CH0_DB5 0x00380000 -#define AR_AN_RF5G1_CH0_DB5_S 19 - -#define AR_AN_RF2G1_CH1 0x7834 -#define AR_AN_RF2G1_CH1_OB 0x03800000 -#define AR_AN_RF2G1_CH1_OB_S 23 -#define AR_AN_RF2G1_CH1_DB 0x1C000000 -#define AR_AN_RF2G1_CH1_DB_S 26 - -#define AR_AN_RF5G1_CH1 0x783C -#define AR_AN_RF5G1_CH1_OB5 0x00070000 -#define AR_AN_RF5G1_CH1_OB5_S 16 -#define AR_AN_RF5G1_CH1_DB5 0x00380000 -#define AR_AN_RF5G1_CH1_DB5_S 19 - -#define AR_AN_TOP1 0x7890 -#define AR_AN_TOP1_DACIPMODE 0x00040000 -#define AR_AN_TOP1_DACIPMODE_S 18 - -#define AR_AN_TOP2 0x7894 -#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 -#define AR_AN_TOP2_XPABIAS_LVL_S 30 -#define AR_AN_TOP2_LOCALBIAS 0x00200000 -#define AR_AN_TOP2_LOCALBIAS_S 21 -#define AR_AN_TOP2_PWDCLKIND 0x00400000 -#define AR_AN_TOP2_PWDCLKIND_S 22 - -#define AR_AN_SYNTH9 0x7868 -#define AR_AN_SYNTH9_REFDIVA 0xf8000000 -#define AR_AN_SYNTH9_REFDIVA_S 27 - -#define AR9285_AN_RF2G1 0x7820 -#define AR9285_AN_RF2G1_ENPACAL 0x00000800 -#define AR9285_AN_RF2G1_ENPACAL_S 11 -#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 -#define AR9285_AN_RF2G1_PDPADRV1_S 25 -#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 -#define AR9285_AN_RF2G1_PDPADRV2_S 24 -#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 -#define AR9285_AN_RF2G1_PDPAOUT_S 23 - - -#define AR9285_AN_RF2G2 0x7824 -#define AR9285_AN_RF2G2_OFFCAL 0x00001000 -#define AR9285_AN_RF2G2_OFFCAL_S 12 - -#define AR9285_AN_RF2G3 0x7828 -#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 -#define AR9285_AN_RF2G3_PDVCCOMP_S 25 -#define AR9285_AN_RF2G3_OB_0 0x00E00000 -#define AR9285_AN_RF2G3_OB_0_S 21 -#define AR9285_AN_RF2G3_OB_1 0x001C0000 -#define AR9285_AN_RF2G3_OB_1_S 18 -#define AR9285_AN_RF2G3_OB_2 0x00038000 -#define AR9285_AN_RF2G3_OB_2_S 15 -#define AR9285_AN_RF2G3_OB_3 0x00007000 -#define AR9285_AN_RF2G3_OB_3_S 12 -#define AR9285_AN_RF2G3_OB_4 0x00000E00 -#define AR9285_AN_RF2G3_OB_4_S 9 - -#define AR9285_AN_RF2G3_DB1_0 0x000001C0 -#define AR9285_AN_RF2G3_DB1_0_S 6 -#define AR9285_AN_RF2G3_DB1_1 0x00000038 -#define AR9285_AN_RF2G3_DB1_1_S 3 -#define AR9285_AN_RF2G3_DB1_2 0x00000007 -#define AR9285_AN_RF2G3_DB1_2_S 0 -#define AR9285_AN_RF2G4 0x782C -#define AR9285_AN_RF2G4_DB1_3 0xE0000000 -#define AR9285_AN_RF2G4_DB1_3_S 29 -#define AR9285_AN_RF2G4_DB1_4 0x1C000000 -#define AR9285_AN_RF2G4_DB1_4_S 26 - -#define AR9285_AN_RF2G4_DB2_0 0x03800000 -#define AR9285_AN_RF2G4_DB2_0_S 23 -#define AR9285_AN_RF2G4_DB2_1 0x00700000 -#define AR9285_AN_RF2G4_DB2_1_S 20 -#define AR9285_AN_RF2G4_DB2_2 0x000E0000 -#define AR9285_AN_RF2G4_DB2_2_S 17 -#define AR9285_AN_RF2G4_DB2_3 0x0001C000 -#define AR9285_AN_RF2G4_DB2_3_S 14 -#define AR9285_AN_RF2G4_DB2_4 0x00003800 -#define AR9285_AN_RF2G4_DB2_4_S 11 - -#define AR9285_AN_RF2G6 0x7834 -#define AR9285_AN_RF2G6_CCOMP 0x00007800 -#define AR9285_AN_RF2G6_CCOMP_S 11 -#define AR9285_AN_RF2G6_OFFS 0x03f00000 -#define AR9285_AN_RF2G6_OFFS_S 20 - -#define AR9285_AN_RF2G7 0x7838 -#define AR9285_AN_RF2G7_PWDDB 0x00000002 -#define AR9285_AN_RF2G7_PWDDB_S 1 -#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 -#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 - -#define AR9285_AN_RF2G8 0x783C -#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 -#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 - - -#define AR9285_AN_RF2G9 0x7840 -#define AR9285_AN_RXTXBB1 0x7854 -#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 -#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 -#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 -#define AR9285_AN_RXTXBB1_PDV2I_S 7 -#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 -#define AR9285_AN_RXTXBB1_PDDACIF_S 8 -#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 -#define AR9285_AN_RXTXBB1_SPARE9_S 0 - -#define AR9285_AN_TOP2 0x7868 - -#define AR9285_AN_TOP3 0x786c -#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C -#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 -#define AR9285_AN_TOP3_PWDDAC 0x00800000 -#define AR9285_AN_TOP3_PWDDAC_S 23 - -#define AR9285_AN_TOP4 0x7870 -#define AR9285_AN_TOP4_DEFAULT 0x10142c00 - -#define AR_STA_ID0 0x8000 -#define AR_STA_ID1 0x8004 -#define AR_STA_ID1_SADH_MASK 0x0000FFFF -#define AR_STA_ID1_STA_AP 0x00010000 -#define AR_STA_ID1_ADHOC 0x00020000 -#define AR_STA_ID1_PWR_SAV 0x00040000 -#define AR_STA_ID1_KSRCHDIS 0x00080000 -#define AR_STA_ID1_PCF 0x00100000 -#define AR_STA_ID1_USE_DEFANT 0x00200000 -#define AR_STA_ID1_DEFANT_UPDATE 0x00400000 -#define AR_STA_ID1_RTS_USE_DEF 0x00800000 -#define AR_STA_ID1_ACKCTS_6MB 0x01000000 -#define AR_STA_ID1_BASE_RATE_11B 0x02000000 -#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000 -#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 -#define AR_STA_ID1_KSRCH_MODE 0x10000000 -#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 -#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 -#define AR_STA_ID1_MCAST_KSRCH 0x80000000 - -#define AR_BSS_ID0 0x8008 -#define AR_BSS_ID1 0x800C -#define AR_BSS_ID1_U16 0x0000FFFF -#define AR_BSS_ID1_AID 0x07FF0000 -#define AR_BSS_ID1_AID_S 16 - -#define AR_BCN_RSSI_AVE 0x8010 -#define AR_BCN_RSSI_AVE_MASK 0x00000FFF - -#define AR_TIME_OUT 0x8014 -#define AR_TIME_OUT_ACK 0x00003FFF -#define AR_TIME_OUT_ACK_S 0 -#define AR_TIME_OUT_CTS 0x3FFF0000 -#define AR_TIME_OUT_CTS_S 16 - -#define AR_RSSI_THR 0x8018 -#define AR_RSSI_THR_MASK 0x000000FF -#define AR_RSSI_THR_BM_THR 0x0000FF00 -#define AR_RSSI_THR_BM_THR_S 8 -#define AR_RSSI_BCN_WEIGHT 0x1F000000 -#define AR_RSSI_BCN_WEIGHT_S 24 -#define AR_RSSI_BCN_RSSI_RST 0x20000000 - -#define AR_USEC 0x801c -#define AR_USEC_USEC 0x0000007F -#define AR_USEC_TX_LAT 0x007FC000 -#define AR_USEC_TX_LAT_S 14 -#define AR_USEC_RX_LAT 0x1F800000 -#define AR_USEC_RX_LAT_S 23 - -#define AR_RESET_TSF 0x8020 -#define AR_RESET_TSF_ONCE 0x01000000 - -#define AR_MAX_CFP_DUR 0x8038 -#define AR_CFP_VAL 0x0000FFFF - -#define AR_RX_FILTER 0x803C -#define AR_RX_COMPR_BAR 0x00000400 - -#define AR_MCAST_FIL0 0x8040 -#define AR_MCAST_FIL1 0x8044 - -#define AR_DIAG_SW 0x8048 -#define AR_DIAG_CACHE_ACK 0x00000001 -#define AR_DIAG_ACK_DIS 0x00000002 -#define AR_DIAG_CTS_DIS 0x00000004 -#define AR_DIAG_ENCRYPT_DIS 0x00000008 -#define AR_DIAG_DECRYPT_DIS 0x00000010 -#define AR_DIAG_RX_DIS 0x00000020 -#define AR_DIAG_LOOP_BACK 0x00000040 -#define AR_DIAG_CORR_FCS 0x00000080 -#define AR_DIAG_CHAN_INFO 0x00000100 -#define AR_DIAG_SCRAM_SEED 0x0001FE00 -#define AR_DIAG_SCRAM_SEED_S 8 -#define AR_DIAG_FRAME_NV0 0x00020000 -#define AR_DIAG_OBS_PT_SEL1 0x000C0000 -#define AR_DIAG_OBS_PT_SEL1_S 18 -#define AR_DIAG_FORCE_RX_CLEAR 0x00100000 -#define AR_DIAG_IGNORE_VIRT_CS 0x00200000 -#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 -#define AR_DIAG_EIFS_CTRL_ENA 0x00800000 -#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 -#define AR_DIAG_RX_ABORT 0x02000000 -#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000 -#define AR_DIAG_OBS_PT_SEL2 0x08000000 -#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000 -#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000 - -#define AR_TSF_L32 0x804c -#define AR_TSF_U32 0x8050 - -#define AR_TST_ADDAC 0x8054 -#define AR_DEF_ANTENNA 0x8058 - -#define AR_AES_MUTE_MASK0 0x805c -#define AR_AES_MUTE_MASK0_FC 0x0000FFFF -#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 -#define AR_AES_MUTE_MASK0_QOS_S 16 - -#define AR_AES_MUTE_MASK1 0x8060 -#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF -#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 -#define AR_AES_MUTE_MASK1_FC_MGMT_S 16 - -#define AR_GATED_CLKS 0x8064 -#define AR_GATED_CLKS_TX 0x00000002 -#define AR_GATED_CLKS_RX 0x00000004 -#define AR_GATED_CLKS_REG 0x00000008 - -#define AR_OBS_BUS_CTRL 0x8068 -#define AR_OBS_BUS_SEL_1 0x00040000 -#define AR_OBS_BUS_SEL_2 0x00080000 -#define AR_OBS_BUS_SEL_3 0x000C0000 -#define AR_OBS_BUS_SEL_4 0x08040000 -#define AR_OBS_BUS_SEL_5 0x08080000 - -#define AR_OBS_BUS_1 0x806c -#define AR_OBS_BUS_1_PCU 0x00000001 -#define AR_OBS_BUS_1_RX_END 0x00000002 -#define AR_OBS_BUS_1_RX_WEP 0x00000004 -#define AR_OBS_BUS_1_RX_BEACON 0x00000008 -#define AR_OBS_BUS_1_RX_FILTER 0x00000010 -#define AR_OBS_BUS_1_TX_HCF 0x00000020 -#define AR_OBS_BUS_1_QUIET_TIME 0x00000040 -#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080 -#define AR_OBS_BUS_1_TX_HOLD 0x00000100 -#define AR_OBS_BUS_1_TX_FRAME 0x00000200 -#define AR_OBS_BUS_1_RX_FRAME 0x00000400 -#define AR_OBS_BUS_1_RX_CLEAR 0x00000800 -#define AR_OBS_BUS_1_WEP_STATE 0x0003F000 -#define AR_OBS_BUS_1_WEP_STATE_S 12 -#define AR_OBS_BUS_1_RX_STATE 0x01F00000 -#define AR_OBS_BUS_1_RX_STATE_S 20 -#define AR_OBS_BUS_1_TX_STATE 0x7E000000 -#define AR_OBS_BUS_1_TX_STATE_S 25 - -#define AR_LAST_TSTP 0x8080 -#define AR_NAV 0x8084 -#define AR_RTS_OK 0x8088 -#define AR_RTS_FAIL 0x808c -#define AR_ACK_FAIL 0x8090 -#define AR_FCS_FAIL 0x8094 -#define AR_BEACON_CNT 0x8098 - -#define AR_SLEEP1 0x80d4 -#define AR_SLEEP1_ASSUME_DTIM 0x00080000 -#define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000 -#define AR_SLEEP1_CAB_TIMEOUT_S 21 - -#define AR_SLEEP2 0x80d8 -#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 -#define AR_SLEEP2_BEACON_TIMEOUT_S 21 - -#define AR_BSSMSKL 0x80e0 -#define AR_BSSMSKU 0x80e4 - -#define AR_TPC 0x80e8 -#define AR_TPC_ACK 0x0000003f -#define AR_TPC_ACK_S 0x00 -#define AR_TPC_CTS 0x00003f00 -#define AR_TPC_CTS_S 0x08 -#define AR_TPC_CHIRP 0x003f0000 -#define AR_TPC_CHIRP_S 0x16 - -#define AR_TFCNT 0x80ec -#define AR_RFCNT 0x80f0 -#define AR_RCCNT 0x80f4 -#define AR_CCCNT 0x80f8 - -#define AR_QUIET1 0x80fc -#define AR_QUIET1_NEXT_QUIET_S 0 -#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff -#define AR_QUIET1_QUIET_ENABLE 0x00010000 -#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 -#define AR_QUIET2 0x8100 -#define AR_QUIET2_QUIET_PERIOD_S 0 -#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff -#define AR_QUIET2_QUIET_DUR_S 16 -#define AR_QUIET2_QUIET_DUR 0xffff0000 - -#define AR_TSF_PARM 0x8104 -#define AR_TSF_INCREMENT_M 0x000000ff -#define AR_TSF_INCREMENT_S 0x00 - -#define AR_QOS_NO_ACK 0x8108 -#define AR_QOS_NO_ACK_TWO_BIT 0x0000000f -#define AR_QOS_NO_ACK_TWO_BIT_S 0 -#define AR_QOS_NO_ACK_BIT_OFF 0x00000070 -#define AR_QOS_NO_ACK_BIT_OFF_S 4 -#define AR_QOS_NO_ACK_BYTE_OFF 0x00000180 -#define AR_QOS_NO_ACK_BYTE_OFF_S 7 - -#define AR_PHY_ERR 0x810c - -#define AR_PHY_ERR_DCHIRP 0x00000008 -#define AR_PHY_ERR_RADAR 0x00000020 -#define AR_PHY_ERR_OFDM_TIMING 0x00020000 -#define AR_PHY_ERR_CCK_TIMING 0x02000000 - -#define AR_RXFIFO_CFG 0x8114 - - -#define AR_MIC_QOS_CONTROL 0x8118 -#define AR_MIC_QOS_SELECT 0x811c - -#define AR_PCU_MISC 0x8120 -#define AR_PCU_FORCE_BSSID_MATCH 0x00000001 -#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 -#define AR_PCU_TX_ADD_TSF 0x00000008 -#define AR_PCU_CCK_SIFS_MODE 0x00000010 -#define AR_PCU_RX_ANT_UPDT 0x00000800 -#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 -#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 -#define AR_PCU_BUG_12306_FIX_ENA 0x00020000 -#define AR_PCU_FORCE_QUIET_COLL 0x00040000 -#define AR_PCU_TBTT_PROTECT 0x00200000 -#define AR_PCU_CLEAR_VMF 0x01000000 -#define AR_PCU_CLEAR_BA_VALID 0x04000000 - - -#define AR_FILT_OFDM 0x8124 -#define AR_FILT_OFDM_COUNT 0x00FFFFFF - -#define AR_FILT_CCK 0x8128 -#define AR_FILT_CCK_COUNT 0x00FFFFFF - -#define AR_PHY_ERR_1 0x812c -#define AR_PHY_ERR_1_COUNT 0x00FFFFFF -#define AR_PHY_ERR_MASK_1 0x8130 - -#define AR_PHY_ERR_2 0x8134 -#define AR_PHY_ERR_2_COUNT 0x00FFFFFF -#define AR_PHY_ERR_MASK_2 0x8138 - -#define AR_PHY_COUNTMAX (3 << 22) -#define AR_MIBCNT_INTRMASK (3 << 22) - -#define AR_TSFOOR_THRESHOLD 0x813c -#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF - -#define AR_PHY_ERR_EIFS_MASK 8144 - -#define AR_PHY_ERR_3 0x8168 -#define AR_PHY_ERR_3_COUNT 0x00FFFFFF -#define AR_PHY_ERR_MASK_3 0x816c - -#define AR_TXSIFS 0x81d0 -#define AR_TXSIFS_TIME 0x000000FF -#define AR_TXSIFS_TX_LATENCY 0x00000F00 -#define AR_TXSIFS_TX_LATENCY_S 8 -#define AR_TXSIFS_ACK_SHIFT 0x00007000 -#define AR_TXSIFS_ACK_SHIFT_S 12 - -#define AR_TXOP_X 0x81ec -#define AR_TXOP_X_VAL 0x000000FF - - -#define AR_TXOP_0_3 0x81f0 -#define AR_TXOP_4_7 0x81f4 -#define AR_TXOP_8_11 0x81f8 -#define AR_TXOP_12_15 0x81fc - - -#define AR_NEXT_TBTT_TIMER 0x8200 -#define AR_NEXT_DMA_BEACON_ALERT 0x8204 -#define AR_NEXT_SWBA 0x8208 -#define AR_NEXT_CFP 0x8208 -#define AR_NEXT_HCF 0x820C -#define AR_NEXT_TIM 0x8210 -#define AR_NEXT_DTIM 0x8214 -#define AR_NEXT_QUIET_TIMER 0x8218 -#define AR_NEXT_NDP_TIMER 0x821C - -#define AR_BEACON_PERIOD 0x8220 -#define AR_DMA_BEACON_PERIOD 0x8224 -#define AR_SWBA_PERIOD 0x8228 -#define AR_HCF_PERIOD 0x822C -#define AR_TIM_PERIOD 0x8230 -#define AR_DTIM_PERIOD 0x8234 -#define AR_QUIET_PERIOD 0x8238 -#define AR_NDP_PERIOD 0x823C - -#define AR_TIMER_MODE 0x8240 -#define AR_TBTT_TIMER_EN 0x00000001 -#define AR_DBA_TIMER_EN 0x00000002 -#define AR_SWBA_TIMER_EN 0x00000004 -#define AR_HCF_TIMER_EN 0x00000008 -#define AR_TIM_TIMER_EN 0x00000010 -#define AR_DTIM_TIMER_EN 0x00000020 -#define AR_QUIET_TIMER_EN 0x00000040 -#define AR_NDP_TIMER_EN 0x00000080 -#define AR_TIMER_OVERFLOW_INDEX 0x00000700 -#define AR_TIMER_OVERFLOW_INDEX_S 8 -#define AR_TIMER_THRESH 0xFFFFF000 -#define AR_TIMER_THRESH_S 12 - -#define AR_SLP32_MODE 0x8244 -#define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF -#define AR_SLP32_ENA 0x00100000 -#define AR_SLP32_TSF_WRITE_STATUS 0x00200000 - -#define AR_SLP32_WAKE 0x8248 -#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF - -#define AR_SLP32_INC 0x824c -#define AR_SLP32_TST_INC 0x000FFFFF - -#define AR_SLP_CNT 0x8250 -#define AR_SLP_CYCLE_CNT 0x8254 - -#define AR_SLP_MIB_CTRL 0x8258 -#define AR_SLP_MIB_CLEAR 0x00000001 -#define AR_SLP_MIB_PENDING 0x00000002 - -#define AR_2040_MODE 0x8318 -#define AR_2040_JOINED_RX_CLEAR 0x00000001 - - -#define AR_EXTRCCNT 0x8328 - -#define AR_SELFGEN_MASK 0x832c - -#define AR_PCU_TXBUF_CTRL 0x8340 -#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF -#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 -#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 - -#define AR_PCU_MISC_MODE2 0x8344 -#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 -#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 - -#define AR_KEYTABLE_0 0x8800 -#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) -#define AR_KEY_CACHE_SIZE 128 -#define AR_RSVD_KEYTABLE_ENTRIES 4 -#define AR_KEY_TYPE 0x00000007 -#define AR_KEYTABLE_TYPE_40 0x00000000 -#define AR_KEYTABLE_TYPE_104 0x00000001 -#define AR_KEYTABLE_TYPE_128 0x00000003 -#define AR_KEYTABLE_TYPE_TKIP 0x00000004 -#define AR_KEYTABLE_TYPE_AES 0x00000005 -#define AR_KEYTABLE_TYPE_CCM 0x00000006 -#define AR_KEYTABLE_TYPE_CLR 0x00000007 -#define AR_KEYTABLE_ANT 0x00000008 -#define AR_KEYTABLE_VALID 0x00008000 -#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) -#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) -#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) -#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) -#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) -#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) -#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) -#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) - -#endif diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath9k/virtual.c deleted file mode 100644 index 1ff429b027d7..000000000000 --- a/drivers/net/wireless/ath9k/virtual.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * 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 "ath9k.h" - -struct ath9k_vif_iter_data { - int count; - u8 *addr; -}; - -static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath9k_vif_iter_data *iter_data = data; - u8 *nbuf; - - nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN, - GFP_ATOMIC); - if (nbuf == NULL) - return; - - memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN); - iter_data->addr = nbuf; - iter_data->count++; -} - -void ath9k_set_bssid_mask(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath9k_vif_iter_data iter_data; - int i, j; - u8 mask[ETH_ALEN]; - - /* - * Add primary MAC address even if it is not in active use since it - * will be configured to the hardware as the starting point and the - * BSSID mask will need to be changed if another address is active. - */ - iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); - if (iter_data.addr) { - memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN); - iter_data.count = 1; - } else - iter_data.count = 0; - - /* Get list of all active MAC addresses */ - spin_lock_bh(&sc->wiphy_lock); - ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, - &iter_data); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] == NULL) - continue; - ieee80211_iterate_active_interfaces_atomic( - sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data); - } - spin_unlock_bh(&sc->wiphy_lock); - - /* Generate an address mask to cover all active addresses */ - memset(mask, 0, ETH_ALEN); - for (i = 0; i < iter_data.count; i++) { - u8 *a1 = iter_data.addr + i * ETH_ALEN; - for (j = i + 1; j < iter_data.count; j++) { - u8 *a2 = iter_data.addr + j * ETH_ALEN; - mask[0] |= a1[0] ^ a2[0]; - mask[1] |= a1[1] ^ a2[1]; - mask[2] |= a1[2] ^ a2[2]; - mask[3] |= a1[3] ^ a2[3]; - mask[4] |= a1[4] ^ a2[4]; - mask[5] |= a1[5] ^ a2[5]; - } - } - - kfree(iter_data.addr); - - /* Invert the mask and configure hardware */ - sc->bssidmask[0] = ~mask[0]; - sc->bssidmask[1] = ~mask[1]; - sc->bssidmask[2] = ~mask[2]; - sc->bssidmask[3] = ~mask[3]; - sc->bssidmask[4] = ~mask[4]; - sc->bssidmask[5] = ~mask[5]; - - ath9k_hw_setbssidmask(sc); -} - -int ath9k_wiphy_add(struct ath_softc *sc) -{ - int i, error; - struct ath_wiphy *aphy; - struct ieee80211_hw *hw; - u8 addr[ETH_ALEN]; - - hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); - if (hw == NULL) - return -ENOMEM; - - spin_lock_bh(&sc->wiphy_lock); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] == NULL) - break; - } - - if (i == sc->num_sec_wiphy) { - /* No empty slot available; increase array length */ - struct ath_wiphy **n; - n = krealloc(sc->sec_wiphy, - (sc->num_sec_wiphy + 1) * - sizeof(struct ath_wiphy *), - GFP_ATOMIC); - if (n == NULL) { - spin_unlock_bh(&sc->wiphy_lock); - ieee80211_free_hw(hw); - return -ENOMEM; - } - n[i] = NULL; - sc->sec_wiphy = n; - sc->num_sec_wiphy++; - } - - SET_IEEE80211_DEV(hw, sc->dev); - - aphy = hw->priv; - aphy->sc = sc; - aphy->hw = hw; - sc->sec_wiphy[i] = aphy; - spin_unlock_bh(&sc->wiphy_lock); - - memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN); - addr[0] |= 0x02; /* Locally managed address */ - /* - * XOR virtual wiphy index into the least significant bits to generate - * a different MAC address for each virtual wiphy. - */ - addr[5] ^= i & 0xff; - addr[4] ^= (i & 0xff00) >> 8; - addr[3] ^= (i & 0xff0000) >> 16; - - SET_IEEE80211_PERM_ADDR(hw, addr); - - ath_set_hw_capab(sc, hw); - - error = ieee80211_register_hw(hw); - - if (error == 0) { - /* Make sure wiphy scheduler is started (if enabled) */ - ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); - } - - return error; -} - -int ath9k_wiphy_del(struct ath_wiphy *aphy) -{ - struct ath_softc *sc = aphy->sc; - int i; - - spin_lock_bh(&sc->wiphy_lock); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (aphy == sc->sec_wiphy[i]) { - sc->sec_wiphy[i] = NULL; - spin_unlock_bh(&sc->wiphy_lock); - ieee80211_unregister_hw(aphy->hw); - ieee80211_free_hw(aphy->hw); - return 0; - } - } - spin_unlock_bh(&sc->wiphy_lock); - return -ENOENT; -} - -static int ath9k_send_nullfunc(struct ath_wiphy *aphy, - struct ieee80211_vif *vif, const u8 *bssid, - int ps) -{ - struct ath_softc *sc = aphy->sc; - struct ath_tx_control txctl; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - __le16 fc; - struct ieee80211_tx_info *info; - - skb = dev_alloc_skb(24); - if (skb == NULL) - return -ENOMEM; - hdr = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(hdr, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - if (ps) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - hdr->frame_control = fc; - memcpy(hdr->addr1, bssid, ETH_ALEN); - memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN); - memcpy(hdr->addr3, bssid, ETH_ALEN); - - info = IEEE80211_SKB_CB(skb); - memset(info, 0, sizeof(*info)); - info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS; - info->control.vif = vif; - info->control.rates[0].idx = 0; - info->control.rates[0].count = 4; - info->control.rates[1].idx = -1; - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; - txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE; - - if (ath_tx_start(aphy->hw, skb, &txctl) != 0) - goto exit; - - return 0; -exit: - dev_kfree_skb_any(skb); - return -1; -} - -static bool __ath9k_wiphy_pausing(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING) - return true; - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING) - return true; - } - return false; -} - -static bool ath9k_wiphy_pausing(struct ath_softc *sc) -{ - bool ret; - spin_lock_bh(&sc->wiphy_lock); - ret = __ath9k_wiphy_pausing(sc); - spin_unlock_bh(&sc->wiphy_lock); - return ret; -} - -static bool __ath9k_wiphy_scanning(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) - return true; - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) - return true; - } - return false; -} - -bool ath9k_wiphy_scanning(struct ath_softc *sc) -{ - bool ret; - spin_lock_bh(&sc->wiphy_lock); - ret = __ath9k_wiphy_scanning(sc); - spin_unlock_bh(&sc->wiphy_lock); - return ret; -} - -static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); - -/* caller must hold wiphy_lock */ -static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy) -{ - if (aphy == NULL) - return; - if (aphy->chan_idx != aphy->sc->chan_idx) - return; /* wiphy not on the selected channel */ - __ath9k_wiphy_unpause(aphy); -} - -static void ath9k_wiphy_unpause_channel(struct ath_softc *sc) -{ - int i; - spin_lock_bh(&sc->wiphy_lock); - __ath9k_wiphy_unpause_ch(sc->pri_wiphy); - for (i = 0; i < sc->num_sec_wiphy; i++) - __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]); - spin_unlock_bh(&sc->wiphy_lock); -} - -void ath9k_wiphy_chan_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); - struct ath_wiphy *aphy = sc->next_wiphy; - - if (aphy == NULL) - return; - - /* - * All pending interfaces paused; ready to change - * channels. - */ - - /* Change channels */ - mutex_lock(&sc->mutex); - /* XXX: remove me eventually */ - ath9k_update_ichannel(sc, aphy->hw, - &sc->sc_ah->channels[sc->chan_idx]); - ath_update_chainmask(sc, sc->chan_is_ht); - if (ath_set_channel(sc, aphy->hw, - &sc->sc_ah->channels[sc->chan_idx]) < 0) { - printk(KERN_DEBUG "ath9k: Failed to set channel for new " - "virtual wiphy\n"); - mutex_unlock(&sc->mutex); - return; - } - mutex_unlock(&sc->mutex); - - ath9k_wiphy_unpause_channel(sc); -} - -/* - * ath9k version of ieee80211_tx_status() for TX frames that are generated - * internally in the driver. - */ -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - - if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE && - aphy->state == ATH_WIPHY_PAUSING) { - if (!(info->flags & IEEE80211_TX_STAT_ACK)) { - printk(KERN_DEBUG "ath9k: %s: no ACK for pause " - "frame\n", wiphy_name(hw->wiphy)); - /* - * The AP did not reply; ignore this to allow us to - * continue. - */ - } - aphy->state = ATH_WIPHY_PAUSED; - if (!ath9k_wiphy_pausing(aphy->sc)) { - /* - * Drop from tasklet to work to allow mutex for channel - * change. - */ - queue_work(aphy->sc->hw->workqueue, - &aphy->sc->chan_work); - } - } - - kfree(tx_info_priv); - tx_info->rate_driver_data[0] = NULL; - - dev_kfree_skb(skb); -} - -static void ath9k_mark_paused(struct ath_wiphy *aphy) -{ - struct ath_softc *sc = aphy->sc; - aphy->state = ATH_WIPHY_PAUSED; - if (!__ath9k_wiphy_pausing(sc)) - queue_work(sc->hw->workqueue, &sc->chan_work); -} - -static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath_wiphy *aphy = data; - struct ath_vif *avp = (void *) vif->drv_priv; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - if (!vif->bss_conf.assoc) { - ath9k_mark_paused(aphy); - break; - } - /* TODO: could avoid this if already in PS mode */ - if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) { - printk(KERN_DEBUG "%s: failed to send PS nullfunc\n", - __func__); - ath9k_mark_paused(aphy); - } - break; - case NL80211_IFTYPE_AP: - /* Beacon transmission is paused by aphy->state change */ - ath9k_mark_paused(aphy); - break; - default: - break; - } -} - -/* caller must hold wiphy_lock */ -static int __ath9k_wiphy_pause(struct ath_wiphy *aphy) -{ - ieee80211_stop_queues(aphy->hw); - aphy->state = ATH_WIPHY_PAUSING; - /* - * TODO: handle PAUSING->PAUSED for the case where there are multiple - * active vifs (now we do it on the first vif getting ready; should be - * on the last) - */ - ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter, - aphy); - return 0; -} - -int ath9k_wiphy_pause(struct ath_wiphy *aphy) -{ - int ret; - spin_lock_bh(&aphy->sc->wiphy_lock); - ret = __ath9k_wiphy_pause(aphy); - spin_unlock_bh(&aphy->sc->wiphy_lock); - return ret; -} - -static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath_wiphy *aphy = data; - struct ath_vif *avp = (void *) vif->drv_priv; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - if (!vif->bss_conf.assoc) - break; - ath9k_send_nullfunc(aphy, vif, avp->bssid, 0); - break; - case NL80211_IFTYPE_AP: - /* Beacon transmission is re-enabled by aphy->state change */ - break; - default: - break; - } -} - -/* caller must hold wiphy_lock */ -static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy) -{ - ieee80211_iterate_active_interfaces_atomic(aphy->hw, - ath9k_unpause_iter, aphy); - aphy->state = ATH_WIPHY_ACTIVE; - ieee80211_wake_queues(aphy->hw); - return 0; -} - -int ath9k_wiphy_unpause(struct ath_wiphy *aphy) -{ - int ret; - spin_lock_bh(&aphy->sc->wiphy_lock); - ret = __ath9k_wiphy_unpause(aphy); - spin_unlock_bh(&aphy->sc->wiphy_lock); - return ret; -} - -static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) - sc->pri_wiphy->state = ATH_WIPHY_PAUSED; - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) - sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED; - } -} - -/* caller must hold wiphy_lock */ -static void __ath9k_wiphy_pause_all(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) - __ath9k_wiphy_pause(sc->pri_wiphy); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) - __ath9k_wiphy_pause(sc->sec_wiphy[i]); - } -} - -int ath9k_wiphy_select(struct ath_wiphy *aphy) -{ - struct ath_softc *sc = aphy->sc; - bool now; - - spin_lock_bh(&sc->wiphy_lock); - if (__ath9k_wiphy_scanning(sc)) { - /* - * For now, we are using mac80211 sw scan and it expects to - * have full control over channel changes, so avoid wiphy - * scheduling during a scan. This could be optimized if the - * scanning control were moved into the driver. - */ - spin_unlock_bh(&sc->wiphy_lock); - return -EBUSY; - } - if (__ath9k_wiphy_pausing(sc)) { - if (sc->wiphy_select_failures == 0) - sc->wiphy_select_first_fail = jiffies; - sc->wiphy_select_failures++; - if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2)) - { - printk(KERN_DEBUG "ath9k: Previous wiphy select timed " - "out; disable/enable hw to recover\n"); - __ath9k_wiphy_mark_all_paused(sc); - /* - * TODO: this workaround to fix hardware is unlikely to - * be specific to virtual wiphy changes. It can happen - * on normal channel change, too, and as such, this - * should really be made more generic. For example, - * tricker radio disable/enable on GTT interrupt burst - * (say, 10 GTT interrupts received without any TX - * frame being completed) - */ - spin_unlock_bh(&sc->wiphy_lock); - ath_radio_disable(sc); - ath_radio_enable(sc); - queue_work(aphy->sc->hw->workqueue, - &aphy->sc->chan_work); - return -EBUSY; /* previous select still in progress */ - } - spin_unlock_bh(&sc->wiphy_lock); - return -EBUSY; /* previous select still in progress */ - } - sc->wiphy_select_failures = 0; - - /* Store the new channel */ - sc->chan_idx = aphy->chan_idx; - sc->chan_is_ht = aphy->chan_is_ht; - sc->next_wiphy = aphy; - - __ath9k_wiphy_pause_all(sc); - now = !__ath9k_wiphy_pausing(aphy->sc); - spin_unlock_bh(&sc->wiphy_lock); - - if (now) { - /* Ready to request channel change immediately */ - queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work); - } - - /* - * wiphys will be unpaused in ath9k_tx_status() once channel has been - * changed if any wiphy needs time to become paused. - */ - - return 0; -} - -bool ath9k_wiphy_started(struct ath_softc *sc) -{ - int i; - spin_lock_bh(&sc->wiphy_lock); - if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { - spin_unlock_bh(&sc->wiphy_lock); - return true; - } - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { - spin_unlock_bh(&sc->wiphy_lock); - return true; - } - } - spin_unlock_bh(&sc->wiphy_lock); - return false; -} - -static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, - struct ath_wiphy *selected) -{ - if (selected->state == ATH_WIPHY_SCAN) { - if (aphy == selected) - return; - /* - * Pause all other wiphys for the duration of the scan even if - * they are on the current channel now. - */ - } else if (aphy->chan_idx == selected->chan_idx) - return; - aphy->state = ATH_WIPHY_PAUSED; - ieee80211_stop_queues(aphy->hw); -} - -void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, - struct ath_wiphy *selected) -{ - int i; - spin_lock_bh(&sc->wiphy_lock); - if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) - ath9k_wiphy_pause_chan(sc->pri_wiphy, selected); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) - ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected); - } - spin_unlock_bh(&sc->wiphy_lock); -} - -void ath9k_wiphy_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - wiphy_work.work); - struct ath_wiphy *aphy = NULL; - bool first = true; - - spin_lock_bh(&sc->wiphy_lock); - - if (sc->wiphy_scheduler_int == 0) { - /* wiphy scheduler is disabled */ - spin_unlock_bh(&sc->wiphy_lock); - return; - } - -try_again: - sc->wiphy_scheduler_index++; - while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { - aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; - if (aphy && aphy->state != ATH_WIPHY_INACTIVE) - break; - - sc->wiphy_scheduler_index++; - aphy = NULL; - } - if (aphy == NULL) { - sc->wiphy_scheduler_index = 0; - if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { - if (first) { - first = false; - goto try_again; - } - /* No wiphy is ready to be scheduled */ - } else - aphy = sc->pri_wiphy; - } - - spin_unlock_bh(&sc->wiphy_lock); - - if (aphy && - aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && - ath9k_wiphy_select(aphy)) { - printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " - "change\n"); - } - - queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, - sc->wiphy_scheduler_int); -} - -void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) -{ - cancel_delayed_work_sync(&sc->wiphy_work); - sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); - if (sc->wiphy_scheduler_int) - queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, - sc->wiphy_scheduler_int); -} diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c deleted file mode 100644 index 628b780d8844..000000000000 --- a/drivers/net/wireless/ath9k/xmit.c +++ /dev/null @@ -1,2171 +0,0 @@ -/* - * 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 "ath9k.h" - -#define BITS_PER_BYTE 8 -#define OFDM_PLCP_BITS 22 -#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) -#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) -#define L_STF 8 -#define L_LTF 8 -#define L_SIG 4 -#define HT_SIG 8 -#define HT_STF 4 -#define HT_LTF(_ns) (4 * (_ns)) -#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */ -#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */ -#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) -#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) - -#define OFDM_SIFS_TIME 16 - -static u32 bits_per_symbol[][2] = { - /* 20MHz 40MHz */ - { 26, 54 }, /* 0: BPSK */ - { 52, 108 }, /* 1: QPSK 1/2 */ - { 78, 162 }, /* 2: QPSK 3/4 */ - { 104, 216 }, /* 3: 16-QAM 1/2 */ - { 156, 324 }, /* 4: 16-QAM 3/4 */ - { 208, 432 }, /* 5: 64-QAM 2/3 */ - { 234, 486 }, /* 6: 64-QAM 3/4 */ - { 260, 540 }, /* 7: 64-QAM 5/6 */ - { 52, 108 }, /* 8: BPSK */ - { 104, 216 }, /* 9: QPSK 1/2 */ - { 156, 324 }, /* 10: QPSK 3/4 */ - { 208, 432 }, /* 11: 16-QAM 1/2 */ - { 312, 648 }, /* 12: 16-QAM 3/4 */ - { 416, 864 }, /* 13: 64-QAM 2/3 */ - { 468, 972 }, /* 14: 64-QAM 3/4 */ - { 520, 1080 }, /* 15: 64-QAM 5/6 */ -}; - -#define IS_HT_RATE(_rate) ((_rate) & 0x80) - -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); -static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, - struct list_head *bf_q, - int txok, int sendbar); -static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *head); -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok); -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok, bool update_rc); - -/*********************/ -/* Aggregation logic */ -/*********************/ - -static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) -{ - struct ath_atx_tid *tid; - tid = ATH_AN_2_TID(an, tidno); - - if (tid->state & AGGR_ADDBA_COMPLETE || - tid->state & AGGR_ADDBA_PROGRESS) - return 1; - else - return 0; -} - -static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) -{ - struct ath_atx_ac *ac = tid->ac; - - if (tid->paused) - return; - - if (tid->sched) - return; - - tid->sched = true; - list_add_tail(&tid->list, &ac->tid_q); - - if (ac->sched) - return; - - ac->sched = true; - list_add_tail(&ac->list, &txq->axq_acq); -} - -static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - - spin_lock_bh(&txq->axq_lock); - tid->paused++; - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - - ASSERT(tid->paused > 0); - spin_lock_bh(&txq->axq_lock); - - tid->paused--; - - if (tid->paused > 0) - goto unlock; - - if (list_empty(&tid->buf_q)) - goto unlock; - - ath_tx_queue_tid(txq, tid); - ath_txq_schedule(sc, txq); -unlock: - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - ASSERT(tid->paused > 0); - spin_lock_bh(&txq->axq_lock); - - tid->paused--; - - if (tid->paused > 0) { - spin_unlock_bh(&txq->axq_lock); - return; - } - - while (!list_empty(&tid->buf_q)) { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - ASSERT(!bf_isretried(bf)); - list_move_tail(&bf->list, &bf_head); - ath_tx_send_ht_normal(sc, txq, tid, &bf_head); - } - - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - int seqno) -{ - int index, cindex; - - index = ATH_BA_INDEX(tid->seq_start, seqno); - cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - - tid->tx_buf[cindex] = NULL; - - while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - INCR(tid->baw_head, ATH_TID_MAX_BUFS); - } -} - -static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf) -{ - int index, cindex; - - if (bf_isretried(bf)) - return; - - index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); - cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - - ASSERT(tid->tx_buf[cindex] == NULL); - tid->tx_buf[cindex] = bf; - - if (index >= ((tid->baw_tail - tid->baw_head) & - (ATH_TID_MAX_BUFS - 1))) { - tid->baw_tail = cindex; - INCR(tid->baw_tail, ATH_TID_MAX_BUFS); - } -} - -/* - * TODO: For frame(s) that are in the retry state, we will reuse the - * sequence number(s) without setting the retry bit. The - * alternative is to give up on these and BAR the receiver's window - * forward. - */ -static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) - -{ - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - for (;;) { - if (list_empty(&tid->buf_q)) - break; - - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - list_move_tail(&bf->list, &bf_head); - - if (bf_isretried(bf)) - ath_tx_update_baw(sc, tid, bf->bf_seqno); - - spin_unlock(&txq->axq_lock); - ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); - spin_lock(&txq->axq_lock); - } - - tid->seq_next = tid->seq_start; - tid->baw_tail = tid->baw_head; -} - -static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) -{ - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - - bf->bf_state.bf_type |= BUF_RETRY; - bf->bf_retries++; - - skb = bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); -} - -static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) -{ - struct ath_buf *tbf; - - spin_lock_bh(&sc->tx.txbuflock); - ASSERT(!list_empty((&sc->tx.txbuf))); - tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&tbf->list); - spin_unlock_bh(&sc->tx.txbuflock); - - ATH_TXBUF_RESET(tbf); - - tbf->bf_mpdu = bf->bf_mpdu; - tbf->bf_buf_addr = bf->bf_buf_addr; - *(tbf->bf_desc) = *(bf->bf_desc); - tbf->bf_state = bf->bf_state; - tbf->bf_dmacontext = bf->bf_dmacontext; - - return tbf; -} - -static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct list_head *bf_q, - int txok) -{ - struct ath_node *an = NULL; - struct sk_buff *skb; - struct ieee80211_sta *sta; - struct ieee80211_hdr *hdr; - struct ath_atx_tid *tid = NULL; - struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; - struct list_head bf_head, bf_pending; - u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; - - skb = bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - - rcu_read_lock(); - - sta = ieee80211_find_sta(sc->hw, hdr->addr1); - if (!sta) { - rcu_read_unlock(); - return; - } - - an = (struct ath_node *)sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); - - isaggr = bf_isaggr(bf); - memset(ba, 0, WME_BA_BMP_SIZE >> 3); - - if (isaggr && txok) { - if (ATH_DS_TX_BA(ds)) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), - WME_BA_BMP_SIZE >> 3); - } else { - /* - * AR5416 can become deaf/mute when BA - * issue happens. Chip needs to be reset. - * But AP code may have sychronization issues - * when perform internal reset in this routine. - * Only enable reset in STA mode for now. - */ - if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) - needreset = 1; - } - } - - INIT_LIST_HEAD(&bf_pending); - INIT_LIST_HEAD(&bf_head); - - nbad = ath_tx_num_badfrms(sc, bf, txok); - while (bf) { - txfail = txpending = 0; - bf_next = bf->bf_next; - - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { - /* transmit completion, subframe is - * acked by block ack */ - acked_cnt++; - } else if (!isaggr && txok) { - /* transmit completion */ - acked_cnt++; - } else { - if (!(tid->state & AGGR_CLEANUP) && - ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { - if (bf->bf_retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, bf); - txpending = 1; - } else { - bf->bf_state.bf_type |= BUF_XRETRY; - txfail = 1; - sendbar = 1; - txfail_cnt++; - } - } else { - /* - * cleanup in progress, just fail - * the un-acked sub-frames - */ - txfail = 1; - } - } - - if (bf_next == NULL) { - INIT_LIST_HEAD(&bf_head); - } else { - ASSERT(!list_empty(bf_q)); - list_move_tail(&bf->list, &bf_head); - } - - if (!txpending) { - /* - * complete the acked-ones/xretried ones; update - * block-ack window - */ - spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, bf->bf_seqno); - spin_unlock_bh(&txq->axq_lock); - - if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { - ath_tx_rc_status(bf, ds, nbad, txok, true); - rc_update = false; - } else { - ath_tx_rc_status(bf, ds, nbad, txok, false); - } - - ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); - } else { - /* retry the un-acked ones */ - if (bf->bf_next == NULL && bf_last->bf_stale) { - struct ath_buf *tbf; - - tbf = ath_clone_txbuf(sc, bf_last); - ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); - list_add_tail(&tbf->list, &bf_head); - } else { - /* - * Clear descriptor status words for - * software retry - */ - ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc); - } - - /* - * Put this buffer to the temporary pending - * queue to retain ordering - */ - list_splice_tail_init(&bf_head, &bf_pending); - } - - bf = bf_next; - } - - if (tid->state & AGGR_CLEANUP) { - if (tid->baw_head == tid->baw_tail) { - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->addba_exchangeattempts = 0; - tid->state &= ~AGGR_CLEANUP; - - /* send buffered frames as singles */ - ath_tx_flush_tid(sc, tid); - } - rcu_read_unlock(); - return; - } - - /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!list_empty(&bf_pending)) { - spin_lock_bh(&txq->axq_lock); - list_splice(&bf_pending, &tid->buf_q); - ath_tx_queue_tid(txq, tid); - spin_unlock_bh(&txq->axq_lock); - } - - rcu_read_unlock(); - - if (needreset) - ath_reset(sc, false); -} - -static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, - struct ath_atx_tid *tid) -{ - struct ath_rate_table *rate_table = sc->cur_rate_table; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; - struct ath_tx_info_priv *tx_info_priv; - u32 max_4ms_framelen, frmlen; - u16 aggr_limit, legacy = 0, maxampdu; - int i; - - skb = bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; - tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; - - /* - * Find the lowest frame length among the rate series that will have a - * 4ms transmit duration. - * TODO - TXOP limit needs to be considered. - */ - max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; - - for (i = 0; i < 4; i++) { - if (rates[i].count) { - if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { - legacy = 1; - break; - } - - frmlen = rate_table->info[rates[i].idx].max_4ms_framelen; - max_4ms_framelen = min(max_4ms_framelen, frmlen); - } - } - - /* - * limit aggregate size by the minimum rate if rate selected is - * not a probe rate, if rate selected is a probe rate then - * avoid aggregation of this packet. - */ - if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) - return 0; - - aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT); - - /* - * h/w can accept aggregates upto 16 bit lengths (65535). - * The IE, however can hold upto 65536, which shows up here - * as zero. Ignore 65536 since we are constrained by hw. - */ - maxampdu = tid->an->maxampdu; - if (maxampdu) - aggr_limit = min(aggr_limit, maxampdu); - - return aggr_limit; -} - -/* - * Returns the number of delimiters to be added to - * meet the minimum required mpdudensity. - * caller should make sure that the rate is HT rate . - */ -static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf, u16 frmlen) -{ - struct ath_rate_table *rt = sc->cur_rate_table; - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - u32 nsymbits, nsymbols, mpdudensity; - u16 minlen; - u8 rc, flags, rix; - int width, half_gi, ndelim, mindelim; - - /* Select standard number of delimiters based on frame length alone */ - ndelim = ATH_AGGR_GET_NDELIM(frmlen); - - /* - * If encryption enabled, hardware requires some more padding between - * subframes. - * TODO - this could be improved to be dependent on the rate. - * The hardware can keep up at lower rates, but not higher rates - */ - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) - ndelim += ATH_AGGR_ENCRYPTDELIM; - - /* - * Convert desired mpdu density from microeconds to bytes based - * on highest rate in rate series (i.e. first rate) to determine - * required minimum length for subframe. Take into account - * whether high rate is 20 or 40Mhz and half or full GI. - */ - mpdudensity = tid->an->mpdudensity; - - /* - * If there is no mpdu density restriction, no further calculation - * is needed. - */ - if (mpdudensity == 0) - return ndelim; - - rix = tx_info->control.rates[0].idx; - flags = tx_info->control.rates[0].flags; - rc = rt->info[rix].ratecode; - width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; - half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; - - if (half_gi) - nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); - else - nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); - - if (nsymbols == 0) - nsymbols = 1; - - nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; - minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; - - if (frmlen < minlen) { - mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; - ndelim = max(mindelim, ndelim); - } - - return ndelim; -} - -static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, - struct ath_atx_tid *tid, - struct list_head *bf_q) -{ -#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *bf_first, *bf_prev = NULL; - int rl = 0, nframes = 0, ndelim, prev_al = 0; - u16 aggr_limit = 0, al = 0, bpad = 0, - al_delta, h_baw = tid->baw_size / 2; - enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; - - bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); - - do { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - - /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { - status = ATH_AGGR_BAW_CLOSED; - break; - } - - if (!rl) { - aggr_limit = ath_lookup_rate(sc, bf, tid); - rl = 1; - } - - /* do not exceed aggregation limit */ - al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; - - if (nframes && - (aggr_limit < (al + bpad + al_delta + prev_al))) { - status = ATH_AGGR_LIMITED; - break; - } - - /* do not exceed subframe limit */ - if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { - status = ATH_AGGR_LIMITED; - break; - } - nframes++; - - /* add padding for previous frame to aggregation length */ - al += bpad + al_delta; - - /* - * Get the delimiters needed to meet the MPDU - * density for this node. - */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); - bpad = PADBYTES(al_delta) + (ndelim << 2); - - bf->bf_next = NULL; - bf->bf_desc->ds_link = 0; - - /* link buffers of this frame to the aggregate */ - ath_tx_addto_baw(sc, tid, bf); - ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); - list_move_tail(&bf->list, bf_q); - if (bf_prev) { - bf_prev->bf_next = bf; - bf_prev->bf_desc->ds_link = bf->bf_daddr; - } - bf_prev = bf; - } while (!list_empty(&tid->buf_q)); - - bf_first->bf_al = al; - bf_first->bf_nframes = nframes; - - return status; -#undef PADBYTES -} - -static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) -{ - struct ath_buf *bf; - enum ATH_AGGR_STATUS status; - struct list_head bf_q; - - do { - if (list_empty(&tid->buf_q)) - return; - - INIT_LIST_HEAD(&bf_q); - - status = ath_tx_form_aggr(sc, tid, &bf_q); - - /* - * no frames picked up to be aggregated; - * block-ack window is not open. - */ - if (list_empty(&bf_q)) - break; - - bf = list_first_entry(&bf_q, struct ath_buf, list); - bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); - - /* if only one frame, send as non-aggregate */ - if (bf->bf_nframes == 1) { - bf->bf_state.bf_type &= ~BUF_AGGR; - ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, &bf_q); - continue; - } - - /* setup first desc of aggregate */ - bf->bf_state.bf_type |= BUF_AGGR; - ath_buf_set_rate(sc, bf); - ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); - - /* anchor last desc of aggregate */ - ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); - - txq->axq_aggr_depth++; - ath_tx_txqaddbuf(sc, txq, &bf_q); - - } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && - status != ATH_AGGR_BAW_CLOSED); -} - -int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, - u16 tid, u16 *ssn) -{ - struct ath_atx_tid *txtid; - struct ath_node *an; - - an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) { - txtid = ATH_AN_2_TID(an, tid); - txtid->state |= AGGR_ADDBA_PROGRESS; - ath_tx_pause_tid(sc, txtid); - *ssn = txtid->seq_start; - } - - return 0; -} - -int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); - struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - if (txtid->state & AGGR_CLEANUP) - return 0; - - if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { - txtid->addba_exchangeattempts = 0; - return 0; - } - - ath_tx_pause_tid(sc, txtid); - - /* drop all software retried frames and mark this TID */ - spin_lock_bh(&txq->axq_lock); - while (!list_empty(&txtid->buf_q)) { - bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); - if (!bf_isretried(bf)) { - /* - * NB: it's based on the assumption that - * software retried frame will always stay - * at the head of software queue. - */ - break; - } - list_move_tail(&bf->list, &bf_head); - ath_tx_update_baw(sc, txtid, bf->bf_seqno); - ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); - } - spin_unlock_bh(&txq->axq_lock); - - if (txtid->baw_head != txtid->baw_tail) { - txtid->state |= AGGR_CLEANUP; - } else { - txtid->state &= ~AGGR_ADDBA_COMPLETE; - txtid->addba_exchangeattempts = 0; - ath_tx_flush_tid(sc, txtid); - } - - return 0; -} - -void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) -{ - struct ath_atx_tid *txtid; - struct ath_node *an; - - an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) { - txtid = ATH_AN_2_TID(an, tid); - txtid->baw_size = - IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; - txtid->state |= AGGR_ADDBA_COMPLETE; - txtid->state &= ~AGGR_ADDBA_PROGRESS; - ath_tx_resume_tid(sc, txtid); - } -} - -bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) -{ - struct ath_atx_tid *txtid; - - if (!(sc->sc_flags & SC_OP_TXAGGR)) - return false; - - txtid = ATH_AN_2_TID(an, tidno); - - if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { - if (!(txtid->state & AGGR_ADDBA_PROGRESS) && - (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) { - txtid->addba_exchangeattempts++; - return true; - } - } - - return false; -} - -/********************/ -/* Queue Management */ -/********************/ - -static void ath_txq_drain_pending_buffers(struct ath_softc *sc, - struct ath_txq *txq) -{ - struct ath_atx_ac *ac, *ac_tmp; - struct ath_atx_tid *tid, *tid_tmp; - - list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { - list_del(&ac->list); - ac->sched = false; - list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { - list_del(&tid->list); - tid->sched = false; - ath_tid_drain(sc, txq, tid); - } - } -} - -struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_tx_queue_info qi; - int qnum; - - memset(&qi, 0, sizeof(qi)); - qi.tqi_subtype = subtype; - qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; - qi.tqi_physCompBuf = 0; - - /* - * Enable interrupts only for EOL and DESC conditions. - * We mark tx descriptors to receive a DESC interrupt - * when a tx queue gets deep; otherwise waiting for the - * EOL to reap descriptors. Note that this is done to - * reduce interrupt load and this only defers reaping - * descriptors, never transmitting frames. Aside from - * reducing interrupts this also permits more concurrency. - * The only potential downside is if the tx queue backs - * up in which case the top half of the kernel may backup - * due to a lack of tx descriptors. - * - * The UAPSD queue is an exception, since we take a desc- - * based intr on the EOSP frames. - */ - if (qtype == ATH9K_TX_QUEUE_UAPSD) - qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; - else - qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | - TXQ_FLAG_TXDESCINT_ENABLE; - qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); - if (qnum == -1) { - /* - * NB: don't print a message, this happens - * normally on parts with too few tx queues - */ - return NULL; - } - if (qnum >= ARRAY_SIZE(sc->tx.txq)) { - DPRINTF(sc, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); - ath9k_hw_releasetxqueue(ah, qnum); - return NULL; - } - if (!ATH_TXQ_SETUP(sc, qnum)) { - struct ath_txq *txq = &sc->tx.txq[qnum]; - - txq->axq_qnum = qnum; - txq->axq_link = NULL; - INIT_LIST_HEAD(&txq->axq_q); - INIT_LIST_HEAD(&txq->axq_acq); - spin_lock_init(&txq->axq_lock); - txq->axq_depth = 0; - txq->axq_aggr_depth = 0; - txq->axq_totalqueued = 0; - txq->axq_linkbuf = NULL; - sc->tx.txqsetup |= 1<tx.txq[qnum]; -} - -static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) -{ - int qnum; - - switch (qtype) { - case ATH9K_TX_QUEUE_DATA: - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - DPRINTF(sc, ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return -1; - } - qnum = sc->tx.hwq_map[haltype]; - break; - case ATH9K_TX_QUEUE_BEACON: - qnum = sc->beacon.beaconq; - break; - case ATH9K_TX_QUEUE_CAB: - qnum = sc->beacon.cabq->axq_qnum; - break; - default: - qnum = -1; - } - return qnum; -} - -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_txq *txq = NULL; - int qnum; - - qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txq = &sc->tx.txq[qnum]; - - spin_lock_bh(&txq->axq_lock); - - if (txq->axq_depth >= (ATH_TXBUF - 20)) { - DPRINTF(sc, ATH_DBG_XMIT, - "TX queue: %d is full, depth: %d\n", - qnum, txq->axq_depth); - ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); - txq->stopped = 1; - spin_unlock_bh(&txq->axq_lock); - return NULL; - } - - spin_unlock_bh(&txq->axq_lock); - - return txq; -} - -int ath_txq_update(struct ath_softc *sc, int qnum, - struct ath9k_tx_queue_info *qinfo) -{ - struct ath_hw *ah = sc->sc_ah; - int error = 0; - struct ath9k_tx_queue_info qi; - - if (qnum == sc->beacon.beaconq) { - /* - * XXX: for beacon queue, we just save the parameter. - * It will be picked up by ath_beaconq_config when - * it's necessary. - */ - sc->beacon.beacon_qi = *qinfo; - return 0; - } - - ASSERT(sc->tx.txq[qnum].axq_qnum == qnum); - - ath9k_hw_get_txq_props(ah, qnum, &qi); - qi.tqi_aifs = qinfo->tqi_aifs; - qi.tqi_cwmin = qinfo->tqi_cwmin; - qi.tqi_cwmax = qinfo->tqi_cwmax; - qi.tqi_burstTime = qinfo->tqi_burstTime; - qi.tqi_readyTime = qinfo->tqi_readyTime; - - if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); - error = -EIO; - } else { - ath9k_hw_resettxqueue(ah, qnum); - } - - return error; -} - -int ath_cabq_update(struct ath_softc *sc) -{ - struct ath9k_tx_queue_info qi; - int qnum = sc->beacon.cabq->axq_qnum; - - ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); - /* - * Ensure the readytime % is within the bounds. - */ - if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) - sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; - else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) - sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; - - qi.tqi_readyTime = (sc->hw->conf.beacon_int * - sc->config.cabqReadytime) / 100; - ath_txq_update(sc, qnum, &qi); - - return 0; -} - -/* - * Drain a given TX queue (could be Beacon or Data) - * - * This assumes output has been stopped and - * we do not need to block ath_tx_tasklet. - */ -void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) -{ - struct ath_buf *bf, *lastbf; - struct list_head bf_head; - - INIT_LIST_HEAD(&bf_head); - - for (;;) { - spin_lock_bh(&txq->axq_lock); - - if (list_empty(&txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; - spin_unlock_bh(&txq->axq_lock); - break; - } - - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - - if (bf->bf_stale) { - list_del(&bf->list); - spin_unlock_bh(&txq->axq_lock); - - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - continue; - } - - lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_desc->ds_txstat.ts_flags = - ATH9K_TX_SW_ABORTED; - - /* remove ath_buf's of the same mpdu from txq */ - list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); - txq->axq_depth--; - - spin_unlock_bh(&txq->axq_lock); - - if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); - else - ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); - } - - /* flush any pending frames if aggregation is enabled */ - if (sc->sc_flags & SC_OP_TXAGGR) { - if (!retry_tx) { - spin_lock_bh(&txq->axq_lock); - ath_txq_drain_pending_buffers(sc, txq); - spin_unlock_bh(&txq->axq_lock); - } - } -} - -void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_txq *txq; - int i, npend = 0; - - if (sc->sc_flags & SC_OP_INVALID) - return; - - /* Stop beacon queue */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - /* Stop data queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - ath9k_hw_stoptxdma(ah, txq->axq_qnum); - npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); - } - } - - if (npend) { - int r; - - DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); - if (r) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %u\n", - r); - spin_unlock_bh(&sc->sc_resetlock); - } - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) - ath_draintxq(sc, &sc->tx.txq[i], retry_tx); - } -} - -void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) -{ - ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); - sc->tx.txqsetup &= ~(1<axq_qnum); -} - -void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) -{ - struct ath_atx_ac *ac; - struct ath_atx_tid *tid; - - if (list_empty(&txq->axq_acq)) - return; - - ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); - list_del(&ac->list); - ac->sched = false; - - do { - if (list_empty(&ac->tid_q)) - return; - - tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); - list_del(&tid->list); - tid->sched = false; - - if (tid->paused) - continue; - - if ((txq->axq_depth % 2) == 0) - ath_tx_sched_aggr(sc, txq, tid); - - /* - * add tid to round-robin queue if more frames - * are pending for the tid - */ - if (!list_empty(&tid->buf_q)) - ath_tx_queue_tid(txq, tid); - - break; - } while (!list_empty(&ac->tid_q)); - - if (!list_empty(&ac->tid_q)) { - if (!ac->sched) { - ac->sched = true; - list_add_tail(&ac->list, &txq->axq_acq); - } - } -} - -int ath_tx_setup(struct ath_softc *sc, int haltype) -{ - struct ath_txq *txq; - - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - DPRINTF(sc, ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return 0; - } - txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); - if (txq != NULL) { - sc->tx.hwq_map[haltype] = txq->axq_qnum; - return 1; - } else - return 0; -} - -/***********/ -/* TX, DMA */ -/***********/ - -/* - * Insert a chain of ath_buf (descriptors) on a txq and - * assume the descriptors are already chained together by caller. - */ -static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *head) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf; - - /* - * Insert the frame on the outbound list and - * pass it on to the hardware. - */ - - if (list_empty(head)) - return; - - bf = list_first_entry(head, struct ath_buf, list); - - list_splice_tail_init(head, &txq->axq_q); - txq->axq_depth++; - txq->axq_totalqueued++; - txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); - - DPRINTF(sc, ATH_DBG_QUEUE, - "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); - - if (txq->axq_link == NULL) { - ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - DPRINTF(sc, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); - } else { - *txq->axq_link = bf->bf_daddr; - DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); - } - txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); - ath9k_hw_txstart(ah, txq->axq_qnum); -} - -static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) -{ - struct ath_buf *bf = NULL; - - spin_lock_bh(&sc->tx.txbuflock); - - if (unlikely(list_empty(&sc->tx.txbuf))) { - spin_unlock_bh(&sc->tx.txbuflock); - return NULL; - } - - bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&bf->list); - - spin_unlock_bh(&sc->tx.txbuflock); - - return bf; -} - -static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct list_head *bf_head, - struct ath_tx_control *txctl) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_state.bf_type |= BUF_AMPDU; - - /* - * Do not queue to h/w when any of the following conditions is true: - * - there are pending frames in software queue - * - the TID is currently paused for ADDBA/BAR request - * - seqno is not within block-ack window - * - h/w queue depth exceeds low water mark - */ - if (!list_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || - txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { - /* - * Add this frame to software queue for scheduling later - * for aggregation. - */ - list_move_tail(&bf->list, &tid->buf_q); - ath_tx_queue_tid(txctl->txq, tid); - return; - } - - /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf); - - /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, bf_head); -} - -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_state.bf_type &= ~BUF_AMPDU; - - /* update starting sequence number for subsequent ADDBA request */ - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); -} - -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); - - bf->bf_lastbf = bf; - bf->bf_nframes = 1; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); -} - -static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - enum ath9k_pkt_type htype; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - if (ieee80211_is_beacon(fc)) - htype = ATH9K_PKT_TYPE_BEACON; - else if (ieee80211_is_probe_resp(fc)) - htype = ATH9K_PKT_TYPE_PROBE_RESP; - else if (ieee80211_is_atim(fc)) - htype = ATH9K_PKT_TYPE_ATIM; - else if (ieee80211_is_pspoll(fc)) - htype = ATH9K_PKT_TYPE_PSPOLL; - else - htype = ATH9K_PKT_TYPE_NORMAL; - - return htype; -} - -static bool is_pae(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - if (ieee80211_is_data(fc)) { - if (ieee80211_is_nullfunc(fc) || - /* Port Access Entity (IEEE 802.1X) */ - (skb->protocol == cpu_to_be16(ETH_P_PAE))) { - return true; - } - } - - return false; -} - -static int get_hw_crypto_keytype(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - if (tx_info->control.hw_key) { - if (tx_info->control.hw_key->alg == ALG_WEP) - return ATH9K_KEY_TYPE_WEP; - else if (tx_info->control.hw_key->alg == ALG_TKIP) - return ATH9K_KEY_TYPE_TKIP; - else if (tx_info->control.hw_key->alg == ALG_CCMP) - return ATH9K_KEY_TYPE_AES; - } - - return ATH9K_KEY_TYPE_CLEAR; -} - -static void assign_aggr_tid_seqno(struct sk_buff *skb, - struct ath_buf *bf) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; - struct ath_node *an; - struct ath_atx_tid *tid; - __le16 fc; - u8 *qc; - - if (!tx_info->control.sta) - return; - - an = (struct ath_node *)tx_info->control.sta->drv_priv; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - bf->bf_tidno = qc[0] & 0xf; - } - - /* - * For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - * - * If fragmentation is on, the sequence number is - * not overridden, since it has been - * incremented by the fragmentation routine. - * - * FIXME: check if the fragmentation threshold exceeds - * IEEE80211 max. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << - IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); -} - -static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, - struct ath_txq *txq) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - int flags = 0; - - flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ - flags |= ATH9K_TXDESC_INTREQ; - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) - flags |= ATH9K_TXDESC_NOACK; - - return flags; -} - -/* - * rix - rate index - * pktlen - total bytes (delims + data + fcs + pads + pad delims) - * width - 0 for 20 MHz, 1 for 40 MHz - * half_gi - to use 4us v/s 3.6 us for symbol time - */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, - int width, int half_gi, bool shortPreamble) -{ - struct ath_rate_table *rate_table = sc->cur_rate_table; - u32 nbits, nsymbits, duration, nsymbols; - u8 rc; - int streams, pktlen; - - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; - rc = rate_table->info[rix].ratecode; - - /* for legacy rates, use old function to compute packet duration */ - if (!IS_HT_RATE(rc)) - return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, - rix, shortPreamble); - - /* find number of symbols: PLCP + data */ - nbits = (pktlen << 3) + OFDM_PLCP_BITS; - nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; - nsymbols = (nbits + nsymbits - 1) / nsymbits; - - if (!half_gi) - duration = SYMBOL_TIME(nsymbols); - else - duration = SYMBOL_TIME_HALFGI(nsymbols); - - /* addup duration for legacy/ht training and signal fields */ - streams = HT_RC_2_STREAMS(rc); - duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); - - return duration; -} - -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) -{ - struct ath_rate_table *rt = sc->cur_rate_table; - struct ath9k_11n_rate_series series[4]; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; - struct ieee80211_hdr *hdr; - int i, flags = 0; - u8 rix = 0, ctsrate = 0; - bool is_pspoll; - - memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - - skb = bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; - hdr = (struct ieee80211_hdr *)skb->data; - is_pspoll = ieee80211_is_pspoll(hdr->frame_control); - - /* - * We check if Short Preamble is needed for the CTS rate by - * checking the BSS's global flag. - * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. - */ - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode | - rt->info[tx_info->control.rts_cts_rate_idx].short_preamble; - else - ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode; - - /* - * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. - * Check the first rate in the series to decide whether RTS/CTS - * or CTS-to-self has to be used. - */ - if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - flags = ATH9K_TXDESC_CTSENA; - else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - flags = ATH9K_TXDESC_RTSENA; - - /* FIXME: Handle aggregation protection */ - if (sc->config.ath_aggr_prot && - (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { - flags = ATH9K_TXDESC_RTSENA; - } - - /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) - flags &= ~(ATH9K_TXDESC_RTSENA); - - for (i = 0; i < 4; i++) { - if (!rates[i].count || (rates[i].idx < 0)) - continue; - - rix = rates[i].idx; - series[i].Tries = rates[i].count; - series[i].ChSel = sc->tx_chainmask; - - if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - series[i].Rate = rt->info[rix].ratecode | - rt->info[rix].short_preamble; - else - series[i].Rate = rt->info[rix].ratecode; - - if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) - series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; - if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - series[i].RateFlags |= ATH9K_RATESERIES_2040; - if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) - series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; - - series[i].PktDuration = ath_pkt_duration(sc, rix, bf, - (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, - (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), - (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)); - } - - /* set dur_update_en for l-sig computation except for PS-Poll frames */ - ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, - bf->bf_lastbf->bf_desc, - !is_pspoll, ctsrate, - 0, series, 4, flags); - - if (sc->config.ath_aggr_prot && flags) - ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); -} - -static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, - struct sk_buff *skb, - struct ath_tx_control *txctl) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_tx_info_priv *tx_info_priv; - int hdrlen; - __le16 fc; - - tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); - if (unlikely(!tx_info_priv)) - return -ENOMEM; - tx_info->rate_driver_data[0] = tx_info_priv; - tx_info_priv->aphy = aphy; - tx_info_priv->frame_type = txctl->frame_type; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; - - ATH_TXBUF_RESET(bf); - - bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); - - if (conf_is_ht(&sc->hw->conf) && !is_pae(skb)) - bf->bf_state.bf_type |= BUF_HT; - - bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); - - bf->bf_keytype = get_hw_crypto_keytype(skb); - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { - bf->bf_frmlen += tx_info->control.hw_key->icv_len; - bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; - } else { - bf->bf_keyix = ATH9K_TXKEYIX_INVALID; - } - - if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) - assign_aggr_tid_seqno(skb, bf); - - bf->bf_mpdu = skb; - - bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, - "dma_mapping_error() on TX\n"); - return -ENOMEM; - } - - bf->bf_buf_addr = bf->bf_dmacontext; - return 0; -} - -/* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_control *txctl) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_node *an = NULL; - struct list_head bf_head; - struct ath_desc *ds; - struct ath_atx_tid *tid; - struct ath_hw *ah = sc->sc_ah; - int frm_type; - __le16 fc; - - frm_type = get_hw_packet_type(skb); - fc = hdr->frame_control; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); - - ds = bf->bf_desc; - ds->ds_link = 0; - ds->ds_data = bf->bf_buf_addr; - - ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, - bf->bf_keyix, bf->bf_keytype, bf->bf_flags); - - ath9k_hw_filltxdesc(ah, ds, - skb->len, /* segment length */ - true, /* first segment */ - true, /* last segment */ - ds); /* first descriptor */ - - spin_lock_bh(&txctl->txq->axq_lock); - - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && - tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); - - if (!ieee80211_is_data_qos(fc)) { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - goto tx_done; - } - - if (ath_aggr_query(sc, an, bf->bf_tidno)) { - /* - * Try aggregation if it's a unicast data frame - * and the destination is HT capable. - */ - ath_tx_send_ampdu(sc, tid, &bf_head, txctl); - } else { - /* - * Send this frame as regular when ADDBA - * exchange is neither complete nor pending. - */ - ath_tx_send_ht_normal(sc, txctl->txq, - tid, &bf_head); - } - } else { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - } - -tx_done: - spin_unlock_bh(&txctl->txq->axq_lock); -} - -/* Upon failure caller should free skb */ -int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath_tx_control *txctl) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_buf *bf; - int r; - - bf = ath_tx_get_buffer(sc); - if (!bf) { - DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n"); - return -1; - } - - r = ath_tx_setup_buffer(hw, bf, skb, txctl); - if (unlikely(r)) { - struct ath_txq *txq = txctl->txq; - - DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n"); - - /* upon ath_tx_processq() this TX queue will be resumed, we - * guarantee this will happen by knowing beforehand that - * we will at least have to run TX completionon one buffer - * on the queue */ - spin_lock_bh(&txq->axq_lock); - if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { - ieee80211_stop_queue(sc->hw, - skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - - return r; - } - - ath_tx_start_dma(sc, bf, txctl); - - return 0; -} - -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int hdrlen, padsize; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_tx_control txctl; - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - if (hdrlen & 3) { - padsize = hdrlen % 4; - if (skb_headroom(skb) < padsize) { - DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n"); - dev_kfree_skb_any(skb); - return; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, hdrlen); - } - - txctl.txq = sc->beacon.cabq; - - DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); - goto exit; - } - - return; -exit: - dev_kfree_skb_any(skb); -} - -/*****************/ -/* TX Completion */ -/*****************/ - -static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - int tx_flags) -{ - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - int hdrlen, padsize; - int frame_type = ATH9K_NOT_INTERNAL; - - DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); - - if (tx_info_priv) { - hw = tx_info_priv->aphy->hw; - frame_type = tx_info_priv->frame_type; - } - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || - tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - kfree(tx_info_priv); - tx_info->rate_driver_data[0] = NULL; - } - - if (tx_flags & ATH_TX_BAR) - tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { - /* Frame was ACKed */ - tx_info->flags |= IEEE80211_TX_STAT_ACK; - } - - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = hdrlen & 3; - if (padsize && hdrlen >= 24) { - /* - * Remove MAC header padding before giving the frame back to - * mac80211. - */ - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - if (frame_type == ATH9K_NOT_INTERNAL) - ieee80211_tx_status(hw, skb); - else - ath9k_tx_status(hw, skb); -} - -static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, - struct list_head *bf_q, - int txok, int sendbar) -{ - struct sk_buff *skb = bf->bf_mpdu; - unsigned long flags; - int tx_flags = 0; - - - if (sendbar) - tx_flags = ATH_TX_BAR; - - if (!txok) { - tx_flags |= ATH_TX_ERROR; - - if (bf_isxretried(bf)) - tx_flags |= ATH_TX_XRETRY; - } - - dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); - ath_tx_complete(sc, skb, tx_flags); - - /* - * Return the list of ath_buf of this mpdu to free queue - */ - spin_lock_irqsave(&sc->tx.txbuflock, flags); - list_splice_tail_init(bf_q, &sc->tx.txbuf); - spin_unlock_irqrestore(&sc->tx.txbuflock, flags); -} - -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok) -{ - struct ath_buf *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; - u16 seq_st = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int ba_index; - int nbad = 0; - int isaggr = 0; - - if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) - return 0; - - isaggr = bf_isaggr(bf); - if (isaggr) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); - } - - while (bf) { - ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); - if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) - nbad++; - - bf = bf->bf_next; - } - - return nbad; -} - -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok, bool update_rc) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - struct ieee80211_hw *hw = tx_info_priv->aphy->hw; - u8 i, tx_rateindex; - - if (txok) - tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; - - tx_rateindex = ds->ds_txstat.ts_rateindex; - WARN_ON(tx_rateindex >= hw->max_rates); - - tx_info_priv->update_rc = update_rc; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - - if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && - (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { - if (ieee80211_is_data(hdr->frame_control)) { - memcpy(&tx_info_priv->tx, &ds->ds_txstat, - sizeof(tx_info_priv->tx)); - tx_info_priv->n_frames = bf->bf_nframes; - tx_info_priv->n_bad_frames = nbad; - } - } - - for (i = tx_rateindex + 1; i < hw->max_rates; i++) - tx_info->status.rates[i].count = 0; - - tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; -} - -static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) -{ - int qnum; - - spin_lock_bh(&txq->axq_lock); - if (txq->stopped && - sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) { - qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); - if (qnum != -1) { - ieee80211_wake_queue(sc->hw, qnum); - txq->stopped = 0; - } - } - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf, *lastbf, *bf_held = NULL; - struct list_head bf_head; - struct ath_desc *ds; - int txok; - int status; - - DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", - txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), - txq->axq_link); - - for (;;) { - spin_lock_bh(&txq->axq_lock); - if (list_empty(&txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; - spin_unlock_bh(&txq->axq_lock); - break; - } - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - - /* - * There is a race condition that a BH gets scheduled - * after sw writes TxE and before hw re-load the last - * descriptor to get the newly chained one. - * Software must keep the last DONE descriptor as a - * holding descriptor - software does so by marking - * it with the STALE flag. - */ - bf_held = NULL; - if (bf->bf_stale) { - bf_held = bf; - if (list_is_last(&bf_held->list, &txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; - spin_unlock_bh(&txq->axq_lock); - - /* - * The holding descriptor is the last - * descriptor in queue. It's safe to remove - * the last holding descriptor in BH context. - */ - spin_lock_bh(&sc->tx.txbuflock); - list_move_tail(&bf_held->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - - break; - } else { - bf = list_entry(bf_held->list.next, - struct ath_buf, list); - } - } - - lastbf = bf->bf_lastbf; - ds = lastbf->bf_desc; - - status = ath9k_hw_txprocdesc(ah, ds); - if (status == -EINPROGRESS) { - spin_unlock_bh(&txq->axq_lock); - break; - } - if (bf->bf_desc == txq->axq_lastdsWithCTS) - txq->axq_lastdsWithCTS = NULL; - if (ds == txq->axq_gatingds) - txq->axq_gatingds = NULL; - - /* - * Remove ath_buf's of the same transmit unit from txq, - * however leave the last descriptor back as the holding - * descriptor for hw. - */ - lastbf->bf_stale = true; - INIT_LIST_HEAD(&bf_head); - if (!list_is_singular(&lastbf->list)) - list_cut_position(&bf_head, - &txq->axq_q, lastbf->list.prev); - - txq->axq_depth--; - if (bf_isaggr(bf)) - txq->axq_aggr_depth--; - - txok = (ds->ds_txstat.ts_status == 0); - spin_unlock_bh(&txq->axq_lock); - - if (bf_held) { - spin_lock_bh(&sc->tx.txbuflock); - list_move_tail(&bf_held->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - } - - if (!bf_isampdu(bf)) { - /* - * This frame is sent out as a single frame. - * Use hardware retry status for this frame. - */ - bf->bf_retries = ds->ds_txstat.ts_longretry; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) - bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ds, 0, txok, true); - } - - if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); - else - ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); - - ath_wake_mac80211_queue(sc, txq); - - spin_lock_bh(&txq->axq_lock); - if (sc->sc_flags & SC_OP_TXAGGR) - ath_txq_schedule(sc, txq); - spin_unlock_bh(&txq->axq_lock); - } -} - - -void ath_tx_tasklet(struct ath_softc *sc) -{ - int i; - u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); - - ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) - ath_tx_processq(sc, &sc->tx.txq[i]); - } -} - -/*****************/ -/* Init, Cleanup */ -/*****************/ - -int ath_tx_init(struct ath_softc *sc, int nbufs) -{ - int error = 0; - - spin_lock_init(&sc->tx.txbuflock); - - error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, - "tx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", error); - goto err; - } - - error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", error); - goto err; - } - -err: - if (error != 0) - ath_tx_cleanup(sc); - - return error; -} - -void ath_tx_cleanup(struct ath_softc *sc) -{ - if (sc->beacon.bdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); - - if (sc->tx.txdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); -} - -void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) -{ - struct ath_atx_tid *tid; - struct ath_atx_ac *ac; - int tidno, acno; - - for (tidno = 0, tid = &an->tid[tidno]; - tidno < WME_NUM_TID; - tidno++, tid++) { - tid->an = an; - tid->tidno = tidno; - tid->seq_start = tid->seq_next = 0; - tid->baw_size = WME_MAX_BA; - tid->baw_head = tid->baw_tail = 0; - tid->sched = false; - tid->paused = false; - tid->state &= ~AGGR_CLEANUP; - INIT_LIST_HEAD(&tid->buf_q); - acno = TID_TO_WME_AC(tidno); - tid->ac = &an->ac[acno]; - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_ADDBA_PROGRESS; - tid->addba_exchangeattempts = 0; - } - - for (acno = 0, ac = &an->ac[acno]; - acno < WME_NUM_AC; acno++, ac++) { - ac->sched = false; - INIT_LIST_HEAD(&ac->tid_q); - - switch (acno) { - case WME_AC_BE: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); - break; - case WME_AC_BK: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); - break; - case WME_AC_VI: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); - break; - case WME_AC_VO: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); - break; - } - } -} - -void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) -{ - int i; - struct ath_atx_ac *ac, *ac_tmp; - struct ath_atx_tid *tid, *tid_tmp; - struct ath_txq *txq; - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - - spin_lock(&txq->axq_lock); - - list_for_each_entry_safe(ac, - ac_tmp, &txq->axq_acq, list) { - tid = list_first_entry(&ac->tid_q, - struct ath_atx_tid, list); - if (tid && tid->an != an) - continue; - list_del(&ac->list); - ac->sched = false; - - list_for_each_entry_safe(tid, - tid_tmp, &ac->tid_q, list) { - list_del(&tid->list); - tid->sched = false; - ath_tid_drain(sc, txq, tid); - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->addba_exchangeattempts = 0; - tid->state &= ~AGGR_CLEANUP; - } - } - - spin_unlock(&txq->axq_lock); - } - } -} -- cgit v1.2.3 From 6b2b2ffbef7750e51bfa74e92229ecee10b59307 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Mar 2009 22:30:34 -0400 Subject: ath: space cleanup Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 3ccf21cceb5a..4b5c851b81ff 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -173,9 +173,9 @@ static bool ath_is_radar_freq(u16 center_freq) * received a beacon on a channel we can enable active scan and * adhoc (or beaconing). */ -static void ath_reg_apply_beaconing_flags( - struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) +static void +ath_reg_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { enum ieee80211_band band; struct ieee80211_supported_band *sband; @@ -232,9 +232,9 @@ static void ath_reg_apply_beaconing_flags( } /* Allows active scan scan on Ch 12 and 13 */ -static void ath_reg_apply_active_scan_flags( - struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) +static void +ath_reg_apply_active_scan_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) { struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; @@ -316,8 +316,8 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy) } static void ath_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator, - struct ath_regulatory *reg) + enum nl80211_reg_initiator initiator, + struct ath_regulatory *reg) { switch (reg->regpair->regDmnEnum) { case 0x60: @@ -335,7 +335,8 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, } int ath_reg_notifier_apply(struct wiphy *wiphy, - struct regulatory_request *request, struct ath_regulatory *reg) + struct regulatory_request *request, + struct ath_regulatory *reg) { /* We always apply this */ ath_reg_apply_radar_flags(wiphy); @@ -433,8 +434,10 @@ ath_get_regpair(int regdmn) return NULL; } -static int ath_regd_init_wiphy(struct ath_regulatory *reg, struct wiphy *wiphy, - int (*reg_notifier)(struct wiphy *wiphy, +static int +ath_regd_init_wiphy(struct ath_regulatory *reg, + struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request)) { const struct ieee80211_regdomain *regd; @@ -464,9 +467,11 @@ static int ath_regd_init_wiphy(struct ath_regulatory *reg, struct wiphy *wiphy, return 0; } -int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, - int (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request)) +int +ath_regd_init(struct ath_regulatory *reg, + struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) { struct country_code_to_enum_rd *country = NULL; u16 regdmn; -- cgit v1.2.3 From 75c2148fa5330c6de741fc96e3308f57d846a6b4 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 30 Mar 2009 22:30:35 -0400 Subject: ath5k: sparse fix ath5k_led_on needs to be static drivers/net/wireless/ath/ath5k/led.c:81:6: warning: symbol 'ath5k_led_on' was not declared. Should it be static? Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/led.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 19555fb79c9b..006f7716168e 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -78,7 +78,7 @@ void ath5k_led_enable(struct ath5k_softc *sc) } } -void ath5k_led_on(struct ath5k_softc *sc) +static void ath5k_led_on(struct ath5k_softc *sc) { if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) return; -- cgit v1.2.3 From 18a8365992a8041aa178ae9ad5f0d951d0457230 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 31 Mar 2009 12:12:05 +0200 Subject: cfg80211: introduce scan IE limit attribute This patch introduces a new attribute for a wiphy that tells userspace how long the information elements added to a probe request frame can be at most. It also updates the at76 to advertise that it cannot support that, and, for now until I can fix that, iwlwifi too. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 1 + include/linux/nl80211.h | 4 ++++ include/net/wireless.h | 1 + net/mac80211/main.c | 13 ++++++++++++- net/mac80211/util.c | 2 ++ net/wireless/nl80211.c | 7 +++++++ 7 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 69248ded5102..55f947ac56d1 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -2250,6 +2250,7 @@ static int at76_init_new_device(struct at76_priv *priv, /* mac80211 initialisation */ priv->hw->wiphy->max_scan_ssids = 1; + priv->hw->wiphy->max_scan_ie_len = 0; priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band; priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 82abb1f9087f..ef55f91374a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1306,6 +1306,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->wiphy->custom_regulatory = true; hw->wiphy->max_scan_ssids = 1; + hw->wiphy->max_scan_ie_len = 0; /* XXX for now */ /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 27f230f063b3..209cacee5285 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -390,6 +390,8 @@ enum nl80211_commands { * * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements + * that can be added to a scan request * * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive @@ -507,6 +509,8 @@ enum nl80211_attrs { NL80211_ATTR_KEY_TYPE, + NL80211_ATTR_MAX_SCAN_IE_LEN, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/wireless.h b/include/net/wireless.h index 64a76208580c..2bcdeda46d81 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -222,6 +222,7 @@ struct wiphy { int bss_priv_size; u8 max_scan_ssids; + u16 max_scan_ie_len; /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't diff --git a/net/mac80211/main.c b/net/mac80211/main.c index fbcbed6cad01..ee58a7873699 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -728,7 +728,18 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, return NULL; wiphy->privid = mac80211_wiphy_privid; - wiphy->max_scan_ssids = 4; + + if (!ops->hw_scan) { + /* For hw_scan, driver needs to set these up. */ + wiphy->max_scan_ssids = 4; + + /* we support a maximum of 32 rates in cfg80211 */ + wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN + - 2 - 32 /* SSID */ + - 4 - 32 /* (ext) supp rates */; + + } + /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - sizeof(struct cfg80211_bss); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index fdf432f14554..05caf34f31da 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -890,6 +890,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, *pos = rate->bitrate / 5; } + /* if adding more here, adjust max_scan_ie_len */ + if (ie) memcpy(skb_put(skb, ie_len), ie, ie_len); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1394115cde95..447fa1790b4e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -181,6 +181,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); + NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, + dev->wiphy.max_scan_ie_len); nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) @@ -2528,6 +2530,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) else ie_len = 0; + if (ie_len > wiphy->max_scan_ie_len) { + err = -EINVAL; + goto out; + } + request = kzalloc(sizeof(*request) + sizeof(*ssid) * n_ssids + sizeof(channel) * n_channels -- cgit v1.2.3 From de95a54b1aebe5592cae971ca5e5d9ec6a381a17 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Apr 2009 11:58:36 +0200 Subject: mac80211: pass all probe request IEs to driver Instead of just passing the cfg80211-requested IEs, pass the locally generated ones as well. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 2 +- include/net/mac80211.h | 13 +++++--- net/mac80211/ieee80211_i.h | 9 ++++-- net/mac80211/main.c | 49 +++++++++++++++++++--------- net/mac80211/scan.c | 24 +++++++++++++- net/mac80211/util.c | 79 ++++++++++++++++++++++++++++------------------ net/wireless/nl80211.c | 3 +- 7 files changed, 123 insertions(+), 56 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2b1f6c69773c..d303c269a693 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -503,7 +503,7 @@ struct cfg80211_scan_request { int n_ssids; struct ieee80211_channel **channels; u32 n_channels; - u8 *ie; + const u8 *ie; size_t ie_len; /* internal */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3b83a80e3fe0..2c6f976831b5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1330,11 +1330,14 @@ enum ieee80211_ampdu_mlme_action { * the scan state machine in stack. The scan must honour the channel * configuration done by the regulatory agent in the wiphy's * registered bands. The hardware (or the driver) needs to make sure - * that power save is disabled. When the scan finishes, - * ieee80211_scan_completed() must be called; note that it also must - * be called when the scan cannot finish because the hardware is - * turned off! Anything else is a bug! Returns a negative error code - * which will be seen in userspace. + * that power save is disabled. + * The @req ie/ie_len members are rewritten by mac80211 to contain the + * entire IEs after the SSID, so that drivers need not look at these + * at all but just send them after the SSID -- mac80211 includes the + * (extended) supported rates and HT information (where applicable). + * When the scan finishes, ieee80211_scan_completed() must be called; + * note that it also must be called when the scan cannot finish due to + * any error unless this callback returned a negative error code. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 73d9f894ed5d..cb80a80504e6 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -671,7 +671,10 @@ struct ieee80211_local { struct cfg80211_scan_request int_scan_req; struct cfg80211_scan_request *scan_req; struct ieee80211_channel *scan_channel; + const u8 *orig_ies; + int orig_ies_len; int scan_channel_idx; + int scan_ies_len; enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; unsigned long last_scan_completed; @@ -1090,9 +1093,11 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u8 *extra, size_t extra_len, const u8 *bssid, int encrypt); +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len); + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, const size_t supp_rates_len, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ee58a7873699..b3bbe78821d9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -729,22 +729,12 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, wiphy->privid = mac80211_wiphy_privid; - if (!ops->hw_scan) { - /* For hw_scan, driver needs to set these up. */ - wiphy->max_scan_ssids = 4; - - /* we support a maximum of 32 rates in cfg80211 */ - wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN - - 2 - 32 /* SSID */ - - 4 - 32 /* (ext) supp rates */; - - } - /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - sizeof(struct cfg80211_bss); local = wiphy_priv(wiphy); + local->hw.wiphy = wiphy; local->hw.priv = (char *)local + @@ -831,7 +821,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) enum ieee80211_band band; struct net_device *mdev; struct ieee80211_master_priv *mpriv; - int channels, i, j; + int channels, i, j, max_bitrates; /* * generic code guarantees at least one band, @@ -839,18 +829,23 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) * that hw.conf.channel is assigned */ channels = 0; + max_bitrates = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; - if (sband && !local->oper_channel) { + if (!sband) + continue; + if (!local->oper_channel) { /* init channel we're on */ local->hw.conf.channel = local->oper_channel = local->scan_channel = &sband->channels[0]; } - if (sband) - channels += sband->n_channels; + channels += sband->n_channels; + + if (max_bitrates < sband->n_bitrates) + max_bitrates = sband->n_bitrates; } local->int_scan_req.n_channels = channels; @@ -870,6 +865,30 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; + /* + * Calculate scan IE length -- we need this to alloc + * memory and to subtract from the driver limit. It + * includes the (extended) supported rates and HT + * information -- SSID is the driver's responsibility. + */ + local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ + + if (!local->ops->hw_scan) { + /* For hw_scan, driver needs to set these up. */ + local->hw.wiphy->max_scan_ssids = 4; + local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + } + + /* + * If the driver supports any scan IEs, then assume the + * limit includes the IEs mac80211 will add, otherwise + * leave it at zero and let the driver sort it out; we + * still pass our IEs to the driver but userspace will + * not be allowed to in that case. + */ + if (local->hw.wiphy->max_scan_ie_len) + local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; + result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 3bf9839f5916..4ec1bfc7f6a9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -285,6 +285,12 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) if (WARN_ON(!local->scan_req)) return; + if (local->hw_scanning) { + kfree(local->scan_req->ie); + local->scan_req->ie = local->orig_ies; + local->scan_req->ie_len = local->orig_ies_len; + } + if (local->scan_req != &local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; @@ -457,12 +463,28 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, } if (local->ops->hw_scan) { - int rc; + u8 *ies; + int rc, ielen; + + ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + req->ie_len, GFP_KERNEL); + if (!ies) + return -ENOMEM; + + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + local->orig_ies = req->ie; + local->orig_ies_len = req->ie_len; + req->ie = ies; + req->ie_len = ielen; local->hw_scanning = true; rc = local->ops->hw_scan(local_to_hw(local), req); if (rc) { local->hw_scanning = false; + kfree(ies); + req->ie_len = local->orig_ies_len; + req->ie = local->orig_ies; return rc; } local->scan_sdata = scan_sdata; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 05caf34f31da..72b091317a7c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -831,16 +831,57 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb, encrypt); } +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + const u8 *ie, size_t ie_len) +{ + struct ieee80211_supported_band *sband; + u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; + int i; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + pos = buffer; + + *pos++ = WLAN_EID_SUPP_RATES; + supp_rates_len = pos; + *pos++ = 0; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + + if (esupp_rates_len) { + *esupp_rates_len += 1; + } else if (*supp_rates_len == 8) { + *pos++ = WLAN_EID_EXT_SUPP_RATES; + esupp_rates_len = pos; + *pos++ = 1; + } else + *supp_rates_len += 1; + + *pos++ = rate->bitrate / 5; + } + + /* + * If adding more here, adjust code in main.c + * that calculates local->scan_ies_len. + */ + + if (ie) { + memcpy(pos, ie, ie_len); + pos += ie_len; + } + + return pos - buffer; +} + void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len, - u8 *ie, size_t ie_len) + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; + u8 *pos; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ie_len); @@ -867,33 +908,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; memcpy(pos, ssid, ssid_len); + pos += ssid_len; - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - *pos = rate->bitrate / 5; - } - - /* if adding more here, adjust max_scan_ie_len */ - - if (ie) - memcpy(skb_put(skb, ie_len), ie, ie_len); + skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); ieee80211_tx_skb(sdata, skb, 0); } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 447fa1790b4e..68c51022e9dd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2597,7 +2597,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_IE]) { request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); - memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]), + memcpy((void *)request->ie, + nla_data(info->attrs[NL80211_ATTR_IE]), request->ie_len); } -- cgit v1.2.3 From 5ef2d41afb7fce2315d12a8aaebe0c9f1b50755b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 31 Mar 2009 12:12:07 +0200 Subject: mac80211: include HT capabilities in probe request Include the HT capabilities in the probe request frame. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 5 +++++ net/mac80211/util.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b3bbe78821d9..679b3a14f11f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -822,6 +822,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) struct net_device *mdev; struct ieee80211_master_priv *mpriv; int channels, i, j, max_bitrates; + bool supp_ht; /* * generic code guarantees at least one band, @@ -830,6 +831,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) */ channels = 0; max_bitrates = 0; + supp_ht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; @@ -846,6 +848,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; + supp_ht = supp_ht || sband->ht_cap.ht_supported; } local->int_scan_req.n_channels = channels; @@ -872,6 +875,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) * information -- SSID is the driver's responsibility. */ local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ + if (supp_ht) + local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 72b091317a7c..1ff83532120f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -861,6 +861,22 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, *pos++ = rate->bitrate / 5; } + if (sband->ht_cap.ht_supported) { + __le16 tmp = cpu_to_le16(sband->ht_cap.cap); + + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + /* TODO: needs a define here for << 2 */ + *pos++ = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << 2); + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ + } + /* * If adding more here, adjust code in main.c * that calculates local->scan_ies_len. -- cgit v1.2.3 From 66174bbea0b9c5bd4b7d060fed26bf5ec912c422 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2009 17:23:54 +0300 Subject: mac80211: Report rejected association to user space SME When using nl80211 association, we need to send association response with a failure code to user space SME instead of just internally trying to send out the same (re)association request again couple of times. This fixes problems in association process getting stuck on a failure when user space is not notified in any way that something actually failed. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4ce5b9c22324..90267afa8e69 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1374,6 +1374,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * association next time. This works around some broken APs * which do not correctly reject reassociation requests. */ ifmgd->flags &= ~IEEE80211_STA_PREV_BSSID_SET; + cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, len); + if (ifmgd->flags & IEEE80211_STA_EXT_SME) { + /* Wait for SME to decide what to do next */ + ifmgd->state = IEEE80211_STA_MLME_DISABLED; + } return; } -- cgit v1.2.3 From 910cfee363feda81cd5af4939ed9e0d27677b43f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 1 Apr 2009 10:42:36 -0500 Subject: b43legacy: Do not select HW_RANDOM Auto-depend on HW_RANDOM, rather than "select"ing it. This way the user has the choice to enable or disable HWRNG support. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/Kconfig | 8 +++++++- drivers/net/wireless/b43legacy/b43legacy.h | 2 ++ drivers/net/wireless/b43legacy/main.c | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig index aef2298d37ac..d4f628a74bbd 100644 --- a/drivers/net/wireless/b43legacy/Kconfig +++ b/drivers/net/wireless/b43legacy/Kconfig @@ -3,7 +3,6 @@ config B43LEGACY depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA select SSB select FW_LOADER - select HW_RANDOM ---help--- b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the @@ -51,6 +50,13 @@ config B43LEGACY_RFKILL depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY) default y +# This config option automatically enables b43 HW-RNG support, +# if the HW-RNG core is enabled. +config B43LEGACY_HWRNG + bool + depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY) + default y + config B43LEGACY_DEBUG bool "Broadcom 43xx-legacy debugging" depends on B43LEGACY diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 97b0e06dfe21..4cdde4ad17c0 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -596,9 +596,11 @@ struct b43legacy_wl { /* Stats about the wireless interface */ struct ieee80211_low_level_stats ieee_stats; +#ifdef CONFIG_B43LEGACY_HWRNG struct hwrng rng; u8 rng_initialized; char rng_name[30 + 1]; +#endif /* The RF-kill button */ struct b43legacy_rfkill rfkill; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 879edc786713..81dbbc1c591a 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2297,6 +2297,7 @@ static void b43legacy_security_init(struct b43legacy_wldev *dev) dev->max_nr_keys - 8); } +#ifdef CONFIG_B43LEGACY_HWRNG static int b43legacy_rng_read(struct hwrng *rng, u32 *data) { struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv; @@ -2312,17 +2313,21 @@ static int b43legacy_rng_read(struct hwrng *rng, u32 *data) return (sizeof(u16)); } +#endif static void b43legacy_rng_exit(struct b43legacy_wl *wl) { +#ifdef CONFIG_B43LEGACY_HWRNG if (wl->rng_initialized) hwrng_unregister(&wl->rng); +#endif } static int b43legacy_rng_init(struct b43legacy_wl *wl) { - int err; + int err = 0; +#ifdef CONFIG_B43LEGACY_HWRNG snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); wl->rng.name = wl->rng_name; @@ -2336,6 +2341,7 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl) "number generator (%d)\n", err); } +#endif return err; } -- cgit v1.2.3 From 64cdb0e3b8a5e5393cb64328ce0c844b7cf3a40e Mon Sep 17 00:00:00 2001 From: Fabio Rossi Date: Wed, 1 Apr 2009 20:37:50 +0200 Subject: ath5k: fix interpolation with equal power levels When the EEPROM contains weird values for the power levels we have to fix the interpolation process. Signed-off-by: Fabio Rossi Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 49 ++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 9e2faae5ae94..b48b29dca3d2 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1487,28 +1487,35 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, { s8 tmp; s16 min_pwrL, min_pwrR; - s16 pwr_i = pwrL[0]; - - do { - pwr_i--; - tmp = (s8) ath5k_get_interpolated_value(pwr_i, - pwrL[0], pwrL[1], - stepL[0], stepL[1]); - - } while (tmp > 1); - - min_pwrL = pwr_i; - - pwr_i = pwrR[0]; - do { - pwr_i--; - tmp = (s8) ath5k_get_interpolated_value(pwr_i, - pwrR[0], pwrR[1], - stepR[0], stepR[1]); - - } while (tmp > 1); + s16 pwr_i; + + if (pwrL[0] == pwrL[1]) + min_pwrL = pwrL[0]; + else { + pwr_i = pwrL[0]; + do { + pwr_i--; + tmp = (s8) ath5k_get_interpolated_value(pwr_i, + pwrL[0], pwrL[1], + stepL[0], stepL[1]); + } while (tmp > 1); + + min_pwrL = pwr_i; + } - min_pwrR = pwr_i; + if (pwrR[0] == pwrR[1]) + min_pwrR = pwrR[0]; + else { + pwr_i = pwrR[0]; + do { + pwr_i--; + tmp = (s8) ath5k_get_interpolated_value(pwr_i, + pwrR[0], pwrR[1], + stepR[0], stepR[1]); + } while (tmp > 1); + + min_pwrR = pwr_i; + } /* Keep the right boundary so that it works for both curves */ return max(min_pwrL, min_pwrR); -- cgit v1.2.3 From 11397a656f14466421bac503f0f3aaadf9486120 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 1 Apr 2009 14:33:23 -0700 Subject: iwlwifi: adding triple stream rate support for MIMO3 Adding ht triple_stream_basic_rates for MIMO3 supports Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index ef55f91374a1..84ac1cec6f5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1117,6 +1117,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; + priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; } EXPORT_SYMBOL(iwl_connection_init_rx_config); -- cgit v1.2.3 From 584a0f00636d34f71a80f5b550a305f1a1620693 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 1 Apr 2009 14:33:24 -0700 Subject: iwlwifi: adding MIMO3 support in rate scaling Separated the MIMO tpt matrix into MIMO2 and MIMO3, adding MIMO3 support in rate scaling algorithm. If the device support 3x3, then utilize all three antenna (A/B/C) for tx to improve throughput. Adding rs_switch_to_mimo3() function to allow switch to mimo3 modulation mode from other modes(legacy/siso/mimo2). Adding rs_move_mimo3_to_other() function to allow switch from mimo3 modulation mode to either siso or mimo2; also support toggle between SGI and NGI. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 331 +++++++++++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 18 ++ 2 files changed, 325 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index cab7842a73aa..7cdbcfe483f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -191,7 +191,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits * "G" is the only table that supports CCK (the first 4 rates). */ -/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/ + static s32 expected_tpt_A[IWL_RATE_COUNT] = { 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 }; @@ -208,11 +208,11 @@ static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 }; -static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = { 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 }; -static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 }; @@ -224,14 +224,31 @@ static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 }; -static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 }; -static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { +static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 }; +/* Expected throughput metric MIMO3 */ +static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 +}; + +static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 +}; + +static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 +}; + +static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { + 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 +}; + static inline u8 rs_extract_rate(u32 rate_n_flags) { return (u8)(rate_n_flags & 0xFF); @@ -1011,17 +1028,26 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, tbl->expected_tpt = expected_tpt_siso20MHzSGI; else tbl->expected_tpt = expected_tpt_siso20MHz; - - } else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */ + } else if (is_mimo2(tbl->lq_type)) { + if (tbl->is_fat && !lq_sta->is_dup) + if (tbl->is_SGI) + tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; + else + tbl->expected_tpt = expected_tpt_mimo2_40MHz; + else if (tbl->is_SGI) + tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; + else + tbl->expected_tpt = expected_tpt_mimo2_20MHz; + } else if (is_mimo3(tbl->lq_type)) { if (tbl->is_fat && !lq_sta->is_dup) if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo40MHzSGI; + tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; else - tbl->expected_tpt = expected_tpt_mimo40MHz; + tbl->expected_tpt = expected_tpt_mimo3_40MHz; else if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo20MHzSGI; + tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI; else - tbl->expected_tpt = expected_tpt_mimo20MHz; + tbl->expected_tpt = expected_tpt_mimo3_20MHz; } else tbl->expected_tpt = expected_tpt_G; } @@ -1130,7 +1156,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, } /* - * Set up search table for MIMO + * Set up search table for MIMO2 */ static int rs_switch_to_mimo2(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, @@ -1183,7 +1209,73 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); + if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { + IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", + rate, rate_mask); + return -1; + } + tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); + + IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", + tbl->current_rate, is_green); + return 0; +} + +/* + * Set up search table for MIMO3 + */ +static int rs_switch_to_mimo3(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta, + struct ieee80211_conf *conf, + struct ieee80211_sta *sta, + struct iwl_scale_tbl_info *tbl, int index) +{ + u16 rate_mask; + s32 rate; + s8 is_green = lq_sta->is_green; + + if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) + return -1; + + if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + == WLAN_HT_CAP_SM_PS_STATIC) + return -1; + + /* Need both Tx chains/antennas to support MIMO */ + if (priv->hw_params.tx_chains_num < 3) + return -1; + + IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); + + tbl->lq_type = LQ_MIMO3; + tbl->is_dup = lq_sta->is_dup; + tbl->action = 0; + rate_mask = lq_sta->active_mimo3_rate; + + if (priv->current_ht_config.supported_chan_width + == IWL_CHANNEL_WIDTH_40MHZ) + tbl->is_fat = 1; + else + tbl->is_fat = 0; + /* FIXME: - don't toggle SGI here + if (tbl->is_fat) { + if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) + tbl->is_SGI = 1; + else + tbl->is_SGI = 0; + } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) + tbl->is_SGI = 1; + else + tbl->is_SGI = 0; + */ + + rs_set_expected_tpt_table(lq_sta, tbl); + + rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); + + IWL_DEBUG_RATE(priv, "LQ: MIMO3 best rate %d mask %X\n", + rate, rate_mask); if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", rate, rate_mask); @@ -1342,9 +1434,29 @@ static int rs_move_legacy_other(struct iwl_priv *priv, goto out; } break; + + case IWL_LEGACY_SWITCH_MIMO3_ABC: + IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO3\n"); + + /* Set up search table to try MIMO3 */ + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + + search_tbl->ant_type = ANT_ABC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) { + lq_sta->action_counter = 0; + goto out; + } + break; } tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) + if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; if (tbl->action == start_action) @@ -1357,7 +1469,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, out: lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) + if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; return 0; @@ -1457,9 +1569,23 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, rate_n_flags_from_tbl(priv, search_tbl, index, is_green); goto out; + case IWL_SISO_SWITCH_MIMO3_ABC: + IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n"); + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + search_tbl->ant_type = ANT_ABC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + break; } tbl->action++; - if (tbl->action > IWL_SISO_SWITCH_GI) + if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) tbl->action = IWL_SISO_SWITCH_ANTENNA1; if (tbl->action == start_action) @@ -1471,15 +1597,15 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, out: lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_SISO_SWITCH_GI) + if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) tbl->action = IWL_SISO_SWITCH_ANTENNA1; return 0; } /* - * Try to switch to new modulation mode from MIMO + * Try to switch to new modulation mode from MIMO2 */ -static int rs_move_mimo_to_other(struct iwl_priv *priv, +static int rs_move_mimo2_to_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, struct ieee80211_sta *sta, int index) @@ -1501,7 +1627,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, switch (tbl->action) { case IWL_MIMO2_SWITCH_ANTENNA1: case IWL_MIMO2_SWITCH_ANTENNA2: - IWL_DEBUG_RATE(priv, "LQ: MIMO toggle Antennas\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n"); if (tx_chains_num <= 2) break; @@ -1549,9 +1675,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, HT_SHORT_GI_40MHZ)) break; - IWL_DEBUG_RATE(priv, "LQ: MIMO toggle SGI/NGI\n"); + IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); - /* Set up new search table for MIMO */ + /* Set up new search table for MIMO2 */ memcpy(search_tbl, tbl, sz); search_tbl->is_SGI = !tbl->is_SGI; rs_set_expected_tpt_table(lq_sta, search_tbl); @@ -1571,9 +1697,24 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, index, is_green); goto out; + case IWL_MIMO2_SWITCH_MIMO3_ABC: + IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to MIMO3\n"); + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + search_tbl->ant_type = ANT_ABC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + + break; } tbl->action++; - if (tbl->action > IWL_MIMO2_SWITCH_GI) + if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; if (tbl->action == start_action) @@ -1584,12 +1725,149 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, out: lq_sta->search_better_tbl = 1; tbl->action++; - if (tbl->action > IWL_MIMO2_SWITCH_GI) + if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; return 0; } +/* + * Try to switch to new modulation mode from MIMO3 + */ +static int rs_move_mimo3_to_other(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta, + struct ieee80211_conf *conf, + struct ieee80211_sta *sta, int index) +{ + s8 is_green = lq_sta->is_green; + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); + u8 start_action = tbl->action; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; + int ret; + + for (;;) { + lq_sta->action_counter++; + switch (tbl->action) { + case IWL_MIMO3_SWITCH_ANTENNA1: + case IWL_MIMO3_SWITCH_ANTENNA2: + IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle Antennas\n"); + + if (tx_chains_num <= 3) + break; + + if (window->success_ratio >= IWL_RS_GOOD_RATIO) + break; + + memcpy(search_tbl, tbl, sz); + if (rs_toggle_antenna(valid_tx_ant, + &search_tbl->current_rate, search_tbl)) + goto out; + break; + case IWL_MIMO3_SWITCH_SISO_A: + case IWL_MIMO3_SWITCH_SISO_B: + case IWL_MIMO3_SWITCH_SISO_C: + IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to SISO\n"); + + /* Set up new search table for SISO */ + memcpy(search_tbl, tbl, sz); + + if (tbl->action == IWL_MIMO3_SWITCH_SISO_A) + search_tbl->ant_type = ANT_A; + else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B) + search_tbl->ant_type = ANT_B; + else + search_tbl->ant_type = ANT_C; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_siso(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + + break; + + case IWL_MIMO3_SWITCH_MIMO2_AB: + case IWL_MIMO3_SWITCH_MIMO2_AC: + case IWL_MIMO3_SWITCH_MIMO2_BC: + IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to MIMO2\n"); + + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = 0; + if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB) + search_tbl->ant_type = ANT_AB; + else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC) + search_tbl->ant_type = ANT_AC; + else + search_tbl->ant_type = ANT_BC; + + if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) + break; + + ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, + search_tbl, index); + if (!ret) + goto out; + + break; + + case IWL_MIMO3_SWITCH_GI: + if (!tbl->is_fat && + !(priv->current_ht_config.sgf & + HT_SHORT_GI_20MHZ)) + break; + if (tbl->is_fat && + !(priv->current_ht_config.sgf & + HT_SHORT_GI_40MHZ)) + break; + + IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); + + /* Set up new search table for MIMO */ + memcpy(search_tbl, tbl, sz); + search_tbl->is_SGI = !tbl->is_SGI; + rs_set_expected_tpt_table(lq_sta, search_tbl); + /* + * If active table already uses the fastest possible + * modulation (dual stream with short guard interval), + * and it's working well, there's no need to look + * for a better type of modulation! + */ + if (tbl->is_SGI) { + s32 tpt = lq_sta->last_tpt / 100; + if (tpt >= search_tbl->expected_tpt[index]) + break; + } + search_tbl->current_rate = + rate_n_flags_from_tbl(priv, search_tbl, + index, is_green); + goto out; + } + tbl->action++; + if (tbl->action > IWL_MIMO3_SWITCH_GI) + tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; + + if (tbl->action == start_action) + break; + } + search_tbl->lq_type = LQ_NONE; + return 0; + out: + lq_sta->search_better_tbl = 1; + tbl->action++; + if (tbl->action > IWL_MIMO3_SWITCH_GI) + tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; + return 0; + +} + /* * Check whether we should continue using same modulation mode, or * begin search for a new mode, based on: @@ -1997,8 +2275,10 @@ lq_update: rs_move_legacy_other(priv, lq_sta, conf, sta, index); else if (is_siso(tbl->lq_type)) rs_move_siso_to_other(priv, lq_sta, conf, sta, index); + else if (is_mimo2(tbl->lq_type)) + rs_move_mimo2_to_other(priv, lq_sta, conf, sta, index); else - rs_move_mimo_to_other(priv, lq_sta, conf, sta, index); + rs_move_mimo3_to_other(priv, lq_sta, conf, sta, index); /* If new "search" mode was selected, set up in uCode table */ if (lq_sta->search_better_tbl) { @@ -2362,6 +2642,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, } else if (num_of_ant(tbl_type.ant_type) == 2) { lq_cmd->general_params.dual_stream_ant_msk = tbl_type.ant_type; + } else if (num_of_ant(tbl_type.ant_type) == 3) { + lq_cmd->general_params.dual_stream_ant_msk = + tbl_type.ant_type; } /* otherwise we don't modify the existing value */ index++; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index ab59acc405d9..9cd90ba5ef95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -241,6 +241,7 @@ enum { #define IWL_LEGACY_SWITCH_MIMO2_AB 3 #define IWL_LEGACY_SWITCH_MIMO2_AC 4 #define IWL_LEGACY_SWITCH_MIMO2_BC 5 +#define IWL_LEGACY_SWITCH_MIMO3_ABC 6 /* possible actions when in siso mode */ #define IWL_SISO_SWITCH_ANTENNA1 0 @@ -249,6 +250,8 @@ enum { #define IWL_SISO_SWITCH_MIMO2_AC 3 #define IWL_SISO_SWITCH_MIMO2_BC 4 #define IWL_SISO_SWITCH_GI 5 +#define IWL_SISO_SWITCH_MIMO3_ABC 6 + /* possible actions when in mimo mode */ #define IWL_MIMO2_SWITCH_ANTENNA1 0 @@ -257,6 +260,21 @@ enum { #define IWL_MIMO2_SWITCH_SISO_B 3 #define IWL_MIMO2_SWITCH_SISO_C 4 #define IWL_MIMO2_SWITCH_GI 5 +#define IWL_MIMO2_SWITCH_MIMO3_ABC 6 + + +/* possible actions when in mimo3 mode */ +#define IWL_MIMO3_SWITCH_ANTENNA1 0 +#define IWL_MIMO3_SWITCH_ANTENNA2 1 +#define IWL_MIMO3_SWITCH_SISO_A 2 +#define IWL_MIMO3_SWITCH_SISO_B 3 +#define IWL_MIMO3_SWITCH_SISO_C 4 +#define IWL_MIMO3_SWITCH_MIMO2_AB 5 +#define IWL_MIMO3_SWITCH_MIMO2_AC 6 +#define IWL_MIMO3_SWITCH_MIMO2_BC 7 +#define IWL_MIMO3_SWITCH_GI 8 + + /*FIXME:RS:add possible actions for MIMO3*/ -- cgit v1.2.3 From 3eb9296970e70902593b15ed3080e389954cf5f5 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 1 Apr 2009 14:33:25 -0700 Subject: iwlwifi: add debug messages when start aggregation queue This patch adding few more debug messages if encounter error when driver try to start tx aggregation queue. Also change from IWL_ERR to IWL_DEBUG_HT is the HW legacy queue is empty when driver request to move to aggregation queue. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-tx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1f117a49c569..c734c5f7e976 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1170,8 +1170,10 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) __func__, ra, tid); sta_id = iwl_find_station(priv, ra); - if (sta_id == IWL_INVALID_STATION) + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; + } if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); @@ -1179,8 +1181,10 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) } txq_id = iwl_txq_ctx_activate_free(priv); - if (txq_id == -1) + if (txq_id == -1) { + IWL_ERR(priv, "No free aggregation queue available\n"); return -ENXIO; + } spin_lock_irqsave(&priv->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; @@ -1194,7 +1198,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) return ret; if (tid_data->tfds_in_queue == 0) { - IWL_ERR(priv, "HW queue is empty\n"); + IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); } else { -- cgit v1.2.3 From a4ed90d60c39c5aef9a170d7693f61175acb22e0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 2 Apr 2009 14:08:07 -0400 Subject: cfg80211: respect API on orig_flags on channel for beacon hint As part of our documented API we always respect the orig_flag settings on a channel. We forgot to follow this for the beacon hints. Acked-by: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 6c1993d99902..4af4304cec3e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1070,12 +1070,14 @@ static void handle_reg_beacon(struct wiphy *wiphy, if (likely(chan->center_freq != reg_beacon->chan.center_freq)) return; - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { + if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) { chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; REG_DEBUG_BEACON_FLAG("active scanning"); } - if (chan->flags & IEEE80211_CHAN_NO_IBSS) { + if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && + !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) { chan->flags &= ~IEEE80211_CHAN_NO_IBSS; REG_DEBUG_BEACON_FLAG("beaconing"); } -- cgit v1.2.3 From 5dab3b8a68cc97a7e6b9f79f5de05803c8e55a3c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 2 Apr 2009 14:08:08 -0400 Subject: cfg80211: add netlink channel put helper This adds a netlink channel put helper, nl80211_msg_put_channel(), which we will also make use of later for the beacon hints events. Acked-by: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 68c51022e9dd..7285bdc4e598 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -156,6 +156,30 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); } +static int nl80211_msg_put_channel(struct sk_buff *msg, + struct ieee80211_channel *chan) +{ + NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, + chan->center_freq); + + if (chan->flags & IEEE80211_CHAN_DISABLED) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); + if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); + if (chan->flags & IEEE80211_CHAN_NO_IBSS) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); + if (chan->flags & IEEE80211_CHAN_RADAR) + NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); + + NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, + DBM_TO_MBM(chan->max_power)); + + return 0; + + nla_put_failure: + return -ENOBUFS; +} + /* netlink command implementations */ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, @@ -234,20 +258,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, goto nla_put_failure; chan = &dev->wiphy.bands[band]->channels[i]; - NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, - chan->center_freq); - - if (chan->flags & IEEE80211_CHAN_DISABLED) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED); - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN); - if (chan->flags & IEEE80211_CHAN_NO_IBSS) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS); - if (chan->flags & IEEE80211_CHAN_RADAR) - NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); - - NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - DBM_TO_MBM(chan->max_power)); + + if (nl80211_msg_put_channel(msg, chan)) + goto nla_put_failure; nla_nest_end(msg, nl_freq); } -- cgit v1.2.3 From 6bad8766620a3c8b64afa981502fdb543e3cfd6c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 2 Apr 2009 14:08:09 -0400 Subject: cfg80211: send regulatory beacon hint events to userspace This informs userspace when a change has occured on a world roaming wiphy's channel which has lifted some restrictions due to a regulatory beacon hint. Because this is now sent to userspace through the regulatory multicast group we remove the debug prints we used to use as they are no longer necessary. Acked-by: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/linux/nl80211.h | 34 ++++++++++++++++++++++++++++++- net/wireless/nl80211.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 5 +++++ net/wireless/reg.c | 28 ++++++++++++------------- 4 files changed, 106 insertions(+), 15 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 209cacee5285..05ba3539b77e 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -7,7 +7,7 @@ * Copyright 2008 Michael Wu * Copyright 2008 Luis Carlos Cobo * Copyright 2008 Michael Buesch - * Copyright 2008 Luis R. Rodriguez + * Copyright 2008, 2009 Luis R. Rodriguez * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe * @@ -166,6 +166,22 @@ * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on * to (%NL80211_ATTR_REG_ALPHA2). + * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon + * has been found while world roaming thus enabling active scan or + * any mode of operation that initiates TX (beacons) on a channel + * where we would not have been able to do either before. As an example + * if you are world roaming (regulatory domain set to world or if your + * driver is using a custom world roaming regulatory domain) and while + * doing a passive scan on the 5 GHz band you find an AP there (if not + * on a DFS channel) you will now be able to actively scan for that AP + * or use AP mode on your card on that same channel. Note that this will + * never be used for channels 1-11 on the 2 GHz band as they are always + * enabled world wide. This beacon hint is only sent if your device had + * either disabled active scanning or beaconing on a channel. We send to + * userspace the wiphy on which we removed a restriction from + * (%NL80211_ATTR_WIPHY) and the channel on which this occurred + * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) + * the beacon hint was processed. * * @NL80211_CMD_AUTHENTICATE: authentication request and notification. * This command is used both as a command (request to authenticate) and @@ -270,6 +286,8 @@ enum nl80211_commands { NL80211_CMD_MICHAEL_MIC_FAILURE, + NL80211_CMD_REG_BEACON_HINT, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -288,6 +306,7 @@ enum nl80211_commands { #define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE #define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE +#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT /** * enum nl80211_attrs - nl80211 netlink attributes @@ -423,6 +442,17 @@ enum nl80211_commands { * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as * a u32 * + * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _before_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _after_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -511,6 +541,8 @@ enum nl80211_attrs { NL80211_ATTR_MAX_SCAN_IE_LEN, + NL80211_ATTR_FREQ_BEFORE, + NL80211_ATTR_FREQ_AFTER, /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7285bdc4e598..85b5aa3c76f8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3491,6 +3491,60 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, nlmsg_free(msg); } +void nl80211_send_beacon_hint_event(struct wiphy *wiphy, + struct ieee80211_channel *channel_before, + struct ieee80211_channel *channel_after) +{ + struct sk_buff *msg; + void *hdr; + struct nlattr *nl_freq; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_BEACON_HINT); + if (!hdr) { + nlmsg_free(msg); + return; + } + + /* + * Since we are applying the beacon hint to a wiphy we know its + * wiphy_idx is valid + */ + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)); + + /* Before */ + nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE); + if (!nl_freq) + goto nla_put_failure; + if (nl80211_msg_put_channel(msg, channel_before)) + goto nla_put_failure; + nla_nest_end(msg, nl_freq); + + /* After */ + nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER); + if (!nl_freq) + goto nla_put_failure; + if (nl80211_msg_put_channel(msg, channel_after)) + goto nla_put_failure; + nla_nest_end(msg, nl_freq); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_ATOMIC); + + return; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + /* initialisation/exit functions */ int nl80211_init(void) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index e4b92cccd157..b3aaa59afa08 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -29,4 +29,9 @@ nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, enum nl80211_key_type key_type, int key_id, const u8 *tsc); +extern void +nl80211_send_beacon_hint_event(struct wiphy *wiphy, + struct ieee80211_channel *channel_before, + struct ieee80211_channel *channel_after); + #endif /* __NET_WIRELESS_NL80211_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4af4304cec3e..574e217bcc86 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1049,18 +1049,10 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, struct reg_beacon *reg_beacon) { -#ifdef CONFIG_CFG80211_REG_DEBUG -#define REG_DEBUG_BEACON_FLAG(desc) \ - printk(KERN_DEBUG "cfg80211: Enabling " desc " on " \ - "frequency: %d MHz (Ch %d) on %s\n", \ - reg_beacon->chan.center_freq, \ - ieee80211_frequency_to_channel(reg_beacon->chan.center_freq), \ - wiphy_name(wiphy)); -#else -#define REG_DEBUG_BEACON_FLAG(desc) do {} while (0) -#endif struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; + bool channel_changed = false; + struct ieee80211_channel chan_before; assert_cfg80211_lock(); @@ -1070,20 +1062,28 @@ static void handle_reg_beacon(struct wiphy *wiphy, if (likely(chan->center_freq != reg_beacon->chan.center_freq)) return; + if (chan->beacon_found) + return; + + chan->beacon_found = true; + + chan_before.center_freq = chan->center_freq; + chan_before.flags = chan->flags; + if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) { chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - REG_DEBUG_BEACON_FLAG("active scanning"); + channel_changed = true; } if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) { chan->flags &= ~IEEE80211_CHAN_NO_IBSS; - REG_DEBUG_BEACON_FLAG("beaconing"); + channel_changed = true; } - chan->beacon_found = true; -#undef REG_DEBUG_BEACON_FLAG + if (channel_changed) + nl80211_send_beacon_hint_event(wiphy, &chan_before, chan); } /* -- cgit v1.2.3 From 25e47c18ac4d8ad09c2ed4b99c1dbbcb7e3d2c51 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 2 Apr 2009 20:14:06 +0200 Subject: cfg80211: add cipher capabilities This adds the necessary code and fields to let drivers specify their cipher capabilities and exports them to userspace. Also update mac80211 to export the ciphers it has. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 4 ++++ include/net/wireless.h | 5 +++++ net/mac80211/main.c | 14 ++++++++++++++ net/wireless/nl80211.c | 14 +++++++++++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 05ba3539b77e..c01423888db9 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -453,6 +453,9 @@ enum nl80211_commands { * attributes consists of a nested attribute containing * NL80211_FREQUENCY_ATTR_* * + * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported + * cipher suites + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -540,6 +543,7 @@ enum nl80211_attrs { NL80211_ATTR_KEY_TYPE, NL80211_ATTR_MAX_SCAN_IE_LEN, + NL80211_ATTR_CIPHER_SUITES, NL80211_ATTR_FREQ_BEFORE, NL80211_ATTR_FREQ_AFTER, diff --git a/include/net/wireless.h b/include/net/wireless.h index 2bcdeda46d81..44c2642d3c06 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -205,6 +205,8 @@ struct ieee80211_supported_band { * on the reg_notifier() if it chooses to ignore future * regulatory domain changes caused by other drivers. * @signal_type: signal type reported in &struct cfg80211_bss. + * @cipher_suites: supported cipher suites + * @n_cipher_suites: number of supported cipher suites */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -224,6 +226,9 @@ struct wiphy { u8 max_scan_ssids; u16 max_scan_ie_len; + int n_cipher_suites; + const u32 *cipher_suites; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 679b3a14f11f..c1145be72da4 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -823,6 +823,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) struct ieee80211_master_priv *mpriv; int channels, i, j, max_bitrates; bool supp_ht; + static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC + }; /* * generic code guarantees at least one band, @@ -894,6 +903,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (local->hw.wiphy->max_scan_ie_len) local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; + local->hw.wiphy->cipher_suites = cipher_suites; + local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) + local->hw.wiphy->n_cipher_suites--; + result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 85b5aa3c76f8..d33cab0e0fb2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -208,6 +208,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, dev->wiphy.max_scan_ie_len); + NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, + sizeof(u32) * dev->wiphy.n_cipher_suites, + dev->wiphy.cipher_suites); + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); if (!nl_modes) goto nla_put_failure; @@ -979,7 +983,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *drv; - int err; + int err, i; struct net_device *dev; struct key_params params; u8 key_idx = 0; @@ -1048,6 +1052,14 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) if (err) goto unlock_rtnl; + for (i = 0; i < drv->wiphy.n_cipher_suites; i++) + if (params.cipher == drv->wiphy.cipher_suites[i]) + break; + if (i == drv->wiphy.n_cipher_suites) { + err = -EINVAL; + goto out; + } + if (!drv->ops->add_key) { err = -EOPNOTSUPP; goto out; -- cgit v1.2.3 From b26ed97c75e1538176c09f29c423a3f8a75868a7 Mon Sep 17 00:00:00 2001 From: Anna Neal Date: Thu, 2 Apr 2009 14:44:09 -0700 Subject: libertas: increase spi driver thread priority Currently, the libertas main thread contends with the spi driver thread in the TX path. To improve throughput, ensure that the driver thread has higher scheduling priority than the libertas main thread. Do this by making the libertas spi driver thread a low priority real time thread. We measured an average throughput improvement of 13%. Signed-off-by: Anna Neal Signed-off-by: Andrey Yurovsky Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 07311e71af92..97493e2f4109 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -1020,6 +1020,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) struct libertas_spi_platform_data *pdata = spi->dev.platform_data; int err = 0; u32 scratch; + struct sched_param param = { .sched_priority = 1 }; lbs_deb_enter(LBS_DEB_SPI); @@ -1123,6 +1124,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) lbs_pr_err("error creating SPI thread: err=%d\n", err); goto remove_card; } + if (sched_setscheduler(card->spi_thread, SCHED_FIFO, ¶m)) + lbs_pr_err("Error setting scheduler, using default.\n"); + err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); if (err) { -- cgit v1.2.3 From 6a362bb1c9f900f7e6daeee52ff2d538badae49b Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 5 Apr 2009 11:01:20 -0400 Subject: ath5k: add support for Fukato Datacask Jupiter LEDs This adds support for the LEDs on the Jupiter netbook. Reported-by: Martin Bammer Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/led.c | 2 ++ include/linux/pci_ids.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 006f7716168e..cbdc0b308429 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -67,6 +67,8 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, /* Acer Extensa 5620z (nekoreeve@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, + /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ + { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, { } }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ee98cd570885..ea061e290d02 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2313,6 +2313,8 @@ #define PCI_VENDOR_ID_QMI 0x1a32 +#define PCI_VENDOR_ID_AZWAVE 0x1a3b + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 -- cgit v1.2.3 From 87cbfd06889256cac945b37c7f62f4ce7f44b34a Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 6 Apr 2009 01:03:09 +0400 Subject: p54spi: get rid of busy-wait loops p54spi_wakeup and p54spi_tx_frame used busy-waiting loop to poll for 'ready' bits in SPI_ADRS_HOST_INTERRUPTS register. With this change in place 'WR_READY timeout' messages do not show anymore. Signed-off-by: Max Filippov Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 41 +++++++++++++-------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 52023127cf37..59a5e778bb08 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -167,14 +167,13 @@ static const struct p54spi_spi_reg p54spi_registers_array[] = static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits) { int i; - __le32 buffer; for (i = 0; i < 2000; i++) { - p54spi_spi_read(priv, reg, &buffer, sizeof(buffer)); + __le32 buffer = p54spi_read32(priv, reg); if ((buffer & bits) == bits) return 1; - msleep(1); + msleep(0); } return 0; } @@ -185,10 +184,10 @@ static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base, p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); - if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, - cpu_to_le32(HOST_ALLOWED)) == 0) { + if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, + cpu_to_le32(HOST_ALLOWED))) { dev_err(&priv->spi->dev, "spi_write_dma not allowed " - "to DMA write."); + "to DMA write.\n"); return -EAGAIN; } @@ -330,21 +329,15 @@ static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val) static void p54spi_wakeup(struct p54s_priv *priv) { - unsigned long timeout; - u32 ints; - /* wake the chip */ p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, cpu_to_le32(SPI_TARGET_INT_WAKEUP)); /* And wait for the READY interrupt */ - timeout = jiffies + HZ; - - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); - while (!(ints & SPI_HOST_INT_READY)) { - if (time_after(jiffies, timeout)) - goto out; - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, + cpu_to_le32(SPI_HOST_INT_READY))) { + dev_err(&priv->spi->dev, "INT_READY timeout\n"); + goto out; } p54spi_int_ack(priv, SPI_HOST_INT_READY); @@ -432,9 +425,7 @@ static irqreturn_t p54spi_interrupt(int irq, void *config) static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) { struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - unsigned long timeout; int ret = 0; - u32 ints; p54spi_wakeup(priv); @@ -442,15 +433,11 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) if (ret < 0) goto out; - timeout = jiffies + 2 * HZ; - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); - while (!(ints & SPI_HOST_INT_WR_READY)) { - if (time_after(jiffies, timeout)) { - dev_err(&priv->spi->dev, "WR_READY timeout\n"); - ret = -1; - goto out; - } - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); + if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, + cpu_to_le32(SPI_HOST_INT_WR_READY))) { + dev_err(&priv->spi->dev, "WR_READY timeout\n"); + ret = -1; + goto out; } p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); -- cgit v1.2.3 From e45d8e534b67580eedd9b4910ccc16d6dd3cceff Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Mon, 6 Apr 2009 15:50:56 -0700 Subject: libertas: add support for Marvell SD8688 chip libertas: add support for Marvell SD8688 chip Use RxPD->pkt_ptr to locate eth803 header in the packet received since SD8688/v10 firmware allows a gap between RxPD and eth803 header. Set SDIO block size to 256 for CMD53. The maximum block size for SD8688 WLAN function is set to 512 in TPLFE_MAX_BLK_SIZE. But using 512 as block size results upto 2K bytes data (4 blocks) being transferred and causes buffer overflow in firmware. Both changes above are backward compatible with earlier firmware versions for SD8385/SD8686. The SDIO_DEVICE_IDs for SD8688 chip are added in include/linux/mmc/sdio_ids.h Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 4 ++-- drivers/net/wireless/libertas/if_sdio.c | 17 +++++++++++++---- drivers/net/wireless/libertas/if_sdio.h | 2 ++ drivers/net/wireless/libertas/rx.c | 15 ++++++++------- include/linux/mmc/sdio_ids.h | 2 ++ 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 8f279e7bd049..ad99470ae92d 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -146,10 +146,10 @@ config LIBERTAS_CS A driver for Marvell Libertas 8385 CompactFlash devices. config LIBERTAS_SDIO - tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards" + tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" depends on LIBERTAS && MMC ---help--- - A driver for Marvell Libertas 8385 and 8686 SDIO devices. + A driver for Marvell Libertas 8385/8686/8688 SDIO devices. config LIBERTAS_SPI tristate "Marvell Libertas 8686 SPI 802.11b/g cards" diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 76f4c653d641..55864c10f9f1 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -48,8 +48,11 @@ static char *lbs_fw_name = NULL; module_param_named(fw_name, lbs_fw_name, charp, 0644); static const struct sdio_device_id if_sdio_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, - { /* end: all zeroes */ }, + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, + SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, + SDIO_DEVICE_ID_MARVELL_8688WLAN) }, + { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, if_sdio_ids); @@ -73,6 +76,12 @@ static struct if_sdio_model if_sdio_models[] = { .helper = "sd8686_helper.bin", .firmware = "sd8686.bin", }, + { + /* 8688 */ + .model = 0x10, + .helper = "sd8688_helper.bin", + .firmware = "sd8688.bin", + }, }; struct if_sdio_packet { @@ -488,7 +497,7 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) ret = 0; release: - sdio_set_block_size(card->func, 0); + sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); sdio_release_host(card->func); kfree(chunk_buffer); release_fw: @@ -624,7 +633,7 @@ static int if_sdio_prog_real(struct if_sdio_card *card) ret = 0; release: - sdio_set_block_size(card->func, 0); + sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); sdio_release_host(card->func); kfree(chunk_buffer); release_fw: diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 533bdfbf5d2a..37ada2c29aa9 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h @@ -42,4 +42,6 @@ #define IF_SDIO_EVENT 0x80fc +#define IF_SDIO_BLOCK_SIZE 256 + #endif diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 820c22d9220f..bd845d09f174 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -25,7 +25,6 @@ struct rfc1042hdr { } __attribute__ ((packed)); struct rxpackethdr { - struct rxpd rx_pd; struct eth803hdr eth803_hdr; struct rfc1042hdr rfc1042_hdr; } __attribute__ ((packed)); @@ -158,8 +157,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) if (priv->monitormode) return process_rxed_802_11_packet(priv, skb); - p_rx_pkt = (struct rxpackethdr *) skb->data; - p_rx_pd = &p_rx_pkt->rx_pd; + p_rx_pd = (struct rxpd *) skb->data; + p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + + le32_to_cpu(p_rx_pd->pkt_ptr)); if (priv->mesh_dev) { if (priv->mesh_fw_ver == MESH_FW_OLD) { if (p_rx_pd->rx_control & RxPD_MESH_FRAME) @@ -181,8 +181,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) goto done; } - lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", - skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); + lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n", + skb->len, le32_to_cpu(p_rx_pd->pkt_ptr), + skb->len - le32_to_cpu(p_rx_pd->pkt_ptr)); lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, sizeof(p_rx_pkt->eth803_hdr.dest_addr)); @@ -216,14 +217,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header * that was removed */ - hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt; + hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; } else { lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", (u8 *) & p_rx_pkt->rfc1042_hdr, sizeof(p_rx_pkt->rfc1042_hdr)); /* Chop off the rxpd */ - hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt; + hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd; } /* Chop off the leading header bytes so the skb points to the start of diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index ea1bf5ba092f..c7211ab6dd4b 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -25,5 +25,7 @@ #define SDIO_VENDOR_ID_MARVELL 0x02df #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103 +#define SDIO_DEVICE_ID_MARVELL_8688WLAN 0x9104 +#define SDIO_DEVICE_ID_MARVELL_8688BT 0x9105 #endif -- cgit v1.2.3 From 4499b23933b44bf9e56d1a29b51d9a62941f9fa4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Apr 2009 02:55:34 +0200 Subject: mac80211: re-upload keys only after telling driver about association In the normal WPA or RSN case keys are only configured after associating, so we should do that in that order when resuming as well. It shouldn't really matter since we do not send any data at either point, but iwlwifi prefers it this way and it does seem more natural. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/pm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 027302326498..2b4c95cd9daf 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -127,11 +127,6 @@ int __ieee80211_resume(struct ieee80211_hw *hw) rcu_read_unlock(); - /* add back keys */ - list_for_each_entry(sdata, &local->interfaces, list) - if (netif_running(sdata->dev)) - ieee80211_enable_keys(sdata); - /* setup RTS threshold */ if (local->ops->set_rts_threshold) local->ops->set_rts_threshold(hw, local->rts_threshold); @@ -172,6 +167,11 @@ int __ieee80211_resume(struct ieee80211_hw *hw) } } + /* add back keys */ + list_for_each_entry(sdata, &local->interfaces, list) + if (netif_running(sdata->dev)) + ieee80211_enable_keys(sdata); + ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); -- cgit v1.2.3 From de2b3e864aa908e613dd9912def88af7877d85f3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 Apr 2009 12:54:41 +0200 Subject: mac80211: update injection documentation We don't currently support antenna or rate setting, so remove that. Also update the link -- the current one is dead and the wiki can be kept updated easier. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/networking/mac80211-injection.txt | 28 ++++++------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt index 84906ef3ed6e..b30e81ad5307 100644 --- a/Documentation/networking/mac80211-injection.txt +++ b/Documentation/networking/mac80211-injection.txt @@ -12,38 +12,22 @@ following format: The radiotap format is discussed in ./Documentation/networking/radiotap-headers.txt. -Despite 13 radiotap argument types are currently defined, most only make sense +Despite many radiotap parameters being currently defined, most only make sense to appear on received packets. The following information is parsed from the radiotap headers and used to control injection: - * IEEE80211_RADIOTAP_RATE - - rate in 500kbps units, automatic if invalid or not present - - - * IEEE80211_RADIOTAP_ANTENNA - - antenna to use, automatic if not present - - - * IEEE80211_RADIOTAP_DBM_TX_POWER - - transmit power in dBm, automatic if not present - - * IEEE80211_RADIOTAP_FLAGS IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the - current fragmentation threshold. Note that - this flag is only reliable when software - fragmentation is enabled) + current fragmentation threshold. + The injection code can also skip all other currently defined radiotap fields facilitating replay of captured radiotap headers directly. -Here is an example valid radiotap header defining these three parameters +Here is an example valid radiotap header defining some parameters 0x00, 0x00, // <-- radiotap version 0x0b, 0x00, // <- radiotap header length @@ -72,8 +56,8 @@ interface), along the following lines: ... r = pcap_inject(ppcap, u8aSendBuffer, nLength); -You can also find sources for a complete inject test applet here: +You can also find a link to a complete inject application here: -http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer +http://wireless.kernel.org/en/users/Documentation/packetspammer Andy Green -- cgit v1.2.3 From 5bbe233b9bafabc08a5404d54b9fa086e8390fc7 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:35 -0700 Subject: iwl3945: use iwl_bss_info_changed 3945 can use iwl_bss_info_changed. A new lib op is created for post_assoicate to distinguish between 3945 and iwlwifi's post_associate operations. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 50 ++++++++++ drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 138 +--------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 136 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 7 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 116 ++--------------------- 8 files changed, 204 insertions(+), 247 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 2399328e8de7..519e8922d9f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1964,6 +1964,50 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) return 0; } +static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) +{ + int rc = 0; + struct iwl_rx_packet *res = NULL; + struct iwl3945_rxon_assoc_cmd rxon_assoc; + struct iwl_host_cmd cmd = { + .id = REPLY_RXON_ASSOC, + .len = sizeof(rxon_assoc), + .meta.flags = CMD_WANT_SKB, + .data = &rxon_assoc, + }; + const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; + const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; + + if ((rxon1->flags == rxon2->flags) && + (rxon1->filter_flags == rxon2->filter_flags) && + (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && + (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { + IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); + return 0; + } + + rxon_assoc.flags = priv->staging_rxon.flags; + rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.reserved = 0; + + rc = iwl_send_cmd_sync(priv, &cmd); + if (rc) + return rc; + + res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; + if (res->hdr.flags & IWL_CMD_FAILED_MSK) { + IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); + rc = -EIO; + } + + priv->alloc_rxb_skb--; + dev_kfree_skb_any(cmd.meta.u.skb); + + return rc; +} + /* will add 3945 channel switch cmd handling later */ int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) { @@ -2729,6 +2773,10 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) return 0; } +static struct iwl_hcmd_ops iwl3945_hcmd = { + .rxon_assoc = iwl3945_send_rxon_assoc, +}; + static struct iwl_lib_ops iwl3945_lib = { .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, .txq_free_tfd = iwl3945_hw_txq_free_tfd, @@ -2758,6 +2806,7 @@ static struct iwl_lib_ops iwl3945_lib = { }, .send_tx_power = iwl3945_send_tx_power, .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, + .post_associate = iwl3945_post_associate, }; static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { @@ -2767,6 +2816,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { static struct iwl_ops iwl3945_ops = { .lib = &iwl3945_lib, + .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 29bc0d2656bc..13b191f155ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -276,7 +276,7 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); - +extern void iwl3945_post_associate(struct iwl_priv *priv); /** * iwl3945_hw_find_station - Find station id for a given BSSID * @bssid: MAC address of station ID to find diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 847a6220c5e6..37544afbebe6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2324,6 +2324,7 @@ static struct iwl_lib_ops iwl4965_lib = { .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl_update_chain_flags, .temperature = iwl4965_temperature_calib, + .post_associate = iwl_post_associate, }; static struct iwl_ops iwl4965_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e5ca2511a81a..837dbad80e5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1527,6 +1527,7 @@ struct iwl_lib_ops iwl5000_lib = { .calib_version = iwl5000_eeprom_calib_version, .query_addr = iwl5000_eeprom_query_addr, }, + .post_associate = iwl_post_associate, }; struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1f5ee55778f1..d14146fa751f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -531,76 +531,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv, * ******************************************************************************/ -static void iwl_ht_conf(struct iwl_priv *priv, - struct ieee80211_bss_conf *bss_conf) -{ - struct ieee80211_sta_ht_cap *ht_conf; - struct iwl_ht_info *iwl_conf = &priv->current_ht_config; - struct ieee80211_sta *sta; - - IWL_DEBUG_MAC80211(priv, "enter: \n"); - - if (!iwl_conf->is_ht) - return; - - - /* - * It is totally wrong to base global information on something - * that is valid only when associated, alas, this driver works - * that way and I don't know how to fix it. - */ - - rcu_read_lock(); - sta = ieee80211_find_sta(priv->hw, priv->bssid); - if (!sta) { - rcu_read_unlock(); - return; - } - ht_conf = &sta->ht_cap; - - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) - iwl_conf->sgf |= HT_SHORT_GI_20MHZ; - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) - iwl_conf->sgf |= HT_SHORT_GI_40MHZ; - - iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); - iwl_conf->max_amsdu_size = - !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); - - iwl_conf->supported_chan_width = - !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); - - /* - * XXX: The HT configuration needs to be moved into iwl_mac_config() - * to be done there correctly. - */ - - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - if (conf_is_ht40_minus(&priv->hw->conf)) - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - else if (conf_is_ht40_plus(&priv->hw->conf)) - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - - /* If no above or below channel supplied disable FAT channel */ - if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && - iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) - iwl_conf->supported_chan_width = 0; - - iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); - - memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); - - iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; - iwl_conf->ht_protection = - bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - iwl_conf->non_GF_STA_present = - !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - - rcu_read_unlock(); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - #define MAX_UCODE_BEACON_INTERVAL 4096 static u16 iwl_adjust_beacon_interval(u16 beacon_val) @@ -1911,7 +1841,7 @@ static void iwl_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl_post_associate(struct iwl_priv *priv) +void iwl_post_associate(struct iwl_priv *priv) { struct ieee80211_conf *conf = NULL; int ret = 0; @@ -2482,70 +2412,6 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, } -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) -static void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - } - - if (changes & BSS_CHANGED_HT) { - iwl_ht_conf(priv, bss_conf); - iwl_set_rxon_chain(priv); - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - /* This should never happen as this function should - * never be called from interrupt context. */ - if (WARN_ON_ONCE(in_interrupt())) - return; - if (bss_conf->assoc) { - priv->assoc_id = bss_conf->aid; - priv->beacon_int = bss_conf->beacon_int; - priv->power_data.dtim_period = bss_conf->dtim_period; - priv->timestamp = bss_conf->timestamp; - priv->assoc_capability = bss_conf->assoc_capability; - - /* we have just associated, don't start scan too early - * leave time for EAPOL exchange to complete - */ - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - mutex_lock(&priv->mutex); - iwl_post_associate(priv); - mutex_unlock(&priv->mutex); - } else { - priv->assoc_id = 0; - IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); - } - } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); - iwl_send_rxon_assoc(priv); - } - -} - static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key) @@ -2825,7 +2691,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) iwl_reset_qos(priv); - iwl_post_associate(priv); + priv->cfg->ops->lib->post_associate(priv); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 84ac1cec6f5b..15691829e023 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2157,6 +2157,142 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, return 0; } EXPORT_SYMBOL(iwl_mac_conf_tx); + +static void iwl_ht_conf(struct iwl_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_sta_ht_cap *ht_conf; + struct iwl_ht_info *iwl_conf = &priv->current_ht_config; + struct ieee80211_sta *sta; + + IWL_DEBUG_MAC80211(priv, "enter: \n"); + + if (!iwl_conf->is_ht) + return; + + + /* + * It is totally wrong to base global information on something + * that is valid only when associated, alas, this driver works + * that way and I don't know how to fix it. + */ + + rcu_read_lock(); + sta = ieee80211_find_sta(priv->hw, priv->bssid); + if (!sta) { + rcu_read_unlock(); + return; + } + ht_conf = &sta->ht_cap; + + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) + iwl_conf->sgf |= HT_SHORT_GI_20MHZ; + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) + iwl_conf->sgf |= HT_SHORT_GI_40MHZ; + + iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); + iwl_conf->max_amsdu_size = + !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); + + iwl_conf->supported_chan_width = + !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); + + /* + * XXX: The HT configuration needs to be moved into iwl_mac_config() + * to be done there correctly. + */ + + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + if (conf_is_ht40_minus(&priv->hw->conf)) + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; + else if (conf_is_ht40_plus(&priv->hw->conf)) + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + + /* If no above or below channel supplied disable FAT channel */ + if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && + iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) + iwl_conf->supported_chan_width = 0; + + iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); + + memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); + + iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; + iwl_conf->ht_protection = + bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; + iwl_conf->non_GF_STA_present = + !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + + rcu_read_unlock(); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} + +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) +void iwl_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct iwl_priv *priv = hw->priv; + + IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); + + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); + if (bss_conf->use_short_preamble) + priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + } + + if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) + priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; + else + priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + } + + if (changes & BSS_CHANGED_HT) { + iwl_ht_conf(priv, bss_conf); + iwl_set_rxon_chain(priv); + } + + if (changes & BSS_CHANGED_ASSOC) { + IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); + /* This should never happen as this function should + * never be called from interrupt context. */ + if (WARN_ON_ONCE(in_interrupt())) + return; + if (bss_conf->assoc) { + priv->assoc_id = bss_conf->aid; + priv->beacon_int = bss_conf->beacon_int; + priv->power_data.dtim_period = bss_conf->dtim_period; + priv->timestamp = bss_conf->timestamp; + priv->assoc_capability = bss_conf->assoc_capability; + + /* we have just associated, don't start scan too early + * leave time for EAPOL exchange to complete + */ + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + mutex_lock(&priv->mutex); + priv->cfg->ops->lib->post_associate(priv); + mutex_unlock(&priv->mutex); + } else { + priv->assoc_id = 0; + IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); + } + } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { + IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); + iwl_send_rxon_assoc(priv); + } + +} +EXPORT_SYMBOL(iwl_bss_info_changed); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d56edcd97aa0..4ad8465ae5fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -149,6 +149,8 @@ struct iwl_lib_ops { int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); void (*temperature) (struct iwl_priv *priv); + void (*post_associate) (struct iwl_priv *priv); + /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; }; @@ -251,6 +253,11 @@ int iwl_setup_mac(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); int iwl_init_drv(struct iwl_priv *priv); void iwl_uninit_drv(struct iwl_priv *priv); +void iwl_post_associate(struct iwl_priv *priv); +void iwl_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ed31030c7643..6f44abc2dce0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -233,50 +233,6 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag } -static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) -{ - int rc = 0; - struct iwl_rx_packet *res = NULL; - struct iwl3945_rxon_assoc_cmd rxon_assoc; - struct iwl_host_cmd cmd = { - .id = REPLY_RXON_ASSOC, - .len = sizeof(rxon_assoc), - .meta.flags = CMD_WANT_SKB, - .data = &rxon_assoc, - }; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved = 0; - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); - rc = -EIO; - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.meta.u.skb); - - return rc; -} - /** * iwl3945_get_antenna_flags - Get antenna flags for RXON command * @priv: eeprom and antenna fields are used to determine antenna flags @@ -352,7 +308,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * iwl3945_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ if (!iwl_full_rxon_required(priv)) { - rc = iwl3945_send_rxon_assoc(priv); + rc = iwl_send_rxon_assoc(priv); if (rc) { IWL_ERR(priv, "Error setting RXON_ASSOC " "configuration (%d).\n", rc); @@ -3450,9 +3406,11 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } +static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); + #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl3945_post_associate(struct iwl_priv *priv) +void iwl3945_post_associate(struct iwl_priv *priv) { int rc = 0; struct ieee80211_conf *conf = NULL; @@ -3542,8 +3500,6 @@ static void iwl3945_post_associate(struct iwl_priv *priv) priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; } -static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); - /***************************************************************************** * * mac80211 entry point functions @@ -3982,66 +3938,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); } -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) - -static void iwl3945_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", - bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - /* This should never happen as this function should - * never be called from interrupt context. */ - if (WARN_ON_ONCE(in_interrupt())) - return; - if (bss_conf->assoc) { - priv->assoc_id = bss_conf->aid; - priv->beacon_int = bss_conf->beacon_int; - priv->timestamp = bss_conf->timestamp; - priv->assoc_capability = bss_conf->assoc_capability; - priv->power_data.dtim_period = bss_conf->dtim_period; - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - mutex_lock(&priv->mutex); - iwl3945_post_associate(priv); - mutex_unlock(&priv->mutex); - } else { - priv->assoc_id = 0; - IWL_DEBUG_MAC80211(priv, - "DISASSOC %d\n", bss_conf->assoc); - } - } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211(priv, - "Associated Changes %d\n", changes); - iwl3945_send_rxon_assoc(priv); - } - -} - static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4227,7 +4123,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk iwl_reset_qos(priv); - iwl3945_post_associate(priv); + priv->cfg->ops->lib->post_associate(priv); return 0; @@ -4765,7 +4661,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .get_tx_stats = iwl3945_mac_get_tx_stats, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl3945_mac_reset_tsf, - .bss_info_changed = iwl3945_bss_info_changed, + .bss_info_changed = iwl_bss_info_changed, .hw_scan = iwl_mac_hw_scan }; -- cgit v1.2.3 From 9944b938f23fdd1ce2f5da190f771f176bb51eef Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:36 -0700 Subject: iwl3945: use iwl_mac_beacon_update 3945 can use iwl_mac_beacon_update. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 43 ------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 41 ++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 49 ++--------------------------- 4 files changed, 44 insertions(+), 90 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d14146fa751f..124a477ebd99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1443,10 +1443,6 @@ static int iwl_read_ucode(struct iwl_priv *priv) return ret; } -/* temporary */ -static int iwl_mac_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *skb); - /** * iwl_alive_start - called after REPLY_ALIVE notification received * from protocol/runtime uCode (initialization uCode's @@ -2657,45 +2653,6 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "leave\n"); } -static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - priv->assoc_id = 0; - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - priv->cfg->ops->lib->post_associate(priv); - - - return 0; -} /***************************************************************************** * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 15691829e023..eaeeb4dae0ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2293,6 +2293,47 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_bss_info_changed); +int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + __le64 timestamp; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); + return -EIO; + } + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = skb; + + priv->assoc_id = 0; + timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + priv->timestamp = le64_to_cpu(timestamp); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_reset_qos(priv); + + priv->cfg->ops->lib->post_associate(priv); + + + return 0; +} +EXPORT_SYMBOL(iwl_mac_beacon_update); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ad8465ae5fb..04473858b9b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -258,6 +258,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); +int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6f44abc2dce0..857393a69016 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2792,11 +2792,6 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv) queue_work(priv->workqueue, &priv->restart); } - -/* temporary */ -static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, - struct sk_buff *skb); - /** * iwl3945_alive_start - called after REPLY_ALIVE notification received * from protocol/runtime uCode (initialization uCode's @@ -2904,7 +2899,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (beacon) - iwl3945_mac_beacon_update(priv->hw, beacon); + iwl_mac_beacon_update(priv->hw, beacon); } return; @@ -3837,7 +3832,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (!beacon) return -ENOMEM; mutex_lock(&priv->mutex); - rc = iwl3945_mac_beacon_update(hw, beacon); + rc = iwl_mac_beacon_update(hw, beacon); mutex_unlock(&priv->mutex); if (rc) return rc; @@ -4089,46 +4084,6 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) } -static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - priv->assoc_id = 0; - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - priv->cfg->ops->lib->post_associate(priv); - - - return 0; -} - /***************************************************************************** * * sysfs attributes -- cgit v1.2.3 From e0158e61108bdadd70865c2149dc829a5c84dd73 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:37 -0700 Subject: iwlwifi: add commit_rxon lib Patch adds commit_rxon lib operation to iwlwifi and iwl3945 drivers. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 145 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-3945.h | 1 + drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 32 ++--- drivers/net/wireless/iwlwifi/iwl-core.h | 6 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 174 +++------------------------- 7 files changed, 185 insertions(+), 175 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 519e8922d9f4..9a0fb80023ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2008,6 +2008,150 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) return rc; } +/** + * iwl3945_commit_rxon - commit staging_rxon to hardware + * + * The RXON command in staging_rxon is committed to the hardware and + * the active_rxon structure is updated with the new data. This + * function correctly transitions out of the RXON_ASSOC_MSK state if + * a HW tune is required based on the RXON structure changes. + */ +static int iwl3945_commit_rxon(struct iwl_priv *priv) +{ + /* cast away the const for active_rxon in this function */ + struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; + struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; + int rc = 0; + bool new_assoc = + !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); + + if (!iwl_is_alive(priv)) + return -1; + + /* always get timestamp with Rx frame */ + staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; + + /* select antenna */ + staging_rxon->flags &= + ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); + staging_rxon->flags |= iwl3945_get_antenna_flags(priv); + + rc = iwl_check_rxon_cmd(priv); + if (rc) { + IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); + return -EINVAL; + } + + /* If we don't need to send a full RXON, we can use + * iwl3945_rxon_assoc_cmd which is used to reconfigure filter + * and other flags for the current radio configuration. */ + if (!iwl_full_rxon_required(priv)) { + rc = iwl_send_rxon_assoc(priv); + if (rc) { + IWL_ERR(priv, "Error setting RXON_ASSOC " + "configuration (%d).\n", rc); + return rc; + } + + memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); + + return 0; + } + + /* If we are currently associated and the new config requires + * an RXON_ASSOC and the new config wants the associated mask enabled, + * we must clear the associated from the active configuration + * before we apply the new config */ + if (iwl_is_associated(priv) && new_assoc) { + IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); + active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + + /* + * reserved4 and 5 could have been filled by the iwlcore code. + * Let's clear them before pushing to the 3945. + */ + active_rxon->reserved4 = 0; + active_rxon->reserved5 = 0; + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, + sizeof(struct iwl3945_rxon_cmd), + &priv->active_rxon); + + /* If the mask clearing failed then we set + * active_rxon back to what it was previously */ + if (rc) { + active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; + IWL_ERR(priv, "Error clearing ASSOC_MSK on current " + "configuration (%d).\n", rc); + return rc; + } + } + + IWL_DEBUG_INFO(priv, "Sending RXON\n" + "* with%s RXON_FILTER_ASSOC_MSK\n" + "* channel = %d\n" + "* bssid = %pM\n", + (new_assoc ? "" : "out"), + le16_to_cpu(staging_rxon->channel), + staging_rxon->bssid_addr); + + /* + * reserved4 and 5 could have been filled by the iwlcore code. + * Let's clear them before pushing to the 3945. + */ + staging_rxon->reserved4 = 0; + staging_rxon->reserved5 = 0; + + iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); + + /* Apply the new configuration */ + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, + sizeof(struct iwl3945_rxon_cmd), + staging_rxon); + if (rc) { + IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); + return rc; + } + + memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); + + iwl3945_clear_stations_table(priv); + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ + rc = priv->cfg->ops->lib->send_tx_power(priv); + if (rc) { + IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); + return rc; + } + + /* Add the broadcast address so we can send broadcast frames */ + if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == + IWL_INVALID_STATION) { + IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); + return -EIO; + } + + /* If we have set the ASSOC_MSK and we are in BSS mode then + * add the IWL_AP_ID to the station rate table */ + if (iwl_is_associated(priv) && + (priv->iw_mode == NL80211_IFTYPE_STATION)) + if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, + 1, 0) + == IWL_INVALID_STATION) { + IWL_ERR(priv, "Error adding AP address for transmit\n"); + return -EIO; + } + + /* Init the hardware's rate fallback order based on the band */ + rc = iwl3945_init_hw_rate_table(priv); + if (rc) { + IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); + return -EIO; + } + + return 0; +} + /* will add 3945 channel switch cmd handling later */ int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) { @@ -2775,6 +2919,7 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl3945_hcmd = { .rxon_assoc = iwl3945_send_rxon_assoc, + .commit_rxon = iwl3945_commit_rxon, }; static struct iwl_lib_ops iwl3945_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 13b191f155ad..8e3e8161526a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -207,6 +207,7 @@ extern int iwl3945_send_add_station(struct iwl_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags); extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid, int is_ap, u8 flags); +extern void iwl3945_clear_stations_table(struct iwl_priv *priv); extern int iwl3945_power_init_handle(struct iwl_priv *priv); extern int iwl3945_eeprom_init(struct iwl_priv *priv); extern int iwl3945_calc_db_from_ratio(int sig_ratio); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 37544afbebe6..053e42091124 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2271,6 +2271,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, + .commit_rxon = iwl_commit_rxon, }; static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 837dbad80e5e..410cba221610 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1474,6 +1474,7 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, + .commit_rxon = iwl_commit_rxon, }; struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 124a477ebd99..50ef649b1c97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -102,7 +102,7 @@ MODULE_ALIAS("iwl4965"); * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -static int iwl_commit_rxon(struct iwl_priv *priv) +int iwl_commit_rxon(struct iwl_priv *priv) { /* cast away the const for active_rxon in this function */ struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; @@ -247,7 +247,7 @@ void iwl_update_chain_flags(struct iwl_priv *priv) { iwl_set_rxon_chain(priv); - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } static void iwl_clear_free_frames(struct iwl_priv *priv) @@ -606,7 +606,7 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode) return -EAGAIN; } - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); return 0; } @@ -1000,7 +1000,7 @@ static void iwl_error_recovery(struct iwl_priv *priv) memcpy(&priv->staging_rxon, &priv->recovery_rxon, sizeof(priv->staging_rxon)); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl_rxon_add_station(priv, priv->bssid, 1); @@ -1509,7 +1509,7 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); /* Configure the adapter for unassociated operation */ - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); /* At this point, the NIC is initialized and operational */ iwl_rf_kill_ct_config(priv); @@ -1865,7 +1865,7 @@ void iwl_post_associate(struct iwl_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl_setup_rxon_timing(priv); ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, @@ -1900,7 +1900,7 @@ void iwl_post_associate(struct iwl_priv *priv) } - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: @@ -2211,7 +2211,7 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if (memcmp(&priv->active_rxon, &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); else IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); @@ -2235,7 +2235,7 @@ static void iwl_config_ap(struct iwl_priv *priv) /* RXON - unassoc (to set timing command) */ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); /* RXON Timing */ iwl_setup_rxon_timing(priv); @@ -2271,7 +2271,7 @@ static void iwl_config_ap(struct iwl_priv *priv) } /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); spin_lock_irqsave(&priv->lock, flags); iwl_activate_qos(priv, 1); spin_unlock_irqrestore(&priv->lock, flags); @@ -2365,7 +2365,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, if (priv->iw_mode == NL80211_IFTYPE_AP) iwl_config_ap(priv); else { - rc = iwl_commit_rxon(priv); + rc = iwlcore_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl_rxon_add_station( priv, priv->active_rxon.bssid_addr, 1); @@ -2374,7 +2374,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, } else { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } done: @@ -2396,7 +2396,7 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw, if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } if (priv->vif == conf->vif) { priv->vif = NULL; @@ -2623,7 +2623,7 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } iwl_power_update_mode(priv, 0); @@ -2803,7 +2803,7 @@ static ssize_t store_flags(struct device *d, else { IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); @@ -2844,7 +2844,7 @@ static ssize_t store_filter_flags(struct device *d, "0x%04X\n", filter_flags); priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); - iwl_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 04473858b9b5..c7e05953cb75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -85,6 +85,7 @@ struct iwl_cmd; struct iwl_hcmd_ops { int (*rxon_assoc)(struct iwl_priv *priv); + int (*commit_rxon)(struct iwl_priv *priv); }; struct iwl_hcmd_utils_ops { u16 (*get_hcmd_size)(u8 cmd_id, u16 len); @@ -259,6 +260,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changes); int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); +int iwl_commit_rxon(struct iwl_priv *priv); /***************************************************** * RX handlers. @@ -541,6 +543,10 @@ static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) { return priv->cfg->ops->hcmd->rxon_assoc(priv); } +static inline int iwlcore_commit_rxon(struct iwl_priv *priv) +{ + return priv->cfg->ops->hcmd->commit_rxon(priv); +} static inline const struct ieee80211_supported_band *iwl_get_hw_mode( struct iwl_priv *priv, enum ieee80211_band band) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 857393a69016..e96a726dc5c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -149,7 +149,7 @@ out: * * NOTE: This does not clear or otherwise alter the device's station table. */ -static void iwl3945_clear_stations_table(struct iwl_priv *priv) +void iwl3945_clear_stations_table(struct iwl_priv *priv) { unsigned long flags; @@ -270,150 +270,6 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) return 0; /* "diversity" is default if error */ } -/** - * iwl3945_commit_rxon - commit staging_rxon to hardware - * - * The RXON command in staging_rxon is committed to the hardware and - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. - */ -static int iwl3945_commit_rxon(struct iwl_priv *priv) -{ - /* cast away the const for active_rxon in this function */ - struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; - struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; - int rc = 0; - bool new_assoc = - !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); - - if (!iwl_is_alive(priv)) - return -1; - - /* always get timestamp with Rx frame */ - staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; - - /* select antenna */ - staging_rxon->flags &= - ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); - staging_rxon->flags |= iwl3945_get_antenna_flags(priv); - - rc = iwl_check_rxon_cmd(priv); - if (rc) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); - return -EINVAL; - } - - /* If we don't need to send a full RXON, we can use - * iwl3945_rxon_assoc_cmd which is used to reconfigure filter - * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv)) { - rc = iwl_send_rxon_assoc(priv); - if (rc) { - IWL_ERR(priv, "Error setting RXON_ASSOC " - "configuration (%d).\n", rc); - return rc; - } - - memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - - return 0; - } - - /* If we are currently associated and the new config requires - * an RXON_ASSOC and the new config wants the associated mask enabled, - * we must clear the associated from the active configuration - * before we apply the new config */ - if (iwl_is_associated(priv) && new_assoc) { - IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - - /* - * reserved4 and 5 could have been filled by the iwlcore code. - * Let's clear them before pushing to the 3945. - */ - active_rxon->reserved4 = 0; - active_rxon->reserved5 = 0; - rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), - &priv->active_rxon); - - /* If the mask clearing failed then we set - * active_rxon back to what it was previously */ - if (rc) { - active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERR(priv, "Error clearing ASSOC_MSK on current " - "configuration (%d).\n", rc); - return rc; - } - } - - IWL_DEBUG_INFO(priv, "Sending RXON\n" - "* with%s RXON_FILTER_ASSOC_MSK\n" - "* channel = %d\n" - "* bssid = %pM\n", - (new_assoc ? "" : "out"), - le16_to_cpu(staging_rxon->channel), - staging_rxon->bssid_addr); - - /* - * reserved4 and 5 could have been filled by the iwlcore code. - * Let's clear them before pushing to the 3945. - */ - staging_rxon->reserved4 = 0; - staging_rxon->reserved5 = 0; - - iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); - - /* Apply the new configuration */ - rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), - staging_rxon); - if (rc) { - IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); - return rc; - } - - memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - - iwl3945_clear_stations_table(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - rc = priv->cfg->ops->lib->send_tx_power(priv); - if (rc) { - IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); - return rc; - } - - /* Add the broadcast address so we can send broadcast frames */ - if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == - IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); - return -EIO; - } - - /* If we have set the ASSOC_MSK and we are in BSS mode then - * add the IWL_AP_ID to the station rate table */ - if (iwl_is_associated(priv) && - (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, - 1, 0) - == IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding AP address for transmit\n"); - return -EIO; - } - - /* Init the hardware's rate fallback order based on the band */ - rc = iwl3945_init_hw_rate_table(priv); - if (rc) { - IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); - return -EIO; - } - - return 0; -} - static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) @@ -745,7 +601,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) return -EAGAIN; } - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); return 0; } @@ -2025,7 +1881,7 @@ static void iwl3945_error_recovery(struct iwl_priv *priv) memcpy(&priv->staging_rxon, &priv->recovery_rxon, sizeof(priv->staging_rxon)); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl3945_add_station(priv, priv->bssid, 1, 0); @@ -2881,7 +2737,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl_send_bt_config(priv); /* Configure the adapter for unassociated operation */ - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl3945_reg_txpower_periodic(priv); @@ -3430,7 +3286,7 @@ void iwl3945_post_associate(struct iwl_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); iwl3945_setup_rxon_timing(priv); @@ -3463,7 +3319,7 @@ void iwl3945_post_associate(struct iwl_priv *priv) } - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); switch (priv->iw_mode) { case NL80211_IFTYPE_STATION: @@ -3740,7 +3596,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) if (memcmp(&priv->active_rxon, &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); else IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n"); @@ -3764,7 +3620,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv) /* RXON - unassoc (to set timing command) */ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); /* RXON Timing */ memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -3800,7 +3656,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv) } /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); iwl3945_add_station(priv, iwl_bcast_addr, 0, 0); } iwl3945_send_beacon_cmd(priv); @@ -3891,7 +3747,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (priv->iw_mode == NL80211_IFTYPE_AP) iwl3945_config_ap(priv); else { - rc = iwl3945_commit_rxon(priv); + rc = iwlcore_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0); @@ -3900,7 +3756,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, } else { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } done: @@ -3922,7 +3778,7 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, if (iwl_is_ready_rf(priv)) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } if (priv->vif == conf->vif) { priv->vif = NULL; @@ -4065,7 +3921,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } /* Per mac80211.h: This is only used in IBSS mode... */ @@ -4191,7 +4047,7 @@ static ssize_t store_flags(struct device *d, IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", flags); priv->staging_rxon.flags = cpu_to_le32(flags); - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); @@ -4227,7 +4083,7 @@ static ssize_t store_filter_flags(struct device *d, "0x%04X\n", filter_flags); priv->staging_rxon.filter_flags = cpu_to_le32(filter_flags); - iwl3945_commit_rxon(priv); + iwlcore_commit_rxon(priv); } } mutex_unlock(&priv->mutex); -- cgit v1.2.3 From f45c271493c37d2d80177582191acc1a4e446297 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:38 -0700 Subject: iwl3945: delay mode setting Delay mode setting till uCode is ready. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e96a726dc5c9..0ad89fb90d05 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2758,6 +2758,9 @@ static void iwl3945_alive_start(struct iwl_priv *priv) iwl_mac_beacon_update(priv->hw, beacon); } + if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) + iwl3945_set_mode(priv, priv->iw_mode); + return; restart: @@ -3497,8 +3500,8 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } - if (iwl_is_ready(priv)) - iwl3945_set_mode(priv, conf->type); + if (iwl3945_set_mode(priv, conf->type) == -EAGAIN) + set_bit(STATUS_MODE_PENDING, &priv->status); mutex_unlock(&priv->mutex); -- cgit v1.2.3 From 79fa455a995057b6559fcd2a02e8b089b2e2e288 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:39 -0700 Subject: iwlwifi: add station management ops This patch adds declarations for station management ops to iwlwifi drivers. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 ++++++++++ drivers/net/wireless/iwlwifi/iwl-4965.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-5000.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 13 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 6 files changed, 40 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9a0fb80023ab..fb08295417f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2954,6 +2954,15 @@ static struct iwl_lib_ops iwl3945_lib = { .post_associate = iwl3945_post_associate, }; +static struct iwl_station_mgmt_ops iwl3945_station_mgmt = { + .add_station = iwl3945_add_station, +#if 0 + .remove_station = iwl3945_remove_station, +#endif + .find_station = iwl3945_hw_find_station, + .clear_station_table = iwl3945_clear_stations_table, +}; + static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .get_hcmd_size = iwl3945_get_hcmd_size, .build_addsta_hcmd = iwl3945_build_addsta_hcmd, @@ -2963,6 +2972,7 @@ static struct iwl_ops iwl3945_ops = { .lib = &iwl3945_lib, .hcmd = &iwl3945_hcmd, .utils = &iwl3945_hcmd_utils, + .smgmt = &iwl3945_station_mgmt, }; static struct iwl_cfg iwl3945_bg_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 053e42091124..e3d1e30e62b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2268,6 +2268,12 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->txpower_work); } +static struct iwl_station_mgmt_ops iwl4965_station_mgmt = { + .add_station_ht = iwl_add_station_flags, + .remove_station = iwl_remove_station, + .find_station = iwl_find_station, + .clear_station_table = iwl_clear_stations_table, +}; static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, @@ -2332,6 +2338,7 @@ static struct iwl_ops iwl4965_ops = { .lib = &iwl4965_lib, .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, + .smgmt = &iwl4965_station_mgmt, }; struct iwl_cfg iwl4965_agn_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 410cba221610..1344943a5f36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1472,6 +1472,13 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, return max_rssi - agc - IWL49_RSSI_OFFSET; } +struct iwl_station_mgmt_ops iwl5000_station_mgmt = { + .add_station_ht = iwl_add_station_flags, + .remove_station = iwl_remove_station, + .find_station = iwl_find_station, + .clear_station_table = iwl_clear_stations_table, +}; + struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, @@ -1535,6 +1542,7 @@ struct iwl_ops iwl5000_ops = { .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl5000_hcmd_utils, + .smgmt = &iwl5000_station_mgmt, }; struct iwl_mod_params iwl50_mod_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index edfa5e149f71..ee271d7f6120 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -72,6 +72,7 @@ static struct iwl_ops iwl6000_ops = { .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, .utils = &iwl6000_hcmd_utils, + .smgmt = &iwl5000_station_mgmt, }; struct iwl_cfg iwl6000_2ag_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c7e05953cb75..8b7f5bd2c8e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -83,10 +83,22 @@ struct iwl_cmd; #define IWL_SKU_A 0x2 #define IWL_SKU_N 0x8 +struct iwl_station_mgmt_ops { + u8 (*add_station_ht)(struct iwl_priv *priv, const u8 *addr, + int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); + u8 (*add_station)(struct iwl_priv *priv, const u8 *addr, + int is_ap, u8 flags); + int (*remove_station)(struct iwl_priv *priv, const u8 *addr, + int is_ap); + u8 (*find_station)(struct iwl_priv *priv, const u8 *addr); + void (*clear_station_table)(struct iwl_priv *priv); +}; + struct iwl_hcmd_ops { int (*rxon_assoc)(struct iwl_priv *priv); int (*commit_rxon)(struct iwl_priv *priv); }; + struct iwl_hcmd_utils_ops { u16 (*get_hcmd_size)(u8 cmd_id, u16 len); u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); @@ -160,6 +172,7 @@ struct iwl_ops { const struct iwl_lib_ops *lib; const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; + const struct iwl_station_mgmt_ops *smgmt; }; struct iwl_mod_params { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ec9a13846edd..59930f398f31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -70,6 +70,7 @@ extern struct iwl_ops iwl5000_ops; extern struct iwl_lib_ops iwl5000_lib; extern struct iwl_hcmd_ops iwl5000_hcmd; extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; +extern struct iwl_station_mgmt_ops iwl5000_station_mgmt; /* shared functions from iwl-5000.c */ extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); -- cgit v1.2.3 From 40ace5b385ccf8a4d4d096b353b7f1baac1d014b Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:40 -0700 Subject: iwl3945: replace station function with station ops Patch replaces station function used in driver by station management ops in 3945. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl3945-base.c | 29 +++++++++++++++-------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index fb08295417f0..7c0c7992b596 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2114,7 +2114,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ @@ -2125,7 +2125,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) } /* Add the broadcast address so we can send broadcast frames */ - if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) == + if (priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0) == IWL_INVALID_STATION) { IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); return -EIO; @@ -2135,8 +2135,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) * add the IWL_AP_ID to the station rate table */ if (iwl_is_associated(priv) && (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, - 1, 0) + if (priv->cfg->ops->smgmt->add_station(priv, + priv->active_rxon.bssid_addr, 1, 0) == IWL_INVALID_STATION) { IWL_ERR(priv, "Error adding AP address for transmit\n"); return -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0ad89fb90d05..f5f39cc28102 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -588,7 +588,7 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode) iwl_connection_init_rx_config(priv, mode); - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* don't commit rxon if rf-kill is on*/ if (!iwl_is_ready_rf(priv)) @@ -734,7 +734,7 @@ static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If we are an AP, then find the station, or use BCAST */ case NL80211_IFTYPE_AP: - sta_id = iwl3945_hw_find_station(priv, hdr->addr1); + sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; return priv->hw_params.bcast_sta_id; @@ -743,11 +743,12 @@ static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) * or create a new station table entry */ case NL80211_IFTYPE_ADHOC: { /* Create new station table entry */ - sta_id = iwl3945_hw_find_station(priv, hdr->addr1); + sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; - sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC); + sta_id = priv->cfg->ops->smgmt->add_station(priv, + hdr->addr1, 0, CMD_ASYNC); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -1883,7 +1884,7 @@ static void iwl3945_error_recovery(struct iwl_priv *priv) priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl3945_add_station(priv, priv->bssid, 1, 0); + priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0); spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); @@ -2678,7 +2679,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) goto restart; } - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); rc = iwl_grab_nic_access(priv); if (rc) { @@ -2783,7 +2784,7 @@ static void __iwl3945_down(struct iwl_priv *priv) set_bit(STATUS_EXIT_PENDING, &priv->status); iwl3945_led_unregister(priv); - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -2940,7 +2941,7 @@ static int __iwl3945_up(struct iwl_priv *priv) for (i = 0; i < MAX_HW_RESTARTS; i++) { - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* load bootstrap state machine, * load bootstrap program into processor's memory, @@ -3332,7 +3333,7 @@ void iwl3945_post_associate(struct iwl_priv *priv) case NL80211_IFTYPE_ADHOC: priv->assoc_id = 1; - iwl3945_add_station(priv, priv->bssid, 0, 0); + priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 0, 0); iwl3945_sync_sta(priv, IWL_STA_ID, (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, @@ -3660,7 +3661,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - iwl3945_add_station(priv, iwl_bcast_addr, 0, 0); + priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0); } iwl3945_send_beacon_cmd(priv); @@ -3752,7 +3753,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, else { rc = iwlcore_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) - iwl3945_add_station(priv, + priv->cfg->ops->smgmt->add_station(priv, priv->active_rxon.bssid_addr, 1, 0); } @@ -3814,7 +3815,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static_key = !iwl_is_associated(priv); if (!static_key) { - sta_id = iwl3945_hw_find_station(priv, addr); + sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); @@ -4497,7 +4498,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) mutex_init(&priv->mutex); /* Clear the driver's (not device's) station table */ - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); priv->data_retry_limit = -1; priv->ieee_channels = NULL; @@ -4860,7 +4861,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_hw_txq_ctx_free(priv); iwl3945_unset_hw_params(priv); - iwl3945_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); -- cgit v1.2.3 From e11bc0286a4ff8f4e5cdefbcce0878d29c03c630 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:41 -0700 Subject: iwlwifi: use station management ops Patch replaces station management functions with ops declared. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 16 ++++++++++------ drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 20 ++++++++++---------- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1344943a5f36..26f30a7ecb1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -678,7 +678,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv) goto restart; } - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); ret = priv->cfg->ops->lib->alive_notify(priv); if (ret) { IWL_WARN(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 7cdbcfe483f3..a99512807f63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2453,13 +2453,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) { - u8 sta_id = iwl_find_station(priv, hdr->addr1); + u8 sta_id = priv->cfg->ops->smgmt->find_station(priv, + hdr->addr1); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", hdr->addr1); - sta_id = iwl_add_station_flags(priv, hdr->addr1, - 0, CMD_ASYNC, NULL); + sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, + hdr->addr1, 0, + CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { lq_sta->lq.sta_id = sta_id; @@ -2526,15 +2528,17 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, lq_sta->ibss_sta_added = 0; if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, sta->addr); + u8 sta_id = priv->cfg->ops->smgmt->find_station(priv, + sta->addr); /* for IBSS the call are from tasklet */ IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - sta_id = iwl_add_station_flags(priv, sta->addr, - 0, CMD_ASYNC, NULL); + sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, + sta->addr, 0, + CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { lq_sta->lq.sta_id = sta_id; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 50ef649b1c97..565a441052eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -188,7 +188,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); } - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); if (!priv->error_recovering) priv->start_calib = 0; @@ -593,7 +593,7 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode) iwl_set_rxon_chain(priv); memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* dont commit rxon if rf-kill is on*/ if (!iwl_is_ready_rf(priv)) @@ -1471,7 +1471,7 @@ static void iwl_alive_start(struct iwl_priv *priv) goto restart; } - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); ret = priv->cfg->ops->lib->alive_notify(priv); if (ret) { IWL_WARN(priv, @@ -1557,7 +1557,7 @@ static void __iwl_down(struct iwl_priv *priv) iwl_leds_unregister(priv); - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -1708,7 +1708,7 @@ static int __iwl_up(struct iwl_priv *priv) for (i = 0; i < MAX_HW_RESTARTS; i++) { - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); /* load bootstrap state machine, * load bootstrap program into processor's memory, @@ -2439,7 +2439,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } addr = sta ? sta->addr : iwl_bcast_addr; - sta_id = iwl_find_station(priv, addr); + sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); @@ -3311,7 +3311,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_rx_queue_free(priv, &priv->rxq); iwl_hw_txq_ctx_free(priv); - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); iwl_eeprom_free(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eaeeb4dae0ed..0532d99b9085 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1368,7 +1368,7 @@ int iwl_init_drv(struct iwl_priv *priv) mutex_init(&priv->mutex); /* Clear the driver's (not device's) station table */ - iwl_clear_stations_table(priv); + priv->cfg->ops->smgmt->clear_station_table(priv); priv->data_retry_limit = -1; priv->ieee_channels = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5798fe49c771..5816368ffc40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -75,7 +75,7 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return IWL_AP_ID; } else { u8 *da = ieee80211_get_DA(hdr); - return iwl_find_station(priv, da); + return priv->cfg->ops->smgmt->find_station(priv, da); } } EXPORT_SYMBOL(iwl_get_ra_sta_id); @@ -300,7 +300,7 @@ EXPORT_SYMBOL(iwl_add_station_flags); static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) { unsigned long flags; - u8 sta_id = iwl_find_station(priv, addr); + u8 sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); BUG_ON(sta_id == IWL_INVALID_STATION); @@ -758,7 +758,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, int i; DECLARE_MAC_BUF(mac); - sta_id = iwl_find_station(priv, addr); + sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", addr); @@ -1019,7 +1019,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) rcu_read_unlock(); } - sta_id = iwl_add_station_flags(priv, addr, is_ap, + sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, addr, is_ap, 0, cur_ht_config); /* Set up default rate scaling table in device's station table */ @@ -1053,7 +1053,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If we are an AP, then find the station, or use BCAST */ case NL80211_IFTYPE_AP: - sta_id = iwl_find_station(priv, hdr->addr1); + sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; return priv->hw_params.bcast_sta_id; @@ -1061,12 +1061,12 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ case NL80211_IFTYPE_ADHOC: - sta_id = iwl_find_station(priv, hdr->addr1); + sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; /* Create new station table entry */ - sta_id = iwl_add_station_flags(priv, hdr->addr1, + sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, hdr->addr1, 0, CMD_ASYNC, NULL); if (sta_id != IWL_INVALID_STATION) @@ -1115,7 +1115,7 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, unsigned long flags; int sta_id; - sta_id = iwl_find_station(priv, addr); + sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) return -ENXIO; @@ -1137,7 +1137,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) unsigned long flags; int sta_id; - sta_id = iwl_find_station(priv, addr); + sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); return -ENXIO; @@ -1172,7 +1172,7 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) { /* FIXME: need locking over ps_status ??? */ - u8 sta_id = iwl_find_station(priv, addr); + u8 sta_id = priv->cfg->ops->smgmt->find_station(priv, addr); if (sta_id != IWL_INVALID_STATION) { u8 sta_awake = priv->stations[sta_id]. -- cgit v1.2.3 From 06fd3d86a426848dbd8db27b7257a4eb4be8cfae Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:42 -0700 Subject: iwl3945/iwlwifi: unify add_station function Patch unifies the add_station function for 3945 and iwlwifi drivers. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.h | 4 +--- drivers/net/wireless/iwlwifi/iwl-sta.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 ++++++------ 9 files changed, 17 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index af6b9d444778..f63a9c5ba262 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -719,7 +719,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n", hdr->addr1); sta_id = iwl3945_add_station(priv, - hdr->addr1, 0, CMD_ASYNC); + hdr->addr1, 0, CMD_ASYNC, NULL); } if (sta_id != IWL_INVALID_STATION) rs_sta->ibss_sta_added = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7c0c7992b596..a854feba82c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2125,7 +2125,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) } /* Add the broadcast address so we can send broadcast frames */ - if (priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0) == + if (priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL) == IWL_INVALID_STATION) { IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); return -EIO; @@ -2136,7 +2136,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) if (iwl_is_associated(priv) && (priv->iw_mode == NL80211_IFTYPE_STATION)) if (priv->cfg->ops->smgmt->add_station(priv, - priv->active_rxon.bssid_addr, 1, 0) + priv->active_rxon.bssid_addr, 1, 0, NULL) == IWL_INVALID_STATION) { IWL_ERR(priv, "Error adding AP address for transmit\n"); return -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 8e3e8161526a..88628b23efd9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -206,7 +206,7 @@ struct iwl3945_addsta_cmd; extern int iwl3945_send_add_station(struct iwl_priv *priv, struct iwl3945_addsta_cmd *sta, u8 flags); extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid, - int is_ap, u8 flags); + int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); extern void iwl3945_clear_stations_table(struct iwl_priv *priv); extern int iwl3945_power_init_handle(struct iwl_priv *priv); extern int iwl3945_eeprom_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e3d1e30e62b5..e98849edafd5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2269,7 +2269,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) } static struct iwl_station_mgmt_ops iwl4965_station_mgmt = { - .add_station_ht = iwl_add_station_flags, + .add_station = iwl_add_station_flags, .remove_station = iwl_remove_station, .find_station = iwl_find_station, .clear_station_table = iwl_clear_stations_table, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 26f30a7ecb1a..52ee77347328 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1473,7 +1473,7 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, } struct iwl_station_mgmt_ops iwl5000_station_mgmt = { - .add_station_ht = iwl_add_station_flags, + .add_station = iwl_add_station_flags, .remove_station = iwl_remove_station, .find_station = iwl_find_station, .clear_station_table = iwl_clear_stations_table, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a99512807f63..b1818a3d1e51 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2459,7 +2459,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", hdr->addr1); - sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, + sta_id = priv->cfg->ops->smgmt->add_station(priv, hdr->addr1, 0, CMD_ASYNC, NULL); } @@ -2536,7 +2536,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, + sta_id = priv->cfg->ops->smgmt->add_station(priv, sta->addr, 0, CMD_ASYNC, NULL); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8b7f5bd2c8e3..383590cd8b02 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -84,10 +84,8 @@ struct iwl_cmd; #define IWL_SKU_N 0x8 struct iwl_station_mgmt_ops { - u8 (*add_station_ht)(struct iwl_priv *priv, const u8 *addr, - int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); u8 (*add_station)(struct iwl_priv *priv, const u8 *addr, - int is_ap, u8 flags); + int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); int (*remove_station)(struct iwl_priv *priv, const u8 *addr, int is_ap); u8 (*find_station)(struct iwl_priv *priv, const u8 *addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5816368ffc40..b8f18c697888 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1019,7 +1019,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) rcu_read_unlock(); } - sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, addr, is_ap, + sta_id = priv->cfg->ops->smgmt->add_station(priv, addr, is_ap, 0, cur_ht_config); /* Set up default rate scaling table in device's station table */ @@ -1066,7 +1066,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return sta_id; /* Create new station table entry */ - sta_id = priv->cfg->ops->smgmt->add_station_ht(priv, hdr->addr1, + sta_id = priv->cfg->ops->smgmt->add_station(priv, hdr->addr1, 0, CMD_ASYNC, NULL); if (sta_id != IWL_INVALID_STATION) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f5f39cc28102..566914569104 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -164,7 +164,7 @@ void iwl3945_clear_stations_table(struct iwl_priv *priv) /** * iwl3945_add_station - Add station to station tables in driver and device */ -u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags) +u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info) { int i; int index = IWL_INVALID_STATION; @@ -748,7 +748,7 @@ static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return sta_id; sta_id = priv->cfg->ops->smgmt->add_station(priv, - hdr->addr1, 0, CMD_ASYNC); + hdr->addr1, 0, CMD_ASYNC, NULL); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -1884,7 +1884,7 @@ static void iwl3945_error_recovery(struct iwl_priv *priv) priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0); + priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0, NULL); spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id); @@ -3333,7 +3333,7 @@ void iwl3945_post_associate(struct iwl_priv *priv) case NL80211_IFTYPE_ADHOC: priv->assoc_id = 1; - priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 0, 0); + priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 0, 0, NULL); iwl3945_sync_sta(priv, IWL_STA_ID, (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, @@ -3661,7 +3661,7 @@ static void iwl3945_config_ap(struct iwl_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); - priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0); + priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL); } iwl3945_send_beacon_cmd(priv); @@ -3754,7 +3754,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, rc = iwlcore_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) priv->cfg->ops->smgmt->add_station(priv, - priv->active_rxon.bssid_addr, 1, 0); + priv->active_rxon.bssid_addr, 1, 0, NULL); } } else { -- cgit v1.2.3 From f5d3026683da45e00c49a24999ad0d256e4651d5 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:43 -0700 Subject: iwl3945: use iwl_get_sta_id from iwlwifi iwl3945 can now use iwl_get_sta_id. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 61 +---------------------------- 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 566914569104..7f35017d9df2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -712,65 +712,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, tx->next_frame_len = 0; } -/** - * iwl3945_get_sta_id - Find station's index within station table - */ -static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) -{ - int sta_id; - u16 fc = le16_to_cpu(hdr->frame_control); - - /* If this frame is broadcast or management, use broadcast station id */ - if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || - is_multicast_ether_addr(hdr->addr1)) - return priv->hw_params.bcast_sta_id; - - switch (priv->iw_mode) { - - /* If we are a client station in a BSS network, use the special - * AP station entry (that's the only station we communicate with) */ - case NL80211_IFTYPE_STATION: - return IWL_AP_ID; - - /* If we are an AP, then find the station, or use BCAST */ - case NL80211_IFTYPE_AP: - sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - return priv->hw_params.bcast_sta_id; - - /* If this frame is going out to an IBSS network, find the station, - * or create a new station table entry */ - case NL80211_IFTYPE_ADHOC: { - /* Create new station table entry */ - sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - sta_id = priv->cfg->ops->smgmt->add_station(priv, - hdr->addr1, 0, CMD_ASYNC, NULL); - - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - IWL_DEBUG_DROP(priv, "Station %pM not in station map. " - "Defaulting to broadcast...\n", - hdr->addr1); - iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_params.bcast_sta_id; - } - /* If we are in monitor mode, use BCAST. This is required for - * packet injection. */ - case NL80211_IFTYPE_MONITOR: - return priv->hw_params.bcast_sta_id; - - default: - IWL_WARN(priv, "Unknown mode of operation: %d\n", - priv->iw_mode); - return priv->hw_params.bcast_sta_id; - } -} - /* * start REPLY_TX command process */ @@ -836,7 +777,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find (or create) index into station table for destination station */ - sta_id = iwl3945_get_sta_id(priv, hdr); + sta_id = iwl_get_sta_id(priv, hdr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); -- cgit v1.2.3 From 45823531662028a8cbd68906c20e887bb287c85e Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:44 -0700 Subject: iwlwifi: add set_rxon_chain op add set_rxon_chain op to iwlwifi cfg ops in preparation of future 3945 porting work. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 23 +++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 11 ++++++++--- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e98849edafd5..ab25e6ab59d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2278,6 +2278,7 @@ static struct iwl_station_mgmt_ops iwl4965_station_mgmt = { static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, + .set_rxon_chain = iwl_set_rxon_chain, }; static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 52ee77347328..cf622a14bfe2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1482,6 +1482,7 @@ struct iwl_station_mgmt_ops iwl5000_station_mgmt = { struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, .commit_rxon = iwl_commit_rxon, + .set_rxon_chain = iwl_set_rxon_chain, }; struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 565a441052eb..11e17923ad01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -246,7 +246,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) void iwl_update_chain_flags(struct iwl_priv *priv) { - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); iwlcore_commit_rxon(priv); } @@ -590,7 +591,10 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) static int iwl_set_mode(struct iwl_priv *priv, int mode) { iwl_connection_init_rx_config(priv, mode); - iwl_set_rxon_chain(priv); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); priv->cfg->ops->smgmt->clear_station_table(priv); @@ -1499,7 +1503,10 @@ static void iwl_alive_start(struct iwl_priv *priv) } else { /* Initialize our rx_config data */ iwl_connection_init_rx_config(priv, priv->iw_mode); - iwl_set_rxon_chain(priv); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); } @@ -1878,7 +1885,9 @@ void iwl_post_associate(struct iwl_priv *priv) iwl_set_rxon_ht(priv, &priv->current_ht_config); - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", @@ -2182,7 +2191,8 @@ static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) } /* call to ensure that 4965 rx_chain is set properly in monitor mode */ - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { if (conf->radio_enabled && @@ -2245,7 +2255,8 @@ static void iwl_config_ap(struct iwl_priv *priv) IWL_WARN(priv, "REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); /* FIXME: what should be the assoc_id for AP? */ priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0532d99b9085..cca37af3243f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -821,7 +821,8 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS); - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X " "rxon flags 0x%X operation mode :0x%X " @@ -1380,7 +1381,9 @@ int iwl_init_drv(struct iwl_priv *priv) priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; /* Choose which receivers/antennas to use */ - iwl_set_rxon_chain(priv); + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + iwl_init_scan_params(priv); iwl_reset_qos(priv); @@ -2257,7 +2260,9 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, if (changes & BSS_CHANGED_HT) { iwl_ht_conf(priv, bss_conf); - iwl_set_rxon_chain(priv); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); } if (changes & BSS_CHANGED_ASSOC) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 383590cd8b02..f5eff747e964 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -95,6 +95,7 @@ struct iwl_station_mgmt_ops { struct iwl_hcmd_ops { int (*rxon_assoc)(struct iwl_priv *priv); int (*commit_rxon)(struct iwl_priv *priv); + void (*set_rxon_chain)(struct iwl_priv *priv); }; struct iwl_hcmd_utils_ops { -- cgit v1.2.3 From 727882d62477ed45d248e8cd6d53cf794537b073 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:45 -0700 Subject: iwl3945: use iwl_set_mode in 3945 3945 can now use iwl_set_mode from iwlcore library. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 27 ------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 42 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 40 ++------------------------- 4 files changed, 45 insertions(+), 65 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 11e17923ad01..479fcf142707 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -588,33 +588,6 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl_set_mode(struct iwl_priv *priv, int mode) -{ - iwl_connection_init_rx_config(priv, mode); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - - priv->cfg->ops->smgmt->clear_station_table(priv); - - /* dont commit rxon if rf-kill is on*/ - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - - cancel_delayed_work(&priv->scan_check); - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - return -EAGAIN; - } - - iwlcore_commit_rxon(priv); - - return 0; -} - /****************************************************************************** * * Generic RX handler implementations diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index cca37af3243f..01e7604bf33f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2339,6 +2339,48 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) } EXPORT_SYMBOL(iwl_mac_beacon_update); +int iwl_set_mode(struct iwl_priv *priv, int mode) +{ + if (mode == NL80211_IFTYPE_ADHOC) { + const struct iwl_channel_info *ch_info; + + ch_info = iwl_get_channel_info(priv, + priv->band, + le16_to_cpu(priv->staging_rxon.channel)); + + if (!ch_info || !is_channel_ibss(ch_info)) { + IWL_ERR(priv, "channel %d not IBSS channel\n", + le16_to_cpu(priv->staging_rxon.channel)); + return -EINVAL; + } + } + + iwl_connection_init_rx_config(priv, mode); + + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + + memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); + + priv->cfg->ops->smgmt->clear_station_table(priv); + + /* dont commit rxon if rf-kill is on*/ + if (!iwl_is_ready_rf(priv)) + return -EAGAIN; + + cancel_delayed_work(&priv->scan_check); + if (iwl_scan_cancel_timeout(priv, 100)) { + IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); + return -EAGAIN; + } + + iwlcore_commit_rxon(priv); + + return 0; +} +EXPORT_SYMBOL(iwl_set_mode); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f5eff747e964..49df47a53b5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -273,6 +273,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, u32 changes); int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); +int iwl_set_mode(struct iwl_priv *priv, int mode); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7f35017d9df2..666c1fff62b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -570,42 +570,6 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl3945_set_mode(struct iwl_priv *priv, int mode) -{ - if (mode == NL80211_IFTYPE_ADHOC) { - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->staging_rxon.channel)); - - if (!ch_info || !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d not IBSS channel\n", - le16_to_cpu(priv->staging_rxon.channel)); - return -EINVAL; - } - } - - iwl_connection_init_rx_config(priv, mode); - - priv->cfg->ops->smgmt->clear_station_table(priv); - - /* don't commit rxon if rf-kill is on*/ - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - - cancel_delayed_work(&priv->scan_check); - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - return -EAGAIN; - } - - iwlcore_commit_rxon(priv); - - return 0; -} - static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_info *info, struct iwl_cmd *cmd, @@ -2701,7 +2665,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) } if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) - iwl3945_set_mode(priv, priv->iw_mode); + iwl_set_mode(priv, priv->iw_mode); return; @@ -3442,7 +3406,7 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } - if (iwl3945_set_mode(priv, conf->type) == -EAGAIN) + if (iwl_set_mode(priv, conf->type) == -EAGAIN) set_bit(STATUS_MODE_PENDING, &priv->status); mutex_unlock(&priv->mutex); -- cgit v1.2.3 From cbb6ab94b66cfb7136e640191a9628c5a71220a3 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:46 -0700 Subject: iwl3945: use iwl_mac_add_interface from iwlwifi Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 36 ---------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 37 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 37 +---------------------------- 4 files changed, 40 insertions(+), 72 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 479fcf142707..7e7b584ec257 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2036,42 +2036,6 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -static int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); - - if (priv->vif) { - IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - } - - if (iwl_set_mode(priv, conf->type) == -EAGAIN) - /* we are not ready, will run again when ready */ - set_bit(STATUS_MODE_PENDING, &priv->status); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - /** * iwl_mac_config - mac80211 config callback * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 01e7604bf33f..e08aee9b2b8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2381,6 +2381,43 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) } EXPORT_SYMBOL(iwl_set_mode); +int iwl_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + + IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); + + if (priv->vif) { + IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); + return -EOPNOTSUPP; + } + + spin_lock_irqsave(&priv->lock, flags); + priv->vif = conf->vif; + priv->iw_mode = conf->type; + + spin_unlock_irqrestore(&priv->lock, flags); + + mutex_lock(&priv->mutex); + + if (conf->mac_addr) { + IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + } + + if (iwl_set_mode(priv, conf->type) == -EAGAIN) + /* we are not ready, will run again when ready */ + set_bit(STATUS_MODE_PENDING, &priv->status); + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + return 0; +} +EXPORT_SYMBOL(iwl_mac_add_interface); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 49df47a53b5d..7df54405bef7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -274,6 +274,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); int iwl_set_mode(struct iwl_priv *priv, int mode); +int iwl_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 666c1fff62b2..955e50a124b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3380,41 +3380,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -static int iwl3945_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); - - if (priv->vif) { - IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - } - - if (iwl_set_mode(priv, conf->type) == -EAGAIN) - set_bit(STATUS_MODE_PENDING, &priv->status); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - /** * iwl3945_mac_config - mac80211 config callback * @@ -4372,7 +4337,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .tx = iwl3945_mac_tx, .start = iwl3945_mac_start, .stop = iwl3945_mac_stop, - .add_interface = iwl3945_mac_add_interface, + .add_interface = iwl_mac_add_interface, .remove_interface = iwl3945_mac_remove_interface, .config = iwl3945_mac_config, .config_interface = iwl3945_mac_config_interface, -- cgit v1.2.3 From d8052319f2a7d1ee86248df00193110ad1946a33 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:47 -0700 Subject: iwl3945: use iwl_mac_remove_interface from iwlwifi 3945 can now use iwl_mac_remove_interface from iwlwifi Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 24 ------------------------ drivers/net/wireless/iwlwifi/iwl-core.c | 25 +++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 25 +------------------------ 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7e7b584ec257..5cc30a223cf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2332,30 +2332,6 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, return 0; } -static void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - if (iwl_is_ready_rf(priv)) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - if (priv->vif == conf->vif) { - priv->vif = NULL; - memset(priv->bssid, 0, ETH_ALEN); - } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -} - static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e08aee9b2b8c..b8afd9b81fb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2418,6 +2418,31 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_mac_add_interface); +void iwl_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct iwl_priv *priv = hw->priv; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + mutex_lock(&priv->mutex); + + if (iwl_is_ready_rf(priv)) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + if (priv->vif == conf->vif) { + priv->vif = NULL; + memset(priv->bssid, 0, ETH_ALEN); + } + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + +} +EXPORT_SYMBOL(iwl_mac_remove_interface); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7df54405bef7..5dc33065f0ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -276,6 +276,8 @@ int iwl_commit_rxon(struct iwl_priv *priv); int iwl_set_mode(struct iwl_priv *priv, int mode); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); +void iwl_mac_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 955e50a124b5..f82a9dc82eef 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3640,29 +3640,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, return 0; } -static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - if (iwl_is_ready_rf(priv)) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - if (priv->vif == conf->vif) { - priv->vif = NULL; - memset(priv->bssid, 0, ETH_ALEN); - } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4338,7 +4315,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .start = iwl3945_mac_start, .stop = iwl3945_mac_stop, .add_interface = iwl_mac_add_interface, - .remove_interface = iwl3945_mac_remove_interface, + .remove_interface = iwl_mac_remove_interface, .config = iwl3945_mac_config, .config_interface = iwl3945_mac_config_interface, .configure_filter = iwl_configure_filter, -- cgit v1.2.3 From 4808368dad3263ac46e71f037c0dcd2dcf082525 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:48 -0700 Subject: iwl3945: use iwl_mac_config from iwlwifi 3945 can now use iwl_mac_config from iwlwifi Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 133 --------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 136 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 106 +--------------------- 4 files changed, 138 insertions(+), 238 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5cc30a223cf0..4640996aa298 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2036,139 +2036,6 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -/** - * iwl_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ -static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - unsigned long flags = 0; - int ret = 0; - u16 ch; - int scan_active = 0; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - conf->channel->hw_value, changed); - - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - scan_active = 1; - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - } - - - /* during scanning mac80211 will delay channel setting until - * scan finish with changed = 0 - */ - if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - if (scan_active) - goto set_ch_out; - - ch = ieee80211_frequency_to_channel(conf->channel->center_freq); - ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - ret = -EINVAL; - goto set_ch_out; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d in band %d not " - "IBSS channel\n", - conf->channel->hw_value, conf->channel->band); - ret = -EINVAL; - goto set_ch_out; - } - - priv->current_ht_config.is_ht = conf_is_ht(conf); - - spin_lock_irqsave(&priv->lock, flags); - - - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) - priv->staging_rxon.flags = 0; - - iwl_set_rxon_channel(priv, conf->channel); - - iwl_set_flags_for_band(priv, conf->channel->band); - spin_unlock_irqrestore(&priv->lock, flags); - set_ch_out: - /* The list of supported rates and rate mask can be different - * for each band; since the band may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) - ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); - else - ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); - if (ret) - IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); - - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", - priv->tx_power_user_lmt, conf->power_level); - - iwl_set_tx_power(priv, conf->power_level, false); - } - - /* call to ensure that 4965 rx_chain is set properly in monitor mode */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { - if (conf->radio_enabled && - iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " - "waiting for uCode\n"); - goto out; - } - - if (!conf->radio_enabled) - iwl_radio_kill_sw_disable_radio(priv); - } - - if (!conf->radio_enabled) { - IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); - goto out; - } - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - goto out; - } - - if (scan_active) - goto out; - - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwlcore_commit_rxon(priv); - else - IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n"); - - -out: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - return ret; -} - static void iwl_config_ap(struct iwl_priv *priv) { int ret = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b8afd9b81fb8..4369fc8978f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2443,6 +2443,142 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_mac_remove_interface); +/** + * iwl_mac_config - mac80211 config callback + * + * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to + * be set inappropriately and the driver currently sets the hardware up to + * use it whenever needed. + */ +int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) +{ + struct iwl_priv *priv = hw->priv; + const struct iwl_channel_info *ch_info; + struct ieee80211_conf *conf = &hw->conf; + unsigned long flags = 0; + int ret = 0; + u16 ch; + int scan_active = 0; + + mutex_lock(&priv->mutex); + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + ret = -EIO; + goto out; + } + + IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", + conf->channel->hw_value, changed); + + if (unlikely(!priv->cfg->mod_params->disable_hw_scan && + test_bit(STATUS_SCANNING, &priv->status))) { + scan_active = 1; + IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); + } + + + /* during scanning mac80211 will delay channel setting until + * scan finish with changed = 0 + */ + if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + if (scan_active) + goto set_ch_out; + + ch = ieee80211_frequency_to_channel(conf->channel->center_freq); + ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); + if (!is_channel_valid(ch_info)) { + IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); + ret = -EINVAL; + goto set_ch_out; + } + + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + !is_channel_ibss(ch_info)) { + IWL_ERR(priv, "channel %d in band %d not " + "IBSS channel\n", + conf->channel->hw_value, conf->channel->band); + ret = -EINVAL; + goto set_ch_out; + } + + priv->current_ht_config.is_ht = conf_is_ht(conf); + + spin_lock_irqsave(&priv->lock, flags); + + + /* if we are switching from ht to 2.4 clear flags + * from any ht related info since 2.4 does not + * support ht */ + if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) + priv->staging_rxon.flags = 0; + + iwl_set_rxon_channel(priv, conf->channel); + + iwl_set_flags_for_band(priv, conf->channel->band); + spin_unlock_irqrestore(&priv->lock, flags); + set_ch_out: + /* The list of supported rates and rate mask can be different + * for each band; since the band may have changed, reset + * the rate mask to what mac80211 lists */ + iwl_set_rate(priv); + } + + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) + ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3); + else + ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM); + if (ret) + IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); + + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", + priv->tx_power_user_lmt, conf->power_level); + + iwl_set_tx_power(priv, conf->power_level, false); + } + + /* call to ensure that 4965 rx_chain is set properly in monitor mode */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + + if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { + if (conf->radio_enabled && + iwl_radio_kill_sw_enable_radio(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " + "waiting for uCode\n"); + goto out; + } + + if (!conf->radio_enabled) + iwl_radio_kill_sw_disable_radio(priv); + } + + if (!conf->radio_enabled) { + IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); + goto out; + } + + if (scan_active) + goto out; + + if (memcmp(&priv->active_rxon, + &priv->staging_rxon, sizeof(priv->staging_rxon))) + iwlcore_commit_rxon(priv); + else + IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n"); + + +out: + IWL_DEBUG_MAC80211(priv, "leave\n"); + mutex_unlock(&priv->mutex); + return ret; +} +EXPORT_SYMBOL(iwl_mac_config); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5dc33065f0ba..da8fae52a5d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -278,6 +278,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); +int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f82a9dc82eef..c5644a5e50c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3166,8 +3166,6 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) mutex_unlock(&priv->mutex); } -static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); - #define IWL_DELAY_NEXT_SCAN (HZ*2) void iwl3945_post_associate(struct iwl_priv *priv) @@ -3380,108 +3378,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -/** - * iwl3945_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ -static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - int ret = 0; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter to channel %d\n", - conf->channel->hw_value); - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - ret = -EIO; - goto out; - } - - if (unlikely(!iwl3945_mod_params.disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - set_bit(STATUS_CONF_PENDING, &priv->status); - mutex_unlock(&priv->mutex); - return 0; - } - - spin_lock_irqsave(&priv->lock, flags); - - ch_info = iwl_get_channel_info(priv, conf->channel->band, - conf->channel->hw_value); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN(priv, - "Channel %d [%d] is INVALID for this band.\n", - conf->channel->hw_value, conf->channel->band); - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - spin_unlock_irqrestore(&priv->lock, flags); - ret = -EINVAL; - goto out; - } - - iwl_set_rxon_channel(priv, conf->channel); - - iwl_set_flags_for_band(priv, conf->channel->band); - - /* The list of supported rates and rate mask can be different - * for each phymode; since the phymode may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - -#ifdef IEEE80211_CONF_CHANNEL_SWITCH - if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { - iwl3945_hw_channel_switch(priv, conf->channel); - goto out; - } -#endif - - if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) { - if (conf->radio_enabled && - iwl_radio_kill_sw_enable_radio(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - " - "waiting for uCode\n"); - goto out; - } - - if (!conf->radio_enabled) { - iwl_radio_kill_sw_disable_radio(priv); - IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n"); - goto out; - } - } - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF kill\n"); - ret = -EIO; - goto out; - } - - iwl_set_rate(priv); - - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwlcore_commit_rxon(priv); - else - IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n"); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -out: - clear_bit(STATUS_CONF_PENDING, &priv->status); - mutex_unlock(&priv->mutex); - return ret; -} - static void iwl3945_config_ap(struct iwl_priv *priv) { int rc = 0; @@ -4316,7 +4212,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .stop = iwl3945_mac_stop, .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, - .config = iwl3945_mac_config, + .config = iwl_mac_config, .config_interface = iwl3945_mac_config_interface, .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, -- cgit v1.2.3 From 60690a6a38cc03142a0c5aaed64cf043e707457d Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:49 -0700 Subject: iwlwifi: add config_ap lib op add config_ap lib op to iwlwifi and iwl3945 in preparation of future 3945 porting actions. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.h | 7 ++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 7 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a854feba82c8..edc0cb38033d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2952,6 +2952,7 @@ static struct iwl_lib_ops iwl3945_lib = { .send_tx_power = iwl3945_send_tx_power, .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, .post_associate = iwl3945_post_associate, + .config_ap = iwl3945_config_ap, }; static struct iwl_station_mgmt_ops iwl3945_station_mgmt = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 88628b23efd9..4f5473e01617 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -278,6 +278,8 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, extern void iwl3945_disable_events(struct iwl_priv *priv); extern int iwl4965_get_temperature(const struct iwl_priv *priv); extern void iwl3945_post_associate(struct iwl_priv *priv); +extern void iwl3945_config_ap(struct iwl_priv *priv); + /** * iwl3945_hw_find_station - Find station id for a given BSSID * @bssid: MAC address of station ID to find diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ab25e6ab59d5..e4762e530345 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2333,6 +2333,7 @@ static struct iwl_lib_ops iwl4965_lib = { .update_chain_flags = iwl_update_chain_flags, .temperature = iwl4965_temperature_calib, .post_associate = iwl_post_associate, + .config_ap = iwl_config_ap, }; static struct iwl_ops iwl4965_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index cf622a14bfe2..5bbb4f953364 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1537,6 +1537,7 @@ struct iwl_lib_ops iwl5000_lib = { .query_addr = iwl5000_eeprom_query_addr, }, .post_associate = iwl_post_associate, + .config_ap = iwl_config_ap, }; struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4640996aa298..97f8322e0661 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2036,7 +2036,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -static void iwl_config_ap(struct iwl_priv *priv) +void iwl_config_ap(struct iwl_priv *priv) { int ret = 0; unsigned long flags; @@ -2178,7 +2178,7 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, memcpy(priv->bssid, conf->bssid, ETH_ALEN); if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_config_ap(priv); + iwlcore_config_ap(priv); else { rc = iwlcore_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index da8fae52a5d6..af559b07cc8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -162,6 +162,7 @@ struct iwl_lib_ops { void (*update_chain_flags)(struct iwl_priv *priv); void (*temperature) (struct iwl_priv *priv); void (*post_associate) (struct iwl_priv *priv); + void (*config_ap) (struct iwl_priv *priv); /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; @@ -279,6 +280,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); +void iwl_config_ap(struct iwl_priv *priv); /***************************************************** * RX handlers. @@ -565,7 +567,10 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv) { return priv->cfg->ops->hcmd->commit_rxon(priv); } - +static inline void iwlcore_config_ap(struct iwl_priv *priv) +{ + priv->cfg->ops->lib->config_ap(priv); +} static inline const struct ieee80211_supported_band *iwl_get_hw_mode( struct iwl_priv *priv, enum ieee80211_band band) { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c5644a5e50c9..ad6f5ebeaf7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3378,7 +3378,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return NETDEV_TX_OK; } -static void iwl3945_config_ap(struct iwl_priv *priv) +void iwl3945_config_ap(struct iwl_priv *priv) { int rc = 0; @@ -3515,7 +3515,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, memcpy(priv->bssid, conf->bssid, ETH_ALEN); if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl3945_config_ap(priv); + iwlcore_config_ap(priv); else { rc = iwlcore_commit_rxon(priv); if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) -- cgit v1.2.3 From 5ee5811e24b20d49ea553fda568433effbab7a62 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:50 -0700 Subject: iwl3945: use iwl_mac_config_interface from iwlwifi 3945 can now use iwl_mac_config_interface from iwlwifi. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 100 --------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 100 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 3 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 102 +--------------------------- 4 files changed, 104 insertions(+), 201 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 97f8322e0661..edfece6e0d4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2099,106 +2099,6 @@ void iwl_config_ap(struct iwl_priv *priv) * clear sta table, add BCAST sta... */ } - -static int iwl_mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - int rc; - - if (conf == NULL) - return -EIO; - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); - return 0; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) - return -ENOMEM; - mutex_lock(&priv->mutex); - rc = iwl_mac_beacon_update(hw, beacon); - mutex_unlock(&priv->mutex); - if (rc) - return rc; - } - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - - if (conf->bssid) - IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); - -/* - * very dubious code was here; the probe filtering flag is never set: - * - if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && - !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { - */ - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - if (!conf->bssid) { - conf->bssid = priv->mac_addr; - memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", - conf->bssid); - } - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); - } - - if (iwl_is_rfkill(priv)) - goto done; - - if (conf->bssid && !is_zero_ether_addr(conf->bssid) && - !is_multicast_ether_addr(conf->bssid)) { - /* If there is currently a HW scan going on in the background - * then we need to cancel it else the RXON below will fail. */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress " - "after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - mutex_unlock(&priv->mutex); - return -EAGAIN; - } - memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); - - /* TODO: Audit driver for usage of these members and see - * if mac80211 deprecates them (priv->bssid looks like it - * shouldn't be there, but I haven't scanned the IBSS code - * to verify) - jpk */ - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwlcore_config_ap(priv); - else { - rc = iwlcore_commit_rxon(priv); - if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) - iwl_rxon_add_station( - priv, priv->active_rxon.bssid_addr, 1); - } - - } else { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - done: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - - return 0; -} - static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_key_conf *keyconf, const u8 *addr, u32 iv32, u16 *phase1key) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4369fc8978f9..e8b74fc82515 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2579,6 +2579,106 @@ out: } EXPORT_SYMBOL(iwl_mac_config); +int iwl_mac_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct iwl_priv *priv = hw->priv; + int rc; + + if (conf == NULL) + return -EIO; + + if (priv->vif != vif) { + IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); + return 0; + } + + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + conf->changed & IEEE80211_IFCC_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + if (!beacon) + return -ENOMEM; + mutex_lock(&priv->mutex); + rc = iwl_mac_beacon_update(hw, beacon); + mutex_unlock(&priv->mutex); + if (rc) + return rc; + } + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + mutex_lock(&priv->mutex); + + if (conf->bssid) + IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); + +/* + * very dubious code was here; the probe filtering flag is never set: + * + if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && + !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { + */ + + if (priv->iw_mode == NL80211_IFTYPE_AP) { + if (!conf->bssid) { + conf->bssid = priv->mac_addr; + memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); + IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", + conf->bssid); + } + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); + } + + if (iwl_is_rfkill(priv)) + goto done; + + if (conf->bssid && !is_zero_ether_addr(conf->bssid) && + !is_multicast_ether_addr(conf->bssid)) { + /* If there is currently a HW scan going on in the background + * then we need to cancel it else the RXON below will fail. */ + if (iwl_scan_cancel_timeout(priv, 100)) { + IWL_WARN(priv, "Aborted scan still in progress " + "after 100ms\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); + mutex_unlock(&priv->mutex); + return -EAGAIN; + } + memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); + + /* TODO: Audit driver for usage of these members and see + * if mac80211 deprecates them (priv->bssid looks like it + * shouldn't be there, but I haven't scanned the IBSS code + * to verify) - jpk */ + memcpy(priv->bssid, conf->bssid, ETH_ALEN); + + if (priv->iw_mode == NL80211_IFTYPE_AP) + iwlcore_config_ap(priv); + else { + rc = iwlcore_commit_rxon(priv); + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) + iwl_rxon_add_station( + priv, priv->active_rxon.bssid_addr, 1); + } + + } else { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + + done: + IWL_DEBUG_MAC80211(priv, "leave\n"); + mutex_unlock(&priv->mutex); + + return 0; +} +EXPORT_SYMBOL(iwl_mac_config_interface); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index af559b07cc8e..92a42c880488 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -281,6 +281,9 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); void iwl_config_ap(struct iwl_priv *priv); +int iwl_mac_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ad6f5ebeaf7a..3461768e5a2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3436,106 +3436,6 @@ void iwl3945_config_ap(struct iwl_priv *priv) * clear sta table, add BCAST sta... */ } -static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - int rc; - - if (conf == NULL) - return -EIO; - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); - return 0; - } - - /* handle this temporarily here */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) - return -ENOMEM; - mutex_lock(&priv->mutex); - rc = iwl_mac_beacon_update(hw, beacon); - mutex_unlock(&priv->mutex); - if (rc) - return rc; - } - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - - if (conf->bssid) - IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); - -/* - * very dubious code was here; the probe filtering flag is never set: - * - if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && - !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { - */ - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - if (!conf->bssid) { - conf->bssid = priv->mac_addr; - memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", - conf->bssid); - } - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); - } - - if (iwl_is_rfkill(priv)) - goto done; - - if (conf->bssid && !is_zero_ether_addr(conf->bssid) && - !is_multicast_ether_addr(conf->bssid)) { - /* If there is currently a HW scan going on in the background - * then we need to cancel it else the RXON below will fail. */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress " - "after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n"); - mutex_unlock(&priv->mutex); - return -EAGAIN; - } - memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); - - /* TODO: Audit driver for usage of these members and see - * if mac80211 deprecates them (priv->bssid looks like it - * shouldn't be there, but I haven't scanned the IBSS code - * to verify) - jpk */ - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwlcore_config_ap(priv); - else { - rc = iwlcore_commit_rxon(priv); - if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) - priv->cfg->ops->smgmt->add_station(priv, - priv->active_rxon.bssid_addr, 1, 0, NULL); - } - - } else { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - done: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - - return 0; -} - static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4213,7 +4113,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .config_interface = iwl3945_mac_config_interface, + .config_interface = iwl_mac_config_interface, .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, .get_tx_stats = iwl3945_mac_get_tx_stats, -- cgit v1.2.3 From aa89f31e708d469f5dd824c59c98e4856a2e3572 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:51 -0700 Subject: iwl3945: use iwl_mac_get_tx_stats from iwlwifi 3945 can now use iwl_mac_get_tx_stats from iwlwifi. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 35 --------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 36 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 37 +---------------------------- 4 files changed, 39 insertions(+), 71 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index edfece6e0d4c..3ebf80fbebab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2223,41 +2223,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return 0; } -static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - int i, avail; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; - q = &txq->q; - avail = iwl_queue_space(q); - - stats[i].len = q->n_window - avail; - stats[i].limit = q->n_window - q->high_mark; - stats[i].count = q->n_window; - - } - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} - static int iwl_mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e8b74fc82515..144630b25491 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2679,6 +2679,42 @@ int iwl_mac_config_interface(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_mac_config_interface); +int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats) +{ + struct iwl_priv *priv = hw->priv; + int i, avail; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + unsigned long flags; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + spin_lock_irqsave(&priv->lock, flags); + + for (i = 0; i < AC_NUM; i++) { + txq = &priv->txq[i]; + q = &txq->q; + avail = iwl_queue_space(q); + + stats[i].len = q->n_window - avail; + stats[i].limit = q->n_window - q->high_mark; + stats[i].count = q->n_window; + + } + spin_unlock_irqrestore(&priv->lock, flags); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + + return 0; +} +EXPORT_SYMBOL(iwl_mac_get_tx_stats); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 92a42c880488..7e0d0ed0a5db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -284,6 +284,8 @@ void iwl_config_ap(struct iwl_priv *priv); int iwl_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf); +int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3461768e5a2b..07883b264b7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3494,41 +3494,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - int i, avail; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; - q = &txq->q; - avail = iwl_queue_space(q); - - stats[i].len = q->n_window - avail; - stats[i].limit = q->n_window - q->high_mark; - stats[i].count = q->n_window; - - } - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} - static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; @@ -4116,7 +4081,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .config_interface = iwl_mac_config_interface, .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, - .get_tx_stats = iwl3945_mac_get_tx_stats, + .get_tx_stats = iwl_mac_get_tx_stats, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl3945_mac_reset_tsf, .bss_info_changed = iwl_bss_info_changed, -- cgit v1.2.3 From bd564261d7dd3660f7a5ba308a867c6bb23de6a2 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 8 Apr 2009 11:26:52 -0700 Subject: iwl3945: use iwl_mac_reset_tsf from iwlwifi 3945 can now use iwl_mac_reset_tsf from iwlwifi. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 75 ----------------------------- drivers/net/wireless/iwlwifi/iwl-core.c | 75 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 60 +---------------------- 4 files changed, 77 insertions(+), 134 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3ebf80fbebab..9dda3d547d0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2235,81 +2235,6 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, return 0; } -static void iwl_mac_reset_tsf(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - spin_lock_irqsave(&priv->lock, flags); - memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = 0; - priv->assoc_capability = 0; - priv->assoc_station_added = 0; - - /* new association get rid of ibss beacon skb */ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = NULL; - - priv->beacon_int = priv->hw->conf.beacon_int; - priv->timestamp = 0; - if ((priv->iw_mode == NL80211_IFTYPE_STATION)) - priv->beacon_int = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - iwl_power_update_mode(priv, 0); - - /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - - /* switch to CAM during association period. - * the ucode will block any association/authentication - * frome during assiciation period if it can not hear - * the AP because of PM. the timer enable PM back is - * association do not complete - */ - if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN | - IEEE80211_CHAN_RADAR)) - iwl_power_disable_management(priv, 3000); - - IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); - mutex_unlock(&priv->mutex); - return; - } - - iwl_set_rate(priv); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - - /***************************************************************************** * * sysfs attributes diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 144630b25491..c523cc339eaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2715,6 +2715,81 @@ int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_mac_get_tx_stats); +void iwl_mac_reset_tsf(struct ieee80211_hw *hw) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + + mutex_lock(&priv->mutex); + IWL_DEBUG_MAC80211(priv, "enter\n"); + + spin_lock_irqsave(&priv->lock, flags); + memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_reset_qos(priv); + + spin_lock_irqsave(&priv->lock, flags); + priv->assoc_id = 0; + priv->assoc_capability = 0; + priv->assoc_station_added = 0; + + /* new association get rid of ibss beacon skb */ + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = NULL; + + priv->beacon_int = priv->hw->conf.beacon_int; + priv->timestamp = 0; + if ((priv->iw_mode == NL80211_IFTYPE_STATION)) + priv->beacon_int = 0; + + spin_unlock_irqrestore(&priv->lock, flags); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + mutex_unlock(&priv->mutex); + return; + } + + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ + if (priv->iw_mode != NL80211_IFTYPE_AP) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + + iwl_power_update_mode(priv, 0); + + /* Per mac80211.h: This is only used in IBSS mode... */ + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { + + /* switch to CAM during association period. + * the ucode will block any association/authentication + * frome during assiciation period if it can not hear + * the AP because of PM. the timer enable PM back is + * association do not complete + */ + if (priv->hw->conf.channel->flags & + (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR)) + iwl_power_disable_management(priv, 3000); + + IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); + mutex_unlock(&priv->mutex); + return; + } + + iwl_set_rate(priv); + + mutex_unlock(&priv->mutex); + + IWL_DEBUG_MAC80211(priv, "leave\n"); +} +EXPORT_SYMBOL(iwl_mac_reset_tsf); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7e0d0ed0a5db..df90c261b6b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -286,6 +286,7 @@ int iwl_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf); int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats); +void iwl_mac_reset_tsf(struct ieee80211_hw *hw); /***************************************************** * RX handlers. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 07883b264b7e..ed497551a860 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3494,64 +3494,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - iwl_reset_qos(priv); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = 0; - priv->assoc_capability = 0; - - /* new association get rid of ibss beacon skb */ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = NULL; - - priv->beacon_int = priv->hw->conf.beacon_int; - priv->timestamp = 0; - if ((priv->iw_mode == NL80211_IFTYPE_STATION)) - priv->beacon_int = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - - IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); - mutex_unlock(&priv->mutex); - return; - } - - iwl_set_rate(priv); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -} - /***************************************************************************** * * sysfs attributes @@ -4083,7 +4025,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .set_key = iwl3945_mac_set_key, .get_tx_stats = iwl_mac_get_tx_stats, .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl3945_mac_reset_tsf, + .reset_tsf = iwl_mac_reset_tsf, .bss_info_changed = iwl_bss_info_changed, .hw_scan = iwl_mac_hw_scan }; -- cgit v1.2.3 From 12b9681721adb34b7ec42aa973ab96692998153d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 8 Apr 2009 11:39:27 -0700 Subject: iwlwifi: Display decoded rate/mcs information This patch adding MCS information in rate_scale_table, it help for debugging rate scaling algorithm, easy to understand what is the current rate scale table and matching modulation, plus the last mcs used for tx. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 40 +++++++++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 7 ++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index b1818a3d1e51..786b11d52b45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -167,6 +167,8 @@ struct iwl_lq_sta { /* used to be in sta_info */ int last_txrate_idx; + /* last tx rate_n_flags */ + u32 last_rate_n_flags; }; static void rs_rate_scale_perform(struct iwl_priv *priv, @@ -249,6 +251,23 @@ static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 }; +/* mbps, mcs */ +const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { + {"1", ""}, + {"2", ""}, + {"5.5", ""}, + {"11", ""}, + {"6", "BPSK 1/2"}, + {"9", "BPSK 1/2"}, + {"12", "QPSK 1/2"}, + {"18", "QPSK 3/4"}, + {"24", "16QAM 1/2"}, + {"36", "16QAM 3/4"}, + {"48", "64QAM 2/3"}, + {"54", "64QAM 3/4"}, + {"60", "64QAM 5/6"} +}; + static inline u8 rs_extract_rate(u32 rate_n_flags) { return (u8)(rate_n_flags & 0xFF); @@ -919,6 +938,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, * else look up the rate that was, finally, successful. */ tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); + lq_sta->last_rate_n_flags = tx_rate; rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); /* Update frame history window with "success" if Tx got ACKed ... */ @@ -2826,6 +2846,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, char *buff; int desc = 0; int i = 0; + int index = 0; ssize_t ret; struct iwl_lq_sta *lq_sta = file->private_data; @@ -2857,6 +2878,8 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, (tbl->is_fat) ? "40MHz" : "20MHz"); desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : ""); } + desc += sprintf(buff+desc, "last tx rate=0x%X\n", + lq_sta->last_rate_n_flags); desc += sprintf(buff+desc, "general:" "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", lq_sta->lq.general_params.flags, @@ -2877,10 +2900,19 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->lq.general_params.start_rate_index[2], lq_sta->lq.general_params.start_rate_index[3]); - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - desc += sprintf(buff+desc, " rate[%d] 0x%X\n", - i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { + index = iwl_hwrate_to_plcp_idx( + le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); + if (is_legacy(tbl->lq_type)) { + desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n", + i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), + iwl_rate_mcs[index].mbps); + } else { + desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps (%s)\n", + i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), + iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs); + } + } ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); kfree(buff); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 9cd90ba5ef95..f875136bc5dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -325,6 +325,13 @@ enum iwl_table_type { #define ANT_BC (ANT_B | ANT_C) #define ANT_ABC (ANT_AB | ANT_C) +#define IWL_MAX_MCS_DISPLAY_SIZE 12 + +struct iwl_rate_mcs_info { + char mbps[IWL_MAX_MCS_DISPLAY_SIZE]; + char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; +}; + static inline u8 num_of_ant(u8 mask) { return !!((mask) & ANT_A) + -- cgit v1.2.3 From ddfcf999274838a8dfb0ccf8e69fc1e50eea3341 Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Wed, 8 Apr 2009 11:39:28 -0700 Subject: iwlwifi: do not set dual_stream_ant_msk for 3 streams This patch fixes a bug introduced by commit "iwlwifi: adding MIMO3 support in rate scaling". We should not set the dual_stream_ant_msk (for 2x2 MIMO) when using a 3x3 rate, this will cause a SYSASSERT in uCode. Note: there is no triple_stream_ant_msk, because all three antennas are used. Signed-off-by: Daniel C Halperin Acked-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 786b11d52b45..98b6b37951b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2666,9 +2666,6 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, } else if (num_of_ant(tbl_type.ant_type) == 2) { lq_cmd->general_params.dual_stream_ant_msk = tbl_type.ant_type; - } else if (num_of_ant(tbl_type.ant_type) == 3) { - lq_cmd->general_params.dual_stream_ant_msk = - tbl_type.ant_type; } /* otherwise we don't modify the existing value */ index++; -- cgit v1.2.3 From 3a6502927f763f05069d1b84af3a05b38eb1a818 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Wed, 8 Apr 2009 11:39:29 -0700 Subject: iwlagn: Sync rxon active with changes We need to sync rxon_active with changes after we commit rxon_assoc, without rxon_active will still have the old data that cause iwl_send_rxon_assoc to fail with no change in rxon command. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c523cc339eaf..8f121fa3f325 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2238,6 +2238,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct iwl_priv *priv = hw->priv; + int ret; IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); @@ -2292,7 +2293,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); - iwl_send_rxon_assoc(priv); + ret = iwl_send_rxon_assoc(priv); + if (!ret) + /* Sync active_rxon with latest change. */ + memcpy((void *)&priv->active_rxon, + &priv->staging_rxon, + sizeof(struct iwl_rxon_cmd)); } } -- cgit v1.2.3 From c2105fa7b68547a414095cfbf59bf513a9aae3ce Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Wed, 8 Apr 2009 11:39:30 -0700 Subject: iwlwifi: check triple_stream_basic_rates in iwl_full_rxon_required For completeness, we should also make sure that the 3x3 MIMO rates are also checked when seeing if one rxon struct matches another. Signed-off-by: Daniel C Halperin Acked-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8f121fa3f325..5877293bd21f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -735,6 +735,8 @@ int iwl_full_rxon_required(struct iwl_priv *priv) priv->active_rxon.ofdm_ht_single_stream_basic_rates) || (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || + (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates != + priv->active_rxon.ofdm_ht_triple_stream_basic_rates) || (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) return 1; -- cgit v1.2.3 From 1620108910b07bc41f4ad462ca56e899faf7e61a Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Wed, 8 Apr 2009 11:39:31 -0700 Subject: iwlcore: fix channel display in debugfs Fix displaying of wrong channel information when user query channel through debugfs Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index af1d1214b184..5b8c83939bf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -389,7 +389,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, channels[i].max_power, channels[i].flags & IEEE80211_CHAN_RADAR ? " (IEEE 802.11h required)" : "", - (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS) + ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) || (channels[i].flags & IEEE80211_CHAN_RADAR)) ? "" : ", IBSS", -- cgit v1.2.3 From a83b9141b540f96dd59409c6487828e880113a29 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 8 Apr 2009 11:39:32 -0700 Subject: iwlwifi: adding interrupt counter in debugfs for debugging This patch adds interrupt statistics report to debugfs, this can help to understand number of interrupts happened which including HW/SW error for easier and better debugging. in /sys/kernel/debug/ieee80211/phyN/iwlagn/data directory use "cat interrupt" to view the current interrupt counter use "echo 0 > interrupt" to clear interrupt counter Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 26 ++++++++- drivers/net/wireless/iwlwifi/iwl-core.c | 6 ++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 92 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 18 ++++++ 6 files changed, 141 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 9dda3d547d0d..12de63e9c720 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -911,6 +911,7 @@ void iwl_rx_handle(struct iwl_priv *priv) IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; } else { /* No handling needed */ IWL_DEBUG_RX(priv, @@ -1035,6 +1036,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); + priv->isr_stats.hw++; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -1047,13 +1049,17 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) #ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) + if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); + priv->isr_stats.sch++; + } /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) + if (inta & CSR_INT_BIT_ALIVE) { IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } } #endif /* Safely ignore these bits for debug checks below */ @@ -1069,6 +1075,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); + priv->isr_stats.rfkill++; + /* driver only loads ucode once setting the interface up. * the driver allows loading the ucode even if the radio * is killed. Hence update the killswitch state here. The @@ -1088,6 +1096,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; handled |= CSR_INT_BIT_CT_KILL; } @@ -1095,6 +1104,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_SW_ERR) { IWL_ERR(priv, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + priv->isr_stats.sw_err = inta; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -1110,6 +1121,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) iwl_txq_update_write_ptr(priv, &priv->txq[4]); iwl_txq_update_write_ptr(priv, &priv->txq[5]); + priv->isr_stats.wakeup++; + handled |= CSR_INT_BIT_WAKEUP; } @@ -1118,19 +1131,23 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { iwl_rx_handle(priv); + priv->isr_stats.rx++; handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); } if (inta & CSR_INT_BIT_FH_TX) { IWL_DEBUG_ISR(priv, "Tx interrupt\n"); + priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; /* FH finished to write, send event */ priv->ucode_write_complete = 1; wake_up_interruptible(&priv->wait_command_queue); } - if (inta & ~handled) + if (inta & ~handled) { IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } if (inta & ~CSR_INI_SET_MASK) { IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", @@ -1155,6 +1172,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } + /****************************************************************************** * * uCode download functions @@ -1983,6 +2001,8 @@ static int iwl_mac_start(struct ieee80211_hw *hw) out: priv->is_open = 1; + /* default to MONITOR mode */ + priv->iw_mode = NL80211_IFTYPE_MONITOR; IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5877293bd21f..f23175240289 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2119,6 +2119,12 @@ void iwl_rx_reply_error(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_reply_error); +void iwl_clear_isr_stats(struct iwl_priv *priv) +{ + memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); +} +EXPORT_SYMBOL(iwl_clear_isr_stats); + int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index df90c261b6b5..8773d733a54e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -480,6 +480,7 @@ int iwl_pci_resume(struct pci_dev *pdev); ******************************************************/ void iwl_dump_nic_error_log(struct iwl_priv *priv); void iwl_dump_nic_event_log(struct iwl_priv *priv); +void iwl_clear_isr_stats(struct iwl_priv *priv); /***************************************************** * GEOS diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 65d1a7f2db9e..db069801bc41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -75,6 +75,7 @@ struct iwl_debugfs { struct dentry *file_log_event; struct dentry *file_channels; struct dentry *file_status; + struct dentry *file_interrupt; } dbgfs_data_files; struct dir_rf_files { struct dentry *file_disable_sensitivity; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 5b8c83939bf0..ffc4be3842b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -473,6 +473,95 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } +static ssize_t iwl_dbgfs_interrupt_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + int cnt = 0; + char *buf; + int bufsz = 24 * 64; /* 24 items * 64 char per item */ + ssize_t ret; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + pos += scnprintf(buf + pos, bufsz - pos, + "Interrupt Statistics Report:\n"); + + pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", + priv->isr_stats.hw); + pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", + priv->isr_stats.sw); + if (priv->isr_stats.sw > 0) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tLast Restarting Code: 0x%X\n", + priv->isr_stats.sw_err); + } +#ifdef CONFIG_IWLWIFI_DEBUG + pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", + priv->isr_stats.sch); + pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", + priv->isr_stats.alive); +#endif + pos += scnprintf(buf + pos, bufsz - pos, + "HW RF KILL switch toggled:\t %u\n", + priv->isr_stats.rfkill); + + pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", + priv->isr_stats.ctkill); + + pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", + priv->isr_stats.wakeup); + + pos += scnprintf(buf + pos, bufsz - pos, + "Rx command responses:\t\t %u\n", + priv->isr_stats.rx); + for (cnt = 0; cnt < REPLY_MAX; cnt++) { + if (priv->isr_stats.rx_handlers[cnt] > 0) + pos += scnprintf(buf + pos, bufsz - pos, + "\tRx handler[%36s]:\t\t %u\n", + get_cmd_string(cnt), + priv->isr_stats.rx_handlers[cnt]); + } + + pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", + priv->isr_stats.tx); + + pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", + priv->isr_stats.unhandled); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_interrupt_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + u32 reset_flag; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%x", &reset_flag) != 1) + return -EFAULT; + if (reset_flag == 0) + iwl_clear_isr_stats(priv); + + return count; +} + + DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(eeprom); @@ -481,6 +570,7 @@ DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(status); +DEBUGFS_READ_WRITE_FILE_OPS(interrupt); /* * Create the debugfs files and directories @@ -516,6 +606,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(tx_statistics, data); DEBUGFS_ADD_FILE(channels, data); DEBUGFS_ADD_FILE(status, data); + DEBUGFS_ADD_FILE(interrupt, data); DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, &priv->disable_chain_noise_cal); @@ -546,6 +637,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); DEBUGFS_REMOVE(priv->dbgfs->dir_data); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 59930f398f31..0922e33a7d42 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -819,6 +819,21 @@ enum { MEASUREMENT_ACTIVE = (1 << 1), }; +/* interrupt statistics */ +struct isr_statistics { + u32 hw; + u32 sw; + u32 sw_err; + u32 sch; + u32 alive; + u32 rfkill; + u32 ctkill; + u32 wakeup; + u32 rx; + u32 rx_handlers[REPLY_MAX]; + u32 tx; + u32 unhandled; +}; #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ @@ -975,6 +990,9 @@ struct iwl_priv { u64 bytes; } tx_stats[3], rx_stats[3]; + /* counts interrupts */ + struct isr_statistics isr_stats; + struct iwl_power_mgr power_data; struct iwl_notif_statistics statistics; -- cgit v1.2.3 From a2caba6b5fc4e046edfefb1db82f52b939b526a5 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 14 Apr 2009 11:45:57 -0400 Subject: libertas: fix warning about %zd: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/libertas/rx.c: In function ‘lbs_process_rxed_packet’: drivers/net/wireless/libertas/rx.c:184: warning: format ‘%zd’ expects type ‘signed size_t’, but argument 4 has type ‘__le32’ drivers/net/wireless/libertas/rx.c:184: warning: format ‘%zd’ expects type ‘signed size_t’, but argument 5 has type ‘unsigned int’ Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index bd845d09f174..65f02cc6752f 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -182,8 +182,8 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) } lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n", - skb->len, le32_to_cpu(p_rx_pd->pkt_ptr), - skb->len - le32_to_cpu(p_rx_pd->pkt_ptr)); + skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr), + skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr)); lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, sizeof(p_rx_pkt->eth803_hdr.dest_addr)); -- cgit v1.2.3 From 137907287789607f2a2586ad625e7b8c646b3425 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Apr 2009 21:26:27 +0200 Subject: b43: Remove unnecessary MMIO in interrupt hotpath This removes unnecessary MMIO accesses in the interrupt hotpath. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 4 +-- drivers/net/wireless/b43/main.c | 61 +++++++++++++---------------------------- 2 files changed, 21 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index cc1db7e5c664..4e8ad841c3c5 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -778,8 +778,8 @@ struct b43_wldev { /* Reason code of the last interrupt. */ u32 irq_reason; u32 dma_reason[6]; - /* saved irq enable/disable state bitfield. */ - u32 irq_savedstate; + /* The currently active generic-interrupt mask. */ + u32 irq_mask; /* Link Quality calculation context. */ struct b43_noise_calculation noisecalc; /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 09e0c60d96df..a97c6ff0f12e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -673,32 +673,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev) b43_set_slot_time(dev, 20); } -/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask) -{ - u32 old_mask; - - old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask); - - return old_mask; -} - -/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask) -{ - u32 old_mask; - - old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask); - - return old_mask; -} - /* Synchronize IRQ top- and bottom-half. * IRQs must be masked before calling this. * This must not be called with the irq_lock held. @@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) /* This is the bottom half of the asynchronous beacon update. */ /* Ignore interrupt in the future. */ - dev->irq_savedstate &= ~B43_IRQ_BEACON; + dev->irq_mask &= ~B43_IRQ_BEACON; cmd = b43_read32(dev, B43_MMIO_MACCMD); beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); @@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) /* Schedule interrupt manually, if busy. */ if (beacon0_valid && beacon1_valid) { b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON); - dev->irq_savedstate |= B43_IRQ_BEACON; + dev->irq_mask |= B43_IRQ_BEACON; return; } @@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { spin_lock_irq(&wl->irq_lock); /* update beacon right away or defer to irq */ - dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); handle_irq_beacon(dev); /* The handler might have updated the IRQ mask. */ - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, - dev->irq_savedstate); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); mmiowb(); spin_unlock_irq(&wl->irq_lock); } @@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) if (reason & B43_IRQ_TX_OK) handle_irq_transmit_status(dev); - b43_interrupt_enable(dev, dev->irq_savedstate); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); mmiowb(); spin_unlock_irqrestore(&dev->wl->irq_lock, flags); } @@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason) b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); +/* Unused ring b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]); +*/ } /* Interrupt handler top-half */ @@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) struct b43_wldev *dev = dev_id; u32 reason; - if (!dev) - return IRQ_NONE; + B43_WARN_ON(!dev); spin_lock(&dev->wl->irq_lock); - if (b43_status(dev) < B43_STAT_STARTED) + if (unlikely(b43_status(dev) < B43_STAT_STARTED)) { + /* This can only happen on shared IRQ lines. */ goto out; + } reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) /* shared IRQ */ goto out; ret = IRQ_HANDLED; - reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); + reason &= dev->irq_mask; if (!reason) goto out; @@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) & 0x0001DC00; dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON) & 0x0000DC00; +/* Unused ring dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON) & 0x0000DC00; +*/ b43_interrupt_ack(dev, reason); /* disable all IRQs. They are enabled again in the bottom half. */ - dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); /* save the reason code and call our bottom half. */ dev->irq_reason = reason; tasklet_schedule(&dev->isr_tasklet); - out: +out: mmiowb(); spin_unlock(&dev->wl->irq_lock); @@ -3799,7 +3776,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) * setting the status to INITIALIZED, as the interrupt handler * won't care about IRQs then. */ spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ spin_unlock_irqrestore(&wl->irq_lock, flags); b43_synchronize_irq(dev); @@ -3840,7 +3817,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev) /* Start data flow (TX/RX). */ b43_mac_enable(dev); - b43_interrupt_enable(dev, dev->irq_savedstate); + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); /* Start maintainance work */ b43_periodic_tasks_setup(dev); @@ -4003,9 +3980,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) /* IRQ related flags */ dev->irq_reason = 0; memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); - dev->irq_savedstate = B43_IRQ_MASKTEMPLATE; + dev->irq_mask = B43_IRQ_MASKTEMPLATE; if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) - dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR; + dev->irq_mask &= ~B43_IRQ_PHY_TXERR; dev->mac_suspended = 1; -- cgit v1.2.3 From 492301fb5d12e4a77a1010ad2b6f1ed306014123 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 9 Apr 2009 22:14:19 -0500 Subject: rfkill: Fix broken rfkill LED in 2.6.30-rc1 The rfkill system fails to issue a LED trigger event when the rfkill state changes. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/rfkill/rfkill.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index df1269c5ca70..e2d4510623f2 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -96,6 +96,7 @@ static void update_rfkill_state(struct rfkill *rfkill) } mutex_unlock(&rfkill->mutex); } + rfkill_led_trigger(rfkill, rfkill->state); } /** @@ -136,8 +137,9 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, oldstate = rfkill->state; if (rfkill->get_state && !force && - !rfkill->get_state(rfkill->data, &newstate)) + !rfkill->get_state(rfkill->data, &newstate)) { rfkill->state = newstate; + } switch (state) { case RFKILL_STATE_HARD_BLOCKED: @@ -172,6 +174,7 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, if (force || rfkill->state != oldstate) rfkill_uevent(rfkill); + rfkill_led_trigger(rfkill, rfkill->state); return retval; } @@ -204,6 +207,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, mutex_lock(&rfkill->mutex); rfkill_toggle_radio(rfkill, state, 0); mutex_unlock(&rfkill->mutex); + rfkill_led_trigger(rfkill, rfkill->state); } } } @@ -256,6 +260,7 @@ void rfkill_epo(void) RFKILL_STATE_SOFT_BLOCKED; } mutex_unlock(&rfkill_global_mutex); + rfkill_led_trigger(rfkill, rfkill->state); } EXPORT_SYMBOL_GPL(rfkill_epo); @@ -358,6 +363,7 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) rfkill_uevent(rfkill); mutex_unlock(&rfkill->mutex); + rfkill_led_trigger(rfkill, rfkill->state); return 0; } @@ -520,6 +526,7 @@ static int rfkill_resume(struct device *dev) 1); mutex_unlock(&rfkill->mutex); + rfkill_led_trigger(rfkill, rfkill->state); } return 0; -- cgit v1.2.3 From 6dfe9a884fec67070fc7502ad82f7eb328950b72 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 11 Apr 2009 03:58:01 +0200 Subject: p54: utilize all available key slots for decryption offload This patch takes care of outstanding TODOs: /* TODO: some devices have 4 more free slots for rx keys */ Now the driver can utilize all available key slots instead of just 4. Obviously, this helps most in AP/IBSS(/MESH) mode, when we have to use more different keys. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 1 + drivers/net/wireless/p54/p54common.c | 101 +++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index d6354faaa2bc..7fda1a9e263b 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -186,6 +186,7 @@ struct p54_common { /* cryptographic engine information */ u8 privacy_caps; u8 rx_keycache_size; + unsigned long *used_rxkeys; /* LED management */ #ifdef CONFIG_MAC80211_LEDS diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index cb490584cb8e..7bd4fdf83349 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -249,7 +249,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) dev->queues = P54_QUEUE_AC_NUM; } - if (!modparam_nohwcrypt) + if (!modparam_nohwcrypt) { printk(KERN_INFO "%s: cryptographic accelerator " "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(dev->wiphy), @@ -259,6 +259,26 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ? "YES" : "no"); + if (priv->rx_keycache_size) { + /* + * NOTE: + * + * The firmware provides at most 255 (0 - 254) slots + * for keys which are then used to offload decryption. + * As a result the 255 entry (aka 0xff) can be used + * safely by the driver to mark keys that didn't fit + * into the full cache. This trick saves us from + * keeping a extra list for uploaded keys. + */ + + priv->used_rxkeys = kzalloc(BITS_TO_LONGS( + priv->rx_keycache_size), GFP_KERNEL); + + if (!priv->used_rxkeys) + return -ENOMEM; + } + } + return 0; } EXPORT_SYMBOL_GPL(p54_parse_firmware); @@ -2355,61 +2375,84 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, struct p54_common *priv = dev->priv; struct sk_buff *skb; struct p54_keycache *rxkey; + int slot, ret = 0; u8 algo = 0; if (modparam_nohwcrypt) return -EOPNOTSUPP; - if (cmd == DISABLE_KEY) - algo = 0; - else { + mutex_lock(&priv->conf_mutex); + if (cmd == SET_KEY) { switch (key->alg) { case ALG_TKIP: if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | - BR_DESC_PRIV_CAP_TKIP))) - return -EOPNOTSUPP; + BR_DESC_PRIV_CAP_TKIP))) { + ret = -EOPNOTSUPP; + goto out_unlock; + } key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; algo = P54_CRYPTO_TKIPMICHAEL; break; case ALG_WEP: - if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) - return -EOPNOTSUPP; + if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { + ret = -EOPNOTSUPP; + goto out_unlock; + } key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; algo = P54_CRYPTO_WEP; break; case ALG_CCMP: - if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) - return -EOPNOTSUPP; + if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { + ret = -EOPNOTSUPP; + goto out_unlock; + } key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; algo = P54_CRYPTO_AESCCMP; break; default: - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out_unlock; } - } + slot = bitmap_find_free_region(priv->used_rxkeys, + priv->rx_keycache_size, 0); - if (key->keyidx > priv->rx_keycache_size) { - /* - * The device supports the choosen algorithm, but the firmware - * does not provide enough key slots to store all of them. - * So, incoming frames have to be decoded by the mac80211 stack, - * but we can still offload encryption for outgoing frames. - */ + if (slot < 0) { + /* + * The device supports the choosen algorithm, but the + * firmware does not provide enough key slots to store + * all of them. + * But encryption offload for outgoing frames is always + * possible, so we just pretend that the upload was + * successful and do the decryption in software. + */ - return 0; + /* mark the key as invalid. */ + key->hw_key_idx = 0xff; + goto out_unlock; + } + } else { + slot = key->hw_key_idx; + + if (slot == 0xff) { + /* This key was not uploaded into the rx key cache. */ + + goto out_unlock; + } + + bitmap_release_region(priv->used_rxkeys, slot, 0); + algo = 0; } - mutex_lock(&priv->conf_mutex); skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey), - P54_CONTROL_TYPE_RX_KEYCACHE, GFP_ATOMIC); + P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL); if (!skb) { - mutex_unlock(&priv->conf_mutex); - return -ENOMEM; + bitmap_release_region(priv->used_rxkeys, slot, 0); + ret = -ENOSPC; + goto out_unlock; } - /* TODO: some devices have 4 more free slots for rx keys */ rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey)); - rxkey->entry = key->keyidx; + rxkey->entry = slot; rxkey->key_id = key->keyidx; rxkey->key_type = algo; if (sta) @@ -2427,8 +2470,11 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, } priv->tx(dev, skb); + key->hw_key_idx = slot; + +out_unlock: mutex_unlock(&priv->conf_mutex); - return 0; + return ret; } #ifdef CONFIG_P54_LEDS @@ -2662,6 +2708,7 @@ void p54_free_common(struct ieee80211_hw *dev) kfree(priv->iq_autocal); kfree(priv->output_limit); kfree(priv->curve_data); + kfree(priv->used_rxkeys); #ifdef CONFIG_P54_LEDS p54_unregister_leds(dev); -- cgit v1.2.3 From 4312a86b6840bca503603e918996b139fa3293ba Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 11 Apr 2009 03:58:14 +0200 Subject: p54: remove obsolet signal quality calculation The signal quality percentage is now calculated by mac80211 stack. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 7bd4fdf83349..b18fc93a8bce 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -769,8 +769,6 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi); rx_status.noise = priv->noise; - /* XX correct? */ - rx_status.qual = (100 * hdr->rssi) / 127; if (hdr->rate & 0x10) rx_status.flag |= RX_FLAG_SHORTPRE; if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) -- cgit v1.2.3 From 7edfab7adef45a09b459cb7f5957f476108f5e77 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 11 Apr 2009 13:32:46 +0200 Subject: cfg80211: convert mutex assert to macro That will make the various cases where the WARN_ON can happen distinguishable. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/wireless/core.h b/net/wireless/core.h index fcee83a0c9bb..02668b02e331 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -73,10 +73,7 @@ bool wiphy_idx_valid(int wiphy_idx) extern struct mutex cfg80211_mutex; extern struct list_head cfg80211_drv_list; -static inline void assert_cfg80211_lock(void) -{ - WARN_ON(!mutex_is_locked(&cfg80211_mutex)); -} +#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) /* * You can use this to mark a wiphy_idx as not having an associated wiphy. -- cgit v1.2.3 From 7858e07b7ccf1d2fd5898a405c93d022d3f1f42d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 11 Apr 2009 11:25:24 -0500 Subject: b43legacy: Fixes for beaconing This patch ports the beaconing fixes from commit a82d992261f "b43: Beaconing fixes" to b43legacy. Basically it prevents the card from triggering the beacon IRQ over and over again. Signed-off-by: Larry Finger Acked-by: Michael Buesch Tested-by: David Ellingsworth Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 4 ++- drivers/net/wireless/b43legacy/main.c | 47 +++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 4cdde4ad17c0..ad4794a0a327 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -59,7 +59,8 @@ #define B43legacy_MMIO_XMITSTAT_1 0x174 #define B43legacy_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ #define B43legacy_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ - +#define B43legacy_MMIO_TSF_CFP_REP 0x188 +#define B43legacy_MMIO_TSF_CFP_START 0x18C /* 32-bit DMA */ #define B43legacy_MMIO_DMA32_BASE0 0x200 #define B43legacy_MMIO_DMA32_BASE1 0x220 @@ -616,6 +617,7 @@ struct b43legacy_wl { struct sk_buff *current_beacon; bool beacon0_uploaded; bool beacon1_uploaded; + struct work_struct beacon_update_trigger; }; /* Pointers to the firmware data and meta information about it. */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 81dbbc1c591a..4f3f01629465 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1013,7 +1013,8 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, b43legacywarn(dev->wl, "Did not find a valid TIM IE in the " "beacon template packet. AP or IBSS operation " "may be broken.\n"); - } + } else + b43legacydbg(dev->wl, "Updated beacon template\n"); } static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, @@ -1133,6 +1134,27 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, kfree(probe_resp_data); } +static void b43legacy_beacon_update_trigger_work(struct work_struct *work) +{ + struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl, + beacon_update_trigger); + struct b43legacy_wldev *dev; + + mutex_lock(&wl->mutex); + dev = wl->current_dev; + if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) { + /* Force the microcode to trigger the + * beacon update bottom-half IRQ. */ + spin_lock_irq(&wl->irq_lock); + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, + b43legacy_read32(dev, B43legacy_MMIO_MACCMD) + | B43legacy_MACCMD_BEACON0_VALID + | B43legacy_MACCMD_BEACON1_VALID); + spin_unlock_irq(&wl->irq_lock); + } + mutex_unlock(&wl->mutex); +} + /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ static void b43legacy_update_templates(struct b43legacy_wl *wl) @@ -1156,25 +1178,31 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl) wl->current_beacon = beacon; wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; + queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); } static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, u16 beacon_int) { b43legacy_time_lock(dev); - if (dev->dev->id.revision >= 3) - b43legacy_write32(dev, 0x188, (beacon_int << 16)); - else { + if (dev->dev->id.revision >= 3) { + b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP, + (beacon_int << 16)); + b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START, + (beacon_int << 10)); + } else { b43legacy_write16(dev, 0x606, (beacon_int >> 6)); b43legacy_write16(dev, 0x610, beacon_int); } b43legacy_time_unlock(dev); + b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int); } static void handle_irq_beacon(struct b43legacy_wldev *dev) { struct b43legacy_wl *wl = dev->wl; u32 cmd; + u32 beacon0_valid, beacon1_valid; if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) return; @@ -1182,7 +1210,11 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) /* This is the bottom half of the asynchronous beacon update. */ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) { + beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); + beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID); + cmd &= ~(B43legacy_MACCMD_BEACON0_VALID | B43legacy_MACCMD_BEACON1_VALID); + + if (!beacon0_valid) { if (!wl->beacon0_uploaded) { b43legacy_write_beacon_template(dev, 0x68, B43legacy_SHM_SH_BTL0, @@ -1193,8 +1225,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) wl->beacon0_uploaded = 1; } cmd |= B43legacy_MACCMD_BEACON0_VALID; - } - if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) { + } else if (!beacon1_valid) { if (!wl->beacon1_uploaded) { b43legacy_write_beacon_template(dev, 0x468, B43legacy_SHM_SH_BTL1, @@ -3435,6 +3466,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) struct b43legacy_wldev *dev = wl->current_dev; b43legacy_rfkill_exit(dev); + cancel_work_sync(&(wl->beacon_update_trigger)); mutex_lock(&wl->mutex); if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) @@ -3766,6 +3798,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) spin_lock_init(&wl->leds_lock); mutex_init(&wl->mutex); INIT_LIST_HEAD(&wl->devlist); + INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); ssb_set_devtypedata(dev, wl); b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); -- cgit v1.2.3 From 2d1f96dd90a20c25243cc3b13e9f21d72f00aba0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 11 Apr 2009 11:26:01 -0500 Subject: b43legacy: Clean up beacon IRQ This patch ports commit c97a4ccc1fad35d3 "b43: Fix beacon BH update" to b43legacy. It fixes beacon updating in the bottomhalf. In case the device is busy, we will defer to later in the IRQ handler. Signed-off-by: Larry Finger Acked-by: Michael Buesch Tested-by: David Ellingsworth Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 2 +- drivers/net/wireless/b43legacy/main.c | 164 ++++++++++++++++++++--------- drivers/net/wireless/b43legacy/xmit.c | 2 +- drivers/net/wireless/b43legacy/xmit.h | 4 +- 4 files changed, 121 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index ad4794a0a327..da59ef02b6ef 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -259,7 +259,6 @@ #define B43legacy_IRQ_ALL 0xFFFFFFFF #define B43legacy_IRQ_MASKTEMPLATE (B43legacy_IRQ_MAC_SUSPENDED | \ - B43legacy_IRQ_BEACON | \ B43legacy_IRQ_TBTT_INDI | \ B43legacy_IRQ_ATIM_END | \ B43legacy_IRQ_PMQ | \ @@ -617,6 +616,7 @@ struct b43legacy_wl { struct sk_buff *current_beacon; bool beacon0_uploaded; bool beacon1_uploaded; + bool beacon_templates_virgin; /* Never wrote the templates? */ struct work_struct beacon_update_trigger; }; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 4f3f01629465..ee202b4f77b5 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -955,23 +955,54 @@ static void b43legacy_write_template_common(struct b43legacy_wldev *dev, size + sizeof(struct b43legacy_plcp_hdr6)); } +/* Convert a b43legacy antenna number value to the PHY TX control value. */ +static u16 b43legacy_antenna_to_phyctl(int antenna) +{ + switch (antenna) { + case B43legacy_ANTENNA0: + return B43legacy_TX4_PHY_ANT0; + case B43legacy_ANTENNA1: + return B43legacy_TX4_PHY_ANT1; + } + return B43legacy_TX4_PHY_ANTLAST; +} + static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset) { unsigned int i, len, variable_len; const struct ieee80211_mgmt *bcn; const u8 *ie; bool tim_found = 0; + unsigned int rate; + u16 ctl; + int antenna; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); len = min((size_t)dev->wl->current_beacon->len, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); + rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); + /* Write the PHY TX control parameters. */ + antenna = B43legacy_ANTENNA_DEFAULT; + antenna = b43legacy_antenna_to_phyctl(antenna); + ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_BEACPHYCTL); + /* We can't send beacons with short preamble. Would get PHY errors. */ + ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL; + ctl &= ~B43legacy_TX4_PHY_ANT; + ctl &= ~B43legacy_TX4_PHY_ENC; + ctl |= antenna; + ctl |= B43legacy_TX4_PHY_ENC_CCK; + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_BEACPHYCTL, ctl); + /* Find the position of the TIM and the DTIM_period value * and write them to SHM. */ ie = bcn->u.beacon.variable; @@ -1026,7 +1057,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, __le16 dur; plcp.data = 0; - b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate); + b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, size, @@ -1130,10 +1161,82 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); b43legacy_write_template_common(dev, probe_resp_data, size, ram_offset, - shm_size_offset, rate->bitrate); + shm_size_offset, rate->hw_value); kfree(probe_resp_data); } +static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev) +{ + struct b43legacy_wl *wl = dev->wl; + + if (wl->beacon0_uploaded) + return; + b43legacy_write_beacon_template(dev, 0x68, 0x18); + /* FIXME: Probe resp upload doesn't really belong here, + * but we don't use that feature anyway. */ + b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, + &__b43legacy_ratetable[3]); + wl->beacon0_uploaded = 1; +} + +static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev) +{ + struct b43legacy_wl *wl = dev->wl; + + if (wl->beacon1_uploaded) + return; + b43legacy_write_beacon_template(dev, 0x468, 0x1A); + wl->beacon1_uploaded = 1; +} + +static void handle_irq_beacon(struct b43legacy_wldev *dev) +{ + struct b43legacy_wl *wl = dev->wl; + u32 cmd, beacon0_valid, beacon1_valid; + + if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) + return; + + /* This is the bottom half of the asynchronous beacon update. */ + + /* Ignore interrupt in the future. */ + dev->irq_savedstate &= ~B43legacy_IRQ_BEACON; + + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); + beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID); + + /* Schedule interrupt manually, if busy. */ + if (beacon0_valid && beacon1_valid) { + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON); + dev->irq_savedstate |= B43legacy_IRQ_BEACON; + return; + } + + if (unlikely(wl->beacon_templates_virgin)) { + /* We never uploaded a beacon before. + * Upload both templates now, but only mark one valid. */ + wl->beacon_templates_virgin = 0; + b43legacy_upload_beacon0(dev); + b43legacy_upload_beacon1(dev); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON0_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + } else { + if (!beacon0_valid) { + b43legacy_upload_beacon0(dev); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON0_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + } else if (!beacon1_valid) { + b43legacy_upload_beacon1(dev); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON1_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); + } + } +} + static void b43legacy_beacon_update_trigger_work(struct work_struct *work) { struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl, @@ -1143,13 +1246,14 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work) mutex_lock(&wl->mutex); dev = wl->current_dev; if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) { - /* Force the microcode to trigger the - * beacon update bottom-half IRQ. */ spin_lock_irq(&wl->irq_lock); - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - b43legacy_read32(dev, B43legacy_MMIO_MACCMD) - | B43legacy_MACCMD_BEACON0_VALID - | B43legacy_MACCMD_BEACON1_VALID); + /* update beacon right away or defer to irq */ + dev->irq_savedstate = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); + handle_irq_beacon(dev); + /* The handler might have updated the IRQ mask. */ + b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, + dev->irq_savedstate); + mmiowb(); spin_unlock_irq(&wl->irq_lock); } mutex_unlock(&wl->mutex); @@ -1198,45 +1302,6 @@ static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int); } -static void handle_irq_beacon(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - u32 cmd; - u32 beacon0_valid, beacon1_valid; - - if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) - return; - - /* This is the bottom half of the asynchronous beacon update. */ - - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); - beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID); - cmd &= ~(B43legacy_MACCMD_BEACON0_VALID | B43legacy_MACCMD_BEACON1_VALID); - - if (!beacon0_valid) { - if (!wl->beacon0_uploaded) { - b43legacy_write_beacon_template(dev, 0x68, - B43legacy_SHM_SH_BTL0, - B43legacy_CCK_RATE_1MB); - b43legacy_write_probe_resp_template(dev, 0x268, - B43legacy_SHM_SH_PRTLEN, - &__b43legacy_ratetable[3]); - wl->beacon0_uploaded = 1; - } - cmd |= B43legacy_MACCMD_BEACON0_VALID; - } else if (!beacon1_valid) { - if (!wl->beacon1_uploaded) { - b43legacy_write_beacon_template(dev, 0x468, - B43legacy_SHM_SH_BTL1, - B43legacy_CCK_RATE_1MB); - wl->beacon1_uploaded = 1; - } - cmd |= B43legacy_MACCMD_BEACON1_VALID; - } - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); -} - static void handle_irq_ucode_debug(struct b43legacy_wldev *dev) { } @@ -3429,6 +3494,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) memset(wl->bssid, 0, ETH_ALEN); memset(wl->mac_addr, 0, ETH_ALEN); wl->filter_flags = 0; + wl->beacon0_uploaded = 0; + wl->beacon1_uploaded = 0; + wl->beacon_templates_virgin = 1; mutex_lock(&wl->mutex); diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 12fca99f7578..b8e39dd06e99 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -274,7 +274,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, /* PHY TX Control word */ if (rate_ofdm) - phy_ctl |= B43legacy_TX4_PHY_OFDM; + phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM; if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; switch (info->antenna_sel_tx) { diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index 62e09d02788f..91633087a20b 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h @@ -67,7 +67,9 @@ struct b43legacy_txhdr_fw3 { #define B43legacy_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */ /* PHY TX control word */ -#define B43legacy_TX4_PHY_OFDM 0x0001 /* Data frame rate type */ +#define B43legacy_TX4_PHY_ENC 0x0003 /* Data frame encoding */ +#define B43legacy_TX4_PHY_ENC_CCK 0x0000 /* CCK */ +#define B43legacy_TX4_PHY_ENC_OFDM 0x0001 /* Data frame rate type */ #define B43legacy_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ #define B43legacy_TX4_PHY_ANT 0x03C0 /* Antenna selection */ #define B43legacy_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */ -- cgit v1.2.3 From a89bff9a78b2bf51e21a961b473b5be94b22f12e Mon Sep 17 00:00:00 2001 From: Steven Luo Date: Sun, 12 Apr 2009 02:57:54 -0700 Subject: ath9k: reset after PCI FATAL/PERR interrupts ath9k_hw_getisr() doesn't appear to set anything in the status mask for PCI FATAL or PERR interrupts (AR_INTR_SYNC_HOST1_FATAL/PERR), which the open-source HAL seems to do. This means that the card isn't reset after these interrupts. This patch seems to fix a problem where the wireless drops out with an "ath9k: received PCI FATAL interrupt" in dmesg after some time; the hardware is an AR5416 in an ASUS WL-500W running 2.6.28.7 (OpenWRT) and compat-wireless 2009-03-31. Signed-off-by: Steven Luo Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 24299e65fdcf..9cb85b0e9851 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2976,6 +2976,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) DPRINTF(ah->ah_sc, ATH_DBG_ANY, "received PCI PERR interrupt\n"); } + *masked |= ATH9K_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, -- cgit v1.2.3 From d2f5b3a6778ae86fd93cb01ccac16aa0b079e441 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:25 +0530 Subject: ath9k: Handle ASPM properly for RFKILL Radio enable/disable have to handle ASPM state properly. This patch fixes it. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8b6a7ea4e59b..1a9bf7ece4a5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1089,10 +1089,10 @@ void ath_radio_enable(struct ath_softc *sc) int r; ath9k_ps_wakeup(sc); - spin_lock_bh(&sc->sc_resetlock); + ath9k_hw_configpcipowersave(ah, 0); + spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, false); - if (r) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset channel %u (%uMhz) ", @@ -1154,6 +1154,7 @@ void ath_radio_disable(struct ath_softc *sc) spin_unlock_bh(&sc->sc_resetlock); ath9k_hw_phy_disable(ah); + ath9k_hw_configpcipowersave(ah, 1); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); ath9k_ps_restore(sc); } -- cgit v1.2.3 From 675902ef822c114c0dac17ed10eed43eb8f5c9ec Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:34 +0530 Subject: ath9k: Fix memleak on TX DMA failure The driver-specific region has to be freed in case of a DMA mapping failure. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 628b780d8844..faf2cab49ea3 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1572,8 +1572,9 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_CONFIG, - "dma_mapping_error() on TX\n"); + kfree(tx_info_priv); + tx_info->rate_driver_data[0] = NULL; + DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); return -ENOMEM; } -- cgit v1.2.3 From 9c07a7777f44c7e39accec5ad8c4293d6a9b2a47 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:36 +0530 Subject: ath9k: Fix bug in scan termination A full HW reset needs to be done on termination of a scan run. Not setting SC_OP_FULL_RESET resulted in doing a fast channel change. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1a9bf7ece4a5..b2d129f50339 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2749,6 +2749,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) mutex_lock(&sc->mutex); aphy->state = ATH_WIPHY_ACTIVE; sc->sc_flags &= ~SC_OP_SCANNING; + sc->sc_flags |= SC_OP_FULL_RESET; mutex_unlock(&sc->mutex); } -- cgit v1.2.3 From 822b0dfc135cf205379ea62aae7a5b393811b238 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:38 +0530 Subject: ath9k: Remove unused channel flags Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 5c4127e6c1c6..7e37570608bc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -266,13 +266,6 @@ enum ath9k_int { #define CHANNEL_HT40PLUS 0x20000 #define CHANNEL_HT40MINUS 0x40000 -#define CHANNEL_INTERFERENCE 0x01 -#define CHANNEL_DFS 0x02 -#define CHANNEL_4MS_LIMIT 0x04 -#define CHANNEL_DFS_CLEAR 0x08 -#define CHANNEL_DISALLOW_ADHOC 0x10 -#define CHANNEL_PER_11D_ADHOC 0x20 - #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) @@ -303,10 +296,6 @@ struct ath9k_channel { int16_t rawNoiseFloor; }; -#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ - (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ - (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ - (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ @@ -314,7 +303,6 @@ struct ath9k_channel { #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) -#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) #define IS_CHAN_A_5MHZ_SPACED(_c) \ -- cgit v1.2.3 From db2f63f60a087ed29ae04310c1076c61f77a5d20 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:41 +0530 Subject: ath9k: Fix bug in checking HT flag The operating HT mode is stored in chanmode and not channelFlags. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e2d62e97131c..d0b675562d40 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -883,7 +883,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - if (chan->channelFlags & CHANNEL_HT20) { + if (IS_CHAN_HT20(chan)) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -- cgit v1.2.3 From a451aa66dcb14efcb7addf1d8edcac8df76a97b6 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:43 +0530 Subject: ath9k: Fix bug in determining calibration support ADC gain calibration has to be done for all non 2GHZ-HT20 channels. Regression from "ath9k: use ieee80211_conf on ath9k_hw_iscal_supported()" Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index d0b675562d40..3195c0b9a6a7 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -284,8 +284,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hw *ah, return true; case ADC_GAIN_CAL: case ADC_DC_CAL: - if (conf->channel->band == IEEE80211_BAND_5GHZ && - conf_is_ht20(conf)) + if (!(conf->channel->band == IEEE80211_BAND_2GHZ && + conf_is_ht20(conf))) return true; break; } -- cgit v1.2.3 From 415f738ecf41b427921b503ecfd427e26f89dc23 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:46 +0530 Subject: ath9k: Initialize ANI timers The various ANI timers have to be initialized properly when starting the calibration timer. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index b2d129f50339..9564b73ded51 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -407,6 +407,18 @@ set_timer: mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); } +static void ath_start_ani(struct ath_softc *sc) +{ + unsigned long timestamp = jiffies_to_msecs(jiffies); + + sc->ani.longcal_timer = timestamp; + sc->ani.shortcal_timer = timestamp; + sc->ani.checkani_timer = timestamp; + + mod_timer(&sc->ani.timer, + jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); +} + /* * Update tx/rx chainmask. For legacy association, * hard code chainmask to 1x1, for 11n association, use @@ -911,9 +923,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; - /* Start ANI */ - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + ath_start_ani(sc); } else { DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); sc->curaid = 0; @@ -2239,12 +2249,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - if (conf->type == NL80211_IFTYPE_AP) { - /* TODO: is this a suitable place to start ANI for AP mode? */ - /* Start ANI */ - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); - } + if (conf->type == NL80211_IFTYPE_AP) + ath_start_ani(sc); out: mutex_unlock(&sc->mutex); -- cgit v1.2.3 From 379f04407c92d84f2506385b66fb9fc89ecd96c3 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:48 +0530 Subject: ath9k: Cleanup calibration interface This patch cleans up the functions dealing with calibration, using proper return values. ath9k_hw_per_calibration(), ath9k_hw_calibrate now return bool values instead of setting error values in the function arguments. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 27 +++++++++++++-------------- drivers/net/wireless/ath/ath9k/calib.h | 3 +-- drivers/net/wireless/ath/ath9k/main.c | 32 ++++++++++---------------------- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 3195c0b9a6a7..a0661bb96723 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -238,13 +238,12 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah, ah->cal_samples = 0; } -static void ath9k_hw_per_calibration(struct ath_hw *ah, +static bool ath9k_hw_per_calibration(struct ath_hw *ah, struct ath9k_channel *ichan, u8 rxchainmask, - struct hal_cal_list *currCal, - bool *isCalDone) + struct hal_cal_list *currCal) { - *isCalDone = false; + bool iscaldone = false; if (currCal->calState == CAL_RUNNING) { if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & @@ -263,7 +262,7 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah, currCal->calData->calPostProc(ah, numChains); ichan->CalValid |= currCal->calData->calType; currCal->calState = CAL_DONE; - *isCalDone = true; + iscaldone = true; } else { ath9k_hw_setup_calibration(ah, currCal); } @@ -271,6 +270,8 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah, } else if (!(ichan->CalValid & currCal->calData->calType)) { ath9k_hw_reset_calibration(ah, currCal); } + + return iscaldone; } /* Assumes you are talking about the currently configured channel */ @@ -841,23 +842,21 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) } bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone) + u8 rxchainmask, bool longcal) { + bool iscaldone = true; struct hal_cal_list *currCal = ah->cal_list_curr; - *isCalDone = true; - if (currCal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { - ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, - isCalDone); - if (*isCalDone) { + iscaldone = ath9k_hw_per_calibration(ah, chan, + rxchainmask, currCal); + if (iscaldone) { ah->cal_list_curr = currCal = currCal->calNext; if (currCal->calState == CAL_WAITING) { - *isCalDone = false; + iscaldone = false; ath9k_hw_reset_calibration(ah, currCal); } } @@ -877,7 +876,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, chan->channelFlags &= ~CHANNEL_CW_INT; } - return true; + return iscaldone; } static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 1c74bd50700d..ac71ed966a1b 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -116,8 +116,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal, - bool *isCalDone); + u8 rxchainmask, bool longcal); bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9564b73ded51..8bf2bf36fd6d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -367,28 +367,16 @@ static void ath_ani_calibrate(unsigned long data) /* Perform calibration if necessary */ if (longcal || shortcal) { - bool iscaldone = false; - - if (ath9k_hw_calibrate(ah, ah->curchan, - sc->rx_chainmask, longcal, - &iscaldone)) { - if (longcal) - sc->ani.noise_floor = - ath9k_hw_getchan_noise(ah, - ah->curchan); - - DPRINTF(sc, ATH_DBG_ANI, - "calibrate chan %u/%x nf: %d\n", - ah->curchan->channel, - ah->curchan->channelFlags, - sc->ani.noise_floor); - } else { - DPRINTF(sc, ATH_DBG_ANY, - "calibrate chan %u/%x failed\n", - ah->curchan->channel, - ah->curchan->channelFlags); - } - sc->ani.caldone = iscaldone; + sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, + sc->rx_chainmask, longcal); + + if (longcal) + sc->ani.noise_floor = ath9k_hw_getchan_noise(ah, + ah->curchan); + + DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n", + ah->curchan->channel, ah->curchan->channelFlags, + sc->ani.noise_floor); } } -- cgit v1.2.3 From cbfe946860ffc718c5d99a6b740e33ac95fe8b8d Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:56 +0530 Subject: ath9k: Use a consistent naming convention This patch replaces old 'hal_' prefixes with 'ath9k_'. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 28 ++++++++++++++-------------- drivers/net/wireless/ath/ath9k/calib.h | 30 +++++++++++++++--------------- drivers/net/wireless/ath/ath9k/hw.h | 16 ++++++++-------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index a0661bb96723..67375adf23c0 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -186,7 +186,7 @@ static bool getNoiseFloorThresh(struct ath_hw *ah, } static void ath9k_hw_setup_calibration(struct ath_hw *ah, - struct hal_cal_list *currCal) + struct ath9k_cal_list *currCal) { REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, @@ -220,7 +220,7 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah, } static void ath9k_hw_reset_calibration(struct ath_hw *ah, - struct hal_cal_list *currCal) + struct ath9k_cal_list *currCal) { int i; @@ -241,7 +241,7 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah, static bool ath9k_hw_per_calibration(struct ath_hw *ah, struct ath9k_channel *ichan, u8 rxchainmask, - struct hal_cal_list *currCal) + struct ath9k_cal_list *currCal) { bool iscaldone = false; @@ -276,7 +276,7 @@ static bool ath9k_hw_per_calibration(struct ath_hw *ah, /* Assumes you are talking about the currently configured channel */ static bool ath9k_hw_iscal_supported(struct ath_hw *ah, - enum hal_cal_types calType) + enum ath9k_cal_types calType) { struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; @@ -499,7 +499,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) { u32 iOddMeasOffset, iEvenMeasOffset, val, i; int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; - const struct hal_percal_data *calData = + const struct ath9k_percal_data *calData = ah->cal_list_curr->calData; u32 numSamples = (1 << (calData->calCountMax + 5)) * calData->calNumSamples; @@ -556,7 +556,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) bool ath9k_hw_reset_calvalid(struct ath_hw *ah) { struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct hal_cal_list *currCal = ah->cal_list_curr; + struct ath9k_cal_list *currCal = ah->cal_list_curr; if (!ah->curchan) return true; @@ -845,7 +845,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, bool longcal) { bool iscaldone = true; - struct hal_cal_list *currCal = ah->cal_list_curr; + struct ath9k_cal_list *currCal = ah->cal_list_curr; if (currCal && (currCal->calState == CAL_RUNNING || @@ -1008,49 +1008,49 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, return true; } -const struct hal_percal_data iq_cal_multi_sample = { +const struct ath9k_percal_data iq_cal_multi_sample = { IQ_MISMATCH_CAL, MAX_CAL_SAMPLES, PER_MIN_LOG_COUNT, ath9k_hw_iqcal_collect, ath9k_hw_iqcalibrate }; -const struct hal_percal_data iq_cal_single_sample = { +const struct ath9k_percal_data iq_cal_single_sample = { IQ_MISMATCH_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ath9k_hw_iqcal_collect, ath9k_hw_iqcalibrate }; -const struct hal_percal_data adc_gain_cal_multi_sample = { +const struct ath9k_percal_data adc_gain_cal_multi_sample = { ADC_GAIN_CAL, MAX_CAL_SAMPLES, PER_MIN_LOG_COUNT, ath9k_hw_adc_gaincal_collect, ath9k_hw_adc_gaincal_calibrate }; -const struct hal_percal_data adc_gain_cal_single_sample = { +const struct ath9k_percal_data adc_gain_cal_single_sample = { ADC_GAIN_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ath9k_hw_adc_gaincal_collect, ath9k_hw_adc_gaincal_calibrate }; -const struct hal_percal_data adc_dc_cal_multi_sample = { +const struct ath9k_percal_data adc_dc_cal_multi_sample = { ADC_DC_CAL, MAX_CAL_SAMPLES, PER_MIN_LOG_COUNT, ath9k_hw_adc_dccal_collect, ath9k_hw_adc_dccal_calibrate }; -const struct hal_percal_data adc_dc_cal_single_sample = { +const struct ath9k_percal_data adc_dc_cal_single_sample = { ADC_DC_CAL, MIN_CAL_SAMPLES, PER_MAX_LOG_COUNT, ath9k_hw_adc_dccal_collect, ath9k_hw_adc_dccal_calibrate }; -const struct hal_percal_data adc_init_dc_cal = { +const struct ath9k_percal_data adc_init_dc_cal = { ADC_DC_INIT_CAL, MIN_CAL_SAMPLES, INIT_LOG_COUNT, diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index ac71ed966a1b..fe5367f14148 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -17,13 +17,13 @@ #ifndef CALIB_H #define CALIB_H -extern const struct hal_percal_data iq_cal_multi_sample; -extern const struct hal_percal_data iq_cal_single_sample; -extern const struct hal_percal_data adc_gain_cal_multi_sample; -extern const struct hal_percal_data adc_gain_cal_single_sample; -extern const struct hal_percal_data adc_dc_cal_multi_sample; -extern const struct hal_percal_data adc_dc_cal_single_sample; -extern const struct hal_percal_data adc_init_dc_cal; +extern const struct ath9k_percal_data iq_cal_multi_sample; +extern const struct ath9k_percal_data iq_cal_single_sample; +extern const struct ath9k_percal_data adc_gain_cal_multi_sample; +extern const struct ath9k_percal_data adc_gain_cal_single_sample; +extern const struct ath9k_percal_data adc_dc_cal_multi_sample; +extern const struct ath9k_percal_data adc_dc_cal_single_sample; +extern const struct ath9k_percal_data adc_init_dc_cal; #define AR_PHY_CCA_MAX_GOOD_VALUE -85 #define AR_PHY_CCA_MAX_HIGH_VALUE -62 @@ -67,14 +67,14 @@ struct ar5416IniArray { } \ } while (0) -enum hal_cal_types { +enum ath9k_cal_types { ADC_DC_INIT_CAL = 0x1, ADC_GAIN_CAL = 0x2, ADC_DC_CAL = 0x4, IQ_MISMATCH_CAL = 0x8 }; -enum hal_cal_state { +enum ath9k_cal_state { CAL_INACTIVE, CAL_WAITING, CAL_RUNNING, @@ -87,18 +87,18 @@ enum hal_cal_state { #define PER_MIN_LOG_COUNT 2 #define PER_MAX_LOG_COUNT 10 -struct hal_percal_data { - enum hal_cal_types calType; +struct ath9k_percal_data { + enum ath9k_cal_types calType; u32 calNumSamples; u32 calCountMax; void (*calCollect) (struct ath_hw *); void (*calPostProc) (struct ath_hw *, u8); }; -struct hal_cal_list { - const struct hal_percal_data *calData; - enum hal_cal_state calState; - struct hal_cal_list *calNext; +struct ath9k_cal_list { + const struct ath9k_percal_data *calData; + enum ath9k_cal_state calState; + struct ath9k_cal_list *calNext; }; struct ath9k_nfcal_hist { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7e37570608bc..ab3412672e36 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -436,14 +436,14 @@ struct ath_hw { enum ath9k_ant_setting diversity_control; /* Calibration */ - enum hal_cal_types supp_cals; - struct hal_cal_list iq_caldata; - struct hal_cal_list adcgain_caldata; - struct hal_cal_list adcdc_calinitdata; - struct hal_cal_list adcdc_caldata; - struct hal_cal_list *cal_list; - struct hal_cal_list *cal_list_last; - struct hal_cal_list *cal_list_curr; + enum ath9k_cal_types supp_cals; + struct ath9k_cal_list iq_caldata; + struct ath9k_cal_list adcgain_caldata; + struct ath9k_cal_list adcdc_calinitdata; + struct ath9k_cal_list adcdc_caldata; + struct ath9k_cal_list *cal_list; + struct ath9k_cal_list *cal_list_last; + struct ath9k_cal_list *cal_list_curr; #define totalPowerMeasI meas0.unsign #define totalPowerMeasQ meas1.unsign #define totalIqCorrMeas meas2.sign -- cgit v1.2.3 From 04d19ddd254b404703151ab25aa5041e50ff40f7 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:56:59 +0530 Subject: ath9k: Fix bug in calibration initialization This patch fixes a bug in ath9k_hw_init_cal() where the wrong calibration was being done for non-AR9285 chipsets. Also add a few helpful comments. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 61 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 67375adf23c0..08f690279789 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -918,83 +918,66 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) return true; } -bool ath9k_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan) +bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { if (!ar9285_clc(ah, chan)) return false; - } else if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); + } else { + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + } - /* Kick off the cal */ + /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); + REG_READ(ah, AR_PHY_AGC_CONTROL) | + AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, - AH_WAIT_TIMEOUT)) { + /* Poll for offset calibration complete */ + if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, + 0, AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration failed to complete in 1ms; " "noisy environment?\n"); return false; } - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - } - - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); - - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; " - "noisy environment?\n"); - return false; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + if (AR_SREV_9280_10_OR_LATER(ah)) { + REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + } } /* Do PA Calibration */ if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah); - /* Do NF Calibration */ + /* Do NF Calibration after DC offset and other calibrations */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_NF); + REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + /* Enable IQ, ADC Gain and ADC DC offset CALs */ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); + "enabling ADC Gain Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); + "enabling ADC DC Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { INIT_CAL(&ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); + "enabling IQ Calibration.\n"); } ah->cal_list_curr = ah->cal_list; -- cgit v1.2.3 From 386aeacfa8912e1accffc47e30ffe0c0ecfe71e5 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 13 Apr 2009 21:57:01 +0530 Subject: ath9k: Remove CHANNEL_CW_INT handling in ath9k_hw_calibrate It is already handled properly in ath9k_hw_getnf. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 08f690279789..a197041d76b5 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -871,9 +871,6 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_getnf(ah, chan); ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah); - - if (chan->channelFlags & CHANNEL_CW_INT) - chan->channelFlags &= ~CHANNEL_CW_INT; } return iscaldone; -- cgit v1.2.3 From 06bfd0d3dbe965de4f60079955cca19d7e853c60 Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Mon, 13 Apr 2009 21:54:27 +0200 Subject: rtl8187: Remove the "8187B chip detected" message when probing RTL8187B cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This message appears to be nothing more than a leftover of the experimental-8187B era. Also, we print the HW type in the hwaddr line, making this message reduntant. And it's definitely not important enough to be a KERN_WARNING. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index fd81884b9c7d..d6d4001812a7 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1470,9 +1470,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr >> 8; } - if (priv->is_rtl8187b) - printk(KERN_WARNING "rtl8187: 8187B chip detected.\n"); - /* * XXX: Once this driver supports anything that requires * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ. -- cgit v1.2.3 From a1c555802a62c845520d2486d783c9bb1d5e68a9 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 14 Apr 2009 22:11:20 +0200 Subject: ath: add module information This patch adds licensing, author information and a description to the module. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/Makefile | 3 +-- drivers/net/wireless/ath/main.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/ath/main.c diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index a005b919233f..4bb0132ada37 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -3,5 +3,4 @@ obj-$(CONFIG_ATH9K) += ath9k/ obj-$(CONFIG_AR9170_USB) += ar9170/ obj-$(CONFIG_ATH_COMMON) += ath.o -ath-objs := regd.o - +ath-objs := main.o regd.o diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c new file mode 100644 index 000000000000..9949b11cb151 --- /dev/null +++ b/drivers/net/wireless/ath/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 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 +#include + +MODULE_AUTHOR("Atheros Communications"); +MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards."); +MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From f2753ddbadb0873a98421415882318251bbd9eaa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 14 Apr 2009 10:09:24 +0200 Subject: mac80211: add hardware restart function Some hardware defects may require the hardware to be re-initialised completely from scratch. Drivers would need much information (for instance the current MAC address, crypto keys, beaconing information, etc.) stored duplicated from mac80211 to be able to do this, so let mac80211 help them. The new ieee80211_restart_hw() function requires the same code as resuming, so move that code into a new ieee80211_reconfig() function in util.c and leave only the suspend code in pm.c. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 14 ++++++ net/mac80211/ieee80211_i.h | 13 ++++- net/mac80211/main.c | 24 +++++++++ net/mac80211/pm.c | 110 ++---------------------------------------- net/mac80211/util.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 107 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2c6f976831b5..a593bedcfeda 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1575,6 +1575,20 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw); */ void ieee80211_free_hw(struct ieee80211_hw *hw); +/** + * ieee80211_restart_hw - restart hardware completely + * + * Call this function when the hardware was restarted for some reason + * (hardware error, ...) and the driver is unable to restore its state + * by itself. mac80211 assumes that at this point the driver/hardware + * is completely uninitialised and stopped, it starts the process by + * calling the ->start() operation. The driver will need to reset all + * internal state that it has prior to calling this function. + * + * @hw: the hardware to restart + */ +void ieee80211_restart_hw(struct ieee80211_hw *hw); + /* trick to avoid symbol clashes with the ieee80211 subsystem */ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_rx_status *status); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cb80a80504e6..13d6f890ced4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -748,6 +748,8 @@ struct ieee80211_local { int user_power_level; /* in dBm */ int power_constr_level; /* in dBm */ + struct work_struct restart_work; + #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { struct dentry *rcdir; @@ -1036,15 +1038,22 @@ void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, u16 capab_info, u8 *pwr_constr_elem, u8 pwr_constr_elem_len); -/* Suspend/resume */ +/* Suspend/resume and hw reconfiguration */ +int ieee80211_reconfig(struct ieee80211_local *local); + #ifdef CONFIG_PM int __ieee80211_suspend(struct ieee80211_hw *hw); -int __ieee80211_resume(struct ieee80211_hw *hw); + +static inline int __ieee80211_resume(struct ieee80211_hw *hw) +{ + return ieee80211_reconfig(hw_to_local(hw)); +} #else static inline int __ieee80211_suspend(struct ieee80211_hw *hw) { return 0; } + static inline int __ieee80211_resume(struct ieee80211_hw *hw) { return 0; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c1145be72da4..80c0e28bf549 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -696,6 +696,28 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) } EXPORT_SYMBOL(ieee80211_tx_status); +static void ieee80211_restart_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, restart_work); + + rtnl_lock(); + ieee80211_reconfig(local); + rtnl_unlock(); +} + +void ieee80211_restart_hw(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + + /* use this reason, __ieee80211_resume will unblock it */ + ieee80211_stop_queues_by_reason(hw, + IEEE80211_QUEUE_STOP_REASON_SUSPEND); + + schedule_work(&local->restart_work); +} +EXPORT_SYMBOL(ieee80211_restart_hw); + struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops) { @@ -768,6 +790,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); + INIT_WORK(&local->restart_work, ieee80211_restart_work); + INIT_WORK(&local->dynamic_ps_enable_work, ieee80211_dynamic_ps_enable_work); INIT_WORK(&local->dynamic_ps_disable_work, diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 2b4c95cd9daf..b38986c9deef 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -72,108 +72,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) return 0; } -int __ieee80211_resume(struct ieee80211_hw *hw) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_init_conf conf; - struct sta_info *sta; - unsigned long flags; - int res; - - /* restart hardware */ - if (local->open_count) { - res = local->ops->start(hw); - - ieee80211_led_radio(local, hw->conf.radio_enabled); - } - - /* add interfaces */ - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_MONITOR && - netif_running(sdata->dev)) { - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->dev->dev_addr; - res = local->ops->add_interface(hw, &conf); - } - } - - /* add STAs back */ - if (local->ops->sta_notify) { - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(sta, &local->sta_list, list) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - - local->ops->sta_notify(hw, &sdata->vif, - STA_NOTIFY_ADD, &sta->sta); - } - spin_unlock_irqrestore(&local->sta_lock, flags); - } - - /* Clear Suspend state so that ADDBA requests can be processed */ - - rcu_read_lock(); - - if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { - list_for_each_entry_rcu(sta, &local->sta_list, list) { - clear_sta_flags(sta, WLAN_STA_SUSPEND); - } - } - - rcu_read_unlock(); - - /* setup RTS threshold */ - if (local->ops->set_rts_threshold) - local->ops->set_rts_threshold(hw, local->rts_threshold); - - /* reconfigure hardware */ - ieee80211_hw_config(local, ~0); - - netif_addr_lock_bh(local->mdev); - ieee80211_configure_filter(local); - netif_addr_unlock_bh(local->mdev); - - /* Finally also reconfigure all the BSS information */ - list_for_each_entry(sdata, &local->interfaces, list) { - u32 changed = ~0; - if (!netif_running(sdata->dev)) - continue; - switch (sdata->vif.type) { - case NL80211_IFTYPE_STATION: - /* disable beacon change bits */ - changed &= ~IEEE80211_IFCC_BEACON; - /* fall through */ - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - WARN_ON(ieee80211_if_config(sdata, changed)); - ieee80211_bss_info_change_notify(sdata, ~0); - break; - case NL80211_IFTYPE_WDS: - break; - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_MONITOR: - /* ignore virtual */ - break; - case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: - WARN_ON(1); - break; - } - } - - /* add back keys */ - list_for_each_entry(sdata, &local->interfaces, list) - if (netif_running(sdata->dev)) - ieee80211_enable_keys(sdata); - - ieee80211_wake_queues_by_reason(hw, - IEEE80211_QUEUE_STOP_REASON_SUSPEND); - - return 0; -} +/* + * __ieee80211_resume() is a static inline which just calls + * ieee80211_reconfig(), which is also needed for hardware + * hang/firmware failure/etc. recovery. + */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1ff83532120f..b361e2acfce9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -28,6 +28,7 @@ #include "rate.h" #include "mesh.h" #include "wme.h" +#include "led.h" /* privid for wiphys to determine whether they belong to us or not */ void *mac80211_wiphy_privid = &mac80211_wiphy_privid; @@ -966,3 +967,120 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, } return supp_rates; } + +int ieee80211_reconfig(struct ieee80211_local *local) +{ + struct ieee80211_hw *hw = &local->hw; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_init_conf conf; + struct sta_info *sta; + unsigned long flags; + int res; + + /* restart hardware */ + if (local->open_count) { + res = local->ops->start(hw); + + ieee80211_led_radio(local, hw->conf.radio_enabled); + } + + /* add interfaces */ + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && + sdata->vif.type != NL80211_IFTYPE_MONITOR && + netif_running(sdata->dev)) { + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = sdata->dev->dev_addr; + res = local->ops->add_interface(hw, &conf); + } + } + + /* add STAs back */ + if (local->ops->sta_notify) { + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry(sta, &local->sta_list, list) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + + local->ops->sta_notify(hw, &sdata->vif, + STA_NOTIFY_ADD, &sta->sta); + } + spin_unlock_irqrestore(&local->sta_lock, flags); + } + + /* Clear Suspend state so that ADDBA requests can be processed */ + + rcu_read_lock(); + + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + list_for_each_entry_rcu(sta, &local->sta_list, list) { + clear_sta_flags(sta, WLAN_STA_SUSPEND); + } + } + + rcu_read_unlock(); + + /* setup RTS threshold */ + if (local->ops->set_rts_threshold) + local->ops->set_rts_threshold(hw, local->rts_threshold); + + /* reconfigure hardware */ + ieee80211_hw_config(local, ~0); + + netif_addr_lock_bh(local->mdev); + ieee80211_configure_filter(local); + netif_addr_unlock_bh(local->mdev); + + /* Finally also reconfigure all the BSS information */ + list_for_each_entry(sdata, &local->interfaces, list) { + u32 changed = ~0; + if (!netif_running(sdata->dev)) + continue; + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + /* disable beacon change bits */ + changed &= ~IEEE80211_IFCC_BEACON; + /* fall through */ + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + /* + * Driver's config_interface can fail if rfkill is + * enabled. Accommodate this return code. + * FIXME: When mac80211 has knowledge of rfkill + * state the code below can change back to: + * WARN(ieee80211_if_config(sdata, changed)); + * ieee80211_bss_info_change_notify(sdata, ~0); + */ + if (ieee80211_if_config(sdata, changed)) + printk(KERN_DEBUG "%s: failed to configure interface during resume\n", + sdata->dev->name); + else + ieee80211_bss_info_change_notify(sdata, ~0); + break; + case NL80211_IFTYPE_WDS: + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* ignore virtual */ + break; + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: + WARN_ON(1); + break; + } + } + + /* add back keys */ + list_for_each_entry(sdata, &local->interfaces, list) + if (netif_running(sdata->dev)) + ieee80211_enable_keys(sdata); + + ieee80211_wake_queues_by_reason(hw, + IEEE80211_QUEUE_STOP_REASON_SUSPEND); + + return 0; +} -- cgit v1.2.3 From 882b709230246de3359b04b195ad3e80b93b73ef Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 14 Apr 2009 16:21:01 +0530 Subject: ath9k: Disable autosleep feature for AR9285 based chipsets. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9cb85b0e9851..ec2a7a40b00d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3377,7 +3377,8 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || (ah->hw_version.macVersion == AR_SREV_VERSION_9160) || (ah->hw_version.macVersion == AR_SREV_VERSION_9100) || - (ah->hw_version.macVersion == AR_SREV_VERSION_9280)) + (ah->hw_version.macVersion == AR_SREV_VERSION_9280) || + (ah->hw_version.macVersion == AR_SREV_VERSION_9285)) pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; else pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; -- cgit v1.2.3 From 45f483c00299807a1635d6ee327957b796b60076 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 14 Apr 2009 22:19:29 +0200 Subject: p54: remove module_ stubs Christoph Hellwig pointed out that these stubs are unnecessary. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b18fc93a8bce..bc1bd72392a4 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2713,15 +2713,3 @@ void p54_free_common(struct ieee80211_hw *dev) #endif /* CONFIG_P54_LEDS */ } EXPORT_SYMBOL_GPL(p54_free_common); - -static int __init p54_init(void) -{ - return 0; -} - -static void __exit p54_exit(void) -{ -} - -module_init(p54_init); -module_exit(p54_exit); -- cgit v1.2.3 From 77ded01cc25744245c58a369d24e251833e995bd Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 15 Apr 2009 07:57:32 -0400 Subject: ath5k: fix initvals errors This patch corrects a few errors in the initvals tables to match those in the HAL tables. Namely, remove a couple of repetitions, fix some turbo mode errors, and correct a register for the CCK rate power table. Changes-licensed-under: ISC Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/initvals.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 61fb621ed20d..18eb5190ce4b 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -537,8 +537,6 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { { AR5K_DCU_TX_FILTER_1(15), 0x00000000 }, { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, - { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, - { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, { AR5K_STA_ID1, 0x00000000 }, { AR5K_BSS_ID0, 0x00000000 }, { AR5K_BSS_ID1, 0x00000000 }, @@ -669,7 +667,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { /*{ AR5K_PHY(650), 0x000001b5 },*/ { AR5K_PHY(651), 0x00000000 }, { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, - { AR5K_PHY_TXPOWER_RATE2, 0x20202020 }, + { AR5K_PHY_TXPOWER_RATE4, 0x20202020 }, /*{ AR5K_PHY(655), 0x13c889af },*/ { AR5K_PHY(656), 0x38490a20 }, { AR5K_PHY(657), 0x00007bb6 }, @@ -718,7 +716,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { { AR5K_PHY_SETTLING, { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, { AR5K_PHY_AGCCTL, - { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } }, + { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } }, { AR5K_PHY_NF, { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, { AR5K_PHY_WEAK_OFDM_HIGH_THR, @@ -799,7 +797,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { { AR5K_PHY_DESIRED_SIZE, { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } }, + { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } }, { AR5K_PHY_AGCCOARSE, { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, { AR5K_PHY_WEAK_OFDM_LOW_THR, -- cgit v1.2.3 From 56d2ac763829d2443075e8266dd00166ee11c80d Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 15 Apr 2009 07:57:33 -0400 Subject: ath5k: use tasklet_hi_schedule for beacon queue For embedded platforms, beacon transmission can be starved when flooded with data packets. Prioritize beacons by giving the beacon queue the first shot when the isr completes. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ff6d4f839734..ef8523e418e2 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2496,7 +2496,7 @@ ath5k_intr(int irq, void *dev_id) tasklet_schedule(&sc->restq); } else { if (status & AR5K_INT_SWBA) { - tasklet_schedule(&sc->beacontq); + tasklet_hi_schedule(&sc->beacontq); } if (status & AR5K_INT_RXEOL) { /* -- cgit v1.2.3 From 46802a4f07cd2367d584bb1a2e6998d22d4d4f3a Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 15 Apr 2009 07:57:34 -0400 Subject: ath5k: use bool for modparams Current code uses int types, but both modparams are boolean values. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index ef8523e418e2..3bde18f91450 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -61,11 +61,11 @@ static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); static int modparam_all_channels; -module_param_named(all_channels, modparam_all_channels, int, 0444); +module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); -- cgit v1.2.3 From c57ca81576e7ca0369ea52c9ac5f35d0f6ca1270 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 15 Apr 2009 07:57:35 -0400 Subject: ath5k: use rx hw descriptor pointer for self-linked check This patch simplifies the code used to detect when the self-linked DMA buffer is still in use by hardware, by checking the hardware's rxdp register instead of looking at the software buffer list. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 24 ++++-------------------- drivers/net/wireless/ath/ath5k/base.h | 1 - drivers/net/wireless/ath/ath5k/dma.c | 2 -- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3bde18f91450..1a6e72fe7be9 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1780,7 +1780,7 @@ ath5k_tasklet_rx(unsigned long data) struct sk_buff *skb, *next_skb; dma_addr_t next_skb_addr; struct ath5k_softc *sc = (void *)data; - struct ath5k_buf *bf, *bf_last; + struct ath5k_buf *bf; struct ath5k_desc *ds; int ret; int hdrlen; @@ -1791,7 +1791,6 @@ ath5k_tasklet_rx(unsigned long data) ATH5K_WARN(sc, "empty rx buf pool\n"); goto unlock; } - bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); do { rxs.flag = 0; @@ -1800,24 +1799,9 @@ ath5k_tasklet_rx(unsigned long data) skb = bf->skb; ds = bf->desc; - /* - * last buffer must not be freed to ensure proper hardware - * function. When the hardware finishes also a packet next to - * it, we are sure, it doesn't use it anymore and we can go on. - */ - if (bf_last == bf) - bf->flags |= 1; - if (bf->flags) { - struct ath5k_buf *bf_next = list_entry(bf->list.next, - struct ath5k_buf, list); - ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, - &rs); - if (ret) - break; - bf->flags &= ~1; - /* skip the overwritten one (even status is martian) */ - goto next; - } + /* bail if HW is still using self-linked descriptor */ + if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr) + break; ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); if (unlikely(ret == -EINPROGRESS)) diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 822956114cd7..852b2c189fd8 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -56,7 +56,6 @@ struct ath5k_buf { struct list_head list; - unsigned int flags; /* rx descriptor flags */ struct ath5k_desc *desc; /* virtual addr of desc */ dma_addr_t daddr; /* physical addr of desc */ struct sk_buff *skb; /* skbuff for buf */ diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index b65b4feb2d28..941b51130a6f 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -80,8 +80,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) * ath5k_hw_get_rxdp - Get RX Descriptor's address * * @ah: The &struct ath5k_hw - * - * XXX: Is RXDP read and clear ? */ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) { -- cgit v1.2.3 From 26925042b6b105995ee54c6015e95f0caf9632d6 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 15 Apr 2009 07:57:36 -0400 Subject: ath5k: manipulate rxlink and descriptor address under rxbuf lock Grabbing an ath5k_buf then dropping the lock is racy because the referenced descriptor can be obtained in another thread and released before the buffer is handed to the hardware. Likewise, manipulating sc->rxlink without the lock can lead to having multiple self-linked hardware descriptors. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 1a6e72fe7be9..c8c658bfcf9d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1618,9 +1618,8 @@ ath5k_rx_start(struct ath5k_softc *sc) ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", sc->cachelsz, sc->rxbufsize); - sc->rxlink = NULL; - spin_lock_bh(&sc->rxbuflock); + sc->rxlink = NULL; list_for_each_entry(bf, &sc->rxbuf, list) { ret = ath5k_rxbuf_setup(sc, bf); if (ret != 0) { @@ -1629,9 +1628,9 @@ ath5k_rx_start(struct ath5k_softc *sc) } } bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); + ath5k_hw_set_rxdp(ah, bf->daddr); spin_unlock_bh(&sc->rxbuflock); - ath5k_hw_set_rxdp(ah, bf->daddr); ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ ath5k_mode_setup(sc); /* set filters, etc. */ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ -- cgit v1.2.3 From 85efc86eb7c6cbb1c8ce8d99b10b948be033fbb9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 13 Apr 2009 21:41:46 -0400 Subject: atheros: fix propagation of bad EEPROM on regulatory init When the EEPROM is not in good condition we cannot continue so we currently bail out but only ath5k is bailing out properly. Both ath9k and ar9170 were proceeding and if a user were to run into this they'd see an obscure panic. Lets propagate the error as intended and make sure we inform the user by lifting the error message from debug to a kernel error. Stable note: You can find a port of this page here: http://bombadil.infradead.org/~mcgrof/patches/ath9k/ath9k-fix-eeprom.patch.txt Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/main.c | 2 ++ drivers/net/wireless/ath/ath9k/main.c | 5 +++-- drivers/net/wireless/ath/regd.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 8de0ff9f580b..857416c80199 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1649,6 +1649,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, ar9170_reg_notifier); + if (err) + goto err_out; err = ieee80211_register_hw(ar->hw); if (err) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8bf2bf36fd6d..2398d4f45f28 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1416,8 +1416,9 @@ static int ath_init(u16 devid, struct ath_softc *sc) for (i = 0; i < sc->keymax; i++) ath9k_hw_keyreset(ah, (u16) i); - if (ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, - ath9k_reg_notifier)) + error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, + ath9k_reg_notifier); + if (error) goto bad; /* default to MONITOR mode */ diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 4b5c851b81ff..526c7f1308db 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -477,7 +477,7 @@ ath_regd_init(struct ath_regulatory *reg, u16 regdmn; if (!ath_regd_is_eeprom_valid(reg)) { - printk(KERN_DEBUG "ath: Invalid EEPROM contents\n"); + printk(KERN_ERR "ath: Invalid EEPROM contents\n"); return -EINVAL; } -- cgit v1.2.3 From fade5db4f227bf59874efd6023f39d345e17e2a4 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 17 Apr 2009 15:14:22 +0200 Subject: p54: deactivate broken powersave function (part 2) This patch deactivates powersave in station mode. It does not work correctly yet, so the code does more harm than good. (I split the original patch and sent part of it for 2.6.30, which didn't have the IEEE80211_HW_BEACON_FILTER flag. -- JWL) Reported-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index bc1bd72392a4..5368aa33dab8 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2642,8 +2642,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) skb_queue_head_init(&priv->tx_queue); dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_BEACON_FILTER; + IEEE80211_HW_NOISE_DBM; dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | -- cgit v1.2.3 From dc7d243d75b906cc964c12caa3b2eebe953a69be Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 24 Mar 2009 21:33:43 +0100 Subject: Add support for CF8381 WiFi card. A detection function was added for identifying CF8381. Signed-off-by: Marek Vasut Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_cs.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index cedeac6322fe..2a5b083bf9bd 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -273,7 +273,28 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r */ #define IF_CS_PRODUCT_ID 0x0000001C #define IF_CS_CF8385_B1_REV 0x12 +#define IF_CS_CF8381_B3_REV 0x04 +/* + * Used to detect other cards than CF8385 since their revisions of silicon + * doesn't match those from CF8385, eg. CF8381 B3 works with this driver. + */ +#define CF8381_MANFID 0x02db +#define CF8381_CARDID 0x6064 +#define CF8385_MANFID 0x02df +#define CF8385_CARDID 0x8103 + +static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) +{ + return (p_dev->manf_id == CF8381_MANFID && + p_dev->card_id == CF8381_CARDID); +} + +static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) +{ + return (p_dev->manf_id == CF8385_MANFID && + p_dev->card_id == CF8385_CARDID); +} /********************************************************************/ /* I/O and interrupt handling */ @@ -757,6 +778,7 @@ static void if_cs_release(struct pcmcia_device *p_dev) static int if_cs_probe(struct pcmcia_device *p_dev) { int ret = -ENOMEM; + unsigned int prod_id; struct lbs_private *priv; struct if_cs_card *card; /* CIS parsing */ @@ -859,7 +881,14 @@ static int if_cs_probe(struct pcmcia_device *p_dev) p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); /* Check if we have a current silicon */ - if (if_cs_read8(card, IF_CS_PRODUCT_ID) < IF_CS_CF8385_B1_REV) { + prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); + if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { + lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); + ret = -ENODEV; + goto out2; + } + + if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); ret = -ENODEV; goto out2; @@ -950,7 +979,8 @@ static void if_cs_detach(struct pcmcia_device *p_dev) /********************************************************************/ static struct pcmcia_device_id if_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x02df, 0x8103), + PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), + PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); -- cgit v1.2.3 From 965bedadc01d34027455d5d5b67063ef0209c955 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 13:17:24 +0200 Subject: mac80211: improve powersave implementation When you have multiple virtual interfaces the current implementation requires setting them up properly from userspace, which is undesirable when we want to default to power save mode. Keep track of powersave requested from userspace per managed mode interface, and only enable powersave globally when exactly one managed mode interface is active and has powersave turned on. Second, only start the dynPS timer when PS is turned on, and properly turn it off when PS is turned off. Third, fix the scan_sdata abuse in the dynps code. Finally, also reorder the code and refactor the code that enables PS or the dynps timer instead of having it copied in two places. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 9 +- net/mac80211/iface.c | 4 + net/mac80211/mlme.c | 228 ++++++++++++++++++++++++++++----------------- net/mac80211/scan.c | 2 +- net/mac80211/wext.c | 43 ++------- 5 files changed, 165 insertions(+), 121 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 13d6f890ced4..ff40dd7b523a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -295,6 +295,8 @@ struct ieee80211_if_managed { int auth_tries; /* retries for auth req */ int assoc_tries; /* retries for assoc req */ + bool powersave; /* powersave requested for this iface */ + unsigned long request; unsigned long last_probe; @@ -739,8 +741,12 @@ struct ieee80211_local { int wifi_wme_noack_test; unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ - bool powersave; bool pspolling; + /* + * PS can only be enabled when we have exactly one managed + * interface (and monitors) in PS, this then points there. + */ + struct ieee80211_sub_if_data *ps_sdata; struct work_struct dynamic_ps_enable_work; struct work_struct dynamic_ps_disable_work; struct timer_list dynamic_ps_timer; @@ -932,6 +938,7 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); void ieee80211_send_pspoll(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); +void ieee80211_recalc_ps(struct ieee80211_local *local); /* IBSS code */ int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 91e8e1bacaaa..6240f76e2a43 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -317,6 +317,8 @@ static int ieee80211_open(struct net_device *dev) ieee80211_set_wmm_default(sdata); } + ieee80211_recalc_ps(local); + /* * ieee80211_sta_work is disabled while network interface * is down. Therefore, some configuration changes may not @@ -572,6 +574,8 @@ static int ieee80211_stop(struct net_device *dev) hw_reconf_flags = 0; } + ieee80211_recalc_ps(local); + /* do after stop to avoid reconfiguring when we stop anyway */ if (hw_reconf_flags) ieee80211_hw_config(local, hw_reconf_flags); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 90267afa8e69..06d9a1d23252 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -446,6 +446,145 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, ieee80211_tx_skb(sdata, skb, 0); } +void ieee80211_send_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + int powersave) +{ + struct sk_buff *skb; + struct ieee80211_hdr *nullfunc; + __le16 fc; + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + return; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); + memset(nullfunc, 0, 24); + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS); + if (powersave) + fc |= cpu_to_le16(IEEE80211_FCTL_PM); + nullfunc->frame_control = fc; + memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); + memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); + memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); + + ieee80211_tx_skb(sdata, skb, 0); +} + +/* powersave */ +static void ieee80211_enable_ps(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_conf *conf = &local->hw.conf; + + if (conf->dynamic_ps_timeout > 0 && + !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(conf->dynamic_ps_timeout)); + } else { + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + ieee80211_send_nullfunc(local, sdata, 1); + conf->flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } +} + +static void ieee80211_change_ps(struct ieee80211_local *local) +{ + struct ieee80211_conf *conf = &local->hw.conf; + + if (local->ps_sdata) { + if (!(local->ps_sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)) + return; + + ieee80211_enable_ps(local, local->ps_sdata); + } else if (conf->flags & IEEE80211_CONF_PS) { + conf->flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); + } +} + +/* need to hold RTNL or interface lock */ +void ieee80211_recalc_ps(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata, *found = NULL; + int count = 0; + + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { + local->ps_sdata = NULL; + return; + } + + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + if (sdata->vif.type != NL80211_IFTYPE_STATION) + continue; + found = sdata; + count++; + } + + if (count == 1 && found->u.mgd.powersave) + local->ps_sdata = found; + else + local->ps_sdata = NULL; + + ieee80211_change_ps(local); +} + +void ieee80211_dynamic_ps_disable_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + dynamic_ps_disable_work); + + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + + ieee80211_wake_queues_by_reason(&local->hw, + IEEE80211_QUEUE_STOP_REASON_PS); +} + +void ieee80211_dynamic_ps_enable_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + dynamic_ps_enable_work); + struct ieee80211_sub_if_data *sdata = local->ps_sdata; + + /* can only happen when PS was just disabled anyway */ + if (!sdata) + return; + + if (local->hw.conf.flags & IEEE80211_CONF_PS) + return; + + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + ieee80211_send_nullfunc(local, sdata, 1); + + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); +} + +void ieee80211_dynamic_ps_timer(unsigned long data) +{ + struct ieee80211_local *local = (void *) data; + + queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); +} + /* MLME */ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, struct ieee80211_if_managed *ifmgd, @@ -721,19 +860,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, bss_info_changed |= BSS_CHANGED_BASIC_RATES; ieee80211_bss_info_change_notify(sdata, bss_info_changed); - if (local->powersave) { - if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) && - local->hw.conf.dynamic_ps_timeout > 0) { - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies( - local->hw.conf.dynamic_ps_timeout)); - } else { - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - ieee80211_send_nullfunc(local, sdata, 1); - conf->flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - } + /* will be same as sdata */ + if (local->ps_sdata) + ieee80211_enable_ps(local, sdata); netif_tx_start_all_queues(sdata->dev); netif_carrier_on(sdata->dev); @@ -2195,76 +2324,3 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) ieee80211_restart_sta_timer(sdata); rcu_read_unlock(); } - -void ieee80211_dynamic_ps_disable_work(struct work_struct *work) -{ - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, - dynamic_ps_disable_work); - - if (local->hw.conf.flags & IEEE80211_CONF_PS) { - local->hw.conf.flags &= ~IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - - ieee80211_wake_queues_by_reason(&local->hw, - IEEE80211_QUEUE_STOP_REASON_PS); -} - -void ieee80211_dynamic_ps_enable_work(struct work_struct *work) -{ - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, - dynamic_ps_enable_work); - /* XXX: using scan_sdata is completely broken! */ - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - - if (local->hw.conf.flags & IEEE80211_CONF_PS) - return; - - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK && sdata) - ieee80211_send_nullfunc(local, sdata, 1); - - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); -} - -void ieee80211_dynamic_ps_timer(unsigned long data) -{ - struct ieee80211_local *local = (void *) data; - - queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); -} - -void ieee80211_send_nullfunc(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - int powersave) -{ - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; - __le16 fc; - - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) - return; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " - "frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(nullfunc, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - if (powersave) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - nullfunc->frame_control = fc; - memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); - memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); - memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); - - ieee80211_tx_skb(sdata, skb, 0); -} diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4ec1bfc7f6a9..20df861c6c4c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -253,7 +253,7 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - if (!local->powersave) + if (!local->ps_sdata) ieee80211_send_nullfunc(local, sdata, 0); else { /* diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index a52fb3a4a455..81f63e57027f 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -747,7 +747,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_conf *conf = &local->hw.conf; - int ret = 0, timeout = 0; + int timeout = 0; bool ps; if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) @@ -779,42 +779,19 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, timeout = wrq->value / 1000; set: - if (ps == local->powersave && timeout == conf->dynamic_ps_timeout) - return ret; + if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout) + return 0; - local->powersave = ps; + sdata->u.mgd.powersave = ps; conf->dynamic_ps_timeout = timeout; if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); - - if (!(sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED)) - return ret; + ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); - if (conf->dynamic_ps_timeout > 0 && - !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(conf->dynamic_ps_timeout)); - } else { - if (local->powersave) { - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - ieee80211_send_nullfunc(local, sdata, 1); - conf->flags |= IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); - } else { - conf->flags &= ~IEEE80211_CONF_PS; - ret = ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_PS); - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - ieee80211_send_nullfunc(local, sdata, 0); - del_timer_sync(&local->dynamic_ps_timer); - cancel_work_sync(&local->dynamic_ps_enable_work); - } - } + ieee80211_recalc_ps(local); - return ret; + return 0; } static int ieee80211_ioctl_giwpower(struct net_device *dev, @@ -822,9 +799,9 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - wrqu->power.disabled = !local->powersave; + wrqu->power.disabled = !sdata->u.mgd.powersave; return 0; } -- cgit v1.2.3 From 10f644a47b76d3e61b98f2d02ce9690b94c51ee5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 13:17:25 +0200 Subject: mac80211: disable powersave if pm_qos asks for low latency When an application asks for a latency lower than the beacon interval there's nothing we can do -- we need to stay awake and not have the AP buffer frames for us. Add code to automatically calculate this constraint in mac80211 so drivers need not concern themselves with it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 9 +++++++++ net/mac80211/ieee80211_i.h | 5 ++++- net/mac80211/iface.c | 4 ++-- net/mac80211/main.c | 31 ++++++++++++++++++++++++------- net/mac80211/mlme.c | 36 ++++++++++++++++++++++++++++++++---- net/mac80211/wext.c | 2 +- 6 files changed, 72 insertions(+), 15 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 4b501b48ce86..53563d53b5ad 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1383,4 +1383,13 @@ static inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) return -1; } +/** + * ieee80211_tu_to_usec - convert time units (TU) to microseconds + * @tu: the TUs + */ +static inline unsigned long ieee80211_tu_to_usec(unsigned long tu) +{ + return 1024 * tu; +} + #endif /* LINUX_IEEE80211_H */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ff40dd7b523a..b1d18d967d8c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -750,6 +750,7 @@ struct ieee80211_local { struct work_struct dynamic_ps_enable_work; struct work_struct dynamic_ps_disable_work; struct timer_list dynamic_ps_timer; + struct notifier_block network_latency_notifier; int user_power_level; /* in dBm */ int power_constr_level; /* in dBm */ @@ -938,7 +939,9 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); void ieee80211_send_pspoll(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); -void ieee80211_recalc_ps(struct ieee80211_local *local); +void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); +int ieee80211_max_network_latency(struct notifier_block *nb, + unsigned long data, void *dummy); /* IBSS code */ int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6240f76e2a43..5d60deb219d3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -317,7 +317,7 @@ static int ieee80211_open(struct net_device *dev) ieee80211_set_wmm_default(sdata); } - ieee80211_recalc_ps(local); + ieee80211_recalc_ps(local, -1); /* * ieee80211_sta_work is disabled while network interface @@ -574,7 +574,7 @@ static int ieee80211_stop(struct net_device *dev) hw_reconf_flags = 0; } - ieee80211_recalc_ps(local); + ieee80211_recalc_ps(local, -1); /* do after stop to avoid reconfiguring when we stop anyway */ if (hw_reconf_flags) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 80c0e28bf549..049ce8639806 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -1038,25 +1039,38 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } } + local->network_latency_notifier.notifier_call = + ieee80211_max_network_latency; + result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); + + if (result) { + rtnl_lock(); + goto fail_pm_qos; + } + return 0; -fail_wep: + fail_pm_qos: + ieee80211_led_exit(local); + ieee80211_remove_interfaces(local); + fail_wep: rate_control_deinitialize(local); -fail_rate: + fail_rate: unregister_netdevice(local->mdev); local->mdev = NULL; -fail_dev: + fail_dev: rtnl_unlock(); sta_info_stop(local); -fail_sta_info: + fail_sta_info: debugfs_hw_del(local); destroy_workqueue(local->hw.workqueue); -fail_workqueue: + fail_workqueue: if (local->mdev) free_netdev(local->mdev); -fail_mdev_alloc: + fail_mdev_alloc: wiphy_unregister(local->hw.wiphy); -fail_wiphy_register: + fail_wiphy_register: kfree(local->int_scan_req.channels); return result; } @@ -1069,6 +1083,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); + pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); + rtnl_lock(); /* diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 06d9a1d23252..c39a214e7ad0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -515,7 +516,7 @@ static void ieee80211_change_ps(struct ieee80211_local *local) } /* need to hold RTNL or interface lock */ -void ieee80211_recalc_ps(struct ieee80211_local *local) +void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) { struct ieee80211_sub_if_data *sdata, *found = NULL; int count = 0; @@ -534,10 +535,22 @@ void ieee80211_recalc_ps(struct ieee80211_local *local) count++; } - if (count == 1 && found->u.mgd.powersave) - local->ps_sdata = found; - else + if (count == 1 && found->u.mgd.powersave) { + s32 beaconint_us; + + if (latency < 0) + latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY); + + beaconint_us = ieee80211_tu_to_usec( + found->vif.bss_conf.beacon_int); + + if (beaconint_us > latency) + local->ps_sdata = NULL; + else + local->ps_sdata = found; + } else { local->ps_sdata = NULL; + } ieee80211_change_ps(local); } @@ -2324,3 +2337,18 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) ieee80211_restart_sta_timer(sdata); rcu_read_unlock(); } + +int ieee80211_max_network_latency(struct notifier_block *nb, + unsigned long data, void *dummy) +{ + s32 latency_usec = (s32) data; + struct ieee80211_local *local = + container_of(nb, struct ieee80211_local, + network_latency_notifier); + + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, latency_usec); + mutex_unlock(&local->iflist_mtx); + + return 0; +} diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 81f63e57027f..1c4664b8b1a0 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -789,7 +789,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); - ieee80211_recalc_ps(local); + ieee80211_recalc_ps(local, -1); return 0; } -- cgit v1.2.3 From d91f36db51661018f6d54ff5966e283bcec4c545 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 13:17:26 +0200 Subject: mac80211: implement beacon filtering in software Regardless of whether the hardware implements beacon filtering, there's no need to process all beacons in software all the time throughout the stack (mac80211 does a lot, then cfg80211, then in the future possibly userspace). This patch implements the "best possible" beacon filtering in mac80211. "Best possible" means that it can look for changes in all requested information elements, and distinguish vendor IEs by their OUI. In the future, we will add nl80211 API for userspace to request information elements and vendor IE OUIs to watch -- drivers can then implement the best they can do while software implements it fully. It is unclear whether or not this actually saves CPU time, but the data is all in the cache already so it should be fairly cheap. The additional _testing_, however, has great benefit; Without this, and on hardware that doesn't implement beacon filtering, wrong assumptions about, for example, scan result updates could quickly creep into code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 5 +++++ net/mac80211/mlme.c | 52 +++++++++++++++++++++++++++++++++++----------- net/mac80211/util.c | 23 ++++++++++++++++++-- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b1d18d967d8c..38c980612518 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -308,6 +308,8 @@ struct ieee80211_if_managed { int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ int auth_transaction; + u32 beacon_crc; + enum { IEEE80211_MFP_DISABLED, IEEE80211_MFP_OPTIONAL, @@ -1085,6 +1087,9 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); +u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, + struct ieee802_11_elems *elems, + u64 filter, u32 crc); int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); u32 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c39a214e7ad0..7a8d4c494246 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1752,46 +1753,73 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; } +/* + * This is the canonical list of information elements we care about, + * the filter code also gives us all changes to the Microsoft OUI + * (00:50:F2) vendor IE which is used for WMM which we need to track. + * + * We implement beacon filtering in software since that means we can + * avoid processing the frame here and in cfg80211, and userspace + * will not be able to tell whether the hardware supports it or not. + * + * XXX: This list needs to be dynamic -- userspace needs to be able to + * add items it requires. It also needs to be able to tell us to + * look out for other vendor IEs. + */ +static const u64 care_about_ies = + BIT(WLAN_EID_COUNTRY) | + BIT(WLAN_EID_ERP_INFO) | + BIT(WLAN_EID_CHANNEL_SWITCH) | + BIT(WLAN_EID_PWR_CONSTRAINT) | + BIT(WLAN_EID_HT_CAPABILITY) | + BIT(WLAN_EID_HT_INFORMATION); + static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_if_managed *ifmgd; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; size_t baselen; struct ieee802_11_elems elems; struct ieee80211_local *local = sdata->local; u32 changed = 0; - bool erp_valid, directed_tim; + bool erp_valid, directed_tim = false; u8 erp_value = 0; + u32 ncrc; /* Process beacon from the current BSS */ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; if (baselen > len) return; - ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); - - if (sdata->vif.type != NL80211_IFTYPE_STATION) + if (rx_status->freq != local->hw.conf.channel->center_freq) return; - ifmgd = &sdata->u.mgd; - if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED) || memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - if (rx_status->freq != local->hw.conf.channel->center_freq) + ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); + ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, + len - baselen, &elems, + care_about_ies, ncrc); + + if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + directed_tim = ieee80211_check_tim(&elems, ifmgd->aid); + + ncrc = crc32_be(ncrc, (void *)&directed_tim, sizeof(directed_tim)); + + if (ncrc == ifmgd->beacon_crc) return; + ifmgd->beacon_crc = ncrc; + + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, elems.wmm_param_len); if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { - directed_tim = ieee80211_check_tim(&elems, ifmgd->aid); - if (directed_tim) { if (local->hw.conf.dynamic_ps_timeout > 0) { local->hw.conf.flags &= ~IEEE80211_CONF_PS; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b361e2acfce9..3dd490fa4b68 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -536,9 +537,17 @@ EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems) +{ + ieee802_11_parse_elems_crc(start, len, elems, 0, 0); +} + +u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, + struct ieee802_11_elems *elems, + u64 filter, u32 crc) { size_t left = len; u8 *pos = start; + bool calc_crc = filter != 0; memset(elems, 0, sizeof(*elems)); elems->ie_start = start; @@ -552,7 +561,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len, left -= 2; if (elen > left) - return; + break; + + if (calc_crc && id < 64 && (filter & BIT(id))) + crc = crc32_be(crc, pos - 2, elen + 2); switch (id) { case WLAN_EID_SSID: @@ -587,15 +599,20 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->challenge = pos; elems->challenge_len = elen; break; - case WLAN_EID_WPA: + case WLAN_EID_VENDOR_SPECIFIC: if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && pos[2] == 0xf2) { /* Microsoft OUI (00:50:F2) */ + + if (calc_crc) + crc = crc32_be(crc, pos - 2, elen + 2); + if (pos[3] == 1) { /* OUI Type 1 - WPA IE */ elems->wpa = pos; elems->wpa_len = elen; } else if (elen >= 5 && pos[3] == 2) { + /* OUI Type 2 - WMM IE */ if (pos[4] == 0) { elems->wmm_info = pos; elems->wmm_info_len = elen; @@ -680,6 +697,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, left -= elen; pos += elen; } + + return crc; } void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) -- cgit v1.2.3 From bbbdff9e00449928f228867076a07bdfecd3dca8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 13:27:42 +0200 Subject: mac80211: enable PS by default Enable PS by default (depending on Kconfig) -- rely on drivers to control the level using pm_qos. Due to the previous patch we turn off PS when necessary due to latency requirements. This has a Kconfig symbol so people can, if they really want, configure the default in their kernels. We may want to keep it at "default y" only in wireless-testing for a while. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 16 ++++++++++++++++ net/mac80211/mlme.c | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index ecc3faf9f11a..9cbf545e95a2 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -11,6 +11,22 @@ config MAC80211 This option enables the hardware independent IEEE 802.11 networking stack. +config MAC80211_DEFAULT_PS + bool "enable powersave by default" + depends on MAC80211 + default y + help + This option enables powersave mode by default. + + If this causes your applications to misbehave you should fix your + applications instead -- they need to register their network + latency requirement, see Documentation/power/pm_qos_interface.txt. + +config MAC80211_DEFAULT_PS_VALUE + int + default 1 if MAC80211_DEFAULT_PS + default 0 + menu "Rate control algorithm selection" depends on MAC80211 != n diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7a8d4c494246..a16c9d724be1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2192,6 +2192,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd; + u32 hw_flags; ifmgd = &sdata->u.mgd; INIT_WORK(&ifmgd->work, ieee80211_sta_work); @@ -2211,6 +2212,13 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) IEEE80211_STA_AUTO_CHANNEL_SEL; if (sdata->local->hw.queues >= 4) ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; + + hw_flags = sdata->local->hw.flags; + + if (hw_flags & IEEE80211_HW_SUPPORTS_PS) { + ifmgd->powersave = CONFIG_MAC80211_DEFAULT_PS_VALUE; + sdata->local->hw.conf.dynamic_ps_timeout = 500; + } } /* configuration hooks */ -- cgit v1.2.3 From 955394c98c9cb79bdb3e6b479695af3a90ea0623 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 Apr 2009 17:04:25 +0200 Subject: mac80211: document powersaving/beacon filter future Document what mac80211 will do in the future to help save power. We're not quite there yet, but a plan helps. Also, while at it, fix the docs wrt. multicast traffic. Signed-off-by: Johannes Berg Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 60 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a593bedcfeda..52808bdcc6ca 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1109,11 +1109,9 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * need software support for parsing the TIM bitmap. This is also supported * by mac80211 by combining the %IEEE80211_HW_SUPPORTS_PS and * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still - * required to pass up beacons. Additionally, in this case, mac80211 will - * wake up the hardware when multicast traffic is announced in the beacon. - * - * FIXME: I don't think we can be fast enough in software when we want to - * receive multicast traffic? + * required to pass up beacons. The hardware is still required to handle + * waking up for multicast traffic; if it cannot the driver must handle that + * as best as it can, mac80211 is too slow. * * Dynamic powersave mode is an extension to normal powersave mode in which * the hardware stays awake for a user-specified period of time after sending @@ -1134,11 +1132,53 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * way the host will only receive beacons where some relevant information * (for example ERP protection or WMM settings) have changed. * - * Beacon filter support is informed with %IEEE80211_HW_BEACON_FILTER flag. - * The driver needs to enable beacon filter support whenever power save is - * enabled, that is %IEEE80211_CONF_PS is set. When power save is enabled, - * the stack will not check for beacon miss at all and the driver needs to - * notify about complete loss of beacons with ieee80211_beacon_loss(). + * Beacon filter support is advertised with the %IEEE80211_HW_BEACON_FILTER + * hardware capability. The driver needs to enable beacon filter support + * whenever power save is enabled, that is %IEEE80211_CONF_PS is set. When + * power save is enabled, the stack will not check for beacon loss and the + * driver needs to notify about loss of beacons with ieee80211_beacon_loss(). + * + * The time (or number of beacons missed) until the firmware notifies the + * driver of a beacon loss event (which in turn causes the driver to call + * ieee80211_beacon_loss()) should be configurable and will be controlled + * by mac80211 and the roaming algorithm in the future. + * + * Since there may be constantly changing information elements that nothing + * in the software stack cares about, we will, in the future, have mac80211 + * tell the driver which information elements are interesting in the sense + * that we want to see changes in them. This will include + * - a list of information element IDs + * - a list of OUIs for the vendor information element + * + * Ideally, the hardware would filter out any beacons without changes in the + * requested elements, but if it cannot support that it may, at the expense + * of some efficiency, filter out only a subset. For example, if the device + * doesn't support checking for OUIs it should pass up all changes in all + * vendor information elements. + * + * Note that change, for the sake of simplification, also includes information + * elements appearing or disappearing from the beacon. + * + * Some hardware supports an "ignore list" instead, just make sure nothing + * that was requested is on the ignore list, and include commonly changing + * information element IDs in the ignore list, for example 11 (BSS load) and + * the various vendor-assigned IEs with unknown contents (128, 129, 133-136, + * 149, 150, 155, 156, 173, 176, 178, 179, 219); for forward compatibility + * it could also include some currently unused IDs. + * + * + * In addition to these capabilities, hardware should support notifying the + * host of changes in the beacon RSSI. This is relevant to implement roaming + * when no traffic is flowing (when traffic is flowing we see the RSSI of + * the received data packets). This can consist in notifying the host when + * the RSSI changes significantly or when it drops below or rises above + * configurable thresholds. In the future these thresholds will also be + * configured by mac80211 (which gets them from userspace) to implement + * them as the roaming algorithm requires. + * + * If the hardware cannot implement this, the driver should ask it to + * periodically pass beacon frames to the host so that software can do the + * signal strength threshold checking. */ /** -- cgit v1.2.3 From 357303e2b61272b191f2e5d782d94fdd8f50fd71 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 16 Apr 2009 18:44:53 +0300 Subject: mac80211: Allow scan to be requested in AP mode We can allow scan requests in AP mode as long as the interface has not yet been configured to send out Beacon frames (or if beaconing has been disabled prior to the scan request). This makes it easier to scan for neighboring BSSes during AP initialization and makes it possible to run a scan without setting the interface down, if needed. Without this change, the only available option would be to set the interface down, move into station mode, and set the interface up, prior to requesting the scan. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e677b751d468..520efa8a0791 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1167,7 +1167,8 @@ static int ieee80211_scan(struct wiphy *wiphy, if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_ADHOC && - sdata->vif.type != NL80211_IFTYPE_MESH_POINT) + sdata->vif.type != NL80211_IFTYPE_MESH_POINT && + (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) return -EOPNOTSUPP; return ieee80211_request_scan(sdata, req); -- cgit v1.2.3 From a027087a6b4c7d985b872cac3e19ce023670792e Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 16 Apr 2009 19:56:38 -0500 Subject: rtl8187: Implement TX/RX blink for LED The following patch implements some control over the LED on RTL8187B and RTL8187L devices. Triggers are registered for TX and RX. Whenever the trigger event occurs, the LED is turned off for 1/20 second, then turned back on. Note: For those RTL8187X devices that are built into the computer and have a LED that is expected to be controlled with a radio switch, this patch will not operate that LED. That will take a separate patch to be prepared later. Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Tested-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 7 + drivers/net/wireless/rtl818x/Makefile | 2 +- drivers/net/wireless/rtl818x/rtl8187.h | 7 + drivers/net/wireless/rtl818x/rtl8187_dev.c | 18 ++- drivers/net/wireless/rtl818x/rtl8187_leds.c | 218 ++++++++++++++++++++++++++++ drivers/net/wireless/rtl818x/rtl8187_leds.h | 57 ++++++++ 6 files changed, 305 insertions(+), 4 deletions(-) create mode 100644 drivers/net/wireless/rtl818x/rtl8187_leds.c create mode 100644 drivers/net/wireless/rtl818x/rtl8187_leds.h diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index ad99470ae92d..11c248180982 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -433,6 +433,13 @@ config RTL8187 Thanks to Realtek for their support! +# If possible, automatically enable LEDs for RTL8187. + +config RTL8187_LEDS + bool + depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) + default y + config ADM8211 tristate "ADMtek ADM8211 support" depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile index c113b3e69046..37e3d4db0c40 100644 --- a/drivers/net/wireless/rtl818x/Makefile +++ b/drivers/net/wireless/rtl818x/Makefile @@ -1,5 +1,5 @@ rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o -rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o +rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o obj-$(CONFIG_RTL8180) += rtl8180.o obj-$(CONFIG_RTL8187) += rtl8187.o diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 9718f61809cf..622196dc078e 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -16,6 +16,7 @@ #define RTL8187_H #include "rtl818x.h" +#include "rtl8187_leds.h" #define RTL8187_EEPROM_TXPWR_BASE 0x05 #define RTL8187_EEPROM_MAC_ADDR 0x07 @@ -102,6 +103,12 @@ struct rtl8187_priv { struct usb_anchor anchored; struct delayed_work work; struct ieee80211_hw *dev; +#ifdef CONFIG_RTL8187_LEDS + struct rtl8187_led led_tx; + struct rtl8187_led led_rx; + struct delayed_work led_on; + struct delayed_work led_off; +#endif u16 txpwr_base; u8 asic_rev; u8 is_rtl8187b; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index d6d4001812a7..ac558da92aac 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -29,6 +29,9 @@ #include "rtl8187.h" #include "rtl8187_rtl8225.h" +#ifdef CONFIG_RTL8187_LEDS +#include "rtl8187_leds.h" +#endif MODULE_AUTHOR("Michael Wu "); MODULE_AUTHOR("Andrea Merello "); @@ -734,10 +737,10 @@ static const u8 rtl8187b_reg_table[][3] = { {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, - {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0}, + {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, - {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, - {0x8E, 0x08, 0}, {0x8F, 0x00, 0} + {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, + {0x8F, 0x00, 0} }; static int rtl8187b_init_hw(struct ieee80211_hw *dev) @@ -1501,6 +1504,12 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, wiphy_name(dev->wiphy), dev->wiphy->perm_addr, chip_name, priv->asic_rev, priv->rf->name); +#ifdef CONFIG_RTL8187_LEDS + eeprom_93cx6_read(&eeprom, 0x3F, ®); + reg &= 0xFF; + rtl8187_leds_init(dev, reg); +#endif + return 0; err_free_dev: @@ -1518,6 +1527,9 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf) if (!dev) return; +#ifdef CONFIG_RTL8187_LEDS + rtl8187_leds_exit(dev); +#endif ieee80211_unregister_hw(dev); priv = dev->priv; diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c new file mode 100644 index 000000000000..b44253592243 --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -0,0 +1,218 @@ +/* + * Linux LED driver for RTL8187 + * + * Copyright 2009 Larry Finger + * + * Based on the LED handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * Thanks to Realtek for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef CONFIG_RTL8187_LEDS + +#include +#include +#include + +#include "rtl8187.h" +#include "rtl8187_leds.h" + +static void led_turn_on(struct work_struct *work) +{ + /* As this routine does read/write operations on the hardware, it must + * be run from a work queue. + */ + u8 reg; + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + led_on.work); + struct rtl8187_led *led = &priv->led_tx; + + /* Don't change the LED, when the device is down. */ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return ; + + /* Skip if the LED is not registered. */ + if (!led->dev) + return; + mutex_lock(&priv->conf_mutex); + switch (led->ledpin) { + case LED_PIN_GPIO0: + rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00); + break; + case LED_PIN_LED0: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_LED1: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_HW: + default: + break; + } + mutex_unlock(&priv->conf_mutex); +} + +static void led_turn_off(struct work_struct *work) +{ + /* As this routine does read/write operations on the hardware, it must + * be run from a work queue. + */ + u8 reg; + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + led_off.work); + struct rtl8187_led *led = &priv->led_tx; + + /* Don't change the LED, when the device is down. */ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return ; + + /* Skip if the LED is not registered. */ + if (!led->dev) + return; + mutex_lock(&priv->conf_mutex); + switch (led->ledpin) { + case LED_PIN_GPIO0: + rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01); + break; + case LED_PIN_LED0: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_LED1: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_HW: + default: + break; + } + mutex_unlock(&priv->conf_mutex); +} + +/* Callback from the LED subsystem. */ +static void rtl8187_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, + led_dev); + struct ieee80211_hw *hw = led->dev; + struct rtl8187_priv *priv = hw->priv; + + if (brightness == LED_OFF) { + queue_delayed_work(hw->workqueue, &priv->led_off, 0); + /* The LED is off for 1/20 sec so that it just blinks. */ + queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20); + } else + queue_delayed_work(hw->workqueue, &priv->led_on, 0); +} + +static int rtl8187_register_led(struct ieee80211_hw *dev, + struct rtl8187_led *led, const char *name, + const char *default_trigger, u8 ledpin) +{ + int err; + struct rtl8187_priv *priv = dev->priv; + + if (led->dev) + return -EEXIST; + if (!default_trigger) + return -EINVAL; + led->dev = dev; + led->ledpin = ledpin; + strncpy(led->name, name, sizeof(led->name)); + + led->led_dev.name = led->name; + led->led_dev.default_trigger = default_trigger; + led->led_dev.brightness_set = rtl8187_led_brightness_set; + + err = led_classdev_register(&priv->udev->dev, &led->led_dev); + if (err) { + printk(KERN_INFO "LEDs: Failed to register %s\n", name); + led->dev = NULL; + return err; + } + return 0; +} + +static void rtl8187_unregister_led(struct rtl8187_led *led) +{ + led_classdev_unregister(&led->led_dev); + led->dev = NULL; +} + +void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) +{ + struct rtl8187_priv *priv = dev->priv; + char name[RTL8187_LED_MAX_NAME_LEN + 1]; + u8 ledpin; + int err; + + /* According to the vendor driver, the LED operation depends on the + * customer ID encoded in the EEPROM + */ + printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid); + switch (custid) { + case EEPROM_CID_RSVD0: + case EEPROM_CID_RSVD1: + case EEPROM_CID_SERCOMM_PS: + case EEPROM_CID_QMI: + case EEPROM_CID_DELL: + case EEPROM_CID_TOSHIBA: + ledpin = LED_PIN_GPIO0; + break; + case EEPROM_CID_ALPHA0: + ledpin = LED_PIN_LED0; + break; + case EEPROM_CID_HW: + ledpin = LED_PIN_HW; + break; + default: + ledpin = LED_PIN_GPIO0; + } + + INIT_DELAYED_WORK(&priv->led_on, led_turn_on); + INIT_DELAYED_WORK(&priv->led_off, led_turn_off); + + snprintf(name, sizeof(name), + "rtl8187-%s::tx", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_tx, name, + ieee80211_get_tx_led_name(dev), ledpin); + if (err) + goto error; + snprintf(name, sizeof(name), + "rtl8187-%s::rx", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_rx, name, + ieee80211_get_rx_led_name(dev), ledpin); + if (!err) { + queue_delayed_work(dev->workqueue, &priv->led_on, 0); + return; + } + /* registration of RX LED failed - unregister TX */ + rtl8187_unregister_led(&priv->led_tx); +error: + /* If registration of either failed, cancel delayed work */ + cancel_delayed_work_sync(&priv->led_off); + cancel_delayed_work_sync(&priv->led_on); +} + +void rtl8187_leds_exit(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + + rtl8187_unregister_led(&priv->led_tx); + /* turn the LED off before exiting */ + queue_delayed_work(dev->workqueue, &priv->led_off, 0); + cancel_delayed_work_sync(&priv->led_off); + rtl8187_unregister_led(&priv->led_rx); +} +#endif /* def CONFIG_RTL8187_LED */ + diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h new file mode 100644 index 000000000000..a0332027aead --- /dev/null +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h @@ -0,0 +1,57 @@ +/* + * Definitions for RTL8187 leds + * + * Copyright 2009 Larry Finger + * + * Based on the LED handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187_LED_H +#define RTL8187_LED_H + +#ifdef CONFIG_RTL8187_LEDS + +#define RTL8187_LED_MAX_NAME_LEN 21 + +#include +#include + +enum { + LED_PIN_LED0, + LED_PIN_LED1, + LED_PIN_GPIO0, + LED_PIN_HW +}; + +enum { + EEPROM_CID_RSVD0 = 0x00, + EEPROM_CID_RSVD1 = 0xFF, + EEPROM_CID_ALPHA0 = 0x01, + EEPROM_CID_SERCOMM_PS = 0x02, + EEPROM_CID_HW = 0x03, + EEPROM_CID_TOSHIBA = 0x04, + EEPROM_CID_QMI = 0x07, + EEPROM_CID_DELL = 0x08 +}; + +struct rtl8187_led { + struct ieee80211_hw *dev; + /* The LED class device */ + struct led_classdev led_dev; + /* The pin/method used to control the led */ + u8 ledpin; + /* The unique name string for this LED device. */ + char name[RTL8187_LED_MAX_NAME_LEN + 1]; +}; + +void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); +void rtl8187_leds_exit(struct ieee80211_hw *dev); + +#endif /* def CONFIG_RTL8187_LED */ + +#endif /* RTL8187_LED_H */ -- cgit v1.2.3 From d577e7cdb1be027bc51ee1030bc7fd647ea6d0da Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 18 Apr 2009 18:30:13 +0200 Subject: p54: fix ps-poll delivery in ap mode PS-Polled frames must be sent with OUT_NOCANCEL flag set, or the firmware will reject all of them, at the station is still blacklisted. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 5368aa33dab8..71394968d450 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1473,7 +1473,8 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, if (info->control.sta) *aid = info->control.sta->aid; - else + + if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; break; } -- cgit v1.2.3 From fef99929cd6b409a67a35e41f7c177bade5bca34 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 18 Apr 2009 19:39:15 +0200 Subject: mac80211: set CLEAR_PS for pspolled frames This patch sets IEEE80211_TX_CTL_CLEAR_PS_FILT for outgoing frames for a half-wake station. this is necessary if one wants to get ps-poll working properly with a p54 ap. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/tx.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3fb04a86444d..f336cc731df6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -409,8 +409,24 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) sta->sta.addr); } #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - clear_sta_flags(sta, WLAN_STA_PSPOLL); + if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { + /* + * The sleeping station with pending data is now snoozing. + * It queried us for its buffered frames and will go back + * to deep sleep once it got everything. + * + * inform the driver, in case the hardware does powersave + * frame filtering and keeps a station blacklist on its own + * (e.g: p54), so that frames can be delivered unimpeded. + * + * Note: It should be save to disable the filter now. + * As, it is really unlikely that we still have any pending + * frame for this station in the hw's buffers/fifos left, + * that is not rejected with a unsuccessful tx_status yet. + */ + info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; + } return TX_CONTINUE; } -- cgit v1.2.3 From d726405af6c8c81d2ee5e6a29301c68b9d4c574f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 19 Apr 2009 16:23:20 +0200 Subject: nl80211: send wiphy along with netdev When listing all wireless netdevs in the system this is useful to print which wiphy they belong to. Just add the attribute, any program that doesn't care will just ignore it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d33cab0e0fb2..d2cfde659e76 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -538,6 +538,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, + struct cfg80211_registered_device *rdev, struct net_device *dev) { void *hdr; @@ -547,6 +548,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, return -1; NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); return genlmsg_end(msg, hdr); @@ -581,7 +583,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * } if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - wdev->netdev) < 0) { + dev, wdev->netdev) < 0) { mutex_unlock(&dev->devlist_mtx); goto out; } @@ -615,7 +617,8 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) if (!msg) goto out_err; - if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) + if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, + dev, netdev) < 0) goto out_free; dev_put(netdev); -- cgit v1.2.3 From 691597cb26f236ac7471f1adf925a134c86799d6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 19 Apr 2009 19:57:45 +0200 Subject: cfg80211/mac80211: move wext SIWMLME into cfg80211 Since we have ->deauth and ->disassoc we can support the wext SIWMLME call directly without driver wext handlers. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 3 +++ net/mac80211/cfg.c | 12 ++++-------- net/mac80211/mlme.c | 6 ------ net/mac80211/wext.c | 25 +------------------------ net/wireless/wext-compat.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 39 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d303c269a693..019a41efa0bb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -833,6 +833,9 @@ int cfg80211_wext_siwscan(struct net_device *dev, int cfg80211_wext_giwscan(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); +int cfg80211_wext_siwmlme(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra); int cfg80211_wext_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 520efa8a0791..daf75287e92a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1268,22 +1268,18 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req) { - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* TODO: req->ie */ + /* TODO: req->ie, req->peer_addr */ return ieee80211_sta_deauthenticate(sdata, req->reason_code); } static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) { - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* TODO: req->ie */ + /* TODO: req->ie, req->peer_addr */ return ieee80211_sta_disassociate(sdata, req->reason_code); } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a16c9d724be1..428742d7f440 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2338,9 +2338,6 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", sdata->dev->name, reason); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EINVAL; - ieee80211_set_disassoc(sdata, true, true, reason); return 0; } @@ -2352,9 +2349,6 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", sdata->dev->name, reason); - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EINVAL; - if (!(ifmgd->flags & IEEE80211_STA_ASSOCIATED)) return -ENOLINK; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1c4664b8b1a0..896704cf94e1 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -612,29 +612,6 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev, return 0; } -static int ieee80211_ioctl_siwmlme(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct ieee80211_sub_if_data *sdata; - struct iw_mlme *mlme = (struct iw_mlme *) extra; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (!(sdata->vif.type == NL80211_IFTYPE_STATION)) - return -EINVAL; - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); - case IW_MLME_DISASSOC: - /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_disassociate(sdata, mlme->reason_code); - default: - return -EOPNOTSUPP; - } -} - static int ieee80211_ioctl_siwencode(struct net_device *dev, struct iw_request_info *info, @@ -1076,7 +1053,7 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* SIOCGIWTHRSPY */ (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */ + (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 0fd1db6e95bb..6fd7bf7b4481 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -206,7 +207,6 @@ int cfg80211_wext_giwrange(struct net_device *dev, range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { int i; struct ieee80211_supported_band *sband; @@ -241,3 +241,47 @@ int cfg80211_wext_giwrange(struct net_device *dev, return 0; } EXPORT_SYMBOL(cfg80211_wext_giwrange); + +int cfg80211_wext_siwmlme(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + struct cfg80211_registered_device *rdev; + union { + struct cfg80211_disassoc_request disassoc; + struct cfg80211_deauth_request deauth; + } cmd; + + if (!wdev) + return -EOPNOTSUPP; + + rdev = wiphy_to_dev(wdev->wiphy); + + if (wdev->iftype != NL80211_IFTYPE_STATION) + return -EINVAL; + + if (mlme->addr.sa_family != ARPHRD_ETHER) + return -EINVAL; + + memset(&cmd, 0, sizeof(cmd)); + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + if (!rdev->ops->deauth) + return -EOPNOTSUPP; + cmd.deauth.peer_addr = mlme->addr.sa_data; + cmd.deauth.reason_code = mlme->reason_code; + return rdev->ops->deauth(wdev->wiphy, dev, &cmd.deauth); + case IW_MLME_DISASSOC: + if (!rdev->ops->disassoc) + return -EOPNOTSUPP; + cmd.disassoc.peer_addr = mlme->addr.sa_data; + cmd.disassoc.reason_code = mlme->reason_code; + return rdev->ops->disassoc(wdev->wiphy, dev, &cmd.disassoc); + default: + return -EOPNOTSUPP; + } +} +EXPORT_SYMBOL(cfg80211_wext_siwmlme); -- cgit v1.2.3 From 04a773ade0680d862b479d7219973df60f7a3834 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 19 Apr 2009 21:24:32 +0200 Subject: cfg80211/nl80211: add IBSS API This adds IBSS API along with (preliminary) wext handlers. The wext handlers can only do IBSS so you need to call them from your own wext handlers if the mode is IBSS. The nl80211 API requires * an SSID * a channel (frequency) for the case that a new IBSS has to be created It optionally supports * a flag to fix the channel * a fixed BSSID The cfg80211 code also takes care to leave the IBSS before the netdev is set down. If wireless extensions are used, it also caches values when the interface is down and instructs the driver to join when the interface is set up. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 18 +++ include/net/cfg80211.h | 72 +++++++++ include/net/wireless.h | 14 ++ net/wireless/Makefile | 2 +- net/wireless/core.c | 16 ++ net/wireless/core.h | 8 + net/wireless/ibss.c | 360 +++++++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.c | 182 +++++++++++++++++++++-- net/wireless/nl80211.h | 4 + net/wireless/wext-compat.c | 30 ++++ 10 files changed, 693 insertions(+), 13 deletions(-) create mode 100644 net/wireless/ibss.c diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index c01423888db9..25ce3e42bd10 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -223,6 +223,15 @@ * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this * event matches with MLME-MICHAELMICFAILURE.indication() primitive * + * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a + * FREQ attribute (for the initial frequency if no peer can be found) + * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those + * should be fixed rather than automatically determined. Can only be + * executed on a network interface that is UP, and fixed BSSID/FREQ + * may be rejected. + * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is + * determined by the network interface. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -288,6 +297,9 @@ enum nl80211_commands { NL80211_CMD_REG_BEACON_HINT, + NL80211_CMD_JOIN_IBSS, + NL80211_CMD_LEAVE_IBSS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -456,6 +468,9 @@ enum nl80211_commands { * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported * cipher suites * + * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look + * for other networks on different channels + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -547,6 +562,9 @@ enum nl80211_attrs { NL80211_ATTR_FREQ_BEFORE, NL80211_ATTR_FREQ_AFTER, + + NL80211_ATTR_FREQ_FIXED, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 019a41efa0bb..5287a3e56e7c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -657,6 +657,31 @@ struct cfg80211_disassoc_request { size_t ie_len; }; +/** + * struct cfg80211_ibss_params - IBSS parameters + * + * This structure defines the IBSS parameters for the join_ibss() + * method. + * + * @ssid: The SSID, will always be non-null. + * @ssid_len: The length of the SSID, will always be non-zero. + * @bssid: Fixed BSSID requested, maybe be %NULL, if set do not + * search for IBSSs with a different BSSID. + * @channel: The channel to use if no IBSS can be found to join. + * @channel_fixed: The channel should be fixed -- do not search for + * IBSSs to join on other channels. + * @ie: information element(s) to include in the beacon + * @ie_len: length of that + */ +struct cfg80211_ibss_params { + u8 *ssid; + u8 *bssid; + struct ieee80211_channel *channel; + u8 *ie; + u8 ssid_len, ie_len; + bool channel_fixed; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -732,6 +757,11 @@ struct cfg80211_disassoc_request { * @assoc: Request to (re)associate with the specified peer * @deauth: Request to deauthenticate from the specified peer * @disassoc: Request to disassociate from the specified peer + * + * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call + * cfg80211_ibss_joined(), also call that function when changing BSSID due + * to a merge. + * @leave_ibss: Leave the IBSS. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy); @@ -817,6 +847,10 @@ struct cfg80211_ops { struct cfg80211_deauth_request *req); int (*disassoc)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); + + int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params); + int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); }; /* temporary wext handlers */ @@ -839,6 +873,28 @@ int cfg80211_wext_siwmlme(struct net_device *dev, int cfg80211_wext_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); +int cfg80211_ibss_wext_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); +int cfg80211_ibss_wext_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); +int cfg80211_ibss_wext_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); +int cfg80211_ibss_wext_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); +int cfg80211_ibss_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); +int cfg80211_ibss_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); + +/* wext helper for now (to be removed) */ +struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, + struct iw_freq *freq); /** * cfg80211_scan_done - notify that scan finished @@ -984,4 +1040,20 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, enum nl80211_key_type key_type, int key_id, const u8 *tsc); +/** + * cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS + * + * @dev: network device + * @bssid: the BSSID of the IBSS joined + * @gfp: allocation flags + * + * This function notifies cfg80211 that the device joined an IBSS or + * switched to a different BSSID. Before this function can be called, + * either a beacon has to have been received from the IBSS, or one of + * the cfg80211_inform_bss{,_frame} functions must have been called + * with the locally generated beacon -- this guarantees that there is + * always a scan result for this IBSS. cfg80211 will handle the rest. + */ +void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); + #endif /* __NET_CFG80211_H */ diff --git a/include/net/wireless.h b/include/net/wireless.h index 44c2642d3c06..abd27b033331 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -265,6 +265,8 @@ struct wiphy { * * @wiphy: pointer to hardware description * @iftype: interface type + * @list: (private) + * @netdev (private) */ struct wireless_dev { struct wiphy *wiphy; @@ -273,6 +275,18 @@ struct wireless_dev { /* private to the generic wireless code */ struct list_head list; struct net_device *netdev; + + /* currently used for IBSS - might be rearranged in the future */ + struct cfg80211_bss *current_bss; + u8 bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + +#ifdef CONFIG_WIRELESS_EXT + /* wext data */ + struct cfg80211_ibss_params wext; + u8 wext_bssid[ETH_ALEN]; +#endif }; /** diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 6d1e7b27b752..14ea01c4a103 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o -cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o +cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/net/wireless/core.c b/net/wireless/core.c index d1f556535f6d..de1ac51ae4e5 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -450,6 +450,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, dev->ieee80211_ptr->netdev = dev; mutex_unlock(&rdev->devlist_mtx); break; + case NETDEV_GOING_DOWN: + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) + break; + if (!dev->ieee80211_ptr->ssid_len) + break; + cfg80211_leave_ibss(rdev, dev); + break; + case NETDEV_UP: +#ifdef CONFIG_WIRELESS_EXT + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) + break; + if (!dev->ieee80211_ptr->wext.ssid_len) + break; + cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext); + break; +#endif case NETDEV_UNREGISTER: mutex_lock(&rdev->devlist_mtx); if (!list_empty(&dev->ieee80211_ptr->list)) { diff --git a/net/wireless/core.h b/net/wireless/core.h index 02668b02e331..2ef3595fd6e0 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -144,4 +144,12 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev); void cfg80211_bss_age(struct cfg80211_registered_device *dev, unsigned long age_secs); +/* IBSS */ +int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_ibss_params *params); +void cfg80211_clear_ibss(struct net_device *dev); +int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, + struct net_device *dev); + #endif /* __NET_WIRELESS_CORE_H */ diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c new file mode 100644 index 000000000000..2bf42fdef3a1 --- /dev/null +++ b/net/wireless/ibss.c @@ -0,0 +1,360 @@ +/* + * Some IBSS support code for cfg80211. + * + * Copyright 2009 Johannes Berg + */ + +#include +#include +#include +#include +#include "nl80211.h" + + +void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_bss *bss; +#ifdef CONFIG_WIRELESS_EXT + union iwreq_data wrqu; +#endif + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return; + + if (WARN_ON(!wdev->ssid_len)) + return; + + if (memcmp(bssid, wdev->bssid, ETH_ALEN) == 0) + return; + + bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, + wdev->ssid, wdev->ssid_len, + WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); + + if (WARN_ON(!bss)) + return; + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->current_bss); + } + + cfg80211_hold_bss(bss); + wdev->current_bss = bss; + memcpy(wdev->bssid, bssid, ETH_ALEN); + + nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp); +#ifdef CONFIG_WIRELESS_EXT + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); +#endif +} +EXPORT_SYMBOL(cfg80211_ibss_joined); + +int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; + + if (wdev->ssid_len) + return -EALREADY; + +#ifdef CONFIG_WIRELESS_EXT + wdev->wext.channel = params->channel; +#endif + err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); + + if (err) + return err; + + memcpy(wdev->ssid, params->ssid, params->ssid_len); + wdev->ssid_len = params->ssid_len; + + return 0; +} + +void cfg80211_clear_ibss(struct net_device *dev) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->current_bss); + } + + wdev->current_bss = NULL; + wdev->ssid_len = 0; + memset(wdev->bssid, 0, ETH_ALEN); +} + +int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, + struct net_device *dev) +{ + int err; + + err = rdev->ops->leave_ibss(&rdev->wiphy, dev); + + if (err) + return err; + + cfg80211_clear_ibss(dev); + + return 0; +} + +#ifdef CONFIG_WIRELESS_EXT +static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev) +{ + enum ieee80211_band band; + int i; + + /* try to find an IBSS channel if none requested ... */ + if (!wdev->wext.channel) { + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + + sband = rdev->wiphy.bands[band]; + if (!sband) + continue; + + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + if (chan->flags & IEEE80211_CHAN_NO_IBSS) + continue; + if (chan->flags & IEEE80211_CHAN_DISABLED) + continue; + wdev->wext.channel = chan; + break; + } + + if (wdev->wext.channel) + break; + } + + if (!wdev->wext.channel) + return -EINVAL; + } + + /* don't join -- SSID is not there */ + if (!wdev->wext.ssid_len) + return 0; + + if (!netif_running(wdev->netdev)) + return 0; + + return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), + wdev->netdev, &wdev->wext); +} + +int cfg80211_ibss_wext_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct ieee80211_channel *chan; + int err; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) + return -EOPNOTSUPP; + + chan = cfg80211_wext_freq(wdev->wiphy, freq); + if (chan && IS_ERR(chan)) + return PTR_ERR(chan); + + if (chan && + (chan->flags & IEEE80211_CHAN_NO_IBSS || + chan->flags & IEEE80211_CHAN_DISABLED)) + return -EINVAL; + + if (wdev->wext.channel == chan) + return 0; + + if (wdev->ssid_len) { + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), dev); + if (err) + return err; + } + + if (chan) { + wdev->wext.channel = chan; + wdev->wext.channel_fixed = true; + } else { + /* cfg80211_ibss_wext_join will pick one if needed */ + wdev->wext.channel_fixed = false; + } + + return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); +} +/* temporary symbol - mark GPL - in the future the handler won't be */ +EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); + +int cfg80211_ibss_wext_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct ieee80211_channel *chan = NULL; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (wdev->current_bss) + chan = wdev->current_bss->channel; + else if (wdev->wext.channel) + chan = wdev->wext.channel; + + if (chan) { + freq->m = chan->center_freq; + freq->e = 6; + return 0; + } + + /* no channel if not joining */ + return -EINVAL; +} +/* temporary symbol - mark GPL - in the future the handler won't be */ +EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwfreq); + +int cfg80211_ibss_wext_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + size_t len = data->length; + int err; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) + return -EOPNOTSUPP; + + if (wdev->ssid_len) { + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), dev); + if (err) + return err; + } + + /* iwconfig uses nul termination in SSID.. */ + if (len > 0 && ssid[len - 1] == '\0') + len--; + + wdev->wext.ssid = wdev->ssid; + memcpy(wdev->wext.ssid, ssid, len); + wdev->wext.ssid_len = len; + + return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); +} +/* temporary symbol - mark GPL - in the future the handler won't be */ +EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); + +int cfg80211_ibss_wext_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + data->flags = 0; + + if (wdev->ssid_len) { + data->flags = 1; + data->length = wdev->ssid_len; + memcpy(ssid, wdev->ssid, data->length); + } else if (wdev->wext.ssid) { + data->flags = 1; + data->length = wdev->wext.ssid_len; + memcpy(ssid, wdev->wext.ssid, data->length); + } + + return 0; +} +/* temporary symbol - mark GPL - in the future the handler won't be */ +EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwessid); + +int cfg80211_ibss_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + u8 *bssid = ap_addr->sa_data; + int err; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) + return -EOPNOTSUPP; + + if (ap_addr->sa_family != ARPHRD_ETHER) + return -EINVAL; + + /* automatic mode */ + if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) + bssid = NULL; + + /* both automatic */ + if (!bssid && !wdev->wext.bssid) + return 0; + + /* fixed already - and no change */ + if (wdev->wext.bssid && bssid && + compare_ether_addr(bssid, wdev->wext.bssid) == 0) + return 0; + + if (wdev->ssid_len) { + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), dev); + if (err) + return err; + } + + if (bssid) { + memcpy(wdev->wext_bssid, bssid, ETH_ALEN); + wdev->wext.bssid = wdev->wext_bssid; + } else + wdev->wext.bssid = NULL; + + return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); +} +/* temporary symbol - mark GPL - in the future the handler won't be */ +EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); + +int cfg80211_ibss_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + /* call only for ibss! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) + return -EINVAL; + + ap_addr->sa_family = ARPHRD_ETHER; + + if (wdev->wext.bssid) { + memcpy(ap_addr->sa_data, wdev->wext.bssid, ETH_ALEN); + return 0; + } + + memcpy(ap_addr->sa_data, wdev->bssid, ETH_ALEN); + return 0; +} +/* temporary symbol - mark GPL - in the future the handler won't be */ +EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwap); +#endif diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d2cfde659e76..16f86356ac97 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -116,6 +116,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { .len = IEEE80211_MAX_SSID_LEN }, [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 }, [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, + [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, }; /* IE validation */ @@ -322,6 +323,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(assoc, ASSOCIATE); CMD(deauth, DEAUTHENTICATE); CMD(disassoc, DISASSOCIATE); + CMD(join_ibss, JOIN_IBSS); #undef CMD nla_nest_end(msg, nl_cmds); @@ -668,7 +670,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *drv; struct vif_params params; int err, ifindex; - enum nl80211_iftype type; + enum nl80211_iftype otype, ntype; struct net_device *dev; u32 _flags, *flags = NULL; bool change = false; @@ -682,30 +684,27 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) goto unlock_rtnl; ifindex = dev->ifindex; - type = dev->ieee80211_ptr->iftype; + otype = ntype = dev->ieee80211_ptr->iftype; dev_put(dev); if (info->attrs[NL80211_ATTR_IFTYPE]) { - enum nl80211_iftype ntype; - ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); - if (type != ntype) + if (otype != ntype) change = true; - type = ntype; - if (type > NL80211_IFTYPE_MAX) { + if (ntype > NL80211_IFTYPE_MAX) { err = -EINVAL; goto unlock; } } if (!drv->ops->change_virtual_intf || - !(drv->wiphy.interface_modes & (1 << type))) { + !(drv->wiphy.interface_modes & (1 << ntype))) { err = -EOPNOTSUPP; goto unlock; } if (info->attrs[NL80211_ATTR_MESH_ID]) { - if (type != NL80211_IFTYPE_MESH_POINT) { + if (ntype != NL80211_IFTYPE_MESH_POINT) { err = -EINVAL; goto unlock; } @@ -715,7 +714,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { - if (type != NL80211_IFTYPE_MONITOR) { + if (ntype != NL80211_IFTYPE_MONITOR) { err = -EINVAL; goto unlock; } @@ -730,12 +729,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) if (change) err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, - type, flags, ¶ms); + ntype, flags, ¶ms); else err = 0; dev = __dev_get_by_index(&init_net, ifindex); - WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); + WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != ntype)); + + if (dev && !err && (ntype != otype)) { + if (otype == NL80211_IFTYPE_ADHOC) + cfg80211_clear_ibss(dev); + } unlock: cfg80211_put_dev(drv); @@ -3052,6 +3056,114 @@ unlock_rtnl: return err; } +static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + struct cfg80211_ibss_params ibss; + struct wiphy *wiphy; + int err; + + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || + !info->attrs[NL80211_ATTR_SSID] || + !nla_len(info->attrs[NL80211_ATTR_SSID])) + return -EINVAL; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->join_ibss) { + err = -EOPNOTSUPP; + goto out; + } + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + wiphy = &drv->wiphy; + memset(&ibss, 0, sizeof(ibss)); + + if (info->attrs[NL80211_ATTR_MAC]) + ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); + ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); + ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + + if (info->attrs[NL80211_ATTR_IE]) { + ibss.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + ibss.channel = ieee80211_get_channel(wiphy, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); + if (!ibss.channel || + ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || + ibss.channel->flags & IEEE80211_CHAN_DISABLED) { + err = -EINVAL; + goto out; + } + + ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; + + err = cfg80211_join_ibss(drv, dev, &ibss); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + struct net_device *dev; + int err; + + rtnl_lock(); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + goto unlock_rtnl; + + if (!drv->ops->leave_ibss) { + err = -EOPNOTSUPP; + goto out; + } + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + err = cfg80211_leave_ibss(drv, dev); + +out: + cfg80211_put_dev(drv); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -3253,6 +3365,18 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_JOIN_IBSS, + .doit = nl80211_join_ibss, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_LEAVE_IBSS, + .doit = nl80211_leave_ibss, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { .name = "mlme", @@ -3466,6 +3590,40 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, NL80211_CMD_DISASSOCIATE); } +void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *bssid, + gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_JOIN_IBSS); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, enum nl80211_key_type key_type, int key_id, diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b3aaa59afa08..17d2d8bfaf75 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -34,4 +34,8 @@ nl80211_send_beacon_hint_event(struct wiphy *wiphy, struct ieee80211_channel *channel_before, struct ieee80211_channel *channel_after); +void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *bssid, + gfp_t gfp); + #endif /* __NET_WIRELESS_NL80211_H */ diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 6fd7bf7b4481..57eaea26b67a 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -285,3 +285,33 @@ int cfg80211_wext_siwmlme(struct net_device *dev, } } EXPORT_SYMBOL(cfg80211_wext_siwmlme); + + +/** + * cfg80211_wext_freq - get wext frequency for non-"auto" + * @wiphy: the wiphy + * @freq: the wext freq encoding + * + * Returns a channel, %NULL for auto, or an ERR_PTR for errors! + */ +struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, + struct iw_freq *freq) +{ + if (freq->e == 0) { + if (freq->m < 0) + return NULL; + else + return ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(freq->m)); + } else { + int i, div = 1000000; + for (i = 0; i < freq->e; i++) + div /= 10; + if (div > 0) + return ieee80211_get_channel(wiphy, freq->m / div); + else + return ERR_PTR(-EINVAL); + } + +} +EXPORT_SYMBOL(cfg80211_wext_freq); -- cgit v1.2.3 From af8cdcd828ad751fae8e6cbfe94eef9f2f23b14b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 19 Apr 2009 21:25:43 +0200 Subject: mac80211: convert to cfg80211 IBSS API This converts mac80211 to the new cfg80211 IBSS API, the wext handling functions are called where appropriate. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 17 +++ net/mac80211/ibss.c | 347 +++++++++++++++++++++------------------------ net/mac80211/ieee80211_i.h | 35 ++--- net/mac80211/iface.c | 12 +- net/mac80211/main.c | 2 +- net/mac80211/scan.c | 2 - net/mac80211/sta_info.c | 71 +--------- net/mac80211/sta_info.h | 3 +- net/mac80211/tx.c | 6 +- net/mac80211/wext.c | 63 ++++---- 10 files changed, 228 insertions(+), 330 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index daf75287e92a..14013dc64474 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1283,6 +1283,21 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, return ieee80211_sta_disassociate(sdata, req->reason_code); } +static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + return ieee80211_ibss_join(sdata, params); +} + +static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + return ieee80211_ibss_leave(sdata); +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1319,4 +1334,6 @@ struct cfg80211_ops mac80211_config_ops = { .assoc = ieee80211_assoc, .deauth = ieee80211_deauth, .disassoc = ieee80211_disassoc, + .join_ibss = ieee80211_join_ibss, + .leave_ibss = ieee80211_leave_ibss, }; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3201e1f96365..4f7a54518be4 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -59,74 +59,59 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.bssid, 0); } -static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, - const u8 *bssid, const int beacon_int, - const int freq, - const size_t supp_rates_len, - const u8 *supp_rates, - const u16 capability, u64 tsf) +static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, + const u8 *bssid, const int beacon_int, + struct ieee80211_channel *chan, + const size_t supp_rates_len, + const u8 *supp_rates, + const u16 capability, u64 tsf) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; - int res = 0, rates, i, j; + int rates, i, j; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; struct ieee80211_supported_band *sband; - union iwreq_data wrqu; if (local->ops->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ local->ops->reset_tsf(local_to_hw(local)); } - if ((ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) && - memcmp(ifibss->bssid, bssid, ETH_ALEN) == 0) - return res; + skb = ifibss->skb; + rcu_assign_pointer(ifibss->presp, NULL); + synchronize_rcu(); + skb->data = skb->head; + skb->len = 0; + skb_reset_tail_pointer(skb); + skb_reserve(skb, sdata->local->hw.extra_tx_headroom); - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "response\n", sdata->dev->name); - return -ENOMEM; - } - - if (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) { - /* Remove possible STA entries from other IBSS networks. */ - sta_info_flush_delayed(sdata); - } + if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) + sta_info_flush(sdata->local, sdata); memcpy(ifibss->bssid, bssid, ETH_ALEN); - res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); - if (res) - return res; local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; - sdata->drop_unencrypted = capability & - WLAN_CAPABILITY_PRIVACY ? 1 : 0; - - res = ieee80211_set_freq(sdata, freq); + sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - if (res) - return res; + ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + local->oper_channel = chan; + local->oper_channel_type = NL80211_CHAN_NO_HT; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + sband = local->hw.wiphy->bands[chan->band]; /* Build IBSS probe response */ - - skb_reserve(skb, local->hw.extra_tx_headroom); - - mgmt = (struct ieee80211_mgmt *) - skb_put(skb, 24 + sizeof(mgmt->u.beacon)); + mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); - mgmt->u.beacon.beacon_int = - cpu_to_le16(local->hw.conf.beacon_int); + mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int); mgmt->u.beacon.timestamp = cpu_to_le64(tsf); mgmt->u.beacon.capab_info = cpu_to_le16(capability); @@ -147,7 +132,7 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, pos = skb_put(skb, 2 + 1); *pos++ = WLAN_EID_DS_PARAMS; *pos++ = 1; - *pos++ = ieee80211_frequency_to_channel(freq); + *pos++ = ieee80211_frequency_to_channel(chan->center_freq); } pos = skb_put(skb, 2 + 2); @@ -165,12 +150,15 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, memcpy(pos, &supp_rates[8], rates); } - ifibss->probe_resp = skb; + if (ifibss->ie_len) + memcpy(skb_put(skb, ifibss->ie_len), + ifibss->ie, ifibss->ie_len); + + rcu_assign_pointer(ifibss->presp, skb); ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | IEEE80211_IFCC_BEACON_ENABLED); - rates = 0; for (i = 0; i < supp_rates_len; i++) { int bitrate = (supp_rates[i] & 0x7f) * 5; @@ -181,27 +169,24 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); - ifibss->flags |= IEEE80211_IBSS_PREV_BSSID_SET; ifibss->state = IEEE80211_IBSS_MLME_JOINED; - mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + mod_timer(&ifibss->timer, + round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); - wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); - - return res; + cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, + mgmt, skb->len, 0, GFP_KERNEL); + cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); } -static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, - struct ieee80211_bss *bss) +static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss *bss) { - return __ieee80211_sta_join_ibss(sdata, - bss->cbss.bssid, - bss->cbss.beacon_interval, - bss->cbss.channel->center_freq, - bss->supp_rates_len, bss->supp_rates, - bss->cbss.capability, - bss->cbss.tsf); + __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, + bss->cbss.beacon_interval, + bss->cbss.channel, + bss->supp_rates_len, bss->supp_rates, + bss->cbss.capability, + bss->cbss.tsf); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, @@ -277,7 +262,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, goto put_bss; /* we use a fixed BSSID */ - if (sdata->u.ibss.flags & IEEE80211_IBSS_BSSID_SET) + if (sdata->u.ibss.bssid) goto put_bss; /* not an IBSS */ @@ -369,13 +354,14 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; int band = local->hw.conf.channel->band; - /* TODO: Could consider removing the least recently used entry and - * allow new one to be added. */ + /* + * XXX: Consider removing the least recently used entry and + * allow new one to be added. + */ if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: No room for a new IBSS STA " - "entry %pM\n", sdata->dev->name, addr); - } + if (net_ratelimit()) + printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", + sdata->dev->name, addr); return NULL; } @@ -432,14 +418,15 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + mod_timer(&ifibss->timer, + round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); + if (ieee80211_sta_active_ibss(sdata)) return; - if ((ifibss->flags & IEEE80211_IBSS_BSSID_SET) && - (!(ifibss->flags & IEEE80211_IBSS_AUTO_CHANNEL_SEL))) + if (ifibss->fixed_channel) return; printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " @@ -455,7 +442,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) ieee80211_request_scan(sdata, &sdata->local->int_scan_req); } -static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) +static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; @@ -466,7 +453,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) u16 capability; int i; - if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) { + if (ifibss->fixed_bssid) { memcpy(bssid, ifibss->bssid, ETH_ALEN); } else { /* Generate random, not broadcast, locally administered BSSID. Mix in @@ -482,7 +469,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", sdata->dev->name, bssid); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = local->hw.wiphy->bands[ifibss->channel->band]; if (local->hw.conf.beacon_int == 0) local->hw.conf.beacon_int = 100; @@ -500,24 +487,20 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) *pos++ = (u8) (rate / 5); } - return __ieee80211_sta_join_ibss(sdata, - bssid, local->hw.conf.beacon_int, - local->hw.conf.channel->center_freq, - sband->n_bitrates, supp_rates, - capability, 0); + __ieee80211_sta_join_ibss(sdata, bssid, local->hw.conf.beacon_int, + ifibss->channel, sband->n_bitrates, + supp_rates, capability, 0); } -static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) +static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; struct ieee80211_bss *bss; + struct ieee80211_channel *chan = NULL; const u8 *bssid = NULL; int active_ibss; - if (ifibss->ssid_len == 0) - return -EINVAL; - active_ibss = ieee80211_sta_active_ibss(sdata); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", @@ -525,11 +508,15 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (active_ibss) - return 0; + return; - if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) + if (ifibss->fixed_bssid) + bssid = ifibss->bssid; + if (ifibss->fixed_channel) + chan = ifibss->channel; + if (!is_zero_ether_addr(ifibss->bssid)) bssid = ifibss->bssid; - bss = (void *)cfg80211_get_bss(local->hw.wiphy, NULL, bssid, + bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, ifibss->ssid, ifibss->ssid_len, WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); @@ -540,18 +527,14 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) "%pM\n", bss->cbss.bssid, ifibss->bssid); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (bss && - (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) || - memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN))) { - int ret; - + if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) { printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" " based on configured SSID\n", sdata->dev->name, bss->cbss.bssid); - ret = ieee80211_sta_join_ibss(sdata, bss); + ieee80211_sta_join_ibss(sdata, bss); ieee80211_rx_bss_put(local, bss); - return ret; + return; } else if (bss) ieee80211_rx_bss_put(local, bss); @@ -562,29 +545,31 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) /* Selected IBSS not found in current scan results - try to scan */ if (ifibss->state == IEEE80211_IBSS_MLME_JOINED && !ieee80211_sta_active_ibss(sdata)) { - mod_timer(&ifibss->timer, jiffies + - IEEE80211_IBSS_MERGE_INTERVAL); - } else if (time_after(jiffies, local->last_scan_completed + + mod_timer(&ifibss->timer, + round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); + } else if (time_after(jiffies, ifibss->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->dev->name); /* XXX maybe racy? */ if (local->scan_req) - return -EBUSY; + return; memcpy(local->int_scan_req.ssids[0].ssid, ifibss->ssid, IEEE80211_MAX_SSID_LEN); - local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; - return ieee80211_request_scan(sdata, &local->int_scan_req); + local->int_scan_req.ssids[0].ssid_len = + ifibss->ssid_len; + ieee80211_request_scan(sdata, &local->int_scan_req); } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, ifibss->ibss_join_req + IEEE80211_IBSS_JOIN_TIMEOUT)) { - if (!(local->oper_channel->flags & - IEEE80211_CHAN_NO_IBSS)) - return ieee80211_sta_create_ibss(sdata); + if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) { + ieee80211_sta_create_ibss(sdata); + return; + } printk(KERN_DEBUG "%s: IBSS not allowed on" " %d MHz\n", sdata->dev->name, local->hw.conf.channel->center_freq); @@ -595,11 +580,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) } ifibss->state = IEEE80211_IBSS_MLME_SEARCH; - mod_timer(&ifibss->timer, jiffies + interval); - return 0; + mod_timer(&ifibss->timer, + round_jiffies(jiffies + interval)); } - - return 0; } static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, @@ -614,7 +597,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, u8 *pos, *end; if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || - len < 24 + 2 || !ifibss->probe_resp) + len < 24 + 2 || !ifibss->presp) return; if (local->ops->tx_last_beacon) @@ -649,13 +632,13 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, } if (pos[1] != 0 && (pos[1] != ifibss->ssid_len || - memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len) != 0)) { + !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { /* Ignore ProbeReq for foreign SSID */ return; } /* Reply with ProbeResp */ - skb = skb_copy(ifibss->probe_resp, GFP_KERNEL); + skb = skb_copy(ifibss->presp, GFP_KERNEL); if (!skb) return; @@ -794,89 +777,21 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) setup_timer(&ifibss->timer, ieee80211_ibss_timer, (unsigned long) sdata); skb_queue_head_init(&ifibss->skb_queue); - - ifibss->flags |= IEEE80211_IBSS_AUTO_BSSID_SEL | - IEEE80211_IBSS_AUTO_CHANNEL_SEL; -} - -int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - ifibss->flags &= ~IEEE80211_IBSS_PREV_BSSID_SET; - - if (ifibss->ssid_len) - ifibss->flags |= IEEE80211_IBSS_SSID_SET; - else - ifibss->flags &= ~IEEE80211_IBSS_SSID_SET; - - ifibss->ibss_join_req = jiffies; - ifibss->state = IEEE80211_IBSS_MLME_SEARCH; - set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); - - return 0; -} - -int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - if (len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - - if (ifibss->ssid_len != len || memcmp(ifibss->ssid, ssid, len) != 0) { - memset(ifibss->ssid, 0, sizeof(ifibss->ssid)); - memcpy(ifibss->ssid, ssid, len); - ifibss->ssid_len = len; - } - - return ieee80211_ibss_commit(sdata); -} - -int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - memcpy(ssid, ifibss->ssid, ifibss->ssid_len); - *len = ifibss->ssid_len; - - return 0; -} - -int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) -{ - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - if (is_valid_ether_addr(bssid)) { - memcpy(ifibss->bssid, bssid, ETH_ALEN); - ifibss->flags |= IEEE80211_IBSS_BSSID_SET; - } else { - memset(ifibss->bssid, 0, ETH_ALEN); - ifibss->flags &= ~IEEE80211_IBSS_BSSID_SET; - } - - if (netif_running(sdata->dev)) { - if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", sdata->dev->name); - } - } - - return ieee80211_ibss_commit(sdata); } /* scan finished notification */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) { - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - struct ieee80211_if_ibss *ifibss; + struct ieee80211_sub_if_data *sdata; - if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { - ifibss = &sdata->u.ibss; - if ((!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) || - !ieee80211_sta_active_ibss(sdata)) - ieee80211_sta_find_ibss(sdata); + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_ADHOC) + continue; + sdata->u.ibss.last_scan_completed = jiffies; + ieee80211_sta_find_ibss(sdata); } + rcu_read_unlock(); } ieee80211_rx_result @@ -906,3 +821,71 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_DROP_MONITOR; } + +int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, + struct cfg80211_ibss_params *params) +{ + struct sk_buff *skb; + + memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + sdata->u.ibss.ssid_len = params->ssid_len; + + if (params->bssid) { + memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); + sdata->u.ibss.fixed_bssid = true; + } else + sdata->u.ibss.fixed_bssid = false; + + sdata->u.ibss.channel = params->channel; + sdata->u.ibss.fixed_channel = params->channel_fixed; + + if (params->ie) { + sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, + GFP_KERNEL); + if (sdata->u.ibss.ie) + sdata->u.ibss.ie_len = params->ie_len; + } + + skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + + 36 /* bitrates */ + + 34 /* SSID */ + + 3 /* DS params */ + + 4 /* IBSS params */ + + params->ie_len); + if (!skb) + return -ENOMEM; + + sdata->u.ibss.skb = skb; + sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; + sdata->u.ibss.ibss_join_req = jiffies; + + set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); + queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); + + return 0; +} + +int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) +{ + struct sk_buff *skb; + + del_timer_sync(&sdata->u.ibss.timer); + clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); + cancel_work_sync(&sdata->u.ibss.work); + clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); + + sta_info_flush(sdata->local, sdata); + + /* remove beacon */ + kfree(sdata->u.ibss.ie); + skb = sdata->u.ibss.presp; + rcu_assign_pointer(sdata->u.ibss.presp, NULL); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); + synchronize_rcu(); + kfree_skb(skb); + + skb_queue_purge(&sdata->u.ibss.skb_queue); + memset(sdata->u.ibss.bssid, 0, ETH_ALEN); + + return 0; +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 38c980612518..e770c1e8e08c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -323,14 +323,6 @@ struct ieee80211_if_managed { size_t sme_auth_ie_len; }; -enum ieee80211_ibss_flags { - IEEE80211_IBSS_AUTO_CHANNEL_SEL = BIT(0), - IEEE80211_IBSS_AUTO_BSSID_SEL = BIT(1), - IEEE80211_IBSS_BSSID_SET = BIT(2), - IEEE80211_IBSS_PREV_BSSID_SET = BIT(3), - IEEE80211_IBSS_SSID_SET = BIT(4), -}; - enum ieee80211_ibss_request { IEEE80211_IBSS_REQ_RUN = 0, }; @@ -341,17 +333,20 @@ struct ieee80211_if_ibss { struct sk_buff_head skb_queue; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - - u32 flags; + unsigned long request; + unsigned long last_scan_completed; + bool fixed_bssid; + bool fixed_channel; u8 bssid[ETH_ALEN]; - - unsigned long request; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len, ie_len; + u8 *ie; + struct ieee80211_channel *channel; unsigned long ibss_join_req; - struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ + /* probe response/beacon for IBSS */ + struct sk_buff *presp, *skb; enum { IEEE80211_IBSS_MLME_SEARCH, @@ -630,8 +625,6 @@ struct ieee80211_local { spinlock_t sta_lock; unsigned long num_sta; struct list_head sta_list; - struct list_head sta_flush_list; - struct work_struct sta_flush_work; struct sta_info *sta_hash[STA_HASH_SIZE]; struct timer_list sta_cleanup; @@ -681,7 +674,6 @@ struct ieee80211_local { int scan_ies_len; enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; - unsigned long last_scan_completed; struct delayed_work scan_work; struct ieee80211_sub_if_data *scan_sdata; enum nl80211_channel_type oper_channel_type; @@ -946,10 +938,6 @@ int ieee80211_max_network_latency(struct notifier_block *nb, unsigned long data, void *dummy); /* IBSS code */ -int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata); -int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); -int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); -int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); ieee80211_rx_result @@ -957,6 +945,9 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, u8 *bssid, u8 *addr, u32 supp_rates); +int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, + struct cfg80211_ibss_params *params); +int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 5d60deb219d3..52425975bbbe 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -235,11 +235,7 @@ static int ieee80211_open(struct net_device *dev) netif_addr_unlock_bh(local->mdev); break; case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - if (sdata->vif.type == NL80211_IFTYPE_STATION) - sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; - else - sdata->u.ibss.flags &= ~IEEE80211_IBSS_PREV_BSSID_SET; + sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; /* fall through */ default: conf.vif = &sdata->vif; @@ -327,8 +323,6 @@ static int ieee80211_open(struct net_device *dev) */ if (sdata->vif.type == NL80211_IFTYPE_STATION) queue_work(local->hw.workqueue, &sdata->u.mgd.work); - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - queue_work(local->hw.workqueue, &sdata->u.ibss.work); netif_tx_start_all_queues(dev); @@ -499,7 +493,6 @@ static int ieee80211_stop(struct net_device *dev) /* fall through */ case NL80211_IFTYPE_ADHOC: if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.ibss.timer); cancel_work_sync(&sdata->u.ibss.work); synchronize_rcu(); @@ -653,7 +646,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev) mesh_rmc_free(sdata); break; case NL80211_IFTYPE_ADHOC: - kfree_skb(sdata->u.ibss.probe_resp); + if (WARN_ON(sdata->u.ibss.presp)) + kfree_skb(sdata->u.ibss.presp); break; case NL80211_IFTYPE_STATION: kfree(sdata->u.mgd.extra_ie); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 049ce8639806..d26fc399285e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -209,7 +209,7 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) !!rcu_dereference(sdata->u.ap.beacon); break; case NL80211_IFTYPE_ADHOC: - conf.enable_beacon = !!sdata->u.ibss.probe_resp; + conf.enable_beacon = !!sdata->u.ibss.presp; break; case NL80211_IFTYPE_MESH_POINT: conf.enable_beacon = true; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 20df861c6c4c..f25b07feabf9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -295,8 +295,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; - local->last_scan_completed = jiffies; - if (local->hw_scanning) { local->hw_scanning = false; /* diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c5f14e6bbde2..654a8e963ccb 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -686,41 +686,10 @@ static void sta_info_debugfs_add_work(struct work_struct *work) } #endif -static void __ieee80211_run_pending_flush(struct ieee80211_local *local) -{ - struct sta_info *sta; - unsigned long flags; - - ASSERT_RTNL(); - - spin_lock_irqsave(&local->sta_lock, flags); - while (!list_empty(&local->sta_flush_list)) { - sta = list_first_entry(&local->sta_flush_list, - struct sta_info, list); - list_del(&sta->list); - spin_unlock_irqrestore(&local->sta_lock, flags); - sta_info_destroy(sta); - spin_lock_irqsave(&local->sta_lock, flags); - } - spin_unlock_irqrestore(&local->sta_lock, flags); -} - -static void ieee80211_sta_flush_work(struct work_struct *work) -{ - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, sta_flush_work); - - rtnl_lock(); - __ieee80211_run_pending_flush(local); - rtnl_unlock(); -} - void sta_info_init(struct ieee80211_local *local) { spin_lock_init(&local->sta_lock); INIT_LIST_HEAD(&local->sta_list); - INIT_LIST_HEAD(&local->sta_flush_list); - INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work); setup_timer(&local->sta_cleanup, sta_info_cleanup, (unsigned long)local); @@ -741,7 +710,6 @@ int sta_info_start(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { del_timer(&local->sta_cleanup); - cancel_work_sync(&local->sta_flush_work); #ifdef CONFIG_MAC80211_DEBUGFS /* * Make sure the debugfs adding work isn't pending after this @@ -752,10 +720,7 @@ void sta_info_stop(struct ieee80211_local *local) cancel_work_sync(&local->sta_debugfs_add); #endif - rtnl_lock(); sta_info_flush(local, NULL); - __ieee80211_run_pending_flush(local); - rtnl_unlock(); } /** @@ -767,7 +732,7 @@ void sta_info_stop(struct ieee80211_local *local) * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs */ int sta_info_flush(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) + struct ieee80211_sub_if_data *sdata) { struct sta_info *sta, *tmp; LIST_HEAD(tmp_list); @@ -775,7 +740,6 @@ int sta_info_flush(struct ieee80211_local *local, unsigned long flags; might_sleep(); - ASSERT_RTNL(); spin_lock_irqsave(&local->sta_lock, flags); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { @@ -795,39 +759,6 @@ int sta_info_flush(struct ieee80211_local *local, return ret; } -/** - * sta_info_flush_delayed - flush matching STA entries from the STA table - * - * This function unlinks all stations for a given interface and queues - * them for freeing. Note that the workqueue function scheduled here has - * to run before any new keys can be added to the system to avoid set_key() - * callback ordering issues. - * - * @sdata: the interface - */ -void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta, *tmp; - unsigned long flags; - bool work = false; - - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { - if (sdata == sta->sdata) { - __sta_info_unlink(&sta); - if (sta) { - list_add_tail(&sta->list, - &local->sta_flush_list); - work = true; - } - } - } - if (work) - schedule_work(&local->sta_flush_work); - spin_unlock_irqrestore(&local->sta_lock, flags); -} - void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5534d489f506..31a8990ce401 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -442,8 +442,7 @@ void sta_info_init(struct ieee80211_local *local); int sta_info_start(struct ieee80211_local *local); void sta_info_stop(struct ieee80211_local *local); int sta_info_flush(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata); -void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); + struct ieee80211_sub_if_data *sdata); void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f336cc731df6..c53d77db3e4f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2102,18 +2102,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_hdr *hdr; + struct sk_buff *presp = rcu_dereference(ifibss->presp); - if (!ifibss->probe_resp) + if (!presp) goto out; - skb = skb_copy(ifibss->probe_resp, GFP_ATOMIC); + skb = skb_copy(presp, GFP_ATOMIC); if (!skb) goto out; hdr = (struct ieee80211_hdr *) skb->data; hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - } else if (ieee80211_vif_is_mesh(&sdata->vif)) { struct ieee80211_mgmt *mgmt; u8 *pos; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 896704cf94e1..eb63fc148019 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -149,17 +149,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_CHANNEL_SEL; + return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); else if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ if (freq->e == 0) { if (freq->m < 0) { - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - sdata->u.ibss.flags |= - IEEE80211_IBSS_AUTO_CHANNEL_SEL; - else if (sdata->vif.type == NL80211_IFTYPE_STATION) + if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; @@ -183,6 +180,10 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_freq *freq, char *extra) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); freq->m = local->hw.conf.channel->center_freq; freq->e = 6; @@ -195,15 +196,17 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); size_t len = data->length; int ret; + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); + /* iwconfig uses nul termination in SSID.. */ if (len > 0 && ssid[len - 1] == '\0') len--; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (data->flags) sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; @@ -217,8 +220,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; ieee80211_sta_req_auth(sdata); return 0; - } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return ieee80211_ibss_set_ssid(sdata, ssid, len); + } return -EOPNOTSUPP; } @@ -229,9 +231,13 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, struct iw_point *data, char *ssid) { size_t len; - struct ieee80211_sub_if_data *sdata; + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); + if (sdata->vif.type == NL80211_IFTYPE_STATION) { int res = ieee80211_sta_get_ssid(sdata, ssid, &len); if (res == 0) { @@ -240,14 +246,6 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, } else data->flags = 0; return res; - } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - int res = ieee80211_ibss_get_ssid(sdata, ssid, &len); - if (res == 0) { - data->length = len; - data->flags = 1; - } else - data->flags = 0; - return res; } return -EOPNOTSUPP; @@ -258,9 +256,11 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { int ret; @@ -277,16 +277,6 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; ieee80211_sta_req_auth(sdata); return 0; - } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) - sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL | - IEEE80211_IBSS_AUTO_CHANNEL_SEL; - else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data)) - sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL; - else - sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_BSSID_SEL; - - return ieee80211_ibss_set_bssid(sdata, (u8 *) &ap_addr->sa_data); } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { /* * If it is necessary to update the WDS peer address @@ -312,9 +302,11 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { ap_addr->sa_family = ARPHRD_ETHER; @@ -322,13 +314,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, } else memset(&ap_addr->sa_data, 0, ETH_ALEN); return 0; - } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - if (sdata->u.ibss.state == IEEE80211_IBSS_MLME_JOINED) { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(&ap_addr->sa_data, sdata->u.ibss.bssid, ETH_ALEN); - } else - memset(&ap_addr->sa_data, 0, ETH_ALEN); - return 0; } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { ap_addr->sa_family = ARPHRD_ETHER; memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); -- cgit v1.2.3 From d323655372590c533c275b1d798f9d1221efb5c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 14:31:42 +0200 Subject: cfg80211: clean up includes Trying to separate header files into net/wireless.h and net/cfg80211.h has been a source of confusion. Remove net/wireless.h (because there also is the linux/wireless.h) and subsume everything into net/cfg80211.h -- except the definitions for regulatory structures which get moved to a new header net/regulatory.h. The "new" net/cfg80211.h is now divided into sections. There are no real changes in this patch but code shuffling and some very minor documentation fixes. I have also, to make things reflect reality, put in a copyright line for Luis to net/regulatory.h since that is probably exclusively written by him but was formerly in a file that only had my copyright line. Signed-off-by: Johannes Berg Cc: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 2 +- drivers/net/wireless/ath/ar9170/usb.h | 2 +- drivers/net/wireless/ath/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath/regd.c | 1 - drivers/net/wireless/ath/regd.h | 1 - drivers/net/wireless/rndis_wlan.c | 1 - include/net/cfg80211.h | 709 +++++++++++++++++++++++++------ include/net/mac80211.h | 1 - include/net/regulatory.h | 101 +++++ include/net/wireless.h | 492 --------------------- net/mac80211/ht.c | 1 - net/mac80211/ieee80211_i.h | 1 - net/mac80211/spectmgmt.c | 2 +- net/wireless/core.c | 1 - net/wireless/core.h | 1 - net/wireless/ibss.c | 1 - net/wireless/reg.c | 1 - net/wireless/util.c | 6 +- net/wireless/wext-compat.c | 1 - 19 files changed, 690 insertions(+), 637 deletions(-) create mode 100644 include/net/regulatory.h delete mode 100644 include/net/wireless.h diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index f797495faa56..2522a190fdfb 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -40,7 +40,7 @@ #include #include -#include +#include #include #ifdef CONFIG_AR9170_LEDS #include diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index f5852924cd64..ac42586495d8 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include "eeprom.h" diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 9a7715df5cff..7c59dc47f912 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -17,7 +17,7 @@ #ifndef EEPROM_H #define EEPROM_H -#include +#include #define AH_USE_EEPROM 0x1 diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 526c7f1308db..fdf07c822081 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "regd.h" #include "regd_common.h" diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index eba7c7123b50..07291ccb23f2 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -20,7 +20,6 @@ #include #include -#include #define NO_CTL 0xff #define SD_NO_CTL 0xE0 diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 239e6a14eae2..43e0ba61df24 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5287a3e56e7c..601eac64b02d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1,70 +1,217 @@ #ifndef __NET_CFG80211_H #define __NET_CFG80211_H +/* + * 802.11 device and configuration interface + * + * Copyright 2006-2009 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include #include #include #include #include #include -#include -#include -#include +#include + /* remove once we remove the wext stuff */ +#include +#include + /* - * 802.11 configuration in-kernel interface + * wireless hardware capability structures + */ + +/** + * enum ieee80211_band - supported frequency bands + * + * The bands are assigned this way because the supported + * bitrates differ in these bands. * - * Copyright 2006, 2007 Johannes Berg + * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band + * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) */ +enum ieee80211_band { + IEEE80211_BAND_2GHZ, + IEEE80211_BAND_5GHZ, + + /* keep last */ + IEEE80211_NUM_BANDS +}; /** - * struct vif_params - describes virtual interface parameters - * @mesh_id: mesh ID to use - * @mesh_id_len: length of the mesh ID + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted + * on this channel. + * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel + * is not permitted. */ -struct vif_params { - u8 *mesh_id; - int mesh_id_len; +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = 1<<0, + IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, + IEEE80211_CHAN_NO_IBSS = 1<<2, + IEEE80211_CHAN_RADAR = 1<<3, + IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, + IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, }; -/* Radiotap header iteration - * implemented in net/wireless/radiotap.c - * docs in Documentation/networking/radiotap-headers.txt +/** + * struct ieee80211_channel - channel definition + * + * This structure describes a single channel for use + * with cfg80211. + * + * @center_freq: center frequency in MHz + * @max_bandwidth: maximum allowed bandwidth for this channel, in MHz + * @hw_value: hardware-specific value for the channel + * @flags: channel flags from &enum ieee80211_channel_flags. + * @orig_flags: channel flags at registration time, used by regulatory + * code to support devices with additional restrictions + * @band: band this channel belongs to. + * @max_antenna_gain: maximum antenna gain in dBi + * @max_power: maximum transmission power (in dBm) + * @beacon_found: helper to regulatory code to indicate when a beacon + * has been found on this channel. Use regulatory_hint_found_beacon() + * to enable this, this is is useful only on 5 GHz band. + * @orig_mag: internal use + * @orig_mpwr: internal use */ +struct ieee80211_channel { + enum ieee80211_band band; + u16 center_freq; + u8 max_bandwidth; + u16 hw_value; + u32 flags; + int max_antenna_gain; + int max_power; + bool beacon_found; + u32 orig_flags; + int orig_mag, orig_mpwr; +}; + /** - * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args - * @rtheader: pointer to the radiotap header we are walking through - * @max_length: length of radiotap header in cpu byte ordering - * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg - * @this_arg: pointer to current radiotap arg - * @arg_index: internal next argument index - * @arg: internal next argument pointer - * @next_bitmap: internal pointer to next present u32 - * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + * enum ieee80211_rate_flags - rate flags + * + * Hardware/specification flags for rates. These are structured + * in a way that allows using the same bitrate structure for + * different bands/PHY modes. + * + * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short + * preamble on this bitrate; only relevant in 2.4GHz band and + * with CCK rates. + * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate + * when used with 802.11a (on the 5 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate + * when used with 802.11b (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate + * when used with 802.11g (on the 2.4 GHz band); filled by the + * core code when registering the wiphy. + * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. */ +enum ieee80211_rate_flags { + IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, + IEEE80211_RATE_MANDATORY_A = 1<<1, + IEEE80211_RATE_MANDATORY_B = 1<<2, + IEEE80211_RATE_MANDATORY_G = 1<<3, + IEEE80211_RATE_ERP_G = 1<<4, +}; -struct ieee80211_radiotap_iterator { - struct ieee80211_radiotap_header *rtheader; - int max_length; - int this_arg_index; - u8 *this_arg; +/** + * struct ieee80211_rate - bitrate definition + * + * This structure describes a bitrate that an 802.11 PHY can + * operate with. The two values @hw_value and @hw_value_short + * are only for driver use when pointers to this structure are + * passed around. + * + * @flags: rate-specific flags + * @bitrate: bitrate in units of 100 Kbps + * @hw_value: driver/hardware value for this rate + * @hw_value_short: driver/hardware value for this rate when + * short preamble is used + */ +struct ieee80211_rate { + u32 flags; + u16 bitrate; + u16 hw_value, hw_value_short; +}; - int arg_index; - u8 *arg; - __le32 *next_bitmap; - u32 bitmap_shifter; +/** + * struct ieee80211_sta_ht_cap - STA's HT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11n HT capabilities for an STA. + * + * @ht_supported: is HT supported by the STA + * @cap: HT capabilities map as described in 802.11n spec + * @ampdu_factor: Maximum A-MPDU length factor + * @ampdu_density: Minimum A-MPDU spacing + * @mcs: Supported MCS rates + */ +struct ieee80211_sta_ht_cap { + u16 cap; /* use IEEE80211_HT_CAP_ */ + bool ht_supported; + u8 ampdu_factor; + u8 ampdu_density; + struct ieee80211_mcs_info mcs; }; -extern int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length); +/** + * struct ieee80211_supported_band - frequency band definition + * + * This structure describes a frequency band a wiphy + * is able to operate in. + * + * @channels: Array of channels the hardware can operate in + * in this band. + * @band: the band this structure represents + * @n_channels: Number of channels in @channels + * @bitrates: Array of bitrates the hardware can operate with + * in this band. Must be sorted to give a valid "supported + * rates" IE, i.e. CCK rates first, then OFDM. + * @n_bitrates: Number of bitrates in @bitrates + */ +struct ieee80211_supported_band { + struct ieee80211_channel *channels; + struct ieee80211_rate *bitrates; + enum ieee80211_band band; + int n_channels; + int n_bitrates; + struct ieee80211_sta_ht_cap ht_cap; +}; -extern int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator); +/* + * Wireless hardware/device configuration structures and methods + */ +/** + * struct vif_params - describes virtual interface parameters + * @mesh_id: mesh ID to use + * @mesh_id_len: length of the mesh ID + */ +struct vif_params { + u8 *mesh_id; + int mesh_id_len; +}; - /** +/** * struct key_params - key information * * Information about a key @@ -347,92 +494,6 @@ struct bss_parameters { u8 basic_rates_len; }; -/** - * enum environment_cap - Environment parsed from country IE - * @ENVIRON_ANY: indicates country IE applies to both indoor and - * outdoor operation. - * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation - * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation - */ -enum environment_cap { - ENVIRON_ANY, - ENVIRON_INDOOR, - ENVIRON_OUTDOOR, -}; - -/** - * struct regulatory_request - used to keep track of regulatory requests - * - * @wiphy_idx: this is set if this request's initiator is - * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This - * can be used by the wireless core to deal with conflicts - * and potentially inform users of which devices specifically - * cased the conflicts. - * @initiator: indicates who sent this request, could be any of - * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) - * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested - * regulatory domain. We have a few special codes: - * 00 - World regulatory domain - * 99 - built by driver but a specific alpha2 cannot be determined - * 98 - result of an intersection between two regulatory domains - * @intersect: indicates whether the wireless core should intersect - * the requested regulatory domain with the presently set regulatory - * domain. - * @country_ie_checksum: checksum of the last processed and accepted - * country IE - * @country_ie_env: lets us know if the AP is telling us we are outdoor, - * indoor, or if it doesn't matter - * @list: used to insert into the reg_requests_list linked list - */ -struct regulatory_request { - int wiphy_idx; - enum nl80211_reg_initiator initiator; - char alpha2[2]; - bool intersect; - u32 country_ie_checksum; - enum environment_cap country_ie_env; - struct list_head list; -}; - -struct ieee80211_freq_range { - u32 start_freq_khz; - u32 end_freq_khz; - u32 max_bandwidth_khz; -}; - -struct ieee80211_power_rule { - u32 max_antenna_gain; - u32 max_eirp; -}; - -struct ieee80211_reg_rule { - struct ieee80211_freq_range freq_range; - struct ieee80211_power_rule power_rule; - u32 flags; -}; - -struct ieee80211_regdomain { - u32 n_reg_rules; - char alpha2[2]; - struct ieee80211_reg_rule reg_rules[]; -}; - -#define MHZ_TO_KHZ(freq) ((freq) * 1000) -#define KHZ_TO_MHZ(freq) ((freq) / 1000) -#define DBI_TO_MBI(gain) ((gain) * 100) -#define MBI_TO_DBI(gain) ((gain) / 100) -#define DBM_TO_MBM(gain) ((gain) * 100) -#define MBM_TO_DBM(gain) ((gain) / 100) - -#define REG_RULE(start, end, bw, gain, eirp, reg_flags) { \ - .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ - .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ - .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ - .power_rule.max_antenna_gain = DBI_TO_MBI(gain), \ - .power_rule.max_eirp = DBM_TO_MBM(eirp), \ - .flags = reg_flags, \ - } - struct mesh_config { /* Timeouts in ms */ /* Mesh plink management parameters */ @@ -853,7 +914,396 @@ struct cfg80211_ops { int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); }; -/* temporary wext handlers */ +/* + * wireless hardware and networking interfaces structures + * and registration/helper functions + */ + +/** + * struct wiphy - wireless hardware description + * @idx: the wiphy index assigned to this item + * @class_dev: the class device representing /sys/class/ieee80211/ + * @custom_regulatory: tells us the driver for this device + * has its own custom regulatory domain and cannot identify the + * ISO / IEC 3166 alpha2 it belongs to. When this is enabled + * we will disregard the first regulatory hint (when the + * initiator is %REGDOM_SET_BY_CORE). + * @strict_regulatory: tells us the driver for this device will ignore + * regulatory domain settings until it gets its own regulatory domain + * via its regulatory_hint(). After its gets its own regulatory domain + * it will only allow further regulatory domain settings to further + * enhance compliance. For example if channel 13 and 14 are disabled + * by this regulatory domain no user regulatory domain can enable these + * channels at a later time. This can be used for devices which do not + * have calibration information gauranteed for frequencies or settings + * outside of its regulatory domain. + * @reg_notifier: the driver's regulatory notification callback + * @regd: the driver's regulatory domain, if one was requested via + * the regulatory_hint() API. This can be used by the driver + * on the reg_notifier() if it chooses to ignore future + * regulatory domain changes caused by other drivers. + * @signal_type: signal type reported in &struct cfg80211_bss. + * @cipher_suites: supported cipher suites + * @n_cipher_suites: number of supported cipher suites + */ +struct wiphy { + /* assign these fields before you register the wiphy */ + + /* permanent MAC address */ + u8 perm_addr[ETH_ALEN]; + + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ + u16 interface_modes; + + bool custom_regulatory; + bool strict_regulatory; + + enum cfg80211_signal_type signal_type; + + int bss_priv_size; + u8 max_scan_ssids; + u16 max_scan_ie_len; + + int n_cipher_suites; + const u32 *cipher_suites; + + /* If multiple wiphys are registered and you're handed e.g. + * a regular netdev with assigned ieee80211_ptr, you won't + * know whether it points to a wiphy your driver has registered + * or not. Assign this to something global to your driver to + * help determine whether you own this wiphy or not. */ + void *privid; + + struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; + + /* Lets us get back the wiphy on the callback */ + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request); + + /* fields below are read-only, assigned by cfg80211 */ + + const struct ieee80211_regdomain *regd; + + /* the item in /sys/class/ieee80211/ points to this, + * you need use set_wiphy_dev() (see below) */ + struct device dev; + + /* dir in debugfs: ieee80211/ */ + struct dentry *debugfsdir; + + char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); +}; + +/** + * wiphy_priv - return priv from wiphy + * + * @wiphy: the wiphy whose priv pointer to return + */ +static inline void *wiphy_priv(struct wiphy *wiphy) +{ + BUG_ON(!wiphy); + return &wiphy->priv; +} + +/** + * set_wiphy_dev - set device pointer for wiphy + * + * @wiphy: The wiphy whose device to bind + * @dev: The device to parent it to + */ +static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev) +{ + wiphy->dev.parent = dev; +} + +/** + * wiphy_dev - get wiphy dev pointer + * + * @wiphy: The wiphy whose device struct to look up + */ +static inline struct device *wiphy_dev(struct wiphy *wiphy) +{ + return wiphy->dev.parent; +} + +/** + * wiphy_name - get wiphy name + * + * @wiphy: The wiphy whose name to return + */ +static inline const char *wiphy_name(struct wiphy *wiphy) +{ + return dev_name(&wiphy->dev); +} + +/** + * wiphy_new - create a new wiphy for use with cfg80211 + * + * @ops: The configuration operations for this device + * @sizeof_priv: The size of the private area to allocate + * + * Create a new wiphy and associate the given operations with it. + * @sizeof_priv bytes are allocated for private use. + * + * The returned pointer must be assigned to each netdev's + * ieee80211_ptr for proper operation. + */ +struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv); + +/** + * wiphy_register - register a wiphy with cfg80211 + * + * @wiphy: The wiphy to register. + * + * Returns a non-negative wiphy index or a negative error code. + */ +extern int wiphy_register(struct wiphy *wiphy); + +/** + * wiphy_unregister - deregister a wiphy from cfg80211 + * + * @wiphy: The wiphy to unregister. + * + * After this call, no more requests can be made with this priv + * pointer, but the call may sleep to wait for an outstanding + * request that is being handled. + */ +extern void wiphy_unregister(struct wiphy *wiphy); + +/** + * wiphy_free - free wiphy + * + * @wiphy: The wiphy to free + */ +extern void wiphy_free(struct wiphy *wiphy); + +/** + * struct wireless_dev - wireless per-netdev state + * + * This structure must be allocated by the driver/stack + * that uses the ieee80211_ptr field in struct net_device + * (this is intentional so it can be allocated along with + * the netdev.) + * + * @wiphy: pointer to hardware description + * @iftype: interface type + * @list: (private) Used to collect the interfaces + * @netdev: (private) Used to reference back to the netdev + * @current_bss: (private) Used by the internal configuration code + * @bssid: (private) Used by the internal configuration code + * @ssid: (private) Used by the internal configuration code + * @ssid_len: (private) Used by the internal configuration code + * @wext: (private) Used by the internal wireless extensions compat code + * @wext_bssid: (private) Used by the internal wireless extensions compat code + */ +struct wireless_dev { + struct wiphy *wiphy; + enum nl80211_iftype iftype; + + /* private to the generic wireless code */ + struct list_head list; + struct net_device *netdev; + + /* currently used for IBSS - might be rearranged in the future */ + struct cfg80211_bss *current_bss; + u8 bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + +#ifdef CONFIG_WIRELESS_EXT + /* wext data */ + struct cfg80211_ibss_params wext; + u8 wext_bssid[ETH_ALEN]; +#endif +}; + +/** + * wdev_priv - return wiphy priv from wireless_dev + * + * @wdev: The wireless device whose wiphy's priv pointer to return + */ +static inline void *wdev_priv(struct wireless_dev *wdev) +{ + BUG_ON(!wdev); + return wiphy_priv(wdev->wiphy); +} + +/* + * Utility functions + */ + +/** + * ieee80211_channel_to_frequency - convert channel number to frequency + */ +extern int ieee80211_channel_to_frequency(int chan); + +/** + * ieee80211_frequency_to_channel - convert frequency to channel number + */ +extern int ieee80211_frequency_to_channel(int freq); + +/* + * Name indirection necessary because the ieee80211 code also has + * a function named "ieee80211_get_channel", so if you include + * cfg80211's header file you get cfg80211's version, if you try + * to include both header files you'll (rightfully!) get a symbol + * clash. + */ +extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, + int freq); +/** + * ieee80211_get_channel - get channel struct from wiphy for specified frequency + */ +static inline struct ieee80211_channel * +ieee80211_get_channel(struct wiphy *wiphy, int freq) +{ + return __ieee80211_get_channel(wiphy, freq); +} + +/** + * ieee80211_get_response_rate - get basic rate for a given rate + * + * @sband: the band to look for rates in + * @basic_rates: bitmap of basic rates + * @bitrate: the bitrate for which to find the basic rate + * + * This function returns the basic rate corresponding to a given + * bitrate, that is the next lower bitrate contained in the basic + * rate map, which is, for this function, given as a bitmap of + * indices of rates in the band's bitrate table. + */ +struct ieee80211_rate * +ieee80211_get_response_rate(struct ieee80211_supported_band *sband, + u32 basic_rates, int bitrate); + +/* + * Radiotap parsing functions -- for controlled injection support + * + * Implemented in net/wireless/radiotap.c + * Documentation in Documentation/networking/radiotap-headers.txt + */ + +/** + * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args + * @rtheader: pointer to the radiotap header we are walking through + * @max_length: length of radiotap header in cpu byte ordering + * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg + * @this_arg: pointer to current radiotap arg + * @arg_index: internal next argument index + * @arg: internal next argument pointer + * @next_bitmap: internal pointer to next present u32 + * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + */ + +struct ieee80211_radiotap_iterator { + struct ieee80211_radiotap_header *rtheader; + int max_length; + int this_arg_index; + u8 *this_arg; + + int arg_index; + u8 *arg; + __le32 *next_bitmap; + u32 bitmap_shifter; +}; + +extern int ieee80211_radiotap_iterator_init( + struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, + int max_length); + +extern int ieee80211_radiotap_iterator_next( + struct ieee80211_radiotap_iterator *iterator); + +/* + * Regulatory helper functions for wiphys + */ + +/** + * regulatory_hint - driver hint to the wireless core a regulatory domain + * @wiphy: the wireless device giving the hint (used only for reporting + * conflicts) + * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain + * should be in. If @rd is set this should be NULL. Note that if you + * set this to NULL you should still set rd->alpha2 to some accepted + * alpha2. + * + * Wireless drivers can use this function to hint to the wireless core + * what it believes should be the current regulatory domain by + * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory + * domain should be in or by providing a completely build regulatory domain. + * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried + * for a regulatory domain structure for the respective country. + * + * The wiphy must have been registered to cfg80211 prior to this call. + * For cfg80211 drivers this means you must first use wiphy_register(), + * for mac80211 drivers you must first use ieee80211_register_hw(). + * + * Drivers should check the return value, its possible you can get + * an -ENOMEM. + */ +extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2); + +/** + * regulatory_hint_11d - hints a country IE as a regulatory domain + * @wiphy: the wireless device giving the hint (used only for reporting + * conflicts) + * @country_ie: pointer to the country IE + * @country_ie_len: length of the country IE + * + * We will intersect the rd with the what CRDA tells us should apply + * for the alpha2 this country IE belongs to, this prevents APs from + * sending us incorrect or outdated information against a country. + */ +extern void regulatory_hint_11d(struct wiphy *wiphy, + u8 *country_ie, + u8 country_ie_len); +/** + * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain + * @wiphy: the wireless device we want to process the regulatory domain on + * @regd: the custom regulatory domain to use for this wiphy + * + * Drivers can sometimes have custom regulatory domains which do not apply + * to a specific country. Drivers can use this to apply such custom regulatory + * domains. This routine must be called prior to wiphy registration. The + * custom regulatory domain will be trusted completely and as such previous + * default channel settings will be disregarded. If no rule is found for a + * channel on the regulatory domain the channel will be disabled. + */ +extern void wiphy_apply_custom_regulatory( + struct wiphy *wiphy, + const struct ieee80211_regdomain *regd); + +/** + * freq_reg_info - get regulatory information for the given frequency + * @wiphy: the wiphy for which we want to process this rule for + * @center_freq: Frequency in KHz for which we want regulatory information for + * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one + * you can set this to 0. If this frequency is allowed we then set + * this value to the maximum allowed bandwidth. + * @reg_rule: the regulatory rule which we have for this frequency + * + * Use this function to get the regulatory rule for a specific frequency on + * a given wireless device. If the device has a specific regulatory domain + * it wants to follow we respect that unless a country IE has been received + * and processed already. + * + * Returns 0 if it was able to find a valid regulatory rule which does + * apply to the given center_freq otherwise it returns non-zero. It will + * also return -ERANGE if we determine the given center_freq does not even have + * a regulatory rule for a frequency range in the center_freq's band. See + * freq_in_rule_band() for our current definition of a band -- this is purely + * subjective and right now its 802.11 specific. + */ +extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, + const struct ieee80211_reg_rule **reg_rule); + +/* + * Temporary wext handlers & helper functions + * + * In the future cfg80211 will simply assign the entire wext handler + * structure to netdevs it manages, but we're not there yet. + */ int cfg80211_wext_giwname(struct net_device *dev, struct iw_request_info *info, char *name, char *extra); @@ -892,10 +1342,14 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra); -/* wext helper for now (to be removed) */ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq); +/* + * callbacks for asynchronous cfg80211 methods, notification + * functions and BSS handling helpers + */ + /** * cfg80211_scan_done - notify that scan finished * @@ -949,6 +1403,7 @@ struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, const u8 *meshid, size_t meshidlen, const u8 *meshcfg); void cfg80211_put_bss(struct cfg80211_bss *bss); + /** * cfg80211_unlink_bss - unlink BSS from internal data structures * @wiphy: the wiphy diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 52808bdcc6ca..d9686917252b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -19,7 +19,6 @@ #include #include #include -#include #include /** diff --git a/include/net/regulatory.h b/include/net/regulatory.h new file mode 100644 index 000000000000..47995b81c5d7 --- /dev/null +++ b/include/net/regulatory.h @@ -0,0 +1,101 @@ +#ifndef __NET_REGULATORY_H +#define __NET_REGULATORY_H +/* + * regulatory support structures + * + * Copyright 2008-2009 Luis R. Rodriguez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +/** + * enum environment_cap - Environment parsed from country IE + * @ENVIRON_ANY: indicates country IE applies to both indoor and + * outdoor operation. + * @ENVIRON_INDOOR: indicates country IE applies only to indoor operation + * @ENVIRON_OUTDOOR: indicates country IE applies only to outdoor operation + */ +enum environment_cap { + ENVIRON_ANY, + ENVIRON_INDOOR, + ENVIRON_OUTDOOR, +}; + +/** + * struct regulatory_request - used to keep track of regulatory requests + * + * @wiphy_idx: this is set if this request's initiator is + * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This + * can be used by the wireless core to deal with conflicts + * and potentially inform users of which devices specifically + * cased the conflicts. + * @initiator: indicates who sent this request, could be any of + * of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*) + * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested + * regulatory domain. We have a few special codes: + * 00 - World regulatory domain + * 99 - built by driver but a specific alpha2 cannot be determined + * 98 - result of an intersection between two regulatory domains + * @intersect: indicates whether the wireless core should intersect + * the requested regulatory domain with the presently set regulatory + * domain. + * @country_ie_checksum: checksum of the last processed and accepted + * country IE + * @country_ie_env: lets us know if the AP is telling us we are outdoor, + * indoor, or if it doesn't matter + * @list: used to insert into the reg_requests_list linked list + */ +struct regulatory_request { + int wiphy_idx; + enum nl80211_reg_initiator initiator; + char alpha2[2]; + bool intersect; + u32 country_ie_checksum; + enum environment_cap country_ie_env; + struct list_head list; +}; + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 flags; +}; + +struct ieee80211_regdomain { + u32 n_reg_rules; + char alpha2[2]; + struct ieee80211_reg_rule reg_rules[]; +}; + +#define MHZ_TO_KHZ(freq) ((freq) * 1000) +#define KHZ_TO_MHZ(freq) ((freq) / 1000) +#define DBI_TO_MBI(gain) ((gain) * 100) +#define MBI_TO_DBI(gain) ((gain) / 100) +#define DBM_TO_MBM(gain) ((gain) * 100) +#define MBM_TO_DBM(gain) ((gain) / 100) + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \ +{ \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(start), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(gain),\ + .power_rule.max_eirp = DBM_TO_MBM(eirp), \ + .flags = reg_flags, \ +} + +#endif diff --git a/include/net/wireless.h b/include/net/wireless.h deleted file mode 100644 index abd27b033331..000000000000 --- a/include/net/wireless.h +++ /dev/null @@ -1,492 +0,0 @@ -#ifndef __NET_WIRELESS_H -#define __NET_WIRELESS_H - -/* - * 802.11 device management - * - * Copyright 2007 Johannes Berg - */ - -#include -#include -#include -#include -#include - -/** - * enum ieee80211_band - supported frequency bands - * - * The bands are assigned this way because the supported - * bitrates differ in these bands. - * - * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band - * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) - */ -enum ieee80211_band { - IEEE80211_BAND_2GHZ, - IEEE80211_BAND_5GHZ, - - /* keep last */ - IEEE80211_NUM_BANDS -}; - -/** - * enum ieee80211_channel_flags - channel flags - * - * Channel flags set by the regulatory control code. - * - * @IEEE80211_CHAN_DISABLED: This channel is disabled. - * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted - * on this channel. - * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. - * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. - * @IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel - * is not permitted. - * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel - * is not permitted. - */ -enum ieee80211_channel_flags { - IEEE80211_CHAN_DISABLED = 1<<0, - IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, - IEEE80211_CHAN_NO_IBSS = 1<<2, - IEEE80211_CHAN_RADAR = 1<<3, - IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, - IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, -}; - -/** - * struct ieee80211_channel - channel definition - * - * This structure describes a single channel for use - * with cfg80211. - * - * @center_freq: center frequency in MHz - * @max_bandwidth: maximum allowed bandwidth for this channel, in MHz - * @hw_value: hardware-specific value for the channel - * @flags: channel flags from &enum ieee80211_channel_flags. - * @orig_flags: channel flags at registration time, used by regulatory - * code to support devices with additional restrictions - * @band: band this channel belongs to. - * @max_antenna_gain: maximum antenna gain in dBi - * @max_power: maximum transmission power (in dBm) - * @beacon_found: helper to regulatory code to indicate when a beacon - * has been found on this channel. Use regulatory_hint_found_beacon() - * to enable this, this is is useful only on 5 GHz band. - * @orig_mag: internal use - * @orig_mpwr: internal use - */ -struct ieee80211_channel { - enum ieee80211_band band; - u16 center_freq; - u8 max_bandwidth; - u16 hw_value; - u32 flags; - int max_antenna_gain; - int max_power; - bool beacon_found; - u32 orig_flags; - int orig_mag, orig_mpwr; -}; - -/** - * enum ieee80211_rate_flags - rate flags - * - * Hardware/specification flags for rates. These are structured - * in a way that allows using the same bitrate structure for - * different bands/PHY modes. - * - * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short - * preamble on this bitrate; only relevant in 2.4GHz band and - * with CCK rates. - * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate - * when used with 802.11a (on the 5 GHz band); filled by the - * core code when registering the wiphy. - * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate - * when used with 802.11b (on the 2.4 GHz band); filled by the - * core code when registering the wiphy. - * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate - * when used with 802.11g (on the 2.4 GHz band); filled by the - * core code when registering the wiphy. - * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. - */ -enum ieee80211_rate_flags { - IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, - IEEE80211_RATE_MANDATORY_A = 1<<1, - IEEE80211_RATE_MANDATORY_B = 1<<2, - IEEE80211_RATE_MANDATORY_G = 1<<3, - IEEE80211_RATE_ERP_G = 1<<4, -}; - -/** - * struct ieee80211_rate - bitrate definition - * - * This structure describes a bitrate that an 802.11 PHY can - * operate with. The two values @hw_value and @hw_value_short - * are only for driver use when pointers to this structure are - * passed around. - * - * @flags: rate-specific flags - * @bitrate: bitrate in units of 100 Kbps - * @hw_value: driver/hardware value for this rate - * @hw_value_short: driver/hardware value for this rate when - * short preamble is used - */ -struct ieee80211_rate { - u32 flags; - u16 bitrate; - u16 hw_value, hw_value_short; -}; - -/** - * struct ieee80211_sta_ht_cap - STA's HT capabilities - * - * This structure describes most essential parameters needed - * to describe 802.11n HT capabilities for an STA. - * - * @ht_supported: is HT supported by the STA - * @cap: HT capabilities map as described in 802.11n spec - * @ampdu_factor: Maximum A-MPDU length factor - * @ampdu_density: Minimum A-MPDU spacing - * @mcs: Supported MCS rates - */ -struct ieee80211_sta_ht_cap { - u16 cap; /* use IEEE80211_HT_CAP_ */ - bool ht_supported; - u8 ampdu_factor; - u8 ampdu_density; - struct ieee80211_mcs_info mcs; -}; - -/** - * struct ieee80211_supported_band - frequency band definition - * - * This structure describes a frequency band a wiphy - * is able to operate in. - * - * @channels: Array of channels the hardware can operate in - * in this band. - * @band: the band this structure represents - * @n_channels: Number of channels in @channels - * @bitrates: Array of bitrates the hardware can operate with - * in this band. Must be sorted to give a valid "supported - * rates" IE, i.e. CCK rates first, then OFDM. - * @n_bitrates: Number of bitrates in @bitrates - */ -struct ieee80211_supported_band { - struct ieee80211_channel *channels; - struct ieee80211_rate *bitrates; - enum ieee80211_band band; - int n_channels; - int n_bitrates; - struct ieee80211_sta_ht_cap ht_cap; -}; - -/** - * struct wiphy - wireless hardware description - * @idx: the wiphy index assigned to this item - * @class_dev: the class device representing /sys/class/ieee80211/ - * @custom_regulatory: tells us the driver for this device - * has its own custom regulatory domain and cannot identify the - * ISO / IEC 3166 alpha2 it belongs to. When this is enabled - * we will disregard the first regulatory hint (when the - * initiator is %REGDOM_SET_BY_CORE). - * @strict_regulatory: tells us the driver for this device will ignore - * regulatory domain settings until it gets its own regulatory domain - * via its regulatory_hint(). After its gets its own regulatory domain - * it will only allow further regulatory domain settings to further - * enhance compliance. For example if channel 13 and 14 are disabled - * by this regulatory domain no user regulatory domain can enable these - * channels at a later time. This can be used for devices which do not - * have calibration information gauranteed for frequencies or settings - * outside of its regulatory domain. - * @reg_notifier: the driver's regulatory notification callback - * @regd: the driver's regulatory domain, if one was requested via - * the regulatory_hint() API. This can be used by the driver - * on the reg_notifier() if it chooses to ignore future - * regulatory domain changes caused by other drivers. - * @signal_type: signal type reported in &struct cfg80211_bss. - * @cipher_suites: supported cipher suites - * @n_cipher_suites: number of supported cipher suites - */ -struct wiphy { - /* assign these fields before you register the wiphy */ - - /* permanent MAC address */ - u8 perm_addr[ETH_ALEN]; - - /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ - u16 interface_modes; - - bool custom_regulatory; - bool strict_regulatory; - - enum cfg80211_signal_type signal_type; - - int bss_priv_size; - u8 max_scan_ssids; - u16 max_scan_ie_len; - - int n_cipher_suites; - const u32 *cipher_suites; - - /* If multiple wiphys are registered and you're handed e.g. - * a regular netdev with assigned ieee80211_ptr, you won't - * know whether it points to a wiphy your driver has registered - * or not. Assign this to something global to your driver to - * help determine whether you own this wiphy or not. */ - void *privid; - - struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; - - /* Lets us get back the wiphy on the callback */ - int (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request); - - /* fields below are read-only, assigned by cfg80211 */ - - const struct ieee80211_regdomain *regd; - - /* the item in /sys/class/ieee80211/ points to this, - * you need use set_wiphy_dev() (see below) */ - struct device dev; - - /* dir in debugfs: ieee80211/ */ - struct dentry *debugfsdir; - - char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); -}; - -/** struct wireless_dev - wireless per-netdev state - * - * This structure must be allocated by the driver/stack - * that uses the ieee80211_ptr field in struct net_device - * (this is intentional so it can be allocated along with - * the netdev.) - * - * @wiphy: pointer to hardware description - * @iftype: interface type - * @list: (private) - * @netdev (private) - */ -struct wireless_dev { - struct wiphy *wiphy; - enum nl80211_iftype iftype; - - /* private to the generic wireless code */ - struct list_head list; - struct net_device *netdev; - - /* currently used for IBSS - might be rearranged in the future */ - struct cfg80211_bss *current_bss; - u8 bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - -#ifdef CONFIG_WIRELESS_EXT - /* wext data */ - struct cfg80211_ibss_params wext; - u8 wext_bssid[ETH_ALEN]; -#endif -}; - -/** - * wiphy_priv - return priv from wiphy - */ -static inline void *wiphy_priv(struct wiphy *wiphy) -{ - BUG_ON(!wiphy); - return &wiphy->priv; -} - -/** - * set_wiphy_dev - set device pointer for wiphy - */ -static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev) -{ - wiphy->dev.parent = dev; -} - -/** - * wiphy_dev - get wiphy dev pointer - */ -static inline struct device *wiphy_dev(struct wiphy *wiphy) -{ - return wiphy->dev.parent; -} - -/** - * wiphy_name - get wiphy name - */ -static inline const char *wiphy_name(struct wiphy *wiphy) -{ - return dev_name(&wiphy->dev); -} - -/** - * wdev_priv - return wiphy priv from wireless_dev - */ -static inline void *wdev_priv(struct wireless_dev *wdev) -{ - BUG_ON(!wdev); - return wiphy_priv(wdev->wiphy); -} - -/** - * wiphy_new - create a new wiphy for use with cfg80211 - * - * create a new wiphy and associate the given operations with it. - * @sizeof_priv bytes are allocated for private use. - * - * the returned pointer must be assigned to each netdev's - * ieee80211_ptr for proper operation. - */ -struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv); - -/** - * wiphy_register - register a wiphy with cfg80211 - * - * register the given wiphy - * - * Returns a non-negative wiphy index or a negative error code. - */ -extern int wiphy_register(struct wiphy *wiphy); - -/** - * wiphy_unregister - deregister a wiphy from cfg80211 - * - * unregister a device with the given priv pointer. - * After this call, no more requests can be made with this priv - * pointer, but the call may sleep to wait for an outstanding - * request that is being handled. - */ -extern void wiphy_unregister(struct wiphy *wiphy); - -/** - * wiphy_free - free wiphy - */ -extern void wiphy_free(struct wiphy *wiphy); - -/** - * ieee80211_channel_to_frequency - convert channel number to frequency - */ -extern int ieee80211_channel_to_frequency(int chan); - -/** - * ieee80211_frequency_to_channel - convert frequency to channel number - */ -extern int ieee80211_frequency_to_channel(int freq); - -/* - * Name indirection necessary because the ieee80211 code also has - * a function named "ieee80211_get_channel", so if you include - * cfg80211's header file you get cfg80211's version, if you try - * to include both header files you'll (rightfully!) get a symbol - * clash. - */ -extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, - int freq); -/** - * ieee80211_get_channel - get channel struct from wiphy for specified frequency - */ -static inline struct ieee80211_channel * -ieee80211_get_channel(struct wiphy *wiphy, int freq) -{ - return __ieee80211_get_channel(wiphy, freq); -} - -/** - * ieee80211_get_response_rate - get basic rate for a given rate - * - * @sband: the band to look for rates in - * @basic_rates: bitmap of basic rates - * @bitrate: the bitrate for which to find the basic rate - * - * This function returns the basic rate corresponding to a given - * bitrate, that is the next lower bitrate contained in the basic - * rate map, which is, for this function, given as a bitmap of - * indices of rates in the band's bitrate table. - */ -struct ieee80211_rate * -ieee80211_get_response_rate(struct ieee80211_supported_band *sband, - u32 basic_rates, int bitrate); - -/** - * regulatory_hint - driver hint to the wireless core a regulatory domain - * @wiphy: the wireless device giving the hint (used only for reporting - * conflicts) - * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain - * should be in. If @rd is set this should be NULL. Note that if you - * set this to NULL you should still set rd->alpha2 to some accepted - * alpha2. - * - * Wireless drivers can use this function to hint to the wireless core - * what it believes should be the current regulatory domain by - * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory - * domain should be in or by providing a completely build regulatory domain. - * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried - * for a regulatory domain structure for the respective country. - * - * The wiphy must have been registered to cfg80211 prior to this call. - * For cfg80211 drivers this means you must first use wiphy_register(), - * for mac80211 drivers you must first use ieee80211_register_hw(). - * - * Drivers should check the return value, its possible you can get - * an -ENOMEM. - */ -extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2); - -/** - * regulatory_hint_11d - hints a country IE as a regulatory domain - * @wiphy: the wireless device giving the hint (used only for reporting - * conflicts) - * @country_ie: pointer to the country IE - * @country_ie_len: length of the country IE - * - * We will intersect the rd with the what CRDA tells us should apply - * for the alpha2 this country IE belongs to, this prevents APs from - * sending us incorrect or outdated information against a country. - */ -extern void regulatory_hint_11d(struct wiphy *wiphy, - u8 *country_ie, - u8 country_ie_len); -/** - * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain - * @wiphy: the wireless device we want to process the regulatory domain on - * @regd: the custom regulatory domain to use for this wiphy - * - * Drivers can sometimes have custom regulatory domains which do not apply - * to a specific country. Drivers can use this to apply such custom regulatory - * domains. This routine must be called prior to wiphy registration. The - * custom regulatory domain will be trusted completely and as such previous - * default channel settings will be disregarded. If no rule is found for a - * channel on the regulatory domain the channel will be disabled. - */ -extern void wiphy_apply_custom_regulatory( - struct wiphy *wiphy, - const struct ieee80211_regdomain *regd); - -/** - * freq_reg_info - get regulatory information for the given frequency - * @wiphy: the wiphy for which we want to process this rule for - * @center_freq: Frequency in KHz for which we want regulatory information for - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. - * @reg_rule: the regulatory rule which we have for this frequency - * - * Use this function to get the regulatory rule for a specific frequency on - * a given wireless device. If the device has a specific regulatory domain - * it wants to follow we respect that unless a country IE has been received - * and processed already. - * - * Returns 0 if it was able to find a valid regulatory rule which does - * apply to the given center_freq otherwise it returns non-zero. It will - * also return -ERANGE if we determine the given center_freq does not even have - * a regulatory rule for a frequency range in the center_freq's band. See - * freq_in_rule_band() for our current definition of a band -- this is purely - * subjective and right now its 802.11 specific. - */ -extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule); - -#endif /* __NET_WIRELESS_H */ diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 73bd427750ef..0891bfb06996 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -14,7 +14,6 @@ */ #include -#include #include #include "ieee80211_i.h" #include "rate.h" diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e770c1e8e08c..92a573bf1035 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include "key.h" diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 5f7a2624ed74..48bf78e7fa7a 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include "ieee80211_i.h" #include "sta_info.h" diff --git a/net/wireless/core.c b/net/wireless/core.c index de1ac51ae4e5..827a56263551 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "nl80211.h" #include "core.h" #include "sysfs.h" diff --git a/net/wireless/core.h b/net/wireless/core.h index 2ef3595fd6e0..89a8159ef0b1 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "reg.h" diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 2bf42fdef3a1..4e1fcb0c9e4c 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -7,7 +7,6 @@ #include #include #include -#include #include "nl80211.h" diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 574e217bcc86..f38cc39fa79e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include "core.h" #include "reg.h" diff --git a/net/wireless/util.c b/net/wireless/util.c index 487cdd9bcffc..5f7e997195c7 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1,10 +1,10 @@ /* * Wireless utility functions * - * Copyright 2007 Johannes Berg + * Copyright 2007-2009 Johannes Berg */ -#include -#include +#include +#include #include "core.h" struct ieee80211_rate * diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 57eaea26b67a..4e054ea9c0a0 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "core.h" -- cgit v1.2.3 From 314bd7503b1e96841931311f28a8925dab66ed83 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 15:17:01 +0200 Subject: rndis_wlan: remove nickname support Supporting wireless extension nickname is pointless and no other modern driver supports this, so remove it. Signed-off-by: Johannes Berg Acked-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 43e0ba61df24..109e60343363 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -372,9 +372,6 @@ struct rndis_wext_private { struct iw_statistics iwstats; struct iw_statistics privstats; - int nick_len; - char nick[32]; - int caps; int multicast_size; @@ -1798,39 +1795,6 @@ static int rndis_iw_get_frag(struct net_device *dev, } -static int rndis_iw_set_nick(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - devdbg(usbdev, "SIOCSIWNICK"); - - priv->nick_len = wrqu->data.length; - if (priv->nick_len > 32) - priv->nick_len = 32; - - memcpy(priv->nick, extra, priv->nick_len); - return 0; -} - - -static int rndis_iw_get_nick(struct net_device *dev, - struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - - wrqu->data.flags = 1; - wrqu->data.length = priv->nick_len; - memcpy(extra, priv->nick, priv->nick_len); - - devdbg(usbdev, "SIOCGIWNICK: '%s'", priv->nick); - - return 0; -} - - static int rndis_iw_set_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -2039,8 +2003,6 @@ static const iw_handler rndis_iw_handler[] = IW_IOCTL(SIOCGIWSCAN) = (iw_handler) cfg80211_wext_giwscan, IW_IOCTL(SIOCSIWESSID) = rndis_iw_set_essid, IW_IOCTL(SIOCGIWESSID) = rndis_iw_get_essid, - IW_IOCTL(SIOCSIWNICKN) = rndis_iw_set_nick, - IW_IOCTL(SIOCGIWNICKN) = rndis_iw_get_nick, IW_IOCTL(SIOCGIWRATE) = rndis_iw_get_rate, IW_IOCTL(SIOCSIWRTS) = rndis_iw_set_rts, IW_IOCTL(SIOCGIWRTS) = rndis_iw_get_rts, -- cgit v1.2.3 From 9e52b0623c6eb49c3f23a326c1fb97bdecc49ba1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 18:27:04 +0200 Subject: ar9170: support HT receive and channel config This patch adds support for configuring HT40 channels and receiving HT40 to ar9170. Receiving aggregation doesn't seem to work right now, so it's not enabled. Same goes for TX aggregation, but that probably needs even more work. With this, I can receive roughly 33 Mbits/sec. The HT capabilities are a little odd, I tried following otus here -- in particular having SGI_40 but not SGI_20 is a little weird but afaict that's what otus does. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 15 +++++++++ drivers/net/wireless/ath/ar9170/main.c | 54 +++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 2522a190fdfb..b6a1bff67cab 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -60,6 +60,21 @@ enum ar9170_bw { __AR9170_NUM_BW, }; +static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) +{ + switch (type) { + case NL80211_CHAN_NO_HT: + case NL80211_CHAN_HT20: + return AR9170_BW_20; + case NL80211_CHAN_HT40MINUS: + return AR9170_BW_40_BELOW; + case NL80211_CHAN_HT40PLUS: + return AR9170_BW_40_ABOVE; + default: + BUG(); + } +} + enum ar9170_rf_init_mode { AR9170_RFI_NONE, AR9170_RFI_WARM, diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 857416c80199..4682fe2f3f3c 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -142,11 +142,36 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { }; #undef CHAN +#define AR9170_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ + IEEE80211_HT_CAP_SM_PS | \ + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ + IEEE80211_HT_CAP_SGI_40 | \ + IEEE80211_HT_CAP_DSSSCCK40 | \ + IEEE80211_HT_CAP_SM_PS, \ + .ampdu_factor = 3, /* ?? */ \ + .ampdu_density = 7, /* ?? */ \ + .mcs = { \ + .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \ + }, \ +} + static struct ieee80211_supported_band ar9170_band_2GHz = { .channels = ar9170_2ghz_chantable, .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), .bitrates = ar9170_g_ratetable, .n_bitrates = ar9170_g_ratetable_size, + .ht_cap = AR9170_HT_CAP, +}; + +static struct ieee80211_supported_band ar9170_band_5GHz = { + .channels = ar9170_5ghz_chantable, + .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), + .bitrates = ar9170_a_ratetable, + .n_bitrates = ar9170_a_ratetable_size, + .ht_cap = AR9170_HT_CAP, }; #ifdef AR9170_QUEUE_DEBUG @@ -190,13 +215,6 @@ static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar, } #endif /* AR9170_QUEUE_DEBUG */ -static struct ieee80211_supported_band ar9170_band_5GHz = { - .channels = ar9170_5ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), - .bitrates = ar9170_a_ratetable, - .n_bitrates = ar9170_a_ratetable_size, -}; - void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb, bool valid_status, u16 tx_status) { @@ -1077,7 +1095,8 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { err = ar9170_set_channel(ar, hw->conf.channel, - AR9170_RFI_NONE, AR9170_BW_20); + AR9170_RFI_NONE, + nl80211_to_ar9170(hw->conf.channel_type)); if (err) goto out; /* adjust slot time for 5 GHz */ @@ -1499,6 +1518,24 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, return ret; } +static int ar9170_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) +{ + switch (action) { + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + /* + * Something goes wrong -- RX locks up + * after a while of receiving aggregated + * frames -- not enabling for now. + */ + return -EOPNOTSUPP; + default: + return -EOPNOTSUPP; + } +} + static const struct ieee80211_ops ar9170_ops = { .start = ar9170_op_start, .stop = ar9170_op_stop, @@ -1515,6 +1552,7 @@ static const struct ieee80211_ops ar9170_ops = { .sta_notify = ar9170_sta_notify, .get_stats = ar9170_get_stats, .get_tx_stats = ar9170_get_tx_stats, + .ampdu_action = ar9170_ampdu_action, }; void *ar9170_alloc(size_t priv_size) -- cgit v1.2.3 From b9a5f8cab751d362f7c2d94899ca788c22fcd1ef Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 20 Apr 2009 18:39:05 +0200 Subject: nl80211: Add set/get for frag/rts threshold and retry limits Add new nl80211 attributes that can be used with NL80211_CMD_SET_WIPHY and NL80211_CMD_GET_WIPHY to manage fragmentation/RTS threshold and retry limits. Since these values are stored in struct wiphy, remove the local copy from mac80211 where feasible (frag & rts threshold). The retry limits are currently needed in struct ieee80211_conf, but these could be eventually removed since the driver should have access to the values in struct wiphy. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 24 ++++++- include/net/cfg80211.h | 50 +++++++++++++++ net/mac80211/cfg.c | 27 ++++++++ net/mac80211/debugfs.c | 8 +-- net/mac80211/ieee80211_i.h | 3 - net/mac80211/main.c | 6 +- net/mac80211/tx.c | 9 ++- net/mac80211/util.c | 2 +- net/mac80211/wext.c | 138 ++--------------------------------------- net/wireless/core.c | 10 +++ net/wireless/nl80211.c | 95 ++++++++++++++++++++++++++++ net/wireless/wext-compat.c | 151 +++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 372 insertions(+), 151 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 25ce3e42bd10..dc9d9ec5d1ae 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -46,8 +46,10 @@ * to get a list of all present wiphys. * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or - * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, + * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request * or rename notification. Has attributes %NL80211_ATTR_WIPHY and * %NL80211_ATTR_WIPHY_NAME. @@ -337,6 +339,18 @@ enum nl80211_commands { * NL80211_CHAN_HT20 = HT20 only * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel + * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is + * less than or equal to the RTS threshold; allowed range: 1..255; + * dot11ShortRetryLimit; u8 + * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is + * greater than the RTS threshold; allowed range: 1..255; + * dot11ShortLongLimit; u8 + * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum + * length in octets for frames; allowed range: 256..8000, disable + * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 + * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length + * larger than or equal to this use RTS/CTS handshake); allowed range: + * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 * * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on * @NL80211_ATTR_IFNAME: network interface name @@ -565,6 +579,12 @@ enum nl80211_attrs { NL80211_ATTR_FREQ_FIXED, + + NL80211_ATTR_WIPHY_RETRY_SHORT, + NL80211_ATTR_WIPHY_RETRY_LONG, + NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + NL80211_ATTR_WIPHY_RTS_THRESHOLD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 601eac64b02d..54bc69c83691 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -743,6 +743,20 @@ struct cfg80211_ibss_params { bool channel_fixed; }; +/** + * enum wiphy_params_flags - set_wiphy_params bitfield values + * WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed + * WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed + * WIPHY_PARAM_FRAG_THRESHOLD: wiphy->frag_threshold has changed + * WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed + */ +enum wiphy_params_flags { + WIPHY_PARAM_RETRY_SHORT = 1 << 0, + WIPHY_PARAM_RETRY_LONG = 1 << 1, + WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2, + WIPHY_PARAM_RTS_THRESHOLD = 1 << 3, +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -823,6 +837,11 @@ struct cfg80211_ibss_params { * cfg80211_ibss_joined(), also call that function when changing BSSID due * to a merge. * @leave_ibss: Leave the IBSS. + * + * @set_wiphy_params: Notify that wiphy parameters have changed; + * @changed bitfield (see &enum wiphy_params_flags) describes which values + * have changed. The actual parameter values are available in + * struct wiphy. If returning an error, no value should be changed. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy); @@ -912,6 +931,8 @@ struct cfg80211_ops { int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params); int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); + + int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed); }; /* @@ -945,6 +966,11 @@ struct cfg80211_ops { * @signal_type: signal type reported in &struct cfg80211_bss. * @cipher_suites: supported cipher suites * @n_cipher_suites: number of supported cipher suites + * @retry_short: Retry limit for short frames (dot11ShortRetryLimit) + * @retry_long: Retry limit for long frames (dot11LongRetryLimit) + * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold); + * -1 = fragmentation disabled, only odd values >= 256 used + * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -967,6 +993,11 @@ struct wiphy { int n_cipher_suites; const u32 *cipher_suites; + u8 retry_short; + u8 retry_long; + u32 frag_threshold; + u32 rts_threshold; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered @@ -1345,6 +1376,25 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq); +int cfg80211_wext_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra); +int cfg80211_wext_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra); +int cfg80211_wext_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra); +int cfg80211_wext_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra); +int cfg80211_wext_siwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra); +int cfg80211_wext_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra); + /* * callbacks for asynchronous cfg80211 methods, notification * functions and BSS handling helpers diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 14013dc64474..5e1c230744b5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1298,6 +1298,32 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return ieee80211_ibss_leave(sdata); } +static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + int err; + + if (local->ops->set_rts_threshold) { + err = local->ops->set_rts_threshold( + local_to_hw(local), wiphy->rts_threshold); + if (err) + return err; + } + } + + if (changed & WIPHY_PARAM_RETRY_SHORT) + local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; + if (changed & WIPHY_PARAM_RETRY_LONG) + local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; + if (changed & + (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); + + return 0; +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1336,4 +1362,5 @@ struct cfg80211_ops mac80211_config_ops = { .disassoc = ieee80211_disassoc, .join_ibss = ieee80211_join_ibss, .leave_ibss = ieee80211_leave_ibss, + .set_wiphy_params = ieee80211_set_wiphy_params, }; diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 210b9b6fecd2..5001328be46b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -52,13 +52,13 @@ static const struct file_operations name## _ops = { \ DEBUGFS_READONLY_FILE(frequency, 20, "%d", local->hw.conf.channel->center_freq); DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", - local->rts_threshold); + local->hw.wiphy->rts_threshold); DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", - local->fragmentation_threshold); + local->hw.wiphy->frag_threshold); DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", - local->hw.conf.short_frame_max_tx_count); + local->hw.wiphy->retry_short); DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", - local->hw.conf.long_frame_max_tx_count); + local->hw.wiphy->retry_long); DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", local->total_ps_buffered); DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 92a573bf1035..dba78d89a10c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -643,9 +643,6 @@ struct ieee80211_local { struct rate_control_ref *rate_ctrl; - int rts_threshold; - int fragmentation_threshold; - struct crypto_blkcipher *wep_tx_tfm; struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d26fc399285e..5320e08434ac 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -776,10 +776,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, /* set up some defaults */ local->hw.queues = 1; local->hw.max_rates = 1; - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - local->hw.conf.long_frame_max_tx_count = 4; - local->hw.conf.short_frame_max_tx_count = 7; + local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; + local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; local->hw.conf.radio_enabled = true; INIT_LIST_HEAD(&local->interfaces); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c53d77db3e4f..9ab49826c15a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -516,7 +516,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) sband = tx->local->hw.wiphy->bands[tx->channel->band]; len = min_t(int, tx->skb->len + FCS_LEN, - tx->local->fragmentation_threshold); + tx->local->hw.wiphy->frag_threshold); /* set up the tx rate control struct we give the RC algo */ txrc.hw = local_to_hw(tx->local); @@ -527,8 +527,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; /* set up RTS protection if desired */ - if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && - len > tx->local->rts_threshold) { + if (len > tx->local->hw.wiphy->rts_threshold) { txrc.rts = rts = true; } @@ -770,7 +769,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) struct sk_buff *skb = tx->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; - int frag_threshold = tx->local->fragmentation_threshold; + int frag_threshold = tx->local->hw.wiphy->frag_threshold; int hdrlen; int fragnum; @@ -1088,7 +1087,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, if (tx->flags & IEEE80211_TX_FRAGMENTED) { if ((tx->flags & IEEE80211_TX_UNICAST) && - skb->len + FCS_LEN > local->fragmentation_threshold && + skb->len + FCS_LEN > local->hw.wiphy->frag_threshold && !(info->flags & IEEE80211_TX_CTL_AMPDU)) tx->flags |= IEEE80211_TX_FRAGMENTED; else diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3dd490fa4b68..11244212f41d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1044,7 +1044,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* setup RTS threshold */ if (local->ops->set_rts_threshold) - local->ops->set_rts_threshold(hw, local->rts_threshold); + local->ops->set_rts_threshold(hw, hw->wiphy->rts_threshold); /* reconfigure hardware */ ieee80211_hw_config(local, ~0); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index eb63fc148019..1eb6d8642a77 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -472,132 +472,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev, return 0; } -static int ieee80211_ioctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - if (rts->disabled) - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - else if (!rts->fixed) - /* if the rts value is not fixed, then take default */ - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) - return -EINVAL; - else - local->rts_threshold = rts->value; - - /* If the wlan card performs RTS/CTS in hardware/firmware, - * configure it here */ - - if (local->ops->set_rts_threshold) - local->ops->set_rts_threshold(local_to_hw(local), - local->rts_threshold); - - return 0; -} - -static int ieee80211_ioctl_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - rts->value = local->rts_threshold; - rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD); - rts->fixed = 1; - - return 0; -} - - -static int ieee80211_ioctl_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - if (frag->disabled) - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - else if (!frag->fixed) - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - else if (frag->value < 256 || - frag->value > IEEE80211_MAX_FRAG_THRESHOLD) - return -EINVAL; - else { - /* Fragment length must be even, so strip LSB. */ - local->fragmentation_threshold = frag->value & ~0x1; - } - - return 0; -} - -static int ieee80211_ioctl_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - frag->value = local->fragmentation_threshold; - frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD); - frag->fixed = 1; - - return 0; -} - - -static int ieee80211_ioctl_siwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *retry, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - if (retry->disabled || - (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) - return -EINVAL; - - if (retry->flags & IW_RETRY_MAX) { - local->hw.conf.long_frame_max_tx_count = retry->value; - } else if (retry->flags & IW_RETRY_MIN) { - local->hw.conf.short_frame_max_tx_count = retry->value; - } else { - local->hw.conf.long_frame_max_tx_count = retry->value; - local->hw.conf.short_frame_max_tx_count = retry->value; - } - - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); - - return 0; -} - - -static int ieee80211_ioctl_giwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *retry, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - - retry->disabled = 0; - if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) { - /* first return min value, iwconfig will ask max value - * later if needed */ - retry->flags |= IW_RETRY_LIMIT; - retry->value = local->hw.conf.short_frame_max_tx_count; - if (local->hw.conf.long_frame_max_tx_count != - local->hw.conf.short_frame_max_tx_count) - retry->flags |= IW_RETRY_MIN; - return 0; - } - if (retry->flags & IW_RETRY_MAX) { - retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - retry->value = local->hw.conf.long_frame_max_tx_count; - } - - return 0; -} - - static int ieee80211_ioctl_siwencode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *keybuf) @@ -1050,14 +924,14 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* -- hole -- */ (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ - (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ - (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ + (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ + (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */ (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ - (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */ - (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ + (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ + (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ diff --git a/net/wireless/core.c b/net/wireless/core.c index 827a56263551..f256b4f7e833 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -273,6 +273,16 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) drv->wiphy.dev.class = &ieee80211_class; drv->wiphy.dev.platform_data = drv; + /* + * Initialize wiphy parameters to IEEE 802.11 MIB default values. + * Fragmentation and RTS threshold are disabled by default with the + * special -1 value. + */ + drv->wiphy.retry_short = 7; + drv->wiphy.retry_long = 4; + drv->wiphy.frag_threshold = (u32) -1; + drv->wiphy.rts_threshold = (u32) -1; + return &drv->wiphy; } EXPORT_SYMBOL(wiphy_new); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 16f86356ac97..5a9a5c6c71db 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -61,6 +61,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, + [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, + [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, @@ -204,6 +208,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); + + NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, + dev->wiphy.retry_short); + NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, + dev->wiphy.retry_long); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + dev->wiphy.frag_threshold); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, + dev->wiphy.rts_threshold); + NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, @@ -416,6 +430,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev; int result = 0, rem_txq_params = 0; struct nlattr *nl_txq_params; + u32 changed; + u8 retry_short = 0, retry_long = 0; + u32 frag_threshold = 0, rts_threshold = 0; rtnl_lock(); @@ -530,6 +547,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } + changed = 0; + + if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { + retry_short = nla_get_u8( + info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]); + if (retry_short == 0) { + result = -EINVAL; + goto bad_res; + } + changed |= WIPHY_PARAM_RETRY_SHORT; + } + + if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) { + retry_long = nla_get_u8( + info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]); + if (retry_long == 0) { + result = -EINVAL; + goto bad_res; + } + changed |= WIPHY_PARAM_RETRY_LONG; + } + + if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { + frag_threshold = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); + if (frag_threshold < 256) { + result = -EINVAL; + goto bad_res; + } + if (frag_threshold != (u32) -1) { + /* + * Fragments (apart from the last one) are required to + * have even length. Make the fragmentation code + * simpler by stripping LSB should someone try to use + * odd threshold value. + */ + frag_threshold &= ~0x1; + } + changed |= WIPHY_PARAM_FRAG_THRESHOLD; + } + + if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) { + rts_threshold = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]); + changed |= WIPHY_PARAM_RTS_THRESHOLD; + } + + if (changed) { + u8 old_retry_short, old_retry_long; + u32 old_frag_threshold, old_rts_threshold; + + if (!rdev->ops->set_wiphy_params) { + result = -EOPNOTSUPP; + goto bad_res; + } + + old_retry_short = rdev->wiphy.retry_short; + old_retry_long = rdev->wiphy.retry_long; + old_frag_threshold = rdev->wiphy.frag_threshold; + old_rts_threshold = rdev->wiphy.rts_threshold; + + if (changed & WIPHY_PARAM_RETRY_SHORT) + rdev->wiphy.retry_short = retry_short; + if (changed & WIPHY_PARAM_RETRY_LONG) + rdev->wiphy.retry_long = retry_long; + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + rdev->wiphy.frag_threshold = frag_threshold; + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + rdev->wiphy.rts_threshold = rts_threshold; + + result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); + if (result) { + rdev->wiphy.retry_short = old_retry_short; + rdev->wiphy.retry_long = old_retry_long; + rdev->wiphy.frag_threshold = old_frag_threshold; + rdev->wiphy.rts_threshold = old_rts_threshold; + } + } bad_res: mutex_unlock(&rdev->mtx); diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 4e054ea9c0a0..3279e7f038dc 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -314,3 +314,154 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_wext_freq); + +int cfg80211_wext_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + u32 orts = wdev->wiphy->rts_threshold; + int err; + + if (rts->disabled || !rts->fixed) + wdev->wiphy->rts_threshold = (u32) -1; + else if (rts->value < 0) + return -EINVAL; + else + wdev->wiphy->rts_threshold = rts->value; + + err = rdev->ops->set_wiphy_params(wdev->wiphy, + WIPHY_PARAM_RTS_THRESHOLD); + if (err) + wdev->wiphy->rts_threshold = orts; + + return err; +} +EXPORT_SYMBOL(cfg80211_wext_siwrts); + +int cfg80211_wext_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + rts->value = wdev->wiphy->rts_threshold; + rts->disabled = rts->value == (u32) -1; + rts->fixed = 1; + + return 0; +} +EXPORT_SYMBOL(cfg80211_wext_giwrts); + +int cfg80211_wext_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + u32 ofrag = wdev->wiphy->frag_threshold; + int err; + + if (frag->disabled || !frag->fixed) + wdev->wiphy->frag_threshold = (u32) -1; + else if (frag->value < 256) + return -EINVAL; + else { + /* Fragment length must be even, so strip LSB. */ + wdev->wiphy->frag_threshold = frag->value & ~0x1; + } + + err = rdev->ops->set_wiphy_params(wdev->wiphy, + WIPHY_PARAM_FRAG_THRESHOLD); + if (err) + wdev->wiphy->frag_threshold = ofrag; + + return err; +} +EXPORT_SYMBOL(cfg80211_wext_siwfrag); + +int cfg80211_wext_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + frag->value = wdev->wiphy->frag_threshold; + frag->disabled = frag->value == (u32) -1; + frag->fixed = 1; + + return 0; +} +EXPORT_SYMBOL(cfg80211_wext_giwfrag); + +int cfg80211_wext_siwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + u32 changed = 0; + u8 olong = wdev->wiphy->retry_long; + u8 oshort = wdev->wiphy->retry_short; + int err; + + if (retry->disabled || + (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) + return -EINVAL; + + if (retry->flags & IW_RETRY_LONG) { + wdev->wiphy->retry_long = retry->value; + changed |= WIPHY_PARAM_RETRY_LONG; + } else if (retry->flags & IW_RETRY_SHORT) { + wdev->wiphy->retry_short = retry->value; + changed |= WIPHY_PARAM_RETRY_SHORT; + } else { + wdev->wiphy->retry_short = retry->value; + wdev->wiphy->retry_long = retry->value; + changed |= WIPHY_PARAM_RETRY_LONG; + changed |= WIPHY_PARAM_RETRY_SHORT; + } + + if (!changed) + return 0; + + err = rdev->ops->set_wiphy_params(wdev->wiphy, changed); + if (err) { + wdev->wiphy->retry_short = oshort; + wdev->wiphy->retry_long = olong; + } + + return err; +} +EXPORT_SYMBOL(cfg80211_wext_siwretry); + +int cfg80211_wext_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + retry->disabled = 0; + + if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) { + /* + * First return short value, iwconfig will ask long value + * later if needed + */ + retry->flags |= IW_RETRY_LIMIT; + retry->value = wdev->wiphy->retry_short; + if (wdev->wiphy->retry_long != wdev->wiphy->retry_short) + retry->flags |= IW_RETRY_LONG; + + return 0; + } + + if (retry->flags & IW_RETRY_LONG) { + retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; + retry->value = wdev->wiphy->retry_long; + } + + return 0; +} +EXPORT_SYMBOL(cfg80211_wext_giwretry); -- cgit v1.2.3 From 9d308429a9fd0fa644f0b748f6241631f74a6cda Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 18:43:46 +0200 Subject: cfg80211: clear WEXT SSID when clearing IBSS When we leave an IBSS, we should clear the SSID and not just the BSSID, but since WEXT allows configuring while the interface is down we must not clear it when leaving due to taking the iface down, so some complications are needed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 2 +- net/wireless/core.h | 4 ++-- net/wireless/ibss.c | 21 ++++++++++++++------- net/wireless/nl80211.c | 4 ++-- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index f256b4f7e833..2006a4ee60eb 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -464,7 +464,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, break; if (!dev->ieee80211_ptr->ssid_len) break; - cfg80211_leave_ibss(rdev, dev); + cfg80211_leave_ibss(rdev, dev, true); break; case NETDEV_UP: #ifdef CONFIG_WIRELESS_EXT diff --git a/net/wireless/core.h b/net/wireless/core.h index 89a8159ef0b1..3e49d3399311 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -147,8 +147,8 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, struct net_device *dev, struct cfg80211_ibss_params *params); -void cfg80211_clear_ibss(struct net_device *dev); +void cfg80211_clear_ibss(struct net_device *dev, bool nowext); int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, - struct net_device *dev); + struct net_device *dev, bool nowext); #endif /* __NET_WIRELESS_CORE_H */ diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 4e1fcb0c9e4c..b5c601e1b1b7 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -76,7 +76,7 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, return 0; } -void cfg80211_clear_ibss(struct net_device *dev) +void cfg80211_clear_ibss(struct net_device *dev, bool nowext) { struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -88,10 +88,14 @@ void cfg80211_clear_ibss(struct net_device *dev) wdev->current_bss = NULL; wdev->ssid_len = 0; memset(wdev->bssid, 0, ETH_ALEN); +#ifdef CONFIG_WIRELESS_EXT + if (!nowext) + wdev->wext.ssid_len = 0; +#endif } int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, - struct net_device *dev) + struct net_device *dev, bool nowext) { int err; @@ -100,7 +104,7 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, if (err) return err; - cfg80211_clear_ibss(dev); + cfg80211_clear_ibss(dev, nowext); return 0; } @@ -179,7 +183,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, return 0; if (wdev->ssid_len) { - err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), dev); + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), + dev, true); if (err) return err; } @@ -241,7 +246,8 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, return -EOPNOTSUPP; if (wdev->ssid_len) { - err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), dev); + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), + dev, true); if (err) return err; } @@ -275,7 +281,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev, data->flags = 1; data->length = wdev->ssid_len; memcpy(ssid, wdev->ssid, data->length); - } else if (wdev->wext.ssid) { + } else if (wdev->wext.ssid && wdev->wext.ssid_len) { data->flags = 1; data->length = wdev->wext.ssid_len; memcpy(ssid, wdev->wext.ssid, data->length); @@ -318,7 +324,8 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, return 0; if (wdev->ssid_len) { - err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), dev); + err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), + dev, true); if (err) return err; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5a9a5c6c71db..97bb5c80125d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -833,7 +833,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) if (dev && !err && (ntype != otype)) { if (otype == NL80211_IFTYPE_ADHOC) - cfg80211_clear_ibss(dev); + cfg80211_clear_ibss(dev, false); } unlock: @@ -3249,7 +3249,7 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info) goto out; } - err = cfg80211_leave_ibss(drv, dev); + err = cfg80211_leave_ibss(drv, dev, false); out: cfg80211_put_dev(drv); -- cgit v1.2.3 From ba44cb7226afd4e19308c1d8a90e8b7c566c0d8b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 18:49:39 +0200 Subject: cfg80211: mark all WEXT handlers _GPL The fact that these are exported is a technical detail of the conversion period -- we don't want anybody to start relying on these. Ultimately we want things to use cfg80211 only, and once everything that is in wext is converted to cfg80211 drivers will not need to touch wext _at all_. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/scan.c | 4 ++-- net/wireless/wext-compat.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 1396248dc5cc..723aeb3d9462 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -653,7 +653,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, cfg80211_put_dev(rdev); return err; } -EXPORT_SYMBOL(cfg80211_wext_siwscan); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); static void ieee80211_scan_add_ies(struct iw_request_info *info, struct cfg80211_bss *bss, @@ -962,5 +962,5 @@ int cfg80211_wext_giwscan(struct net_device *dev, cfg80211_put_dev(rdev); return res; } -EXPORT_SYMBOL(cfg80211_wext_giwscan); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); #endif diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 3279e7f038dc..5ef82f2ca88f 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -57,7 +57,7 @@ int cfg80211_wext_giwname(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwname); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwname); int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, u32 *mode, char *extra) @@ -108,7 +108,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, return ret; } -EXPORT_SYMBOL(cfg80211_wext_siwmode); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, u32 *mode, char *extra) @@ -143,7 +143,7 @@ int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, } return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwmode); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwmode); int cfg80211_wext_giwrange(struct net_device *dev, @@ -239,7 +239,7 @@ int cfg80211_wext_giwrange(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwrange); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange); int cfg80211_wext_siwmlme(struct net_device *dev, struct iw_request_info *info, @@ -283,7 +283,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev, return -EOPNOTSUPP; } } -EXPORT_SYMBOL(cfg80211_wext_siwmlme); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); /** @@ -313,7 +313,7 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, } } -EXPORT_SYMBOL(cfg80211_wext_freq); +EXPORT_SYMBOL_GPL(cfg80211_wext_freq); int cfg80211_wext_siwrts(struct net_device *dev, struct iw_request_info *info, @@ -338,7 +338,7 @@ int cfg80211_wext_siwrts(struct net_device *dev, return err; } -EXPORT_SYMBOL(cfg80211_wext_siwrts); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwrts); int cfg80211_wext_giwrts(struct net_device *dev, struct iw_request_info *info, @@ -352,7 +352,7 @@ int cfg80211_wext_giwrts(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwrts); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwrts); int cfg80211_wext_siwfrag(struct net_device *dev, struct iw_request_info *info, @@ -379,7 +379,7 @@ int cfg80211_wext_siwfrag(struct net_device *dev, return err; } -EXPORT_SYMBOL(cfg80211_wext_siwfrag); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwfrag); int cfg80211_wext_giwfrag(struct net_device *dev, struct iw_request_info *info, @@ -393,7 +393,7 @@ int cfg80211_wext_giwfrag(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwfrag); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwfrag); int cfg80211_wext_siwretry(struct net_device *dev, struct iw_request_info *info, @@ -434,7 +434,7 @@ int cfg80211_wext_siwretry(struct net_device *dev, return err; } -EXPORT_SYMBOL(cfg80211_wext_siwretry); +EXPORT_SYMBOL_GPL(cfg80211_wext_siwretry); int cfg80211_wext_giwretry(struct net_device *dev, struct iw_request_info *info, @@ -464,4 +464,4 @@ int cfg80211_wext_giwretry(struct net_device *dev, return 0; } -EXPORT_SYMBOL(cfg80211_wext_giwretry); +EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); -- cgit v1.2.3 From e7ec86f54e519e8e86f1cf328db13263f3ef8bd4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 18 Apr 2009 17:33:24 +0200 Subject: mac80211: validate TIM IE length (redux) The TIM IE must not be shorter than 4 bytes, so verify that when parsing it and use the proper type. To ease that adjust struct ieee80211_tim_ie to have a virtual bitmap of size at least 1. Also check that the TIM IE is actually present before trying to parse it! Because other people may need the function, make it a static inline in ieee80211.h. (The original "mac80211: validate TIM IE length" was a minimal fix for 2.6.30. This purports to be the full, correct fix. -- JWL) Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 32 +++++++++++++++++++++++++++++++- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/mlme.c | 27 ++------------------------- net/mac80211/util.c | 6 ++++-- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 53563d53b5ad..c52e7fba4e40 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -540,7 +540,7 @@ struct ieee80211_tim_ie { u8 dtim_period; u8 bitmap_ctrl; /* variable size: 1 - 251 bytes */ - u8 virtual_map[0]; + u8 virtual_map[1]; } __attribute__ ((packed)); #define WLAN_SA_QUERY_TR_ID_LEN 16 @@ -1392,4 +1392,34 @@ static inline unsigned long ieee80211_tu_to_usec(unsigned long tu) return 1024 * tu; } +/** + * ieee80211_check_tim - check if AID bit is set in TIM + * @tim: the TIM IE + * @tim_len: length of the TIM IE + * @aid: the AID to look for + */ +static inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, + u8 tim_len, u16 aid) +{ + u8 mask; + u8 index, indexn1, indexn2; + + if (unlikely(!tim || tim_len < sizeof(*tim))) + return false; + + aid &= 0x3fff; + index = aid / 8; + mask = 1 << (aid & 7); + + indexn1 = tim->bitmap_ctrl & 0xfe; + indexn2 = tim_len + indexn1 - 4; + + if (index < indexn1 || index > indexn2) + return false; + + index -= indexn1; + + return !!(tim->virtual_map[index] & mask); +} + #endif /* LINUX_IEEE80211_H */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index dba78d89a10c..1579bc92c88d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -832,7 +832,7 @@ struct ieee802_11_elems { u8 *fh_params; u8 *ds_params; u8 *cf_params; - u8 *tim; + struct ieee80211_tim_ie *tim; u8 *ibss_params; u8 *challenge; u8 *wpa; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 428742d7f440..1b0b7aa387ee 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -675,30 +675,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, } } -static bool ieee80211_check_tim(struct ieee802_11_elems *elems, u16 aid) -{ - u8 mask; - u8 index, indexn1, indexn2; - struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim; - - if (unlikely(!tim || elems->tim_len < 4)) - return false; - - aid &= 0x3fff; - index = aid / 8; - mask = 1 << (aid & 7); - - indexn1 = tim->bitmap_ctrl & 0xfe; - indexn2 = elems->tim_len + indexn1 - 4; - - if (index < indexn1 || index > indexn2) - return false; - - index -= indexn1; - - return !!(tim->virtual_map[index] & mask); -} - static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, u16 capab, bool erp_valid, u8 erp) { @@ -1806,7 +1782,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, care_about_ies, ncrc); if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) - directed_tim = ieee80211_check_tim(&elems, ifmgd->aid); + directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, + ifmgd->aid); ncrc = crc32_be(ncrc, (void *)&directed_tim, sizeof(directed_tim)); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 11244212f41d..61876eb50b49 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -588,8 +588,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, elems->cf_params_len = elen; break; case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; + if (elen >= sizeof(struct ieee80211_tim_ie)) { + elems->tim = (void *)pos; + elems->tim_len = elen; + } break; case WLAN_EID_IBSS_PARAMS: elems->ibss_params = pos; -- cgit v1.2.3 From cca84799dfe9f5201ae9c69eb8ed15fd26b72b37 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 19 Apr 2009 01:28:12 +0200 Subject: ar9170: rework rxstream code With this patch ar9170 is capable of receiving aggregated 802.11n frames and sniffing on most networks without having a "debug message overhead". (Includes phy initialization requested by Johannes Berg -- JWL) Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 12 + drivers/net/wireless/ath/ar9170/hw.h | 15 +- drivers/net/wireless/ath/ar9170/main.c | 532 +++++++++++++++++++++++-------- 3 files changed, 421 insertions(+), 138 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index b6a1bff67cab..17bd3eaf3e03 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -104,10 +104,16 @@ enum ar9170_device_state { AR9170_ASSOCIATED, }; +struct ar9170_rxstream_mpdu_merge { + struct ar9170_rx_head plcp; + bool has_plcp; +}; + struct ar9170 { struct ieee80211_hw *hw; struct mutex mutex; enum ar9170_device_state state; + unsigned long bad_hw_nagger; int (*open)(struct ar9170 *); void (*stop)(struct ar9170 *); @@ -135,6 +141,7 @@ struct ar9170 { u64 cur_mc_hash, want_mc_hash; u32 cur_filter, want_filter; unsigned int filter_changed; + unsigned int filter_state; bool sniffer_enabled; /* PHY */ @@ -174,6 +181,11 @@ struct ar9170 { struct sk_buff_head global_tx_status; struct sk_buff_head global_tx_status_waste; struct delayed_work tx_status_janitor; + + /* rxstream mpdu merge */ + struct ar9170_rxstream_mpdu_merge rx_mpdu; + struct sk_buff *rx_failover; + int rx_failover_missing; }; struct ar9170_sta_info { diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 53e250a4278f..95bf812d6fcc 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -312,7 +312,7 @@ struct ar9170_rx_head { u8 plcp[12]; } __packed; -struct ar9170_rx_tail { +struct ar9170_rx_phystatus { union { struct { u8 rssi_ant0, rssi_ant1, rssi_ant2, @@ -324,6 +324,9 @@ struct ar9170_rx_tail { u8 evm_stream0[6], evm_stream1[6]; u8 phy_err; +} __packed; + +struct ar9170_rx_macstatus { u8 SAidx, DAidx; u8 error; u8 status; @@ -339,7 +342,7 @@ struct ar9170_rx_tail { #define AR9170_RX_ENC_SOFTWARE 0x8 -static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) +static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) { return (t->SAidx & 0xc0) >> 4 | (t->DAidx & 0xc0) >> 6; @@ -357,10 +360,9 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) #define AR9170_RX_STATUS_MPDU_MASK 0x30 #define AR9170_RX_STATUS_MPDU_SINGLE 0x00 -#define AR9170_RX_STATUS_MPDU_FIRST 0x10 -#define AR9170_RX_STATUS_MPDU_MIDDLE 0x20 -#define AR9170_RX_STATUS_MPDU_LAST 0x30 - +#define AR9170_RX_STATUS_MPDU_FIRST 0x20 +#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 +#define AR9170_RX_STATUS_MPDU_LAST 0x10 #define AR9170_RX_ERROR_RXTO 0x01 #define AR9170_RX_ERROR_OVERRUN 0x02 @@ -369,6 +371,7 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t) #define AR9170_RX_ERROR_WRONG_RA 0x10 #define AR9170_RX_ERROR_PLCP 0x20 #define AR9170_RX_ERROR_MMIC 0x40 +#define AR9170_RX_ERROR_FATAL 0x80 struct ar9170_cmd_tx_status { __le16 unkn; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 4682fe2f3f3c..1b60906b80c9 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -454,214 +454,430 @@ static void ar9170_handle_command_response(struct ar9170 *ar, } } -/* - * If the frame alignment is right (or the kernel has - * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there - * is only a single MPDU in the USB frame, then we can - * submit to mac80211 the SKB directly. However, since - * there may be multiple packets in one SKB in stream - * mode, and we need to observe the proper ordering, - * this is non-trivial. - */ -static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) { - struct sk_buff *skb; - struct ar9170_rx_head *head = (void *)buf; - struct ar9170_rx_tail *tail; - struct ieee80211_rx_status status; - int mpdu_len, i; - u8 error, antennas = 0, decrypt; - __le16 fc; - int reserved; + memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); + ar->rx_mpdu.has_plcp = false; +} - if (unlikely(!IS_STARTED(ar))) - return ; +static int ar9170_nag_limiter(struct ar9170 *ar) +{ + bool print_message; + + /* + * we expect all sorts of errors in promiscuous mode. + * don't bother with it, it's OK! + */ + if (ar->sniffer_enabled) + return false; + + /* + * only go for frequent errors! The hardware tends to + * do some stupid thing once in a while under load, in + * noisy environments or just for fun! + */ + if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) + print_message = true; + else + print_message = false; + + /* reset threshold for "once in a while" */ + ar->bad_hw_nagger = jiffies + HZ / 4; + return print_message; +} + +static int ar9170_rx_mac_status(struct ar9170 *ar, + struct ar9170_rx_head *head, + struct ar9170_rx_macstatus *mac, + struct ieee80211_rx_status *status) +{ + u8 error, decrypt; - /* Received MPDU */ - mpdu_len = len; - mpdu_len -= sizeof(struct ar9170_rx_head); - mpdu_len -= sizeof(struct ar9170_rx_tail); BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); - BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24); + BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); - if (mpdu_len <= FCS_LEN) - return; + error = mac->error; + if (error & AR9170_RX_ERROR_MMIC) { + status->flag |= RX_FLAG_MMIC_ERROR; + error &= ~AR9170_RX_ERROR_MMIC; + } - tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len); + if (error & AR9170_RX_ERROR_PLCP) { + status->flag |= RX_FLAG_FAILED_PLCP_CRC; + error &= ~AR9170_RX_ERROR_PLCP; - for (i = 0; i < 3; i++) - if (tail->rssi[i] != 0x80) - antennas |= BIT(i); + if (!(ar->filter_state & FIF_PLCPFAIL)) + return -EINVAL; + } - /* post-process RSSI */ - for (i = 0; i < 7; i++) - if (tail->rssi[i] & 0x80) - tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f; + if (error & AR9170_RX_ERROR_FCS) { + status->flag |= RX_FLAG_FAILED_FCS_CRC; + error &= ~AR9170_RX_ERROR_FCS; - memset(&status, 0, sizeof(status)); + if (!(ar->filter_state & FIF_FCSFAIL)) + return -EINVAL; + } + + decrypt = ar9170_get_decrypt_type(mac); + if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && + decrypt != AR9170_ENC_ALG_NONE) + status->flag |= RX_FLAG_DECRYPTED; - status.band = ar->channel->band; - status.freq = ar->channel->center_freq; - status.signal = ar->noise[0] + tail->rssi_combined; - status.noise = ar->noise[0]; - status.antenna = antennas; + /* ignore wrong RA errors */ + error &= ~AR9170_RX_ERROR_WRONG_RA; - switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) { + if (error & AR9170_RX_ERROR_DECRYPT) { + error &= ~AR9170_RX_ERROR_DECRYPT; + /* + * Rx decryption is done in place, + * the original data is lost anyway. + */ + + return -EINVAL; + } + + /* drop any other error frames */ + if (unlikely(error)) { + /* TODO: update netdevice's RX dropped/errors statistics */ + + if (ar9170_nag_limiter(ar)) + printk(KERN_DEBUG "%s: received frame with " + "suspicious error code (%#x).\n", + wiphy_name(ar->hw->wiphy), error); + + return -EINVAL; + } + + status->band = ar->channel->band; + status->freq = ar->channel->center_freq; + + switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { case AR9170_RX_STATUS_MODULATION_CCK: - if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE) - status.flag |= RX_FLAG_SHORTPRE; + if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) + status->flag |= RX_FLAG_SHORTPRE; switch (head->plcp[0]) { case 0x0a: - status.rate_idx = 0; + status->rate_idx = 0; break; case 0x14: - status.rate_idx = 1; + status->rate_idx = 1; break; case 0x37: - status.rate_idx = 2; + status->rate_idx = 2; break; case 0x6e: - status.rate_idx = 3; + status->rate_idx = 3; break; default: - if ((!ar->sniffer_enabled) && (net_ratelimit())) + if (ar9170_nag_limiter(ar)) printk(KERN_ERR "%s: invalid plcp cck rate " "(%x).\n", wiphy_name(ar->hw->wiphy), head->plcp[0]); - return; + return -EINVAL; } break; + case AR9170_RX_STATUS_MODULATION_OFDM: - switch (head->plcp[0] & 0xF) { - case 0xB: - status.rate_idx = 0; + switch (head->plcp[0] & 0xf) { + case 0xb: + status->rate_idx = 0; break; - case 0xF: - status.rate_idx = 1; + case 0xf: + status->rate_idx = 1; break; - case 0xA: - status.rate_idx = 2; + case 0xa: + status->rate_idx = 2; break; - case 0xE: - status.rate_idx = 3; + case 0xe: + status->rate_idx = 3; break; case 0x9: - status.rate_idx = 4; + status->rate_idx = 4; break; - case 0xD: - status.rate_idx = 5; + case 0xd: + status->rate_idx = 5; break; case 0x8: - status.rate_idx = 6; + status->rate_idx = 6; break; - case 0xC: - status.rate_idx = 7; + case 0xc: + status->rate_idx = 7; break; default: - if ((!ar->sniffer_enabled) && (net_ratelimit())) + if (ar9170_nag_limiter(ar)) printk(KERN_ERR "%s: invalid plcp ofdm rate " "(%x).\n", wiphy_name(ar->hw->wiphy), head->plcp[0]); - return; + return -EINVAL; } - if (status.band == IEEE80211_BAND_2GHZ) - status.rate_idx += 4; + if (status->band == IEEE80211_BAND_2GHZ) + status->rate_idx += 4; break; + case AR9170_RX_STATUS_MODULATION_HT: + if (head->plcp[3] & 0x80) + status->flag |= RX_FLAG_40MHZ; + if (head->plcp[6] & 0x80) + status->flag |= RX_FLAG_SHORT_GI; + + status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); + status->flag |= RX_FLAG_HT; + break; + case AR9170_RX_STATUS_MODULATION_DUPOFDM: /* XXX */ - - if (net_ratelimit()) + if (ar9170_nag_limiter(ar)) printk(KERN_ERR "%s: invalid modulation\n", wiphy_name(ar->hw->wiphy)); - return; + return -EINVAL; } - error = tail->error; + return 0; +} - if (error & AR9170_RX_ERROR_MMIC) { - status.flag |= RX_FLAG_MMIC_ERROR; - error &= ~AR9170_RX_ERROR_MMIC; - } +static void ar9170_rx_phy_status(struct ar9170 *ar, + struct ar9170_rx_phystatus *phy, + struct ieee80211_rx_status *status) +{ + int i; - if (error & AR9170_RX_ERROR_PLCP) { - status.flag |= RX_FLAG_FAILED_PLCP_CRC; - error &= ~AR9170_RX_ERROR_PLCP; + BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); + + for (i = 0; i < 3; i++) + if (phy->rssi[i] != 0x80) + status->antenna |= BIT(i); + + /* post-process RSSI */ + for (i = 0; i < 7; i++) + if (phy->rssi[i] & 0x80) + phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; + + /* TODO: we could do something with phy_errors */ + status->signal = ar->noise[0] + phy->rssi_combined; + status->noise = ar->noise[0]; +} + +static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) +{ + struct sk_buff *skb; + int reserved = 0; + struct ieee80211_hdr *hdr = (void *) buf; + + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + reserved += NET_IP_ALIGN; + + if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) + reserved += NET_IP_ALIGN; } - if (error & AR9170_RX_ERROR_FCS) { - status.flag |= RX_FLAG_FAILED_FCS_CRC; - error &= ~AR9170_RX_ERROR_FCS; + if (ieee80211_has_a4(hdr->frame_control)) + reserved += NET_IP_ALIGN; + + reserved = 32 + (reserved & NET_IP_ALIGN); + + skb = dev_alloc_skb(len + reserved); + if (likely(skb)) { + skb_reserve(skb, reserved); + memcpy(skb_put(skb, len), buf, len); } - decrypt = ar9170_get_decrypt_type(tail); - if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && - decrypt != AR9170_ENC_ALG_NONE) - status.flag |= RX_FLAG_DECRYPTED; + return skb; +} - /* ignore wrong RA errors */ - error &= ~AR9170_RX_ERROR_WRONG_RA; +/* + * If the frame alignment is right (or the kernel has + * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there + * is only a single MPDU in the USB frame, then we could + * submit to mac80211 the SKB directly. However, since + * there may be multiple packets in one SKB in stream + * mode, and we need to observe the proper ordering, + * this is non-trivial. + */ - if (error & AR9170_RX_ERROR_DECRYPT) { - error &= ~AR9170_RX_ERROR_DECRYPT; +static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +{ + struct ar9170_rx_head *head; + struct ar9170_rx_macstatus *mac; + struct ar9170_rx_phystatus *phy = NULL; + struct ieee80211_rx_status status; + struct sk_buff *skb; + int mpdu_len; + + if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) + return ; + + /* Received MPDU */ + mpdu_len = len - sizeof(*mac); + + mac = (void *)(buf + mpdu_len); + if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { + /* this frame is too damaged and can't be used - drop it */ - /* - * Rx decryption is done in place, - * the original data is lost anyway. - */ return ; } - /* drop any other error frames */ - if ((error) && (net_ratelimit())) { - printk(KERN_DEBUG "%s: errors: %#x\n", - wiphy_name(ar->hw->wiphy), error); - return; + switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { + case AR9170_RX_STATUS_MPDU_FIRST: + /* first mpdu packet has the plcp header */ + if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { + head = (void *) buf; + memcpy(&ar->rx_mpdu.plcp, (void *) buf, + sizeof(struct ar9170_rx_head)); + + mpdu_len -= sizeof(struct ar9170_rx_head); + buf += sizeof(struct ar9170_rx_head); + ar->rx_mpdu.has_plcp = true; + } else { + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: plcp info is clipped.\n", + wiphy_name(ar->hw->wiphy)); + return ; + } + break; + + case AR9170_RX_STATUS_MPDU_LAST: + /* last mpdu has a extra tail with phy status information */ + + if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { + mpdu_len -= sizeof(struct ar9170_rx_phystatus); + phy = (void *)(buf + mpdu_len); + } else { + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: frame tail is clipped.\n", + wiphy_name(ar->hw->wiphy)); + return ; + } + + case AR9170_RX_STATUS_MPDU_MIDDLE: + /* middle mpdus are just data */ + if (unlikely(!ar->rx_mpdu.has_plcp)) { + if (!ar9170_nag_limiter(ar)) + return ; + + printk(KERN_ERR "%s: rx stream did not start " + "with a first_mpdu frame tag.\n", + wiphy_name(ar->hw->wiphy)); + + return ; + } + + head = &ar->rx_mpdu.plcp; + break; + + case AR9170_RX_STATUS_MPDU_SINGLE: + /* single mpdu - has plcp (head) and phy status (tail) */ + head = (void *) buf; + + mpdu_len -= sizeof(struct ar9170_rx_head); + mpdu_len -= sizeof(struct ar9170_rx_phystatus); + + buf += sizeof(struct ar9170_rx_head); + phy = (void *)(buf + mpdu_len); + break; + + default: + BUG_ON(1); + break; } - buf += sizeof(struct ar9170_rx_head); - fc = *(__le16 *)buf; + if (unlikely(mpdu_len < FCS_LEN)) + return ; - if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc)) - reserved = 32 + 2; - else - reserved = 32; + memset(&status, 0, sizeof(status)); + if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) + return ; - skb = dev_alloc_skb(mpdu_len + reserved); - if (!skb) - return; + if (phy) + ar9170_rx_phy_status(ar, phy, &status); - skb_reserve(skb, reserved); - memcpy(skb_put(skb, mpdu_len), buf, mpdu_len); - ieee80211_rx_irqsafe(ar->hw, skb, &status); + skb = ar9170_rx_copy_data(buf, mpdu_len); + if (likely(skb)) + ieee80211_rx_irqsafe(ar->hw, skb, &status); } void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) { - unsigned int i, tlen, resplen; + unsigned int i, tlen, resplen, wlen = 0, clen = 0; u8 *tbuf, *respbuf; tbuf = skb->data; tlen = skb->len; while (tlen >= 4) { - int clen = tbuf[1] << 8 | tbuf[0]; - int wlen = (clen + 3) & ~3; + clen = tbuf[1] << 8 | tbuf[0]; + wlen = ALIGN(clen, 4); - /* - * parse stream (if any) - */ + /* check if this is stream has a valid tag.*/ if (tbuf[2] != 0 || tbuf[3] != 0x4e) { - printk(KERN_ERR "%s: missing tag!\n", - wiphy_name(ar->hw->wiphy)); + /* + * TODO: handle the highly unlikely event that the + * corrupted stream has the TAG at the right position. + */ + + /* check if the frame can be repaired. */ + if (!ar->rx_failover_missing) { + /* this is no "short read". */ + if (ar9170_nag_limiter(ar)) { + printk(KERN_ERR "%s: missing tag!\n", + wiphy_name(ar->hw->wiphy)); + goto err_telluser; + } else + goto err_silent; + } + + if (ar->rx_failover_missing > tlen) { + if (ar9170_nag_limiter(ar)) { + printk(KERN_ERR "%s: possible multi " + "stream corruption!\n", + wiphy_name(ar->hw->wiphy)); + goto err_telluser; + } else + goto err_silent; + } + + memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { + /* + * nested ar9170_rx call! + * termination is guranteed, even when the + * combined frame also have a element with + * a bad tag. + */ + + ar->rx_failover_missing = 0; + ar9170_rx(ar, ar->rx_failover); + + skb_reset_tail_pointer(ar->rx_failover); + skb_trim(ar->rx_failover, 0); + } + return ; } + + /* check if stream is clipped */ if (wlen > tlen - 4) { - printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n", - wiphy_name(ar->hw->wiphy), clen, wlen, tlen); - print_hex_dump(KERN_DEBUG, "data: ", - DUMP_PREFIX_OFFSET, - 16, 1, tbuf, tlen, true); + if (ar->rx_failover_missing) { + /* TODO: handle double stream corruption. */ + if (ar9170_nag_limiter(ar)) { + printk(KERN_ERR "%s: double rx stream " + "corruption!\n", + wiphy_name(ar->hw->wiphy)); + goto err_telluser; + } else + goto err_silent; + } + + /* + * save incomplete data set. + * the firmware will resend the missing bits when + * the rx - descriptor comes round again. + */ + + memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); + ar->rx_failover_missing = clen - tlen; return ; } resplen = clen; @@ -686,12 +902,44 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) if (i == 12) ar9170_handle_command_response(ar, respbuf, resplen); else - ar9170_handle_mpdu(ar, respbuf, resplen); + ar9170_handle_mpdu(ar, respbuf, clen); } - if (tlen) - printk(KERN_ERR "%s: buffer remains!\n", - wiphy_name(ar->hw->wiphy)); + if (tlen) { + if (net_ratelimit()) + printk(KERN_ERR "%s: %d bytes of unprocessed " + "data left in rx stream!\n", + wiphy_name(ar->hw->wiphy), tlen); + + goto err_telluser; + } + + return ; + +err_telluser: + printk(KERN_ERR "%s: damaged RX stream data [want:%d, " + "data:%d, rx:%d, pending:%d ]\n", + wiphy_name(ar->hw->wiphy), clen, wlen, tlen, + ar->rx_failover_missing); + + if (ar->rx_failover_missing) + print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, + ar->rx_failover->data, + ar->rx_failover->len); + + print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, + skb->data, skb->len); + + printk(KERN_ERR "%s: please check your hardware and cables, if " + "you see this message frequently.\n", + wiphy_name(ar->hw->wiphy)); + +err_silent: + if (ar->rx_failover_missing) { + skb_reset_tail_pointer(ar->rx_failover); + skb_trim(ar->rx_failover, 0); + ar->rx_failover_missing = 0; + } } #define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ @@ -721,6 +969,8 @@ static int ar9170_op_start(struct ieee80211_hw *hw) AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ + ar->bad_hw_nagger = jiffies; + err = ar->open(ar); if (err) goto out; @@ -1175,8 +1425,8 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, /* mask supported flags */ *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | - FIF_PROMISC_IN_BSS; - + FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; + ar->filter_state = *new_flags; /* * We can support more by setting the sniffer bit and * then checking the error flags, later. @@ -1559,20 +1809,33 @@ void *ar9170_alloc(size_t priv_size) { struct ieee80211_hw *hw; struct ar9170 *ar; + struct sk_buff *skb; int i; + /* + * this buffer is used for rx stream reconstruction. + * Under heavy load this device (or the transport layer?) + * tends to split the streams into seperate rx descriptors. + */ + + skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); + if (!skb) + goto err_nomem; + hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); if (!hw) - return ERR_PTR(-ENOMEM); + goto err_nomem; ar = hw->priv; ar->hw = hw; + ar->rx_failover = skb; mutex_init(&ar->mutex); spin_lock_init(&ar->cmdlock); spin_lock_init(&ar->tx_stats_lock); skb_queue_head_init(&ar->global_tx_status); skb_queue_head_init(&ar->global_tx_status_waste); + ar9170_rx_reset_rx_mpdu(ar); INIT_WORK(&ar->filter_config_work, ar9170_set_filters); INIT_WORK(&ar->beacon_work, ar9170_new_beacon); INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor); @@ -1600,6 +1863,10 @@ void *ar9170_alloc(size_t priv_size) ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ return ar; + +err_nomem: + kfree_skb(skb); + return ERR_PTR(-ENOMEM); } static int ar9170_read_eeprom(struct ar9170 *ar) @@ -1725,6 +1992,7 @@ void ar9170_unregister(struct ar9170 *ar) ar9170_unregister_leds(ar); #endif /* CONFIG_AR9170_LEDS */ + kfree_skb(ar->rx_failover); ieee80211_unregister_hw(ar->hw); mutex_destroy(&ar->mutex); } -- cgit v1.2.3 From 9b3bf06abad70db820c74c90118ea49358549d22 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 14:36:55 -0700 Subject: iwlwifi: rename PROBE_OPTION_MAX_API1 to PROBE_OPTION_MAX_3945 This limit applies to current (APIv1 and APIv2) 3945 firmware only, not supported firmware of any of the other cards. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 29d40746da6a..411a5d2d9148 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2469,8 +2469,8 @@ struct iwl_ssid_ie { u8 ssid[32]; } __attribute__ ((packed)); -#define PROBE_OPTION_MAX_API1 0x4 -#define PROBE_OPTION_MAX 0x14 +#define PROBE_OPTION_MAX_3945 4 +#define PROBE_OPTION_MAX 20 #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 @@ -2552,7 +2552,7 @@ struct iwl3945_scan_cmd { struct iwl3945_tx_cmd tx_cmd; /* For directed active scans (set to all-0s otherwise) */ - struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1]; + struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945]; /* * Probe request frame, followed by channel list. -- cgit v1.2.3 From 1ecf9fc1317f8df91eb1d74360f408558d657478 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 14:36:56 -0700 Subject: iwlwifi: improve scan support This modifies iwlwifi to * no longer build its own probe request, but use mac80211's * therefore, support arbitrary scan IEs (up to the max len) * support multiple scan SSIDs * support passive scanning Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 6 +- drivers/net/wireless/iwlwifi/iwl-core.h | 4 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 187 ++++++---------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 48 ++++--- 6 files changed, 73 insertions(+), 177 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 411a5d2d9148..7b84d5246b36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2474,6 +2474,7 @@ struct iwl_ssid_ie { #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 +#define IWL_MAX_PROBE_REQUEST 200 /* * REPLY_SCAN_CMD = 0x80 (command) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f23175240289..c43c57d7a4cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1309,8 +1309,10 @@ int iwl_setup_mac(struct iwl_priv *priv) BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->custom_regulatory = true; - hw->wiphy->max_scan_ssids = 1; - hw->wiphy->max_scan_ie_len = 0; /* XXX for now */ + + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; + /* we create the 802.11 header and a zero-length SSID element */ + hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8773d733a54e..8ab60df48d56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -396,8 +396,8 @@ int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_scan_initiate(struct iwl_priv *priv); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); -u16 iwl_fill_probe_req(struct iwl_priv *priv, enum ieee80211_band band, - struct ieee80211_mgmt *frame, int left); +u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, + const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); u16 iwl_get_active_dwell_time(struct iwl_priv *priv, enum ieee80211_band band, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0922e33a7d42..e363d9b05eeb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -889,9 +889,7 @@ struct iwl_priv { unsigned long scan_start_tsf; void *scan; int scan_bands; - int one_direct_scan; - u8 direct_ssid_len; - u8 direct_ssid[IW_ESSID_MAX_SIZE]; + struct cfg80211_scan_request *scan_request; u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 23644cf884f1..9edcf8c76b20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -448,13 +448,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, unsigned long flags; struct iwl_priv *priv = hw->priv; int ret; - u8 *ssid = NULL; - size_t ssid_len = 0; - - if (req->n_ssids) { - ssid = req->ssids[0].ssid; - ssid_len = req->ssids[0].ssid_len; - } IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -488,13 +481,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } - if (ssid_len) { - priv->one_direct_scan = 1; - priv->direct_ssid_len = ssid_len; - memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len); - } else { - priv->one_direct_scan = 0; - } + priv->scan_request = req; ret = iwl_scan_initiate(priv); @@ -532,74 +519,15 @@ void iwl_bg_scan_check(struct work_struct *data) } EXPORT_SYMBOL(iwl_bg_scan_check); -/** - * iwl_supported_rate_to_ie - fill in the supported rate in IE field - * - * return : set the bit for each supported rate insert in ie - */ -static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, - u16 basic_rate, int *left) -{ - u16 ret_rates = 0, bit; - int i; - u8 *cnt = ie; - u8 *rates = ie + 1; - - for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { - if (bit & supported_rate) { - ret_rates |= bit; - rates[*cnt] = iwl_rates[i].ieee | - ((bit & basic_rate) ? 0x80 : 0x00); - (*cnt)++; - (*left)--; - if ((*left <= 0) || - (*cnt >= IWL_SUPPORTED_RATES_IE_LEN)) - break; - } - } - - return ret_rates; -} - - -static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband, - u8 *pos, int *left) -{ - struct ieee80211_ht_cap *ht_cap; - - if (!sband || !sband->ht_cap.ht_supported) - return; - - if (*left < sizeof(struct ieee80211_ht_cap)) - return; - - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (struct ieee80211_ht_cap *) pos; - - ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap); - memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16); - ht_cap->ampdu_params_info = - (sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) | - ((sband->ht_cap.ampdu_density << 2) & - IEEE80211_HT_AMPDU_PARM_DENSITY); - *left -= sizeof(struct ieee80211_ht_cap); -} - /** * iwl_fill_probe_req - fill in all required fields and IE for probe request */ -u16 iwl_fill_probe_req(struct iwl_priv *priv, - enum ieee80211_band band, - struct ieee80211_mgmt *frame, - int left) +u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, + const u8 *ies, int ie_len, int left) { int len = 0; u8 *pos = NULL; - u16 active_rates, ret_rates, cck_rates, active_rate_basic; - const struct ieee80211_supported_band *sband = - iwl_get_hw_mode(priv, band); - /* Make sure there is enough space for the probe request, * two mandatory IEs and the data */ @@ -627,62 +555,12 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, len += 2; - /* fill in supported rate */ - left -= 2; - if (left < 0) - return 0; - - *pos++ = WLAN_EID_SUPP_RATES; - *pos = 0; - - /* exclude 60M rate */ - active_rates = priv->rates_mask; - active_rates &= ~IWL_RATE_60M_MASK; - - active_rate_basic = active_rates & IWL_BASIC_RATES_MASK; - - cck_rates = IWL_CCK_RATES_MASK & active_rates; - ret_rates = iwl_supported_rate_to_ie(pos, cck_rates, - active_rate_basic, &left); - active_rates &= ~ret_rates; - - ret_rates = iwl_supported_rate_to_ie(pos, active_rates, - active_rate_basic, &left); - active_rates &= ~ret_rates; + if (WARN_ON(left < ie_len)) + return len; - len += 2 + *pos; - pos += (*pos) + 1; - - if (active_rates == 0) - goto fill_end; - - /* fill in supported extended rate */ - /* ...next IE... */ - left -= 2; - if (left < 0) - return 0; - /* ... fill it in... */ - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos = 0; - iwl_supported_rate_to_ie(pos, active_rates, active_rate_basic, &left); - if (*pos > 0) { - len += 2 + *pos; - pos += (*pos) + 1; - } else { - pos--; - } - - fill_end: - - left -= 2; - if (left < 0) - return 0; - - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos = 0; - iwl_ht_cap_to_ie(sband, pos, &left); - if (*pos > 0) - len += 2 + *pos; + memcpy(pos, ies, ie_len); + len += ie_len; + left -= ie_len; return (u16)len; } @@ -703,10 +581,10 @@ static void iwl_bg_request_scan(struct work_struct *data) u32 rate_flags = 0; u16 cmd_len; enum ieee80211_band band; - u8 n_probes = 2; + u8 n_probes = 0; u8 rx_chain = priv->hw_params.valid_rx_ant; u8 rate; - DECLARE_SSID_BUF(ssid); + bool is_active = false; conf = ieee80211_get_hw_conf(priv->hw); @@ -796,19 +674,25 @@ static void iwl_bg_request_scan(struct work_struct *data) scan_suspend_time, interval); } - /* We should add the ability for user to lock to PASSIVE ONLY */ - if (priv->one_direct_scan) { - IWL_DEBUG_SCAN(priv, "Start direct scan for '%s'\n", - print_ssid(ssid, priv->direct_ssid, - priv->direct_ssid_len)); - scan->direct_scan[0].id = WLAN_EID_SSID; - scan->direct_scan[0].len = priv->direct_ssid_len; - memcpy(scan->direct_scan[0].ssid, - priv->direct_ssid, priv->direct_ssid_len); - n_probes++; - } else { - IWL_DEBUG_SCAN(priv, "Start indirect scan.\n"); - } + if (priv->scan_request->n_ssids) { + int i, p = 0; + IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } + is_active = true; + } else + IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; @@ -850,10 +734,11 @@ static void iwl_bg_request_scan(struct work_struct *data) cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); - - cmd_len = iwl_fill_probe_req(priv, band, - (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); scan->tx_cmd.len = cpu_to_le16(cmd_len); @@ -864,8 +749,7 @@ static void iwl_bg_request_scan(struct work_struct *data) RXON_FILTER_BCON_AWARE_MSK); scan->channel_count = - iwl_get_channels_for_scan(priv, band, 1, /* active */ - n_probes, + iwl_get_channels_for_scan(priv, band, is_active, n_probes, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); if (scan->channel_count == 0) { @@ -928,6 +812,7 @@ void iwl_bg_scan_completed(struct work_struct *work) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + priv->scan_request = NULL; ieee80211_scan_completed(priv->hw, false); /* Since setting the TXPOWER may have been deferred while diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ed497551a860..4df9b4b5072a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2942,9 +2942,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) int rc = 0; struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; - u8 n_probes = 2; + u8 n_probes = 0; enum ieee80211_band band; - DECLARE_SSID_BUF(ssid); + bool is_active = false; conf = ieee80211_get_hw_conf(priv->hw); @@ -3043,18 +3043,25 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan_suspend_time, interval); } - /* We should add the ability for user to lock to PASSIVE ONLY */ - if (priv->one_direct_scan) { - IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n", - print_ssid(ssid, priv->direct_ssid, - priv->direct_ssid_len)); - scan->direct_scan[0].id = WLAN_EID_SSID; - scan->direct_scan[0].len = priv->direct_ssid_len; - memcpy(scan->direct_scan[0].ssid, - priv->direct_ssid, priv->direct_ssid_len); - n_probes++; + if (priv->scan_request->n_ssids) { + int i, p = 0; + IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } + is_active = true; } else - IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n"); + IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n"); /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ @@ -3079,9 +3086,11 @@ static void iwl3945_bg_request_scan(struct work_struct *data) } scan->tx_cmd.len = cpu_to_le16( - iwl_fill_probe_req(priv, band, - (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan))); + iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan))); /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); @@ -3090,8 +3099,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->channel_count = - iwl3945_get_channels_for_scan(priv, band, 1, /* active */ - n_probes, + iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); if (scan->channel_count == 0) { @@ -4119,7 +4127,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) hw->wiphy->custom_regulatory = true; - hw->wiphy->max_scan_ssids = 1; /* WILL FIX */ + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; + /* we create the 802.11 header and a zero-length SSID element */ + hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; -- cgit v1.2.3 From b097ad29752f909ec1121ac3dc57d348f08dd8d7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 20 Apr 2009 14:36:57 -0700 Subject: iwlwifi: support truly passive scanning If passive scanning is requested we should not ask the microcode to do active scanning after detecting traffic on a channel -- that should only be used when an active scan is requested but some channels are marked passive. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 7 ++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 9edcf8c76b20..25311e1ceed7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -712,7 +712,12 @@ static void iwl_bg_request_scan(struct work_struct *data) } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { band = IEEE80211_BAND_5GHZ; rate = IWL_RATE_6M_PLCP; - scan->good_CRC_th = IWL_GOOD_CRC_TH; + /* + * If active scaning is requested but a certain channel + * is marked passive, we can do active scanning if we + * detect transmissions. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; /* Force use of chains B and C (0x6) for scan Rx for 4965 * Avoid A (0x1) because of its off-channel reception on A-band. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4df9b4b5072a..c15d0cfb93bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3078,7 +3078,12 @@ static void iwl3945_bg_request_scan(struct work_struct *data) band = IEEE80211_BAND_2GHZ; } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { scan->tx_cmd.rate = IWL_RATE_6M_PLCP; - scan->good_CRC_th = IWL_GOOD_CRC_TH; + /* + * If active scaning is requested but a certain channel + * is marked passive, we can do active scanning if we + * detect transmissions. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; band = IEEE80211_BAND_5GHZ; } else { IWL_WARN(priv, "Invalid scan band count\n"); -- cgit v1.2.3 From a75fbe8d68ceace836b27c216a5eda1c4687be4b Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Mon, 20 Apr 2009 14:36:58 -0700 Subject: iwl3945: add debugfs to 3945 Patch adds debugfs to 3945. Also fix debugfs registration in iwlagn to return error code if it fails. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 12de63e9c720..2751736b0b64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2829,7 +2829,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = iwl_dbgfs_register(priv, DRV_NAME); if (err) - IWL_ERR(priv, "failed to create debugfs files\n"); + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c15d0cfb93bc..bcfe199567e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4346,6 +4346,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if (err) goto out_remove_sysfs; + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); + err = iwl_rfkill_init(priv); if (err) IWL_ERR(priv, "Unable to initialize RFKILL system. " @@ -4396,6 +4400,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); + iwl_dbgfs_unregister(priv); + set_bit(STATUS_EXIT_PENDING, &priv->status); if (priv->mac80211_registered) { -- cgit v1.2.3 From 86ddbf62c2daefebba13e3c79f88cbdfde766176 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Mon, 20 Apr 2009 14:36:59 -0700 Subject: iwl3945: calculate debugfs isr statistics This patch calculates interrupt statistics for debugfs. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bcfe199567e6..562dd76226cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1543,6 +1543,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; } else { /* No handling needed */ IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR, @@ -1845,6 +1846,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) /* Tell the device to stop sending interrupts */ iwl_disable_interrupts(priv); + priv->isr_stats.hw++; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -1857,13 +1859,17 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) #ifdef CONFIG_IWLWIFI_DEBUG if (priv->debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) + if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); + priv->isr_stats.sch++; + } /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) + if (inta & CSR_INT_BIT_ALIVE) { IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; + } } #endif /* Safely ignore these bits for debug checks below */ @@ -1873,6 +1879,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) if (inta & CSR_INT_BIT_SW_ERR) { IWL_ERR(priv, "Microcode SW error detected. " "Restarting 0x%X.\n", inta); + priv->isr_stats.sw++; + priv->isr_stats.sw_err = inta; iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } @@ -1888,6 +1896,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) iwl_txq_update_write_ptr(priv, &priv->txq[4]); iwl_txq_update_write_ptr(priv, &priv->txq[5]); + priv->isr_stats.wakeup++; handled |= CSR_INT_BIT_WAKEUP; } @@ -1896,11 +1905,13 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { iwl3945_rx_handle(priv); + priv->isr_stats.rx++; handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); } if (inta & CSR_INT_BIT_FH_TX) { IWL_DEBUG_ISR(priv, "Tx interrupt\n"); + priv->isr_stats.tx++; iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); if (!iwl_grab_nic_access(priv)) { @@ -1911,8 +1922,10 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) handled |= CSR_INT_BIT_FH_TX; } - if (inta & ~handled) + if (inta & ~handled) { IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; + } if (inta & ~CSR_INI_SET_MASK) { IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", -- cgit v1.2.3 From 279b05d4362472ae9269f982f00e644265bdbf94 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 20 Apr 2009 14:37:00 -0700 Subject: iwlwifi: clean up unused NL80211_IFTYPE_MONITOR for Monitor mode This patch clean up the code for NL80211_IFTYPE_MONITOR mode, priv->iw_mode is set in add_interface, but add_interface is never called for monitor mode. The only way mac80211 informs us about monitor mode is through configuring filter; since iw_mode will never set to NL80211_IFTYPE_MONITOR, modify and remove all the code refer to NL80211_IFTYPE_MONITOR and replace with iwl_is_monitor_mode() function call. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 -- drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++------ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-rx.c | 7 ------- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 8 files changed, 7 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2751736b0b64..fc52d3229d66 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2001,8 +2001,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw) out: priv->is_open = 1; - /* default to MONITOR mode */ - priv->iw_mode = NL80211_IFTYPE_MONITOR; IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c43c57d7a4cb..bf7ad515e6a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -904,10 +904,11 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) * never called for monitor mode. The only way mac80211 informs us about * monitor mode is through configuring filters (call to configure_filter). */ -static bool iwl_is_monitor_mode(struct iwl_priv *priv) +bool iwl_is_monitor_mode(struct iwl_priv *priv) { return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); } +EXPORT_SYMBOL(iwl_is_monitor_mode); /** * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image @@ -1071,11 +1072,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) RXON_FILTER_ACCEPT_GRP_MSK; break; - case NL80211_IFTYPE_MONITOR: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; - priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | - RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - break; default: IWL_ERR(priv, "Unsupported interface type %d\n", mode); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8ab60df48d56..3bc2f6c3e8b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -267,6 +267,7 @@ int iwl_setup_mac(struct iwl_priv *priv); int iwl_set_hw_params(struct iwl_priv *priv); int iwl_init_drv(struct iwl_priv *priv); void iwl_uninit_drv(struct iwl_priv *priv); +bool iwl_is_monitor_mode(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv); void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 8f65908f66f1..fae84262efb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1102,13 +1102,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) rx_status.flag |= RX_FLAG_SHORTPRE; - /* Take shortcut when only in monitor mode */ - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - iwl_pass_packet_to_mac80211(priv, include_phy, - rxb, &rx_status); - return; - } - network_packet = iwl_is_network_packet(priv, header); if (network_packet) { priv->last_rx_rssi = rx_status.signal; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 25311e1ceed7..799f5eb61ece 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -747,7 +747,7 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) + if (iwl_is_monitor_mode(priv)) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index b8f18c697888..17a4dd2be1f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1078,11 +1078,6 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return priv->hw_params.bcast_sta_id; - /* If we are in monitor mode, use BCAST. This is required for - * packet injection. */ - case NL80211_IFTYPE_MONITOR: - return priv->hw_params.bcast_sta_id; - default: IWL_WARN(priv, "Unknown mode of operation: %d\n", priv->iw_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index c734c5f7e976..58cdd3294216 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -728,7 +728,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != NL80211_IFTYPE_MONITOR || + (!iwl_is_monitor_mode(priv) || !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */ (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 562dd76226cc..c9fde0e0c982 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -729,7 +729,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */ + (!iwl_is_monitor_mode(priv)) && /* packet injection */ (!iwl_is_associated(priv) || ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); @@ -3113,7 +3113,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) + if (iwl_is_monitor_mode(priv)) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->channel_count = -- cgit v1.2.3 From 447fee700f6cb7ada906c5db61c6c045741893e8 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Mon, 20 Apr 2009 14:37:02 -0700 Subject: iwlcore: Fix stay in table function. Function rs_stay_in_table was flushing the rate scale table way to early. time_after macro in expecting long value and was failing because we passing u32 value. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 98b6b37951b3..3504279c7586 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -52,7 +52,7 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 /* max time to accum history 2 seconds */ -#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) +#define IWL_RATE_SCALE_FLUSH_INTVL (3*HZ) static u8 rs_ht_to_legacy[] = { IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, @@ -135,7 +135,7 @@ struct iwl_lq_sta { u32 table_count; u32 total_failed; /* total failed frames, any/all rates */ u32 total_success; /* total successful frames, any/all rates */ - u32 flush_timer; /* time staying in mode before new search */ + u64 flush_timer; /* time staying in mode before new search */ u8 action_counter; /* # mode-switch actions tried */ u8 is_green; @@ -1025,6 +1025,7 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, lq_sta->table_count = 0; lq_sta->total_failed = 0; lq_sta->total_success = 0; + lq_sta->flush_timer = jiffies; } /* @@ -1914,8 +1915,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) /* Elapsed time using current modulation mode */ if (lq_sta->flush_timer) flush_interval_passed = - time_after(jiffies, - (unsigned long)(lq_sta->flush_timer + + time_after(jiffies, + (unsigned long)(lq_sta->flush_timer + IWL_RATE_SCALE_FLUSH_INTVL)); /* @@ -2249,6 +2250,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, update_lq = 1; index = low; } + break; case 1: /* Increase starting rate, update uCode's rate table */ @@ -2314,8 +2316,11 @@ lq_update: tbl->current_rate, index); rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); - } + } else + done_search = 1; + } + if (done_search && !lq_sta->stay_in_tbl) { /* If the "active" (non-search) mode was legacy, * and we've tried switching antennas, * but we haven't been able to try HT modes (not available), @@ -2350,17 +2355,6 @@ lq_update: lq_sta->action_counter = 0; rs_set_stay_in_table(priv, 0, lq_sta); } - - /* - * Else, don't search for a new modulation mode. - * Put new timestamp in stay-in-modulation-mode flush timer if: - * 1) Not changing rates right now - * 2) Not just finishing up a search - * 3) flush timer is empty - */ - } else { - if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer)) - lq_sta->flush_timer = jiffies; } out: -- cgit v1.2.3 From 09f9bf79b7870ac017a94f7f9b603c2e28ac73f7 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Mon, 20 Apr 2009 14:37:03 -0700 Subject: iwlwifi: remove radio disable parameter. Patch removes the "manual radio disable" parameter as there is no usage scenario of disabling radio using this module parameter. User can use iwconfig's txpower to enable and disable radio. This module parameter also does not work as expected. During module load the status of radio is set, the radio is not actually disabled. Even so, the moment mac80211 requests the interface to be up the radio will be enabled again. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 ++------------ drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 18 ++---------------- 5 files changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e4762e530345..a98ff4ead720 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2361,8 +2361,6 @@ MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(disable, iwl4965_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); module_param_named(debug, iwl4965_mod_params.debug, uint, 0444); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5bbb4f953364..d731a836e6c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1655,9 +1655,6 @@ struct iwl_cfg iwl5150_agn_cfg = { MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); -module_param_named(disable50, iwl50_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable50, - "manually disable the 50XX radio (default 0 [radio on])"); module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); MODULE_PARM_DESC(swcrypto50, "using software crypto engine (default 0 [hardware])\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fc52d3229d66..9e41e1bb7c79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2774,18 +2774,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_free_eeprom; /* At this point both hw and priv are initialized. */ - /********************************** - * 7. Initialize module parameters - **********************************/ - - /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (priv->cfg->mod_params->disable) { - set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO(priv, "Radio disabled.\n"); - } - /******************** - * 8. Setup services + * 7. Setup services ********************/ spin_lock_irqsave(&priv->lock, flags); iwl_disable_interrupts(priv); @@ -2809,7 +2799,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_setup_rx_handlers(priv); /********************************** - * 9. Setup and register mac80211 + * 8. Setup and register mac80211 **********************************/ /* enable interrupts if needed: hw bug w/a */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3bc2f6c3e8b9..d4c60afa2891 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -176,7 +176,6 @@ struct iwl_ops { }; struct iwl_mod_params { - int disable; /* def: 0 = enable radio */ int sw_crypto; /* def: 0 = using hardware encryption */ u32 debug; /* def: 0 = minimal debug log messages */ int disable_hw_scan; /* def: 0 = use h/w scan */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c9fde0e0c982..a5efb3b28c74 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4309,20 +4309,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); - /*********************************** - * 7. Initialize Module Parameters - * **********************************/ - - /* Initialize module parameter values here */ - /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (iwl3945_mod_params.disable) { - set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO(priv, "Radio disabled.\n"); - } - - /*********************** - * 8. Setup Services + * 7. Setup Services * ********************/ spin_lock_irqsave(&priv->lock, flags); @@ -4350,7 +4338,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_setup_rx_handlers(priv); /********************************* - * 9. Setup and Register mac80211 + * 8. Setup and Register mac80211 * *******************************/ iwl_enable_interrupts(priv); @@ -4528,8 +4516,6 @@ MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(disable, iwl3945_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); MODULE_PARM_DESC(swcrypto, "using software crypto (default 1 [software])\n"); -- cgit v1.2.3 From 0cf4c01ebe2ccf4487fe9301bab905365dca06c3 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Mon, 20 Apr 2009 14:37:04 -0700 Subject: iwlwifi: allow config if device not ready Allow user to config the device all the time but only allow commiting these changes to card if the card is up and running. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bf7ad515e6a0..3dec2d25fa3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2474,12 +2474,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - ret = -EIO; - goto out; - } - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", conf->channel->hw_value, changed); @@ -2574,6 +2568,11 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } + if (!iwl_is_ready(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); + goto out; + } + if (scan_active) goto out; -- cgit v1.2.3 From 29b4a4f7c7b588b5568edd0da42f38623b81fc66 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Apr 2009 00:30:49 +0200 Subject: mac80211: fix IBSS code to not sleep while atomic With the RCU locking here we sleep while in an atomic context, since we can sleep just use mutex locking for the interface list instead of RCU. Sorry, seems I didn't get that in my UML test. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 4f7a54518be4..6030e003180c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -784,14 +784,14 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_ADHOC) continue; sdata->u.ibss.last_scan_completed = jiffies; ieee80211_sta_find_ibss(sdata); } - rcu_read_unlock(); + mutex_unlock(&local->iflist_mtx); } ieee80211_rx_result -- cgit v1.2.3 From caa6dfadebee2098e9c5ece1d5efae96a6926d0f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Apr 2009 10:55:10 +0200 Subject: rndis_wlan: make some symbols static sparse complains, correctly, about these: drivers/net/wireless/rndis_wlan.c:418:21: warning: symbol 'rndis_config_ops' was not declared. Should it be static? drivers/net/wireless/rndis_wlan.c:423:6: warning: symbol 'rndis_wiphy_privid' was not declared. Should it be static? Fix that. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 109e60343363..4b11ceae5b64 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -415,12 +415,12 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex, static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request); -struct cfg80211_ops rndis_config_ops = { +static struct cfg80211_ops rndis_config_ops = { .change_virtual_intf = rndis_change_virtual_intf, .scan = rndis_scan, }; -void *rndis_wiphy_privid = &rndis_wiphy_privid; +static void *rndis_wiphy_privid = &rndis_wiphy_privid; static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; -- cgit v1.2.3 From 8d4d99ae89a8845a1d63b0529dd98da28dc0ff65 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 21 Apr 2009 19:48:07 +0300 Subject: rndis_wlan: fix initialization order for workqueue&workers rndis_wext_link_change() might be called from rndis_command() at initialization stage and priv->workqueue/priv->work have not been initialized yet. This causes invalid opcode at rndis_wext_bind on some brands of bcm4320. Fix by initializing workqueue/workers in rndis_wext_bind() before rndis_command is used. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 4b11ceae5b64..9ef547d6724e 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2384,6 +2384,12 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) mutex_init(&priv->command_lock); spin_lock_init(&priv->stats_lock); + /* because rndis_command() sleeps we need to use workqueue */ + priv->workqueue = create_singlethread_workqueue("rndis_wlan"); + INIT_WORK(&priv->work, rndis_wext_worker); + INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); + INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results); + /* try bind rndis_host */ retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); if (retval < 0) @@ -2454,17 +2460,18 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) disassociate(usbdev, 1); netif_carrier_off(usbdev->net); - /* because rndis_command() sleeps we need to use workqueue */ - priv->workqueue = create_singlethread_workqueue("rndis_wlan"); - INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); queue_delayed_work(priv->workqueue, &priv->stats_work, round_jiffies_relative(STATS_UPDATE_JIFFIES)); - INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results); - INIT_WORK(&priv->work, rndis_wext_worker); return 0; fail: + cancel_delayed_work_sync(&priv->stats_work); + cancel_delayed_work_sync(&priv->scan_work); + cancel_work_sync(&priv->work); + flush_workqueue(priv->workqueue); + destroy_workqueue(priv->workqueue); + kfree(priv); return retval; } -- cgit v1.2.3 From eb1a685e07310b5137c561e25ab738292db2c8a5 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 21 Apr 2009 19:48:15 +0300 Subject: rndis_wlan: free priv correctly when rndis_wext_bind fails Private structure is allocated by wiphy_new now, so use wiphy_free instead of kfree. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9ef547d6724e..52fc647e6cb6 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2449,8 +2449,8 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) set_wiphy_dev(wiphy, &usbdev->udev->dev); if (wiphy_register(wiphy)) { - wiphy_free(wiphy); - return -ENODEV; + retval = -ENODEV; + goto fail; } set_default_iw_params(usbdev); @@ -2472,7 +2472,7 @@ fail: flush_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue); - kfree(priv); + wiphy_free(wiphy); return retval; } -- cgit v1.2.3 From 1d4df3a50f40a731fc03c86a76535ed141b0e4bc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Apr 2009 11:25:43 +0200 Subject: mac80211: fix variable truncation on 32-bit Stephen Rothwell reported these warnings from a 32-bit build: net/mac80211/mlme.c:1771: warning: left shift count >= width of type net/mac80211/mlme.c:1772: warning: left shift count >= width of type net/mac80211/mlme.c:1773: warning: left shift count >= width of type net/mac80211/mlme.c:1774: warning: left shift count >= width of type net/mac80211/mlme.c:1775: warning: left shift count >= width of type This shows a bug in my code -- BIT(X) uses just "1 << X" which means a 32-bit integer on 32-bit platforms, but the code here needs a u64 on all platforms. Fix this by using "1ULL << X" instead of BIT(X). Thanks Stephen! Reported-by: Stephen Rothwell Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1b0b7aa387ee..e819c02d13f0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1743,12 +1743,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, * look out for other vendor IEs. */ static const u64 care_about_ies = - BIT(WLAN_EID_COUNTRY) | - BIT(WLAN_EID_ERP_INFO) | - BIT(WLAN_EID_CHANNEL_SWITCH) | - BIT(WLAN_EID_PWR_CONSTRAINT) | - BIT(WLAN_EID_HT_CAPABILITY) | - BIT(WLAN_EID_HT_INFORMATION); + (1ULL << WLAN_EID_COUNTRY) | + (1ULL << WLAN_EID_ERP_INFO) | + (1ULL << WLAN_EID_CHANNEL_SWITCH) | + (1ULL << WLAN_EID_PWR_CONSTRAINT) | + (1ULL << WLAN_EID_HT_CAPABILITY) | + (1ULL << WLAN_EID_HT_INFORMATION); static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, -- cgit v1.2.3 From e255d5eb2b478eec1416b46aea03798b64355402 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Apr 2009 12:40:07 +0200 Subject: mac80211: remove IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT Just setting IEEE80211_CONF_CHANGE_PS should be sufficient for changes in the power saving things. The driver already tells us whether it wants notification of dynps via the "have dynps support" hw flag. Signed-off-by: Johannes Berg Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 10 ++++------ net/mac80211/wext.c | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d9686917252b..183956e4930a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -532,8 +532,7 @@ enum ieee80211_conf_flags { * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed - * @IEEE80211_CONF_CHANGE_PS: the PS flag changed - * @IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT: the dynamic PS timeout changed + * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed * @IEEE80211_CONF_CHANGE_POWER: the TX power changed * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed @@ -544,10 +543,9 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), IEEE80211_CONF_CHANGE_PS = BIT(4), - IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT = BIT(5), - IEEE80211_CONF_CHANGE_POWER = BIT(6), - IEEE80211_CONF_CHANGE_CHANNEL = BIT(7), - IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(8), + IEEE80211_CONF_CHANGE_POWER = BIT(5), + IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), + IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), }; /** diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1eb6d8642a77..1a649da42c41 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -622,8 +622,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, conf->dynamic_ps_timeout = timeout; if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - ieee80211_hw_config(local, - IEEE80211_CONF_CHANGE_DYNPS_TIMEOUT); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); ieee80211_recalc_ps(local, -1); -- cgit v1.2.3 From 8e30bc55de98c000b0b836cb42525c82f605f191 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Apr 2009 17:45:38 +0200 Subject: nl80211: allow configuring IBSS beacon interval Make the JOIN_IBSS command look at the beacon interval attribute to see if the user requested a specific beacon interval, if not default to 100 TU (wext too). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 4 +++- include/net/cfg80211.h | 2 ++ net/wireless/ibss.c | 3 +++ net/wireless/nl80211.c | 12 +++++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index dc9d9ec5d1ae..b6a48dd502ce 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -230,7 +230,9 @@ * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those * should be fixed rather than automatically determined. Can only be * executed on a network interface that is UP, and fixed BSSID/FREQ - * may be rejected. + * may be rejected. Another optional parameter is the beacon interval, + * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not + * given defaults to 100 TU (102.4ms). * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is * determined by the network interface. * diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 54bc69c83691..7f7b53b69cb2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -733,6 +733,7 @@ struct cfg80211_disassoc_request { * IBSSs to join on other channels. * @ie: information element(s) to include in the beacon * @ie_len: length of that + * @beacon_interval: beacon interval to use */ struct cfg80211_ibss_params { u8 *ssid; @@ -740,6 +741,7 @@ struct cfg80211_ibss_params { struct ieee80211_channel *channel; u8 *ie; u8 ssid_len, ie_len; + u16 beacon_interval; bool channel_fixed; }; diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index b5c601e1b1b7..3c38afaed28a 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -116,6 +116,9 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, enum ieee80211_band band; int i; + if (!wdev->wext.beacon_interval) + wdev->wext.beacon_interval = 100; + /* try to find an IBSS channel if none requested ... */ if (!wdev->wext.channel) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 97bb5c80125d..3b21b3e89e96 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3159,6 +3159,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err; + memset(&ibss, 0, sizeof(ibss)); + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) return -EINVAL; @@ -3167,6 +3169,15 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) !nla_len(info->attrs[NL80211_ATTR_SSID])) return -EINVAL; + ibss.beacon_interval = 100; + + if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { + ibss.beacon_interval = + nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); + if (ibss.beacon_interval < 1 || ibss.beacon_interval > 10000) + return -EINVAL; + } + rtnl_lock(); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); @@ -3189,7 +3200,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) } wiphy = &drv->wiphy; - memset(&ibss, 0, sizeof(ibss)); if (info->attrs[NL80211_ATTR_MAC]) ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); -- cgit v1.2.3 From 04fe20372e70685d9f15966216cdffd3795fe590 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Apr 2009 18:44:37 +0200 Subject: mac80211: calculate maximum sleep interval The maximum sleep interval, for powersave purposes, is determined by the DTIM period (it may not be larger) and the required networking latency (it must be small enough to fulfil those constraints). This makes mac80211 calculate the maximum sleep interval based on those constraints, and pass it to the driver. Then the driver should instruct the device to sleep at most that long. Note that the device is responsible for aligning the maximum sleep interval between DTIMs, we make sure it's not longer but it needs to make sure it's between them. Also, group some powersave documentation together and make it more explicit that we support managed mode only, and no IBSS powersaving (yet). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 19 ++++++++++++++++--- net/mac80211/mlme.c | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 183956e4930a..446dbf75a1c5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -517,7 +517,7 @@ struct ieee80211_rx_status { * Flags to define PHY configuration options * * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) - * @IEEE80211_CONF_PS: Enable 802.11 power save mode + * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only) */ enum ieee80211_conf_flags { IEEE80211_CONF_RADIOTAP = (1<<0), @@ -553,14 +553,26 @@ enum ieee80211_conf_changed { * * This struct indicates how the driver shall configure the hardware. * + * @flags: configuration flags defined above + * * @radio_enabled: when zero, driver is required to switch off the radio. * @beacon_int: beacon interval (TODO make interface config) + * * @listen_interval: listen interval in units of beacon interval - * @flags: configuration flags defined above + * @max_sleep_interval: the maximum number of beacon intervals to sleep for + * before checking the beacon for a TIM bit (managed mode only); this + * value will be only achievable between DTIM frames, the hardware + * needs to check for the multicast traffic bit in DTIM beacons. + * This variable is valid only when the CONF_PS flag is set. + * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the + * powersave documentation below. This variable is valid only when + * the CONF_PS flag is set. + * * @power_level: requested transmit power (in dBm) - * @dynamic_ps_timeout: dynamic powersave timeout (in ms) + * * @channel: the channel to tune to * @channel_type: the channel (HT) type + * * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, * but actually means the number of transmissions not the number of retries @@ -572,6 +584,7 @@ struct ieee80211_conf { int beacon_int; u32 flags; int power_level, dynamic_ps_timeout; + int max_sleep_interval; u16 listen_interval; bool radio_enabled; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e819c02d13f0..df27c68620c9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -545,10 +545,19 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) beaconint_us = ieee80211_tu_to_usec( found->vif.bss_conf.beacon_int); - if (beaconint_us > latency) + if (beaconint_us > latency) { local->ps_sdata = NULL; - else + } else { + u8 dtimper = found->vif.bss_conf.dtim_period; + int maxslp = 1; + + if (dtimper > 1) + maxslp = min_t(int, dtimper, + latency / beaconint_us); + + local->hw.conf.max_sleep_interval = maxslp; local->ps_sdata = found; + } } else { local->ps_sdata = NULL; } @@ -851,8 +860,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_bss_info_change_notify(sdata, bss_info_changed); /* will be same as sdata */ - if (local->ps_sdata) - ieee80211_enable_ps(local, sdata); + if (local->ps_sdata) { + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, -1); + mutex_unlock(&local->iflist_mtx); + } netif_tx_start_all_queues(sdata->dev); netif_carrier_on(sdata->dev); -- cgit v1.2.3 From ff2ba188fc5eaae529cb2ef9b127c3ca2a7df4b9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 22 Apr 2009 13:27:08 -0400 Subject: rndis_wlan: select CFG80211 in Kconfig Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 11c248180982..2d8434f409b6 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -337,6 +337,7 @@ config USB_NET_RNDIS_WLAN select USB_NET_CDCETHER select USB_NET_RNDIS_HOST select WIRELESS_EXT + select CFG80211 ---help--- This is a driver for wireless RNDIS devices. These are USB based adapters found in devices such as: -- cgit v1.2.3 From 1965c85331ed29dc4fd32479ff31663e3e9a518f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 22 Apr 2009 21:38:25 +0300 Subject: nl80211: Add event for authentication/association timeout SME needs to be notified when the authentication or association attempt times out and MLME has stopped processing in order to allow the SME to decide what to do next. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 13 +++++++++++-- include/net/cfg80211.h | 22 ++++++++++++++++++++-- net/mac80211/mlme.c | 4 ++-- net/wireless/mlme.c | 27 +++++++++++++++++++++++++++ net/wireless/nl80211.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ net/wireless/nl80211.h | 6 ++++++ 6 files changed, 115 insertions(+), 6 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index b6a48dd502ce..e9fd13aa79f0 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -203,8 +203,12 @@ * frame, i.e., it was for the local STA and was received in correct * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the * MLME SAP interface (kernel providing MLME, userspace SME). The - * included NL80211_ATTR_FRAME attribute contains the management frame - * (including both the header and frame body, but not FCS). + * included %NL80211_ATTR_FRAME attribute contains the management frame + * (including both the header and frame body, but not FCS). This event is + * also used to indicate if the authentication attempt timed out. In that + * case the %NL80211_ATTR_FRAME attribute is replaced with a + * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which + * pending authentication timed out). * @NL80211_CMD_ASSOCIATE: association request and notification; like * NL80211_CMD_AUTHENTICATE but for Association and Reassociation * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, @@ -487,6 +491,9 @@ enum nl80211_commands { * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look * for other networks on different channels * + * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this + * is used, e.g., with %NL80211_CMD_AUTHENTICATE event + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -587,6 +594,8 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_FRAG_THRESHOLD, NL80211_ATTR_WIPHY_RTS_THRESHOLD, + NL80211_ATTR_TIMED_OUT, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7f7b53b69cb2..b8a76764e1c5 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1475,10 +1475,19 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); * @len: length of the frame data * * This function is called whenever an authentication has been processed in - * station mode. + * station mode. The driver is required to call either this function or + * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth() + * call. */ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); +/** + * cfg80211_send_auth_timeout - notification of timed out authentication + * @dev: network device + * @addr: The MAC address of the device with which the authentication timed out + */ +void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); + /** * cfg80211_send_rx_assoc - notification of processed association * @dev: network device @@ -1486,10 +1495,19 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); * @len: length of the frame data * * This function is called whenever a (re)association response has been - * processed in station mode. + * processed in station mode. The driver is required to call either this + * function or cfg80211_send_assoc_timeout() to indicate the result of + * cfg80211_ops::assoc() call. */ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len); +/** + * cfg80211_send_assoc_timeout - notification of timed out association + * @dev: network device + * @addr: The MAC address of the device with which the association timed out + */ +void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); + /** * cfg80211_send_deauth - notification of processed deauthentication * @dev: network device diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index df27c68620c9..3610c11286bc 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -932,7 +932,7 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) " timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_sta_send_apinfo(sdata); + cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, ifmgd->ssid, ifmgd->ssid_len); @@ -1115,7 +1115,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) " timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_sta_send_apinfo(sdata); + cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid); ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, ifmgd->ssid, ifmgd->ssid_len); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1407244a647e..42184361a109 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -44,6 +44,33 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) } EXPORT_SYMBOL(cfg80211_send_disassoc); +static void cfg80211_wext_disconnected(struct net_device *dev) +{ +#ifdef CONFIG_WIRELESS_EXT + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); +#endif +} + +void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_auth_timeout(rdev, dev, addr); + cfg80211_wext_disconnected(dev); +} +EXPORT_SYMBOL(cfg80211_send_auth_timeout); + +void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + nl80211_send_assoc_timeout(rdev, dev, addr); + cfg80211_wext_disconnected(dev); +} +EXPORT_SYMBOL(cfg80211_send_assoc_timeout); + void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, enum nl80211_key_type key_type, int key_id, const u8 *tsc) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3b21b3e89e96..b1fc98225fd1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -121,6 +121,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 }, [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, + [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG }, }; /* IE validation */ @@ -3695,6 +3696,54 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, NL80211_CMD_DISASSOCIATE); } +void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, int cmd, + const u8 *addr) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *addr) +{ + nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE, + addr); +} + +void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, const u8 *addr) +{ + nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr); +} + void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, gfp_t gfp) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 17d2d8bfaf75..5c12ad13499b 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -23,6 +23,12 @@ extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev, extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *buf, size_t len); +extern void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *addr); +extern void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + const u8 *addr); extern void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *addr, -- cgit v1.2.3 From 42e1b4c2c6c823ae26e64c557addf5329a7735b7 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Tue, 21 Apr 2009 23:26:20 +0000 Subject: iucv: provide second per-cpu IUCV command parameter block Some of the IUCV commands can be invoked in interrupt context. Those commands need a different per-cpu IUCV command parameter block, otherwise they might overwrite an IUCV command parameter of a not yet finished IUCV command invocation in process context. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/iucv.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index a35240f61ec3..fcf404065f12 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -280,6 +280,7 @@ union iucv_param { * Anchor for per-cpu IUCV command parameter block. */ static union iucv_param *iucv_param[NR_CPUS]; +static union iucv_param *iucv_param_irq[NR_CPUS]; /** * iucv_call_b2f0 @@ -358,7 +359,7 @@ static void iucv_allow_cpu(void *data) * 0x10 - Flag to allow priority message completion interrupts * 0x08 - Flag to allow IUCV control interrupts */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; memset(parm, 0, sizeof(union iucv_param)); parm->set_mask.ipmask = 0xf8; iucv_call_b2f0(IUCV_SETMASK, parm); @@ -379,7 +380,7 @@ static void iucv_block_cpu(void *data) union iucv_param *parm; /* Disable all iucv interrupts. */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; memset(parm, 0, sizeof(union iucv_param)); iucv_call_b2f0(IUCV_SETMASK, parm); @@ -403,7 +404,7 @@ static void iucv_declare_cpu(void *data) return; /* Declare interrupt buffer. */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; memset(parm, 0, sizeof(union iucv_param)); parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]); rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); @@ -460,7 +461,7 @@ static void iucv_retrieve_cpu(void *data) iucv_block_cpu(NULL); /* Retrieve interrupt buffer. */ - parm = iucv_param[cpu]; + parm = iucv_param_irq[cpu]; iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); /* Clear indication that an iucv buffer exists for this cpu. */ @@ -574,11 +575,22 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, iucv_irq_data[cpu] = NULL; return NOTIFY_BAD; } + iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_param_irq[cpu]) { + kfree(iucv_param[cpu]); + iucv_param[cpu] = NULL; + kfree(iucv_irq_data[cpu]); + iucv_irq_data[cpu] = NULL; + return NOTIFY_BAD; + } break; case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: + kfree(iucv_param_irq[cpu]); + iucv_param_irq[cpu] = NULL; kfree(iucv_param[cpu]); iucv_param[cpu] = NULL; kfree(iucv_irq_data[cpu]); @@ -625,7 +637,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) { union iucv_param *parm; - parm = iucv_param[smp_processor_id()]; + parm = iucv_param_irq[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (userdata) memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); @@ -918,10 +930,8 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) if (iucv_active_cpu != smp_processor_id()) spin_lock_bh(&iucv_table_lock); rc = iucv_sever_pathid(path->pathid, userdata); - if (!rc) { - iucv_path_table[path->pathid] = NULL; - list_del_init(&path->list); - } + iucv_path_table[path->pathid] = NULL; + list_del_init(&path->list); if (iucv_active_cpu != smp_processor_id()) spin_unlock_bh(&iucv_table_lock); preempt_enable(); @@ -1413,7 +1423,7 @@ static void iucv_path_severed(struct iucv_irq_data *data) else { iucv_sever_pathid(path->pathid, NULL); iucv_path_table[path->pathid] = NULL; - list_del_init(&path->list); + list_del(&path->list); iucv_path_free(path); } } @@ -1717,6 +1727,13 @@ static int __init iucv_init(void) rc = -ENOMEM; goto out_free; } + iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_param_irq[cpu]) { + rc = -ENOMEM; + goto out_free; + } + } rc = register_hotcpu_notifier(&iucv_cpu_notifier); if (rc) @@ -1734,6 +1751,8 @@ out_cpu: unregister_hotcpu_notifier(&iucv_cpu_notifier); out_free: for_each_possible_cpu(cpu) { + kfree(iucv_param_irq[cpu]); + iucv_param_irq[cpu] = NULL; kfree(iucv_param[cpu]); iucv_param[cpu] = NULL; kfree(iucv_irq_data[cpu]); @@ -1764,6 +1783,8 @@ static void __exit iucv_exit(void) spin_unlock_irq(&iucv_queue_lock); unregister_hotcpu_notifier(&iucv_cpu_notifier); for_each_possible_cpu(cpu) { + kfree(iucv_param_irq[cpu]); + iucv_param_irq[cpu] = NULL; kfree(iucv_param[cpu]); iucv_param[cpu] = NULL; kfree(iucv_irq_data[cpu]); -- cgit v1.2.3 From af88b52def76679c8c5bcdbed199fbe62b6a16d4 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:21 +0000 Subject: af_iucv: sync sk shutdown flag if iucv path is quiesced If the af_iucv communication partner quiesces the path to shutdown its receive direction, provide a quiesce callback implementation to shutdown the (local) send direction. This ensures that both sides are synchronized. Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 49e786535dc8..6cf02b41ef95 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -54,6 +54,7 @@ static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]); static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]); static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]); +static void iucv_callback_shutdown(struct iucv_path *, u8 ipuser[16]); static struct iucv_sock_list iucv_sk_list = { .lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock), @@ -65,7 +66,8 @@ static struct iucv_handler af_iucv_handler = { .path_complete = iucv_callback_connack, .path_severed = iucv_callback_connrej, .message_pending = iucv_callback_rx, - .message_complete = iucv_callback_txdone + .message_complete = iucv_callback_txdone, + .path_quiesced = iucv_callback_shutdown, }; static inline void high_nmcpy(unsigned char *dst, char *src) @@ -1196,6 +1198,21 @@ static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16]) sk->sk_state_change(sk); } +/* called if the other communication side shuts down its RECV direction; + * in turn, the callback sets SEND_SHUTDOWN to disable sending of data. + */ +static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16]) +{ + struct sock *sk = path->private; + + bh_lock_sock(sk); + if (sk->sk_state != IUCV_CLOSED) { + sk->sk_shutdown |= SEND_SHUTDOWN; + sk->sk_state_change(sk); + } + bh_unlock_sock(sk); +} + static struct proto_ops iucv_sock_ops = { .family = PF_IUCV, .owner = THIS_MODULE, -- cgit v1.2.3 From 9d5c5d8f4105dc56ec10864b195dd1714f282c22 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:22 +0000 Subject: af_iucv: add sockopt() to enable/disable use of IPRM_DATA msgs Provide the socket operations getsocktopt() and setsockopt() to enable/disable sending of data in the parameter list of IUCV messages. The patch sets respective flag only. Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- include/linux/socket.h | 1 + include/net/iucv/af_iucv.h | 4 +++ net/iucv/af_iucv.c | 79 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/include/linux/socket.h b/include/linux/socket.h index 42a0396f2c59..d2310cb45d2f 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -303,6 +303,7 @@ struct ucred { #define SOL_BLUETOOTH 274 #define SOL_PNPIPE 275 #define SOL_RDS 276 +#define SOL_IUCV 277 /* IPX options */ #define IPX_TYPE 1 diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index 85f80eadfa35..78a72764aeff 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -73,8 +73,12 @@ struct iucv_sock { struct sk_buff_head backlog_skb_q; struct sock_msg_q message_q; unsigned int send_tag; + u8 flags; }; +/* iucv socket options (SOL_IUCV) */ +#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */ + struct iucv_sock_list { struct hlist_head head; rwlock_t lock; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 6cf02b41ef95..b7c40c979921 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -32,7 +32,7 @@ #define CONFIG_IUCV_SOCK_DEBUG 1 #define IPRMDATA 0x80 -#define VERSION "1.0" +#define VERSION "1.1" static char iucv_userid[80]; @@ -226,6 +226,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) spin_lock_init(&iucv_sk(sk)->message_q.lock); skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); iucv_sk(sk)->send_tag = 0; + iucv_sk(sk)->flags = 0; sk->sk_destruct = iucv_sock_destruct; sk->sk_sndtimeo = IUCV_CONN_TIMEOUT; @@ -1003,6 +1004,78 @@ static int iucv_sock_release(struct socket *sock) return err; } +/* getsockopt and setsockopt */ +static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, + char __user *optval, int optlen) +{ + struct sock *sk = sock->sk; + struct iucv_sock *iucv = iucv_sk(sk); + int val; + int rc; + + if (level != SOL_IUCV) + return -ENOPROTOOPT; + + if (optlen < sizeof(int)) + return -EINVAL; + + if (get_user(val, (int __user *) optval)) + return -EFAULT; + + rc = 0; + + lock_sock(sk); + switch (optname) { + case SO_IPRMDATA_MSG: + if (val) + iucv->flags |= IUCV_IPRMDATA; + else + iucv->flags &= ~IUCV_IPRMDATA; + break; + default: + rc = -ENOPROTOOPT; + break; + } + release_sock(sk); + + return rc; +} + +static int iucv_sock_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) +{ + struct sock *sk = sock->sk; + struct iucv_sock *iucv = iucv_sk(sk); + int val, len; + + if (level != SOL_IUCV) + return -ENOPROTOOPT; + + if (get_user(len, optlen)) + return -EFAULT; + + if (len < 0) + return -EINVAL; + + len = min_t(unsigned int, len, sizeof(int)); + + switch (optname) { + case SO_IPRMDATA_MSG: + val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0; + break; + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + + return 0; +} + + /* Callback wrappers - called from iucv base support */ static int iucv_callback_connreq(struct iucv_path *path, u8 ipvmid[8], u8 ipuser[16]) @@ -1229,8 +1302,8 @@ static struct proto_ops iucv_sock_ops = { .mmap = sock_no_mmap, .socketpair = sock_no_socketpair, .shutdown = iucv_sock_shutdown, - .setsockopt = sock_no_setsockopt, - .getsockopt = sock_no_getsockopt + .setsockopt = iucv_sock_setsockopt, + .getsockopt = iucv_sock_getsockopt, }; static struct net_proto_family iucv_sock_family_ops = { -- cgit v1.2.3 From b8942e3b6c4b35dda5e8ca75aec5e2f027fe39a9 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:23 +0000 Subject: af_iucv: Support data in IUCV msg parameter lists (IPRMDATA) The patch allows to send and receive data in the parameter list of an iucv message. The parameter list is an arry of 8 bytes that are used by af_iucv as follows: 0..6 7 bytes for socket data and 7 1 byte to store the data length. Instead of storing the data length directly, the difference between 0xFF and the data length is used. This convention does not interfere with the existing use of PRM messages for shutting down the send direction of an AF_IUCV socket (shutdown() operation). Data lenghts greater than 7 (or PRM message byte 8 is less than 0xF8) denotes to special messages. Currently, the special SEND_SHUTDOWN message is supported only. To use IPRM messages, both communicators must set the IUCV_IPRMDATA flag during path negotiation, i.e. in iucv_connect() and path_pending(). To be compatible to older af_iucv implementations, sending PRM messages is controlled by the socket option SO_IPRMDATA_MSG. Receiving PRM messages does not depend on the socket option (but requires the IUCV_IPRMDATA path flag to be set). Sending/Receiving data in the parameter list improves performance for small amounts of data by reducing message_completion() interrupts and memory copy operations. Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 121 ++++++++++++++++++++++++++++++++++++++++++++--------- net/iucv/iucv.c | 2 + 2 files changed, 103 insertions(+), 20 deletions(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index b7c40c979921..5fc077ee5831 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -29,9 +29,6 @@ #include #include -#define CONFIG_IUCV_SOCK_DEBUG 1 - -#define IPRMDATA 0x80 #define VERSION "1.1" static char iucv_userid[80]; @@ -44,6 +41,10 @@ static struct proto iucv_proto = { .obj_size = sizeof(struct iucv_sock), }; +/* special AF_IUCV IPRM messages */ +static const u8 iprm_shutdown[8] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + static void iucv_sock_kill(struct sock *sk); static void iucv_sock_close(struct sock *sk); @@ -80,6 +81,37 @@ static inline void low_nmcpy(unsigned char *dst, char *src) memcpy(&dst[8], src, 8); } +/** + * iucv_msg_length() - Returns the length of an iucv message. + * @msg: Pointer to struct iucv_message, MUST NOT be NULL + * + * The function returns the length of the specified iucv message @msg of data + * stored in a buffer and of data stored in the parameter list (PRMDATA). + * + * For IUCV_IPRMDATA, AF_IUCV uses the following convention to transport socket + * data: + * PRMDATA[0..6] socket data (max 7 bytes); + * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) + * + * The socket data length is computed by substracting the socket data length + * value from 0xFF. + * If the socket data len is greater 7, then PRMDATA can be used for special + * notifications (see iucv_sock_shutdown); and further, + * if the socket data len is > 7, the function returns 8. + * + * Use this function to allocate socket buffers to store iucv message data. + */ +static inline size_t iucv_msg_length(struct iucv_message *msg) +{ + size_t datalen; + + if (msg->flags & IUCV_IPRMDATA) { + datalen = 0xff - msg->rmmsg[7]; + return (datalen < 8) ? datalen : 8; + } + return msg->length; +} + /* Timers */ static void iucv_sock_timeout(unsigned long arg) { @@ -487,7 +519,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, iucv = iucv_sk(sk); /* Create path. */ iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT, - IPRMDATA, GFP_KERNEL); + IUCV_IPRMDATA, GFP_KERNEL); if (!iucv->path) { err = -ENOMEM; goto done; @@ -521,8 +553,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, } if (sk->sk_state == IUCV_DISCONN) { - release_sock(sk); - return -ECONNREFUSED; + err = -ECONNREFUSED; } if (err) { @@ -636,6 +667,30 @@ static int iucv_sock_getname(struct socket *sock, struct sockaddr *addr, return 0; } +/** + * iucv_send_iprm() - Send socket data in parameter list of an iucv message. + * @path: IUCV path + * @msg: Pointer to a struct iucv_message + * @skb: The socket data to send, skb->len MUST BE <= 7 + * + * Send the socket data in the parameter list in the iucv message + * (IUCV_IPRMDATA). The socket data is stored at index 0 to 6 in the parameter + * list and the socket data len at index 7 (last byte). + * See also iucv_msg_length(). + * + * Returns the error code from the iucv_message_send() call. + */ +static int iucv_send_iprm(struct iucv_path *path, struct iucv_message *msg, + struct sk_buff *skb) +{ + u8 prmdata[8]; + + memcpy(prmdata, (void *) skb->data, skb->len); + prmdata[7] = 0xff - (u8) skb->len; + return iucv_message_send(path, msg, IUCV_IPRMDATA, 0, + (void *) prmdata, 8); +} + static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { @@ -677,8 +732,29 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, txmsg.tag = iucv->send_tag++; memcpy(skb->cb, &txmsg.tag, 4); skb_queue_tail(&iucv->send_skb_q, skb); - err = iucv_message_send(iucv->path, &txmsg, 0, 0, - (void *) skb->data, skb->len); + + if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) + && skb->len <= 7) { + err = iucv_send_iprm(iucv->path, &txmsg, skb); + + /* on success: there is no message_complete callback + * for an IPRMDATA msg; remove skb from send queue */ + if (err == 0) { + skb_unlink(skb, &iucv->send_skb_q); + kfree_skb(skb); + } + + /* this error should never happen since the + * IUCV_IPRMDATA path flag is set... sever path */ + if (err == 0x15) { + iucv_path_sever(iucv->path, NULL); + skb_unlink(skb, &iucv->send_skb_q); + err = -EPIPE; + goto fail; + } + } else + err = iucv_message_send(iucv->path, &txmsg, 0, 0, + (void *) skb->data, skb->len); if (err) { if (err == 3) { user_id[8] = 0; @@ -744,19 +820,25 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, struct iucv_message *msg) { int rc; + unsigned int len; + + len = iucv_msg_length(msg); - if (msg->flags & IPRMDATA) { - skb->data = NULL; - skb->len = 0; + /* check for special IPRM messages (e.g. iucv_sock_shutdown) */ + if ((msg->flags & IUCV_IPRMDATA) && len > 7) { + if (memcmp(msg->rmmsg, iprm_shutdown, 8) == 0) { + skb->data = NULL; + skb->len = 0; + } } else { - rc = iucv_message_receive(path, msg, 0, skb->data, - msg->length, NULL); + rc = iucv_message_receive(path, msg, msg->flags & IUCV_IPRMDATA, + skb->data, len, NULL); if (rc) { kfree_skb(skb); return; } if (skb->truesize >= sk->sk_rcvbuf / 4) { - rc = iucv_fragment_skb(sk, skb, msg->length); + rc = iucv_fragment_skb(sk, skb, len); kfree_skb(skb); skb = NULL; if (rc) { @@ -767,7 +849,7 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, } else { skb_reset_transport_header(skb); skb_reset_network_header(skb); - skb->len = msg->length; + skb->len = len; } } @@ -782,7 +864,7 @@ static void iucv_process_message_q(struct sock *sk) struct sock_msg_q *p, *n; list_for_each_entry_safe(p, n, &iucv->message_q.list, list) { - skb = alloc_skb(p->msg.length, GFP_ATOMIC | GFP_DMA); + skb = alloc_skb(iucv_msg_length(&p->msg), GFP_ATOMIC | GFP_DMA); if (!skb) break; iucv_process_message(sk, skb, p->path, &p->msg); @@ -928,7 +1010,6 @@ static int iucv_sock_shutdown(struct socket *sock, int how) struct iucv_sock *iucv = iucv_sk(sk); struct iucv_message txmsg; int err = 0; - u8 prmmsg[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; how++; @@ -950,7 +1031,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how) txmsg.class = 0; txmsg.tag = 0; err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0, - (void *) prmmsg, 8); + (void *) iprm_shutdown, 8); if (err) { switch (err) { case 1: @@ -1196,11 +1277,11 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) goto save_message; len = atomic_read(&sk->sk_rmem_alloc); - len += msg->length + sizeof(struct sk_buff); + len += iucv_msg_length(msg) + sizeof(struct sk_buff); if (len > sk->sk_rcvbuf) goto save_message; - skb = alloc_skb(msg->length, GFP_ATOMIC | GFP_DMA); + skb = alloc_skb(iucv_msg_length(msg), GFP_ATOMIC | GFP_DMA); if (!skb) goto save_message; diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index fcf404065f12..61e8038a55ee 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -1388,6 +1388,8 @@ static void iucv_path_complete(struct iucv_irq_data *data) struct iucv_path_complete *ipc = (void *) data; struct iucv_path *path = iucv_path_table[ipc->ippathid]; + if (path) + path->flags = ipc->ipflags1; if (path && path->handler && path->handler->path_complete) path->handler->path_complete(path, ipc->ipuser); } -- cgit v1.2.3 From 44b1e6b5f9a93cc2ba024e09cf137d5f1b5f8426 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:24 +0000 Subject: af_iucv: Modify iucv msg target class using control msghdr Allow 'classification' of socket data that is sent or received over an af_iucv socket. For classification of data, the target class of an (native) iucv message is used. This patch provides the cmsg interface for iucv_sock_recvmsg() and iucv_sock_sendmsg(). Applications can use the msg_control field of struct msghdr to set or get the target class as a "socket control message" (SCM/CMSG). Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- include/net/iucv/af_iucv.h | 3 ++ net/iucv/af_iucv.c | 79 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index 78a72764aeff..b57739e49dc1 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -79,6 +79,9 @@ struct iucv_sock { /* iucv socket options (SOL_IUCV) */ #define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */ +/* iucv related control messages (scm) */ +#define SCM_IUCV_TRGCLS 0x0001 /* target class control message */ + struct iucv_sock_list { struct hlist_head head; rwlock_t lock; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 5fc077ee5831..47c5c8d3703f 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -45,6 +45,15 @@ static struct proto iucv_proto = { static const u8 iprm_shutdown[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; +#define TRGCLS_SIZE (sizeof(((struct iucv_message *)0)->class)) + +/* macros to set/get socket control buffer at correct offset */ +#define CB_TAG(skb) ((skb)->cb) /* iucv message tag */ +#define CB_TAG_LEN (sizeof(((struct iucv_message *) 0)->tag)) +#define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */ +#define CB_TRGCLS_LEN (TRGCLS_SIZE) + + static void iucv_sock_kill(struct sock *sk); static void iucv_sock_close(struct sock *sk); @@ -698,6 +707,8 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct iucv_sock *iucv = iucv_sk(sk); struct sk_buff *skb; struct iucv_message txmsg; + struct cmsghdr *cmsg; + int cmsg_done; char user_id[9]; char appl_id[9]; int err; @@ -717,6 +728,48 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, } if (sk->sk_state == IUCV_CONNECTED) { + /* initialize defaults */ + cmsg_done = 0; /* check for duplicate headers */ + txmsg.class = 0; + + /* iterate over control messages */ + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + + if (!CMSG_OK(msg, cmsg)) { + err = -EINVAL; + goto out; + } + + if (cmsg->cmsg_level != SOL_IUCV) + continue; + + if (cmsg->cmsg_type & cmsg_done) { + err = -EINVAL; + goto out; + } + cmsg_done |= cmsg->cmsg_type; + + switch (cmsg->cmsg_type) { + case SCM_IUCV_TRGCLS: + if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { + err = -EINVAL; + goto out; + } + + /* set iucv message target class */ + memcpy(&txmsg.class, + (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); + + break; + + default: + err = -EINVAL; + goto out; + break; + } + } + if (!(skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) @@ -727,10 +780,9 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, goto fail; } - txmsg.class = 0; - memcpy(&txmsg.class, skb->data, skb->len >= 4 ? 4 : skb->len); + /* increment and save iucv message tag for msg_completion cbk */ txmsg.tag = iucv->send_tag++; - memcpy(skb->cb, &txmsg.tag, 4); + memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); skb_queue_tail(&iucv->send_skb_q, skb); if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) @@ -801,6 +853,10 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len) if (!nskb) return -ENOMEM; + /* copy target class to control buffer of new skb */ + memcpy(CB_TRGCLS(nskb), CB_TRGCLS(skb), CB_TRGCLS_LEN); + + /* copy data fragment */ memcpy(nskb->data, skb->data + copied, size); copied += size; dataleft -= size; @@ -824,6 +880,10 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, len = iucv_msg_length(msg); + /* store msg target class in the second 4 bytes of skb ctrl buffer */ + /* Note: the first 4 bytes are reserved for msg tag */ + memcpy(CB_TRGCLS(skb), &msg->class, CB_TRGCLS_LEN); + /* check for special IPRM messages (e.g. iucv_sock_shutdown) */ if ((msg->flags & IUCV_IPRMDATA) && len > 7) { if (memcmp(msg->rmmsg, iprm_shutdown, 8) == 0) { @@ -915,6 +975,17 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, len -= copied; + /* create control message to store iucv msg target class: + * get the trgcls from the control buffer of the skb due to + * fragmentation of original iucv message. */ + err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS, + CB_TRGCLS_LEN, CB_TRGCLS(skb)); + if (err) { + if (!(flags & MSG_PEEK)) + skb_queue_head(&sk->sk_receive_queue, skb); + return err; + } + /* Mark read part of skb as used */ if (!(flags & MSG_PEEK)) { skb_pull(skb, copied); @@ -1316,7 +1387,7 @@ static void iucv_callback_txdone(struct iucv_path *path, spin_lock_irqsave(&list->lock, flags); while (list_skb != (struct sk_buff *)list) { - if (!memcmp(&msg->tag, list_skb->cb, 4)) { + if (!memcmp(&msg->tag, CB_TAG(list_skb), CB_TAG_LEN)) { this = list_skb; break; } -- cgit v1.2.3 From aa8e71f58ab8e01d63c33df40ff1bcb997c9df92 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:25 +0000 Subject: af_iucv: Provide new socket type SOCK_SEQPACKET This patch provides the socket type SOCK_SEQPACKET in addition to SOCK_STREAM. AF_IUCV sockets of type SOCK_SEQPACKET supports an 1:1 mapping of socket read or write operations to complete IUCV messages. Socket data or IUCV message data is not fragmented as this is the case for SOCK_STREAM sockets. The intention is to help application developers who write applications or device drivers using native IUCV interfaces (Linux kernel or z/VM IUCV interfaces). Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 73 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 47c5c8d3703f..95e38d3d2d74 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -289,11 +289,22 @@ static int iucv_sock_create(struct net *net, struct socket *sock, int protocol) { struct sock *sk; - if (sock->type != SOCK_STREAM) - return -ESOCKTNOSUPPORT; + if (protocol && protocol != PF_IUCV) + return -EPROTONOSUPPORT; sock->state = SS_UNCONNECTED; - sock->ops = &iucv_sock_ops; + + switch (sock->type) { + case SOCK_STREAM: + sock->ops = &iucv_sock_ops; + break; + case SOCK_SEQPACKET: + /* currently, proto ops can handle both sk types */ + sock->ops = &iucv_sock_ops; + break; + default: + return -ESOCKTNOSUPPORT; + } sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL); if (!sk) @@ -504,11 +515,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, if (sk->sk_state != IUCV_OPEN && sk->sk_state != IUCV_BOUND) return -EBADFD; - if (sk->sk_type != SOCK_STREAM) + if (sk->sk_type != SOCK_STREAM && sk->sk_type != SOCK_SEQPACKET) return -EINVAL; - iucv = iucv_sk(sk); - if (sk->sk_state == IUCV_OPEN) { err = iucv_sock_autobind(sk); if (unlikely(err)) @@ -585,7 +594,10 @@ static int iucv_sock_listen(struct socket *sock, int backlog) lock_sock(sk); err = -EINVAL; - if (sk->sk_state != IUCV_BOUND || sock->type != SOCK_STREAM) + if (sk->sk_state != IUCV_BOUND) + goto done; + + if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) goto done; sk->sk_max_ack_backlog = backlog; @@ -720,6 +732,10 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; + /* SOCK_SEQPACKET: we do not support segmented records */ + if (sk->sk_type == SOCK_SEQPACKET && !(msg->msg_flags & MSG_EOR)) + return -EOPNOTSUPP; + lock_sock(sk); if (sk->sk_shutdown & SEND_SHUTDOWN) { @@ -770,6 +786,10 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, } } + /* allocate one skb for each iucv message: + * this is fine for SOCK_SEQPACKET (unless we want to support + * segmented records using the MSG_EOR flag), but + * for SOCK_STREAM we might want to improve it in future */ if (!(skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) @@ -897,7 +917,11 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, kfree_skb(skb); return; } - if (skb->truesize >= sk->sk_rcvbuf / 4) { + /* we need to fragment iucv messages for SOCK_STREAM only; + * for SOCK_SEQPACKET, it is only relevant if we support + * record segmentation using MSG_EOR (see also recvmsg()) */ + if (sk->sk_type == SOCK_STREAM && + skb->truesize >= sk->sk_rcvbuf / 4) { rc = iucv_fragment_skb(sk, skb, len); kfree_skb(skb); skb = NULL; @@ -941,7 +965,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; struct iucv_sock *iucv = iucv_sk(sk); - int target, copied = 0; + int target; + unsigned int copied, rlen; struct sk_buff *skb, *rskb, *cskb; int err = 0; @@ -963,7 +988,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, return err; } - copied = min_t(unsigned int, skb->len, len); + rlen = skb->len; /* real length of skb */ + copied = min_t(unsigned int, rlen, len); cskb = skb; if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { @@ -973,7 +999,13 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, goto done; } - len -= copied; + /* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */ + if (sk->sk_type == SOCK_SEQPACKET) { + if (copied < rlen) + msg->msg_flags |= MSG_TRUNC; + /* each iucv message contains a complete record */ + msg->msg_flags |= MSG_EOR; + } /* create control message to store iucv msg target class: * get the trgcls from the control buffer of the skb due to @@ -988,11 +1020,14 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, /* Mark read part of skb as used */ if (!(flags & MSG_PEEK)) { - skb_pull(skb, copied); - if (skb->len) { - skb_queue_head(&sk->sk_receive_queue, skb); - goto done; + /* SOCK_STREAM: re-queue skb if it contains unreceived data */ + if (sk->sk_type == SOCK_STREAM) { + skb_pull(skb, copied); + if (skb->len) { + skb_queue_head(&sk->sk_receive_queue, skb); + goto done; + } } kfree_skb(skb); @@ -1019,7 +1054,11 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, skb_queue_head(&sk->sk_receive_queue, skb); done: - return err ? : copied; + /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */ + if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC)) + copied = rlen; + + return copied; } static inline unsigned int iucv_accept_poll(struct sock *parent) @@ -1281,7 +1320,7 @@ static int iucv_callback_connreq(struct iucv_path *path, } /* Create the new socket */ - nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC); + nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC); if (!nsk) { err = iucv_path_sever(path, user_data); iucv_path_free(path); -- cgit v1.2.3 From 802788bf90f78e7f248e78d4d0510bb00e976db8 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:26 +0000 Subject: af_iucv: cleanup and refactor recvmsg() EFAULT handling If the skb cannot be copied to user iovec, always return -EFAULT. The skb is enqueued again, except MSG_PEEK flag is set, to allow user space applications to correct its iovec pointer. Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 95e38d3d2d74..f0dea1b8ed4b 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -965,7 +965,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; struct iucv_sock *iucv = iucv_sk(sk); - int target; unsigned int copied, rlen; struct sk_buff *skb, *rskb, *cskb; int err = 0; @@ -979,8 +978,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); - skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -993,10 +990,9 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, cskb = skb; if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { - skb_queue_head(&sk->sk_receive_queue, skb); - if (copied == 0) - return -EFAULT; - goto done; + if (!(flags & MSG_PEEK)) + skb_queue_head(&sk->sk_receive_queue, skb); + return -EFAULT; } /* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */ -- cgit v1.2.3 From 09488e2e0fab14ebe41135f0d066cfe2c56ba9e5 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 21 Apr 2009 23:26:27 +0000 Subject: af_iucv: New socket option for setting IUCV MSGLIMITs The SO_MSGLIMIT socket option modifies the message limit for new IUCV communication paths. The message limit specifies the maximum number of outstanding messages that are allowed for connections. This setting can be lowered by z/VM when an IUCV connection is established. Expects an integer value in the range of 1 to 65535. The default value is 65535. The message limit must be set before calling connect() or listen() for sockets. If sockets are already connected or in state listen, changing the message limit is not supported. For reading the message limit value, unconnected sockets return the limit that has been set or the default limit. For connected sockets, the actual message limit is returned. The actual message limit is assigned by z/VM for each connection and it depends on IUCV MSGLIMIT authorizations specified for the z/VM guest virtual machine. Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- include/net/iucv/af_iucv.h | 2 ++ net/iucv/af_iucv.c | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index b57739e49dc1..21ee49ffcbaf 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -74,10 +74,12 @@ struct iucv_sock { struct sock_msg_q message_q; unsigned int send_tag; u8 flags; + u16 msglimit; }; /* iucv socket options (SOL_IUCV) */ #define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */ +#define SO_MSGLIMIT 0x1000 /* get/set IUCV MSGLIMIT */ /* iucv related control messages (scm) */ #define SCM_IUCV_TRGCLS 0x0001 /* target class control message */ diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index f0dea1b8ed4b..264c6b36931c 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -268,6 +268,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); iucv_sk(sk)->send_tag = 0; iucv_sk(sk)->flags = 0; + iucv_sk(sk)->msglimit = IUCV_QUEUELEN_DEFAULT; sk->sk_destruct = iucv_sock_destruct; sk->sk_sndtimeo = IUCV_CONN_TIMEOUT; @@ -536,7 +537,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, iucv = iucv_sk(sk); /* Create path. */ - iucv->path = iucv_path_alloc(IUCV_QUEUELEN_DEFAULT, + iucv->path = iucv_path_alloc(iucv->msglimit, IUCV_IPRMDATA, GFP_KERNEL); if (!iucv->path) { err = -ENOMEM; @@ -1219,6 +1220,20 @@ static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, else iucv->flags &= ~IUCV_IPRMDATA; break; + case SO_MSGLIMIT: + switch (sk->sk_state) { + case IUCV_OPEN: + case IUCV_BOUND: + if (val < 1 || val > (u16)(~0)) + rc = -EINVAL; + else + iucv->msglimit = val; + break; + default: + rc = -EINVAL; + break; + } + break; default: rc = -ENOPROTOOPT; break; @@ -1250,6 +1265,12 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname, case SO_IPRMDATA_MSG: val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0; break; + case SO_MSGLIMIT: + lock_sock(sk); + val = (iucv->path != NULL) ? iucv->path->msglim /* connected */ + : iucv->msglimit; /* default */ + release_sock(sk); + break; default: return -ENOPROTOOPT; } @@ -1339,7 +1360,9 @@ static int iucv_callback_connreq(struct iucv_path *path, memcpy(nuser_data + 8, niucv->src_name, 8); ASCEBC(nuser_data + 8, 8); - path->msglim = IUCV_QUEUELEN_DEFAULT; + /* set message limit for path based on msglimit of accepting socket */ + niucv->msglimit = iucv->msglimit; + path->msglim = iucv->msglimit; err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk); if (err) { err = iucv_path_sever(path, user_data); -- cgit v1.2.3 From d93fe1a144c1a4312972bedbefc2213aa8b88612 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Thu, 23 Apr 2009 06:37:16 -0700 Subject: af_iucv: Fix merge. From: Ursula Braun net/iucv/af_iucv.c in net-next-2.6 is almost correct. 4 lines should still be deleted. These are the remaining changes: Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 0fc00087ea8b..a9b3a6f9ea95 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -982,8 +982,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); - /* receive/dequeue next skb: * the function understands MSG_PEEK and, thus, does not dequeue skb */ skb = skb_recv_datagram(sk, flags, noblock, &err); @@ -1429,8 +1427,6 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) iucv_process_message(sk, skb, path, msg); goto out_unlock; - return; - save_message: save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA); if (!save_msg) -- cgit v1.2.3 From ad8affd972a705a38e769859c50ee8e749b631da Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Fri, 24 Apr 2009 04:45:33 -0700 Subject: 8390p: fix build breakage Fix this build error caused by 362b76edb789 "8390p: Get rid of init_module/cleanup_module" drivers/net/8390p.c:94:19: error: invalid suffix "p_init_module" on integer constant drivers/net/8390p.c:94: error: expected identifier or '(' before numeric constant drivers/net/8390p.c:99:20: error: invalid suffix "p_cleanup_module" on integer constant Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/8390p.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c index cacdd86a27d0..d225c291fd93 100644 --- a/drivers/net/8390p.c +++ b/drivers/net/8390p.c @@ -91,15 +91,15 @@ void NS8390p_init(struct net_device *dev, int startp) } EXPORT_SYMBOL(NS8390p_init); -static int __init 8390p_init_module(void) +static int __init NS8390p_init_module(void) { return 0; } -static void __exit 8390p_cleanup_module(void) +static void __exit NS8390p_cleanup_module(void) { } -module_init(8390p_init_module); -module_exit(8390p_cleanup_module); +module_init(NS8390p_init_module); +module_exit(NS8390p_cleanup_module); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 9b171ffe1b3004587f4a90ef293531a4a262e538 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 24 Apr 2009 15:30:28 -0400 Subject: libertas: fix format warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/libertas/if_spi.c: In function ‘if_spi_c2h_data’: drivers/net/wireless/libertas/if_spi.c:733: warning: format ‘%u’ expects type ‘unsigned int’, but argument 4 has type ‘long unsigned int’ Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 97493e2f4109..dccd01fd1f10 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -731,7 +731,7 @@ static int if_spi_c2h_data(struct if_spi_card *card) goto out; } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_pr_err("%s: error: card has %d bytes of data, but " - "our maximum skb size is %u\n", + "our maximum skb size is %lu\n", __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); err = -EINVAL; goto out; -- cgit v1.2.3 From d3feaf5ad12259927039a675cfb25dc342b403ab Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 24 Apr 2009 15:35:42 -0400 Subject: wireless: remove some (bogus?) 'may be used uninitialized' warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/mac80211/tx.c: In function ‘ieee80211_tx_h_select_key’: net/mac80211/tx.c:448: warning: ‘key’ may be used uninitialized in this function drivers/net/wireless/ath/ath9k/rc.c: In function ‘ath_rc_rate_getidx’: drivers/net/wireless/ath/ath9k/rc.c:815: warning: ‘nextindex’ may be used uninitialized in this function drivers/net/wireless/hostap/hostap_plx.c: In function ‘prism2_plx_probe’: drivers/net/wireless/hostap/hostap_plx.c:438: warning: ‘cor_index’ may be used uninitialized in this function drivers/net/wireless/hostap/hostap_plx.c:438: warning: ‘cor_offset’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 2 +- drivers/net/wireless/hostap/hostap_plx.c | 2 +- net/mac80211/tx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index a13668b9b6dc..8f3cf10f65c4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -812,7 +812,7 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc, u16 min_rate) { u32 j; - u8 nextindex; + u8 nextindex = 0; if (min_rate) { for (j = RATE_TABLE_SIZE; j > 0; j--) { diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index cbf15d703201..0e5d51086a44 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -435,7 +435,7 @@ static int prism2_plx_probe(struct pci_dev *pdev, unsigned long pccard_attr_mem; unsigned int pccard_attr_len; void __iomem *attr_mem = NULL; - unsigned int cor_offset, cor_index; + unsigned int cor_offset = 0, cor_index = 0; u32 reg; local_info_t *local = NULL; struct net_device *dev = NULL; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9ab49826c15a..1865622003c9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -445,7 +445,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) { - struct ieee80211_key *key; + struct ieee80211_key *key = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; -- cgit v1.2.3 From 92ae3efa53b481ad669d8b85c6cfa37d774bb21e Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 27 Apr 2009 02:35:32 -0700 Subject: ipv4: remove unused member in fib_table. This patch removes an unused parameter (tb_stamp) from fib_table structure in include/net/ip_fib.h. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- include/net/ip_fib.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 8b12667f7a2b..34855eede5fe 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -145,7 +145,6 @@ struct fib_result_nl { struct fib_table { struct hlist_node tb_hlist; u32 tb_id; - unsigned tb_stamp; int tb_default; int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res); int (*tb_insert)(struct fib_table *, struct fib_config *); -- cgit v1.2.3 From 06bd12c3b861f8ca9e1215428b19dc0026c6268f Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Mon, 27 Apr 2009 02:42:20 -0700 Subject: pcnet32: Remove redundant set of skb->dev Remove redundant set of skb->dev (now handled for ethernet drivers by eth_type_trans()). Signed-off-by: John Dykstra Signed-off-by: David S. Miller --- drivers/net/pcnet32.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 80124fac65fa..e5e8c59243b6 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1227,7 +1227,6 @@ static void pcnet32_rx_entry(struct net_device *dev, dev->stats.rx_dropped++; return; } - skb->dev = dev; if (!rx_in_place) { skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len); /* Make room */ -- cgit v1.2.3 From edf391ff17232f097d72441c9ad467bcb3b5db18 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 27 Apr 2009 02:45:02 -0700 Subject: snmp: add missing counters for RFC 4293 The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and OutMcastOctets: http://tools.ietf.org/html/rfc4293 But it seems we don't track those in any way that easy to separate from other protocols. This patch adds those missing counters to the stats file. Tested successfully by me With help from Eric Dumazet. Signed-off-by: Neil Horman Signed-off-by: David S. Miller --- include/linux/snmp.h | 10 ++++++++-- include/net/ip.h | 3 +++ include/net/ipv6.h | 15 ++++++++++++++- include/net/snmp.h | 19 ++++++++++++++++++- net/ipv4/ip_input.c | 13 ++++++++----- net/ipv4/ip_output.c | 12 ++++++------ net/ipv4/proc.c | 10 ++++++++-- net/ipv6/ip6_input.c | 7 ++++--- net/ipv6/ip6_output.c | 9 +++++---- net/ipv6/mcast.c | 19 ++++++++++++------- net/ipv6/ndisc.c | 4 ++-- net/ipv6/proc.c | 10 ++++++++-- net/ipv6/raw.c | 2 +- 13 files changed, 97 insertions(+), 36 deletions(-) diff --git a/include/linux/snmp.h b/include/linux/snmp.h index aee3f1e1d1ce..0f953fe40413 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -18,7 +18,7 @@ enum { IPSTATS_MIB_NUM = 0, - IPSTATS_MIB_INRECEIVES, /* InReceives */ + IPSTATS_MIB_INPKTS, /* InReceives */ IPSTATS_MIB_INHDRERRORS, /* InHdrErrors */ IPSTATS_MIB_INTOOBIGERRORS, /* InTooBigErrors */ IPSTATS_MIB_INNOROUTES, /* InNoRoutes */ @@ -28,7 +28,7 @@ enum IPSTATS_MIB_INDISCARDS, /* InDiscards */ IPSTATS_MIB_INDELIVERS, /* InDelivers */ IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */ - IPSTATS_MIB_OUTREQUESTS, /* OutRequests */ + IPSTATS_MIB_OUTPKTS, /* OutRequests */ IPSTATS_MIB_OUTDISCARDS, /* OutDiscards */ IPSTATS_MIB_OUTNOROUTES, /* OutNoRoutes */ IPSTATS_MIB_REASMTIMEOUT, /* ReasmTimeout */ @@ -42,6 +42,12 @@ enum IPSTATS_MIB_OUTMCASTPKTS, /* OutMcastPkts */ IPSTATS_MIB_INBCASTPKTS, /* InBcastPkts */ IPSTATS_MIB_OUTBCASTPKTS, /* OutBcastPkts */ + IPSTATS_MIB_INOCTETS, /* InOctets */ + IPSTATS_MIB_OUTOCTETS, /* OutOctets */ + IPSTATS_MIB_INMCASTOCTETS, /* InMcastOctets */ + IPSTATS_MIB_OUTMCASTOCTETS, /* OutMcastOctets */ + IPSTATS_MIB_INBCASTOCTETS, /* InBcastOctets */ + IPSTATS_MIB_OUTBCASTOCTETS, /* OutBcastOctets */ __IPSTATS_MIB_MAX }; diff --git a/include/net/ip.h b/include/net/ip.h index 4ac7577f98d0..72c36926c26d 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -168,7 +168,10 @@ struct ipv4_config extern struct ipv4_config ipv4_config; #define IP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.ip_statistics, field) #define IP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.ip_statistics, field) +#define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.ip_statistics, field, val) #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val) +#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS((net)->mib.ip_statistics, field, val) +#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS_BH((net)->mib.ip_statistics, field, val) #define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field) #define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field) #define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index c1f16fc49ade..f27fd83d67d8 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -126,15 +126,28 @@ extern struct ctl_path net_ipv6_ctl_path[]; SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\ }) +#define _DEVUPD(net, statname, modifier, idev, field, val) \ +({ \ + struct inet6_dev *_idev = (idev); \ + if (likely(_idev != NULL)) \ + SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \ + SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\ +}) + /* MIBs */ #define IP6_INC_STATS(net, idev,field) \ _DEVINC(net, ipv6, , idev, field) #define IP6_INC_STATS_BH(net, idev,field) \ _DEVINC(net, ipv6, _BH, idev, field) +#define IP6_ADD_STATS(net, idev,field,val) \ + _DEVADD(net, ipv6, , idev, field, val) #define IP6_ADD_STATS_BH(net, idev,field,val) \ _DEVADD(net, ipv6, _BH, idev, field, val) - +#define IP6_UPD_PO_STATS(net, idev,field,val) \ + _DEVUPD(net, ipv6, , idev, field, val) +#define IP6_UPD_PO_STATS_BH(net, idev,field,val) \ + _DEVUPD(net, ipv6, _BH, idev, field, val) #define ICMP6_INC_STATS(net, idev, field) \ _DEVINC(net, icmpv6, , idev, field) #define ICMP6_INC_STATS_BH(net, idev, field) \ diff --git a/include/net/snmp.h b/include/net/snmp.h index 57c93628695f..8c842e06bec8 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -153,6 +153,11 @@ struct linux_xfrm_mib { per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \ put_cpu(); \ } while (0) +#define SNMP_ADD_STATS(mib, field, addend) \ + do { \ + per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \ + put_cpu(); \ + } while (0) #define SNMP_ADD_STATS_BH(mib, field, addend) \ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend) #define SNMP_ADD_STATS_USER(mib, field, addend) \ @@ -160,5 +165,17 @@ struct linux_xfrm_mib { per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \ put_cpu(); \ } while (0) - +#define SNMP_UPD_PO_STATS(mib, basefield, addend) \ + do { \ + __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\ + ptr->mibs[basefield##PKTS]++; \ + ptr->mibs[basefield##OCTETS] += addend;\ + put_cpu(); \ + } while (0) +#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ + do { \ + __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\ + ptr->mibs[basefield##PKTS]++; \ + ptr->mibs[basefield##OCTETS] += addend;\ + } while (0) #endif diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 1a58a6fa1dc0..40f6206b2aa9 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -358,10 +358,12 @@ static int ip_rcv_finish(struct sk_buff *skb) goto drop; rt = skb->rtable; - if (rt->rt_type == RTN_MULTICAST) - IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS); - else if (rt->rt_type == RTN_BROADCAST) - IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS); + if (rt->rt_type == RTN_MULTICAST) { + IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST, + skb->len); + } else if (rt->rt_type == RTN_BROADCAST) + IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST, + skb->len); return dst_input(skb); @@ -384,7 +386,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, if (skb->pkt_type == PACKET_OTHERHOST) goto drop; - IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES); + + IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3e7e910c7c0f..ea19c37ccc0c 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -181,10 +181,10 @@ static inline int ip_finish_output2(struct sk_buff *skb) struct net_device *dev = dst->dev; unsigned int hh_len = LL_RESERVED_SPACE(dev); - if (rt->rt_type == RTN_MULTICAST) - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS); - else if (rt->rt_type == RTN_BROADCAST) - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS); + if (rt->rt_type == RTN_MULTICAST) { + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len); + } else if (rt->rt_type == RTN_BROADCAST) + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len); /* Be paranoid, rather than too clever. */ if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { @@ -244,7 +244,7 @@ int ip_mc_output(struct sk_buff *skb) /* * If the indicated interface is up and running, send the packet. */ - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS); + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); skb->dev = dev; skb->protocol = htons(ETH_P_IP); @@ -298,7 +298,7 @@ int ip_output(struct sk_buff *skb) { struct net_device *dev = skb->dst->dev; - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS); + IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); skb->dev = dev; skb->protocol = htons(ETH_P_IP); diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index cf0cdeeb1db0..f25542c48b7d 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -90,14 +90,14 @@ static const struct file_operations sockstat_seq_fops = { /* snmp items */ static const struct snmp_mib snmp4_ipstats_list[] = { - SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES), + SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INPKTS), SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS), SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS), SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS), SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS), SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS), SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS), - SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS), + SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS), SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS), SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES), SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT), @@ -118,6 +118,12 @@ static const struct snmp_mib snmp4_ipextstats_list[] = { SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS), SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS), SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS), + SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS), + SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS), + SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS), + SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), + SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), + SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), SNMP_MIB_SENTINEL }; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 8f04bd9da274..bc1a920c34a1 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -70,7 +70,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt idev = __in6_dev_get(skb->dev); - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES); + IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || !idev || unlikely(idev->cnf.disable_ipv6)) { @@ -242,8 +242,9 @@ int ip6_mc_input(struct sk_buff *skb) struct ipv6hdr *hdr; int deliver; - IP6_INC_STATS_BH(dev_net(skb->dst->dev), - ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); + IP6_UPD_PO_STATS_BH(dev_net(skb->dst->dev), + ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCAST, + skb->len); hdr = ipv6_hdr(skb); deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9fb49c3b518a..735a2bf4b5f1 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb) } } - IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS); + IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST, + skb->len); } return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, @@ -275,8 +276,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, mtu = dst_mtu(dst); if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { - IP6_INC_STATS(net, ip6_dst_idev(skb->dst), - IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, ip6_dst_idev(skb->dst), + IPSTATS_MIB_OUT, skb->len); return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, dst_output); } @@ -1516,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk) skb->mark = sk->sk_mark; skb->dst = dst_clone(&rt->u.dst); - IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); if (proto == IPPROTO_ICMPV6) { struct inet6_dev *idev = ip6_dst_idev(skb->dst); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index a51fb33e6864..4b48819a5b8d 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1449,7 +1449,8 @@ static void mld_sendpack(struct sk_buff *skb) int err; struct flowi fl; - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); + payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); mldlen = skb->tail - skb->transport_header; pip6->payload_len = htons(payload_len); @@ -1473,13 +1474,15 @@ static void mld_sendpack(struct sk_buff *skb) if (err) goto err_out; + payload_len = skb->len; + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT); ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS); + IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); } else IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); @@ -1773,10 +1776,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) IPV6_TLV_PADN, 0 }; struct flowi fl; - rcu_read_lock(); - IP6_INC_STATS(net, __in6_dev_get(dev), - IPSTATS_MIB_OUTREQUESTS); - rcu_read_unlock(); if (type == ICMPV6_MGM_REDUCTION) snd_addr = &in6addr_linklocal_allrouters; else @@ -1786,6 +1785,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) payload_len = len + sizeof(ra); full_len = sizeof(struct ipv6hdr) + payload_len; + rcu_read_lock(); + IP6_UPD_PO_STATS(net, __in6_dev_get(dev), + IPSTATS_MIB_OUT, full_len); + rcu_read_unlock(); + skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err); if (skb == NULL) { @@ -1838,13 +1842,14 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) if (err) goto err_out; + err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, dst_output); out: if (!err) { ICMP6MSGOUT_INC_STATS(net, idev, type); ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len); } else IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 9f061d1adbc2..ab65cc51b00e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -533,7 +533,7 @@ void ndisc_send_skb(struct sk_buff *skb, skb->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, dst_output); @@ -1613,7 +1613,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, buff->dst = dst; idev = in6_dev_get(dst->dev); - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, dst_output); if (!err) { diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 97c17fdd6f75..590ddefb7ffc 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -61,7 +61,7 @@ static const struct file_operations sockstat6_seq_fops = { static struct snmp_mib snmp6_ipstats_list[] = { /* ipv6 mib according to RFC 2465 */ - SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES), + SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS), SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS), SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS), SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES), @@ -71,7 +71,7 @@ static struct snmp_mib snmp6_ipstats_list[] = { SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS), SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS), SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS), - SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS), + SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS), SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS), SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES), SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT), @@ -83,6 +83,12 @@ static struct snmp_mib snmp6_ipstats_list[] = { SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES), SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS), SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS), + SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS), + SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS), + SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS), + SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS), + SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS), + SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS), SNMP_MIB_SENTINEL }; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 61f6827e5906..e99307fba0b1 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, if (err) goto error_fault; - IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); + IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) -- cgit v1.2.3 From 739649c53d7f78f5bf41bdfd1a858ee90c7a687a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:52:40 +0000 Subject: of: add of_parse_phandle() helper for parsing phandle properties of_parse_phandle() is a helper function to read and parse a phandle property and return a pointer to the resulting device_node. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/of/base.c | 24 ++++++++++++++++++++++++ include/linux/of.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 41c5dfd85358..ddf224d456b2 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -494,6 +494,30 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) } EXPORT_SYMBOL_GPL(of_modalias_node); +/** + * of_parse_phandle - Resolve a phandle property to a device_node pointer + * @np: Pointer to device node holding phandle property + * @phandle_name: Name of property holding a phandle value + * @index: For properties holding a table of phandles, this is the index into + * the table + * + * Returns the device_node pointer with refcount incremented. Use + * of_node_put() on it when done. + */ +struct device_node * +of_parse_phandle(struct device_node *np, const char *phandle_name, int index) +{ + const phandle *phandle; + int size; + + phandle = of_get_property(np, phandle_name, &size); + if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) + return NULL; + + return of_find_node_by_phandle(phandle[index]); +} +EXPORT_SYMBOL(of_parse_phandle); + /** * of_parse_phandles_with_args - Find a node pointed by phandle in a list * @np: pointer to a device tree node containing a list diff --git a/include/linux/of.h b/include/linux/of.h index 6a7efa242f5e..7be2d1043c16 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -77,6 +77,9 @@ extern int of_n_size_cells(struct device_node *np); extern const struct of_device_id *of_match_node( const struct of_device_id *matches, const struct device_node *node); extern int of_modalias_node(struct device_node *node, char *modalias, int len); +extern struct device_node *of_parse_phandle(struct device_node *np, + const char *phandle_name, + int index); extern int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const char *cells_name, int index, struct device_node **out_node, const void **out_args); -- cgit v1.2.3 From 4dea547fef1ba23f9d23f5e7f5218187a7dcf1b3 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:52:46 +0000 Subject: phylib: rework to prepare for OF registration of PHYs This patch makes changes in preparation for supporting open firmware device tree descriptions of MDIO busses. Changes include: - Cleanup handling of phy_map[] entries; they are already NULLed when registering and so don't need to be re-cleared, and it is good practice to clear them out when unregistering. - Split phy_device registration out into a new function so that the OF helpers can do two stage registration (separate allocation and registration steps). Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 29 +++------------------------- drivers/net/phy/phy_device.c | 45 ++++++++++++++++++++++++++++++++++++++++---- include/linux/phy.h | 1 + 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index b754020cbe75..bd4e8d72dc08 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -113,7 +113,6 @@ int mdiobus_register(struct mii_bus *bus) bus->reset(bus); for (i = 0; i < PHY_MAX_ADDR; i++) { - bus->phy_map[i] = NULL; if ((bus->phy_mask & (1 << i)) == 0) { struct phy_device *phydev; @@ -150,6 +149,7 @@ void mdiobus_unregister(struct mii_bus *bus) for (i = 0; i < PHY_MAX_ADDR; i++) { if (bus->phy_map[i]) device_unregister(&bus->phy_map[i]->dev); + bus->phy_map[i] = NULL; } } EXPORT_SYMBOL(mdiobus_unregister); @@ -188,35 +188,12 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) if (IS_ERR(phydev) || phydev == NULL) return phydev; - /* There's a PHY at this address - * We need to set: - * 1) IRQ - * 2) bus_id - * 3) parent - * 4) bus - * 5) mii_bus - * And, we need to register it */ - - phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; - - phydev->dev.parent = bus->parent; - phydev->dev.bus = &mdio_bus_type; - dev_set_name(&phydev->dev, PHY_ID_FMT, bus->id, addr); - - phydev->bus = bus; - - /* Run all of the fixups for this PHY */ - phy_scan_fixups(phydev); - - err = device_register(&phydev->dev); + err = phy_device_register(phydev); if (err) { - printk(KERN_ERR "phy %d failed to register\n", addr); phy_device_free(phydev); - phydev = NULL; + return NULL; } - bus->phy_map[addr] = phydev; - return phydev; } EXPORT_SYMBOL(mdiobus_scan); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 0a06e4fd37d9..9352ca8fa2cc 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -39,20 +39,21 @@ MODULE_DESCRIPTION("PHY library"); MODULE_AUTHOR("Andy Fleming"); MODULE_LICENSE("GPL"); -static struct phy_driver genphy_driver; -extern int mdio_bus_init(void); -extern void mdio_bus_exit(void); - void phy_device_free(struct phy_device *phydev) { kfree(phydev); } +EXPORT_SYMBOL(phy_device_free); static void phy_device_release(struct device *dev) { phy_device_free(to_phy_device(dev)); } +static struct phy_driver genphy_driver; +extern int mdio_bus_init(void); +extern void mdio_bus_exit(void); + static LIST_HEAD(phy_fixup_list); static DEFINE_MUTEX(phy_fixup_lock); @@ -166,6 +167,10 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) dev->addr = addr; dev->phy_id = phy_id; dev->bus = bus; + dev->dev.parent = bus->parent; + dev->dev.bus = &mdio_bus_type; + dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; + dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr); dev->state = PHY_DOWN; @@ -235,6 +240,38 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) return dev; } +EXPORT_SYMBOL(get_phy_device); + +/** + * phy_device_register - Register the phy device on the MDIO bus + * @phy_device: phy_device structure to be added to the MDIO bus + */ +int phy_device_register(struct phy_device *phydev) +{ + int err; + + /* Don't register a phy if one is already registered at this + * address */ + if (phydev->bus->phy_map[phydev->addr]) + return -EINVAL; + phydev->bus->phy_map[phydev->addr] = phydev; + + /* Run all of the fixups for this PHY */ + phy_scan_fixups(phydev); + + err = device_register(&phydev->dev); + if (err) { + pr_err("phy %d failed to register\n", phydev->addr); + goto out; + } + + return 0; + + out: + phydev->bus->phy_map[phydev->addr] = NULL; + return err; +} +EXPORT_SYMBOL(phy_device_register); /** * phy_prepare_link - prepares the PHY layer to monitor link status diff --git a/include/linux/phy.h b/include/linux/phy.h index 97e40cb6b588..bf0b5f112dc7 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -444,6 +444,7 @@ static inline int phy_write(struct phy_device *phydev, u16 regnum, u16 val) int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); struct phy_device* get_phy_device(struct mii_bus *bus, int addr); +int phy_device_register(struct phy_device *phy); int phy_clear_interrupt(struct phy_device *phydev); int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); struct phy_device * phy_attach(struct net_device *dev, -- cgit v1.2.3 From fa94f6d93c5382810ff41f010f12ca8698fc775e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:52:51 +0000 Subject: phylib: add *_direct() variants of phy_connect and phy_attach functions Add phy_connect_direct() and phy_attach_direct() functions so that drivers can use a pointer to the phy_device instead of trying to determine the phy's bus_id string. This patch is useful for OF device tree descriptions of phy devices where the driver doesn't need or know what the bus_id value in order to get a phy_device pointer. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 118 +++++++++++++++++++++++++++++++------------ include/linux/phy.h | 5 ++ 2 files changed, 90 insertions(+), 33 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9352ca8fa2cc..a2ece89622d6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -291,6 +291,33 @@ void phy_prepare_link(struct phy_device *phydev, phydev->adjust_link = handler; } +/** + * phy_connect_direct - connect an ethernet device to a specific phy_device + * @dev: the network device to connect + * @phydev: the pointer to the phy device + * @handler: callback function for state change notifications + * @flags: PHY device's dev_flags + * @interface: PHY device's interface + */ +int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, + void (*handler)(struct net_device *), u32 flags, + phy_interface_t interface) +{ + int rc; + + rc = phy_attach_direct(dev, phydev, flags, interface); + if (rc) + return rc; + + phy_prepare_link(phydev, handler); + phy_start_machine(phydev, NULL); + if (phydev->irq > 0) + phy_start_interrupts(phydev); + + return 0; +} +EXPORT_SYMBOL(phy_connect_direct); + /** * phy_connect - connect an ethernet device to a PHY device * @dev: the network device to connect @@ -312,18 +339,21 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, phy_interface_t interface) { struct phy_device *phydev; + struct device *d; + int rc; - phydev = phy_attach(dev, bus_id, flags, interface); - - if (IS_ERR(phydev)) - return phydev; - - phy_prepare_link(phydev, handler); - - phy_start_machine(phydev, NULL); + /* Search the list of PHY devices on the mdio bus for the + * PHY with the requested name */ + d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); + if (!d) { + pr_err("PHY %s not found\n", bus_id); + return ERR_PTR(-ENODEV); + } + phydev = to_phy_device(d); - if (phydev->irq > 0) - phy_start_interrupts(phydev); + rc = phy_connect_direct(dev, phydev, handler, flags, interface); + if (rc) + return ERR_PTR(rc); return phydev; } @@ -347,9 +377,9 @@ void phy_disconnect(struct phy_device *phydev) EXPORT_SYMBOL(phy_disconnect); /** - * phy_attach - attach a network device to a particular PHY device + * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach - * @bus_id: PHY device to attach + * @phydev: Pointer to phy_device to attach * @flags: PHY device's dev_flags * @interface: PHY device's interface * @@ -360,22 +390,10 @@ EXPORT_SYMBOL(phy_disconnect); * the attaching device, and given a callback for link status * change. The phy_device is returned to the attaching driver. */ -struct phy_device *phy_attach(struct net_device *dev, - const char *bus_id, u32 flags, phy_interface_t interface) +int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface) { - struct bus_type *bus = &mdio_bus_type; - struct phy_device *phydev; - struct device *d; - - /* Search the list of PHY devices on the mdio bus for the - * PHY with the requested name */ - d = bus_find_device_by_name(bus, NULL, bus_id); - if (d) { - phydev = to_phy_device(d); - } else { - printk(KERN_ERR "%s not found\n", bus_id); - return ERR_PTR(-ENODEV); - } + struct device *d = &phydev->dev; /* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver. */ @@ -388,13 +406,12 @@ struct phy_device *phy_attach(struct net_device *dev, err = device_bind_driver(d); if (err) - return ERR_PTR(err); + return err; } if (phydev->attached_dev) { - printk(KERN_ERR "%s: %s already attached\n", - dev->name, bus_id); - return ERR_PTR(-EBUSY); + dev_err(&dev->dev, "PHY already attached\n"); + return -EBUSY; } phydev->attached_dev = dev; @@ -412,13 +429,48 @@ struct phy_device *phy_attach(struct net_device *dev, err = phy_scan_fixups(phydev); if (err < 0) - return ERR_PTR(err); + return err; err = phydev->drv->config_init(phydev); if (err < 0) - return ERR_PTR(err); + return err; + } + + return 0; +} +EXPORT_SYMBOL(phy_attach_direct); + +/** + * phy_attach - attach a network device to a particular PHY device + * @dev: network device to attach + * @bus_id: Bus ID of PHY device to attach + * @flags: PHY device's dev_flags + * @interface: PHY device's interface + * + * Description: Same as phy_attach_direct() except that a PHY bus_id + * string is passed instead of a pointer to a struct phy_device. + */ +struct phy_device *phy_attach(struct net_device *dev, + const char *bus_id, u32 flags, phy_interface_t interface) +{ + struct bus_type *bus = &mdio_bus_type; + struct phy_device *phydev; + struct device *d; + int rc; + + /* Search the list of PHY devices on the mdio bus for the + * PHY with the requested name */ + d = bus_find_device_by_name(bus, NULL, bus_id); + if (!d) { + pr_err("PHY %s not found\n", bus_id); + return ERR_PTR(-ENODEV); } + phydev = to_phy_device(d); + + rc = phy_attach_direct(dev, phydev, flags, interface); + if (rc) + return ERR_PTR(rc); return phydev; } diff --git a/include/linux/phy.h b/include/linux/phy.h index bf0b5f112dc7..c216e4e503b3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -447,8 +447,13 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); int phy_device_register(struct phy_device *phy); int phy_clear_interrupt(struct phy_device *phydev); int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); +int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface); struct phy_device * phy_attach(struct net_device *dev, const char *bus_id, u32 flags, phy_interface_t interface); +int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, + void (*handler)(struct net_device *), u32 flags, + phy_interface_t interface); struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device *), u32 flags, phy_interface_t interface); -- cgit v1.2.3 From 8bc487d150b939e69830c39322df4ee486efe381 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:52:56 +0000 Subject: openfirmware: Add OF phylib support code Add support for parsing the device tree for PHY devices on an MDIO bus. Currently many of the PowerPC ethernet drivers are open coding a solution for reading data out of the device tree to find the correct PHY device. This patch implements a set of common routines to: a) let MDIO bus drivers register phy_devices described in the tree, and b) let MAC drivers find the correct phy_device via the tree. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/of/Kconfig | 6 +++ drivers/of/Makefile | 1 + drivers/of/of_mdio.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_mdio.h | 22 ++++++++ 4 files changed, 168 insertions(+) create mode 100644 drivers/of/of_mdio.c create mode 100644 include/linux/of_mdio.h diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index f821dbc952a4..6fe043bd3770 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -19,3 +19,9 @@ config OF_SPI depends on OF && PPC_OF && SPI help OpenFirmware SPI accessors + +config OF_MDIO + def_tristate PHYLIB + depends on OF && PHYLIB + help + OpenFirmware MDIO bus (Ethernet PHY) accessors diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 4c3c6f8e36f5..bdfb5f5d4b06 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_OF_DEVICE) += device.o platform.o obj-$(CONFIG_OF_GPIO) += gpio.o obj-$(CONFIG_OF_I2C) += of_i2c.o obj-$(CONFIG_OF_SPI) += of_spi.o +obj-$(CONFIG_OF_MDIO) += of_mdio.o diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c new file mode 100644 index 000000000000..aee967d7f760 --- /dev/null +++ b/drivers/of/of_mdio.c @@ -0,0 +1,139 @@ +/* + * OF helpers for the MDIO (Ethernet PHY) API + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + * + * This file is released under the GPLv2 + * + * This file provides helper functions for extracting PHY device information + * out of the OpenFirmware device tree and using it to populate an mii_bus. + */ + +#include +#include +#include +#include + +MODULE_AUTHOR("Grant Likely "); +MODULE_LICENSE("GPL"); + +/** + * of_mdiobus_register - Register mii_bus and create PHYs from the device tree + * @mdio: pointer to mii_bus structure + * @np: pointer to device_node of MDIO bus. + * + * This function registers the mii_bus structure and registers a phy_device + * for each child node of @np. + */ +int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +{ + struct phy_device *phy; + struct device_node *child; + int rc, i; + + /* Mask out all PHYs from auto probing. Instead the PHYs listed in + * the device tree are populated after the bus has been registered */ + mdio->phy_mask = ~0; + + /* Clear all the IRQ properties */ + if (mdio->irq) + for (i=0; iirq[i] = PHY_POLL; + + /* Register the MDIO bus */ + rc = mdiobus_register(mdio); + if (rc) + return rc; + + /* Loop over the child nodes and register a phy_device for each one */ + for_each_child_of_node(np, child) { + const u32 *addr; + int len; + + /* A PHY must have a reg property in the range [0-31] */ + addr = of_get_property(child, "reg", &len); + if (!addr || len < sizeof(*addr) || *addr >= 32 || *addr < 0) { + dev_err(&mdio->dev, "%s has invalid PHY address\n", + child->full_name); + continue; + } + + if (mdio->irq) { + mdio->irq[*addr] = irq_of_parse_and_map(child, 0); + if (!mdio->irq[*addr]) + mdio->irq[*addr] = PHY_POLL; + } + + phy = get_phy_device(mdio, *addr); + if (!phy) { + dev_err(&mdio->dev, "error probing PHY at address %i\n", + *addr); + continue; + } + phy_scan_fixups(phy); + + /* Associate the OF node with the device structure so it + * can be looked up later */ + of_node_get(child); + dev_archdata_set_node(&phy->dev.archdata, child); + + /* All data is now stored in the phy struct; register it */ + rc = phy_device_register(phy); + if (rc) { + phy_device_free(phy); + of_node_put(child); + continue; + } + + dev_dbg(&mdio->dev, "registered phy %s at address %i\n", + child->name, *addr); + } + + return 0; +} +EXPORT_SYMBOL(of_mdiobus_register); + +/** + * of_phy_find_device - Give a PHY node, find the phy_device + * @phy_np: Pointer to the phy's device tree node + * + * Returns a pointer to the phy_device. + */ +struct phy_device *of_phy_find_device(struct device_node *phy_np) +{ + struct device *d; + int match(struct device *dev, void *phy_np) + { + return dev_archdata_get_node(&dev->archdata) == phy_np; + } + + if (!phy_np) + return NULL; + + d = bus_find_device(&mdio_bus_type, NULL, phy_np, match); + return d ? to_phy_device(d) : NULL; +} +EXPORT_SYMBOL(of_phy_find_device); + +/** + * of_phy_connect - Connect to the phy described in the device tree + * @dev: pointer to net_device claiming the phy + * @phy_np: Pointer to device tree node for the PHY + * @hndlr: Link state callback for the network device + * @iface: PHY data interface type + * + * Returns a pointer to the phy_device if successfull. NULL otherwise + */ +struct phy_device *of_phy_connect(struct net_device *dev, + struct device_node *phy_np, + void (*hndlr)(struct net_device *), u32 flags, + phy_interface_t iface) +{ + struct phy_device *phy = of_phy_find_device(phy_np); + + if (!phy) + return NULL; + + return phy_connect_direct(dev, phy, hndlr, flags, iface) ? NULL : phy; +} +EXPORT_SYMBOL(of_phy_connect); diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h new file mode 100644 index 000000000000..c9663c690303 --- /dev/null +++ b/include/linux/of_mdio.h @@ -0,0 +1,22 @@ +/* + * OF helpers for the MDIO (Ethernet PHY) API + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + * + * This file is released under the GPLv2 + */ + +#ifndef __LINUX_OF_MDIO_H +#define __LINUX_OF_MDIO_H + +#include +#include + +extern int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np); +extern struct phy_device *of_phy_find_device(struct device_node *phy_np); +extern struct phy_device *of_phy_connect(struct net_device *dev, + struct device_node *phy_np, + void (*hndlr)(struct net_device *), + u32 flags, phy_interface_t iface); + +#endif /* __LINUX_OF_MDIO_H */ -- cgit v1.2.3 From ca816d98170942371535b3e862813b0aba9b7d90 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:02 +0000 Subject: net: Rework mpc5200 fec driver to use of_mdio infrastructure. The patch reworks the MPC5200 Fast Ethernet Controller (FEC) driver to use the of_mdio infrastructure for registering PHY devices from data out openfirmware device tree, and eliminates the assumption that the PHY for the FEC is always attached to the FEC's own MDIO bus. With this patch, the FEC can use a PHY attached to any MDIO bus if it is described in the device tree. Tested on Freescale Lite5200b eval board Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/fec_mpc52xx.c | 180 +++++++++++++----------------------------- drivers/net/fec_mpc52xx_phy.c | 26 ++---- 2 files changed, 59 insertions(+), 147 deletions(-) diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 8bbe7f617994..7d443405bbe2 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -43,11 +44,9 @@ #define DRIVER_NAME "mpc52xx-fec" -#define FEC5200_PHYADDR_NONE (-1) -#define FEC5200_PHYADDR_7WIRE (-2) - /* Private driver data structure */ struct mpc52xx_fec_priv { + struct net_device *ndev; int duplex; int speed; int r_irq; @@ -59,10 +58,11 @@ struct mpc52xx_fec_priv { int msg_enable; /* MDIO link details */ - int phy_addr; - unsigned int phy_speed; + unsigned int mdio_speed; + struct device_node *phy_node; struct phy_device *phydev; enum phy_state link; + int seven_wire_mode; }; @@ -211,85 +211,25 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev) phy_print_status(phydev); } -static int mpc52xx_fec_init_phy(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - struct phy_device *phydev; - char phy_id[BUS_ID_SIZE]; - - snprintf(phy_id, sizeof(phy_id), "%x:%02x", - (unsigned int)dev->base_addr, priv->phy_addr); - - priv->link = PHY_DOWN; - priv->speed = 0; - priv->duplex = -1; - - phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(phydev)) { - dev_err(&dev->dev, "phy_connect failed\n"); - return PTR_ERR(phydev); - } - dev_info(&dev->dev, "attached phy %i to driver %s\n", - phydev->addr, phydev->drv->name); - - priv->phydev = phydev; - - return 0; -} - -static int mpc52xx_fec_phy_start(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - int err; - - if (priv->phy_addr < 0) - return 0; - - err = mpc52xx_fec_init_phy(dev); - if (err) { - dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n"); - return err; - } - - /* reset phy - this also wakes it from PDOWN */ - phy_write(priv->phydev, MII_BMCR, BMCR_RESET); - phy_start(priv->phydev); - - return 0; -} - -static void mpc52xx_fec_phy_stop(struct net_device *dev) -{ - struct mpc52xx_fec_priv *priv = netdev_priv(dev); - - if (!priv->phydev) - return; - - phy_disconnect(priv->phydev); - /* power down phy */ - phy_stop(priv->phydev); - phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN); -} - -static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv) -{ - struct mpc52xx_fec __iomem *fec = priv->fec; - - if (priv->phydev) - return; - - out_be32(&fec->mii_speed, priv->phy_speed); -} - static int mpc52xx_fec_open(struct net_device *dev) { struct mpc52xx_fec_priv *priv = netdev_priv(dev); int err = -EBUSY; + if (priv->phy_node) { + priv->phydev = of_phy_connect(priv->ndev, priv->phy_node, + mpc52xx_fec_adjust_link, 0, 0); + if (!priv->phydev) { + dev_err(&dev->dev, "of_phy_connect failed\n"); + return -ENODEV; + } + phy_start(priv->phydev); + } + if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_SHARED, DRIVER_NAME "_ctrl", dev)) { dev_err(&dev->dev, "ctrl interrupt request failed\n"); - goto out; + goto free_phy; } if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, 0, DRIVER_NAME "_rx", dev)) { @@ -311,10 +251,6 @@ static int mpc52xx_fec_open(struct net_device *dev) goto free_irqs; } - err = mpc52xx_fec_phy_start(dev); - if (err) - goto free_skbs; - bcom_enable(priv->rx_dmatsk); bcom_enable(priv->tx_dmatsk); @@ -324,16 +260,18 @@ static int mpc52xx_fec_open(struct net_device *dev) return 0; - free_skbs: - mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk); - free_irqs: free_irq(priv->t_irq, dev); free_2irqs: free_irq(priv->r_irq, dev); free_ctrl_irq: free_irq(dev->irq, dev); - out: + free_phy: + if (priv->phydev) { + phy_stop(priv->phydev); + phy_disconnect(priv->phydev); + priv->phydev = NULL; + } return err; } @@ -352,7 +290,12 @@ static int mpc52xx_fec_close(struct net_device *dev) free_irq(priv->r_irq, dev); free_irq(priv->t_irq, dev); - mpc52xx_fec_phy_stop(dev); + if (priv->phydev) { + /* power down phy */ + phy_stop(priv->phydev); + phy_disconnect(priv->phydev); + priv->phydev = NULL; + } return 0; } @@ -696,7 +639,7 @@ static void mpc52xx_fec_hw_init(struct net_device *dev) /* set phy speed. * this can't be done in phy driver, since it needs to be called * before fec stuff (even on resume) */ - mpc52xx_fec_phy_hw_init(priv); + out_be32(&fec->mii_speed, priv->mdio_speed); } /** @@ -732,7 +675,7 @@ static void mpc52xx_fec_start(struct net_device *dev) rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ rcntrl |= FEC_RCNTRL_FCE; - if (priv->phy_addr != FEC5200_PHYADDR_7WIRE) + if (!priv->seven_wire_mode) rcntrl |= FEC_RCNTRL_MII_MODE; if (priv->duplex == DUPLEX_FULL) @@ -798,8 +741,6 @@ static void mpc52xx_fec_stop(struct net_device *dev) /* Stop FEC */ out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN); - - return; } /* reset fec and bestcomm tasks */ @@ -817,9 +758,11 @@ static void mpc52xx_fec_reset(struct net_device *dev) mpc52xx_fec_hw_init(dev); - phy_stop(priv->phydev); - phy_write(priv->phydev, MII_BMCR, BMCR_RESET); - phy_start(priv->phydev); + if (priv->phydev) { + phy_stop(priv->phydev); + phy_write(priv->phydev, MII_BMCR, BMCR_RESET); + phy_start(priv->phydev); + } bcom_fec_rx_reset(priv->rx_dmatsk); bcom_fec_tx_reset(priv->tx_dmatsk); @@ -919,8 +862,6 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) struct net_device *ndev; struct mpc52xx_fec_priv *priv = NULL; struct resource mem; - struct device_node *phy_node; - const phandle *phy_handle; const u32 *prop; int prop_size; @@ -933,6 +874,7 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) return -ENOMEM; priv = netdev_priv(ndev); + priv->ndev = ndev; /* Reserve FEC control zone */ rv = of_address_to_resource(op->node, 0, &mem); @@ -956,6 +898,7 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) ndev->ethtool_ops = &mpc52xx_fec_ethtool_ops; ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT; ndev->base_addr = mem.start; + SET_NETDEV_DEV(ndev, &op->dev); spin_lock_init(&priv->lock); @@ -1003,14 +946,9 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) */ /* Start with safe defaults for link connection */ - priv->phy_addr = FEC5200_PHYADDR_NONE; priv->speed = 100; priv->duplex = DUPLEX_HALF; - priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; - - /* the 7-wire property means don't use MII mode */ - if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) - priv->phy_addr = FEC5200_PHYADDR_7WIRE; + priv->mdio_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; /* The current speed preconfigures the speed of the MII link */ prop = of_get_property(op->node, "current-speed", &prop_size); @@ -1019,43 +957,23 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; } - /* If there is a phy handle, setup link to that phy */ - phy_handle = of_get_property(op->node, "phy-handle", &prop_size); - if (phy_handle && (prop_size >= sizeof(phandle))) { - phy_node = of_find_node_by_phandle(*phy_handle); - prop = of_get_property(phy_node, "reg", &prop_size); - if (prop && (prop_size >= sizeof(u32))) - if ((*prop >= 0) && (*prop < PHY_MAX_ADDR)) - priv->phy_addr = *prop; - of_node_put(phy_node); + /* If there is a phy handle, then get the PHY node */ + priv->phy_node = of_parse_phandle(op->node, "phy-handle", 0); + + /* the 7-wire property means don't use MII mode */ + if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) { + priv->seven_wire_mode = 1; + dev_info(&ndev->dev, "using 7-wire PHY mode\n"); } /* Hardware init */ mpc52xx_fec_hw_init(ndev); - mpc52xx_fec_reset_stats(ndev); - SET_NETDEV_DEV(ndev, &op->dev); - - /* Register the new network device */ rv = register_netdev(ndev); if (rv < 0) goto probe_error; - /* Now report the link setup */ - switch (priv->phy_addr) { - case FEC5200_PHYADDR_NONE: - dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n", - priv->speed, priv->duplex ? 'F' : 'H'); - break; - case FEC5200_PHYADDR_7WIRE: - dev_info(&ndev->dev, "using 7-wire PHY mode\n"); - break; - default: - dev_info(&ndev->dev, "Using PHY at MDIO address %i\n", - priv->phy_addr); - } - /* We're done ! */ dev_set_drvdata(&op->dev, ndev); @@ -1065,6 +983,10 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) /* Error handling - free everything that might be allocated */ probe_error: + if (priv->phy_node) + of_node_put(priv->phy_node); + priv->phy_node = NULL; + irq_dispose_mapping(ndev->irq); if (priv->rx_dmatsk) @@ -1093,6 +1015,10 @@ mpc52xx_fec_remove(struct of_device *op) unregister_netdev(ndev); + if (priv->phy_node) + of_node_put(priv->phy_node); + priv->phy_node = NULL; + irq_dispose_mapping(ndev->irq); bcom_fec_rx_release(priv->rx_dmatsk); diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index dd9bfa42ac34..fec9f245116b 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #include "fec_mpc52xx.h" struct mpc52xx_fec_mdio_priv { struct mpc52xx_fec __iomem *regs; + int mdio_irqs[PHY_MAX_ADDR]; }; static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, @@ -27,7 +29,7 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, { struct mpc52xx_fec_mdio_priv *priv = bus->priv; struct mpc52xx_fec __iomem *fec; - int tries = 100; + int tries = 3; value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; @@ -38,7 +40,7 @@ static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, /* wait for it to finish, this takes about 23 us on lite5200b */ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) - udelay(5); + msleep(1); if (!tries) return -ETIMEDOUT; @@ -64,7 +66,6 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, { struct device *dev = &of->dev; struct device_node *np = of->node; - struct device_node *child = NULL; struct mii_bus *bus; struct mpc52xx_fec_mdio_priv *priv; struct resource res = {}; @@ -85,22 +86,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, bus->write = mpc52xx_fec_mdio_write; /* setup irqs */ - bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL); - if (bus->irq == NULL) { - err = -ENOMEM; - goto out_free; - } - for (i=0; iirq[i] = PHY_POLL; - - while ((child = of_get_next_child(np, child)) != NULL) { - int irq = irq_of_parse_and_map(child, 0); - if (irq != NO_IRQ) { - const u32 *id = of_get_property(child, "reg", NULL); - if (id) - bus->irq[*id] = irq; - } - } + bus->irq = priv->mdio_irqs; /* setup registers */ err = of_address_to_resource(np, 0, &res); @@ -122,7 +108,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); - err = mdiobus_register(bus); + err = of_mdiobus_register(bus, np); if (err) goto out_unmap; -- cgit v1.2.3 From 324931ba21858c34787dee7d222388ef3fb41ee0 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:07 +0000 Subject: net: rework fsl_pq_mdio driver to use of_mdio infrastructure This patch simplifies the driver by making use of more common code. Tested on Freescale MPC8349emitxgp eval board Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/fsl_pq_mdio.c | 51 +++-------------------------------------------- 1 file changed, 3 insertions(+), 48 deletions(-) diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index aa1eb88c21fc..b01daa1e3adf 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -154,44 +155,6 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus) return 0; } -/* Allocate an array which provides irq #s for each PHY on the given bus */ -static int *create_irq_map(struct device_node *np) -{ - int *irqs; - int i; - struct device_node *child = NULL; - - irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); - - if (!irqs) - return NULL; - - for (i = 0; i < PHY_MAX_ADDR; i++) - irqs[i] = PHY_POLL; - - while ((child = of_get_next_child(np, child)) != NULL) { - int irq = irq_of_parse_and_map(child, 0); - const u32 *id; - - if (irq == NO_IRQ) - continue; - - id = of_get_property(child, "reg", NULL); - - if (!id) - continue; - - if (*id < PHY_MAX_ADDR && *id >= 0) - irqs[*id] = irq; - else - printk(KERN_WARNING "%s: " - "%d is not a valid PHY address\n", - np->full_name, *id); - } - - return irqs; -} - void fsl_pq_mdio_bus_name(char *name, struct device_node *np) { const u32 *addr; @@ -315,7 +278,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, new_bus->priv = (void __force *)regs; - new_bus->irq = create_irq_map(np); + new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); if (NULL == new_bus->irq) { err = -ENOMEM; @@ -384,15 +347,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, out_be32(tbipa, tbiaddr); - /* - * The TBIPHY-only buses will find PHYs at every address, - * so we mask them all but the TBI - */ - if (of_device_is_compatible(np, "fsl,gianfar-tbi")) - new_bus->phy_mask = ~(1 << tbiaddr); - - err = mdiobus_register(new_bus); - + err = of_mdiobus_register(new_bus, np); if (err) { printk (KERN_ERR "%s: Cannot register as MDIO bus\n", new_bus->name); -- cgit v1.2.3 From fe192a49118f5b1272317d60c7930ece4e13ae49 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:12 +0000 Subject: net: Rework gianfar driver to use of_mdio infrastructure. This patch simplifies the driver by making use of more common code. Tested on Freescale MPC8349emitxgp eval board Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 109 +++++++++++++++++--------------------------------- drivers/net/gianfar.h | 4 +- 2 files changed, 39 insertions(+), 74 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index b2c49679bba7..dae14373296a 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -168,17 +169,13 @@ static inline int gfar_uses_fcb(struct gfar_private *priv) static int gfar_of_init(struct net_device *dev) { - struct device_node *phy, *mdio; - const unsigned int *id; const char *model; const char *ctype; const void *mac_addr; - const phandle *ph; u64 addr, size; int err = 0; struct gfar_private *priv = netdev_priv(dev); struct device_node *np = priv->node; - char bus_name[MII_BUS_ID_SIZE]; const u32 *stash; const u32 *stash_len; const u32 *stash_idx; @@ -264,8 +261,8 @@ static int gfar_of_init(struct net_device *dev) if (of_get_property(np, "fsl,magic-packet", NULL)) priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; - ph = of_get_property(np, "phy-handle", NULL); - if (ph == NULL) { + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy_node) { u32 *fixed_link; fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL); @@ -273,57 +270,10 @@ static int gfar_of_init(struct net_device *dev) err = -ENODEV; goto err_out; } - - snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), - PHY_ID_FMT, "0", fixed_link[0]); - } else { - phy = of_find_node_by_phandle(*ph); - - if (phy == NULL) { - err = -ENODEV; - goto err_out; - } - - mdio = of_get_parent(phy); - - id = of_get_property(phy, "reg", NULL); - - of_node_put(phy); - - fsl_pq_mdio_bus_name(bus_name, mdio); - of_node_put(mdio); - snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", - bus_name, *id); } /* Find the TBI PHY. If it's not there, we don't support SGMII */ - ph = of_get_property(np, "tbi-handle", NULL); - if (ph) { - struct device_node *tbi = of_find_node_by_phandle(*ph); - struct of_device *ofdev; - struct mii_bus *bus; - - if (!tbi) - return 0; - - mdio = of_get_parent(tbi); - if (!mdio) - return 0; - - ofdev = of_find_device_by_node(mdio); - - of_node_put(mdio); - - id = of_get_property(tbi, "reg", NULL); - if (!id) - return 0; - - of_node_put(tbi); - - bus = dev_get_drvdata(&ofdev->dev); - - priv->tbiphy = bus->phy_map[*id]; - } + priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0); return 0; @@ -529,6 +479,10 @@ static int gfar_probe(struct of_device *ofdev, register_fail: iounmap(priv->regs); regs_fail: + if (priv->phy_node) + of_node_put(priv->phy_node); + if (priv->tbi_node) + of_node_put(priv->tbi_node); free_netdev(dev); return err; } @@ -537,6 +491,11 @@ static int gfar_remove(struct of_device *ofdev) { struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); + if (priv->phy_node) + of_node_put(priv->phy_node); + if (priv->tbi_node) + of_node_put(priv->tbi_node); + dev_set_drvdata(&ofdev->dev, NULL); iounmap(priv->regs); @@ -690,7 +649,6 @@ static int init_phy(struct net_device *dev) uint gigabit_support = priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? SUPPORTED_1000baseT_Full : 0; - struct phy_device *phydev; phy_interface_t interface; priv->oldlink = 0; @@ -699,21 +657,21 @@ static int init_phy(struct net_device *dev) interface = gfar_get_interface(dev); - phydev = phy_connect(dev, priv->phy_bus_id, &adjust_link, 0, interface); + if (priv->phy_node) { + priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, + 0, interface); + if (!priv->phydev) { + dev_err(&dev->dev, "error: Could not attach to PHY\n"); + return -ENODEV; + } + } if (interface == PHY_INTERFACE_MODE_SGMII) gfar_configure_serdes(dev); - if (IS_ERR(phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); - } - /* Remove any features not supported by the controller */ - phydev->supported &= (GFAR_SUPPORTED | gigabit_support); - phydev->advertising = phydev->supported; - - priv->phydev = phydev; + priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support); + priv->phydev->advertising = priv->phydev->supported; return 0; } @@ -730,10 +688,17 @@ static int init_phy(struct net_device *dev) static void gfar_configure_serdes(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + struct phy_device *tbiphy; + + if (!priv->tbi_node) { + dev_warn(&dev->dev, "error: SGMII mode requires that the " + "device tree specify a tbi-handle\n"); + return; + } - if (!priv->tbiphy) { - printk(KERN_WARNING "SGMII mode requires that the device " - "tree specify a tbi-handle\n"); + tbiphy = of_phy_find_device(priv->tbi_node); + if (!tbiphy) { + dev_err(&dev->dev, "error: Could not get TBI device\n"); return; } @@ -743,17 +708,17 @@ static void gfar_configure_serdes(struct net_device *dev) * everything for us? Resetting it takes the link down and requires * several seconds for it to come back. */ - if (phy_read(priv->tbiphy, MII_BMSR) & BMSR_LSTATUS) + if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) return; /* Single clk mode, mii mode off(for serdes communication) */ - phy_write(priv->tbiphy, MII_TBICON, TBICON_CLK_SELECT); + phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT); - phy_write(priv->tbiphy, MII_ADVERTISE, + phy_write(tbiphy, MII_ADVERTISE, ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM); - phy_write(priv->tbiphy, MII_BMCR, BMCR_ANENABLE | + phy_write(tbiphy, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 0642d52aef5c..91317bc11154 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -779,7 +779,8 @@ struct gfar_private { spinlock_t bflock; phy_interface_t interface; - char phy_bus_id[BUS_ID_SIZE]; + struct device_node *phy_node; + struct device_node *tbi_node; u32 device_flags; unsigned char rx_csum_enable:1, extended_hash:1, @@ -793,7 +794,6 @@ struct gfar_private { /* PHY stuff */ struct phy_device *phydev; - struct phy_device *tbiphy; struct mii_bus *mii_bus; int oldspeed; int oldduplex; -- cgit v1.2.3 From 1dd2d06c0459a2f1bffc56765e3cc57427818867 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:17 +0000 Subject: net: Rework pasemi_mac driver to use of_mdio infrastructure This patch simplifies the driver by making use of more common code. Signed-off-by: Grant Likely Tested-by: Olof Johansson Acked-by: Olof Johansson Acked-by: Andy Fleming Signed-off-by: David S. Miller --- arch/powerpc/platforms/pasemi/gpio_mdio.c | 32 +++++-------------------------- drivers/net/pasemi_mac.c | 28 ++++----------------------- drivers/net/pasemi_mac.h | 1 - 3 files changed, 9 insertions(+), 52 deletions(-) diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 75cc165d5bee..3bf546797cbb 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #define DELAY 1 @@ -39,6 +39,7 @@ static void __iomem *gpio_regs; struct gpio_priv { int mdc_pin; int mdio_pin; + int mdio_irqs[PHY_MAX_ADDR]; }; #define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin) @@ -218,12 +219,11 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device *dev = &ofdev->dev; - struct device_node *phy_dn, *np = ofdev->node; + struct device_node *np = ofdev->node; struct mii_bus *new_bus; struct gpio_priv *priv; const unsigned int *prop; int err; - int i; err = -ENOMEM; priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL); @@ -244,27 +244,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop); new_bus->priv = priv; - new_bus->phy_mask = 0; - - new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); - - if (!new_bus->irq) - goto out_free_bus; - - for (i = 0; i < PHY_MAX_ADDR; i++) - new_bus->irq[i] = NO_IRQ; - - for (phy_dn = of_get_next_child(np, NULL); - phy_dn != NULL; - phy_dn = of_get_next_child(np, phy_dn)) { - const unsigned int *ip, *regp; - - ip = of_get_property(phy_dn, "interrupts", NULL); - regp = of_get_property(phy_dn, "reg", NULL); - if (!ip || !regp || *regp >= PHY_MAX_ADDR) - continue; - new_bus->irq[*regp] = irq_create_mapping(NULL, *ip); - } + new_bus->irq = priv->mdio_irqs; prop = of_get_property(np, "mdc-pin", NULL); priv->mdc_pin = *prop; @@ -275,7 +255,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, new_bus->parent = dev; dev_set_drvdata(dev, new_bus); - err = mdiobus_register(new_bus); + err = of_mdiobus_register(new_bus, np); if (err != 0) { printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n", @@ -286,8 +266,6 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, return 0; out_free_irq: - kfree(new_bus->irq); -out_free_bus: kfree(new_bus); out_free_priv: kfree(priv); diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 067caba43656..6ea4539085d5 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1086,34 +1087,17 @@ static int pasemi_mac_phy_init(struct net_device *dev) struct pasemi_mac *mac = netdev_priv(dev); struct device_node *dn, *phy_dn; struct phy_device *phydev; - unsigned int phy_id; - const phandle *ph; - const unsigned int *prop; - struct resource r; - int ret; dn = pci_device_to_OF_node(mac->pdev); - ph = of_get_property(dn, "phy-handle", NULL); - if (!ph) - return -ENODEV; - phy_dn = of_find_node_by_phandle(*ph); - - prop = of_get_property(phy_dn, "reg", NULL); - ret = of_address_to_resource(phy_dn->parent, 0, &r); - if (ret) - goto err; - - phy_id = *prop; - snprintf(mac->phy_id, sizeof(mac->phy_id), "%x:%02x", - (int)r.start, phy_id); - + phy_dn = of_parse_phandle(dn, "phy-handle", 0); of_node_put(phy_dn); mac->link = 0; mac->speed = 0; mac->duplex = -1; - phydev = phy_connect(dev, mac->phy_id, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII); + phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, + PHY_INTERFACE_MODE_SGMII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); @@ -1123,10 +1107,6 @@ static int pasemi_mac_phy_init(struct net_device *dev) mac->phydev = phydev; return 0; - -err: - of_node_put(phy_dn); - return -ENODEV; } diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h index 1a115ec60b53..e2f4efa8ad46 100644 --- a/drivers/net/pasemi_mac.h +++ b/drivers/net/pasemi_mac.h @@ -100,7 +100,6 @@ struct pasemi_mac { int duplex; unsigned int msg_enable; - char phy_id[BUS_ID_SIZE]; }; /* Software status descriptor (ring_info) */ -- cgit v1.2.3 From 0b9da337dca972e7a4144e298ec3adb8f244d4a4 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:23 +0000 Subject: net: Rework ucc_geth driver to use of_mdio infrastructure This patch simplifies the driver by making use of more common code. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 47 ++++++++++++----------------------------------- drivers/net/ucc_geth.h | 2 +- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 811f97cb0a29..a53628466637 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -1543,12 +1544,14 @@ static int init_phy(struct net_device *dev) priv->oldspeed = 0; priv->oldduplex = -1; - phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0, - priv->phy_interface); + if (!ug_info->phy_node) + return 0; - if (IS_ERR(phydev)) { + phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0, + priv->phy_interface); + if (!phydev) { printk("%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); + return -ENODEV; } phydev->supported &= (ADVERTISED_10baseT_Half | @@ -3511,14 +3514,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma { struct device *device = &ofdev->dev; struct device_node *np = ofdev->node; - struct device_node *mdio; struct net_device *dev = NULL; struct ucc_geth_private *ugeth = NULL; struct ucc_geth_info *ug_info; struct resource res; struct device_node *phy; int err, ucc_num, max_speed = 0; - const phandle *ph; const u32 *fixed_link; const unsigned int *prop; const char *sprop; @@ -3618,45 +3619,21 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); fixed_link = of_get_property(np, "fixed-link", NULL); if (fixed_link) { - snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), - PHY_ID_FMT, "0", fixed_link[0]); phy = NULL; } else { - char bus_name[MII_BUS_ID_SIZE]; - - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); - + phy = of_parse_phandle(np, "phy-handle", 0); if (phy == NULL) return -ENODEV; - - /* set the PHY address */ - prop = of_get_property(phy, "reg", NULL); - if (prop == NULL) - return -1; - - /* Set the bus id */ - mdio = of_get_parent(phy); - - if (mdio == NULL) - return -ENODEV; - - err = of_address_to_resource(mdio, 0, &res); - - if (err) { - of_node_put(mdio); - return err; - } - fsl_pq_mdio_bus_name(bus_name, mdio); - of_node_put(mdio); - snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), - "%s:%02x", bus_name, *prop); } + ug_info->phy_node = phy; /* get the phy interface type, or default to MII */ prop = of_get_property(np, "phy-connection-type", NULL); if (!prop) { /* handle interface property present in old trees */ + if (!phy) + return -ENODEV; + prop = of_get_property(phy, "interface", NULL); if (prop != NULL) { phy_interface = enet_to_phy_interface[*prop]; diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 602764799df0..dca628a922ba 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -1099,7 +1099,7 @@ struct ucc_geth_info { u32 eventRegMask; u16 pausePeriod; u16 extensionField; - char phy_bus_id[BUS_ID_SIZE]; + struct device_node *phy_node; u8 weightfactor[NUM_TX_QUEUES]; u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; -- cgit v1.2.3 From fd84f0ee50d3abedd11454b016823aa3ffcdc919 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:28 +0000 Subject: powerpc/82xx: Rework Embedded Planet ep8248e platform to use of_mdio This patch modifies the bitbanged MDIO driver in the ep8248e platform code to use the common of_mdio infrastructure. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- arch/powerpc/platforms/82xx/ep8248e.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index 0eb6d7f62241..51fcae41f08a 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -115,7 +116,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev, struct mii_bus *bus; struct resource res; struct device_node *node; - int ret, i; + int ret; node = of_get_parent(ofdev->node); of_node_put(node); @@ -130,17 +131,13 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev, if (!bus) return -ENOMEM; - bus->phy_mask = 0; bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); - for (i = 0; i < PHY_MAX_ADDR; i++) - bus->irq[i] = -1; - bus->name = "ep8248e-mdio-bitbang"; bus->parent = &ofdev->dev; snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); - return mdiobus_register(bus); + return of_mdiobus_register(bus, ofdev->node); } static int ep8248e_mdio_remove(struct of_device *ofdev) -- cgit v1.2.3 From aa73832c5a80d6c52c69b18af858d88fa595dd3c Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:33 +0000 Subject: net: Rework fs_enet driver to use of_mdio infrastructure This patch simplifies the driver by making use of more common code. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/fs_enet/fs_enet-main.c | 69 ++++++-------------------------------- drivers/net/fs_enet/mii-bitbang.c | 29 ++-------------- drivers/net/fs_enet/mii-fec.c | 26 +------------- include/linux/fs_enet_pd.h | 6 ++-- 4 files changed, 16 insertions(+), 114 deletions(-) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index a9cbc3191a2a..9604aaed61d6 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -752,9 +754,10 @@ static int fs_init_phy(struct net_device *dev) fep->oldlink = 0; fep->oldspeed = 0; fep->oldduplex = -1; - if(fep->fpi->bus_id) - phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + if(fep->fpi->phy_node) + phydev = of_phy_connect(dev, fep->fpi->phy_node, + &fs_adjust_link, 0, + PHY_INTERFACE_MODE_MII); else { printk("No phy bus ID specified in BSP code\n"); return -EINVAL; @@ -962,57 +965,6 @@ static void cleanup_immap(void) /**************************************************************************************/ -static int __devinit find_phy(struct device_node *np, - struct fs_platform_info *fpi) -{ - struct device_node *phynode, *mdionode; - int ret = 0, len, bus_id; - const u32 *data; - - data = of_get_property(np, "fixed-link", NULL); - if (data) { - snprintf(fpi->bus_id, 16, "%x:%02x", 0, *data); - return 0; - } - - data = of_get_property(np, "phy-handle", &len); - if (!data || len != 4) - return -EINVAL; - - phynode = of_find_node_by_phandle(*data); - if (!phynode) - return -EINVAL; - - data = of_get_property(phynode, "reg", &len); - if (!data || len != 4) { - ret = -EINVAL; - goto out_put_phy; - } - - mdionode = of_get_parent(phynode); - if (!mdionode) { - ret = -EINVAL; - goto out_put_phy; - } - - bus_id = of_get_gpio(mdionode, 0); - if (bus_id < 0) { - struct resource res; - ret = of_address_to_resource(mdionode, 0, &res); - if (ret) - goto out_put_mdio; - bus_id = res.start; - } - - snprintf(fpi->bus_id, 16, "%x:%02x", bus_id, *data); - -out_put_mdio: - of_node_put(mdionode); -out_put_phy: - of_node_put(phynode); - return ret; -} - #ifdef CONFIG_FS_ENET_HAS_FEC #define IS_FEC(match) ((match)->data == &fs_fec_ops) #else @@ -1062,9 +1014,9 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, fpi->rx_copybreak = 240; fpi->use_napi = 1; fpi->napi_weight = 17; - - ret = find_phy(ofdev->node, fpi); - if (ret) + fpi->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0); + if ((!fpi->phy_node) && (!of_get_property(ofdev->node, "fixed-link", + NULL))) goto out_free_fpi; privsize = sizeof(*fep) + @@ -1136,6 +1088,7 @@ out_cleanup_data: out_free_dev: free_netdev(ndev); dev_set_drvdata(&ofdev->dev, NULL); + of_node_put(fpi->phy_node); out_free_fpi: kfree(fpi); return ret; @@ -1151,7 +1104,7 @@ static int fs_enet_remove(struct of_device *ofdev) fep->ops->free_bd(ndev); fep->ops->cleanup_data(ndev); dev_set_drvdata(fep->dev, NULL); - + of_node_put(fep->fpi->phy_node); free_netdev(ndev); return 0; } diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 49b6645d7e0c..93b481b0e3c7 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "fs_enet.h" @@ -149,31 +150,12 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, return 0; } -static void __devinit add_phy(struct mii_bus *bus, struct device_node *np) -{ - const u32 *data; - int len, id, irq; - - data = of_get_property(np, "reg", &len); - if (!data || len != 4) - return; - - id = *data; - bus->phy_mask &= ~(1 << id); - - irq = of_irq_to_resource(np, 0, NULL); - if (irq != NO_IRQ) - bus->irq[id] = irq; -} - static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) { - struct device_node *np = NULL; struct mii_bus *new_bus; struct bb_info *bitbang; int ret = -ENOMEM; - int i; bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); if (!bitbang) @@ -196,17 +178,10 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, if (!new_bus->irq) goto out_unmap_regs; - for (i = 0; i < PHY_MAX_ADDR; i++) - new_bus->irq[i] = -1; - - while ((np = of_get_next_child(ofdev->node, np))) - if (!strcmp(np->type, "ethernet-phy")) - add_phy(new_bus, np); - new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); - ret = mdiobus_register(new_bus); + ret = of_mdiobus_register(new_bus, ofdev->node); if (ret) goto out_free_irqs; diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 61aaae444b40..75a09994d665 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -100,23 +100,6 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) return 0; } -static void __devinit add_phy(struct mii_bus *bus, struct device_node *np) -{ - const u32 *data; - int len, id, irq; - - data = of_get_property(np, "reg", &len); - if (!data || len != 4) - return; - - id = *data; - bus->phy_mask &= ~(1 << id); - - irq = of_irq_to_resource(np, 0, NULL); - if (irq != NO_IRQ) - bus->irq[id] = irq; -} - static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, const struct of_device_id *match) { @@ -163,17 +146,10 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, if (!new_bus->irq) goto out_unmap_regs; - for (i = 0; i < PHY_MAX_ADDR; i++) - new_bus->irq[i] = -1; - - while ((np = of_get_next_child(ofdev->node, np))) - if (!strcmp(np->type, "ethernet-phy")) - add_phy(new_bus, np); - new_bus->parent = &ofdev->dev; dev_set_drvdata(&ofdev->dev, new_bus); - ret = mdiobus_register(new_bus); + ret = of_mdiobus_register(new_bus, ofdev->node); if (ret) goto out_free_irqs; diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h index 8300cab30f9a..51b793466ff3 100644 --- a/include/linux/fs_enet_pd.h +++ b/include/linux/fs_enet_pd.h @@ -17,6 +17,7 @@ #define FS_ENET_PD_H #include +#include #include #define FS_ENET_NAME "fs_enet" @@ -130,10 +131,7 @@ struct fs_platform_info { u32 device_flags; - int phy_addr; /* the phy address (-1 no phy) */ - char bus_id[16]; - int phy_irq; /* the phy irq (if it exists) */ - + struct device_node *phy_node; const struct fs_mii_bus_info *bus_info; int rx_ring, tx_ring; /* number of buffers on rx */ -- cgit v1.2.3 From 92744989533cbe85e8057935d230e128810168ce Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:39 +0000 Subject: net: add Xilinx ll_temac device driver This patch adds support for the Xilinx ll_temac 10/100/1000 Ethernet device. The ll_temac ipcore is typically used on Xilinx Virtex and Spartan designs attached to either a PowerPC 4xx or Microblaze processor. At the present moment, this driver only works with Virtex5 PowerPC designs because it assumes DCR is used to access the DMA registers. However, the low level access to DMA registers is abstracted and it should be easy to adapt for the other implementations. I'm posting this driver now as an RFC. There are still some things that need to be tightened up, but it does appear to be stable. Derived from driver code written by Yoshio Kashiwagi and David H. Lynch Jr. Tested on Xilinx ML507 eval board with Base System Builder generated FPGA design. Signed-off-by: Grant Likely Acked-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/Kconfig | 8 + drivers/net/Makefile | 2 + drivers/net/ll_temac.h | 374 +++++++++++++++++ drivers/net/ll_temac_main.c | 969 ++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ll_temac_mdio.c | 120 ++++++ 5 files changed, 1473 insertions(+) create mode 100644 drivers/net/ll_temac.h create mode 100644 drivers/net/ll_temac_main.c create mode 100644 drivers/net/ll_temac_mdio.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 214a92d1ef75..3320e7761576 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2362,6 +2362,14 @@ config MV643XX_ETH Some boards that use the Discovery chipset are the Momenco Ocelot C and Jaguar ATX and Pegasos II. +config XILINX_LL_TEMAC + tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" + select PHYLIB + depends on PPC_DCR_NATIVE + help + This driver supports the Xilinx 10/100/1000 LocalLink TEMAC + core used in Xilinx Spartan and Virtex FPGAs + config QLA3XXX tristate "QLogic QLA3XXX Network Driver Support" depends on PCI diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1fc4602a6ff2..80420f6d0795 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -134,6 +134,8 @@ obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o +ll_temac-objs := ll_temac_main.o ll_temac_mdio.o +obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o obj-$(CONFIG_QLA3XXX) += qla3xxx.o obj-$(CONFIG_QLGE) += qlge/ diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h new file mode 100644 index 000000000000..1af66a1e6911 --- /dev/null +++ b/drivers/net/ll_temac.h @@ -0,0 +1,374 @@ + +#ifndef XILINX_LL_TEMAC_H +#define XILINX_LL_TEMAC_H + +#include +#include +#include +#include +#include + +/* packet size info */ +#define XTE_HDR_SIZE 14 /* size of Ethernet header */ +#define XTE_TRL_SIZE 4 /* size of Ethernet trailer (FCS) */ +#define XTE_JUMBO_MTU 9000 +#define XTE_MAX_JUMBO_FRAME_SIZE (XTE_JUMBO_MTU + XTE_HDR_SIZE + XTE_TRL_SIZE) + +/* Configuration options */ + +/* Accept all incoming packets. + * This option defaults to disabled (cleared) */ +#define XTE_OPTION_PROMISC (1 << 0) +/* Jumbo frame support for Tx & Rx. + * This option defaults to disabled (cleared) */ +#define XTE_OPTION_JUMBO (1 << 1) +/* VLAN Rx & Tx frame support. + * This option defaults to disabled (cleared) */ +#define XTE_OPTION_VLAN (1 << 2) +/* Enable recognition of flow control frames on Rx + * This option defaults to enabled (set) */ +#define XTE_OPTION_FLOW_CONTROL (1 << 4) +/* Strip FCS and PAD from incoming frames. + * Note: PAD from VLAN frames is not stripped. + * This option defaults to disabled (set) */ +#define XTE_OPTION_FCS_STRIP (1 << 5) +/* Generate FCS field and add PAD automatically for outgoing frames. + * This option defaults to enabled (set) */ +#define XTE_OPTION_FCS_INSERT (1 << 6) +/* Enable Length/Type error checking for incoming frames. When this option is +set, the MAC will filter frames that have a mismatched type/length field +and if XTE_OPTION_REPORT_RXERR is set, the user is notified when these +types of frames are encountered. When this option is cleared, the MAC will +allow these types of frames to be received. +This option defaults to enabled (set) */ +#define XTE_OPTION_LENTYPE_ERR (1 << 7) +/* Enable the transmitter. + * This option defaults to enabled (set) */ +#define XTE_OPTION_TXEN (1 << 11) +/* Enable the receiver +* This option defaults to enabled (set) */ +#define XTE_OPTION_RXEN (1 << 12) + +/* Default options set when device is initialized or reset */ +#define XTE_OPTION_DEFAULTS \ + (XTE_OPTION_TXEN | \ + XTE_OPTION_FLOW_CONTROL | \ + XTE_OPTION_RXEN) + +/* XPS_LL_TEMAC SDMA registers definition */ + +#define TX_NXTDESC_PTR 0x00 /* r */ +#define TX_CURBUF_ADDR 0x01 /* r */ +#define TX_CURBUF_LENGTH 0x02 /* r */ +#define TX_CURDESC_PTR 0x03 /* rw */ +#define TX_TAILDESC_PTR 0x04 /* rw */ +#define TX_CHNL_CTRL 0x05 /* rw */ +/* + 0:7 24:31 IRQTimeout + 8:15 16:23 IRQCount + 16:20 11:15 Reserved + 21 10 0 + 22 9 UseIntOnEnd + 23 8 LdIRQCnt + 24 7 IRQEn + 25:28 3:6 Reserved + 29 2 IrqErrEn + 30 1 IrqDlyEn + 31 0 IrqCoalEn +*/ +#define CHNL_CTRL_IRQ_IOE (1 << 9) +#define CHNL_CTRL_IRQ_EN (1 << 7) +#define CHNL_CTRL_IRQ_ERR_EN (1 << 2) +#define CHNL_CTRL_IRQ_DLY_EN (1 << 1) +#define CHNL_CTRL_IRQ_COAL_EN (1 << 0) +#define TX_IRQ_REG 0x06 /* rw */ +/* + 0:7 24:31 DltTmrValue + 8:15 16:23 ClscCntrValue + 16:17 14:15 Reserved + 18:21 10:13 ClscCnt + 22:23 8:9 DlyCnt + 24:28 3::7 Reserved + 29 2 ErrIrq + 30 1 DlyIrq + 31 0 CoalIrq + */ +#define TX_CHNL_STS 0x07 /* r */ +/* + 0:9 22:31 Reserved + 10 21 TailPErr + 11 20 CmpErr + 12 19 AddrErr + 13 18 NxtPErr + 14 17 CurPErr + 15 16 BsyWr + 16:23 8:15 Reserved + 24 7 Error + 25 6 IOE + 26 5 SOE + 27 4 Cmplt + 28 3 SOP + 29 2 EOP + 30 1 EngBusy + 31 0 Reserved +*/ + +#define RX_NXTDESC_PTR 0x08 /* r */ +#define RX_CURBUF_ADDR 0x09 /* r */ +#define RX_CURBUF_LENGTH 0x0a /* r */ +#define RX_CURDESC_PTR 0x0b /* rw */ +#define RX_TAILDESC_PTR 0x0c /* rw */ +#define RX_CHNL_CTRL 0x0d /* rw */ +/* + 0:7 24:31 IRQTimeout + 8:15 16:23 IRQCount + 16:20 11:15 Reserved + 21 10 0 + 22 9 UseIntOnEnd + 23 8 LdIRQCnt + 24 7 IRQEn + 25:28 3:6 Reserved + 29 2 IrqErrEn + 30 1 IrqDlyEn + 31 0 IrqCoalEn + */ +#define RX_IRQ_REG 0x0e /* rw */ +#define IRQ_COAL (1 << 0) +#define IRQ_DLY (1 << 1) +#define IRQ_ERR (1 << 2) +#define IRQ_DMAERR (1 << 7) /* this is not documented ??? */ +/* + 0:7 24:31 DltTmrValue + 8:15 16:23 ClscCntrValue + 16:17 14:15 Reserved + 18:21 10:13 ClscCnt + 22:23 8:9 DlyCnt + 24:28 3::7 Reserved +*/ +#define RX_CHNL_STS 0x0f /* r */ +#define CHNL_STS_ENGBUSY (1 << 1) +#define CHNL_STS_EOP (1 << 2) +#define CHNL_STS_SOP (1 << 3) +#define CHNL_STS_CMPLT (1 << 4) +#define CHNL_STS_SOE (1 << 5) +#define CHNL_STS_IOE (1 << 6) +#define CHNL_STS_ERR (1 << 7) + +#define CHNL_STS_BSYWR (1 << 16) +#define CHNL_STS_CURPERR (1 << 17) +#define CHNL_STS_NXTPERR (1 << 18) +#define CHNL_STS_ADDRERR (1 << 19) +#define CHNL_STS_CMPERR (1 << 20) +#define CHNL_STS_TAILERR (1 << 21) +/* + 0:9 22:31 Reserved + 10 21 TailPErr + 11 20 CmpErr + 12 19 AddrErr + 13 18 NxtPErr + 14 17 CurPErr + 15 16 BsyWr + 16:23 8:15 Reserved + 24 7 Error + 25 6 IOE + 26 5 SOE + 27 4 Cmplt + 28 3 SOP + 29 2 EOP + 30 1 EngBusy + 31 0 Reserved +*/ + +#define DMA_CONTROL_REG 0x10 /* rw */ +#define DMA_CONTROL_RST (1 << 0) +#define DMA_TAIL_ENABLE (1 << 2) + +/* XPS_LL_TEMAC direct registers definition */ + +#define XTE_RAF0_OFFSET 0x00 +#define RAF0_RST (1 << 0) +#define RAF0_MCSTREJ (1 << 1) +#define RAF0_BCSTREJ (1 << 2) +#define XTE_TPF0_OFFSET 0x04 +#define XTE_IFGP0_OFFSET 0x08 +#define XTE_ISR0_OFFSET 0x0c +#define ISR0_HARDACSCMPLT (1 << 0) +#define ISR0_AUTONEG (1 << 1) +#define ISR0_RXCMPLT (1 << 2) +#define ISR0_RXREJ (1 << 3) +#define ISR0_RXFIFOOVR (1 << 4) +#define ISR0_TXCMPLT (1 << 5) +#define ISR0_RXDCMLCK (1 << 6) + +#define XTE_IPR0_OFFSET 0x10 +#define XTE_IER0_OFFSET 0x14 + +#define XTE_MSW0_OFFSET 0x20 +#define XTE_LSW0_OFFSET 0x24 +#define XTE_CTL0_OFFSET 0x28 +#define XTE_RDY0_OFFSET 0x2c + +#define XTE_RSE_MIIM_RR_MASK 0x0002 +#define XTE_RSE_MIIM_WR_MASK 0x0004 +#define XTE_RSE_CFG_RR_MASK 0x0020 +#define XTE_RSE_CFG_WR_MASK 0x0040 +#define XTE_RDY0_HARD_ACS_RDY_MASK (0x10000) + +/* XPS_LL_TEMAC indirect registers offset definition */ + +#define XTE_RXC0_OFFSET 0x00000200 /* Rx configuration word 0 */ +#define XTE_RXC1_OFFSET 0x00000240 /* Rx configuration word 1 */ +#define XTE_RXC1_RXRST_MASK (1 << 31) /* Receiver reset */ +#define XTE_RXC1_RXJMBO_MASK (1 << 30) /* Jumbo frame enable */ +#define XTE_RXC1_RXFCS_MASK (1 << 29) /* FCS not stripped */ +#define XTE_RXC1_RXEN_MASK (1 << 28) /* Receiver enable */ +#define XTE_RXC1_RXVLAN_MASK (1 << 27) /* VLAN enable */ +#define XTE_RXC1_RXHD_MASK (1 << 26) /* Half duplex */ +#define XTE_RXC1_RXLT_MASK (1 << 25) /* Length/type check disable */ + +#define XTE_TXC_OFFSET 0x00000280 /* Tx configuration */ +#define XTE_TXC_TXRST_MASK (1 << 31) /* Transmitter reset */ +#define XTE_TXC_TXJMBO_MASK (1 << 30) /* Jumbo frame enable */ +#define XTE_TXC_TXFCS_MASK (1 << 29) /* Generate FCS */ +#define XTE_TXC_TXEN_MASK (1 << 28) /* Transmitter enable */ +#define XTE_TXC_TXVLAN_MASK (1 << 27) /* VLAN enable */ +#define XTE_TXC_TXHD_MASK (1 << 26) /* Half duplex */ + +#define XTE_FCC_OFFSET 0x000002C0 /* Flow control config */ +#define XTE_FCC_RXFLO_MASK (1 << 29) /* Rx flow control enable */ +#define XTE_FCC_TXFLO_MASK (1 << 30) /* Tx flow control enable */ + +#define XTE_EMCFG_OFFSET 0x00000300 /* EMAC configuration */ +#define XTE_EMCFG_LINKSPD_MASK 0xC0000000 /* Link speed */ +#define XTE_EMCFG_HOSTEN_MASK (1 << 26) /* Host interface enable */ +#define XTE_EMCFG_LINKSPD_10 0x00000000 /* 10 Mbit LINKSPD_MASK */ +#define XTE_EMCFG_LINKSPD_100 (1 << 30) /* 100 Mbit LINKSPD_MASK */ +#define XTE_EMCFG_LINKSPD_1000 (1 << 31) /* 1000 Mbit LINKSPD_MASK */ + +#define XTE_GMIC_OFFSET 0x00000320 /* RGMII/SGMII config */ +#define XTE_MC_OFFSET 0x00000340 /* MDIO configuration */ +#define XTE_UAW0_OFFSET 0x00000380 /* Unicast address word 0 */ +#define XTE_UAW1_OFFSET 0x00000384 /* Unicast address word 1 */ + +#define XTE_MAW0_OFFSET 0x00000388 /* Multicast addr word 0 */ +#define XTE_MAW1_OFFSET 0x0000038C /* Multicast addr word 1 */ +#define XTE_AFM_OFFSET 0x00000390 /* Promiscuous mode */ +#define XTE_AFM_EPPRM_MASK (1 << 31) /* Promiscuous mode enable */ + +/* Interrupt Request status */ +#define XTE_TIS_OFFSET 0x000003A0 +#define TIS_FRIS (1 << 0) +#define TIS_MRIS (1 << 1) +#define TIS_MWIS (1 << 2) +#define TIS_ARIS (1 << 3) +#define TIS_AWIS (1 << 4) +#define TIS_CRIS (1 << 5) +#define TIS_CWIS (1 << 6) + +#define XTE_TIE_OFFSET 0x000003A4 /* Interrupt enable */ + +/** MII Mamagement Control register (MGTCR) */ +#define XTE_MGTDR_OFFSET 0x000003B0 /* MII data */ +#define XTE_MIIMAI_OFFSET 0x000003B4 /* MII control */ + +#define CNTLREG_WRITE_ENABLE_MASK 0x8000 +#define CNTLREG_EMAC1SEL_MASK 0x0400 +#define CNTLREG_ADDRESSCODE_MASK 0x03ff + +/* CDMAC descriptor status bit definitions */ + +#define STS_CTRL_APP0_ERR (1 << 31) +#define STS_CTRL_APP0_IRQONEND (1 << 30) +/* undoccumented */ +#define STS_CTRL_APP0_STOPONEND (1 << 29) +#define STS_CTRL_APP0_CMPLT (1 << 28) +#define STS_CTRL_APP0_SOP (1 << 27) +#define STS_CTRL_APP0_EOP (1 << 26) +#define STS_CTRL_APP0_ENGBUSY (1 << 25) +/* undocumented */ +#define STS_CTRL_APP0_ENGRST (1 << 24) + +#define TX_CONTROL_CALC_CSUM_MASK 1 + +#define XTE_ALIGN 32 +#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN) + +#define MULTICAST_CAM_TABLE_NUM 4 + +/* TX/RX CURDESC_PTR points to first descriptor */ +/* TX/RX TAILDESC_PTR points to last descriptor in linked list */ + +/** + * struct cdmac_bd - LocalLink buffer descriptor format + * + * app0 bits: + * 0 Error + * 1 IrqOnEnd generate an interrupt at completion of DMA op + * 2 reserved + * 3 completed Current descriptor completed + * 4 SOP TX - marks first desc/ RX marks first desct + * 5 EOP TX marks last desc/RX marks last desc + * 6 EngBusy DMA is processing + * 7 reserved + * 8:31 application specific + */ +struct cdmac_bd { + u32 next; /* Physical address of next buffer descriptor */ + u32 phys; + u32 len; + u32 app0; + u32 app1; /* TX start << 16 | insert */ + u32 app2; /* TX csum */ + u32 app3; + u32 app4; /* skb for TX length for RX */ +}; + +struct temac_local { + struct net_device *ndev; + struct device *dev; + + /* Connection to PHY device */ + struct phy_device *phy_dev; /* Pointer to PHY device */ + struct device_node *phy_node; + + /* MDIO bus data */ + struct mii_bus *mii_bus; /* MII bus reference */ + int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ + + /* IO registers and IRQs */ + void __iomem *regs; + dcr_host_t sdma_dcrs; + int tx_irq; + int rx_irq; + int emac_num; + + struct sk_buff **rx_skb; + spinlock_t rx_lock; + struct mutex indirect_mutex; + u32 options; /* Current options word */ + int last_link; + + /* Buffer descriptors */ + struct cdmac_bd *tx_bd_v; + dma_addr_t tx_bd_p; + struct cdmac_bd *rx_bd_v; + dma_addr_t rx_bd_p; + int tx_bd_ci; + int tx_bd_next; + int tx_bd_tail; + int rx_bd_ci; +}; + +/* xilinx_temac.c */ +u32 temac_ior(struct temac_local *lp, int offset); +void temac_iow(struct temac_local *lp, int offset, u32 value); +int temac_indirect_busywait(struct temac_local *lp); +u32 temac_indirect_in32(struct temac_local *lp, int reg); +void temac_indirect_out32(struct temac_local *lp, int reg, u32 value); + + +/* xilinx_temac_mdio.c */ +int temac_mdio_setup(struct temac_local *lp, struct device_node *np); +void temac_mdio_teardown(struct temac_local *lp); + +#endif /* XILINX_LL_TEMAC_H */ diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c new file mode 100644 index 000000000000..96e7248876c1 --- /dev/null +++ b/drivers/net/ll_temac_main.c @@ -0,0 +1,969 @@ +/* + * Driver for Xilinx TEMAC Ethernet device + * + * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi + * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. + * Copyright (c) 2008-2009 Secret Lab Technologies Ltd. + * + * This is a driver for the Xilinx ll_temac ipcore which is often used + * in the Virtex and Spartan series of chips. + * + * Notes: + * - The ll_temac hardware uses indirect access for many of the TEMAC + * registers, include the MDIO bus. However, indirect access to MDIO + * registers take considerably more clock cycles than to TEMAC registers. + * MDIO accesses are long, so threads doing them should probably sleep + * rather than busywait. However, since only one indirect access can be + * in progress at any given time, that means that *all* indirect accesses + * could end up sleeping (to wait for an MDIO access to complete). + * Fortunately none of the indirect accesses are on the 'hot' path for tx + * or rx, so this should be okay. + * + * TODO: + * - Fix driver to work on more than just Virtex5. Right now the driver + * assumes that the locallink DMA registers are accessed via DCR + * instructions. + * - Factor out locallink DMA code into separate driver + * - Fix multicast assignment. + * - Fix support for hardware checksumming. + * - Testing. Lots and lots of testing. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* needed for sizeof(tcphdr) */ +#include /* needed for sizeof(udphdr) */ +#include +#include +#include +#include + +#include "ll_temac.h" + +#define TX_BD_NUM 64 +#define RX_BD_NUM 128 + +/* --------------------------------------------------------------------- + * Low level register access functions + */ + +u32 temac_ior(struct temac_local *lp, int offset) +{ + return in_be32((u32 *)(lp->regs + offset)); +} + +void temac_iow(struct temac_local *lp, int offset, u32 value) +{ + out_be32((u32 *) (lp->regs + offset), value); +} + +int temac_indirect_busywait(struct temac_local *lp) +{ + long end = jiffies + 2; + + while (!(temac_ior(lp, XTE_RDY0_OFFSET) & XTE_RDY0_HARD_ACS_RDY_MASK)) { + if (end - jiffies <= 0) { + WARN_ON(1); + return -ETIMEDOUT; + } + msleep(1); + } + return 0; +} + +/** + * temac_indirect_in32 + * + * lp->indirect_mutex must be held when calling this function + */ +u32 temac_indirect_in32(struct temac_local *lp, int reg) +{ + u32 val; + + if (temac_indirect_busywait(lp)) + return -ETIMEDOUT; + temac_iow(lp, XTE_CTL0_OFFSET, reg); + if (temac_indirect_busywait(lp)) + return -ETIMEDOUT; + val = temac_ior(lp, XTE_LSW0_OFFSET); + + return val; +} + +/** + * temac_indirect_out32 + * + * lp->indirect_mutex must be held when calling this function + */ +void temac_indirect_out32(struct temac_local *lp, int reg, u32 value) +{ + if (temac_indirect_busywait(lp)) + return; + temac_iow(lp, XTE_LSW0_OFFSET, value); + temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg); +} + +static u32 temac_dma_in32(struct temac_local *lp, int reg) +{ + return dcr_read(lp->sdma_dcrs, reg); +} + +static void temac_dma_out32(struct temac_local *lp, int reg, u32 value) +{ + dcr_write(lp->sdma_dcrs, reg, value); +} + +/** + * temac_dma_bd_init - Setup buffer descriptor rings + */ +static int temac_dma_bd_init(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct sk_buff *skb; + int i; + + lp->rx_skb = kzalloc(sizeof(struct sk_buff)*RX_BD_NUM, GFP_KERNEL); + /* allocate the tx and rx ring buffer descriptors. */ + /* returns a virtual addres and a physical address. */ + lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * TX_BD_NUM, + &lp->tx_bd_p, GFP_KERNEL); + lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * RX_BD_NUM, + &lp->rx_bd_p, GFP_KERNEL); + + memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM); + for (i = 0; i < TX_BD_NUM; i++) { + lp->tx_bd_v[i].next = lp->tx_bd_p + + sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM); + } + + memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM); + for (i = 0; i < RX_BD_NUM; i++) { + lp->rx_bd_v[i].next = lp->rx_bd_p + + sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM); + + skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + + XTE_ALIGN, GFP_ATOMIC); + if (skb == 0) { + dev_err(&ndev->dev, "alloc_skb error %d\n", i); + return -1; + } + lp->rx_skb[i] = skb; + skb_reserve(skb, BUFFER_ALIGN(skb->data)); + /* returns physical address of skb->data */ + lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, + skb->data, + XTE_MAX_JUMBO_FRAME_SIZE, + DMA_FROM_DEVICE); + lp->rx_bd_v[i].len = XTE_MAX_JUMBO_FRAME_SIZE; + lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND; + } + + temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 | + CHNL_CTRL_IRQ_EN | + CHNL_CTRL_IRQ_DLY_EN | + CHNL_CTRL_IRQ_COAL_EN); + /* 0x10220483 */ + /* 0x00100483 */ + temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 | + CHNL_CTRL_IRQ_EN | + CHNL_CTRL_IRQ_DLY_EN | + CHNL_CTRL_IRQ_COAL_EN | + CHNL_CTRL_IRQ_IOE); + /* 0xff010283 */ + + temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p); + temac_dma_out32(lp, RX_TAILDESC_PTR, + lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); + temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p); + + return 0; +} + +/* --------------------------------------------------------------------- + * net_device_ops + */ + +static int temac_set_mac_address(struct net_device *ndev, void *address) +{ + struct temac_local *lp = netdev_priv(ndev); + + if (address) + memcpy(ndev->dev_addr, address, ETH_ALEN); + + if (!is_valid_ether_addr(ndev->dev_addr)) + random_ether_addr(ndev->dev_addr); + + /* set up unicast MAC address filter set its mac address */ + mutex_lock(&lp->indirect_mutex); + temac_indirect_out32(lp, XTE_UAW0_OFFSET, + (ndev->dev_addr[0]) | + (ndev->dev_addr[1] << 8) | + (ndev->dev_addr[2] << 16) | + (ndev->dev_addr[3] << 24)); + /* There are reserved bits in EUAW1 + * so don't affect them Set MAC bits [47:32] in EUAW1 */ + temac_indirect_out32(lp, XTE_UAW1_OFFSET, + (ndev->dev_addr[4] & 0x000000ff) | + (ndev->dev_addr[5] << 8)); + mutex_unlock(&lp->indirect_mutex); + + return 0; +} + +static void temac_set_multicast_list(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + u32 multi_addr_msw, multi_addr_lsw, val; + int i; + + mutex_lock(&lp->indirect_mutex); + if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) + || ndev->mc_count > MULTICAST_CAM_TABLE_NUM) { + /* + * We must make the kernel realise we had to move + * into promisc mode or we start all out war on + * the cable. If it was a promisc request the + * flag is already set. If not we assert it. + */ + ndev->flags |= IFF_PROMISC; + temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); + dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); + } else if (ndev->mc_count) { + struct dev_mc_list *mclist = ndev->mc_list; + for (i = 0; mclist && i < ndev->mc_count; i++) { + + if (i >= MULTICAST_CAM_TABLE_NUM) + break; + multi_addr_msw = ((mclist->dmi_addr[3] << 24) | + (mclist->dmi_addr[2] << 16) | + (mclist->dmi_addr[1] << 8) | + (mclist->dmi_addr[0])); + temac_indirect_out32(lp, XTE_MAW0_OFFSET, + multi_addr_msw); + multi_addr_lsw = ((mclist->dmi_addr[5] << 8) | + (mclist->dmi_addr[4]) | (i << 16)); + temac_indirect_out32(lp, XTE_MAW1_OFFSET, + multi_addr_lsw); + mclist = mclist->next; + } + } else { + val = temac_indirect_in32(lp, XTE_AFM_OFFSET); + temac_indirect_out32(lp, XTE_AFM_OFFSET, + val & ~XTE_AFM_EPPRM_MASK); + temac_indirect_out32(lp, XTE_MAW0_OFFSET, 0); + temac_indirect_out32(lp, XTE_MAW1_OFFSET, 0); + dev_info(&ndev->dev, "Promiscuous mode disabled.\n"); + } + mutex_unlock(&lp->indirect_mutex); +} + +struct temac_option { + int flg; + u32 opt; + u32 reg; + u32 m_or; + u32 m_and; +} temac_options[] = { + /* Turn on jumbo packet support for both Rx and Tx */ + { + .opt = XTE_OPTION_JUMBO, + .reg = XTE_TXC_OFFSET, + .m_or = XTE_TXC_TXJMBO_MASK, + }, + { + .opt = XTE_OPTION_JUMBO, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXJMBO_MASK, + }, + /* Turn on VLAN packet support for both Rx and Tx */ + { + .opt = XTE_OPTION_VLAN, + .reg = XTE_TXC_OFFSET, + .m_or =XTE_TXC_TXVLAN_MASK, + }, + { + .opt = XTE_OPTION_VLAN, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXVLAN_MASK, + }, + /* Turn on FCS stripping on receive packets */ + { + .opt = XTE_OPTION_FCS_STRIP, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXFCS_MASK, + }, + /* Turn on FCS insertion on transmit packets */ + { + .opt = XTE_OPTION_FCS_INSERT, + .reg = XTE_TXC_OFFSET, + .m_or =XTE_TXC_TXFCS_MASK, + }, + /* Turn on length/type field checking on receive packets */ + { + .opt = XTE_OPTION_LENTYPE_ERR, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXLT_MASK, + }, + /* Turn on flow control */ + { + .opt = XTE_OPTION_FLOW_CONTROL, + .reg = XTE_FCC_OFFSET, + .m_or =XTE_FCC_RXFLO_MASK, + }, + /* Turn on flow control */ + { + .opt = XTE_OPTION_FLOW_CONTROL, + .reg = XTE_FCC_OFFSET, + .m_or =XTE_FCC_TXFLO_MASK, + }, + /* Turn on promiscuous frame filtering (all frames are received ) */ + { + .opt = XTE_OPTION_PROMISC, + .reg = XTE_AFM_OFFSET, + .m_or =XTE_AFM_EPPRM_MASK, + }, + /* Enable transmitter if not already enabled */ + { + .opt = XTE_OPTION_TXEN, + .reg = XTE_TXC_OFFSET, + .m_or =XTE_TXC_TXEN_MASK, + }, + /* Enable receiver? */ + { + .opt = XTE_OPTION_RXEN, + .reg = XTE_RXC1_OFFSET, + .m_or =XTE_RXC1_RXEN_MASK, + }, + {} +}; + +/** + * temac_setoptions + */ +static u32 temac_setoptions(struct net_device *ndev, u32 options) +{ + struct temac_local *lp = netdev_priv(ndev); + struct temac_option *tp = &temac_options[0]; + int reg; + + mutex_lock(&lp->indirect_mutex); + while (tp->opt) { + reg = temac_indirect_in32(lp, tp->reg) & ~tp->m_or; + if (options & tp->opt) + reg |= tp->m_or; + temac_indirect_out32(lp, tp->reg, reg); + tp++; + } + lp->options |= options; + mutex_unlock(&lp->indirect_mutex); + + return (0); +} + +/* Initilize temac */ +static void temac_device_reset(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + u32 timeout; + u32 val; + + /* Perform a software reset */ + + /* 0x300 host enable bit ? */ + /* reset PHY through control register ?:1 */ + + dev_dbg(&ndev->dev, "%s()\n", __func__); + + mutex_lock(&lp->indirect_mutex); + /* Reset the receiver and wait for it to finish reset */ + temac_indirect_out32(lp, XTE_RXC1_OFFSET, XTE_RXC1_RXRST_MASK); + timeout = 1000; + while (temac_indirect_in32(lp, XTE_RXC1_OFFSET) & XTE_RXC1_RXRST_MASK) { + udelay(1); + if (--timeout == 0) { + dev_err(&ndev->dev, + "temac_device_reset RX reset timeout!!\n"); + break; + } + } + + /* Reset the transmitter and wait for it to finish reset */ + temac_indirect_out32(lp, XTE_TXC_OFFSET, XTE_TXC_TXRST_MASK); + timeout = 1000; + while (temac_indirect_in32(lp, XTE_TXC_OFFSET) & XTE_TXC_TXRST_MASK) { + udelay(1); + if (--timeout == 0) { + dev_err(&ndev->dev, + "temac_device_reset TX reset timeout!!\n"); + break; + } + } + + /* Disable the receiver */ + val = temac_indirect_in32(lp, XTE_RXC1_OFFSET); + temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK); + + /* Reset Local Link (DMA) */ + temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST); + timeout = 1000; + while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) { + udelay(1); + if (--timeout == 0) { + dev_err(&ndev->dev, + "temac_device_reset DMA reset timeout!!\n"); + break; + } + } + temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); + + temac_dma_bd_init(ndev); + + temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0); + temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0); + temac_indirect_out32(lp, XTE_TXC_OFFSET, 0); + temac_indirect_out32(lp, XTE_FCC_OFFSET, XTE_FCC_RXFLO_MASK); + + mutex_unlock(&lp->indirect_mutex); + + /* Sync default options with HW + * but leave receiver and transmitter disabled. */ + temac_setoptions(ndev, + lp->options & ~(XTE_OPTION_TXEN | XTE_OPTION_RXEN)); + + temac_set_mac_address(ndev, NULL); + + /* Set address filter table */ + temac_set_multicast_list(ndev); + if (temac_setoptions(ndev, lp->options)) + dev_err(&ndev->dev, "Error setting TEMAC options\n"); + + /* Init Driver variable */ + ndev->trans_start = 0; +} + +void temac_adjust_link(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct phy_device *phy = lp->phy_dev; + u32 mii_speed; + int link_state; + + /* hash together the state values to decide if something has changed */ + link_state = phy->speed | (phy->duplex << 1) | phy->link; + + mutex_lock(&lp->indirect_mutex); + if (lp->last_link != link_state) { + mii_speed = temac_indirect_in32(lp, XTE_EMCFG_OFFSET); + mii_speed &= ~XTE_EMCFG_LINKSPD_MASK; + + switch (phy->speed) { + case SPEED_1000: mii_speed |= XTE_EMCFG_LINKSPD_1000; break; + case SPEED_100: mii_speed |= XTE_EMCFG_LINKSPD_100; break; + case SPEED_10: mii_speed |= XTE_EMCFG_LINKSPD_10; break; + } + + /* Write new speed setting out to TEMAC */ + temac_indirect_out32(lp, XTE_EMCFG_OFFSET, mii_speed); + lp->last_link = link_state; + phy_print_status(phy); + } + mutex_unlock(&lp->indirect_mutex); +} + +static void temac_start_xmit_done(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct cdmac_bd *cur_p; + unsigned int stat = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; + stat = cur_p->app0; + + while (stat & STS_CTRL_APP0_CMPLT) { + dma_unmap_single(ndev->dev.parent, cur_p->phys, cur_p->len, + DMA_TO_DEVICE); + if (cur_p->app4) + dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); + cur_p->app0 = 0; + + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += cur_p->len; + + lp->tx_bd_ci++; + if (lp->tx_bd_ci >= TX_BD_NUM) + lp->tx_bd_ci = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; + stat = cur_p->app0; + } + + netif_wake_queue(ndev); +} + +static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct cdmac_bd *cur_p; + dma_addr_t start_p, tail_p; + int ii; + unsigned long num_frag; + skb_frag_t *frag; + + num_frag = skb_shinfo(skb)->nr_frags; + frag = &skb_shinfo(skb)->frags[0]; + start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + + if (cur_p->app0 & STS_CTRL_APP0_CMPLT) { + if (!netif_queue_stopped(ndev)) { + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; + } + return NETDEV_TX_BUSY; + } + + cur_p->app0 = 0; + if (skb->ip_summed == CHECKSUM_PARTIAL) { + const struct iphdr *ip = ip_hdr(skb); + int length = 0, start = 0, insert = 0; + + switch (ip->protocol) { + case IPPROTO_TCP: + start = sizeof(struct iphdr) + ETH_HLEN; + insert = sizeof(struct iphdr) + ETH_HLEN + 16; + length = ip->tot_len - sizeof(struct iphdr); + break; + case IPPROTO_UDP: + start = sizeof(struct iphdr) + ETH_HLEN; + insert = sizeof(struct iphdr) + ETH_HLEN + 6; + length = ip->tot_len - sizeof(struct iphdr); + break; + default: + break; + } + cur_p->app1 = ((start << 16) | insert); + cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr, + length, ip->protocol, 0); + skb->data[insert] = 0; + skb->data[insert + 1] = 0; + } + cur_p->app0 |= STS_CTRL_APP0_SOP; + cur_p->len = skb_headlen(skb); + cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len, + DMA_TO_DEVICE); + cur_p->app4 = (unsigned long)skb; + + for (ii = 0; ii < num_frag; ii++) { + lp->tx_bd_tail++; + if (lp->tx_bd_tail >= TX_BD_NUM) + lp->tx_bd_tail = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + cur_p->phys = dma_map_single(ndev->dev.parent, + (void *)page_address(frag->page) + + frag->page_offset, + frag->size, DMA_TO_DEVICE); + cur_p->len = frag->size; + cur_p->app0 = 0; + frag++; + } + cur_p->app0 |= STS_CTRL_APP0_EOP; + + tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; + lp->tx_bd_tail++; + if (lp->tx_bd_tail >= TX_BD_NUM) + lp->tx_bd_tail = 0; + + /* Kick off the transfer */ + temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ + + return 0; +} + + +static void ll_temac_recv(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + struct sk_buff *skb, *new_skb; + unsigned int bdstat; + struct cdmac_bd *cur_p; + dma_addr_t tail_p; + int length; + unsigned long skb_vaddr; + unsigned long flags; + + spin_lock_irqsave(&lp->rx_lock, flags); + + tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + + bdstat = cur_p->app0; + while ((bdstat & STS_CTRL_APP0_CMPLT)) { + + skb = lp->rx_skb[lp->rx_bd_ci]; + length = cur_p->app4; + + skb_vaddr = virt_to_bus(skb->data); + dma_unmap_single(ndev->dev.parent, skb_vaddr, length, + DMA_FROM_DEVICE); + + skb_put(skb, length); + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + netif_rx(skb); + + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += length; + + new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN, + GFP_ATOMIC); + if (new_skb == 0) { + dev_err(&ndev->dev, "no memory for new sk_buff\n"); + spin_unlock_irqrestore(&lp->rx_lock, flags); + return; + } + + skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data)); + + cur_p->app0 = STS_CTRL_APP0_IRQONEND; + cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data, + XTE_MAX_JUMBO_FRAME_SIZE, + DMA_FROM_DEVICE); + cur_p->len = XTE_MAX_JUMBO_FRAME_SIZE; + lp->rx_skb[lp->rx_bd_ci] = new_skb; + + lp->rx_bd_ci++; + if (lp->rx_bd_ci >= RX_BD_NUM) + lp->rx_bd_ci = 0; + + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + bdstat = cur_p->app0; + } + temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p); + + spin_unlock_irqrestore(&lp->rx_lock, flags); +} + +static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) +{ + struct net_device *ndev = _ndev; + struct temac_local *lp = netdev_priv(ndev); + unsigned int status; + + status = temac_dma_in32(lp, TX_IRQ_REG); + temac_dma_out32(lp, TX_IRQ_REG, status); + + if (status & (IRQ_COAL | IRQ_DLY)) + temac_start_xmit_done(lp->ndev); + if (status & 0x080) + dev_err(&ndev->dev, "DMA error 0x%x\n", status); + + return IRQ_HANDLED; +} + +static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev) +{ + struct net_device *ndev = _ndev; + struct temac_local *lp = netdev_priv(ndev); + unsigned int status; + + /* Read and clear the status registers */ + status = temac_dma_in32(lp, RX_IRQ_REG); + temac_dma_out32(lp, RX_IRQ_REG, status); + + if (status & (IRQ_COAL | IRQ_DLY)) + ll_temac_recv(lp->ndev); + + return IRQ_HANDLED; +} + +static int temac_open(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + int rc; + + dev_dbg(&ndev->dev, "temac_open()\n"); + + if (lp->phy_node) { + lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node, + temac_adjust_link, 0, 0); + if (!lp->phy_dev) { + dev_err(lp->dev, "of_phy_connect() failed\n"); + return -ENODEV; + } + + phy_start(lp->phy_dev); + } + + rc = request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->name, ndev); + if (rc) + goto err_tx_irq; + rc = request_irq(lp->rx_irq, ll_temac_rx_irq, 0, ndev->name, ndev); + if (rc) + goto err_rx_irq; + + temac_device_reset(ndev); + return 0; + + err_rx_irq: + free_irq(lp->tx_irq, ndev); + err_tx_irq: + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + dev_err(lp->dev, "request_irq() failed\n"); + return rc; +} + +static int temac_stop(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + + dev_dbg(&ndev->dev, "temac_close()\n"); + + free_irq(lp->tx_irq, ndev); + free_irq(lp->rx_irq, ndev); + + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +temac_poll_controller(struct net_device *ndev) +{ + struct temac_local *lp = netdev_priv(ndev); + + disable_irq(lp->tx_irq); + disable_irq(lp->rx_irq); + + ll_temac_rx_irq(lp->tx_irq, lp); + ll_temac_tx_irq(lp->rx_irq, lp); + + enable_irq(lp->tx_irq); + enable_irq(lp->rx_irq); +} +#endif + +static const struct net_device_ops temac_netdev_ops = { + .ndo_open = temac_open, + .ndo_stop = temac_stop, + .ndo_start_xmit = temac_start_xmit, + .ndo_set_mac_address = temac_set_mac_address, + //.ndo_set_multicast_list = temac_set_multicast_list, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = temac_poll_controller, +#endif +}; + +/* --------------------------------------------------------------------- + * SYSFS device attributes + */ +static ssize_t temac_show_llink_regs(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct temac_local *lp = netdev_priv(ndev); + int i, len = 0; + + for (i = 0; i < 0x11; i++) + len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i), + (i % 8) == 7 ? "\n" : " "); + len += sprintf(buf + len, "\n"); + + return len; +} + +static DEVICE_ATTR(llink_regs, 0440, temac_show_llink_regs, NULL); + +static struct attribute *temac_device_attrs[] = { + &dev_attr_llink_regs.attr, + NULL, +}; + +static const struct attribute_group temac_attr_group = { + .attrs = temac_device_attrs, +}; + +static int __init +temac_of_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *np; + struct temac_local *lp; + struct net_device *ndev; + const void *addr; + int size, rc = 0; + unsigned int dcrs; + + /* Init network device structure */ + ndev = alloc_etherdev(sizeof(*lp)); + if (!ndev) { + dev_err(&op->dev, "could not allocate device.\n"); + return -ENOMEM; + } + ether_setup(ndev); + dev_set_drvdata(&op->dev, ndev); + SET_NETDEV_DEV(ndev, &op->dev); + ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ + ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->netdev_ops = &temac_netdev_ops; +#if 0 + ndev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4. */ + ndev->features |= NETIF_F_HW_CSUM; /* Can checksum all the packets. */ + ndev->features |= NETIF_F_IPV6_CSUM; /* Can checksum IPV6 TCP/UDP */ + ndev->features |= NETIF_F_HIGHDMA; /* Can DMA to high memory. */ + ndev->features |= NETIF_F_HW_VLAN_TX; /* Transmit VLAN hw accel */ + ndev->features |= NETIF_F_HW_VLAN_RX; /* Receive VLAN hw acceleration */ + ndev->features |= NETIF_F_HW_VLAN_FILTER; /* Receive VLAN filtering */ + ndev->features |= NETIF_F_VLAN_CHALLENGED; /* cannot handle VLAN pkts */ + ndev->features |= NETIF_F_GSO; /* Enable software GSO. */ + ndev->features |= NETIF_F_MULTI_QUEUE; /* Has multiple TX/RX queues */ + ndev->features |= NETIF_F_LRO; /* large receive offload */ +#endif + + /* setup temac private info structure */ + lp = netdev_priv(ndev); + lp->ndev = ndev; + lp->dev = &op->dev; + lp->options = XTE_OPTION_DEFAULTS; + spin_lock_init(&lp->rx_lock); + mutex_init(&lp->indirect_mutex); + + /* map device registers */ + lp->regs = of_iomap(op->node, 0); + if (!lp->regs) { + dev_err(&op->dev, "could not map temac regs.\n"); + goto nodev; + } + + /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ + np = of_parse_phandle(op->node, "llink-connected", 0); + if (!np) { + dev_err(&op->dev, "could not find DMA node\n"); + goto nodev; + } + + dcrs = dcr_resource_start(np, 0); + if (dcrs == 0) { + dev_err(&op->dev, "could not get DMA register address\n"); + goto nodev;; + } + lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0)); + dev_dbg(&op->dev, "DCR base: %x\n", dcrs); + + lp->rx_irq = irq_of_parse_and_map(np, 0); + lp->tx_irq = irq_of_parse_and_map(np, 1); + if (!lp->rx_irq || !lp->tx_irq) { + dev_err(&op->dev, "could not determine irqs\n"); + rc = -ENOMEM; + goto nodev; + } + + of_node_put(np); /* Finished with the DMA node; drop the reference */ + + /* Retrieve the MAC address */ + addr = of_get_property(op->node, "local-mac-address", &size); + if ((!addr) || (size != 6)) { + dev_err(&op->dev, "could not find MAC address\n"); + rc = -ENODEV; + goto nodev; + } + temac_set_mac_address(ndev, (void *)addr); + + rc = temac_mdio_setup(lp, op->node); + if (rc) + dev_warn(&op->dev, "error registering MDIO bus\n"); + + lp->phy_node = of_parse_phandle(op->node, "phy-handle", 0); + if (lp->phy_node) + dev_dbg(lp->dev, "using PHY node %s (%p)\n", np->full_name, np); + + /* Add the device attributes */ + rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group); + if (rc) { + dev_err(lp->dev, "Error creating sysfs files\n"); + goto nodev; + } + + rc = register_netdev(lp->ndev); + if (rc) { + dev_err(lp->dev, "register_netdev() error (%i)\n", rc); + goto err_register_ndev; + } + + return 0; + + err_register_ndev: + sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); + nodev: + free_netdev(ndev); + ndev = NULL; + return rc; +} + +static int __devexit temac_of_remove(struct of_device *op) +{ + struct net_device *ndev = dev_get_drvdata(&op->dev); + struct temac_local *lp = netdev_priv(ndev); + + temac_mdio_teardown(lp); + unregister_netdev(ndev); + sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); + if (lp->phy_node) + of_node_put(lp->phy_node); + lp->phy_node = NULL; + dev_set_drvdata(&op->dev, NULL); + free_netdev(ndev); + return 0; +} + +static struct of_device_id temac_of_match[] __devinitdata = { + { .compatible = "xlnx,xps-ll-temac-1.01.b", }, + {}, +}; +MODULE_DEVICE_TABLE(of, temac_of_match); + +static struct of_platform_driver temac_of_driver = { + .match_table = temac_of_match, + .probe = temac_of_probe, + .remove = __devexit_p(temac_of_remove), + .driver = { + .owner = THIS_MODULE, + .name = "xilinx_temac", + }, +}; + +static int __init temac_init(void) +{ + return of_register_platform_driver(&temac_of_driver); +} +module_init(temac_init); + +static void __exit temac_exit(void) +{ + of_unregister_platform_driver(&temac_of_driver); +} +module_exit(temac_exit); + +MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver"); +MODULE_AUTHOR("Yoshio Kashiwagi"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c new file mode 100644 index 000000000000..da0e462308d5 --- /dev/null +++ b/drivers/net/ll_temac_mdio.c @@ -0,0 +1,120 @@ +/* + * MDIO bus driver for the Xilinx TEMAC device + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ll_temac.h" + +/* --------------------------------------------------------------------- + * MDIO Bus functions + */ +static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + struct temac_local *lp = bus->priv; + u32 rc; + + /* Write the PHY address to the MIIM Access Initiator register. + * When the transfer completes, the PHY register value will appear + * in the LSW0 register */ + mutex_lock(&lp->indirect_mutex); + temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg); + rc = temac_indirect_in32(lp, XTE_MIIMAI_OFFSET); + mutex_unlock(&lp->indirect_mutex); + + dev_dbg(lp->dev, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n", + phy_id, reg, rc); + + return rc; +} + +static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val) +{ + struct temac_local *lp = bus->priv; + + dev_dbg(lp->dev, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n", + phy_id, reg, val); + + /* First write the desired value into the write data register + * and then write the address into the access initiator register + */ + mutex_lock(&lp->indirect_mutex); + temac_indirect_out32(lp, XTE_MGTDR_OFFSET, val); + temac_indirect_out32(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) | reg); + mutex_unlock(&lp->indirect_mutex); + + return 0; +} + +int temac_mdio_setup(struct temac_local *lp, struct device_node *np) +{ + struct mii_bus *bus; + const u32 *bus_hz; + int clk_div; + int rc, size; + struct resource res; + + /* Calculate a reasonable divisor for the clock rate */ + clk_div = 0x3f; /* worst-case default setting */ + bus_hz = of_get_property(np, "clock-frequency", &size); + if (bus_hz && size >= sizeof(*bus_hz)) { + clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1; + if (clk_div < 1) + clk_div = 1; + if (clk_div > 0x3f) + clk_div = 0x3f; + } + + /* Enable the MDIO bus by asserting the enable bit and writing + * in the clock config */ + mutex_lock(&lp->indirect_mutex); + temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div); + mutex_unlock(&lp->indirect_mutex); + + bus = mdiobus_alloc(); + if (!bus) + return -ENOMEM; + + of_address_to_resource(np, 0, &res); + snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", + (unsigned long long)res.start); + bus->priv = lp; + bus->name = "Xilinx TEMAC MDIO"; + bus->read = temac_mdio_read; + bus->write = temac_mdio_write; + bus->parent = lp->dev; + bus->irq = lp->mdio_irqs; /* preallocated IRQ table */ + + lp->mii_bus = bus; + + rc = of_mdiobus_register(bus, np); + if (rc) + goto err_register; + + mutex_lock(&lp->indirect_mutex); + dev_dbg(lp->dev, "MDIO bus registered; MC:%x\n", + temac_indirect_in32(lp, XTE_MC_OFFSET)); + mutex_unlock(&lp->indirect_mutex); + return 0; + + err_register: + mdiobus_free(bus); + return rc; +} + +void temac_mdio_teardown(struct temac_local *lp) +{ + mdiobus_unregister(lp->mii_bus); + kfree(lp->mii_bus->irq); + mdiobus_free(lp->mii_bus); + lp->mii_bus = NULL; +} + -- cgit v1.2.3 From 434e7b0d12f4e2de6686841a42bd344325b4d756 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 25 Apr 2009 12:53:44 +0000 Subject: net: fix fsl_pq_mdio driver to use module_init() Modules are not supposed to use any of the *_initcall*() hooks as the entry point. fsl_pq_mdio.c was using subsys_initcall_sync() instead of module_init() to guarantee that the MDIO bus was initialized before the Ethernet driver goes looking for the phy. However, the recent OF helpers rework happens to also make sure PHY connection is deferred to .open time, so using an initcall is no longer necessary. This patch replaces the initcall with a more traditional an accepted module_init() call. Tested on Freescale MPC8349emitxgp eval board. Signed-off-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/fsl_pq_mdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index b01daa1e3adf..d12e0e0336f4 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -415,10 +415,10 @@ int __init fsl_pq_mdio_init(void) { return of_register_platform_driver(&fsl_pq_mdio_driver); } +module_init(fsl_pq_mdio_init); void fsl_pq_mdio_exit(void) { of_unregister_platform_driver(&fsl_pq_mdio_driver); } -subsys_initcall_sync(fsl_pq_mdio_init); module_exit(fsl_pq_mdio_exit); -- cgit v1.2.3 From 29112f4e248ca6941f2233f6ed96a7283a67cced Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 24 Apr 2009 01:58:23 +0000 Subject: bonding: use ethtool for link checking first This patch only changes the order of interfaces to use for checking slave link status in bond_check_dev_link() to priorize ethtool interface. Should safe some troubles as ethtool seems to be more supported. Jirka Signed-off-by: Jiri Pirko drivers/net/bonding/bond_main.c | 26 ++++++++++++-------------- 1 files changed, 12 insertions(+), 14 deletions(-) Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 63369b6b14d4..e4166ee9091d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -695,6 +695,18 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de if (bond->params.use_carrier) return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; + /* Try to get link status using Ethtool first. */ + if (slave_dev->ethtool_ops) { + if (slave_dev->ethtool_ops->get_link) { + u32 link; + + link = slave_dev->ethtool_ops->get_link(slave_dev); + + return link ? BMSR_LSTATUS : 0; + } + } + + /* Ethtool can't be used, fallback to MII ioclts. */ ioctl = slave_ops->ndo_do_ioctl; if (ioctl) { /* TODO: set pointer to correct ioctl on a per team member */ @@ -720,20 +732,6 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de } } - /* - * Some drivers cache ETHTOOL_GLINK for a period of time so we only - * attempt to get link status from it if the above MII ioctls fail. - */ - if (slave_dev->ethtool_ops) { - if (slave_dev->ethtool_ops->get_link) { - u32 link; - - link = slave_dev->ethtool_ops->get_link(slave_dev); - - return link ? BMSR_LSTATUS : 0; - } - } - /* * If reporting, report that either there's no dev->do_ioctl, * or both SIOCGMIIREG and get_link failed (meaning that we -- cgit v1.2.3 From 41f8910040639eb106b1a5b5301aab79ecde4940 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 24 Apr 2009 03:57:29 +0000 Subject: bonding: ignore updelay param when there is no active slave Pointed out by Sean E. Millichamp. Quote from Documentation/networking/bonding.txt: "Note that when a bonding interface has no active links, the driver will immediately reuse the first link that goes up, even if the updelay parameter has been specified (the updelay is ignored in this case). If there are slave interfaces waiting for the updelay timeout to expire, the interface that first went into that state will be immediately reused. This reduces down time of the network if the value of updelay has been overestimated, and since this occurs only in cases with no connectivity, there is no additional penalty for ignoring the updelay." This patch actually changes the behaviour in this way. Signed-off-by: Jiri Pirko drivers/net/bonding/bond_main.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e4166ee9091d..fd738367d740 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2247,6 +2247,9 @@ static int bond_miimon_inspect(struct bonding *bond) { struct slave *slave; int i, link_state, commit = 0; + bool ignore_updelay; + + ignore_updelay = !bond->curr_active_slave ? true : false; bond_for_each_slave(bond, slave, i) { slave->new_link = BOND_LINK_NOCHANGE; @@ -2311,6 +2314,7 @@ static int bond_miimon_inspect(struct bonding *bond) ": %s: link status up for " "interface %s, enabling it in %d ms.\n", bond->dev->name, slave->dev->name, + ignore_updelay ? 0 : bond->params.updelay * bond->params.miimon); } @@ -2329,9 +2333,13 @@ static int bond_miimon_inspect(struct bonding *bond) continue; } + if (ignore_updelay) + slave->delay = 0; + if (slave->delay <= 0) { slave->new_link = BOND_LINK_UP; commit++; + ignore_updelay = false; continue; } -- cgit v1.2.3 From 4e204c1000561ddb1a62a9df857cb0457dd868a7 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 23 Apr 2009 15:31:38 +0000 Subject: vxge: fix possible NULL dereference in vxge-traffic.c If vpath is NULL then hldev is NULL also. Signed-off-by: Alexander Beregalov Acked-by: Ram Vepa Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-traffic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index 7be0ae10d69b..506625b180ac 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c @@ -1923,7 +1923,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( if (vpath == NULL) { alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN, alarm_event); - goto out; + goto out2; } hldev = vpath->hldev; @@ -2161,7 +2161,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( } out: hldev->stats.sw_dev_err_stats.vpath_alarms++; - +out2: if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) || (alarm_event == VXGE_HW_EVENT_UNKNOWN)) return VXGE_HW_OK; -- cgit v1.2.3 From 011983048a120e520147361be1067dd82343038e Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 23 Apr 2009 15:53:21 +0000 Subject: vxge: use max() instead of VXGE_HW_SET_LEVEL Signed-off-by: Alexander Beregalov Acked-by: Ram Vepa Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-traffic.c | 55 +++++++++++++++++------------------------ drivers/net/vxge/vxge-traffic.h | 2 -- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index 506625b180ac..cf4ebb55273d 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c @@ -505,7 +505,7 @@ enum vxge_hw_status vxge_hw_device_begin_irq(struct __vxge_hw_device *hldev, ret = __vxge_hw_vpath_alarm_process( &hldev->virtual_paths[i], skip_alarms); - error_level = VXGE_HW_SET_LEVEL(ret, error_level); + error_level = max(ret, error_level); if (unlikely((ret == VXGE_HW_ERR_CRITICAL) || (ret == VXGE_HW_ERR_SLOT_FREEZE))) @@ -1921,7 +1921,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( struct vxge_hw_vpath_reg __iomem *vp_reg; if (vpath == NULL) { - alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN, + alarm_event = max(VXGE_HW_EVENT_UNKNOWN, alarm_event); goto out2; } @@ -1931,7 +1931,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( alarm_status = readq(&vp_reg->vpath_general_int_status); if (alarm_status == VXGE_HW_ALL_FOXES) { - alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_SLOT_FREEZE, + alarm_event = max(VXGE_HW_EVENT_SLOT_FREEZE, alarm_event); goto out; } @@ -1945,7 +1945,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) { sw_stats->error_stats.unknown_alarms++; - alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN, + alarm_event = max(VXGE_HW_EVENT_UNKNOWN, alarm_event); goto out; } @@ -1975,8 +1975,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( &vp_reg->asic_ntwk_vp_err_mask); __vxge_hw_device_handle_link_down_ind(hldev); - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_LINK_DOWN, alarm_event); + alarm_event = max(VXGE_HW_EVENT_LINK_DOWN, + alarm_event); } if (((val64 & @@ -1996,15 +1996,15 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( &vp_reg->asic_ntwk_vp_err_mask); __vxge_hw_device_handle_link_up_ind(hldev); - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_LINK_UP, alarm_event); + alarm_event = max(VXGE_HW_EVENT_LINK_UP, + alarm_event); } writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->asic_ntwk_vp_err_reg); - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); + alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event); if (skip_alarms) return VXGE_HW_OK; @@ -2026,8 +2026,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.ini_serr_det++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_SERR, alarm_event); + alarm_event = max(VXGE_HW_EVENT_SERR, + alarm_event); } if ((val64 & @@ -2035,8 +2035,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.dblgen_fifo0_overflow++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_FIFO_ERR, alarm_event); + alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, + alarm_event); } if ((val64 & @@ -2057,8 +2057,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( if (!skip_alarms) { writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->general_errors_reg); - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); } } @@ -2074,8 +2073,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.kdfcctl_fifo0_overwrite++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_FIFO_ERR, + alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, alarm_event); } @@ -2084,8 +2082,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.kdfcctl_fifo0_poison++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_FIFO_ERR, + alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, alarm_event); } @@ -2094,16 +2091,14 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.kdfcctl_fifo0_dma_error++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_FIFO_ERR, + alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, alarm_event); } if (!skip_alarms) { writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_reg); - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); } } @@ -2127,8 +2122,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.prc_rxdcm_sc_err++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_VPATH_ERR, + alarm_event = max(VXGE_HW_EVENT_VPATH_ERR, alarm_event); } @@ -2136,8 +2130,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( & ~mask64) { sw_stats->error_stats.prc_rxdcm_sc_abort++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_VPATH_ERR, + alarm_event = max(VXGE_HW_EVENT_VPATH_ERR, alarm_event); } @@ -2145,16 +2138,14 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( & ~mask64) { sw_stats->error_stats.prc_quanta_size_err++; - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_VPATH_ERR, + alarm_event = max(VXGE_HW_EVENT_VPATH_ERR, alarm_event); } if (!skip_alarms) { writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->prc_alarm_reg); - alarm_event = VXGE_HW_SET_LEVEL( - VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); } } diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 7567a1140d07..d03f3d3805c9 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h @@ -110,8 +110,6 @@ enum vxge_hw_event { VXGE_HW_EVENT_SLOT_FREEZE = VXGE_HW_EVENT_BASE + 14, }; -#define VXGE_HW_SET_LEVEL(a, b) (((a) > (b)) ? (a) : (b)) - /* * struct vxge_hw_mempool_dma - Represents DMA objects passed to the caller. -- cgit v1.2.3 From 78b1f6070fa16cb442a7c48e8f5364cd84a88b90 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 23 Apr 2009 11:20:29 +0000 Subject: igb: always use adapter->itr as EITR value The igb driver was switching between adapter->itr containing the EITR value and the number of interrupts per second. This resulted in high latencies being seen after brining the interface down and then back up. To resolve the issue the itr value will now only contain the value that should be programmed into EITR. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 183235d46aee..ab846ec65204 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2898,13 +2898,13 @@ static void igb_set_itr(struct igb_adapter *adapter) switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency: - new_itr = 70000; + new_itr = 56; /* aka 70,000 ints/sec */ break; case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ + new_itr = 196; /* aka 20,000 ints/sec */ break; case bulk_latency: - new_itr = 4000; + new_itr = 980; /* aka 4,000 ints/sec */ break; default: break; @@ -2923,7 +2923,8 @@ set_itr_now: * by adding intermediate steps when interrupt rate is * increasing */ new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : + max((new_itr * adapter->itr) / + (new_itr + (adapter->itr >> 2)), new_itr) : new_itr; /* Don't write the value here; it resets the adapter's * internal timer, and causes us to delay far longer than @@ -2932,7 +2933,7 @@ set_itr_now: * ends up being correct. */ adapter->itr = new_itr; - adapter->rx_ring->itr_val = 1000000000 / (new_itr * 256); + adapter->rx_ring->itr_val = new_itr; adapter->rx_ring->set_itr = 1; } -- cgit v1.2.3 From fa466e91bdf214e6e136e9da9a46a52775a1e884 Mon Sep 17 00:00:00 2001 From: "Waskiewicz Jr, Peter P" Date: Thu, 23 Apr 2009 11:31:37 +0000 Subject: ixgbe: Disallow SFP 1G modules in the SFP+ cages for 82598 and 82599 82598 and 82599 do not support SFP 1G modules. Instead of allowing the driver to load, but never get link, rejecting the module and displaying a useful message is more preferrable. The framework for displaying the failure message already exists, now we just need to detect and reject the SFP modules. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_phy.c | 22 +++++++++++++++++----- drivers/net/ixgbe/ixgbe_type.h | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index f3258ec901fe..2543c32ca84a 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -673,11 +673,22 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) break; } } - if (hw->mac.type == ixgbe_mac_82598EB || - (hw->phy.sfp_type != ixgbe_sfp_type_sr && - hw->phy.sfp_type != ixgbe_sfp_type_lr && - hw->phy.sfp_type != ixgbe_sfp_type_srlr_core0 && - hw->phy.sfp_type != ixgbe_sfp_type_srlr_core1)) { + + /* All DA cables are supported */ + if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE) { + status = 0; + goto out; + } + + /* 1G SFP modules are not supported */ + if (comp_codes_10g == 0) { + hw->phy.type = ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; + goto out; + } + + /* Anything else 82598-based is supported */ + if (hw->mac.type == ixgbe_mac_82598EB) { status = 0; goto out; } @@ -690,6 +701,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) status = 0; } else { hw_dbg(hw, "SFP+ module not supported\n"); + hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } } else { diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index a3317d8fbf6a..375f0d4ad965 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1904,6 +1904,7 @@ enum ixgbe_phy_type { ixgbe_phy_sfp_ftl, ixgbe_phy_sfp_unknown, ixgbe_phy_sfp_intel, + ixgbe_phy_sfp_unsupported, ixgbe_phy_generic }; -- cgit v1.2.3 From 683703a26e4677db437a1480682851e27c7a154f Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 27 Apr 2009 03:17:31 -0700 Subject: drop_monitor: Update netlink protocol to include netlink attribute header in alert message When I initially implemented this protocol, I disregarded the use of netlink attribute headers, thinking for my purposes they weren't needed. I've come to find out that, as I'm starting to work with sending down messages with associated data (like config messages), the kernel code spits out warnings about trailing data in a netlink skb that doesn't have an associated header on it. As such, I'm going to start including attribute headers in my netlink transaction, and so for completeness, I should likely include them on messages bound from the kernel to user space. This patch adds that header to the kernel, and bumps the protocol version accordingly Signed-off-by: Neil Horman Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 9fd0dc3cca99..2797b711a978 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -51,7 +51,7 @@ static struct genl_family net_drop_monitor_family = { .id = GENL_ID_GENERATE, .hdrsize = 0, .name = "NET_DM", - .version = 1, + .version = 2, .maxattr = NET_DM_CMD_MAX, }; @@ -65,13 +65,17 @@ static void reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; struct net_dm_alert_msg *msg; + struct nlattr *nla; al = sizeof(struct net_dm_alert_msg); al += dm_hit_limit * sizeof(struct net_dm_drop_point); + al += sizeof(struct nlattr); + data->skb = genlmsg_new(al, GFP_KERNEL); genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family, 0, NET_DM_CMD_ALERT); - msg = __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_alert_msg)); + nla = nla_reserve(data->skb, NLA_UNSPEC, sizeof(struct net_dm_alert_msg)); + msg = nla_data(nla); memset(msg, 0, al); atomic_set(&data->dm_hit_count, dm_hit_limit); } @@ -115,6 +119,7 @@ static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) { struct net_dm_alert_msg *msg; struct nlmsghdr *nlh; + struct nlattr *nla; int i; struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data); @@ -127,7 +132,8 @@ static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) } nlh = (struct nlmsghdr *)data->skb->data; - msg = genlmsg_data(nlmsg_data(nlh)); + nla = genlmsg_data(nlmsg_data(nlh)); + msg = nla_data(nla); for (i = 0; i < msg->entries; i++) { if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { msg->points[i].count++; @@ -139,6 +145,7 @@ static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) * We need to create a new entry */ __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point)); + nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point)); memcpy(msg->points[msg->entries].pc, &location, sizeof(void *)); msg->points[msg->entries].count = 1; msg->entries++; -- cgit v1.2.3 From 15b8e19131486856373592e45793a79aefb6fbe7 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Thu, 23 Apr 2009 08:53:20 +0000 Subject: pasemi_mac: mac_to_intf() error not noticed mac_to_intf() can return -1 when no device or function is found, but when mac->dma_if is unsigned. The error wasn't noticed. Signed-off-by: Roel Kluin Acked-by: Olof Johansson Signed-off-by: David S. Miller --- drivers/net/pasemi_mac.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 6ea4539085d5..c254a7f5b9f5 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -1733,7 +1733,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct pasemi_mac *mac; - int err; + int err, ret; err = pci_enable_device(pdev); if (err) @@ -1791,12 +1791,13 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr)); - mac->dma_if = mac_to_intf(mac); - if (mac->dma_if < 0) { + ret = mac_to_intf(mac); + if (ret < 0) { dev_err(&mac->pdev->dev, "Can't map DMA interface\n"); err = -ENODEV; goto out; } + mac->dma_if = ret; switch (pdev->device) { case 0xa005: -- cgit v1.2.3 From 0456b4f8b742006c2b79fcbe6b0736aa1ad39180 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Mon, 27 Apr 2009 03:22:15 -0700 Subject: cxacru: Fix negative dB output Values of dB between -0.99 and -0.01 will be output with the wrong sign. This converts the negative value to positive and outputs it with a "-" prefix. Signed-off-by: Simon Arlott Signed-off-by: David S. Miller --- drivers/usb/atm/cxacru.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 6789089e2461..56802d2e994b 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -227,8 +227,14 @@ static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf) static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d.%02u\n", - value / 100, abs(value) % 100); + if (likely(value >= 0)) { + return snprintf(buf, PAGE_SIZE, "%u.%02u\n", + value / 100, value % 100); + } else { + value = -value; + return snprintf(buf, PAGE_SIZE, "-%u.%02u\n", + value / 100, value % 100); + } } static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) -- cgit v1.2.3 From f85ba78068ac137fe9c1f50d25405d2783d75c77 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 27 Apr 2009 03:23:54 -0700 Subject: tun: add IFF_TUN_EXCL flag to avoid opening a persistent device. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When creating a certain types of VPN, NetworkManager will first attempt to find an available tun device by iterating through 'vpn%d' until it finds one that isn't already busy. Then it'll set that to be persistent and owned by the otherwise unprivileged user that the VPN dæmon itself runs as. There's a race condition here -- during the period where the vpn%d device is created and we're waiting for the VPN dæmon to actually connect and use it, if we try to create _another_ device we could end up re-using the same one -- because trying to open it again doesn't get -EBUSY as it would while it's _actually_ busy. So solve this, we add an IFF_TUN_EXCL flag which causes tun_set_iff() to fail if it would be opening an existing persistent tundevice -- so that we can make sure we're getting an entirely _new_ device. Signed-off-by: David Woodhouse Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 ++ include/linux/if_tun.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 589f0ca668d6..94622e5fb936 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -874,6 +874,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) dev = __dev_get_by_name(net, ifr->ifr_name); if (dev) { + if (ifr->ifr_flags & IFF_TUN_EXCL) + return -EBUSY; if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) tun = netdev_priv(dev); else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 049d6c9428db..915ba5789f0e 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -55,6 +55,7 @@ #define IFF_NO_PI 0x1000 #define IFF_ONE_QUEUE 0x2000 #define IFF_VNET_HDR 0x4000 +#define IFF_TUN_EXCL 0x8000 /* Features for GSO (TUNSETOFFLOAD). */ #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ -- cgit v1.2.3 From ec9323f417e803f07a99a15a9cfb207662ad2c55 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 27 Apr 2009 03:26:13 -0700 Subject: bnx2x: FW 4.8.53.0 Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- firmware/bnx2x-e1-4.8.53.0.fw.ihex | 10364 +++++++++++++++++++++++++++++ firmware/bnx2x-e1h-4.8.53.0.fw.ihex | 12028 ++++++++++++++++++++++++++++++++++ 2 files changed, 22392 insertions(+) create mode 100644 firmware/bnx2x-e1-4.8.53.0.fw.ihex create mode 100644 firmware/bnx2x-e1h-4.8.53.0.fw.ihex diff --git a/firmware/bnx2x-e1-4.8.53.0.fw.ihex b/firmware/bnx2x-e1-4.8.53.0.fw.ihex new file mode 100644 index 000000000000..f1edb1e7ad1b --- /dev/null +++ b/firmware/bnx2x-e1-4.8.53.0.fw.ihex @@ -0,0 +1,10364 @@ +:10000000000028600000006000000630000028C8E2 +:100010000000160800002F000000009400004510AA +:10002000000073C8000045A8000000C40000B978B3 +:100030000000A4680000BA400000007400015EB037 +:100040000000559000015F28000000B80001B4C016 +:100050000000D1F80001B580000000040002878094 +:10006000020400480000000F020400540000004594 +:1000700002040058000000840204005C0000000636 +:100080000204007000000004020400780000000078 +:100090000204007C121700000204008022170000F6 +:1000A00002040084321700000604008800000005E6 +:1000B0000204009C12150000020400A0221500009A +:1000C000020400A432150000060400A80000000489 +:1000D000020400B802100000020400BC001000007E +:1000E000020400C010100000020400C42010000030 +:1000F000020400C830100000060400CC0000000418 +:10010000020400DC00100000020400E012140000F1 +:10011000020400E422140000020400E8321400008B +:10012000060400EC000000040104012400000000AB +:1001300001040128000000000104012C000000005F +:10014000010401300000000002040004000000FF70 +:1001500002040008000000FF0204000C000000FF81 +:1001600002040010000000FF02040014000000FF61 +:1001700002040018000000FF0204001C000000FF41 +:1001800002040020000000FF020400240000003EE2 +:1001900002040028000000000204002C0000003FC0 +:1001A000020400300000003F020400340000003F61 +:1001B00002040038000000000204003C0000003F80 +:1001C000020400400000003F020400440000003F21 +:1001D00002042008000004110204200C00000400A6 +:1001E000020420100000040402042014000004197A +:1001F0000204201C0000FFFF020420200000FFFF7B +:10020000020420240000FFFF020420280000FFFF5A +:1002100006042038000000020204204000000034E0 +:100220000204204400000035060420480000007C41 +:100230000204223807FFFFFF0204223C0000003FB7 +:100240000204224007FFFFFF020422440000000FC7 +:1002500001042248000000000104224C00000000BC +:10026000010422500000000001042254000000009C +:1002700001042258000000000104225C000000007C +:10028000010422600000000001042264000000005C +:1002900001042268000000000104226C000000003C +:1002A000010422700000000001042274000000001C +:1002B00001042278000000000104227C00000000FC +:1002C000020424BC000000010C042000000003E82C +:1002D0000A042000000000010B0420000000000AB6 +:1002E0000205004400000020020500480000003222 +:1002F000020500900215002002050094021500205E +:1003000002050098000000300205009C0810000063 +:10031000020500A000000033020500A40000003028 +:10032000020500A800000031020500AC0000000238 +:10033000020500B000000005020500B40000000640 +:10034000020500B800000002020500BC0000000227 +:10035000020500C000000000020500C40000000506 +:10036000020500C800000002020500CC00000002E7 +:10037000020500D000000002020500D400000001C8 +:1003800002050114000000010205011C000000012B +:100390000205012000000002020502040000000125 +:1003A0000205020C0000004002050210000000409F +:1003B0000205021C000000200205022000000013BC +:1003C0000205022400000020060502400000000A89 +:1003D0000405028000200000020500500000000714 +:1003E0000205005400000007020500580000000844 +:1003F0000205005C00000008060500600000000423 +:10040000020500D800000006020500E00000000D13 +:10041000020500E40000002D020500E800000007CE +:10042000020500EC00000027020500F000000007B4 +:10043000020500F400000027020500F80000000794 +:10044000020500FC00000027020500040000000176 +:1004500002050008000000010205000C0000000178 +:100460000205001000000001020500140000000158 +:1004700002050018000000010205001C0000000138 +:100480000205002000000001020500240000000118 +:1004900002050028000000010205002C00000001F8 +:1004A00002050030000000010205003400000001D8 +:1004B00002050038000000010205003C00000001B8 +:1004C00002050040000000010406100002000020A8 +:1004D000020600DC00000001010600D80000000058 +:1004E0000406020000030220020600DC00000000F7 +:1004F00002060068000000B802060078000001143F +:10050000010600B800000000010600C8000000005D +:100510000206006C000000B80206007C0000011416 +:10052000010600BC00000000010600CC0000000035 +:100530000718040000930000081807600014022345 +:10054000071C0000324F0000071C800033250C946C +:10055000071D00000E4D195E081D1E005C4002259F +:100560000118000000000000011800040000000055 +:1005700001180008000000000118000C0000000035 +:100580000118001000000000011800140000000015 +:1005900002180020000000010218002400000002E0 +:1005A00002180028000000030218002C00000000C0 +:1005B000021800300000000402180034000000019E +:1005C00002180038000000000218003C0000000182 +:1005D000021800400000000402180044000000005F +:1005E00002180048000000010218004C000000033F +:1005F0000218005000000000021800540000000122 +:1006000002180058000000040218005C00000000FE +:1006100002180060000000010218006400000003DE +:1006200002180068000000000218006C00000001C1 +:10063000021800700000000402180074000000009E +:1006400002180078000000040218007C000000037B +:100650000618008000000002021800A400003FFFFE +:10066000021800A8000003FF021802240000000086 +:1006700002180234000000000218024C00000000C2 +:10068000021802E4000000FF061810000000040039 +:10069000021B8BC000000001021B80000000003420 +:1006A000021B804000000018021B80800000000C2C +:1006B000021B80C0000000200C1B83000007A1204B +:1006C0000A1B8300000001380B1B83000000138805 +:1006D000021B83C0000001F4061A2000000000B2D3 +:1006E000061A23C8000000C1041A26CC0001022704 +:1006F000061A1020000000C8061A100000000002B0 +:10070000061A1C1800000004061A1C100000000243 +:10071000061A080000000002061A0808000000027D +:10072000061A081000000004041A1FB00004022872 +:10073000041A4CB00008022C061A22C8000000203F +:10074000061A40000000016C021A4B600000000015 +:10075000061A14000000000A061A145000000006D1 +:10076000061A150000000002041A150800050234DC +:10077000061A151C00000007061A1570000000126A +:10078000061A09C00000004C061A0800000000020A +:10079000061A08200000000E041A1FB000020239D9 +:1007A000061A290800000002061A2348000000204B +:1007B000061A45B00000016C021A4B6400000000EC +:1007C000061A14280000000A061A14680000000621 +:1007D000061A153800000002041A15400005023BF5 +:1007E000061A155400000007061A15B8000000127A +:1007F000061A0AF00000004C061A08080000000261 +:10080000061A08580000000E041A1FB80002024021 +:10081000061A2910000000020200A2800000000158 +:100820000200A294071D29110200A29800000000F6 +:100830000200A29C009C04240200A2A00000000070 +:100840000200A2A4000002090200A4FCFF000000B4 +:10085000020100B400000001020100B80000000124 +:10086000020100DC000000010201010000000001A3 +:1008700002010104000000010201007C00300000C0 +:1008800002010084000000280201008C000000002A +:1008900002010130000000040201025C00000001BE +:1008A000020103280000000002010554000000308E +:1008B000020100C400000001020100CC00000001A0 +:1008C000020100F800000001020100F00000000138 +:1008D00002010080003000000201008800000028B2 +:1008E0000201009000000000020101340000000439 +:1008F000020102DC000000010201032C00000000E4 +:100900000201056400000030020100C8000000017F +:10091000020100D000000001020100FC0000000103 +:10092000020100F400000001020C10000000002091 +:10093000020C200800000A11020C200C00000A0022 +:10094000020C201000000A04020C201C0000FFFF13 +:10095000020C20200000FFFF020C20240000FFFFFB +:10096000020C20280000FFFF020C2038000000C607 +:10097000020C203C00000000020C2040000000346B +:10098000020C204400000035060C20480000001C2A +:10099000020C20B800000001060C20BC0000005F23 +:1009A000020C223807FFFFFF020C223C0000003F30 +:1009B000020C224007FFFFFF020C22440000000F40 +:1009C000010C224800000000010C224C0000000035 +:1009D000010C225000000000010C22540000000015 +:1009E000010C225800000000010C225C00000000F5 +:1009F000010C226000000000010C226400000000D5 +:100A0000010C226800000000010C226C00000000B4 +:100A1000010C227000000000010C22740000000094 +:100A2000010C227800000000010C227C0000000074 +:100A3000020C24BC000000010C0C2000000003E8A4 +:100A40000A0C2000000000010B0C20000000000A2E +:100A5000020C400800000A11020C400C00000A00C1 +:100A6000020C401000000A04020C401400000A218D +:100A7000020C401C0000FFFF020C40200000FFFFA2 +:100A8000020C40240000FFFF020C40280000FFFF82 +:100A9000020C403800000046020C403C00000005FB +:100AA000020C404000000034020C404400000035BD +:100AB000060C40480000005C020C41B80000000138 +:100AC000060C41BC0000001F020C423807FFFFFF6C +:100AD000020C423C0000003F020C424007FFFFFFB7 +:100AE000020C42440000000F010C424800000000CC +:100AF000010C424C00000000010C425000000000BC +:100B0000010C425400000000010C4258000000009B +:100B1000010C425C00000000010C4260000000007B +:100B2000010C426400000000010C4268000000005B +:100B3000010C426C00000000010C4270000000003B +:100B4000010C427400000000010C4278000000001B +:100B5000010C427C00000000010C428000000000FB +:100B6000020C44C0000000010C0C4000000003E82F +:100B70000A0C4000000000010B0C40000000000ABD +:100B8000020D004400000032020D008C021500200E +:100B9000020D009002150020020D009408100000C4 +:100BA000020D009800000033020D009C00000002BE +:100BB000020D00A000000000020D00A400000005CE +:100BC000020D00A800000005060D00AC00000002A8 +:100BD000020D00B400000002020D00B80000000386 +:100BE000020D00BC00000002020D00C00000000168 +:100BF000020D00C800000002020D00CC000000023F +:100C0000020D010800000001020D015C000000015E +:100C1000020D016400000001020D016800000002E5 +:100C2000020D020400000001020D020C0000002071 +:100C3000020D021000000040020D021400000040EE +:100C4000020D022000000003020D02240000001823 +:100C5000060D028000000012040D03000024024271 +:100C6000020D004C00000001020D005000000002C7 +:100C7000020D005400000008020D0058000000089A +:100C8000060D005C00000004020D00C4000000041A +:100C9000020D011400000009020D011800000029D6 +:100CA000020D011C0000000A020D01200000002AB4 +:100CB000020D012400000007020D0128000000279A +:100CC000020D012C00000007020D0130000000277A +:100CD000020D01340000000C020D01380000002C50 +:100CE000020D013C0000000C020D01400000002C30 +:100CF000020D01440000000C020D01480000002C10 +:100D0000020D000400000001020D000800000001B7 +:100D1000020D000C00000001020D00100000000197 +:100D2000020D001400000001020D00180000000177 +:100D3000020D001C00000001020D00200000000157 +:100D4000020D002400000001020D00280000000137 +:100D5000020D002C00000001020D00300000000117 +:100D6000020D003400000001020D003800000001F7 +:100D7000020D003C00000001020E004C0000003299 +:100D8000020E009402150020020E009802150020A9 +:100D9000020E009C00000030020E00A008100000AF +:100DA000020E00A400000033020E00A80000003074 +:100DB000020E00AC00000031020E00B00000000284 +:100DC000020E00B400000004020E00B80000000093 +:100DD000020E00BC00000002020E00C00000000273 +:100DE000020E00C400000000020E00C80000000255 +:100DF000020E00CC00000007020E00D0000000022E +:100E0000020E00D400000002020E00D80000000113 +:100E1000020E00E400000001020E01440000000187 +:100E2000020E014C00000001020E01500000000201 +:100E3000020E020400000001020E020C000000403D +:100E4000020E021000000040020E021C000000040E +:100E5000020E022000000020020E02240000000EFC +:100E6000020E02280000001B060E03000000001204 +:100E7000040E0280001B0266020E005400000010E7 +:100E8000020E005800000007020E005C0000000F78 +:100E9000020E006000000010060E00640000000456 +:100EA000020E00DC00000003020E01100000000F23 +:100EB000020E01140000002F020E01180000000EA7 +:100EC000020E011C0000002E020E000400000001B2 +:100ED000020E000800000001020E000C00000001DC +:100EE000020E001000000001020E001400000001BC +:100EF000020E001800000001020E001C000000019C +:100F0000020E002000000001020E0024000000017B +:100F1000020E002800000001020E002C000000015B +:100F2000020E003000000001020E0034000000013B +:100F3000020E003800000001020E003C000000011B +:100F4000020E004000000001020E004400000001FB +:100F50000730040000C30000083007680013028156 +:100F600007340000314C00000734800035EF0C548A +:100F700007350000361319D00735800007112755B3 +:100F800008358EE04E24028301300000000000008E +:100F900001300004000000000130000800000000E3 +:100FA0000130000C000000000130001000000000C3 +:100FB0000130001400000000023000200000000199 +:100FC000023000240000000202300028000000036C +:100FD0000230002C0000000002300030000000044D +:100FE0000230003400000001023000380000000030 +:100FF0000230003C0000000102300040000000040C +:1010000002300044000000000230004800000001EF +:101010000230004C000000030230005000000000CD +:1010200002300054000000010230005800000004AB +:101030000230005C0000000002300060000000018F +:10104000023000640000000302300068000000006D +:101050000230006C0000000102300070000000044B +:10106000023000740000000002300078000000042C +:101070000230007C00000003063000800000000207 +:10108000023000A400003FFF023000A8000003FF70 +:101090000230022400000000023002340000000090 +:1010A0000230024C00000000023002E40000FFFFAA +:1010B000063020000000080002338BC00000000151 +:1010C000023380000000001A023380400000004E0E +:1010D0000233808000000010023380C00000002036 +:1010E0000C3383000007A1200A338300000001387D +:1010F0000B33830000001388023383C0000001F427 +:101100000C3383801DCD65000A3383800004C4B492 +:101110000B338380004C4B4006325000000000C26D +:1011200006321020000000C8063210000000000245 +:101130000632464000000040063257F0000000042E +:10114000063257D800000005043257EC0001028532 +:1011500006321C60000000200432283000020286A3 +:10116000023308000100000004330C000010028864 +:10117000023308000000000004330C400010029805 +:1011800006321400000000A0063219000000001012 +:10119000063219800000003006324740000000B4DB +:1011A00002321D900000000006321B4000000004C7 +:1011B00006321B6000000020063253180000009821 +:1011C00006321680000000A0063219400000001010 +:1011D00006321A400000003006324A10000000B407 +:1011E00002321D940000000006321B500000000473 +:1011F00006321BE0000000200632557800000098FF +:10120000072004000071000008200780001002A8D9 +:1012100007240000322900000724800023630C8B80 +:101220000824C930654002AA012000000000000027 +:101230000120000400000000012000080000000060 +:101240000120000C00000000012000100000000040 +:101250000120001400000000022000200000000116 +:1012600002200024000000020220002800000003E9 +:101270000220002C000000000220003000000004CA +:1012800002200034000000010220003800000000AD +:101290000220003C00000001022000400000000489 +:1012A000022000440000000002200048000000016D +:1012B0000220004C0000000302200050000000004B +:1012C0000220005400000001022000580000000429 +:1012D0000220005C0000000002200060000000010D +:1012E00002200064000000030220006800000000EB +:1012F0000220006C000000010220007000000004C9 +:1013000002200074000000000220007800000004A9 +:101310000220007C00000003062000800000000284 +:10132000022000A400003FFF022000A8000003FFED +:10133000022002240000000002200234000000000D +:101340000220024C00000000022002E40000FFFF27 +:10135000062020000000080002238BC000000001CE +:1013600002238000000000100223804000000012D1 +:101370000223808000000030022380C00000000EA5 +:10138000022383C0000001F4062250000000004246 +:1013900006221020000000C80622100000000002F3 +:1013A00006222000000000C00622307000000080ED +:1013B0000622428000000004062225C000000240F0 +:1013C00004222EC8000802AC02230800013FFFFFE0 +:1013D00004230C00001002B40223080000000000E7 +:1013E00004230C40001002C406221400000000A0D8 +:1013F00006221900000000100622198000000030AB +:101400000222511800000000062223000000000EF6 +:1014100006223040000000060622241000000030A2 +:1014200006221680000000A00622194000000010CD +:1014300006221A40000000300222511C0000000069 +:10144000062223380000000E062230580000000655 +:10145000062224D0000000300216100000000020F8 +:1014600002170008000000020217002C0000000311 +:101470000217003C000000040217004400000008AE +:1014800002170048000000020217004C0000009004 +:1014900002170050000000900217005400800090D6 +:1014A0000217005808140000021700600000008AAC +:1014B000021700640000008002170068000000901E +:1014C0000217006C00000080021700700000000688 +:1014D00002170078000007D00217007C0000076C9C +:1014E00002170038007C1004021700040000000FEF +:1014F0000616402400000002021640700000001C86 +:10150000021642080000000102164210000000010D +:1015100002164220000000010216422800000001CD +:10152000021642300000000102164238000000019D +:1015300002164260000000010C16401C0003D0900F +:101540000A16401C0000009C0B16401C000009C439 +:101550000216403000000008021640340000000C63 +:10156000021640380000001002164044000000201F +:101570000216400000000001021640D800000001E1 +:1015800002164008000000010216400C0000000195 +:101590000216401000000001021642400000000048 +:1015A00002164248000000000616427000000002C9 +:1015B00002164250000000000216425800000000CF +:1015C00006164280000000020216600800000614A1 +:1015D0000216600C000006000216601000000604EF +:1015E0000216601C0000FFFF021660200000FFFFD3 +:1015F000021660240000FFFF021660280000FFFFB3 +:1016000002166038000000200216603C0000002036 +:1016100002166040000000340216604400000035ED +:1016200002166048000000230216604C00000024EF +:1016300002166050000000250216605400000026CB +:1016400002166058000000270216605C00000029A6 +:10165000021660600000002A021660640000002B81 +:10166000021660680000002C0216606C0000002D5D +:101670000616607000000052021661B800000001FA +:10168000061661BC0000001F0216623807FFFFFF4C +:101690000216623C0000003F0216624007FFFFFF97 +:1016A000021662440000000F0116624800000000AC +:1016B0000116624C0000000001166250000000009C +:1016C000011662540000000001166258000000007C +:1016D0000116625C0000000001166260000000005C +:1016E000011662640000000001166268000000003C +:1016F0000116626C0000000001166270000000001C +:1017000001166274000000000116627800000000FB +:101710000116627C00000000021664BC000000019B +:101720000C166000000003E80A16600000000001CB +:101730000B1660000000000A021680400000000640 +:101740000216804400000005021680480000000ACE +:101750000216804C000000050216805400000002B2 +:10176000021680CC00000004021680D000000004A5 +:10177000021680D400000004021680D80000000485 +:10178000021680DC00000004021680E00000000465 +:10179000021680E400000004021680E80000000445 +:1017A0000216880400000004021680300000007C4D +:1017B000021680340000003D021680380000003F11 +:1017C0000216803C0000009C021680F0000000071A +:1017D000061680F4000000050216880C01010101C4 +:1017E00002168108000000000216810C00000004AF +:1017F000021681100000000402168114000000028D +:101800000216881008012004021681180000000545 +:101810000216811C00000005021681200000000550 +:1018200002168124000000050216882C20081001F1 +:1018300002168128000000080216812C0000000614 +:1018400002168130000000070216813400000000FB +:1018500002168830010101200616813800000004BC +:1018600002168834010101010616814800000004B7 +:101870000216883801010101061681580000000493 +:101880000216883C01010101061681680000000370 +:101890000216817400000001021688400101010156 +:1018A00002168178000000010216817C0000000110 +:1018B00002168180000000010216818400000001F0 +:1018C000021688440101010102168188000000010E +:1018D0000216818C000000040216819000000004B2 +:1018E00002168194000000020216884808012004B4 +:1018F00002168198000000050216819C0000000578 +:10190000021681A000000005021681A40000000557 +:101910000216881420081001021681A80000000891 +:10192000021681AC00000006021681B0000000071C +:10193000021681B40000000102168818010101207E +:10194000021681B800000001021681BC00000001EF +:10195000021681C000000001021681C400000001CF +:101960000216881C01010101021681C80000000155 +:10197000021681CC00000001021681D00000000197 +:10198000021681D400000001021688200101010125 +:10199000021681D800000001021681DC000000015F +:1019A000021681E000000001021681E4000000013F +:1019B0000216882401010101021681E800000001DD +:1019C000021681EC00000001021681F00000000107 +:1019D000021688280101010102168240FFFF003F24 +:1019E00006168244000000020216824CFFFF003FF0 +:1019F000021682500000010002168254000001000D +:101A0000061682580000000202168260000000C024 +:101A100002168264000000C00216826800001E00E8 +:101A20000216826C00001E00021682700000400048 +:101A300002168274000040000216827800008000C6 +:101A40000216827C000080000216828000002000C6 +:101A5000021682840000200006168288000000071B +:101A6000021682A400000001061682A80000000AE7 +:101A7000021681F400000C08021681F800000040F4 +:101A8000021681FC00000100021682000000002006 +:101A9000021682040000001702168208000000806F +:101AA0000216820C000002000216821000000000E4 +:101AB00002168218FFFF01FF02168214FFFF01FFCA +:101AC0000216823C00000013021680900000013FC5 +:101AD0000216806000000140021680640000014090 +:101AE000061680680000000202168070000000C028 +:101AF00006168074000000070216809C0000004853 +:101B0000021680A000000048061680A40000000213 +:101B1000021680AC00000048061680B000000007E6 +:101B2000021682380000800002168234000025E48C +:101B30000216809400007FFF02168220000000073A +:101B40000216821C00000007021682280000000016 +:101B500002168224FFFFFFFF021682300000000001 +:101B60000216822CFFFFFFFF021680EC000000FF30 +:101B700002140000000000010214000C000000012B +:101B800002140040000000010214004400007FFF26 +:101B90000214000C0000000002140000000000000D +:101BA0000214006C00000000021400040000000198 +:101BB00002140030000000010214000400000000C4 +:101BC0000214005C00000000021400080000000184 +:101BD000021400340000000102140008000000009C +:101BE00002140060000000000202005800000032F1 +:101BF000020200A003150020020200A40315002029 +:101C0000020200A801000030020200AC081000002F +:101C1000020200B000000033020200B400000030F5 +:101C2000020200B800000031020200BC0000000304 +:101C3000020200C000000006020200C4000000030F +:101C4000020200C800000003020200CC00000002F3 +:101C5000020200D000000000020200D400000002D6 +:101C6000020200DC00000000020200E000000006AA +:101C7000020200E400000004020200E8000000028A +:101C8000020200EC00000002020200F0000000016D +:101C9000020200FC00000006020201200000000019 +:101CA0000202013400000002020201B00000000143 +:101CB0000202020C000000010202021400000001F6 +:101CC00002020218000000020202040400000001E7 +:101CD0000202040C00000040020204100000004058 +:101CE0000202041C00000004020204200000002084 +:101CF0000202042400000002020204280000001F67 +:101D0000060205000000001204020480001F02D435 +:101D1000020200600000000F0202006400000007E1 +:101D2000020200680000000B0202006C0000000EBE +:101D30000602007000000004020200F4000000042B +:101D4000020200040000000102020008000000017D +:101D50000202000C0000000102020010000000015D +:101D6000020200140000000102020018000000013D +:101D70000202001C0000000102020020000000011D +:101D800002020024000000010202002800000001FD +:101D90000202002C000000010202003000000001DD +:101DA00002020034000000010202003800000001BD +:101DB0000202003C0000000102020040000000019D +:101DC000020200440000000102020048000000017D +:101DD0000202004C0000000102020050000000015D +:101DE00002020108000000C80202011800000002FF +:101DF000020201C400000000020201CC0000000049 +:101E0000020201D400000002020201DC0000000214 +:101E1000020201E4000000FF020201EC000000FFEA +:101E20000202010C000000C80202011C00000002B6 +:101E3000020201C800000000020201D00000000000 +:101E4000020201D800000002020201E000000002CC +:101E5000020201E8000000FF020201F0000000FFA2 +:101E60000728040000B5000008280768001302F3E3 +:101E7000072C000033660000072C800038B30CDA12 +:101E8000072D00003BB11B07072D80002A2629F4EF +:101E9000082DD6C0452802F50128000000000000EA +:101EA00001280004000000000128000800000000D4 +:101EB0000128000C000000000128001000000000B4 +:101EC000012800140000000002280020000000018A +:101ED000022800240000000202280028000000035D +:101EE0000228002C0000000002280030000000043E +:101EF0000228003400000001022800380000000021 +:101F00000228003C000000010228004000000004FC +:101F100002280044000000000228004800000001E0 +:101F20000228004C000000030228005000000000BE +:101F3000022800540000000102280058000000049C +:101F40000228005C00000000022800600000000180 +:101F5000022800640000000302280068000000005E +:101F60000228006C0000000102280070000000043C +:101F7000022800740000000002280078000000041D +:101F80000228007C000000030628008000000002F8 +:101F9000022800A400003FFF022800A8000003FF61 +:101FA0000228022400000000022802340000000081 +:101FB0000228024C00000000022802E40000FFFF9B +:101FC0000628200000000800022B8BC00000000142 +:101FD000022B800000000000022B8040000000184F +:101FE000022B80800000000C022B80C000000066E5 +:101FF0000C2B83000007A1200A2B8300000001386E +:102000000B2B830000001388022B83C0000001F417 +:102010000C2B8340000001F40A2B834000000000D9 +:102020000B2B8340000000050A2B83800004C4B4FE +:102030000C2B83801DCD65000B2B8380004C4B4007 +:10204000062A3D6000000004042A3D70000202F7E9 +:10205000062A300000000048062A1020000000C8B0 +:10206000062A100000000002062A31280000008E17 +:10207000022A336800000000042A3370000202F9CB +:10208000042A3B90000402FB042A3E20000202FFC7 +:10209000022A151800000001022A18300000000072 +:1020A000022A183800000000042A18200002030148 +:1020B000062A4AC000000002062A4B000000000465 +:1020C000042A1F4800020303022B0800000000003E +:1020D000042B0C0000100305022B08000100000077 +:1020E000042B0C4000080315022B0800020000001E +:1020F000042B0C600008031D062A3BA000000014FE +:10210000062A3C4000000024062A14000000000AB1 +:10211000062A145000000006062A3378000000FC4E +:10212000022A3B5800000000042A3D7800020325E3 +:10213000042A3D8800100327022A15000000000031 +:10214000022A150800000001062A502000000002A3 +:10215000062A503000000002062A5000000000024B +:10216000062A501000000002022A50400000000021 +:10217000062A50480000000E022A50B80000000154 +:10218000042A4AC800020337062A4B100000004206 +:10219000062A4D2000000004062A3BF0000000142F +:1021A000062A3CD000000024062A14280000000A59 +:1021B000062A146800000006062A3768000000FCA2 +:1021C000022A3B5C00000000042A3D800002033923 +:1021D000042A3DC80010033B022A15040000000039 +:1021E000022A150C00000001062A502800000002F7 +:1021F000062A503800000002062A5008000000029B +:10220000062A501800000002022A50440000000074 +:10221000062A50800000000E022A50BC0000000177 +:10222000042A4AD00002034B062A4C180000004240 +:10223000062A4D30000000040210100800000001C2 +:10224000021010000003D000021010040000003D36 +:10225000091018000200034D091011000020054D5F +:102260000610118000000002091011880006056D9B +:10227000061011A00000001806102400000000E065 +:102280000210201C000000000210202000000001AD +:10229000021020C000000001021020040000000114 +:1022A000021020080000000109103C000005057321 +:1022B00009103C2000050578091038000005057D4F +:1022C00002104028000000100210404400003FFFB0 +:1022D0000210405800280000021040840084924AF6 +:1022E0000210405800000000061080680000000442 +:1022F00002108000000010800610802800000002FC +:102300000210803800000010021080400000FFFF23 +:10231000021080440000FFFF021080500000000007 +:102320000210810000000000061081200000000261 +:1023300002108008000002B50210801000000000AA +:10234000061082000000004A021081080001FFFF11 +:1023500006108140000000020210800000001A8078 +:102360000610900000000024061091200000004A92 +:10237000061093700000004A061095C00000004A45 +:10238000021080040000108006108030000000025F +:102390000210803C00000010021080480000FFFF87 +:1023A0000210804C0000FFFF02108054000000006B +:1023B00002108104000000000610812800000002C5 +:1023C0000210800C000002B5021080140000000012 +:1023D000061084000000004A0210810C0001FFFF7B +:1023E00006108148000000020210800400001A80DC +:1023F0000610909000000024061092480000004A49 +:10240000061094980000004A061096E80000004A62 +:102410000212049000E383400212051400003C10F5 +:1024200002120494FFFFFFFF02120498FFFFFFFF58 +:102430000212049CFFFFFFFF021204A0FFFFFFFF38 +:10244000021204A4FFFFFFFF021204A8FFFFFFFF18 +:10245000021204ACFFFFFFFF021204B0FFFFFFFFF8 +:10246000021204B8FFFFFFFF021204BCFFFFFFFFD0 +:10247000021204C0FFFFFFFF021204C4FFFFFFFFB0 +:10248000021204C8FFFFFFFF021204CCFFFFFFFF90 +:10249000021204D0FFFFFFFF021204DCFFFFFFFF68 +:1024A000021204E0FFFFFFFF021204E4FFFFFFFF40 +:1024B000021204E8FFFFFFFF021204ECFFFFFFFF20 +:1024C000021204F0FFFFFFFF021204F4FFFFFFFF00 +:1024D000021204F8FFFFFFFF021204FCFFFFFFFFE0 +:1024E00002120500FFFFFFFF02120504FFFFFFFFBE +:1024F00002120508FFFFFFFF0212050CFFFFFFFF9E +:1025000002120510FFFFFFFF021204D4FFFF333059 +:10251000021204D8FFFF3340021204B4F00030006E +:1025200002120390000000080212039C0000000841 +:10253000021203A000000008021203A4000000021F +:10254000021203BC00000004021203C000000005D8 +:10255000021203C400000004021203D000000000B5 +:102560000212036C00000001021203680000003F29 +:10257000021201BC00000040021201C00000180855 +:10258000021201C400000803021201C8000008037F +:10259000021201CC00000040021201D00000000332 +:1025A000021201D400000803021201D8000008033F +:1025B000021201DC00000803021201E00001000326 +:1025C000021201E400000803021201E800000803FF +:1025D000021201EC00000003021201F000000003EF +:1025E000021201F400000003021201F800000003CF +:1025F000021201FC000000030212020000000003AE +:10260000021202040000000302120208000000038C +:102610000212020C0000000302120210000000036C +:10262000021202140000000302120218000000034C +:102630000212021C0000000302120220000000032C +:1026400002120224000000030212022800002403E8 +:102650000212022C0000002F0212023000000009BA +:102660000212023400000019021202380000018434 +:102670000212023C00000183021202400000030625 +:102680000212024400000019021202480000000673 +:102690000212024C00000306021202500000030660 +:1026A00002120254000003060212025800000C86B7 +:1026B0000212025C00000306021202600000030620 +:1026C0000212026400000006021202680000000606 +:1026D0000212026C000000060212027000000006E6 +:1026E00002120274000000060212027800000006C6 +:1026F0000212027C000000060212028000000006A6 +:102700000212028400000006021202880000000685 +:102710000212028C00000006021202900000000665 +:102720000212029400000006021202980000000645 +:102730000212029C00000006021202A00000030622 +:10274000021202A400000013021202A800000006F8 +:10275000021202B000001004021202B400001004C1 +:102760000212032400106440021203280010644087 +:10277000021201B0000000010600A00000000016D7 +:102780000200A06CBF5C00000200A070FFF51FEF0C +:102790000200A0740000FFFF0200A078500003E0D8 +:1027A0000200A07C000000000200A0800000A00049 +:1027B0000600A084000000050200A0980FE00000C1 +:1027C0000600A09C000000140200A0EC555400007C +:1027D0000200A0F0555555550200A0F400005555D3 +:1027E0000200A0F8000000000200A0FC5554000008 +:1027F0000200A100555555550200A1040000555591 +:102800000200A108000000000200A22C000000004D +:102810000600A230000000030200A06000000007D4 +:102820000200A10CBF5C00000200A110FFF51FEF29 +:102830000200A1140000FFFF0200A118500003E0F5 +:102840000200A11C000000000200A1200000A00066 +:102850000600A124000000050200A1380FE00000DE +:102860000600A13C000000140200A18C5554000099 +:102870000200A190555555550200A19400005555F0 +:102880000200A198000000000200A19C5554000025 +:102890000200A1A0555555550200A1A400005555B0 +:1028A0000200A1A8000000000200A23C00000000FD +:1028B0000600A240000000030200A0640000000720 +:1028C00000000000000000000000002E00000000DA +:1028D00000000000000000000000000000000000F8 +:1028E00000000000000000000000000000000000E8 +:1028F00000000000000000000000000000000000D8 +:1029000000000000000000000000000000000000C7 +:1029100000000000000000000000000000000000B7 +:10292000002E005000000000000000000000000029 +:102930000000000000000000000000000000000097 +:102940000000000000000000000000000050008DAA +:102950000000000000000000000000000000000077 +:102960000000000000000000000000000000000067 +:102970000000000000000000008D00920092009610 +:102980000096009A00000000000000000000000017 +:102990000000000000000000000000000000000037 +:1029A00000000000009A00DB00DB00E900E900F70E +:1029B0000000000000000000000000000000000017 +:1029C0000000000000000000000000000000000007 +:1029D00000000000000000000000000000000000F7 +:1029E00000000000000000000000000000000000E7 +:1029F00000000000000000000000000000000000D7 +:102A000000000000000000000000000000000000C6 +:102A100000000000000000000000000000000000B6 +:102A200000000000000000000000000000000000A6 +:102A30000000000000000000000000000000000096 +:102A40000000000000000000000000000000000086 +:102A50000000000000000000000000000000000076 +:102A60000000000000000000000000000000000066 +:102A70000000000000000000000000000000000056 +:102A800000F700FE00000000000000000000000051 +:102A90000000000000000000000000000000000036 +:102AA0000000000000000000000000000000000026 +:102AB0000000000000000000000000000000000016 +:102AC0000000000000000000000000000000000006 +:102AD000000000000000000000FE01030103010EE1 +:102AE000010E0119000000000000000000000000BD +:102AF00000000000000000000000000000000000D6 +:102B000000000000000000000000000000000000C5 +:102B100000000000000000000000000000000000B5 +:102B200000000000000000000000000000000000A5 +:102B30000119011A00000000000000000000000060 +:102B40000000000000000000000000000000000085 +:102B5000000000000000000000000000011A013E1B +:102B60000000000000000000000000000000000065 +:102B70000000000000000000000000000000000055 +:102B80000000000000000000013E016400000000A1 +:102B90000000000000000000000000000000000035 +:102BA0000000000000000000000000000000000025 +:102BB00000000000016401A300000000000000000C +:102BC0000000000000000000000000000000000005 +:102BD00000000000000000000000000000000000F5 +:102BE00001A301DE00000000000000000000000062 +:102BF00000000000000000000000000000000000D5 +:102C000000000000000000000000000001DE0224BF +:102C10000224022C022C02340000000000000000FC +:102C200000000000000000000000000000000000A4 +:102C300000000000000000000234027102710278FE +:102C40000278027F00000000000000000000000089 +:102C50000000000000000000000000000000000074 +:102C600000000000027F0280000000000000000061 +:102C70000000000000000000000000000000000054 +:102C80000000000000000000000000000000000044 +:102C9000028002920000000000000000000000001E +:102CA0000000000000000000000000000000000024 +:102CB000000000000000000000000000029202A7D7 +:102CC00002A702AA02AA02AD000000000000000054 +:102CD00000000000000000000000000000000000F4 +:102CE000000000000000000002AD02DB0000000058 +:102CF00000000000000000000000000000000000D4 +:102D000000000000000000000000000000000000C3 +:102D10000000000002DB0362000000000000000071 +:102D200000000000000000000000000000000000A3 +:102D30000000000000000000000000000000000093 +:102D4000036203690369036D036D037100000000F2 +:102D50000000000000000000000000000000000073 +:102D6000000000000000000000000000037103B03C +:102D700003B003B803B803C0000000000000000067 +:102D80000000000000000000000000000000000043 +:102D9000000000000000000003C004130413042717 +:102DA0000427043B000000000000000000000000B9 +:102DB0000000000000000000000000000000000013 +:102DC00000000000043B044300000000000000007D +:102DD00000000000000000000000000000000000F3 +:102DE00000000000000000000000000000000000E3 +:102DF000044304490000000000000000000000003F +:102E000000000000000000000000000000000000C2 +:102E10000000000000000000000000000449044C15 +:102E200000000000000000000000000000000000A2 +:102E30000000000000000000000000000000000092 +:102E40000000000000000000044C045100000000DD +:102E50000000000000000000000000000000000072 +:102E60000000000000000000000000000000000062 +:102E70000000000004510452045204640464047607 +:102E80000000000000000000000000000000000042 +:102E90000000000000000000000000000000000032 +:102EA000047604E3000000000000000000000000C1 +:102EB0000000000000000000000000000000000012 +:102EC00000000000000000000000000004E304E433 +:102ED00004E404F804F8050C000000000000000001 +:102EE00000000000000000000000000000000000E2 +:102EF00000000000000000000000000000000000D2 +:102F000000010000000204C00003098000040E401C +:102F100000051300000617C000071C8000082140B0 +:102F200000092600000A2AC0000B2F80000C344044 +:102F3000000D3900000E3DC0000F428000104740D8 +:102F400000114C00001250C00013558000145A406C +:102F500000155F00001663C00017688000186D4000 +:102F600000197200001A76C0001B7B80001C804094 +:102F7000001D8500001E89C0001F8E800020934028 +:102F80000000200000004000000060000000800001 +:102F90000000A0000000C0000000E00000010000F0 +:102FA00000012000000140000001600000018000DD +:102FB0000001A0000001C0000001E00000020000CC +:102FC00000022000000240000002600000028000B9 +:102FD0000002A0000002C0000002E00000030000A8 +:102FE0000003200000034000000360000003800095 +:102FF0000003A0000003C0000003E0000004000084 +:103000000004200000044000000460000004800070 +:103010000004A0000004C0000004E000000500005F +:10302000000520000005400000056000000580004C +:103030000005A0000005C0000005E000000600003B +:103040000006200000064000000660000006800028 +:103050000006A0000006C0000006E0000007000017 +:103060000007200000074000000760000007800004 +:103070000007A0000007C0000007E00000080000F3 +:1030800000082000000840000008600000088000E0 +:103090000008A0000008C0000008E00000090000CF +:1030A00000092000000940000009600000098000BC +:1030B0000009A0000009C0000009E000000A0000AB +:1030C000000A2000000A4000000A6000000A800098 +:1030D000000AA000000AC000000AE000000B000087 +:1030E000000B2000000B4000000B6000000B800074 +:1030F000000BA000000BC000000BE000000C000063 +:10310000000C2000000C4000000C6000000C80004F +:10311000000CA000000CC000000CE000000D00003E +:10312000000D2000000D4000000D6000000D80002B +:10313000000DA000000DC000000DE000000E00001A +:10314000000E2000000E4000000E6000000E800007 +:10315000000EA000000EC000000EE000000F0000F6 +:10316000000F2000000F4000000F6000000F8000E3 +:10317000000FA000000FC000000FE00000100000D2 +:1031800000102000001040000010600000108000BF +:103190000010A0000010C0000010E00000110000AE +:1031A000001120000011400000116000001180009B +:1031B0000011A0000011C0000011E000001200008A +:1031C0000012200000124000001260000012800077 +:1031D0000012A0000012C0000012E0000013000066 +:1031E0000013200000134000001360000013800053 +:1031F0000013A0000013C0000013E0000014000042 +:10320000001420000014400000146000001480002E +:103210000014A0000014C0000014E000001500001D +:10322000001520000015400000156000001580000A +:103230000015A0000015C0000015E00000160000F9 +:1032400000162000001640000016600000168000E6 +:103250000016A0000016C0000016E00000170000D5 +:1032600000172000001740000017600000178000C2 +:103270000017A0000017C0000017E00000180000B1 +:10328000001820000018400000186000001880009E +:103290000018A0000018C0000018E000001900008D +:1032A000001920000019400000196000001980007A +:1032B0000019A0000019C0000019E000001A000069 +:1032C000001A2000001A4000001A6000001A800056 +:1032D000001AA000001AC000001AE000001B000045 +:1032E000001B2000001B4000001B6000001B800032 +:1032F000001BA000001BC000001BE000001C000021 +:10330000001C2000001C4000001C6000001C80000D +:10331000001CA000001CC000001CE000001D0000FC +:10332000001D2000001D4000001D6000001D8000E9 +:10333000001DA000001DC000001DE000001E0000D8 +:10334000001E2000001E4000001E6000001E8000C5 +:10335000001EA000001EC000001EE000001F0000B4 +:10336000001F2000001F4000001F6000001F8000A1 +:10337000001FA000001FC000001FE0000020000090 +:10338000002020000020400000206000002080007D +:103390000020A0000020C0000020E000002100006C +:1033A0000021200000214000002160000021800059 +:1033B0000021A0000021C0000021E0000022000048 +:1033C0000022200000224000002260000022800035 +:1033D0000022A0000022C0000022E0000023000024 +:1033E0000023200000234000002360000023800011 +:1033F0000023A0000023C0000023E0000024000000 +:1034000000242000002440000024600000248000EC +:103410000024A0000024C0000024E00000250000DB +:1034200000252000002540000025600000258000C8 +:103430000025A0000025C0000025E00000260000B7 +:1034400000262000002640000026600000268000A4 +:103450000026A0000026C0000026E0000027000093 +:103460000027200000274000002760000027800080 +:103470000027A0000027C0000027E000002800006F +:10348000002820000028400000286000002880005C +:103490000028A0000028C0000028E000002900004B +:1034A0000029200000294000002960000029800038 +:1034B0000029A0000029C0000029E000002A000027 +:1034C000002A2000002A4000002A6000002A800014 +:1034D000002AA000002AC000002AE000002B000003 +:1034E000002B2000002B4000002B6000002B8000F0 +:1034F000002BA000002BC000002BE000002C0000DF +:10350000002C2000002C4000002C6000002C8000CB +:10351000002CA000002CC000002CE000002D0000BA +:10352000002D2000002D4000002D6000002D8000A7 +:10353000002DA000002DC000002DE000002E000096 +:10354000002E2000002E4000002E6000002E800083 +:10355000002EA000002EC000002EE000002F000072 +:10356000002F2000002F4000002F6000002F80005F +:10357000002FA000002FC000002FE000003000004E +:10358000003020000030400000306000003080003B +:103590000030A0000030C0000030E000003100002A +:1035A0000031200000314000003160000031800017 +:1035B0000031A0000031C0000031E0000032000006 +:1035C00000322000003240000032600000328000F3 +:1035D0000032A0000032C0000032E00000330000E2 +:1035E00000332000003340000033600000338000CF +:1035F0000033A0000033C0000033E00000340000BE +:1036000000342000003440000034600000348000AA +:103610000034A0000034C0000034E0000035000099 +:103620000035200000354000003560000035800086 +:103630000035A0000035C0000035E0000036000075 +:103640000036200000364000003660000036800062 +:103650000036A0000036C0000036E0000037000051 +:10366000003720000037400000376000003780003E +:103670000037A0000037C0000037E000003800002D +:10368000003820000038400000386000003880001A +:103690000038A0000038C0000038E0000039000009 +:1036A00000392000003940000039600000398000F6 +:1036B0000039A0000039C0000039E000003A0000E5 +:1036C000003A2000003A4000003A6000003A8000D2 +:1036D000003AA000003AC000003AE000003B0000C1 +:1036E000003B2000003B4000003B6000003B8000AE +:1036F000003BA000003BC000003BE000003C00009D +:10370000003C2000003C4000003C6000003C800089 +:10371000003CA000003CC000003CE000003D000078 +:10372000003D2000003D4000003D6000003D800065 +:10373000003DA000003DC000003DE000003E000054 +:10374000003E2000003E4000003E6000003E800041 +:10375000003EA000003EC000003EE000003F000030 +:10376000003F2000003F4000003F6000003F80001D +:10377000003FA000003FC000003FE000003FE0012C +:1037800000000000000001FF0000020000007FF8C0 +:1037900000007FF8000002920000350000000001E8 +:1037A0000000000300BEBC200000000300BEBC20DF +:1037B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19 +:1037C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09 +:1037D000FFFFFFFF00000000FFFFFFFF00000000F1 +:1037E000FFFFFFFF0000000300BEBC20FFFFFFFF44 +:1037F00000000000FFFFFFFF00000000FFFFFFFFD1 +:103800000000000300BEBC2000002000000040C0FB +:1038100000006180000082400000A3000000C3C0DF +:103820000000E4800001054000012600000146C0C0 +:1038300000016780000188400001A9000001C9C0A3 +:103840000001EA8000020B4000022C0000024CC084 +:1038500000026D8000028E400002AF000002CFC067 +:103860000002F0800003114000033200000352C048 +:1038700000037380000394400003B5000003D5C02B +:103880000003F6800004174000043800000458C00C +:103890000004798000049A40000080000001038049 +:1038A0000001870000020A8000028E0000031180E0 +:1038B000000395000004188000049C0000051F8090 +:1038C0000005A300000626800006AA0000072D8040 +:1038D0000007B100000834800008B80000093B80F0 +:1038E0000009BF00000A4280000AC600000B4980A0 +:1038F000000BCD00000C5080000CD400000D578050 +:10390000000DDB0000007FF800007FF8000003E5F9 +:10391000000015000000190000000000FFFFFFFF7D +:103920004000000040000000400000004000000097 +:103930004000000040000000400000004000000087 +:103940004000000040000000400000004000000077 +:103950004000000040000000400000004000000067 +:103960004000000040000000400000004000000057 +:103970004000000040000000400000004000000047 +:103980004000000040000000400000004000000037 +:103990004000000040000000400000004000000027 +:1039A00000007FF800007FF8000003C80000150049 +:1039B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 +:1039C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 +:1039D00040000000400000004000000040000000E7 +:1039E00040000000400000004000000040000000D7 +:1039F00040000000400000004000000040000000C7 +:103A000040000000400000004000000040000000B6 +:103A100040000000400000004000000040000000A6 +:103A20004000000040000000400000004000000096 +:103A30004000000040000000400000004000000086 +:103A40004000000040000000400000004000000076 +:103A500000001000000020800000310000004180C4 +:103A600000005200000062800000730000008380AC +:103A7000000094000000A4800000B5000000C58094 +:103A80000000D6000000E6800000F700000107807B +:103A90000001180000012880000139000001498060 +:103AA00000015A0000016A8000017B0000018B8048 +:103AB00000019C000001AC800001BD000001CD8030 +:103AC0000001DE000001EE800001FF0000007FF831 +:103AD00000007FF800000207000035001000000021 +:103AE000000028AD000000000001000100350804BE +:103AF000CCCCCCC1FFFFFFFFFFFFFFFF7058103C95 +:103B000000000000CCCC0201CCCCCCCC00000000EA +:103B1000FFFFFFFF400000004000000040000000E9 +:103B20004000000040000000400000004000000095 +:103B30004000000040000000400000004000000085 +:103B40004000000040000000400000004000000075 +:103B50004000000040000000400000004000000065 +:103B60004000000040000000400000004000000055 +:103B70004000000040000000400000004000000045 +:103B80004000000040000000400000004000000035 +:103B900040000000000E01B7011600D60000FFFF34 +:103BA000000000000000FFFF000000000000FFFF19 +:103BB000000000000000FFFF000000000000FFFF09 +:103BC000000000000000FFFF000000000000FFFFF9 +:103BD000000000000000FFFF0000000000100000D7 +:103BE00000000000007201BB012300F30000FFFF92 +:103BF000000000000000FFFF000000000000FFFFC9 +:103C0000000000000000FFFF000000000000FFFFB8 +:103C1000000000000000FFFF000000000000FFFFA8 +:103C2000000000000000FFFF000000000010000086 +:103C300000000000FFFFFFF3320FFFFF0C30C30C4A +:103C4000C30C30C3CF3CF300F3CF3CF30000CF3CB8 +:103C5000CDCDCDCDFFFFFFF130EFFFFF0C30C30C1A +:103C6000C30C30C3CF3CF300F3CF3CF30001CF3C97 +:103C7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C85 +:103C8000C30C30C3CF3CF300F3CF3CF30002CF3C76 +:103C9000CDCDCDCDFFFFF4061CBFFFFF0C30C3051B +:103CA000C30C30C3CF300014F3CF3CF30004CF3C3F +:103CB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C59 +:103CC000C30C30C3CF3CF300F3CF3CF30008CF3C30 +:103CD000CDCDCDCDFFFFFFFA302FFFFF0C30C30C51 +:103CE000C30C30C3CF3CF300F3CF3CF30010CF3C08 +:103CF000CDCDCDCDFFFFFFF731EFFFFF0C30C30C73 +:103D0000C30C30C3CF3CF300F3CF3CF30020CF3CD7 +:103D1000CDCDCDCDFFFFFFF5302FFFFF0C30C30C15 +:103D2000C30C30C3CF3CF300F3CF3CF30040CF3C97 +:103D3000CDCDCDCDFFFFFFF3310FFFFF0C30C30C16 +:103D4000C30C30C3CF3CF300F3CF3CF30000CF3CB7 +:103D5000CDCDCDCDFFFFFFF1310FFFFF0C30C30CF8 +:103D6000C30C30C3CF3CF300F3CF3CF30001CF3C96 +:103D7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C84 +:103D8000C30C30C3CF3CF300F3CF3CF30002CF3C75 +:103D9000CDCDCDCDFFFFF4061CBFFFFF0C30C3051A +:103DA000C30C30C3CF300014F3CF3CF30004CF3C3E +:103DB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C58 +:103DC000C30C30C3CF3CF300F3CF3CF30008CF3C2F +:103DD000CDCDCDCDFFFFFFFA302FFFFF0C30C30C50 +:103DE000C30C30C3CF3CF300F3CF3CF30010CF3C07 +:103DF000CDCDCDCDFFFFFFF730EFFFFF0C30C30C73 +:103E0000C30C30C3CF3CF300F3CF3CF30020CF3CD6 +:103E1000CDCDCDCDFFFFFFF5304FFFFF0C30C30CF4 +:103E2000C30C30C3CF3CF300F3CF3CF30040CF3C96 +:103E3000CDCDCDCDFFFFFFF331EFFFFF0C30C30C35 +:103E4000C30C30C3CF3CF300F3CF3CF30000CF3CB6 +:103E5000CDCDCDCDFFFFFFF1310FFFFF0C30C30CF7 +:103E6000C30C30C3CF3CF300F3CF3CF30001CF3C95 +:103E7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C83 +:103E8000C30C30C3CF3CF300F3CF3CF30002CF3C74 +:103E9000CDCDCDCDFFFFF4061CBFFFFF0C30C30519 +:103EA000C30C30C3CF300014F3CF3CF30004CF3C3D +:103EB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C57 +:103EC000C30C30C3CF3CF300F3CF3CF30008CF3C2E +:103ED000CDCDCDCDFFFFFFFA302FFFFF0C30C30C4F +:103EE000C30C30C3CF3CF300F3CF3CF30010CF3C06 +:103EF000CDCDCDCDFFFFFF97056FFFFF0C30C30C7D +:103F0000C30C30C3CF3CC000F3CF3CF30020CF3C08 +:103F1000CDCDCDCDFFFFFFF5310FFFFF0C30C30C32 +:103F2000C30C30C3CF3CF300F3CF3CF30040CF3C95 +:103F3000CDCDCDCDFFFFFFF3320FFFFF0C30C30C13 +:103F4000C30C30C3CF3CF300F3CF3CF30000CF3CB5 +:103F5000CDCDCDCDFFFFFFF1310FFFFF0C30C30CF6 +:103F6000C30C30C3CF3CF300F3CF3CF30001CF3C94 +:103F7000CDCDCDCDFFFFFFF6305FFFFF0C30C30C82 +:103F8000C30C30C3CF3CF300F3CF3CF30002CF3C73 +:103F9000CDCDCDCDFFFFF4061CBFFFFF0C30C30518 +:103FA000C30C30C3CF300014F3CF3CF30004CF3C3C +:103FB000CDCDCDCDFFFFFFF2304FFFFF0C30C30C56 +:103FC000C30C30C3CF3CF300F3CF3CF30008CF3C2D +:103FD000CDCDCDCDFFFFFF8A042FFFFF0C30C30CEA +:103FE000C30C30C3CF3CC000F3CF3CF30010CF3C38 +:103FF000CDCDCDCDFFFFFF9705CFFFFF0C30C30C1C +:10400000C30C30C3CF3CC000F3CF3CF30020CF3C07 +:10401000CDCDCDCDFFFFFFF5310FFFFF0C30C30C31 +:10402000C30C30C3CF3CF300F3CF3CF30040CF3C94 +:10403000CDCDCDCDFFFFFFF3300FFFFF0C30C30C14 +:10404000C30C30C3CF3CF300F3CF3CF30000CF3CB4 +:10405000CDCDCDCDFFFFFFF1300FFFFF0C30C30CF6 +:10406000C30C30C3CF3CF300F3CF3CF30001CF3C93 +:10407000CDCDCDCDFFFFFFF6305FFFFF0C30C30C81 +:10408000C30C30C3CF3CF300F3CF3CF30002CF3C72 +:10409000CDCDCDCDFFFFF4061CBFFFFF0C30C30517 +:1040A000C30C30C3CF300014F3CF3CF30004CF3C3B +:1040B000CDCDCDCDFFFFFFF2304FFFFF0C30C30C55 +:1040C000C30C30C3CF3CF300F3CF3CF30008CF3C2C +:1040D000CDCDCDCDFFFFFFFA302FFFFF0C30C30C4D +:1040E000C30C30C3CF3CF300F3CF3CF30010CF3C04 +:1040F000CDCDCDCDFFFFFF97040FFFFF0C30C30CDC +:10410000C30C30C3CF3CC000F3CF3CF30020CF3C06 +:10411000CDCDCDCDFFFFFFF5300FFFFF0C30C30C31 +:10412000C30C30C3CF3CF300F3CF3CF30040CF3C93 +:10413000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C47 +:10414000C30C30C3CF3CF3CCF3CF3CF30000CF3CE7 +:10415000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C27 +:10416000C30C30C3CF3CF3CCF3CF3CF30001CF3CC6 +:10417000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C07 +:10418000C30C30C3CF3CF3CCF3CF3CF30002CF3CA5 +:10419000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CE7 +:1041A000C30C30C3CF3CF3CCF3CF3CF30004CF3C83 +:1041B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CC7 +:1041C000C30C30C3CF3CF3CCF3CF3CF30008CF3C5F +:1041D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CA7 +:1041E000C30C30C3CF3CF3CCF3CF3CF30010CF3C37 +:1041F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C87 +:10420000C30C30C3CF3CF3CCF3CF3CF30020CF3C06 +:10421000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C66 +:10422000C30C30C3CF3CF3CCF3CF3CF30040CF3CC6 +:10423000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C46 +:10424000C30C30C3CF3CF3CCF3CF3CF30000CF3CE6 +:10425000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C26 +:10426000C30C30C3CF3CF3CCF3CF3CF30001CF3CC5 +:10427000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C06 +:10428000C30C30C3CF3CF3CCF3CF3CF30002CF3CA4 +:10429000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CE6 +:1042A000C30C30C3CF3CF3CCF3CF3CF30004CF3C82 +:1042B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CC6 +:1042C000C30C30C3CF3CF3CCF3CF3CF30008CF3C5E +:1042D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CA6 +:1042E000C30C30C3CF3CF3CCF3CF3CF30010CF3C36 +:1042F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C86 +:10430000C30C30C3CF3CF3CCF3CF3CF30020CF3C05 +:10431000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C65 +:10432000C30C30C3CF3CF3CCF3CF3CF30040CF3CC5 +:10433000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C45 +:10434000C30C30C3CF3CF3CCF3CF3CF30000CF3CE5 +:10435000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C25 +:10436000C30C30C3CF3CF3CCF3CF3CF30001CF3CC4 +:10437000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C05 +:10438000C30C30C3CF3CF3CCF3CF3CF30002CF3CA3 +:10439000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CE5 +:1043A000C30C30C3CF3CF3CCF3CF3CF30004CF3C81 +:1043B000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CC5 +:1043C000C30C30C3CF3CF3CCF3CF3CF30008CF3C5D +:1043D000CDCDCDCDFFFFFFFF30CFFFFF0C30C30CA5 +:1043E000C30C30C3CF3CF3CCF3CF3CF30010CF3C35 +:1043F000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C85 +:10440000C30C30C3CF3CF3CCF3CF3CF30020CF3C04 +:10441000CDCDCDCDFFFFFFFF30CFFFFF0C30C30C64 +:10442000C30C30C3CF3CF3CCF3CF3CF30040CF3CC4 +:10443000CDCDCDCD0010000000070100000281703D +:10444000000B81980002025000010270000F0280F0 +:1044500000010370000800000008008000028100D5 +:10446000000B8128000201E0000102000007021099 +:1044700000020280000F0000000800F000028170BE +:10448000000B81980002025000010270000B828034 +:1044900000080338001000000008010000028180BD +:1044A000000B81A80002026000018280000E829849 +:1044B0000008038000028000000B8028000200E05A +:1044C000000101000000811000000118CCCCCCCC10 +:1044D000CCCCCCCCCCCCCCCCCCCCCCCC000020002C +:1044E000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC0C +:1044F00000002000CCCCCCCCCCCCCCCCCCCCCCCC0C +:10450000CCCCCCCC0000200000000000000000005B +:104510001F8B08000000000000FFFB51CFC0F0031C +:104520008A45D91918FC3811FCA18059981918D856 +:10453000809803883D80B8819181A1919178FDDABE +:10454000620876BF3003C36E20E611029A23821000 +:104550009F0254F306C85F0F15B312656038263A00 +:10456000F07EA706DE2A8D29364512C1DE86451E5D +:10457000196F4793FF2289CADF4140FF40632965D5 +:1045800054BE9D22845EA604A1A5D1E4EDA1F2D77C +:10459000A1FE9251C66EEE0DA83C00F85C49656024 +:1045A00003000000000000001F8B08000000000056 +:1045B00000FFED7D0B7854D5B5F03E73CE9C994944 +:1045C000CE4C4E4212F2224C1288A0210CAF808AAF +:1045D0007F270122F539202858D40142087983D455 +:1045E0004BAFEDCD8424101135F447058B76885000 +:1045F000D1A20D34D260C10E20147B6D6FF0FAC0D1 +:10460000EAF50B4841312FB1207EC5CBBFD6DAE7A2 +:1046100064E64C2680D8DBAFFFFFFDB4B8D9E7ECE9 +:10462000B3F7DAEBB5D75A7BED3D92750293BFC76E +:10463000D845FC03E54F4D8CB109C1F26766F680A1 +:104640002787B1C9BDFE3A473C63556D193BA29D12 +:104650008C25EC9921142850FED5232C5082DFBFE5 +:1046600065C397F0FFB619423E7C97D0E911E6C3C7 +:10467000FBE4D5026B873A939C310CEA8CB9194B59 +:10468000642C6B12A33F224B8D82FFE07325398F80 +:10469000B134FC2774754661AEC078C6321E535CD7 +:1046A000D4D0A93815783F847FC6D2BC25B731074E +:1046B00063CF03BCC971F0BC5A3ADE61E5EF2EC28C +:1046C000DFA1F33A6ACD58AE303E7732A789654113 +:1046D000BF3EE3F3AC46633D9BD9E34F46C33FEC9B +:1046E000CC7E518C308F13B18C013CCB540E2F6398 +:1046F000BDB26754101F9B6A58A2322C580F2F85E9 +:1047000065873356035E97ED165C16F8FE396C2FFD +:1047100031E6D7BE6BD6EA153E5962A3A10404B5B3 +:10472000E4F4EF6711CBBF11F1FE302BA0B24AEADF +:10473000955580AFAA5A76FB95FEED673389E8540C +:1047400029B9F65B61FCDE5AE66A86F19799D502D3 +:10475000AC2FFB91D3E5837A6663472183FAD03689 +:10476000818919C1EFAF009EDB917F001E2A2BA526 +:10477000DE420674ECDD2BB0E60C1C87F7BB6C77D1 +:1047800006F3650C0CE758662638E732413A89741F +:10479000713007D2C1BC24F38942A8CE54DCF3B0F7 +:1047A0007F9FE29D87EDF4E7490BE638BD0057F2A5 +:1047B0005066A057B1B53A9D653256EA692944BEA4 +:1047C00038B5EC8D5558029E1324C0F77C8BA70892 +:1047D000FBA998579DCD80A7E659188D3FB42DFFB2 +:1047E0003309F80CBAF3C5C4213F31763C844FF04D +:1047F000CFF1115A5D1C98DE972B8BB01F09F10584 +:104800007217011F3F42A026E0284D543A57FC2959 +:104810006BD8A0D0FA5B59C3C66900E511BC0C3F48 +:1048200061AC4308E54BBD1CBA3BFFB0943B303C48 +:10483000FFD3F30474127EAB00B7C81F1576D9BF3F +:1048400012F861CAABE6C0F7803F2A360B7E0BD464 +:104850004DAFDBE87DF7265E0FD86537F24FD716F0 +:10486000A80BF0BDA5FDF11B91BF5E155933763B3A +:1048700022CA84FAE5A4063B1B0F75C047B18D57C9 +:104880002B36EFBB1FBF2F69B3301BF457B17BF141 +:104890001D37427DF16133C326155B6BE514A82FEC +:1048A000F10B2D58EF29E0F0F97689FEADD0BEC7A7 +:1048B000D19E381BE873BAC6CA9C326375F6F6C43B +:1048C00059C067A5FE1D85F85DE976C185689FF230 +:1048D000EAD643C938AF17B97C976D8B664E1D7FFA +:1048E000F0F764AB18F81EBC5F06F364D0EF62D635 +:1048F00054887AB062EB3AD9690FE2EB748D4AE3DF +:10490000F4C9DF8B300E7C57F98AE0C229569A9899 +:1049100017E5B07BB76DCEF30ACEAF56CEB6E3BC8B +:1049200056CBD86EB17FFE2E54CDA5FECD7221BCE4 +:104930002FDDB4592E0E91DBB26D838C706DC81AC9 +:10494000EC8D20D7417880D7B283F552D403A80FDD +:1049500025BF3C2384CF2A8558E2CBB26D22731A3F +:10496000F888D3DDF72EFC13F0E5DB6B27BCEA7487 +:10497000EBD3A71ADDCEA81A1DA5DEBC1911F8F8D5 +:1049800071A403C0D384788272AD069F6332CB9743 +:10499000A07F879BA902BB3C5F3699D97C0663F553 +:1049A000B007DDD2F55097D952E682F550FAB17BC7 +:1049B0002AD49304EF67389F7AC15BC2D7AB9624A1 +:1049C0000FE07995C0E6E0FC8F21D030AF55C9C02B +:1049D0009F80F7A66979CF8B82067B3CD68B7FB10F +:1049E0002683FA3943FD98A19FACCBF7A3164E322C +:1049F000F4A31696E8FDFC8DFAB15D593F4D85375D +:104A000018E1292CD5FB910468576FBFB279A937FB +:104A10004F36C2737339F5133BD5C5BC0AAEE71ADE +:104A20003FB076B708EF95EDB163D7B050BE2850D0 +:104A30000580DB0E5212CA173193A20C7C18EB8E44 +:104A400033D4A127F5E47541FD138895697C394578 +:104A500026BD909F62A5FA43290AE985876EF05E1C +:104A600083EB208ECD92A12E7B47AB11F81AE01478 +:104A7000581296601724F57FBFDACCF150907A2156 +:104A8000FB187C5F65EACD8E85FA35A6FC6B116F4D +:104A90002E81EBE528915563BB280B23FDB43A2307 +:104AA000EF795F089E1A8700FD8560BF8D666F12E3 +:104AB000F2D7F8DA677C12C0B76A08CC2705BA12B9 +:104AC0009E09F8603D5A3DA43809F1699141BE4301 +:104AD000C79761FC1C1AFF06C4A31BC74FE83FBE63 +:104AE000257392617C6B7A89617CAB0CE303BF4FC9 +:104AF000AD6DD6C607FCDDC0D834A199C6B7A49762 +:104B0000D0F8AB655662183FAA6FFC5B70FE9E81C1 +:104B1000E69F798371FEE9A5C6F9CB7CFEB36A5F97 +:104B2000D2C68FA2F9CF165EE2F34F2FE5F3B7F0AE +:104B30007EFBC677F4E1FF5E9CBF7780F12D599331 +:104B40008DF31F5A6E9CBF858F5F54BB531B5FA1B3 +:104B5000F117093BF9FC8796D3F8B2C5EB423E92B8 +:104B600053A3AAFD684FA481400C261DE5A672043C +:104B70001805A01F860A9904C743519CEFCE450132 +:104B8000BF29417DC7FC2051A0CF2A359E2FDB9E37 +:104B90002FA39EA5F7896837F13F456D22AD376C8D +:104BA000BDC53F1CE0ED6E137D582F5A7F935FA467 +:104BB000F58EDBE560C605F0F95F9E1CD51C3AAFAB +:104BC000F0725193F96487418E383CBE0236A21AC6 +:104BD000E06B47269810AC9F043D0AC62F3B0E7A27 +:104BE00014CB53666E8F9C003DCBE450B9A9E5F61B +:104BF000888FBD9303F3BA5B83FFA4C4F17D72B9C0 +:104C0000E047FC9F5BB75446FDB4A8098CE91079D6 +:104C1000AFD2E8D4BBDBE26F16089F4EC4CF3D2471 +:104C20008A8CFD9766D72FDE30C8F0DD3CE66F48F2 +:104C300082F60BD7CE1FA2C2FC7F30C73216ED53CF +:104C400090845413C9314B35816F31A7759D391547 +:104C50002AF7CC311BECFAB95E63FD0725C67AB79B +:104C6000D96F36A1BDB144609BA1DFFBAA8DEFF5E2 +:104C7000713609719CAEDA7877277278EFC3722C9F +:104C80003E5689AEF7ABFC5B1D9EAA87CD2C40EB50 +:104C9000654702433AFA12C85EF3AA7CDEE1F0DE11 +:104CA0006FB6BA3D00CFFD3F12099FE1F077BC1E01 +:104CB000ED36811DD7B1E14B33DAB7E1F30987FF58 +:104CC0008115E1F35165D4F7F37DE1CF399F84F38A +:104CD00053555BFEA01321ED2A5ABE3FE844087FDE +:104CE000956D9B61A82FF1CF35B45FBC61BEE1FD2E +:104CF000A2A62586F70B1B971AEAF37D3F32B47FF5 +:104D00006045ADE1FD7DD58F18DEFFA0649DA13E1D +:104D1000D7BBD1D0FE9E399B0DEF4DAF8FBC13E5B5 +:104D2000A8EE5D91E1BA715639F938DA836715C991 +:104D300085F4F8B42689E4E0748D93CAEEB6715612 +:104D40002FD783C50C4C9C5EE19CAF7132EA65465F +:104D5000FAF3AFC2059F0FEA7F139C843F7183CCA7 +:104D600002C0C2028BEBE3E35E31E47DC765DE6F18 +:104D700000411FD7FFBDD811F97955F3FCA16A0492 +:104D8000FF2128B72C15D7B91E6D7D0F7F5F2E3000 +:104D90004FE873C656929CD769EB4CB9CCF541F9F4 +:104DA000CEE402F4BFCBE54076F5A5C66B01A4A224 +:104DB0009E44EB3C01F901A4C0C02F5906F9EEDC7A +:104DC00027125C95A81340AFAE639EC126D43381F1 +:104DD00003E9778D4238DC49546F4BA075BDB3664B +:104DE000FAA01312D2C743E5A73573A83C59E3A52F +:104DF000F2444D0995C76BAAA9ECA85941E5C735FE +:104E00003E2A3FAA69A4F2CF354D541EADD940E5E4 +:104E10007B357E2ABB6BDC54F6F92BBAFE8DD7ECC2 +:104E200055CDAF809587EA67B4B9D443DB769273EA +:104E30005712CAF919E55C36DAE3678E8263993155 +:104E400030BEC2F96D603ABAC95E29F603FDC7F5F6 +:104E50007F6F8BE274B299D87470A6D923C37FE1B7 +:104E60005A9043750959061624D70C7B847E61ED50 +:104E7000437A5D8E4ECCDD9B3B13E871F299BFE522 +:104E800061BF75DAFA177540A47598059E7721BD44 +:104E900042F046EB5AEFAB9ABEBF0CFEBAFAF0D71F +:104EA0009E8EFEFB4141A5FECFB45A988478DC1358 +:104EB000ED07E667670E3FEF40795C9664524F441A +:104EC000C0835E56B464A84AE8FAD366AC9F691200 +:104ED000A6B7D07AEC8C99350AF94A554F0C43FAAB +:104EE0002751A9F7B32C49564F80BC9EDE9615C3B7 +:104EF000D76F3F5F07B7C712BF825F48EDFFDEF095 +:104F00000CD48F0E0F63ADEC132BEA037897F5EDFD +:104F1000FD7226FD95E2576C8FF91CDA0B16F87BB3 +:104F200091E20712D5F57EAB5A449F65343EDF6EA1 +:104F3000180FBE73EA3EF7C5CC4BF1ADC44E86C424 +:104F400011D669F1C6B26D36D5B8AEC41AEA556D40 +:104F5000C9AA619DC17F80FCB36A4142BE29D7B80E +:104F6000A847521A0580AFDCE4A47EAB04DEAEC2D3 +:104F7000DA217BE151572BA7DB40F09DAE39EC9451 +:104F800040DE4BACE001027C252D23A7A29EEB6AFC +:104F9000AD4B447BB04C3CF39027C2F73B4D028DA8 +:104FA000B7C46FEE35AEA31A7F30E8577F4E7E163A +:104FB000534E86D43B4DDCCE0EEFF780D6EFE5F0B6 +:104FC00053B9FD48E18DCEFE78AA6CFB42F6921CE7 +:104FD000C1FFF28278D2F1576EF21C407D5ABAEDD1 +:104FE00018D9A39F9A7DD90F5F423FF59F9F9244A6 +:104FF00071527D5E3E3029619C055A7C17F8F79E00 +:105000000F613DFDECDFCD6C0DC0C72E402B786FDE +:10501000D65F331333417DA1565BD05A4671DDCF45 +:105020004CDC8E2A621E07D18135E5A11DD9C54C05 +:10503000D3114F5DEC6DC7B8103A9C32C9A4671606 +:10504000361AED18B07F0DF5C51B8CF5623633119D +:10505000F549F17A33F30B343FC3FBF74D2AE17F77 +:1050600031AB5E85EBAAA4F9230B5426A5027C156F +:10507000BF79366F3EC65F4CDC0FD1E3234BE2387D +:10508000FCA5F17ED90DEF3F691D77F78D48068BA2 +:105090007F15C689580C736D65FDF1FB6DE10F87B7 +:1050A000575FAFFBC5693438C46D82DB1F817F2F2A +:1050B000687CA6EBEB5B44D5E017DC8DF510BF21D7 +:1050C00046D4E2B2221391EE5DAAD5678AA1F71405 +:1050D000B7F7EDB4B8EA80DE3F3779068913C84EDA +:1050E000C86521ED7E6EF2D2F34EE1AD62B45B99FC +:1050F00014C8453B14D618E25359E30731CA918BC3 +:10510000F1663B837514E86F41F8A09F55F692DB7A +:10511000582EC6BB41DEA1BFC71C858705A8DB94FE +:105120005686FD59928CF17C9BD358AFC27F201DCF +:1051300046308A3F458F90C2F01860A80FED2EE3ED +:10514000F351E88491DD1F203E76108B43695502B0 +:10515000228CCF26499D7DFE5626FA7B1C7E8A2F07 +:1051600040FBE52A6F5FA9C5CF977F503038EE121C +:10517000FAA8EA3C68904121753DBE7F5E62FE71EF +:10518000DF416F3A61550DD19B734DDE69480FD4F5 +:1051900093089F00E3780D76609A1A2AE70BC2F80D +:1051A000E3AAE1886706FD5D6EF2DE2D26F487E353 +:1051B000AAFB4FEAD7FF8248F3BCEAFE87F5EBBFB4 +:1051C0003252FF15BF7979970FF8A9F4574F3A80FB +:1051D00099D9675253A20BE85EBEB5C18172F9A995 +:1051E000E473205D3FF38BD323C9E71651974FB784 +:1051F00022E411FF101F9D7EE9D13BD0AE3AB7D516 +:10520000AC527C609B256001A6AC6C5DC2E5639BE3 +:10521000E518AFAFFE02F9B3AACDA82F4A5F7832E6 +:1052200011E3CD4049CD7F0E907F50B9E52F8568C1 +:105230007755B15ED27BE1DFE1F8E7E3C81E982F36 +:10524000C7F47FAFEFF3556978A96A7DF40B9184B9 +:10525000A583FCCDF0F6259ABDFFA4688FA738DFA3 +:10526000443611F94CC707F3737BBFEEC5A7738FA4 +:10527000013C9D5BFEDD21E484F227D77B675A1653 +:10528000FEFC35E7C0F2D40D7A31D4AED6D76767CD +:105290009BE6A7ECE165B939E0403FB07CB3D9E5C6 +:1052A00043BABEFCFC2F9EC1B8CC0716D770E8BF2E +:1052B000ECE583EFDD00F5B21DE6F8DBF8341421F0 +:1052C0003148972AF8BB626C900EA5BF3E283B4739 +:1052D000F1E73F8E0BD2A36CC73E998DEA8F8F29E1 +:1052E0002DFBE40E25025D5A8E15A23F51F7E257C1 +:1052F00032EAAFCF5E17D8E08C08F8DC7C90EC6225 +:10530000C413D151A3531FDDC2DA57015D50BFEA68 +:10531000740A7FFF2F9AFEC7FE9C39C4CFAFBC86AC +:10532000FB287FB6B870FE25AF3CE8C0799C92AAF6 +:10533000395F3FDB90E886714BCCBE44954AFEBC9A +:10534000E4B91F12BF2D3EF2C3448A7F3077B28981 +:105350006C055F32CE6FD1A6D934BF62E625BE2B75 +:105360007956F4E0FEE059894DDF11412E5224AE0A +:105370008F4F355B704D65A770E1C07D85B745FFE8 +:10538000568AFF2DA5F8CA0FF5FD20B68CEA67AD49 +:105390009C4E5F88FABE1AAC3CA1FCBA65753BD244 +:1053A000E7F410F7608C1B5731C9A7E143B808FD3B +:1053B0008A47A60DE6F4614E294FFB0EF4FD147CDE +:1053C0008EEDDBCD6E5BAEE13B76312338FE726D48 +:1053D0007C803B0AEDD5538960FF45985FA1A4AF5F +:1053E00037605785F057887C7379DFF208976F5DD7 +:1053F000DEFD33A6E3FBBFBEC3E507BF437B05E08D +:105400000A0CA6F7FB6609A40F2C2C1049AEB7981E +:1054100035B936BED7F904E09670DDEDE317EC3F01 +:105420008EF04F766CF17AF82E445F56E1788EFE5E +:10543000FDE972BB5893FF04C928FF6C1397FB81E9 +:10544000FD091F8F4B98FDBF7806E515E413F7AFF4 +:10545000CB5F367B70DE9F6F3FF0DEBD20A79FB72E +:10546000E8726AD49FE1725AB273028B24A79F63D9 +:105470001A42243985E711E554E9203EFE47E94FF9 +:105480001D7F3785E14FD78703E1315C1FFE5974DB +:1054900046D487F0E71D96D79FFF74BED3F9ADF4CD +:1054A000971543293EA6F3A5CE777D7CA9F35DBF72 +:1054B00078A3017FE1EF2D188301B83CBBCD1447E1 +:1054C00028DFC3F77FE1BB43A9E3094F6E5AC658F3 +:1054D000D3A1D4F8D0BA3FACDE12D6DE1D56F78485 +:1054E000B5F786D5AB0DEDCBDB0EC83CAF256068BC +:1054F00027AE78867D322812BFFAB95FDAFA85ECDA +:1055000043BE507AE97BF34AE6B3633C7CAF48F193 +:10551000911EC0F12A18A7677B861FF3241A6C3CE2 +:10552000EED4A3F63AD05E6C88E5F5DE047915EA90 +:105530003DFD79AF8DC7F57A3CBD8ED810FBEDD817 +:105540001E91F476879F4D8FE467C28A4272D4C160 +:10555000067ACFE3FDD344257D05C65F9A441786BE +:10556000748A6AEF71609E41CF9EAC3BE7C0F34501 +:105570006F8AB48DD883767B0C92C72D2587F877F8 +:105580009F32DF5393317EBF87FB79456BC3EC11AC +:10559000B696F8A958592EA33E05BFECB871FF8204 +:1055A000CB45A9D65FC926E37BFD7BDCC145FBBDAE +:1055B000748BF1BD578B0734EB7232868DD1FC7141 +:1055C0001E8FD2F4F23431E7CE39408F9EC322C30E +:1055D000FDFB337B44A2C799ED7CBF9EE2F6D72347 +:1055E0007FF7923ED4F1D489F2240FACAF3A5FFD3D +:1055F000AFBC87916F767D98FB33283B777D90FD1C +:105600005BACFFE6FDF40F59FFF6535EB7D13E49A0 +:10561000CFEB76E2F79EBD7F4C7F18EBBB2D149F3E +:10562000EE79FDAB5CE49F9E959612D4773D438066 +:10563000FE681FECFD2AB783D6D77AA2DB1F259917 +:10564000DB477BFEF6B1108F25CC0AED86D7A34948 +:105650009EAA5EB3513CAD67EF5779A176FF779D67 +:105660004FA5B67FD963677376227CB17CDFA7EA4A +:10567000B7D73F5F8BF917ADFBE485F07ECAEFBE6D +:10568000C9453DDAB393DB43DDE68EE7707FEE6814 +:10569000FDDC9566C073370A550AAC9B0DCF14A08C +:1056A000DCF4C7CB371427BC527CF4FC5F830FC1FA +:1056B000CDF59DDD6F1570DE5F7FFC21EA85D72D6E +:1056C000C497FA7C3F6FA9257BE572F37698799CA5 +:1056D000E4FF9D790B812B99F728F33F37BD7F2D90 +:1056E00039892EE172D09FCFF73E44F597ED2E8297 +:1056F000F70AF9FDF67FF2F97F6BBAEF04BA3B2E99 +:105700003FEFF27FF2790F4CF737EFD7E8AE627ECA +:105710004BD5EFBE21F8BEAD9E5BFB4F2EEF03CD08 +:105720005FB7EBD7985C4D99189F43AF01D669C519 +:105730003EB311C3856B46CC54D1CE14C3F62BF5C2 +:1057400072AF99FB4D22EE5B629C6F088FF331CDF7 +:105750008FA22D3D185A528AC98E959455DCBE965B +:105760005CED6EC0CB9A6B17B82877888D3DEAC583 +:105770007ADA6417C5AFC3FCC97A81B905B06FA5E1 +:105780006B6F398CFE8D79842960C9A5F21896ABB0 +:10579000B5B8A459950D7E8F9263ACDB9CC6BA4513 +:1057A000EBCFCA38FCD624E6C7F8B43872BF8A7982 +:1057B0006DE218890950B7B1261FFA179624E3F74E +:1057C0001B31C01E12CFBD5A3CF6F6E1716CBB1BFB +:1057D000F138D244716B4A2E25BCB8FC6B789E8D93 +:1057E000D588D755ED884F09FD5F6E7F91DFCC34AA +:1057F0007F59D2BA904698DC36633BCD4FBE2C9D84 +:10580000385DD2CB353A2D33D045A74304FA18E89A +:10581000A2E3F9DBD2279C2EE1F8DF6F7612FE07B8 +:10582000A2974E9734C5CD505ECD9ABF3015FD4935 +:10583000ACA77918ED336BFE8214EF663EA493EAB1 +:1058400062482FF4DB02E0B7FD7EFBF31427EA7A0F +:10585000E9D81D084FD96F456605FC756FB7B300D1 +:105860007E2FF965F4434B5B458AFB3329907757CC +:10587000C8BEAF6EF797FDCA4EF329DD69F1DF06AA +:10588000DF97EEFA2497ECB095BDE4D7F85E1238B6 +:10589000DD7D1DB9B8AF5B2A71FF239C5F62659EF9 +:1058A00027D0B93B7A0EC66D846D3CDFB6B4E51ED9 +:1058B000B3C5907F66D6DB915EF0BD2850BE13C2A3 +:1058C000179AE7A9FB1D9D2F0A1CBE36B31FF3765E +:1058D0004BB7EDE8C6F853E9518B0BC3D255DBBE8D +:1058E000A0FD8D29BF7AD9D141FEB668883FF4F377 +:1058F000FBB789C41F95AD15E487409DF8A2B2257A +:1059000072FCEB72FE69D9AFF6EEF2010ACB7EFDB6 +:105910008203E35BA7DBB73AC8FFDF76E9B85B3FFA +:105920003FBFE5914BFAF9A7F11FE0BFDC2087C527 +:1059300049B60D227F04E0CB8B94EFADF35BD9CB5E +:10594000679FC33874E7CECF9F4378CBFFFBCBE78D +:10595000D09F60AFDBD4AD889797DEA5389EFEDD83 +:105960002C99C79DBB5F7C81E29FDD1F80DF017F9B +:10597000BAF79E4A477FB27BC7D789182F59BE779F +:10598000DA609CEFF257A70C6611F4885E22DFFA0A +:10599000AF20FE1A4EAF03AD07C8EFE9027AA3DFCE +:1059A000D917B769A9E07130A716AFD91E39CEDD76 +:1059B0002F3ED37AD79D378DC7D2EC72B22B88D3C6 +:1059C000BC03741C7D05F4DBFE88E67F46A65F17EA +:1059D000FE03E8B42C8C7E675B17FDFC197CD73A7C +:1059E00068C0384DE00AF0A6C7D1BF27BB7F22A30D +:1059F0007CEDFC25C5C5906EB7C144BB5F3E9B8E58 +:105A0000FB0F9F9A7BEFE7E7322C2AC61B4AF7BEB3 +:105A10004FF2D3FDEA118A53332D9EDDCDFAFEF00D +:105A2000F8A3965359B5C5CEE33B1AFE31FEE37495 +:105A3000D0732DCEC3F9588FFF0C14F7699579DE1A +:105A4000881EDFAFD8F2A1164F09D24B9884743A62 +:105A500076C9FD081D0F2AE26162681C33727CADB5 +:105A60002FDEADD10BE987F1CBBE3825D4D3306E14 +:105A7000E517DE6711F441F7661EFFEC3647CEA34B +:105A8000D2E39ABF0A9753FF95C5332F07FFB7C5D7 +:105A90008F5F7652BFE178EABC10598FBF2DF37546 +:105AA000FFAAF7C5CA0543BE41B9C97B04F9B1A233 +:105AB000F598CCCFA5F0F352FA7C3BB5BCD1CE978C +:105AC000448A77AD6A39407A3C5C5FE8FBA6E1F036 +:105AD0009ED0E0AD6CE3EB44E74EBB5F817E3AF7CE +:105AE000EF267EAEDC7E8CE26D87B6FD5AEE08595D +:105AF00057719DF087C0DFF9CABE5C1EB7E579EC2F +:105B0000E1E39CD1F461D59EC8E3546DFFC2304EF1 +:105B100099AF45E6EBFDA5C73B2DB9EFC1FE4EB7EA +:105B20009B19E6799E6E11A7473A17F5AEB66EEA55 +:105B3000E77E70BDA47CFD23FC5CCCF8B7A3281FD6 +:105B40007EF991E91FC6C463098487FE5A6B399FA9 +:105B5000B6FEC49D8AF46E3D72AF88EBD42EC46F3E +:105B6000889D9FF74EF5143BE885BC8F3CE3915D23 +:105B7000C3F5CDC4A32603FC30CE605C07EAA11FA9 +:105B80003CA782F96E088FE8289C8EF088AA49B558 +:105B900009FDE761563C745E40EFD7AC1ACF03B005 +:105BA0000BE39CD84FD24C1E474CBE8B973EFD3C1E +:105BB0004E7194BF0EE659A078D32CF07D927D7D76 +:105BC000C64186E7BF2651DE7696C5786EAC4B554A +:105BD0007C26D0DFCFE46C5937D949F907D7584232 +:105BE000F30F582017F9516FD7EF7D587E421A7E78 +:105BF00002FD881A7C595A7EC210D621A07DBDC9EB +:105C0000CECF270E55E24DF8FDF39ABDA99F3FEC8C +:105C1000775E31EC9CE2E5CE27C64FC95F3AD405EA +:105C2000FCB47ACF14CC5F8FBF277F47AA8A791242 +:105C30007F9E82E757E25FC81F930CF513AB1F9C52 +:105C40004AF5FFC81F930EF56F1AFF8DD7CB04CA14 +:105C5000572D583D7A2AF2EB55CBF92CC08851CEFE +:105C6000EF40BC75793EBA7B9113F31F7A658E5F66 +:105C7000E6C176432671BCA5291FED403C0D357564 +:105C8000D4227FFE7CEF57B1A8179C4C25FCA8AC12 +:105C90005E45FAC1A349172F9147179E4FA6EB9374 +:105CA000CD8AF70184E391F923E85CE0332533AD35 +:105CB0003C5FCF98C7C0D478A26791464F84D31A6F +:105CC000928FBF58F4C9FC5C4C93A6AFA6AA389E2D +:105CD000E02B172F5EF7EDE17A50E74BED5C69C8DA +:105CE00079C687105E9FE27DC892D0FF3CE31D1607 +:105CF000CF0A7C9F5C7C3E1DF95B3F9F187ECE9156 +:105D000049BDA648F65FB376CE7120783D56EF2A9E +:105D10001C37F377CE9D8741BE4617C92E4CCD1C4C +:105D2000BD627C82C4CF15529E439546BF24139713 +:105D300043F610A37DD61E8BE046BFB9E74195F42C +:105D4000775AD16DE457F54467B4603E50CFC3FC39 +:105D50005C29664CA31C0DD9131340BF0FE4E05C13 +:105D6000981C9C33AE73C6717B2E3ADB3AA83F5524 +:105D7000EB0F0CB0C4E0B9E01E91EBE59E1A27C111 +:105D80003184F9F6E1FA7EA5E36DB518CFFD02DEA8 +:105D90005F40BCE878FFE5C0F47B45A3DF2B91E8CA +:105DA000177EFE74BEC5FB6B6C7FAAF8D02A7415F3 +:105DB000C3CF9D86D3B54A6ADA88AE78E29E2F6853 +:105DC0009DD1E9367A852B411A64A0E3EBD8EFE840 +:105DD0003D5F98105E9D7E4F0F90EFFD070B5FCFEC +:105DE000C2C74B9CD391E28DB4FE60102E2158CFD8 +:105DF000B5E6D1F8834D3CDED3BFBD10713ED07FF8 +:105E0000E6A5F2307355DE2FE0FFFD50BEFF10F126 +:105E10003F2222FE3F46BC03FE3FC6F65780FF4F9F +:105E20002E857FDDAE2FD3F44219EE2B01FFFCC58A +:105E300039333113C62D1415E2FF255B456D1FD292 +:105E40007D5B7262508F2CB9BE7A9F19F870C9B30E +:105E500002F16991765EFD73ED5C4B785E5FF11C3B +:105E60001FE9C9CBE7F7F9490F956D333EBF10E441 +:105E7000DB74CAC7F5F1F393A22617E1F83FA368D4 +:105E8000FAA228D6D02E9C0E43AA4D863CF0E429D7 +:105E90007DFD909F976472BE4FF1B53F9819C6077C +:105EA000DC52FCF800E263BC3015FBCDD7E456EFC2 +:105EB0006FE80AE33A9FE1339EFBCB6A349EFB1BFB +:105EC000DE9462687FCD864CC3FB91FE6B0DEFAF15 +:105ED000DB36D6501FD57283A1FDE8B602437D4C58 +:105EE000E01643FB7187671AEA13DAEF35B49F783F +:105EF0007481E1FDF51DA586F7377EBACC50BFA9A8 +:105F0000F75F0DED038BB85EDC5F939486E70A7450 +:105F1000BCEC5F2A9B547CBE34DBA4E6863E4F7407 +:105F20003B73B1CC73A37F3590BC4CB126A785AE33 +:105F3000CFF9CC6CD06B53ACC67A8155E39774E043 +:105F40001720FECD56A35CA556CF6B02B39BA52CA4 +:105F50001946F9D2205FB758B97EBBC57A65FAED0C +:105F60004E6C7FAA3240E7ECC3E54B44F9CAA2D29B +:105F700047FBA9CC45F9961B6D463E4D1A40AFCC68 +:105F8000B31ACFC38BEA619B649013FDF9F9A8D0D3 +:105F9000E7C2E2DB286F67A07EE5A405B76E017D4E +:105FA00029277BA9D49FAF9A638A9897F790F53BEE +:105FB000FA491BFAD94F0F217EBB92DE7E0AF3CC41 +:105FC0002AE7F592BF946C31E22558770DE67954B3 +:105FD0004E7E8E50E5FFDC54D3782BAEF7FA3C179B +:105FE0007D303311F303D206F09F5ED5E6F15C4DB0 +:105FF000C9AD45C3B03FD5147ABF457AA0AA10FDFC +:1060000098A15A1EF453A6C8F94A3FD5FA198C0A2A +:1060100014ED035521FBA0ABF8238704F3F8779325 +:10602000F7A7C8170B46B7E7F173CB6ED74CB2ABE7 +:1060300054825FD743E98AE729D42BE94912736672 +:10604000F48767F03C6F6306BCAF8F33B914AAF7CF +:106050000A389EE5C78C0D82F1EAFF5B24F8EAF767 +:106060005F4FF93C16A59AE2A7FA3C99B6DFAFC795 +:106070008BCF26CD8A413CD65FDB776E8761FDAC46 +:10608000E26DC77ECFAE37D3B8F50582E1BD3E6F76 +:1060900069C31D741E2B5DE1F32E867923DC9634D3 +:1060A0000E57FD73024B23B8FEF7D243E8BFEC8ACC +:1060B0007661BC0DF0B189E8EDCE3867D2270FF3D9 +:1060C000AA18A434AF21FB25B21FFA9695AFDB4C7A +:1060D0009D9588F654F23546B8C5F566F20717C5A2 +:1060E0002A94AFE0AF59A1D1D538EF554933EF9C91 +:1060F0000BF0D4BD23324CFD7176342D3D04DF15F9 +:10610000B746BBFCCEFE78EF72723801EEB7106E68 +:10611000714321CD9BDA21DC3F17D83319C877DED4 +:10612000E944FF1413C37D9770F8FFD3CAE3C4EFAB +:1061300058559A879C547CEB9641581691DC1DB5B6 +:106140000EB8CE7F68E5EBFC87D608EBFCE5EEFDEC +:10615000289FD37E084BD16DD2ECDAEAEC507B1944 +:10616000F4D649EC57AF8B313FCEC57E07B6CB3C5A +:106170004DD91997B7CBD01E43FED3EDB1BF5A8D81 +:106180007664889EFD4AD3B35F5DA19EBD80ED4ECF +:10619000DD1B8868C724C891F5DC381BC77F952AAA +:1061A00033CAE31B209E9F6D8B6C1F0EB40E5DCE19 +:1061B000CFC88CD6F954D7EFDCDF60C532ED2F9C09 +:1061C000D9E07F241BF729E38751DEED40FDA4AE23 +:1061D000F8830DF1ABE36D88CD884FC0A3D3C6F92A +:1061E000C4698B640F96031E4D063C0EC7F603D997 +:1061F0008357ADDF4B8CE76EBA357C839E9771BCBD +:10620000AEBB3ECEC3B845E5EC73A4E7AF7A9C398C +:10621000C67544F7BF611C01E7DF7DD77F6B71B79F +:106220000E8A17D5BD7A4D0CC6A72A0AFAF48695B0 +:10623000DB8599A407BB7659DC0867571CCFE7ECD0 +:10624000DA35F110C6393EAF399C2985D82D5DAFBE +:106250001CC933437F5D3B8FE4499420E7277ED1FF +:10626000DF575CFCCF3C8F123C27D0C76F56BE0E69 +:10627000ADB7F1F8C9D398C7369AB1F7A363F9FA65 +:1062800091687A1C9F47BFE3F3A17E7F5470E5C7F6 +:10629000002B26DD554C66ABE58DA600968F0A6E69 +:1062A00011E355BE91FC3C4D52161B9101FD284750 +:1062B000DB03088EA3A3D78DDB29EAA7EA3E2C0BCC +:1062C00014EF02C47B5CAF2B097DFC37878DB3A133 +:1062D0005F214DE17AB7777E941FEF294A34B98F59 +:1062E00080AA67670E2F8CC5F77F8BE6F2F258D233 +:1062F00089265C8E7039A038D49B665ADF960D7162 +:10630000272F82EF974D88E77EE905987DC839965B +:10631000C7E367091407B9007881E714FA023EB5AC +:106320004BCC173316F4B089B955F00BEC9342EE11 +:10633000D9C1FF6876FC604DFFF6384D3E33E0452D +:106340007619DBD509EE0C5C4F7781FC0D03FAB4AE +:10635000D558A97CAD464D1806F2B8A72689EAAFF4 +:10636000D738A90CD48CA0E7FB6B5C548F36B5A74B +:10637000D37A2C55AF9B87FEF5FD120BBDB723BC1E +:10638000C47B568E87C8F9972EE69300AE2F353D15 +:1063900052FBD638E2AFA7C600D431FDBFFFD98A81 +:1063A0003F644D053D98FAA3C35953418E9F12781F +:1063B000FE021E188E742E552F9F32B7C4A2A9F06C +:1063C0006B1BF34D4DC2BCC8DE3F158E61CCF6E8A9 +:1063D0009FA64E1D09F3C7FDFE14C6F6DADEABC755 +:1063E00073D8A9FB3FAB8B81F9C86DFC3E9F8982B6 +:1063F000A756407D339BF30B933CB598CFD97337A9 +:1064000073E2FEBE3ECE5E1BB71376DBB89D3951FC +:10641000E0FCC1E6CA5A1E416F6EE8BA11DE3EEFDB +:10642000C0D7748F0F8CB72FD5305E2FC51107FAE8 +:106430002E75FFD7B48E5CE9773D1F49FC7C84C480 +:10644000F32BBAE6266EA6FD78681FBA8FDA2347CB +:10645000B6D7DED2D68106EDBEB79F65F07283A6B1 +:106460005724C6F5FF6BD105BF47B961DE38DA5F47 +:10647000AAD3E209933A7AE5F9767E2F5C3ED413EB +:106480004E78043C0FD7A5D13355601ECCFF486031 +:1064900033840228DD36CFDBD84FD2C24DBE97D130 +:1064A0005ED86571A2D9A3E3ABEE03D98AFA216164 +:1064B000CF31DA8FAA133A64A4F7978F7C4D71CB52 +:1064C0003A737532D56D171BB0FEB4BD7A23D699D9 +:1064D000EFEBA96F003F0CD6CEE1E313D463BB9082 +:1064E000E829583B57EF067ED865E6F52F1F394B54 +:1064F000FCB1CB5C3D9F8DE1F57A98EFAE586FAA69 +:1065000009549052FB65FDE19BB0AEB7FF92DA777C +:10651000DB546E3F2ADE0CA47F5F5D85BA3DA42E5E +:10652000F13AB3F2529F5FC581AF297FB8720FE78E +:1065300047C41BCE13EFCDC375E98C7AD451EBA4BD +:10654000B87336D7D701039FE9E753B798BC2C2A15 +:1065500044CF5E085BFF42CED9B1A88490FEB43828 +:10656000763A03BB342B186FCD642E2A87310F95F2 +:10657000D9DB96EE47B42DBBAFD5897A2B3ED7FA3F +:106580008097E868F41F9ED0F4E2FAE8FC1BA301B0 +:106590009EF582778D887AF165B34AE72F3A24B267 +:1065A000373BB5358CAD3053BD5C3BF76D5EE95D77 +:1065B0003312F5EE2293AB19D7B30C4FBE19BE2F91 +:1065C000DB9DE1AA65C1BCE7B2D896C4B14A30EF01 +:1065D00059AF3FAAF1D946B5C986F7D2E8FB439532 +:1065E0006DEBD2717FFBB37D1F903CBD1F95417C4D +:1065F0005CD17A44F6DA69BF4CC6F3299FD9FAD642 +:106600003F5AF7BE6C19740BEAF52FEB4D74B8794D +:10661000203DF406E83F3738C8876AAC54FEC25DB7 +:106620007D2D9ADE055129D36C60B4BF90E9569157 +:106630008FE6ADB9A6C10A7CF482AC8E443E9B17AE +:10664000954B7C5B162B72BE64B907DD92B6CF0DFD +:10665000F5D43565D3BE533CBEC8686F546D5288BF +:106660000FC00EC8473EA8DC60F2E17EA2C9DA4E38 +:10667000E77DE74531CD8F369E4F5CAFE93BDF6C60 +:106680001EDFBDDC39C592F351741E51AFBF1FE54B +:1066900024BE28917CB4FF5572DE41E718BFFB3859 +:1066A00056C379C8FEE32804873E4E79701CD25742 +:1066B000E51FEC273FF88D6B757BD64D71ACE53B44 +:1066C000B4FC059B7B30F6F3B4A62718FAB18077AB +:1066D00029A3AFEE9340CF1CECD333F90D53D390E5 +:1066E000BEC1F76C92410FB925A0D3C128ADEEFB16 +:1066F0007EE4F65161ED33F5FACC86A993FBC3F342 +:10670000B42D58B7427BE91B4B5F1DE1A373F5A184 +:10671000FDC5E9E3DF4BFDE9FC971AB5F0A00FF8E2 +:10672000EF60AC271FF37C7A673327CAE166498D97 +:106730007285D021358AAF3725E7AF35E03F88F73E +:106740005C03FD4FD5380DFB8A8B8B96D17998541D +:106750009D5ECCC7CF776DCA32EC27FE7F38AE1670 +:106760000EF700704CFD07C331C2305E108E1C0363 +:106770007C570B87183B6B7A06DA6B8F98280F28AB +:10678000D1E4B366A25DF66F268AA70C673C0F883A +:1067900029E30DFBB4997B2CF331FE9E29B1C3D2C2 +:1067A000589427B7B316D7A99F48645FC173AB3914 +:1067B0000E876E72E3FD4F2095D45F66B9B7821FD6 +:1067C000F2E6FB82FA3ED37095E5E3BDA09BA3E71A +:1067D000DF188DFB66731EAAC23C98E795F12F3532 +:1067E0003083BC921DD2202C253BE3ABA8871B70C5 +:1067F000BF767014B75B04F670C3E1E448EFB9BC30 +:106800009E5BF3F0348C1B34AF745E8BFE53B3CDC0 +:10681000DFB21FF3761E53E8DED6AC47FD8D9950EC +:1068200017D79968BD1463FDDB9A71DFFDC96C173A +:10683000DA11CD68BF60FB4714F26B56D538D3F040 +:106840007E923A6D1DD8B276B28A79C1F58A1487E4 +:10685000EBDD2A73F55C3C7731EED18D0DD6EB5133 +:106860008FB91A07A9BC9E948CEB9A33D33A467B16 +:106870000FC868AE75A6A8B1C1FAF06FC0FA203D86 +:10688000B3B1C19D86FD2E2BD5FA3B88718A17E2E4 +:1068900034BC68EF33FBF4D2C606CCCB126B83F565 +:1068A000A930DFADCF723D3518FA47FB0BE6E3C3E5 +:1068B0007B057B874B744ECA06633B607EB691991D +:1068C000B4DFD70C7A11EF2BEE1DC9DFEBFB34F2EE +:1068D0007013EDD3607B5C6F6CC9BCBD3C83DF572C +:1068E00020DB158A37C07A3015F39E14A6FF71F3AA +:1068F000B8A4B68F1185F70184F0A375ED323AF78D +:10690000691D66DC9F97D38C75897916A0BF27AA6D +:10691000C6E737466BF94183580ADA6DC34D3E131B +:10692000B61BC9FC545EC702648F8D621D541F8D57 +:106930005E63161E5B72D241AB71CC2DF238AA4752 +:10694000443B3171AE1E47F24E41BE74476B7661D7 +:106950000AEF3F7EC62CCAF7F569EFCD33863D318D +:106960000DE6B57EC6DDCE50FB4E5F2F75FBAD4804 +:1069700083F9CB6821A2BDA0DB7545365E4F98E553 +:106980007E7A14C611DBCD26BC9FAD588B63166F83 +:10699000C84F44BBAC68DF5CB287D74473BB6CD1D3 +:1069A000FA19B277149EF79A4F767FFEBA0931181A +:1069B000A76FB0B962AE47FEFD23BFDFF54AEDB168 +:1069C000E6C46B0A501E9BC1AFC6FB8F0E9ADDCA90 +:1069D00018E48B75C3C8CE6C8EF2D6C742BFCDFF0C +:1069E000EA74D541FD6736F7F823384E43147F8F9C +:1069F000F726216FF6EDF73F2F5C8C1E78FCF0FD3B +:106A0000FE83B191EFF1BD43C35FD0FEF090DDD9BD +:106A100060F6C4DC87F0BDCBE779D6EA89512F1147 +:106A200067FBB486E70376D6B85840E6F7D162BD77 +:106A3000A4683FDDAF5CD22250DC7C096B223D3A7A +:106A40004C89D5EEA731E6C59616BD4DED4B5B7969 +:106A5000FB32D642ED757AE1BDB501831D3ACEF029 +:106A6000FD1DD1DC6FDDAC781F43FBFF9119D9C44C +:106A70004FC06711F32DE207D877B9319AAF1F37AE +:106A800062DBC8F628F163B87DB85CE0E7B307C203 +:106A900053D57993613D0ADE9F21D37AD4ADF9496C +:106AA00087937CEB6F84F97F9FF54A24A7DABD2397 +:106AB00075825F42F9FABE33ECDE1B2D0F68BAA671 +:106AC00025FE43CBEFF93E6B79C30DFDDCCE02F41E +:106AD000DD61ED9E1214A4487919D0AF411FDC3A54 +:106AE000C258BFDD65ACDF3929F23D7D6B6BD4B494 +:106AF000D07BAAD60E708EF32D8D5E577FDF120BE2 +:106B0000CFEB7B0BE95E81F994B47FC1F3FA141BE0 +:106B1000F3A01ED9BFCF46FB21558ABC1943165599 +:106B2000E0EFE2BDF08A9D9F3740FF17E3058A99A9 +:106B3000B70FDE97C4F751123C495A3CC3953463F2 +:106B4000D4B7871BFD2ACA0B96D846DC770DE627FB +:106B50001AEFEDE88AFE380FFD6398CF6C8C4FE892 +:106B6000715A7D3EFF287F2C5ABBCF399C6E6B3407 +:106B7000F9A80BA3733DD23907DF73B9F952BB876C +:106B8000FF29C143796889261E17ACB3B98E529C80 +:106B900044F30FEAB4B806F37D5DEF56C2EC9510EE +:106BA000FF227DEDD7F5F539E477F338882D6A15A6 +:106BB000AEC30D36BD6EA6FAD3E6A600F9FDAF5AF8 +:106BC0009C181F83EFDD1867F3CD1D417E5D5D06C8 +:106BD0004BC17B0EDEB0CBB4FED6BD6A69C6F5D81C +:106BE0006DF376DB42F249BAECEFD1F9A608FDF974 +:106BF0000CFD0DF976FDC1F8AD8877FDFD1BF6A7FC +:106C00000222FFCE49F91B69ED1F7BA19EB8CB4242 +:106C1000714FFDF70FCACFE7D1FD8C7A7F13144E69 +:106C200087CE1AD5908F5D8E7A3707E5A09DF467E1 +:106C300045CB2083DED4F569C5F91B68BF2C4857C6 +:106C40002D2E21B5935EAA38FFBF68BC3B909E34C1 +:106C50004E12E9F781C74935E8E3E038930C70F745 +:106C60001F6732C1A18FC3DAA20CE79FEBCC3CAE09 +:106C7000726698332636821ED14B7183C970FF60CD +:106C80009DE4B262FF75CA4E35347F287C5F00EF09 +:106C9000C56421F0D5C17A86C1720BF3525E403DC6 +:106CA000F6132207A2D9A562BF62C2F8E9F92EC67F +:106CB000FE45B9BD107D7233F22DD88B3F583B7E17 +:106CC000950FEC49C9EC6947BA4A769313F3686BA0 +:106CD0001513C545EB92AC64FFAD12CA559473BD54 +:106CE0005FA9432238F47D8F81E6299F77D03CC38A +:106CF000EF3BFB9F1B4FA176FDEE573B30D7930F29 +:106D0000FD5B54930B455D4E53D82721F40FEF479D +:106D1000DA2045EC27BC9D8EFF01E96CEE70203D2A +:106D2000BAE3A58879101B95EF9807312F4C1F27E0 +:106D30001CCD0EE0F74287232383F4E54605F5A535 +:106D4000FDCC9FDC4ED2CBB4EFADAF7FE684A9562D +:106D50009E4F6CBC576F20FED3F1627DF341C6F3AA +:106D600053BD947F72393C4882CB43FB007629E2C5 +:106D7000BE36584286FC384931E64F35481EE2633C +:106D8000F34DD556DA27495B69C57D92D592330616 +:106D9000FDD8DE37C1FE83F9353A79BE6A78FF6BDC +:106DA000F01E66B4731553C4FB79A306B0AFBA34B2 +:106DB000FAACD97769FE01F5E1C175372A4E5271F7 +:106DC000DD359B39BC03AD4B7ABF03E1EBD17DFCD4 +:106DD000F71B2C39563FAEFFE1E3354A1E4F3EBC50 +:106DE0006F047870DFAC31CD4DF86D542515FDD5AD +:106DF000E81151CC1AEA6F65CCA2F767E2E3F1CC57 +:106E0000226B8C8F9C97A3E369B7F21DED1D6F1861 +:106E10005F0E7F8FE2E8217CD9A94CE8CF97BB9128 +:106E2000171338FCA1F7A65A338645BC7FB21F7FE3 +:106E300086F14DDE6446E7F70643B919FA6ED5EEE2 +:106E400043AAC0B50BFCF4F27B14A6C2FAE677E4C1 +:106E50005F4039C96BDFCFCFD1B426F07B1EB5EFD1 +:106E6000C3C75D62E7FEC812BB4A65CC51F72FF17C +:106E7000F7375ADBA39C785EB1352EB21F9363D7E8 +:106E8000F3689AB473081DB44FA1B7CF9BC7DCCD8C +:106E90000AC53D1BADE07F25F4B5FFA9B63F0282D0 +:106EA0000BE3DCF9DBEB9AF9F9513E7F8CAB62FB2B +:106EB000C4C48E5C41FC0E74DBC60CF7DB55583B3A +:106EC000B251CEE79ABC997618A7EA684722D65BFA +:106ED000DF3E9D4E7E6F1DB7377B774753DCA03F6B +:106EE0007D6AF979F2F329CC37A83FDDCAA500AD58 +:106EF000ABE5E7D3996F1CCDDB678D0BBEBFD3C26B +:106F0000D8A4B1C8001C4F889F48F430DB4D067AE6 +:106F1000803C5E67D7E88178EAA3B776EF4BA77627 +:106F2000BFE071CD5F612AF7D7F5FBA58E67F7E566 +:106F30005BD07D5BE536F713784F0B3B2252BEE604 +:106F4000C229FCFEC48516770CDA570BFF53146A6E +:106F5000697F93F3FD220D7F9DCC45F70EF8D6DABD +:106F6000F8BE4E987F96F154FEB83FC2F78BDA44D4 +:106F7000CA1B5F3045F161BF79ED05BFC4FDF9E281 +:106F8000C6683A77BEF07BAE9368D72D7CC2E6C464 +:106F9000DF7B59FE41667E32F4BBFCC90CD507DFAE +:106FA00045AFF024595DA0271FDB53887E45833011 +:106FB0007FBE3006FCCAC70EACC2B898F4CD94CFE1 +:106FC0006D507FF4B1775661BCE9B718E7263BF600 +:106FD000DD42B4635F42D0F4FD3FC0C14B874D5AE0 +:106FE000FDC4AAA9A0F2AF4D6835292AFA65275633 +:106FF000E139D9C438F718138CF78EFDB342EC6F22 +:10700000C113A3CE6D80F7E7ED17C8BE003A69DF64 +:107010000B374F01BBBB78B25E972D588F8F6686BA +:1070200038BE3933383EDAD9AD7A7C8B45DD8C7188 +:10703000F7E305D55324E83FC3A1AECE19C9D8C4A0 +:10704000F5F9AA1BC6CF76C4DD8CF198D6BE7D8338 +:10705000F8D5181F6B65DE0366787FD3E3436EB601 +:107060000262E30779C6A830FF41D629ABA7DFF457 +:107070001DE46344BFF3590DF60492934388D2F4A0 +:1070800015FCDEC23EF94EE37CDB571FD1C1CFC3F6 +:10709000E8F5245E6F5D19595FDC12C3F9BA352A31 +:1070A000F2FB664D3F00BE03147F6D8BF60FCF08D9 +:1070B000EA0F901FEB2492A7755C7F801CCDB493E0 +:1070C000DC46ECEFDBCA6BAB76AF79ABE48EC6F88F +:1070D00082AEC7308286E3CCB53B0DFA39AF7D0175 +:1070E000E9D751312A87C7C9F19330C5A84798B568 +:1070F0003D3B74DFFE77DA3C33AED3E33F013974B6 +:10710000DF69F98EFC4B9E9F2DC7387F88BD1D9C83 +:10711000C7548A67F4EB17FA736AFDBB72AE045F5B +:10712000EA65F0154FF8BADC3C83FD19E32FFDFB4F +:1071300093B57DC126E33A224786F3A4CE27807F0C +:107140005388FE2CD6F4A99E07D1BD6B24E54F06CB +:10715000C7E5E73181BEBFC4DF5DF2813E453D96A4 +:1071600027B96FC5F679ED712ADAEFC06FF51ABF4E +:1071700049C86F3A9D5BE3AAF369BEEB04B24BFAD0 +:10718000D941DA3A9AD724D0EF990D9EE715E787CF +:10719000C0A7EB7BE8BF55EB7F3CE7E767FBF8F95F +:1071A0003E941FCD9F67AE0EBA5F3D1CFE852873CF +:1071B0000921EBD5AB368AEBEB78BB5AFED7ED85D0 +:1071C000F201D725077D37F868C0E184768B511E20 +:1071D000505FB57C42F764B6B6890C7FB200E78D8C +:1071E0007A234FD793BE95870A24B25B827AD94916 +:1071F000F68BAE3703566BB0FDB9B52B0BEB51AF29 +:107200006AF7ECC78BA0C5C706E1487370BB7792DD +:107210009745FCDDB81CBB5DD723348F8D2B0AE866 +:107220005E852A6D3D9DD4E1A3785334E27142100E +:107230001FFA7A7DA7A5E315EDBC97811FF53AD813 +:107240002595A6AC60FFF87E6608DFE739381F8415 +:10725000D3E7BBEA27C0830FF1F0430DEF0950C716 +:107260007B2D9804EB17E6FDCC505C6B3242E05668 +:10727000B83E4E104D5C8F5D462EE20731EDF7585B +:10728000EC24CF417C70BBE5018716E7D5EE293FA2 +:10729000680239A17D363ECFEE5DC9D4EF6CADDD1D +:1072A000DF4B2F6FD6F296747BB1E2B5D4CD46F8A2 +:1072B000797FBB1C1C2F7947DD63D08E19EE515CA2 +:1072C000E81FE4B5CFDC8FF924D97BF00704827C7A +:1072D0009EDDC2E514B84BC3CB9BDB43FBAD74D83A +:1072E0007539FBBBCC23FB28E757A4CB7D21725A11 +:1072F000E35038BE607E16C4A764D4A37AF9F7833E +:10730000C3B31FCF2595033E506DEB786B6D99BFCE +:10731000D286727C94B9508EBB5BE69B46215D3170 +:1073200011CC19A21FD6F379E87628F0650BF2E5A7 +:107330003AC7101A6FF85177740EBC1F8E7613C6B9 +:107340007D5BEC7EF423FC0EEF2E07E27356EF1408 +:10735000DC4FAD8CAEAEB5853CEF6BDF06ED898FB3 +:10736000BD22EE1F953FC0F8BDF1DA7CA0A9CF0287 +:10737000E355C820A759540F20DE5A65DEBEF73EFC +:10738000FAA5115629F27BF960FDBE95F8F36D530D +:107390001CD217FD24B493CB454F1AEE7BB2C11615 +:1073A00017AE03E07710BF1FB431C906FDFF1E4AB8 +:1073B000D4D3D3C4A5748E6B5A9640FB44BA7F8F46 +:1073C0007A0BFDA43BBF174DFCC82E3C380CE3D311 +:1073D00009D19C4ED08F55EBC76A1D1B94BFFF4847 +:1073E0001F49FE8EBEBE1D1404EAE7E04DD735D717 +:1073F00085F841D81FEAFF83C28CB4A5C8FF9A1F45 +:1074000047F6617C70DD457B65AC21CEE6D3E0EBD1 +:1074100048473E0AB547D13EEDB3677DF357DF0CD1 +:107420007A76E2F496005E715FCB8A6EFE17E86FA3 +:107430001AD8B336C0C33E8D2F0E66F844DC4F3DDC +:10744000385CA0FBDC0F457973AA95E038895A5C5B +:107450002051CB334F8CE2E50F62B81EFC3C86AF67 +:10746000D737A8BC9EE8881C4798ADBDFFA989EB1B +:10747000F735F991F3D14F68FAF5AAEDDE1C21FC3E +:10748000BEEE138E09DA7DDD946FC7E3FD0B34FE8B +:10749000063B87E814B4ABF87E9D6E879E6D9F4DCA +:1074A000F51382F7BD7B042C3D4F909FF4AE48F15D +:1074B000A1E2586F22E6A55544458ECB0CD2F0F4DC +:1074C000590DA338EF29DCCFCBE6BFB785F5251BD7 +:1074D0009EA47B1D4A999FE2BD451B1A68BFAEC89A +:1074E0002F30A780FE9987C781353A946E110D71B0 +:1074F000E7C552B51C9B13E45BFC1DAED0F7259B82 +:10750000C619EA576F971618F23B827AA790ECBF1C +:10751000F07E753E0FB74F8FD7380DF1EE051B8605 +:1075200017F2CD78DE7E2173D17C17366619EF1104 +:107530006E4CB8B27B82C11EF545845326FDA83F30 +:107540003F0EF8F785C4F7177C3A8CE0F88BC37BC5 +:107550005D8C018E68E633C4CF26F3DF29B4F1F8E1 +:1075600023F08FEF5276407ECC77F507AE1DC01F1B +:10757000C8FD87FA037993B9FE654D02E5E04C9C9E +:107580006AB4CF66C7F0756E764CB4C13E2B9A676D +:107590006C37576B37576B77B9384AA85D2664A1AB +:1075A0003EE3FDE9BF1F9571FA6DCAFFDC10C3ED24 +:1075B000D79FAA6E6F0CF4BB563B77D06FDEDAEF25 +:1075C0004AAD35F7E585525EE0E66F1EACC3DF09D4 +:1075D000E9DD01F63FE8C1FC67DFA07BBAF4EF6E9E +:1075E0005FD132B408F054A9C973B98BCFAFDC15A1 +:1075F0009087413F29E51CAEB4967D8214F25D5A16 +:10760000096FB722C66CF02F7FA2D5FF35C649653A +:107610005A49401806ED52366D1124EC0F7F570B76 +:10762000E049A966FED0DF934A19CFED9ADBC76F18 +:107630001616E604F1D0689A91A3625C3531DA85BA +:10764000EBCC47AAB70EF150FE5180CE494CFCA8B6 +:107650005D42BBBD5B75D7237FEB78708A6A0AAE4B +:10766000A3D11F71389BFAFC62BEBE30F6A86647F4 +:1076700037EB76E961C6ED425AA712578E30FC3ED1 +:1076800061629CB64E2432EF4E85DA3732A227A3D0 +:10769000F924AECC6EE6762CA7F7B42CCF167C3E40 +:1076A0006DF0C8B178DF47D6DA8084BF3BFEDA26BA +:1076B00053C4FB519A35FCC33C9EC5F9E9F3B89C11 +:1076C0005ED0DB9907884FE8F2103D3DB2DFC1D8AC +:1076D000E3F43EFFD9F87BE9FECA7A997E4F4EC7A4 +:1076E0007FB7EA6941BCA6B46C160837DA787ADC51 +:1076F0000E9FA35C1E978DE73A0794FB153B8716F8 +:1077000085CA7DBD4CF4D91C96E7AFDBF77F88E1D5 +:10771000EBEA9058CF3EC44B65DB3A8AEF2CD9C2D6 +:107720007FF76740FC5C21FE8412EE0794CFE1FBFB +:107730005EF9CF4A44FFB27AFEFBACE5DB77F0B8E6 +:10774000CE8F990BF54379CB0EA128077F0773875E +:10775000B028049FA9E57ECA83BFC6AECB1FD75B06 +:10776000E1FC8E7162B4530ED9B87EE8CC577CB878 +:107770001FDC69F69663BBCEE46817E677E9F8FF8D +:10778000FD8E9BE9DCB57DA7258065A3A939C98A53 +:10779000FB0ED7CA2EE4AB6ED57B12E91327795ABC +:1077A000F1FBD878BBAB16BE755AD85855B9723CA8 +:1077B0004C0CE38F893FE67293A43AF4BC86B12463 +:1077C00037AA9DEB2D13D76787CC7C1E3B1987F713 +:1077D0000731EEB3248787E368DC94F2009D1FCA6B +:1077E00038BDD370CE30C85FEEBF7D1B7EFF3F2C0F +:1077F000A14B2800800000001F8B08000000000043 +:1078000000FFD57D7B7C54C5F5F8DCBDFB0AD90DA6 +:107810009BF73BDC100C28246C9E0401D924848740 +:10782000206E0228C86B7947926C02D2FED0FA6DA6 +:10783000168331E56B6BD41645A92E8896B65A830C +:10784000A2060DB82822D64723A58A2DDAA5202224 +:1078500084641BFBC056CB6FCE9999ECDE9B0D0F59 +:107860006BFBF97CE18FC9DC799F73E69C33E79C65 +:10787000991D33B5CDA88C22A4A69A38BC342DFD11 +:10788000E90EE98485900BF06F2221836C3221F19F +:1078900084A43CBD4D522C58BE7F5A1CD6272605C9 +:1078A000BE4BD8AE8696AFA0A95B22848C25E4A0FF +:1078B0008178CC3184B4E82A47D968FD9684487B26 +:1078C000132D3B667345DB687F96639D07ACB4EA76 +:1078D00098633EA38BF64BDAE9C76442DE3012129E +:1078E00041DB1D8C60EDD36D74902242261B89070D +:1078F000BF1B3D2314DADFC1A183B0BF97B7EAA64F +:107900007A697BC320B2D81932EF749B0EDBA56C69 +:10791000DD21E9E8F7B8485A1E323F51EF015B59C3 +:1079200026CC67CCD44E8443DD563DAEA7C2E81CBE +:10793000B66654B0DE68E88FD67BEDE64F8C7EFAF3 +:10794000FDC72FBD6F2450BF5572B4C1FC5BDF373C +:10795000CEC9A1A9E7E7324920643A61FF36BFF0FA +:10796000BE51A1DFA7EFA670A2F5EA76EFD22FA352 +:107970006957A9C5238D2624F3CC6B8B4821FDDEE6 +:10798000662211746EDD3657918DCEFBCD5D530EA0 +:10799000495184589F33F92015F021C49FE1B40662 +:1079A000E725523A30CE2F722AFDB310B246EF557A +:1079B00099F0DD955945EBB7C630F8CC1FCCE042C5 +:1079C0002CEC7B155F97800B1D7F0A8C5F91E5DCAB +:1079D00001FD542446D89B32619EF9AF9929DCEB16 +:1079E000EC923D82568D2B67F00C9D57654EB87911 +:1079F0006DC0F1E263D9F844EFCF807109F1B2EFC5 +:107A0000326921F9C1F67338BEE9771FFB4E863A19 +:107A10007382F3D7E26F834DC2FA61E86C11ACA3B5 +:107A2000F698CFC7E8AC530F749679E630E243D0AE +:107A3000CDCFB6EA3115FDD5D98CD85F9D4D8F706D +:107A4000D90C781A4C53032C9AA61BCC5E0F85C711 +:107A50009BF3261F9272297E6E31FA207D43B7B4C4 +:107A600016CADF4861E3B7E8746B21DF729785348B +:107A7000215E1D6E98CF6B3747217E6AE71ABD26BF +:107A8000DACF8F9F9758DE63F112FA67AD6BF6720B +:107A90006847E222EC4F02FE5C078C73ACFDE94ABA +:107AA000796EBF51A1DFA7B7B1FD27F050DBC6E863 +:107AB0004BEC0701D7203CBDAAFD24F0317FB08DEF +:107AC000D105A5178077CDCE08DB49331BEB02012A +:107AD000FA8C56E5EBDB936D274704F335F007D0BE +:107AE000C10E628179D6F279CED3B9EE83FD5567A6 +:107AF000F61F3450D4161F0DE07E1F887E6BD6FF14 +:107B00003AFB640121AB930E612AF6AD61A87A7F3E +:107B10006FE5786F8294B67B82D34D4D611BEECBBF +:107B20009A930DB89F2D53195FB31C238E503C13AD +:107B3000F243BEDE7BB17D4564DB6499C2BDE27178 +:107B4000C9D644FACF4FA4AB24E26CA3FD7DB6F5B1 +:107B5000F5A82500DFAF2EC8A498AE3782AD7737E1 +:107B6000E73B5D3B29C091DE1B8C24CC7A2FB73FCD +:107B7000E23B22013C6B38ECBB9E2E1FFB29A51774 +:107B8000CFCEC1F6ABE892CF3E3DEBF64FE9BCBBA2 +:107B9000764CB4CB40364D4EA49F407C847D3BA5B3 +:107BA0009F38994C9528DE37B4BD1E358EB6FBFC48 +:107BB00097A3F3816FBFCDF7FD99E7E5F50097BB7C +:107BC0007EF6EC75505EE395624D30CECEC7FF95E4 +:107BD00042FBA9DE510F10264DBF7CD5E8A7F574F6 +:107BE000DE6DECFBCEC136A8F7F913F75F07F06E38 +:107BF0006A6BC2F2334F6CC3FC6B3F7B76DF3F682E +:107C0000BD5A67941DEA9D797E3FE2A5D6A577C04F +:107C10007A07A2EBCDBBF6337ED926E17E2373191A +:107C20001F13742DE8F7F39F2D1E1B2A37C4F71678 +:107C300023973B83981C39CBF76F4D99A505D2B399 +:107C4000CF44CC85F5BA8DFEEC6898CF2846171F37 +:107C50007178D4B6AD31B82DD81EFBF980EE7B48D3 +:107C600073287D9EA2F44E6BEDB85000E3FD0AEB45 +:107C7000D37A251114BE372F382EC17C22473518F0 +:107C80006A709EBF64E574D5A1E5C5EB183D6AE94D +:107C9000E00B9B05EB8B7D90B2BB324D413E60B259 +:107CA000333ECED69752ED6AB2D2EFD7AF73D965D5 +:107CB0008AC7974F1F9E9C4AF33F1B211520FE65E4 +:107CC00089C9398F05C7A95B5F464ED0F9EAA2D9A9 +:107CD0007E49B011FDB5C807B631BAD713BD05F25C +:107CE000FA00F289BA162E0777B0791273206396DC +:107CF00015DB59AE8D09CE83B6B358301FC8B829ED +:107D000007E48E672ECA1DC588F33D23F801F1E410 +:107D10002ECC09EEB7041D7101FE138C34B5307EF4 +:107D20005349FB4F8F2E4D8A2E0AA6098358B91648 +:107D30004EB7F0F21F453B92A2015E3B6355F260E5 +:107D400020BEF2DACDDD4C6EBF721CE9D00D740896 +:107D5000E3BB4EAAE4F67264AE940EF71C473A5C9D +:107D6000DECEF8ABBBBDD4B88CA69B253217E6EFB0 +:107D7000E6F4047464A7F99BA2A3717DEEEBFCD931 +:107D8000C0A7BA39DD75EF61F4F6864EE701F8BC9D +:107D9000B17DE43690075AF928553B11DF6E8A6FA2 +:107DA00093047AD6BAC3A067D555133BEC57F76E48 +:107DB000BE1F1A08EE07777BE572E82F356E9A5DD5 +:107DC00096502F999C4AF3EE5A5204FB2D656BD9BD +:107DD0001EA00BD22E91AB205FEDDC0DEDAF8FAB73 +:107DE000B3CB9920F7B6279969FDEB471463FBCD18 +:107DF000E94A29F4E7A920B627216F70A13CDB9C52 +:107E00003CD20EF2CEEDDA887A175106D9A19CB891 +:107E1000F46BA1BEDBB3806C92C2ECE33D9203CB6A +:107E2000BD91DE08DA7E7A3BD37FDCED6C1F9F13B9 +:107E3000F011A9A173118CD7FD828978A4209DBD72 +:107E4000B9670A93B32F9A50CE9E6D749013543431 +:107E50008F8C5610AF028E35AD993AA05B42669971 +:107E6000601ECBF83C5A0D4C6E44733990752F9BB5 +:107E7000C772BE1F9647EB786AE4FBAF95C9059BB6 +:107E80002717E4E0393E1E924502977374E8BAE57D +:107E90003EDC27B54FB3FEE24C8EBCDB42E855E832 +:107EA000475A7A6CE2E3A66C3D20013349D95AA5C2 +:107EB000DAE7D757135F3D5DE7F55B75BE89B9A873 +:107EC00037DD82FC7C83916C97FAF7774F34E35B64 +:107ED00015B1CE3C09E4D7CD16D43FFAF6E9208798 +:107EE0002E02F4B87CC9DE84AB7016EA68BDD309F3 +:107EF000563BE0ED471C8E5A7DABAFBD460F9CD183 +:107F0000EAC9254369E9864173019E545FB798A188 +:107F10009D8DB6A7F512B68F7B6213F2AB26ECF7F8 +:107F2000F6681BEB27D659D8002C2ECBB98EC92763 +:107F3000AB3DDC7AD2A3859EBD284F07F433DB82AC +:107F4000FBE1C7AF484B19BD514128013DB2FD418E +:107F5000E8FE7852417A443DCADDE0F486A747B690 +:107F60005FDC54AF023D9BD2E35AA6275B08DB4F90 +:107F70008C2E23A73279007C2B549F15FB54BBEF2A +:107F800005FDF6EDFBCBDCEFDD06B61FBB291C8043 +:107F9000DEFBE8FC6546E79B36D0FD48CB37D1FDDC +:107FA000D814C2FFB5E71F98279C0704BF3D66732E +:107FB00076005F746F7FAB19C996F347F7CB3FC864 +:107FC000BE98DE6586CAB45F33DDAFA1F463A6E078 +:107FD000B6E663EA013911B95EAD4789F4836826D4 +:107FE000BFBEB1DE3842D2A3DEC3F155AB737D0014 +:107FF0007C1EF4464A1124633DD31B1340E600DE89 +:10800000B6477A413F4E4820AEE7C2CC673FDF67B4 +:10801000029FE2FC9010C5EAF7F27DFF29AFF74F0F +:108020009E869C4B703F283AD771220F2C8F443B81 +:108030003A2F2C17F3E93BD798D97C13EECADEBE52 +:1080400029048FC17D75753EE037EB5E9F7EA925C3 +:10805000388E908B5ABA81F983FC81F5548E1AB808 +:108060005EEB7E7E3ED3D07104DF5F7BA8B882B426 +:10807000D5E0FB2BEEC7355602FA222507472C9D8B +:1080800057FDBEE16C1F8D086443FBEA58D74D31A4 +:10809000B4DF3193F8FEA0DFABE09CA0271E530CA9 +:1080A000E0DDE0F587E0F9D318D67F8FD5EC91E9D4 +:1080B000FEB823D6150DED3D65C4EE03397307E513 +:1080C00027B06F89AF08F84D3DF147019CC7585D57 +:1080D000F13140BF726736C9A2FC57F2E7C2F763BD +:1080E0001151B984F6F371FB6F9F7985B65AF8CABE +:1080F000B985DF03FA7A312203E8E218D5973B51BC +:10810000DF560683BEDD4B94C1B630FC57A40BCCC2 +:108110003AB3BE20983F66559F2F447A4D0CC36FEB +:10812000FDF914E28985FE099EBF7B6214F65D1F8E +:108130003082EA567F3E8378687F1FEB48755B98F4 +:108140007137C5307ADB4DC8D470E5F7F171760F21 +:1081500065FB30B04DF2027FAC5EBFE1CF32E50788 +:10816000D5EBAC3E4C6931E86FD5368F4F47F3C73E +:108170000C8C1FD17FB3CDC541B947EBE9C7030EC6 +:108180003CF4204BF9E0522EB79635BCF925D813B4 +:10819000AAF5C43C9EF6B3DCEC3C984A8B3EB32C6B +:1081A0008F02B6BFF23BB725805C4A5CD0CAEC3286 +:1081B00064920DF45EC93143BE1079313D4B8FFAA4 +:1081C00031E29FE2EB8B18E74CC0F782C104F580E7 +:1081D00005B7457A3D217CD0CCE1A1A59B4FB87E67 +:1081E000A5ED7F766C1981FE3AA29C73813E16DC68 +:1081F000764EC5CFBA25FF538F025DADB1DA9F64CD +:10820000DD653843E8FE3B62BCF33AC4534F5E671A +:10821000F6FA4CA0DF40C68760CFEA30D93C0A941A +:108220001B11CFA2DD9F1A29E3CB0EE6979E1E36C7 +:1082300019E86B19B13703DE97B544124F083F03B5 +:108240000518E8C37D9E603F4B3BDE3C0AFCDCAD7D +:10825000F7239D2C355B108FEEF37A9C0769317400 +:10826000F9457B8AFB23518EDB607D9E7BC6479F51 +:108270001A493F26D2EFB87ED7EDF0FDA1C828E21B +:1082800000FA784BF60EA7F3EF352B836328BCEA90 +:108290008D940E4663374E7388FE43D2AC6AFC77EA +:1082A000BCF525CC67B9D9650439BEC241CFA73228 +:1082B000E0C957641B158AEFF1F28591978FEF455E +:1082C0007CBF7F6CA4F41F661FDDC7E1DF23EAA536 +:1082D000B07DF27106A97E0ED26B684ADB7D3C94BC +:1082E000E7F3793E9BD74B60F91D7C9F7C9CCBEAE2 +:1082F00069C7F1C530FE363BD6B115E045DBF98CD8 +:108300004017FB22BCA8B716527E07FC6D6D3AEAF7 +:10831000AD94AFEDC07AD9C4178DF54C28574803FA +:10832000E57BB0CF8B1484CFA6524A27B43CB0D79C +:1083300064DBAE04F12AF0A9C5637B8CF4EFC9C3FA +:1083400051923ED48E42E5617B0CB3A318617FD27B +:108350009918999E360CF18574225F3EBE6E8C6032 +:1083600078A0FBF4B518D47B7D39A1FBE504C79751 +:10837000E0671F0F52E3B58AE3E16D5E6F518C8DAC +:10838000C94F7B00F7DDC731AC7E5C169343420FCB +:10839000FF0387CB4D9A54C8953153D5FAC54D1C70 +:1083A0009F37C54409BC7E08F315F288F2175F3485 +:1083B000DD0F0B5E35217F211B03D9B0FF68BD6344 +:1083C000586E0A2C8AA572E426AADF18F3B1DD22C2 +:1083D00068DFEF3C3F4AD08595809C3E25D65318F8 +:1083E000407E4FE51DAE6B29A17C43BA34FE37D0E9 +:1083F0003AC994D6870C56D8F94EA60302ED8F20C1 +:108400000AF447E1FEE750B86BC73BC6E9E09F318D +:10841000921EF19647F2709FBDFF857521EDF29C8B +:10842000CDECD151BEFFB8CE7501FAE9BAFD2DD41D +:10843000CB8F197DD9AD9630E546DF630F49C1F288 +:10844000C53F973D46CA2F767776FDE466BAEEA51E +:108450009DB21D865C7AE75FDF1D037A75A7C10EAA +:10846000E7462ADFEFD5C3BC1B981E794CA7A6832D +:10847000B3DF559F73D26219BEA8DE83FA9CE03B3E +:10848000427EDF4A7C57815C5F461C4648FFB466EB +:10849000D50C42E1B7C2B20EF9D1E76BA7A11EBC61 +:1084A0009278B07C598BE14FA1F26145AB3ABFEABB +:1084B0006175FE56AF3ADF677F2E0F2FDFA7C732F9 +:1084C0003A3E4BD93EE03FB0C1E4053D485BAF9832 +:1084D000D7CBA43CB113F82495FB60475817E1486B +:1084E00004BEBE6E6F69E2C5EC7CF5E7AF21DE101D +:1084F0007D23A837E4126F6CFF7ECB63158423F4D1 +:10850000ABF071E0BC71B62CFC3A26C60A3D651092 +:10851000F627BE8B7E82E345E13CEACF9B07988F2E +:1085200005DB9F5D197E9C1BFAC6B1A9E464B07D92 +:108530001C936BFC1C2DE8A3FE7C127E1779A1070F +:1085400007DBA531FD8AA4D94E4506F994B0638BAB +:10855000FD704222E664B43BDDCFCFEBF65CB05F4A +:108560009F003D08F6E314659F9F4E71D9F7C666DC +:10857000EB8706F78B761D94AECEF843F8EEB25833 +:108580006B1C8E6B27761857D0FBA2DB2B06BBE843 +:108590007CFF786779A26B54283FF530BF8951E89A +:1085A0005F16959C251A39BCACFD2DD4BBA8BE9591 +:1085B0000D4CE7D3BDB723BDAF24CE04A0F39EBDC1 +:1085C000C3335CFF86FC15F399E559622098A79B9D +:1085D00098EEBF2A3E9F591D4CEFD3991D061CC72C +:1085E00041145B021EA5D97C29F3D4D3FC84BEF9C7 +:1085F00083918E90F17CFE12B4A7F09DC053B2D44B +:108600009504F336C1B874BC08E24D82B469AC5D20 +:108610008174A2E4D4B379303C4F260D69505F6772 +:10862000F6CB6C9D740609D0BE0F5E98B7F2FCC6FF +:10863000D9BD8B56C0778B15F98891CF63472CE550 +:108640008766E42F6658B7C9E2FB1CFD643CF594CD +:1086500029B88F3D4309DA3B06913602E35A2CE7ED +:108660003CB0581BB149908FB0F5FAE0FC70CE6673 +:10867000F1E846239FDC190B7C527A6725E085F2EE +:108680006566FF19A85CEFC373B7E073317C7E4D5C +:108690009CCF2513068758E2C0F11EB0AE9C414026 +:1086A0008459D649D07E4BD454F4EF2500E0697943 +:1086B000EC54BD8A6FC53BD5F9C4B9EA7CB24B9D79 +:1086C00037D3933FE88B92CF99742116CF5923C0AB +:1086D000DE62E0FCA299CFEB08A4743DEF713EFD91 +:1086E0008DF513BBFABCEE8E3112B4E32598CDD0D4 +:1086F0003FD557DE8B65FACA271E289703C8CFF3EC +:1087000026B6F9C0AED37C8364BF8B7E6FB62A1BBE +:10871000F494543DD32466C7D1DB4AF5B47C5B8620 +:10872000CDBE89E6EBC17E1D0BF3B7D53C8DF64976 +:1087300013AB4702CDE08FDCB6C966837A71E58161 +:10874000C946D08B5710DB761286BEBFA2FB86CE01 +:10875000F709C853BC489C5E220F29F3710DBC7CFD +:1087600007FC9DC5F2138BE15CCAFE6575E4753AA2 +:10877000C0EEE090512ED677E4BD6EA1E365CDCE7C +:10878000433BBCB39CF97309DFF76334FB6A5C902D +:10879000CEB13C8FE7877570BB6E9C89F96B6D74A9 +:1087A00088626636C0FA718CFEED44FC63FBF25AB7 +:1087B00012FC07FD9507FB473E3429581CDC677403 +:1087C000A87CB3BDA996D61BA3F7ED877D3C8EA7E9 +:1087D000793C7DA3F40694BF9D3A8B62D4B17D6D44 +:1087E000CE0213865306B814DB7ED004FD4C907C79 +:1087F00098664CBDBF09A65FC5ED47D14946EF0657 +:10880000BA8EA6128A67B477FCF920D8A5E5074985 +:1088100001E0E98841C839079ED3157A1CFB1A3A52 +:10882000986C40FDFC2F932AF03B01D58CCEBBD237 +:10883000C61621BE0F2C5F75283F6AE364E437B388 +:10884000A632BF6AFD5CB3579240CE10E677D2BB2A +:10885000326F0AB197083FC4FB0632775798F3444A +:108860006D1CD34FAB66303B6FFD46A3CA7F531DD3 +:10887000C7EC5E33E3268F8C4379C4FCA779715C27 +:108880006F1B4146009F0AE1234550AFABF4ED81D9 +:10889000F88CBA9CF399398E0203EAFD9CDF08BE7E +:1088A000EE1CC4F6F33C42D281AE679306E4FF8728 +:1088B0004B6F457E7313F118006F1F95B17802312D +:1088C000EF5953D57AD21CA73A7FF35CAD1EC5F0A1 +:1088D00021C69DE7529757093D78AA5A0F5EF0FFCF +:1088E000BE8A46B99AF854DD8521E0E760F600C0FB +:1088F0000BF373E8916EDC1B993FBCBE3DEF8D38E6 +:10890000D8677712BECF7649CBD1FFB24B5A1182CE +:10891000FFD45AAF047264B855D87D98DEE4347938 +:10892000F783DFC359831291BCCEE3490E403C4923 +:108930007E90BEAD65561657411CB5309F345BA482 +:108940001DF4FE165D3EDA655BA2AC2A3BFAA60D6D +:108950004A05D413F658C544F26D9C6EC29D77D774 +:10896000C531FEBA59627671CF3C339E2BE3B39C7E +:108970002A3F41BC4C8E829D70649C22EAA3FD6319 +:10898000B3C1955C4053AF44971117D25E261BD1FB +:10899000AEA8E14FF1B176B4EBC70FCE413BFD9CE1 +:1089A0008E3CB42F124B84FD2A29D8FF9CD9DBF4CE +:1089B00010A753DFB14DBFDC12A4BB7BE2B85C8DC6 +:1089C000249140AF7D76BAE74C68A77B5CE7FC5FFB +:1089D000A0CB5AA30FED7121F48ADF07928BAB383D +:1089E000BD18CA9CF356D0F9F5BC6BB4C3F9191D78 +:1089F0006DB4FFE7F744A39D515F45503E6D2C6574 +:108A00007CA407EC5F741D9F4557E3F960A3D48AEB +:108A1000F2A33B6632D2F16ACB013C07576FA574D3 +:108A200018229F56EF50E76B48279EDF6B9FEE475B +:108A3000CFC817051F76EF56B723C3D47C378FCB2B +:108A40008B7CA77D56054C7DAE3D8B9DC3E9418651 +:108A5000AEA3E81D23B7EF2EB09D8A0056FB947499 +:108A600031FDADC77A5A66FB9FC983223E8E566E92 +:108A70001571BDED3ACABFE0FC2AF4B022C2F2077C +:108A8000741D72922E38DF42DE4EE87F424E087C23 +:108A90009596105242F743A7E04F43C950C037EDB7 +:108AA0001FF78904914331D8BF07CE7DE3F878944E +:108AB0001E3C20B73D3AB317E8AB596A4039690606 +:108AC0003D9FA69B2417CA8397AA3D32C07B2C6981 +:108AD000983583D61B6FEE8C0438513A39124A3FD1 +:108AE0004DC497B14B52D111967745BF1D968E84D8 +:108AF0003CF37DC4F498E974C5D04F05387E687A9C +:108B00004062E7C829961FEBA1FDDBBA69482753ED +:108B100089570FF3ABB0A9F13F25499D9FA6F4A358 +:108B20000F8CC37070784E1FA12E77087E47D4FC3F +:108B30002E937C857A18F9C1C1EF805D21723D19B1 +:108B400001FA0DD544711F6AE9E0EBB86FDD6FF2F1 +:108B5000755C18BF490FB7135F4BFC2B9F96FAD378 +:108B600059F71BEBE5A4107A14FBE265038B7F90A9 +:108B70005E65FEA9123319E503FA2A647645B13F12 +:108B8000AE05FA8C09D25D31FF9E11CFE96C081950 +:108B9000027436A13DC22753BCE4F1FEAE05BACB48 +:108BA0000FEA23E25CD154D28FBE32A52CD45F7081 +:108BB000DF097DA4406A6BD267021FB9A709E61BD3 +:108BC000424F43E38B802F517AC27DDA4FCEAACB3E +:108BD00035F426F02EF4E552D28074365BA760EAB5 +:108BE000AB5C85F2B5DC325B0FEDDFAC62F43609CD +:108BF000E8310BEAABE9A5DCACCE6BE9918EA80BB2 +:108C00001D574B9F03D1DB10A037215F632F4D6FA2 +:108C1000D3E3BF757A9B1E7F117AD3D299E05FBBF5 +:108C2000226CE5A03FD7574B280F0ADE1DD604F96A +:108C3000E17599A84FEF8AB6A37E5DDFC0CA0B3BF2 +:108C40001D32C4BD64ADE3E599CE72C8D7AFA7E5C8 +:108C5000B4EBA2232C2E66D89DAC3CEFAE86D7ADEC +:108C6000A0677858FB973F6F96A368B9B799B72F5D +:108C70006D2D877C7D0B6BFF19F8A946437C9AB755 +:108C800009BE5F7D6FA69D1DAB99FE3E91AF7797A4 +:108C9000F4DCEBD8AE95B55B75D03C88E0F99FE984 +:108CA000E5D7F1754EDCCAD61977E2FAA90AA58B89 +:108CB00015010FEA6FA774B5C5C8DF06383F974A9C +:108CC000AD69904EA1EC175287D9DE220F657ECC9C +:108CD000ED74887BE299FD45F8FF20CEA032449FD9 +:108CE000B8279ED96345BD84188A01A08747ACA8E0 +:108CF0005F0BFFA4EF212281BC8735723D24ACBFFE +:108D0000724A5603EA115386083FA55FBF948E9BB3 +:108D100077E18BC9E1EC433FE2E39EE671137D7A94 +:108D2000B237530774B10B88240580F4DEAF417F5E +:108D3000DB057E4826A43CA404F0CAF25BE37FBDB9 +:108D4000A9653C85AFAE41EF01A1962161DCC9CC9C +:108D50004EE21B1CD57FFE53F4C467C4382636FF91 +:108D6000954D541E23D1317E3687E38F8CBF0AE99F +:108D70007736C7D3CF057F2A2005C09FE670BCDDBC +:108D800064A67A34F2C35683866F3C130F726ACBA3 +:108D900080FABBBA5CC357AAF9B82BB9DE7E2B099F +:108DA000A07E724AF2627A7A0BD3DB6B2C4750BFFB +:108DB000E97984E9EDB5C48FFA8FD6BE59B3539DD6 +:108DC000AF6B53E7EBDBD5F99E1C0F8ED3B3A5AE8B +:108DD00018EC8AD50FBF8B76EC6AC15FBC6AFE4285 +:108DE0001571C65F1EBA06ED51DF986F3C4D4F6F8F +:108DF000C5AAB8D0DF029CFAEC352FB2F81437615F +:108E000076821EEB88F9704E251A79A4E527799CA5 +:108E10009F08FB86E02F7984C9237A8E7DD7418213 +:108E20007C5CABD7F5C473BD979FD384FE9307FAE0 +:108E30000FD0D3350D48644139647FDB2487C89F48 +:108E4000798566C073BE99EE6780976CC971595475 +:108E5000F4F005CA9981CF7BEA720DBD88F3D62D57 +:108E60009C5E668127858EFF7BC981E7BAC3B732D6 +:108E70007A99635987F4FAD16A462FE2DC77E5E7FD +:108E80003C87FC4DCE797D741241F55E9A1E4917E0 +:108E9000E77CE68FAF97181DD4557DF818E8CF8290 +:108EA0002F1C6E24F1FA103ED134CD64063B4A9358 +:108EB000819D83AAA67F5CBC3484CF38224A1313D9 +:108EC0004059EE8847FB6C5DA47A9C66A9F3BB7F92 +:108ED00080F3D24F23D14ED4FB304195A477EB7071 +:108EE0008CDB3E6B607E52319F550777EEF3C37E7D +:108EF0005CFFEB083D959F3592F7C55A5AB6C4E41E +:108F0000CA86716A743E23B36376A25F578C3BB006 +:108F10005DD683F2D5F81A93C3016910C6E1D2EF8A +:108F2000D9A1FEB5D1898C4FDF11EB2A48880FCA31 +:108F30004B613FA45296A4C604FD26C1F8066637CD +:108F4000F90B715C32BE6163887D9EB60F1B8F5634 +:108F500096C0F8F5F729CE61DE07A31DE5309FD353 +:108F6000DC8F7B9AFBFD4E47313FE0CCBEFA2C757F +:108F7000F1F434F7139E8E51FB8744BDA509CC8EC6 +:108F800072B2D16CDEA807BF3A316F1C4649EC21A2 +:108F90005303C6932C6078EAD913BD6D5388FFA59F +:108FA0002EA1F4FB309F7FD89C3743BABCF5B83173 +:108FB000D40EDF23B1F3770FA7979E08968A71EB43 +:108FC000122ABF0F78EC99E7473CF6E5C78ABC1335 +:108FD000FBEF99C0F86B5FFE3B2C4FB8DD43D8F533 +:108FE00007F2F769FD7B54D0B0734004B3CF6BFD3B +:108FF000F30B053FE3FEF9059C1F2DEC607E8245D7 +:1090000066D29C4ACB177724B2736E94275BE59F98 +:10901000F7445E513C86A0CB9EF4CE3E7FF62321E2 +:10902000FEEC3AEECFAC13EBDBAD5EDF0309DFBA4B +:109030003FFB818430FE6C6DDCC38BA0470C0BE2E0 +:1090400061AD8DC1AD42AE2D077B6FEF728271E8CD +:109050006BDF5AD604F6E0B53F000B2AF231D4A7F5 +:10906000EB389C075A57BC534714959D7D105142CD +:10907000E69FEC8A51E551430F89034DAD4E51B542 +:109080004F6F18AAAA3F64FD35AAF24C4FBE2A9F23 +:10909000D572ADAAFE55AD65AAFCF087AF57D5CF06 +:1090A000234307A3FDEC900CB62172B5B74A553E99 +:1090B00072E72DAAF69F9186CDE369BDDD42FE7968 +:1090C0001C9DA38A8371CE396D4B55ED9BA4B6626E +:1090D0001FF0469FE49368BD151C5FCB3B99FF6270 +:1090E00074FB6A55FF67A3D83D18AD5F96762EA333 +:1090F0001ED62E9147A4FE7EDAEA8EFB9B21EEA8B7 +:10910000BFBF96F24DDA6E353DBF80FEA6D56F8E9D +:1091100026703F5D0A496174ADA50B0BEA7FBD5B0C +:1091200065B427E691EC87C623BC0CC4ABF4C75FDB +:109130002F6176AEDEA7AD7688FF59F5D632A4470B +:1091400053929A2E2214355D448E50D385D5AEA607 +:1091500083C1256A3AD0C23DDAA1A60BE2A7FF433C +:10916000E02DE02AE01E3B554D375A78E79300DAB0 +:10917000D9DD5EC9EE2361FCE2EDDB705D97D21FA5 +:10918000F5896AF8161C703459106E2CBE4CE861D3 +:1091900026AEFF68FD1342AF894BE47A15EF47F81E +:1091A000179A250FEA517DFEC2125F862F13F4A78E +:1091B00006C2EC44CEA4C4F07646FC3E909D51C05D +:1091C00075F620262F6B8803EDE12B880BF9DDC99E +:1091D000CA5BD13EB4CAF263F4BB9EAD627A52352B +:1091E000F1229FBFE2B802AA879210FBAB168E5203 +:1091F00087E4B302BFE1F22085740879E0C27813F6 +:109200004A86E662951F47ADE782DF30847F09BD5D +:10921000578C27E029F89A18CF441AE424D8171A53 +:109220003E474668FD486A3B8DB0F3E06021FE2270 +:10923000AD5D26440F6E91E938F290CC2642F1578D +:109240006073A0DDAF8874CE87EF25E6B626BDC279 +:10925000ED1357933EFBC480F2EA12FEE8591EC993 +:10926000FF68667F3FB4F06BD3E59FF8036D3C5E0B +:109270005210EF552F0F8F077AEA6FA7B41F7D8525 +:10928000F623EB02B1A1F6C3BEFB06921FD7731300 +:1092900071DC4D42F41037699B3C3F13ECC4544ED3 +:1092A0004641CAEC58A45DAB07EBD18EACA32B01B1 +:1092B000BAAF21217EDACC6039E6E5FE7911377448 +:1092C000297DE242A28DC73FB07827C2F9A0385F5E +:1092D0000E749E13711470CF16FC21224EA8399182 +:1092E0009F8373492EF44FF7DBA644B41FD0FD29AA +:1092F00085EEC7BEB8222CEFB71F35EB177114B23D +:10930000B510ED42CB42D77B19F0107ACB6FA83E57 +:1093100080F7341215A6D70D3AF681038A0B3B5518 +:10932000719EF5467A80017BC18B3C8EAF4DADAF0F +:109330003F9BC8E393F839E752F01A181F3CEE4EF2 +:10934000E0E332F530117727E0F8427FB8EF51C102 +:10935000B5EFBCD807F73DE1E02EE072AEA8F329E7 +:10936000C0976C3D9200F0EE8872EE83FAE947FDFB +:10937000A7245D705E157217C6CBF6B6CB783FCFCB +:109380003D81C55BB9F7C8C81ABA3B4CE837AD6E2A +:109390007F1DF5C2AE46CA68A91E76A6910EA9BF6A +:1093A00088BD4003EF81CE47623D1F68D62FE2752E +:1093B000E83A7F7F0938FC3E1C1C2AE45183E19E79 +:1093C000575F9C913E905115421FDA756CE6F4B0E0 +:1093D00056EF3C01FD1DEF4CDB0CFD55C81D07533E +:1093E000003EEB24BC7F35D1C4EECB26F3FB7425C5 +:1093F000FE063BDC374E4AB3E0FDA9E1DF919DE07C +:1094000017FE78DD6D31704F4CF43F5CD2E1FD4EBC +:10941000429EFBE48E42F0572EB06FA2B98526160D +:109420009791F9DD485F16E523AF1A8919F6A36114 +:109430006803DE6B0944CB68B78C93C924A03B3129 +:109440006F711F567C87FBFA70EF527C9FD81428EF +:10945000584BD30E4E0F62DD13CB03050D9620FC47 +:10946000455CA6163E5B383CDCF1C666D017BBCD2A +:10947000E2FCC95262D3239F596766FBE6D855E2E6 +:10948000FCEDB3C2B9D41DE1183C06F6DFFB32791E +:1094900092267FB1390647E3FA15D4C7D7D958BB0E +:1094A0006E1E07BFEEA3B244885F8E6F0A1F6FA6C1 +:1094B00024B1735C2DF7EF8BEFB57A1FC68DD542C3 +:1094C000BC7641F0FB95C66B8B78FC01E110AD27B3 +:1094D000FAD178EFDC79B17AAFFC4B0E7BBEBE3EA1 +:1094E0004927E20FD1EF4DCF5B61E30B4B93D8F9E6 +:1094F0002A1807E8C77BC37DF1857B4A13C945CE8F +:10950000FBEEF30E55DC9F8837779F9F84717EFDBD +:10951000FAA5FD2996605CE140F0DF92C8E6E58699 +:1095200078BF82D0EF0AFBDE374E1C8FDFF347C1D6 +:109530003EFD45BB8CF7EA7F714837757B9879D73C +:109540002731B85D13AFC77D33D2471CDBC28C2FE8 +:10955000EA89FB35E29EAA767EBBCBFC8B60FE10CF +:10956000471C6EBCA59C8EC4BC77C7307CB8F799ED +:10957000F09E05ED17E3BD77C7F857E2BEB0A9F13D +:109580007C3BB7D7ECBEDE9F81F7BCA6313BC34026 +:10959000F4E08D72FD04F5D89B69654A3FC5FA0673 +:1095A000C916B2FF2E450F41B8EB5478ED0F772363 +:1095B000E257F4FBF961BE4F89C302E7B7255CBEF1 +:1095C0002DD95183FAAF381F7DFEB08CF1179F1350 +:1095D000E627F9BC55C2F3CF521721EB291F5AF9E0 +:1095E00064413388B92549845C17C3BEDF09E94665 +:1095F000B59F7CF9BDFDEC872454AEAE200D2857F5 +:1096000056FE58DDAE9ADCFB67D09FB4FEFBE1DC72 +:109610002E27D6B139899E4740EF2926C5201FD66F +:109620003EF985314A19781F9CA67C77981EF8AFC1 +:1096300019D3AE461BA6BF48723C9644F1B727C962 +:10964000B50DD29EF759FFBDB5BD4C7E6C8D43B9AB +:10965000D564FD2EF2757908E3EBF7C03B09141EC3 +:109660002613D39712740D7214EA2D5EA487E3F1CA +:109670006BAA6662DE9E04741FF7CB295331CEEFCE +:1096800097910E80F7A652471ED8253655B27B9982 +:109690006613F3B37B7F31F63570830C6BBBBF0C65 +:1096A000CEC1B68EFD3EB0F7B4E8FE7C10E2575A4C +:1096B000AE63F18B093AFFFED490F1E223BD49E09D +:1096C000878F1F69C4388F38B934AF21245ECACD63 +:1096D00071D1DB9E8576C21E83B01BB645E0BDA866 +:1096E000DAA183818F5C43189E45DC1BCC2154DFBB +:1096F000EDA27084A04B91BFA64DF219A2F0FD120D +:10970000F4E3D4DEE54B980F72EAE77AF48389F943 +:10971000C5BD9A5C06FE2E219FE64B366647E3FAEE +:10972000FC3C22FE317FD95C4E27F3B81E3F3F92AE +:10973000C17B29B16740BB5BCC244A47B7D4FCF25C +:10974000B6225C678D211AF405E1F71958CF086F2E +:10975000FF723F6565F78DA54036747286C2E76279 +:10976000FB30C0F9B23B9BDDBB23C38803FC8CEE0E +:109770007DC3B7817DC23488F9AF297F3297E4A3D6 +:109780005E6D8673D4ADAF44F0F8222FBF4FECC8A6 +:1097900083F89CFAAAB47C8C13391AC07737BA0DB7 +:1097A000FE0CDCC794EF4854360EDAF2FD197AB895 +:1097B000AF9942F5359A2FD9722FCB0FF5AFD4D18F +:1097C000FC922D4FCDD0D3FDE1BEC67F0AF2355BB2 +:1097D00076B17CBE7FA54CF3CD5B5E65F5E160495B +:1097E00009ECC12D07677868FF67A2B9BCB7FBF128 +:1097F0009EB5FBE5E1BA503B6B6332E35B67B89D16 +:10980000F84C26595C05F01E11BEFEB2641D0F5ABD +:1098100069C554AC57B42749E1DB25F3716EE5F710 +:10982000A32746929608E6B7F344513C1CE8188EED +:109830007EC7AF9362989E6EF3E3FB38A21F014F81 +:10984000D19F187735C867E0CB9A78ACEC64863F37 +:109850003ACE461C679883DD2BAE4ACB03FC51BC45 +:10986000E939DEF4ECFCBB8DCD8FF61B9D8B72A02D +:1098700000ECF807BEA2F53383F3D6D24941329308 +:109880002FB736317F6B203A0BE96962247F67A5D9 +:1098900050BD8E660E87C6E4687E6F46C02B51C2EF +:1098A000719A381CD3FC78CFF24AD75DF11F5A77F2 +:1098B00008BE1CF05ECA81F6ABB7B3F5C4F07BCD31 +:1098C000FE8C18D4F7EE57F5776683A67D09C1B8EC +:1098D00036774C16B6BF278298F13BD9DED72E33A8 +:1098E00097E9ADA0CF8A772C88E73A12EA47EC7B5C +:1098F000AFA28DC56706D739A390AFD3C6D769632A +:10990000EBF4AAE8951C0964CCB6F6A7E33EF8F799 +:10991000F5372A9FF7A7DAE7E1FA837D3D105ED697 +:10992000733AF9D6F022E6A981671F9C35F313F04C +:1099300084FD8DED46A9E952CCB326599C9335FBA5 +:109940003BF31B8E57CADAD5DDCEE2B989A2A6EB6E +:10995000BADD993A882B10ED6AC127101FB4FF3D7C +:109960009ACCED8969246D80F8C4C7938BC2DA0D57 +:10997000F1BBF69CD813CDE2D5B5F68A9E787B274D +:10998000DCAFF49C63EF0A8CD3D86FC0CFF49C2576 +:10999000D82E285FD4F9739C3FF6B73F0532607E1E +:1099A00085A6B2E7153BD547B61C437E5D38B8ECBB +:1099B000B64C9A7F35F98FC8CF0B53CBBEC8A4FCE9 +:1099C0007C7FB29FE547967D3114F25BFCACFE4490 +:1099D000C7F3C0EF89C73F63527250AF782D59412A +:1099E000B8C9E53A027464022586AEC7F4AA09E351 +:1099F000F6045C074A0B4DBA8670F76FDFEEA307DB +:109A0000E65729813F15B0F3713B805FAFB203F495 +:109A100044B17BDF3D7BFF8EF75D3E487675021ECD +:109A2000EA23BB1665D2FC5D919FA01F4F72D03D0B +:109A300001F615C54616D0F94A5D9B9CA03F91D50D +:109A400076B31EE1CAED5E748D1728FC5ED9F7F37C +:109A5000EFA5B2619C308FB19C0FD4EFFBF26FE0A9 +:109A6000F7AD3F63B183F97A6CC796DB40FF1ADB31 +:109A7000F1F6974C0EB3FB3962DE63C1AE49BF9776 +:109A8000B49B70FE633BAE5E01F5C7FDB6230BE8E9 +:109A900064C2315F13B0859EBD2FA5AAEEE590CFBD +:109AA0002E1AD739A0DF4DC0E353AA540D4678F4DF +:109AB00032787C85F167DDF1879BFD68FC54DF7FA0 +:109AC000A2FA3AFA917BC9203BF833C47D7AADBD46 +:109AD000F468255D1FFD3E21406710A24F4F3C6F8B +:109AE000A68C24982F25D1AA7CB9395955BFC29686 +:109AF000A92A9F9274B5AA7C9A92A7CA4F1F315681 +:109B000055FF067BA92A7F63C93455FD4A47A52A1C +:109B10009FE76B53D52F38D4AE2E3F4264C043FE2F +:109B200051FBEB90169D74A0D9B5F874C3EB908EE1 +:109B3000FD0B0387D65E7CEDF9B6D7E1BBB0176BA2 +:109B4000EF3309FBF1CDB2C56B0C6F274ED2670521 +:109B5000DF1F9075EC3ED318ABEBEA94A2E07DA634 +:109B600089602FA648A8587CEE47E3004F0B983D2C +:109B7000ED282006E3BEAD68873C6A6878E60F2CC6 +:109B80000E201DF8DE84C05CD5BA279E77A9D65D6D +:109B90004A6ED5E0698D2A5F61BB5D557F4AD2066A +:109BA00055F934E5071A3CDDAFCADF60DFA2C1D347 +:109BB000360D9E7EAE2A17F4DDC1ED5AFBC01E4560 +:109BC000D3F1FECE72C0C375A703888F92CED67232 +:109BD000C0D3B547DB105F853E6739B0CBE2430D9C +:109BE000AF43EAA3E73168F75A6312A6071A15B420 +:109BF0006B1D6C1C81E9A1463B7EFF756309A6EFD6 +:109C0000343A307DAF712AA69D8D4E4CDB1ADBB005 +:109C1000FE738DEDCC2E16DBF7DE453AD807BA750C +:109C20007E377882173F927703F0CBEE41FE6EC805 +:109C3000DF45EC374CA2F925C044E8BEFC294F377C +:109C4000A43A028057371CCA8A82F1186D3A471E1F +:109C5000E8E177A44CF8A13E9D90BB3738936CD1D6 +:109C60002C6FA6794436C6B34DF8A18312D73320A2 +:109C70004AD0A933E106C8F744B07277CA841B40C2 +:109C80000FFFC6FE73473FFFF91D2961FCE7CF9C1C +:109C900056AC60D739FCD5702BC0E330B76F39486C +:109CA0009E61094D4BF5790690B34707B8B7F08030 +:109CB000AEB409E0D0A6B3CFC178EFEB0D04E8B79E +:109CC0004A62E75F51CF95CAE441CF0D263C4F1D54 +:109CD000D13956605C9914780CE0BC3DA512E1DEE8 +:109CE000630D6400FCBC294E968F0F3C26D943F2CD +:109CF00006069F07526EFCB6E1F35838F83C9162B5 +:109D000063FAB6CF910E7A80C81FA974D4C17E3E83 +:109D100052EAB80AEFCF384D6CFF3AADDEABD03E19 +:109D2000E4289A1362E719926A60F7D1E16222D8B7 +:109D30003B6F91719F6BE1392195E97B482770CE8C +:109D40009C1789E782233AF69E81B6FE020ED7B3AE +:109D500083C2DBE316A632BDA26C56DD332FD0FEE4 +:109D60007AD64560D73DCEE1A88FF53450E82A3445 +:109D70003DDD708E959BEC1C24E8BF9D0F7FD1F2DA +:109D8000673A6EFBEBEF68FD4FD645DA5186D8AEE9 +:109D900041F8DDC22B2F8C35A3FEB4B02ABD0CE4F4 +:109DA000E27CEE075C64D527A03B501F6D8427172B +:109DB000975BF29A2904C9CAB84A233C25559DB637 +:109DC000A619D2D5C3EE37C21329B5A37635831AA7 +:109DD0005B47B77011F23FFFBB8D745E8BD7CB0A28 +:109DE0003BCF89FBAE355714CF22E8F7088F3BA253 +:109DF00040C0F3EA220E6FD16E1187D78914AE3FAF +:109E0000E6909C0B6A3FD66740EF5D0BDFCD1EC02E +:109E1000CFA02EE7FAE3074636AEF6FD1231EEE2AA +:109E20005476FE3A62A49409FAE42D4C0EE4CEFD79 +:109E3000E2AE22BAFEDC0E9B0EE31516D7BD00780B +:109E4000E86DE778349076D84FB33C4B3EF91D224D +:109E5000264E758FF752F2D2DE692B0F9597857ECD +:109E60006779A8BC2C09B496835C14F251F84F7D35 +:109E70008DD59C2F37203F3DD0B81EF3071B3D9852 +:109E80001E6A6CE17CB915CBDF697C98F3652FE71E +:109E9000CB3BF17B47E35C4CF735BA583ECA19958A +:109EA0000AFBC4ECC2F8C437B69808F8E77A3B4C12 +:109EB000189F4177C4638FC641FC9109EF716AE333 +:109EC00090B47CBE8F1E76F77B372505C6E98B1FC5 +:109ED000027D71C8C0F474982856E04BF98FFEE4F7 +:109EE00006D0AF0F2B8A15F4E982D4CD2CEF50ACFD +:109EF000069A2F7C94E75D8AD504AC22F521E45BB9 +:109F0000873D8A3582E68B1F7D88957B093AF3C7AA +:109F10003DBAF5060FF059221D80FD516ECE9C44CE +:109F2000C50595D7A507605F4C495A3209F6C5CEDD +:109F30001405E9639AB2E100E4A78FD8A687ABFACB +:109F40000E4BDE4668571657A9877693D2D66C8497 +:109F5000769387DDAF0F6D3775D4AE8D909F61DF3F +:109F6000A607FD7427F0B1F8603F222FCA059F169F +:109F70007172A33B9C280F72DB9D280F045CCA669C +:109F800057DE0DF6CFFA76C926C13C664B7D410AF5 +:109F90001093E886F74929BFBE3EF597D60DB45D0C +:109FA0003DE4AFC5FC0F377CBBFCFBA6D430FCFB0B +:109FB00043BEDF41DE43DCFB8746F60ECC331C2E6E +:109FC000F51D4BACF88E2A715941CF7A9ECBF39791 +:109FD00020A5E59FF1B48B7F7F40E770C138AB527D +:109FE000B91FB23F7FA84965FB5F738F648072CE53 +:109FF0001FEA526DAAF73CEA08BBBF76A9383B6D51 +:10A000009CB836EE6435693BE8C8EC1F6F520BF71D +:10A01000DCB2FAC77F8B786A6D1C78DFB96A10E30F +:10A02000A77381D750BA6E491D904FDE7B0938DC8B +:10A030001B0E0EFDD643589C7BBF38241EEFAE5D31 +:10A040001771C5B3778D79FCBB767D822EFAAFAFE1 +:10A0500095C15FCFE04FF5BBC7607E158BAD04ECBB +:10A0600056A1FCE77717E13F5A7EF66DF1C99B17C1 +:10A07000D7E1BB6561F8D8F3E1F898B8CFAF4D856B +:10A080009E0AF7F3201E12DE3982737E65A26B1FD3 +:10A09000F4D35316F89B0ECEA171ECDDF083D1AE54 +:10A0A000FDF05D32B2B80611977C5AE7F915E86DFC +:10A0B000EF3DFA19F2B36E1016748FBC41F3A097FE +:10A0C000FDC3E67C13E04746F88DA1EF8F0F147FA8 +:10A0D000FB1B2EFFFAA76CDF8938D49E6D5F66A04C +:10A0E000FDEE12FB62207854C8E3FD703FA4B72454 +:10A0F00012E56797447CF0DE71576902EA2D5DE94D +:10A10000463DA4DFF6B9B82B3D1BFBD79E8FBB9213 +:10A110004BCC6CDCC953217D2FF95421C8BDDFF035 +:10A12000F8CB76A3A7E03DB00F8F8D40FFFE8D9258 +:10A13000BF10E0A03D5777BDB5A04CC9ED7FBEA6CE +:10A14000EB9B04EBAB3DAEBB1BBE5DE979BB76FD83 +:10A15000DF08C4B98F5BFF1581F7EFAEFCFCDD199A +:10A1600093AB805EE16A021219D345F5099ABF5498 +:10A17000FCD639899ED33343CEE5256FB3382E9E66 +:10A180006ACFE7FDDE095CED51C70D96FA8A305EB5 +:10A1900045F647E1BD601D7B6F43C473BDC9CFF376 +:10A1A000F4BC3E240DED709D19AAF3FA1D1F2DFA83 +:10A1B0001EF281088CEF78A6FD443CCCF58F9DF112 +:10A1C0003F794509D277BDED6F24F49DC0DAF5BD26 +:10A1D000AA7CD786E0FB56701FABF65F32CA252AF1 +:10A1E000C75A104FE435E3DA10F94ADAFEDC07EF1C +:10A1F000D194DF5502C050BE36CF74D07695FC3C6A +:10A200004448E48D0EDAAE929F1F8967252B8FE7B5 +:10A21000F53D9FB07CBA28FFE34CAC7F95E86F1CFE +:10A220002B4F1679DEDFD5229F782396678AF62595 +:10A230002C9F23C6AF64EDADACFEE4ADFF9C097A64 +:10A240008DE0F733D2B89CE0EF5251FEEF4C2BBAC1 +:10A2500068BC8EBA9CCB07F10E55C51DD322DF8595 +:10A260007DDC2661EC61ED9D06B4E79F8D69CB0D29 +:10A27000BD2F2FE27A9CE5568CF3AA7B71F8769974 +:10A28000C73B811EB39CFBE92B640BFA617AEF6537 +:10A290007C7E203D70E5FA9755F8EC57CEDFD3462B +:10A2A00047251DEFDC0F13F17E0219D689F102EE6E +:10A2B0003449C427E0BD6A11571797451C707E8E3C +:10A2C0007B2982BDA77AB213F9EFCA97987DBB6E3E +:10A2D000CBEB28EF96CA0ADA97BE1EEA5A07F0E9D6 +:10A2E000B6B2772F57AEDF87FBF431C5C6FD60816C +:10A2F00051A1F0BCB33FFC3D69F11785BFBAFC3FEB +:10A300000C7FAD5D5DDCD75F7D85F17FDD56E607B7 +:10A31000B6733CFD49A71473783D02F03AB7A233F7 +:10A320003B5A8620EE4E8C77AB90DF2982F3566F36 +:10A33000839500DEBBA5CEDC0FC3E05F7BAE389F0C +:10A34000415471693BFBC3F7E94BD0F7D3FF4DFA9A +:10A350004ED4FB8D76F01B1F65EFE51577FEC9180F +:10A360001A1FF44E1A3B070F6E677E311117172C18 +:10A37000B7323C71FF535DD53BE3C1FF24F6C3C444 +:10A3800048D206FE044AD7764ED776A06B41BF412D +:10A390003F146D1706BE41FA252C2E91C3E9B7FD77 +:10A3A000E1FAE125E0FAE17F13AEBBA93E8CFEDBCA +:10A3B0001722D04EA385F33F385C05BC23D32F0E64 +:10A3C000E7C8F4FF0C9C23D315959D43C07B20F96F +:10A3D000A4C58F9877987D5AF44DF6E923199C4FC0 +:10A3E000E9FD188FABC57B4C7A3FBC27A45F1CEFFF +:10A3F000EAF2FF30DEB570D3A6B5DC9FABFD5E9808 +:10A400003E20BFFB56E0F87FCD4FB0B061BFAA7CC5 +:10A41000F1FAB754E54B3CEF5F965F41D8FBFF5B29 +:10A42000FE05E15798F9FC2A1DF81FB5F24137C423 +:10A43000F923A0C71B5FFE7AD48730F9EA6C8CB78A +:10A44000BA8DAFE58BF17FFFE47B94BEBE6860F60A +:10A45000D663FB3F372839FDE965E1791D7184D06A +:10A46000D9C2F5EF1B40CF5A48D8FB54DAFA0FA6F1 +:10A47000337B30C64951BE30D74C0C71941FCC9DF4 +:10A48000CBEE4BCF0507630CA63E172D9FA9273EA9 +:10A49000788FBBD2A2F799D0EFA9BEFF6EE2EF751D +:10A4A00093B858D53D78D921639CDF9C12E62FBD27 +:10A4B000C5D286F787E71DBAEBDCF7602F6FF4147F +:10A4C000B1B87771FFF0F7BA2BF1833E087A2A9C76 +:10A4D000FB24EE5F5F6340FFBAB6DD2ABE9F66CA0B +:10A4E000128BA3D9C3E233C5FEA4EB3B64CA67F762 +:10A4F00060E0F7482A1B0CBEE1B9A067EF473DBBFF +:10A50000BE64432EE0AF7E9274DC941B3CEFD4AF6C +:10A51000FF0BB6D7F2676D7AB9F6D54F1A0F21BD8A +:10A520008873D1B1461FE6B5F6D60513FF17FD9324 +:10A5300063FFE26D8274DC578E0FC7D075FB1B3B47 +:10A54000FF2D7B82B02308BB82D64E21F88878BFCE +:10A55000D2976EE3EFB296A2DF83E8592AF8EDC1F5 +:10A56000FEFCF9D7E917D727D5E5FF61FE7CB9F4E2 +:10A570005F9BC4E4AA96EE8F56FD0CEDCF82BEB56C +:10A58000F4BF006252E8F80BEA25BC273E7755ABD2 +:10A59000619CF4CDE97DB5E56406839B462E5CB1F4 +:10A5A0003C50783C878CE70B93BCC60E760F8187B6 +:10A5B000AFD3D5EF0353BC48191797ABEAF2FFFAB4 +:10A5C00039E0E4A26F2617894A9F48CBE8B76EE5C9 +:10A5D00012EB56FE9BEB0EB9A7B448D605EFE3404D +:10A5E000FC35C481F678D9FDD4EACC56FCDD0352A3 +:10A5F0001288027E77EB5E99FD9E8EDEA14F0E796A +:10A600003FAD8BF83E007A5C359EBD3BA48D9B76BA +:10A61000F378EAD596DD78BF51FB0E9A88CB76F3B6 +:10A62000FEB4EFA189F6E29D03ED7B685332781CFE +:10A63000763EC967712917E7A3DD20CF43FC35DDDE +:10A640005F35A25DE1C6C74AEEF3A405F13227A348 +:10A650001FDF99977171BEA32EFF2FD3AF6CDD81E1 +:10A66000F7D8AE947E47643ADC407F822FF7F19BA7 +:10A67000574CC86FC43BF33D6B9EC1F7877ABE242D +:10A68000E897BDD43BE313BBD835C40927BD4D566D +:10A690008AD771C73C68AF1B7BC485F776C7BCE31C +:10A6A00080887F9277C029C3BC853E23F49B20FF1E +:10A6B000E2F7D9789CD5E5F2B92BF537FEA7FC8CEB +:10A6C000E25E5DB7C15704BFE7E0D91381BF03A1C4 +:10A6D0009DFF9319BA8BBE93DC11E57A12F0348B8F +:10A6E000CB09F15E7285CCDE49EFED94D15EB8EE18 +:10A6F0007F7EFBAB47954BDB15EA6DBD61CF6522D5 +:10A70000ADD7B17B2DF9E50AC649C2790DEC87C2F8 +:10A710009EA8AD7F4A297B2903ED5BE3F13DDADE9C +:10A7200087D97C06C257FDFA008E3F60391FBF7E75 +:10A730006F912DF49D95F3197DE743DB297310DFAD +:10A74000974B17FFD7CE2D3365E291A87CCD91BCF6 +:10A750004CEF254CFF5D403A315D440298BA08BB8E +:10A76000CFB094D8315D4E9C98AE555C5D191837CA +:10A770001448C0F8D317FF390AE8E6DC75E35A211C +:10A7800046F1DBF22369F5BE9E3C85BD97F4C23FDE +:10A790007F07F4D9F33F86CBE21B47A21C6448181D +:10A7A0003FD37BA532BBD754F25DDC17E2FD5D32AF +:10A7B00089F9E1962766E2FE09F2CDC46D826F82C7 +:10A7C0003F39E7B88EC5C3DC2AE17BC6ED7E1D6E3E +:10A7D000B19C15995EF8DDB9F6DDAC3CA72EDA2BFD +:10A7E000D17CCED80856BE26DA0BF74F16123FEEB4 +:10A7F000CBC570FB4486FB4B8C2F8ADF0BA02782D6 +:10A80000A1126DBFA2C3CCEE5110FF30E0FFB970B2 +:10A810007E0A174F3384F1F1D14319BF1F5DA6B6ED +:10A82000870CE5E5F72965DF0778B40C71640D81C5 +:10A83000FA319D9B1E2C043B908E809FE6B3B1B7EE +:10A84000A35F53B47B51291B01F59F9558BCBF678B +:10A850002FBF6F4C0209A1FEB1B54A792ED42B1A35 +:10A86000C2F8D3407085DF517486392F8AF8D1D170 +:10A87000706643BB3CC177D29E95587EF2E35B6F16 +:10A88000DC68415F8207F4E31715D744186FB49171 +:10A89000100BCCFFA7FC7E1B69C800BBE8AAC74C05 +:10A8A0003AD02F3EA2E218EEF7FC819EB721FD9828 +:10A8B0009E9B21FD233D37437A9C9E9B213D41CFAA +:10A8C000CD90AE386F87C7CCC989218EB9D0BFF083 +:10A8D000F769E75B3984F1D7BEF1F71A71FCFB1415 +:10A8E00017C2B70FDF7B08FEDEEDB3D18194988BE2 +:10A8F000D05BCFDEBFA39F7420B808FFA3B67C0A4D +:10A90000C76BEE6E3DCAFFDC767FD4CA907A2B8788 +:10A9100018B17DCE0B27A3A0FF6E5B1F7C1D125DBF +:10A92000F24C1DCBAF7CFCB91B378E82F93BBE0FBE +:10A930007441F7F96A4873DB7FFB00FC5E2AED1F68 +:10A94000E3247AA4C0663C2F68D6A1858358D7B388 +:10A95000D19D9BA0FDB32F0C859550BE43D8BE0161 +:10A960003A92C2AD7703AEE74653A010EE0BDD7806 +:10A97000410E1BA77D9F528A704E067A43FEDDCAA8 +:10A9800053465F026FDF747F6BFB23E2FD15E0A58A +:10A990000AC8A5AFA2402FACE4F104EDBB87FD06C9 +:10A9A000D6E9392413F8BDDAD131EAFDB78BE34992 +:10A9B000A4397B8D4EC0D7B37B4F0D83F789297E99 +:10A9C00086C17BC5DB865C45427FEF3167EC978FA4 +:10A9D0003C1887F5F1F769E7916D15103733DFBC47 +:10A9E000FF0D58D242DBF10A889B599C241D8474C8 +:10A9F00089923919E265C47D8365234A0FC2969A0C +:10AA000061AF447DAE14984C887C283747F247D814 +:10AA1000853C8A55E5A724A5AAEA4F53B254E5D34D +:10AA2000478C54958B7167D80B54F546C70486C282 +:10AA3000798EAE83BD03FFA48CF186392F1CB97EBD +:10AA400024CDCF7C6A0EBE43F92C2F9FF95CB91739 +:10AA5000F0D143E169A40AD5E9921F6C7E103AD384 +:10AA60009C176AF73E71D0A15CC679E112E7848138 +:10AA7000DE4F16EDB5E704CA371F00BE39FAC5D957 +:10AA800036F0DB3E3BF6CB148847FDCD10FEAE0C16 +:10AA90003F3F0C44377DFB435218DDBC259327C351 +:10AAA000D00D44F2323A64E9CCC3EC7EDE95F2B5C7 +:10AAB0004F81AFA1BDC043427F7F576BDF1B6DB499 +:10AAC000FFE636B047BD2BC30DA5BE7B932BE16FD0 +:10AAD0003948EF64F9B6BB93E3F0BB07F46137B7CD +:10AAE000F70D52B83E55BBFFEEE4C2603959775CB2 +:10AAF000559FDC2935ABF21B33D5F97B4B9B43DBF0 +:10AB00000FA48FAD7C7889D19503F76EA5B0BF37C0 +:10AB10002CE6F3FF010980D5200080000000000032 +:10AB20001F8B08000000000000FFB5190B5454658E +:10AB3000FABBF7CE0B1960782810427798440A8444 +:10AB4000895728B08DA01ED7DA1A4C8F545693E53A +:10AB500003794DE0B6F4D8E318AD8FB6076D5B69A5 +:10AB60006B355696E7E439B144462536AE5B49EB82 +:10AB7000D654A266E499D8424C70267A6D9D5AF755 +:10AB8000FBFEFF5E672E605B9DD64EE79FEFFFFFEB +:10AB9000FB7FEF279014CA70CE0008F6ACCC7099FA +:10ABA0000106F7D61AE41880D3F4EFE2F0DAB8F928 +:10ABB0007A8303CF5700383ACCE3CF01D601140390 +:10ABC0005C29817BA2F3145960E760FF65F1BD2F1A +:10ABD000010849009E178DDEED5684E35C06676E22 +:10ABE000F89E8DF04E0618D972FFEFBF2AC2F525E8 +:10ABF000B0E30E8CC4430DBD9BD7755C1471CD9F23 +:10AC000004D7D17779968098806B7055B407E200AD +:10AC10009A6A633C623E9E67860E992E04C8F1A62E +:10AC2000B59B52018E8A22C039440778A014EFE305 +:10AC30001B045F24A739EFA4DFB9C867CC2FC7E78F +:10AC40004532B035BF3294E9C67BD77E87E71CBF5B +:10AC500003A291CE3F804A8F034C5C2E04BBBD19EA +:10AC6000FE3F233F4DBD1218909F61F01DBA5A6000 +:10AC7000D7CCA925002BE9A74CFB1D0690D86F194E +:10AC8000707F95B2BFB27CE5A5108BF056FD4020D9 +:10AC90009BBD0FA7F1FFD57F6F3798F17CF553DA95 +:10ACA0007D420F53902FE5FB3AF0B377EB77E23D0F +:10ACB00053F85E23DCFD9984EF367669BF5F24C7C5 +:10ACC000240DE6E08F0228382DB16D91DE6B36F150 +:10ACD000F7E64ADFBD7B09EAB1E925C96EC4ADD10B +:10ACE000DDD3E200F98339A8E4D4F1F26BDA8C7A8F +:10ACF0002A0CC3A7764BF3BD745F17CAA89E315EBA +:10AD0000CE60C9E2F82C1C5F73C5D70B01F135F793 +:10AD1000E8D0D07E00CF4611E4083CCFED31AEF252 +:10AD20009AC3F4072D9CC7FC9E2F1366E7F2751D8E +:10AD3000D101ED1C2F70BF9821803E09F141B56013 +:10AD4000DF8E4B5F4F7225C9BF4F009F5CC09E587E +:10AD50006442FD5CC19FA37D3324E08F946C1DE1B0 +:10AD600059A8C8FD8AD27F7C23E0778B7B164F439E +:10AD70000AE050D7B23ED40C6C906D0CDF12F0E8B4 +:10AD8000492F7DF1CEF416A4F3324960F6DF171F88 +:10AD90001A16107F5F45B4D026B0F7EFA4F755BE62 +:10ADA000FAF4CE7437E36B8E6510F526382E904E8C +:10ADB000478F974758AE3A1854F52B7177217F9CEF +:10ADC0002BDD3EFB12F4DBD1A5603122BD974B6831 +:10ADD0003808C3ABDC8FAB49D63351AE823F81E834 +:10ADE0006C96176E91F1BBE4D67B41971821371D05 +:10ADF000F733552FAA1CC7D3A1E22DF73B90BFD143 +:10AE00001D02B39F46BBCCECB3B1FCE4834B107F77 +:10AE1000A35FB20B48CFB2EEBD47487E1D6B3B40EF +:10AE2000771E40E7DA6EB62E33997D521EE38BD93A +:10AE3000AD8846417CAD5660C6A7357C1EE67B0CCE +:10AE4000BC513F7C06CE043818EB7C9EF85BF3FBCC +:10AE5000CFFB9610B51BCAE3991F90AD9D1BA63F73 +:10AE6000DF006046FA43DBA3BD4F303C68AF25618D +:10AE70007B3DB127EB700B9E9F7853CFCC755FC5A0 +:10AE8000C3A76E4178CDF66826E71309E049A5F31C +:10AE900027A67B3D7861A518EA6F21B977C6D8B798 +:10AEA000E3F9F147A73FBB13E1DA67A7D9894CF271 +:10AEB0001F19E57D3C1D01DA7F3E957D07291CEFBA +:10AEC0000AC52FA56766DC574EE7CF24DA098FAA9B +:10AED000BFA147A31C80F2FA127C791634BD93827D +:10AEE0006750C487EBC49DC704B4CBDB0CAE83C4EE +:10AEF000F7EA47FE7AA80CF9A97AE6370FCF44FAA9 +:10AF00006ADF9B0CF44E58AFE3E2406C2097FCDF05 +:10AF1000C6FD5F914FDD8E28CBC71171A6A1235EC0 +:10AF2000033775A75A3E8E883775C0650CF5828E3B +:10AF3000F8A957FCAA5E741D25BA1A20C0E3228422 +:10AF40000C64570592E0A07810BAC7C8E43FD6CE8B +:10AF5000466591D1512F828BE27941229852C86F78 +:10AF60005D5C7EC17BA63F7117CA66923541F5FBD9 +:10AF7000AC853322EDB3BFF115B2CFCD46669FC38A +:10AF8000513C2F8DC5F31F399E7DBFC2F405F38759 +:10AF900033F9A4F5DF5A38171C14EF0ADAE4C29B20 +:10AFA000706D51F4722CC5295849EE1DF7EF3AC067 +:10AFB000E4B9F5E6A38477BF99E90F0E70B90705E8 +:10AFC0009E27D5F7569842A02B247AB7317AD5FD23 +:10AFD000C12D87F35CF8FEE00B397980F6BC4CF2AA +:10AFE0000FFE05E5732AC67FEC365C3BF7BF3B8559 +:10AFF000F2E0587AEB5B47D97B2A3C2CF038544F6F +:10B000007CE0FEF799CE64A213C3088B0F0377CDC3 +:10B0100060F29B2BE5C691FE8327B4F48DA5537D8A +:10B020005FA54F7D5FBD37CD2A32398E18FC7994EC +:10B03000F75FCC90357C8DC4FAF3E2CDB46FE17547 +:10B040004402C211F656433F51BF35268CDB485FA0 +:10B050004D8D606F03B6EFA1B889ABCF85E7F529B9 +:10B060002F2B7203A709ED78B162679094C8EC6E3C +:10B070001170BB5EACC4EDABA0430FE82F47C475A5 +:10B08000BF35A0FD0D773CA07745C65DCF51F1746B +:10B09000CE4F8FBB9E4AC8A6F83D6231B3BA669EBA +:10B0A00055D0B17BE9904EF7F0DCEE433BF0741ADB +:10B0B000ED6D48CFE3A2738115E5536FF0E5911F65 +:10B0C000A8DF3D2EBAD8FEB0706005E91B74BE3C07 +:10B0D00056EFC41B40C03A2338D9EE77505DF625B1 +:10B0E000B0B812D4434D27E22DAA12DD9DE6703C84 +:10B0F00054E367510EEEA35C2B685FF557B49BA237 +:10B100007CEDFD303F5AF8B895FB5D51A2E8EE9812 +:10B11000C05F6E57F4DC061D12F7679E47CB14B96B +:10B1200063DD2245D62D8D4A9C0FC69A3C12F25300 +:10B13000B61BF5827099CEB797568C02D08AFA9DCD +:10B14000053EFE5EB7369E530E59CAF2720ECBCB49 +:10B15000B31475AF17DC407A3551FEC2F52EC12FFE +:10B16000D1FA2B08B1D501161DADA806B6CE012720 +:10B170005BE7819BADF3A19DAD0BA083AD97829F53 +:10B18000AD7081AF0D583EB8DD3288F9187EBD52E2 +:10B19000A4BC5CB464E27AFC71455E67970746F92B +:10B1A000929F2F8F79E04A61749D4D2E53B399DDA4 +:10B1B000AB7231927DE27751E04DA1B50202EC9D78 +:10B1C0008BC990F19DD920EB08AE020783E7FE48BA +:10B1D0007994065C3A57EE0472A99AD84E7628768E +:10B1E000524C365D1CD6D787561E1754BD01D24926 +:10B1F000F960BC3E2183E82C8AAEFC5CC690F1DA93 +:10B20000B6F79D3A8CA34585952D36840F593FE5B9 +:10B210007059E5F399081FD976D2A99B49765E59F2 +:10B22000A8B76315BA6ED83907CF4D18FCA3504E96 +:10B23000924D82525C5D51B179807E6794ACEB7423 +:10B24000E857C6DB80C5195714809FD5B36865E4FD +:10B250002735BC7E5D63E17ADB6B70BD4A7EDA60C8 +:10B26000F2C5CAC8D39A757393295F6E30F0F73F61 +:10B270009A2CE7BC827232223E5341984F3CF744ED +:10B28000211C10E496566B18FF8FC0F7CF1FC277B2 +:10B290006B8AEB5D16CF4D5940FA4F53F2796767D1 +:10B2A000598A5D24FC16863F1093D5D28A470752EF +:10B2B0009C1FD27BC1186E771F5AB95ECEB69A32E8 +:10B2C0001D1F5827D80FAEFB7A978FE2D02748086A +:10B2D000BEF399D53540743489818C42D4D71DD1C1 +:10B2E000C70C6427AA1D0BA8BCA5C87F9B03BC067E +:10B2F000E61FE59633F5982DEC07C1E5F81ECAA5C3 +:10B30000C8E9ACD2E371498D7B1FADA5AEF62A3CEE +:10B31000213C41A2A7490AAD20BB3815FF9EE1138D +:10B32000E6A753B93D2AF1AB674FEF6D691C744234 +:10B33000841F36EDF9E6AB0F50DF4DA3663B5D0F82 +:10B34000FBDF9616EA0BB01AD4C417D52F67751B0E +:10B350007DD45F95ED3E7F39DDAB78AFDF4671FA86 +:10B36000E2FE401B95CBC19EC369DC2FD43AFE6B35 +:10B37000E1E7E493B9120575ACCB5E90BC46E4AB53 +:10B3800099EA0B05F6207CDC84761347F779BFA990 +:10B39000F6950DBDAF19A82FC1673CC46FAD42FF34 +:10B3A000AAAD375C4AF562AD57DB2FD6F57BD713D4 +:10B3B000DD753BB4FB6ABFD9A47C5F4FF59A8DEA7B +:10B3C0003EEDBD26EA37F3A8FED3EE67662AFDA65A +:10B3D00092FF40A933572A77883F33EBFF0C5E2357 +:10B3E000F2D6FC688BDD4270BAD9CEE26DFD0666FE +:10B3F000C7EA7DD89AC86C44F5DBDA8DC0EA675598 +:10B400008EF94F1B1DA48FFCA793595D8CF53CABA7 +:10B4100047309EF0FE1E6522A0DD3D171FCA1411A5 +:10B42000CF733DD976AAB75F5EEB807F9D17A64F9D +:10B43000ADF7E74A3BAB0CD447DD887D146E35F79A +:10B440003ED96642B87913D00D242D3B8EEAA6E290 +:10B45000FD1278E91DF03E508E6B971A4F52B0BE28 +:10B460008F9047943C09E409FA79A3A2B7E8EC0469 +:10B47000CD798CFD1CCDF771A599DAEF3D0E7F6E6D +:10B4800009C573FE7DBCE302CDFD36C16DF791CDDC +:10B4900004F03FBC57AE88B1C2BF82CD1D12E71782 +:10B4A00068EE6F889DB79FECBBFC0BDD183B704BC3 +:10B4B000647765018047502FB386B5E7C507DB2168 +:10B4C00016F1471DD48D99577880EA16A3ACDD5F3D +:10B4D000AEDAC55498AA99439C913BB7FBD1219110 +:10B4E000D945099CF7707911C9590F5E79BCDC46C2 +:10B4F00069A5FB6603F38B59BD2D768A47939D5A48 +:10B50000F927D768E59FEAD2CA3B6D9556DEE96E0A +:10B51000ADBCCF6DD5CAD7EAD1CACFB67196E6FE1B +:10B52000B4F64A0D3C7DF302CDFDF3BD0B3570CE74 +:10B530008EAB34F767742CD39CE777AFD69CAB7691 +:10B5400036D60E2EF4358FB13311C408FDAB7A56C2 +:10B55000EDA070FFAD1A3CFF6FFD6F1FA3FFA7C8E2 +:10B56000D731DEBD153B7437B9EB65D13CAE9D9943 +:10B570002794EB59BFF6B69C5815437795FCE654D3 +:10B58000F21B94FF91C3160EDBFDF67D14CF0A8EDD +:10B5900038AB88AEA2807B1F85F392A1F6AA38BA99 +:10B5A000EF00D932858F9CE8FEE5A502E8347E8560 +:10B5B000F094B03CAFF0AC93E2F072D977DE36167F +:10B5C0006EC9E94BC2F320A194E7856A4714E822CB +:10B5D000E452A1EC0325E92961F9ABF323EC07C0A0 +:10B5E00040FD8068F2B65927AA77EC9B25568FB9A3 +:10B5F000587DF686E06273A545267F06C5F7DF25F0 +:10B60000BBDECEC4B8764AB4CBAC9E13026DC45434 +:10B610009018A3A4E5A9AF76501F87ED2CCD2BFF82 +:10B6200074476DB52797916F0994F0B699FEF56749 +:10B63000BA8E64A2FC0704CBFA42FCF6AD5927335C +:10B64000287F1925944401CD4F1C47E9FCCCDC240C +:10B6500019F9C3781B10650F89C273ABC0FA9093B8 +:10B66000F4D8CC08FFDDA867790B94BEEC1A455ED0 +:10B670006A5FB654C13F804FACC2787E4DF71B4C19 +:10B680002E7529C3CA1CCA6DB7E0FB374C3517505D +:10B690005F0A8E423BEFE7D53E2D4DFA297955EDF5 +:10B6A0006BCF76BF2E6548D32FC3CEC409E7916315 +:10B6B000E75E61BEF9FB039BA2591E1AD894CEE641 +:10B6C0008BE1F74FB1F7AF71BFA3B193EB5ADFD75F +:10B6D000D8DFF59E8F34E781A4903E0DF90FEC4A38 +:10B6E0009D7735CA6FE4056309F5ABA8B7385B7180 +:10B6F000F8FDC03DD3E710BEFFCDE7A74CBEFD6B04 +:10B70000FD6CEEA6F2796CED110607D606D83A96D6 +:10B710004FB5BF5557C3DF209BEAE59030C93ED1F6 +:10B72000BCE6311BEF83FA674FA9A47CDC9F6ED087 +:10B73000F1358BC3A9A5260ECF9B4F6B506FDE480A +:10B74000FD6DBF000E01ED61A9E07CEC7AE4BB3A2F +:10B75000D9956BA37A7275284F87FED0941FB8567F +:10B76000407DBE1EEFCA27FE052C065313189D59B7 +:10B77000D4370C899E3C0163C14D4F765753FD3F32 +:10B7800034C9738A3276ADADAB9AFA832103F78F51 +:10B790005B9E7C84F9C3B716D74C7AE71341F2312C +:10B7A0007B7E49F06E67F616302C8CF8BB823AAF80 +:10B7B000A17E9BFA9B60145F67DBF8DF5F2AC7AC52 +:10B7C0004B6D3CAEDD426B31E9E5EE2CFA7BCAE80D +:10B7D0006623905F203E8748F87AF85C760AF2404C +:10B7E000750D566FAC5F2878D5E8A3F8A1CE751615 +:10B7F000DBACECBD241B9FD724DD67F4B6B1FCEEB7 +:10B80000CFA8463ADBF558EF50DF7010D81C6D8496 +:10B81000E661117A596CE3FD17DC08C0CF93B7D10C +:10B820007943EFC0318A27DF67BAAE24390C8872BA +:10B8300009C59386D8BDACDE6BB6C9EC3BA497F1C5 +:10B840008F71E14ED2CF2F380F5C45FA6D300578FD +:10B85000DDAACC03CF26B791E5FE8772D9FCCB9E3B +:10B8600041F4A9F422FDCDB688B99D4A7FF89D1F09 +:10B87000F60B75AEA5C2835B3664919FA15EF8BCE2 +:10B880005112AE5B38C1F70F2AFA3E96E2F410FE71 +:10B89000D56E3EF70BDB4DFBCD4749CFBD66162776 +:10B8A000CFF6FD583E1BF6F43279209FD7127F1158 +:10B8B0007CDE1BC9E748CFE18772E59FCF5F309DF3 +:10B8C000FF1D29B8ED9B0C19BF6FD8FDC611B2BB87 +:10B8D00006751EDFA59D33182761FF9A30D11C1D08 +:10B8E000B34F445D6654BF9FAAD37E8F0539CDA95F +:10B8F000BBC9DFA97E71F0BF8BA9F9B84BE96B8496 +:10B90000C0EB2C1F103EF287F58287E545758ED17E +:10B910002660DE23DDBA5A589E90CE35DBC99EBB29 +:10B92000D006FDE4073A47349B5F8FE9A3BF35B8E3 +:10B930007691FCD6BC53994C7D76E79B0B947E8D1B +:10B94000E7A962C52E8B093FD19F1BC7ECB548A163 +:10B95000AFC484F55026857C8FC4E715CAFC63D339 +:10B96000EB9A3EEFBF32596853001E000000000002 +:10B9700000000000000000001F8B08000000000015 +:10B9800000FFFB51CFC0F0038AC515191844D41924 +:10B99000184C341818566820C46989B5B829D39F43 +:10B9A000C9C2C0900DC4B9409C0FC47C4C0C0CFCA7 +:10B9B0004CC4EB171445B0F50419188480FC6F02D1 +:10B9C0000C0CD7851818BE8B30300803F92E40F1C7 +:10B9D0000420CE01626FA0580B905E04C4DD402CA1 +:10B9E000228ADF7C5102F26B8551F937D1F87B84D2 +:10B9F000F0EB5710C12FAF47401E1B16D1223F3E20 +:10BA00002229D03B10585F01955F26C7C0D0270F71 +:10BA10008C7FA8B80192FC4B20BB5C0EC2F69660EE +:10BA2000602806F20D15B09BEB03942F01CA7D85AB +:10BA3000CA0300CCCCBA8C680300000000000000F0 +:10BA40001F8B08000000000000FFE57D0B78144507 +:10BA5000B670F574F7CC2499994C12F2E03D490088 +:10BA600011030E2144C0709924C0A2460D021A147D +:10BA7000750292849097887EECAEFE330189A0A86F +:10BA8000F1B9AC17DD416137B2E8060C1835E0605A +:10BA900000B32EBAC145C0E72680BC362443F0B9B6 +:10BAA000CB5E6F9D53D533DD9D09C4C7DE7FEFFFAD +:10BAB0008F9F5FA5BAAAEB71DEE7D4E942328F27E8 +:10BAC000640A21DFC18F969F8B8490F850596F20B4 +:10BAD0002E924188D766F46D4CA6CF88237AE6680B +:10BAE0005A981DD1375843EFE9CBD59EA434691835 +:10BAF000210F791C5812E223844EB55A2005F51601 +:10BB0000A83B93E07D3A3E21FDE8F80F46E2F8308D +:10BB10002D99181A671031E07B53ADF989B01E4298 +:10BB20006A47E6C3FC163B21FD7B9F9F8E88EBA7EF +:10BB3000EF0DC1F724FA9EB5EFEF2965570EFD13FF +:10BB4000F6DF6DF66D1408F1EFFCC77158EF9986BA +:10BB5000390E135D6F76B7D93F05EABE6C9F89B683 +:10BB6000E76EFBC026D1FEE5DB4409DA0D3B23F08E +:10BB7000FDCE75820FEA95A6D647AEA4F5C03691E4 +:10BB80003C0FD3F82D069240C87133613F8715EB07 +:10BB90004511AC5ABE7ED76D305F49A38944D0F7BA +:10BBA0008F37882EA82FD928F8089DAFFCB5078CB1 +:10BBB00003E878C53EA13EC241EB1B1F333AE83E85 +:10BBC00097EFFCD8D646E17CDA63260E23EEA3A4D9 +:10BBD0003E8D9052DF96E903E8FBA59B052780BECA +:10BBE00074DDD94E585F69833C5CA4E32DAE8B2293 +:10BBF0008E916CEEEF08CCD77C14E7DB260F83F92F +:10BC00004ACEDF650424E56E93912ECAE93A60DFDF +:10BC1000CABCA73D6B713E059EE52FD2F968BF8A6D +:10BC20009705276CB1C240DCB08ECED7220A5EB039 +:10BC3000C0FEAA8D23ACEA7D146E877D94FAD61BD4 +:10BC4000A75B607DEB8D4569A1F116D7FDA7767DD9 +:10BC50006B5313DD69BDE3F3B487827444A85E4A75 +:10BC6000880BE94FF219818E95E7E78518C4F7E252 +:10BC70003A9138CCA1F1153AF07EC0E9748795F17C +:10BC800001C7DB123BE02C84B76E3BC7A314C8543A +:10BC90008FAF948F003EE87A6A3D762C1FF72461BF +:10BCA000F9A4C781707BDA3312CBB51E273E7FC65D +:10BCB0003301CB751E1796CF796660E9F3E463BF55 +:10BCC000E73D05586EF0B8F1F96F3D2558D679AAD1 +:10BCD000F0F926CF322C377BBCF8FC65CF2A2CEB51 +:10BCE0003DB5586E057CD1B2C1E3C37EDB3D7558CE +:10BCF000367AEAF1F9EB9E462CD77038DAB248B6BC +:10BD000044E16073113B453B89CD7365CBB41E9B09 +:10BD1000CFEA09F3BCD9465A4F70D33A85CB80326B +:10BD20007FB689D60754B1F621F7921C33AD0FF1D7 +:10BD3000B2F69435AE9C085A4FA965ED23D67973B7 +:10BD400022697D848FB58FDAECCF89A2F551F5ACED +:10BD50007D4C13C9B5D0FA183FABA7EF73E55A690C +:10BD60003DBD95D5333FF1E6DA683DB38DBD3FA9C2 +:10BD7000C3273A2C3DF1B055762C2014574DDEB92F +:10BD80002E89CA9BAD46C75DC449C87BDEF92E89A2 +:10BD9000CA8706D985ED6DDEC5AC6E74617BB77759 +:10BDA00029F6DF2EBBB15DAABE0FDBB71BDDD89E27 +:10BDB000505D83ED8DB217DB47563F8AED8D462FE0 +:10BDC000B64FAA5E8BF5D7651FB6E755AFC7FEAF76 +:10BDD0001B7DD8FEF8FD9B5C5369FD05C1BD1DE4CC +:10BDE000DE0AC15D4252819EEA9340EED570F9F9B8 +:10BDF0001C101D6DAFE96F443EDCFA6EE60BC0BF50 +:10BE0000F8EB07F5A2DF3E988CE3BC89E3C8741C0D +:10BE1000F1E2E3A4BF3741334EFA7B25CA382D380F +:10BE20004E44DFC6D9FADE24ED7ADE2B55C6D90F93 +:10BE3000FCB4C2DAB77DA5FF394BBB9E3F9729E31F +:10BE40007C84EB89E9DB7A1A3ED0C2A7E183207CAF +:10BE50008EE238F17D5B4FC6412D7C320E06E1D378 +:10BE600081E3F4EFDB380D07B5F069381884CF971C +:10BE7000089FC17DDB57C6212D7C320E05E1F35FA3 +:10BE8000B89EE4BE8DB3FD532D7CB67F1A848F49D6 +:10BE900080F50CEFDBBE323FD3C227F3B3207CEC3E +:10BEA00038CEA57D1B67FB675AF86CFF2C089FFEF8 +:10BEB00038CEE8BEED2BF3AF5AF864FE35089F1478 +:10BEC00001E033B66FEB69FC5C0B9FC6CF83F0B922 +:10BED0000CC719DFB7F54C38AE85CF84E341F86461 +:10BEE000E0BE26F66D9CC6E35AF8341E0FC26732D8 +:10BEF0008E33B96FFB9A70420B9F092782F0998E9F +:10BF0000E364BBEB985146C7B1F63ECEEB67B4F0A5 +:10BF100079FD4C103ED7E338D3E838A9171F675294 +:10BF2000A7163E933A83F029C071AEEADB38AF77AB +:10BF30006AE1F37A67103E8538CEB57DDBD7A42E53 +:10BF40002D7C267531F88C3B50956BA3ED54173A38 +:10BF500045FACA951D2E9740EBA29DD545BB93800F +:10BF60005D222AF606697589F47DCBE698F4078987 +:10BF7000DAEEC8B913E8C74AAD31B5DD113D21523B +:10BF800063E7C4B86235F5B8190334FDE3F35334FD +:10BF9000ED8905A334EDFDDDE99AFAC092499AFED8 +:10BFA00083AB7234F5A1CBAED6F44FF6DEA0A9A7D1 +:10BFB000AEBA59D37F78ED7C4DFB256B4B35ED97B1 +:10BFC000FA9668EA97D5FD42D37F74FD724DFBE582 +:10BFD0008D0F6ADAC7FA1FD7D4C7B53CA3E93FBEB5 +:10BFE000F5794DFB15873769DA27B66DD5D4AF3CA7 +:10BFF000F9BACECEB3D88F5FC6EB22D03D61767F43 +:10C000007FE6F7F8AD46AC1B0758D08EDF652D7282 +:10C010001CA3F835BEB5C0D18FE217700A7E45F675 +:10C0200080924BDAE8F37B26B92FB1D3E7F718DD1E +:10C0300097DBC3D8A7941E049204A5C300A5BEFD38 +:10C040000199D163CEC0F323DAE9FB9586C0881845 +:10C050005ACF12B31B817E770ACC2F8A144915F46C +:10C060008B3411F40B1E48CE7CC1ABA2D75583296B +:10C070001F0AA17157C9EE24B033DEAA6EF7821DE4 +:10C08000523398EE6B0021CD42BBDF4BFDB4070667 +:10C090001725B9E9782623B5D3D5F31BE9FC693810 +:10C0A0007F0BD0EB7B307F7CCFF94D291334F39B92 +:10C0B000879468E6371BE9FC7642DEAF3EC5E7A70A +:10C0C000489844C85F845338BF694809CEFF8091BF +:10C0D000FA2BEAF92383F31F86FD7FD6DBFE532676 +:10C0E00069F73FA454BB7F23DBFF91EAB37CFE4892 +:10C0F000DCFF51E12CDBFF9052B67F131B3738BFBA +:10C100002D08FF93307F672FF39B52B3B4FB1F5A68 +:10C11000A6DDBF89CDDF5DFD2D9FDF82F39F13BEBE +:10C1200065FB1F5A86F31B4D6E27D08F7160649597 +:10C130008FCE4F1D6107490472A1F340393216FDBD +:10C14000E49784145CC73D918CDEBE8AA4F486F229 +:10C15000C6CBFC581F956C99D4EFE2B4BE7873B689 +:10C1600011E412B6537F65215FEA1D8D22D2377923 +:10C17000D2E41B4ED7DBD9287AA17EC793937D20CA +:10C18000FF2A4DE4F67C784F227E78FEF953A39F78 +:10C1900057EF4B5F2EAC958FB7A9F82DE847E59088 +:10C1A00091551698D7AEA91FA17E10A1FEC527D420 +:10C1B000CF2094248FCA6CBECFA8BF04F536EA2FD7 +:10C1C000413B21D5B85FE2757D308CAE3F9F283F63 +:10C1D00017EEF32664293A9EC4F8F7C81AC107F887 +:10C1E000B87D5914057E683D85DE384D9DEE0FFB08 +:10C1F00007AE127CCF0B38861BE033938F4760BDB0 +:10C20000B45E6067EF1CA2E8EF4F51B060D5408A82 +:10C210008BD038B3884B4EA4EFCF595A2843E8A2AD +:10C220005510062F01FA5920539711E0E78D276921 +:10C230009C38E87A6FB6B3F167BAE4636DAAF51477 +:10C24000C866573E5D4F41A188EB9F3543DBFED169 +:10C25000CE2897610C2D573D81F3CCC9D7B6DF545A +:10C26000A0ADCF756BEB54EFC9A0F76E29D13FA7F6 +:10C2700060A1FB9C17842B5D285DE7AD1C0EB756B3 +:10C28000C95E0D5EC16D55DA21A0E026B82F7C5F36 +:10C29000ECD9FFF665DA7AA1575B5FB04A373EA763 +:10C2A0009BE31CFF47803E687902E883C2F318A72E +:10C2B0008F905CD5D2C78DC16D30FA50F6715C623B +:10C2C0002838BE8ED1C7C2DAA8F0F45018A4079758 +:10C2D0009ABE147AB88DD3C3A79C1E8AD76AE96A1E +:10C2E0002EF1AD4CA2EFDFB26617E2E9A050C8E82C +:10C2F000E1970A3DB469E8C1CDE9418FBFDB383D24 +:10C30000DCF673460F7A7CB6717A685B7B4E262921 +:10C310003DF14AF1A0A9533CE8F06E37023D507C54 +:10C3200084A587F9C17DD38DD3FA02DED6035F9C45 +:10C330001EB03D05C04E104EF87E6ACFFE544E68CA +:10C34000EAC56BC3E3BFB2313BEE986A5DE5F557D2 +:10C35000C51D53F55B5C3753535FE49BABE95FBC92 +:10C36000B650D3BEB07691A67DC1AA3B35F542EF5B +:10C37000CF35FD6F5F56AD69BFB56AB5A6FD969224 +:10C38000C734F5B9EE5F6BFADF54B05ED33E27FFDA +:10C39000454DFBAC195B34F599AED734FD0D3B2F01 +:10C3A000BD1EE831EBA048C0FE38E67120DD1FF766 +:10C3B0008CC4F2A4C7897C71DA3301CB7D8DCD4F5B +:10C3C0005C49BB7C192888264C7F16911842F62CB4 +:10C3D0007757AFCA027D4E50EFFE717951B5771095 +:10C3E00095530607C2396FAD91F8C711228052E20A +:10C3F000F307C4507B561B6D8FEBBD3D6FAD14B67C +:10C400003DAB4D0A3B6EE5E38543ED61E233217EB2 +:10C410002603C13EEAE2F6B9BEBD4C20F9EAE78444 +:10C420002C47FE8F3130FD5C666472A26C6BFF1C82 +:10C430006283BA7F44D585E6ABA7CC9508F491AA70 +:10C44000E1E3E2B59769E43C81E86D3CD0D938CDB1 +:10C45000F3C575576ADEEBD825E2BA2B4086507DCE +:10C460003D8CE4070CA097FDCD43668D8675BACE52 +:10C470001A405E35C6A3FDD8E19911774C023CE61F +:10C480006379D25380E5718F1BCB639E122C8F781A +:10C49000AAB06CF32CC3F2338F17CB4F3CABB0FC7C +:10C4A000C8538BE561CF5A2C0F7A7C581EF0D461AB +:10C4B000F9BEA71ECB564F23969D1E17960ABF297D +:10C4C000F0D0D3DD49AEA74F03FD5D80CEE2C407B7 +:10C4D000AA570D0AD159E28A87ABBD59A171F3D68B +:10C4E0009A389D2468E86108F864E3815E4C9C5E9C +:10C4F000C2B7E7AD952FD89ED526871DBFF2F97F2D +:10C500000DBDCDF991F416A2A7813A7A4ABD183D26 +:10C510004D12C787E8698EC1CEF41FA7A787601F99 +:10C5200061FC8F6230EAC6ABEC3A57148B67F37349 +:10C53000076AD1B278369F7B051DAE15ED3FDF4807 +:10C54000C073F7C8BF8F80787DF761AA28937BDF1F +:10C550009F9E5E7A87BB0BFDA0221F55A2E37AB691 +:10C56000474432B84618C80C924EC8EAE1BF75CEAF +:10C570004FC3BA4462E17D9F736698F32802674F08 +:10C58000891787EB0AEB576360BCE3CFFC2313CA20 +:10C59000398614E6DF348B68DF13FF0B4E806F5053 +:10C5A0001F999C4910070F0C37DAD13EF059B4F0AF +:10C5B000F3D27A66087EAB298C5A51DFD72621FC4C +:10C5C000867D35A27F1FE07731397F3178CEF70D38 +:10C5D000F897C0F362F2F1627291B81C2F37D2FD66 +:10C5E00077ED1C9DFEA003E4E085E1AD9C5FE9D7FB +:10C5F000F3BC287D2F3AEE4A50E8B87508A1F388BD +:10C60000A21DC7EF6EB884C92FC5EEDB66F2F50533 +:10C61000AF6792B5E33DC5F94F19AFBBE5051BF810 +:10C620005B4B920CF66361F0A094E5F5C9768BDA6A +:10C63000FE6CD4D6BB6B8519F568273AA2678F06C6 +:10C640003D61B71F1B06723B094B659C254946FBA4 +:10C65000312AF74ED7A546333FCFC7E4C1E6189439 +:10C6600017A73D66ECFF53AFA7B77194F510D24002 +:10C670008E9A411ED3B6D4DEFBF74ACFD217463C82 +:10C68000F76D92BF02FBD04CFFFF0EFC0D22615DE7 +:10C6900019B7B25EF49A2E87E79B35F3D1F71CCA1F +:10C6A00019EB772917E21B891C57E896EA8B635C24 +:10C6B0009F2CAE8BB06BEDCF184DBDB2B1BF5D639B +:10C6C0008FC21F54FE922A4102FA29E3E4D325596E +:10C6D0005609747D6F429010E85660FDCACD6D46D4 +:10C6E000B703CE9519DE7A5B1FC5DF4C89927C8932 +:10C6F000B916CF614BEA2F9D0A7AE64CC38A0488AB +:10C700001B2C16BBEFC90FF3BE2C3179BFC827070E +:10C71000B4F63DA70F42C7559E635C94588EABEAB2 +:10C720001D06168FD18F9B00E3C65F1C3E159BF73D +:10C730004F073B410FA78AC6B34637CA45FA5F6623 +:10C74000084E0AFCDE14F313243A7E695D3BC62DC5 +:10C750004ECADE11BFBC80BCECB93F4BD2F128D52C +:10C76000BEBCA415E6993F814F441C377D4CE5F8CB +:10C77000A93FC904E410394F7B65624886FB3B063C +:10C7800062C80CF93BF31B16E701BC4F81BF47E5BC +:10C79000E61D24DF867820B599E0DF9C218619000C +:10C7A000A733E47DDB38151E7225238733958294E9 +:10C7B0001E4CC1F1DDFDC1EF3215D4B48A63E0B97E +:10C7C000A4F83FC2771847720B98B750C09E7B8978 +:10C7D000B91AE897FA511A3F8DFA519A3AF5A334EB +:10C7E000F522724302E425143D29139F8070D2B4D0 +:10C7F0008F92EC88C762525503F6D1AF79FC6DBEBB +:10C800009D4803E93ECB5F7D36B390EEE76A89C56C +:10C81000FD9473F545B10C0EA5253EA3CBD2737FD5 +:10C82000471BC6DD48253F8CC7CECF6F36621E053D +:10C83000B44A99DCF449E97DFF890DA22BC206FDBB +:10C84000E87365BDC9DF7FFFFAFD12F238EEA3B4CD +:10C850006E2601FAEB9127C0F723D7092E5F187EC9 +:10C860002AE474AFE8A73B017EE343F1ACFB74F527 +:10C87000D51CBE4AFD295DFB0F962FFD8846BEBC28 +:10C8800029BAEF93C6337902F017A400F2D70F1E2E +:10C890003FA9C7F8AB811F7FB2F10769F99E8EFFF0 +:10C8A000D44FBAFE613DD6BF3EDCFACB5F7D69BB9B +:10C8B00097EA97D23F3C652394DF4E49B5094E8AEB +:10C8C000F7B28D2B6D2E903B92D7067C71CA27CE86 +:10C8D00008470F87B87CA506884580782BFC49C798 +:10C8E0003FBDE9A1EBC09EF86AA36CC7386A9DC939 +:10C8F0006FA2F45CD1B0288F8CC17A3BAB3F70162D +:10C90000E8BFB2513EA2A6D3D2DF3D95007935945F +:10C9100052061A92A0F4A37F52B1E1F3E9606F547A +:10C920009200F2ABFE3D98FF9B58D48785C6E89EE7 +:10C93000ED18984980F7D9AFB2E1A1B3A20DFE6A14 +:10C94000C33890BE7F09F7375A246B3F3C27B98222 +:10C950005C01F2548107F1317F63C58BBF1AD34E5E +:10C96000D7D3B1E14F36410527C54FEAAE5FF09B03 +:10C97000D71DBDCBEF4ECA876ABB56D14F8E46EE50 +:10C980002735B1B24CF6DBAEA4F2A46CBDECF4D208 +:10C99000C7652FBDF0DB67207EFDA1C9399C8EBF26 +:10C9A000F8A53D0727D1FAE22D72BF3CB60D8B905A +:10C9B00010C24B25FD7F597A080FA5AFEC313A46DE +:10C9C000B3E7F7C686F0B178CB2E2319DD131EB975 +:10C9D000F5BB8C6D963078A96F9F0E76DF8A17BFF6 +:10C9E0003682BC3BB5532089C961E0B97E0FDA8538 +:10C9F0000027C423C753106FBAFE95142FA05F14ED +:10CA00003CE9DB37717902E339D2909E5F7E9DCE9F +:10CA10005FF291C909FB2F79F92E1BECE38454C511 +:10CA2000E8FAD9950920DF4A646F821D4BF6BCE411 +:10CA3000B9BB91DE8AF7DF9DC0E292AEFE06D495C7 +:10CA4000DEFEB0BF85EBE6E0FE8A881BE9AEE45966 +:10CA500031DF47CB2F2532634B18BEB8566672F2D2 +:10CA6000C4F35423D0FD9D50F4C0FB22D70377625A +:10CA7000DCF36EBE176A3162FD4B33C3D330D9C0CD +:10CA8000E52CD32B417ADDF000EA8BD3835D8970EE +:10CA9000BE5619D20FA837C4FDD312197E989EC175 +:10CAA000F7A89EC985E7D0BF5576458CD1BC877A5B +:10CAB00045997F299F9FAE3B12ECB51309E1FD8F8D +:10CAC0009FCB0ADF53BB42455F2AFE66FCBE613541 +:10CAD000E36F85DF7D336740FB170718FFC07BA03E +:10CAE00067E9BAFC89D8BE6BB680F2C044FCE1F8B5 +:10CAF0007A83CCF95ADBAED0095DB72444ABE805A4 +:10CB0000C68F45F8A35E2F7A92BEA7929795309F65 +:10CB1000ADE7780ADF1673FE9F216BF99FAC8BEFB0 +:10CB2000533E6599ECFBED33C0AF943FBD0EE0572B +:10CB3000391FF6FDB7CDCD076FA67CFAB77A854FC2 +:10CB4000B5F253CFA7255BEF26409F7A3EFDDBA0D1 +:10CB50002A12964FE9F3B07C3AA8ED7F547E2AF072 +:10CB6000AB02F84585E0A7C8C3DEE0A8978756D991 +:10CB700011561ED2DF0192D993FE14BA53E8ADF4D8 +:10CB8000F7E54341EE04E952A1BB205D2A74A7DF1B +:10CB9000AF167EFAF64932C175E5BF26A3FF5CD613 +:10CBA000C4F242E97B7B0766209C5CA8C648EDDEA8 +:10CBB00081FDD4759FAE5EAFEBEFD2D5F375FDDD91 +:10CBC000BA7A95A67F5963B39120FEFD9A7EE2B2B0 +:10CBD00067C8D1B870F4EA637E59C359A317E8C295 +:10CBE00012C0F7E5E5C40B7986811D22C605BA2877 +:10CBF0008C6B207EB139D9E7A5726365048B3F74D5 +:10CC0000D903B6585AAE8C61F540BCB106E49EF229 +:10CC10003C10C1E28A5DF9015B8CCA9F6A6F1251B8 +:10CC20006EB7F9C88C707E16D528C8476DA4B77644 +:10CC300076EE354DB40C590671A55AD10936F81D5A +:10CC4000D537D9E0DCA9AB29F5FA02FA7CE11F451A +:10CC50004C7BE98AB48D817511AF4BEAAFF26F4E10 +:10CC600012EFD359747F0B9A989F73C71A9D3D4258 +:10CC7000D6203D1559961A419E527FE288F6BC8611 +:10CC8000F145291FAF649DB65D799FD201FAF3A5E6 +:10CC90001BB4ED6EEE0F7FA0F0C9583296FBA32CAB +:10CCA0000EC3E5F23431EDFA028A8FAE1691986820 +:10CCB000BDBB49447C746F167C104F23DE78E4B70B +:10CCC0000A124079A8C0A903F8C9D8BBBCEAD8F6B3 +:10CCD00069E62F816EB67F3CE63F69D9B1FDC3118D +:10CCE0006F40FDD543433E263DFBE7EE8CC073FF0E +:10CCF000AE9D56A4F7AE1DEF0EF925D45F33396112 +:10CD00009D5D3BBF1E03F4D3B5DC5402F2AE6B3025 +:10CD10008BC7AED8F1F59836D4AFF733FD6164FE1A +:10CD20006177D33F3E13FA4149770576C3CE28E4B5 +:10CD3000A7CAD72330DFBB6BC7D7996ECB4FB79F3E +:10CD40000A9EE7D16525055B617D312C8FA1F28DAF +:10CD5000892F54D3F9CB1B761917D0F6DC37FF395E +:10CD600006E468D756660F75CA6DCF411E4394F12D +:10CD7000DC7299E2AB13988A3ACDBF3366E402DFE6 +:10CD8000F484CB3F313ED65778A4FCAF8187E06274 +:10CD9000F2CEEA330BB0EF6F3FFB18E39A26A44BB9 +:10CDA00065BF7FABAF467BE562FBCEFE7F6EDF8269 +:10CDB000BF2FFB76FF9BEFFB38D7BB7A3EE849E7F6 +:10CDC0003BEEC1FA4B5627AEB78FF4EE85FDC7FF99 +:10CDD000FBEEFF7BE37D2BC5BBEDE2FBFECDFF5AF7 +:10CDE000BCFFF1368E773B7ED7F3E63F717DDF5790 +:10CDF000CEBDF96F8EF7DEF6AFD8F5AD862A7B068D +:10CE00005D5F01A9B582613137BEDB92E1806CD7ED +:10CE100073FD308F0ECE4BC3F84D0123F30B4D90B5 +:10CE200047077EFB1C41890BA21F751DB71FAE1B58 +:10CE3000548276C875AE8799DD2055B566D3FEADB0 +:10CE4000390B9C987349D20FBBA13E7B32AF6BFD6F +:10CE5000C9F704E212A81D7F5DCE352D60D75EEFC5 +:10CE600012D1EEA525DABB1F0C99CE9E4FD0FA3D0C +:10CE700073DDDAFA4D05DAFA1C3EDE8D84ADFFC6AD +:10CE80007CC107715553F613F11067352D948990C5 +:10CE90000CF942552BC1BF9893AF7D7F1FF8C1E3BA +:10CEA0007F3C1C534D0A1C97205C48B6E8DC48FACE +:10CEB0000047BEEED6D9637D90CF4C242783E38D07 +:10CEC000E54E8C83737F5BE6EFCB9655ADC0CFB25A +:10CED000CECF56FCE5DEE04DB8FF8DE3A484E02F15 +:10CEE000BB44F4BF659DFFADE0E5FBE243C1E38FCA +:10CEF000C5CB973ABC0CB2B808F0ABCCFD85A916EF +:10CF000027AB0FCA2778DEC8FD05A99F8B78D342CF +:10CF100079DF8BCCE66C385F338F1430DE71FD1A0D +:10CF200011F583394DC075E54F90318FF873437E0D +:10CF300026E03B6FDC1515BF60CB70023C1771B863 +:10CF400017912AB45FC9F9EFBECBCA84730682F683 +:10CF5000EF221721D752BFAD284BF0475278154B1F +:10CF6000C41B9D0E716F811CD1C4BDB575F8FD4702 +:10CF700042689C8BF5EF4DBEFCD4E55FA93C3B328B +:10CF80008CFA411E9EBB4958DC56F1AF6F6F627040 +:10CF9000AC2C137C2948777E395F75EEF81CE7834B +:10CFA000BFDE3B0EE564F6A3A3A3D1EF7739D06FC4 +:10CFB000A8E47E43B7D7110D71AEEEA6547E3E9B1A +:10CFC0006B53CB55A5DCCFFDEEBF407E212DBBA61C +:10CFD0000AB522F8712480F15CEFD408B2314CFE1E +:10CFE000EBFF311938FD54611C007E6226E091FD93 +:10CFF0008AE9ABD1B12ABCADB9F69434A6271EE0BC +:10D000007744750EF963E10B7E3EC0757F44DBF417 +:10D01000FC30FBAD35B13856DE5BDFE2779C373450 +:10D0200025CB00971BA68A9A73FB5526EE978D2376 +:10D03000E3605D796F5D659B087869119DF0DD6641 +:10D0400065D359A33BCC79B01E9E303EC4D58FCA60 +:10D05000CE2280E7D1872308F8D1EFF273C634F8E7 +:10D060006E220D433A2E882BFE9AC3B5D364C77245 +:10D07000565EB61C4FE74D6BB08F85A3D401BC7FC5 +:10D08000271821E3218987BDA7F41B50C6FAB51BD9 +:10D09000ED15E1F63F3C82EDBF9838EF9920FCFB9F +:10D0A000E12DFB51AB3F07EC83A93CAED283AE0927 +:10D0B000F247F70CC107FA1BFC61ACE7B1EF84DF64 +:10D0C00055BEB3BE81E95985EEF570DECBE1ACCC3F +:10D0D0007FDCC4E2AF7FE2FCA5C05981AF7EBD4AD0 +:10D0E0007F2AAFA6A8E351D7378E7D19EC9B8A26FD +:10D0F000C16EA04355486D46E0C3CAC6C764386FC9 +:10D1000099EB60E312297F8C3A9FA0D3C4F23B9A3B +:10D11000D3AFBC0DE8E4DC1A13E842E2BAE3AC0D8D +:10D12000E4F0BB06E79FE17B6AEF7B22D9780179C7 +:10D13000F5B1A7CE3555528F9B8CEB9C55962D4360 +:10D14000F8EC96B25D72A28A9E3A4DB1D8AE3C1F01 +:10D1500050E64887E7743E5C87F7111381EF42D2AF +:10D16000EA5BF1FBD45BAA62181D96D4EF32623DF4 +:10D1700019FB2BF329F3E8F969769E36EF78416EB7 +:10D18000DB20804B9EC9BFD419864E1F332BE78E00 +:10D19000DF534FB828DD8EF9FF484F2C55F4441B60 +:10D1A000E6B92BEFCF35333E57E989C4707A62492F +:10D1B000B52311F0B064476A2230C9923F4E4B0844 +:10D1C000A7273EF0B073E343FCBBEEAED9544F5CEF +:10D1D000AED213B323904EF4EFE59A95738D8BE89E +:10D1E00009056FFFC3F2E603D01361F8FB46B3569F +:10D1F0004FDCD854887AE2C6D9A2E6FBAA6BCD17D9 +:10D20000D313D90973B12E3BA3C2D0CF07DCBF39EA +:10D21000C4F3FB611ED0176BCC76849B5E6FF42643 +:10D22000D7C7F655AEFF5F82B322D797CC61F743DD +:10D23000F4A44382F4BC642E95EB02D02393EB4B11 +:10D240006EE5714E9D9CCD07399BA196B3ECFD0A0E +:10D2500037D30B958DC9BF9A47DB6FAE959D66DAC4 +:10D26000FFE690DCCD54CBDD356609E1DC43EE967C +:10D2700030B97BAE691CDA4FBDEDEF532E6FA93C80 +:10D280001BE60C431F05F3A234DFDF1D1DFB76DA1E +:10D290002BC02FEF8A787EFB39B703F68D7D3B03D9 +:10D2A000ECE9537C3DDBB8FCEBF4F85C53A91CC8FB +:10D2B000BD83D9D3E59B45845F4503E3FF8A619134 +:10D2C0003E07AD4F4FFF16CF6117EF60E7B0740711 +:10D2D00079D92AFC2F7EB7AD06CE0516AF17F01C04 +:10D2E00019BE5F0078167378163917E3394AF1DAF8 +:10D2F000F0E73FE5BCDFA2A6F5180F5FE4D3F62BFD +:10D300001F76F529F047F24C0C0F79AF08BEF5C92E +:10D3100090CFA0EBE75C8DE747E5F5DAE707F97E0C +:10D32000178AFEB457E8FBE4CFCCBFD3C3FBA01EE3 +:10D330002E253F122EFB295C32FEF570E90D0ED42E +:10D34000BEC7F3013D3C0E2B72259D64001F7E6E0F +:10D3500070A15CF1BE43E142E7BBE3B1E19AFB405F +:10D360008E73B8BC6B70D7F4877E1502F62B5EB750 +:10D37000654F02ADCFAB2763E178A178AD560F07BB +:10D38000F57E8303F5FABCAA2D02E4C72EE4DFFB89 +:10D3900095F81EC37B546E5D46F53CEDBF20DDE481 +:10D3A0008673F0FD1101949B0ADDC64730FB258E84 +:10D3B000CBA1A3030253513F350A76E4477F04D340 +:10D3C00057144F70BF4BF3C4AFA773BCB0B8522310 +:10D3D000C36325C51BF0F3F4265EAF6376E02D4AE8 +:10D3E000BD5EF0390490ABBB64765F8C40E2048E86 +:10D3F00004957E84F3D5EC04159E77B433FADF28C8 +:10D4000038F1818FFEF743F0DC2BDD333BA6AFF420 +:10D41000AEC0293E428BE7FD11AD79E3FAC1F99B1D +:10D42000E0C47B739A62F09CE8582DBBFF2595BF42 +:10D43000A7E70BF03BD4F7D1CC8485437EF38C086F +:10D44000CC0FC57953985DA6964FFA7B80BE6FFED0 +:10D45000512569457B2C94C7E87EDE04E3CD10346A +:10D46000F94E1009033AFF09C6BFD57C81F14992F4 +:10D470001DF396EFB22BCFEDECBB2C5E6F1E9C79AB +:10D48000681E85EFB955A2135CA89B0C8E835920AA +:10D490006F1E9409F0CBB97DB28BE98128D43B850E +:10D4A000EF1EC5EFD90A590E1A29BC8FE997A37C44 +:10D4B0003D1F51BDED82580AA91F0FF7E0CC76EE53 +:10D4C0009AE680784BC6FE9570CE392BD77EF02039 +:10D4D000E07335BB07E9C8AA5CF4D3EEBA53407ECB +:10D4E0003B4CF106EFCF999D7CF0209DF7D655F18E +:10D4F000786E39CF157F239C63CEDB273A1DB4DFCE +:10D5000082EBAD1638C7BC66A448DC2AF8DC4A5A60 +:10D5100031BE33AFEACE39B0EE12AA0FC56428F798 +:10D520004F4B84FA3A01DFAFF4BA8DF0BD66EBDA07 +:10D53000B3C60C3A7F11ED0760AF5CC7FA556E10A9 +:10D540009C90FA5DD4F418CACBA20D025E34D34A83 +:10D55000ED5F331BD767A6E3B6AEA3EFD37A31BC3A +:10D560000FE36E88B911CE272BE93AF1FD09D57882 +:10D570002E5D44DFA3CDA475C39D38DEA275028164 +:10D58000EF034B26243F3201C6DB273BA1FDD0AE83 +:10D590005F1B61DDB7D1F9FAD3F117886DD3A03FD6 +:10D5A000F9A560C7FB87EA4660DCAD0B360C2F544B +:10D5B0000DC73AE6133B100C923A1F654704FB4E29 +:10D5C000B86859750DECABCD1B9F6C40BA3A6B0433 +:10D5D0003D7E8CC2DB4D873C6A64792ECDDEA3C6CE +:10D5E00036951CFD282215DFBFA3311BF3261692AA +:10D5F0007CCC9B7057337BA47D65840FE26AEDB2CF +:10D600007D083C6F5E69C2E79D2F31FDD339B80DAF +:10D61000E3DB27D6C904BE5F5CB12EF569C0E389A0 +:10D62000CD32D29BF82CCB1B287E89C5C99AD7B1A5 +:10D63000714F2C35B27BB5A09DD68B5F54F20AB4E6 +:10D6400072ACC8518A724A2F97F4726BD193D54647 +:10D6500020D91EF26AE9749457A554EF00A1F59001 +:10D6600057836A306EAA975795C4A2C8A974885F79 +:10D6700016960FBE6D2DD0F1ADEC838156FF6B5F1A +:10D680003E057AB7CC4AE04985647F5A6074418090 +:10D690005FE6356DF912F8A0645E04DEC7751CF014 +:10D6A000007CB3260ECFAF8B7C85086F252FB77813 +:10D6B000AD96CE95F8E35CB7485C6AFD5512455CC3 +:10D6C000AA7E87EEA3F44AE7B9BD51F081A83C7465 +:10D6D0005FFBDEBB33B06EC7752DE3F6C11A2BD2EC +:10D6E000F3A19F9F5D09F47ADBBD02017B9D78DD8C +:10D6F00035A00F2BD60A0E880F17DFCBDE2FA6EF33 +:10D70000C3BA0FFD9AD115A56F07D07FC5BAC7F66A +:10D7100062FF0D8203C63FB4BE10ED8912AF48B060 +:10D720007D433BFA0F544F619E59B3574C00FAAFFB +:10D73000B8DF64075349A123852EDBF97D08C4ECCB +:10D740001C338BBEB70A1615DF931EC50221A84FE6 +:10D75000814E2ABD8CCEDA5F929D403617A74BF6DC +:10D760001DFC09AE5FC567E74C87EF748AA97E048C +:10D770003A6D5E976B043BE2844FC0FC8A9E74490D +:10D780002C6A3B4AA1CB670526AF7BD0A38E0E7BCC +:10D79000D01DA74B85FE2851A35F59B64F26F0FD3B +:10D7A000BD9E1EDD72FD8D90FF51F832DD0F5D6F65 +:10D7B0006ECDCFD15E57E048EB09502F9258DE8FE7 +:10D7C000C20FE512CB0FFBDEEBD3CDBF2982E7877B +:10D7D000013F882C7FC94FE77D7BF30B982F79663B +:10D7E00053FB7568DFBC41E900E0BFD94AFCE87F24 +:10D7F000F8500E953688986F4D247FE62C95DFAE55 +:10D80000E4BF2CFE8315E15DBAD5E4CBA3EF976EA0 +:10D810003F3A06F311960730BFC7BB4960E71FDEEA +:10D82000B631F0FD50A9C4F270F476C1F04816E7A5 +:10D83000EA782DAA00EC36A18EDDB3575A7F936C9F +:10D8400052C5750745CA382FED87E7635E8A67B80A +:10D850001F01D6A7BEDF4DC9BFE97891D15F69A38B +:10D860008CF65C69DD964EC8C32C3D6C423FB7B266 +:10D87000EEAC11FCD8DC3FBC84F7F355368A9A3CF9 +:10D88000BC1EF96F75A2DF04F95B0DE5787E43EBF2 +:10D89000ED58AF0F9F077AB13CADC57FD8B1DD4BD6 +:10D8A00041B8F895DFD9F0BEBED68D36FCEEA9EEB4 +:10D8B000C2F9A73DF2DDEA575F30DFED34FC4109E4 +:10D8C000EBBA485DBE601D936B747D99F961E2C44B +:10D8D000417BEBA52F9F837CEC8EAD7F7B0ED65BCF +:10D8E000F65FE79E83BC1AB233C20EF648E5A60F78 +:10D8F000309F5579AF2492D97F9D2FFE0EF3803B48 +:10D900003F343961B4CE1D278680BDD1B9E5DB0433 +:10D91000C8EF5DBA631AC673966ECB4D2461E205FB +:10D920004A0974EBEB431EB21E5FCD0DCD98FF7319 +:10D9300086E21BE443307FB1BE9CE5833A78DEE2A9 +:10D94000E6F0F9DE3DF2141B665D3F19E46203B3B5 +:10D950000B2E9AAF7880E2F1F23EE06FF36A2E4F21 +:10D96000C2E3EF0CFC41F15413A9CD57FCB261E1C5 +:10D970006F9E81B686B85EF315FD7D809B924F3E0B +:10D980002BD2F55824F0CDD6DF637E28E02DCF01D1 +:10D99000F2F9CB2110173E290730FE10D861C2EFF3 +:10D9A0002C4B771C42FEE9DCB61FF3B509CFEBEE3A +:10D9B00024C11FCBC3E5B19ECA0D5696E7C8E10F3F +:10D9C00079900E1B3EE7F98E8C8E953CC8DEF21FD7 +:10D9D0005B2253F87D2A2C4FB37CC3C73CAF308405 +:10D9E0002F6102E0A9FD8279A50A1CEC00872BD4E7 +:10D9F000F9BCE1F34C8379DF1C5F803F90D3C17C9D +:10DA00005D5A1F04F99B3EE11009230F3AD7B33C3E +:10DA1000E04E39FCF7CC4A7E6FB39E4F7D7DCBEB59 +:10DA2000BDD8FABF2F7C1A221D38AE1E4E1DE7C38B +:10DA3000CBF1E39CEF7FF0F7216582FEFB93CF8172 +:10DA40001ECB1BDA8D789F89E23FF1FD76F0785A84 +:10DA5000C72611F33E6BEA9B518EEBE545053F2748 +:10DA6000D1AFF71BBEDE8A46A6273AB65A7D163AD4 +:10DA70004EC75BAF213D576C6EC7BCD3BD75AF18A9 +:10DA8000DB54E7CBA0277CAAF577BCBC6B0CCA6D36 +:10DA90007EBF987E1E63149BA7B229FC3C959BCF4A +:10DAA0006AE659ECAD37DA2D179FEFB4E4BA09C630 +:10DAB0003BDDCAECA5D3F5E20C5F98F94F71BD4987 +:10DAC000482D3B0FA5FA12EF59B3B27BD5445B2426 +:10DAD000DA5F4BAD130E47F783D288792F2BAA79E3 +:10DAE0009ECC7DCE24C0F70AEBD504D6BB12E0ABAA +:10DAF000F2E365BB9B80DD2627E567A8CF5994F547 +:10DB00001BFB19884F85FFA5D61989E07F12C93BF9 +:10DB100008D6715DCAD712E8BF560F8BDF93F34763 +:10DB200087C1F356C9BE278E8EDB3A557042E8B5E1 +:10DB300027DDFB347186992EED7DB1F80D1CDD5F7C +:10DB4000B7D380F6A0D5E0B7D32EC41AD19A840EED +:10DB5000AC8338A404FC1402F3211EF49867C1FDC1 +:10DB6000C83642CD53E8E79434F79F444F9074F79A +:10DB7000A19003C328BD5A38BD2A71392BFB9B8E57 +:10DB8000DB86F7ACC4A4916A20DF355637DA0D4F37 +:10DB9000F0FB69E86F24E441C49248A7FAFE263AF4 +:10DBA000AFE6FB383AAFA61EE3D2D6E36648C7C25B +:10DBB000E99738BE8EE9A205E11033CDA0F86B7964 +:10DBC000C31342EB8E89274E3FB45F6BC1EF012830 +:10DBD0007B79D5FBB058B4EBA6EBD3C889E8B43653 +:10DBE000AF81AD53F3DC4E1C02EEDFA57D4ED7AB0B +:10DBF000A917467179271109E49DC5DC4A38FCBB99 +:10DC000035F0BE5FDA373801F043B85FED2590CFCD +:10DC100012CDF741E7D7F4B7437480CDAF1D870C21 +:10DC2000B2ABBF43BD9CEBBF5196FC2551949E32D5 +:10DC30008756616276561249C3EFA59BFAA17C4ACA +:10DC40005996837927422DA3AB616B08F2CDB000C2 +:10DC5000CF9BBA3F12ED5193997823D2E17B36E204 +:10DC600095D361161FCF43702C37D0A1A45594D6FD +:10DC7000E87B4D811CC3428A847A68A2E35746B987 +:10DC8000AAA3289FD6CC742719C6C2F6DE5EB93B7C +:10DC90000BB9F65288081AAAF7EE69198C2204EF1C +:10DCA000F120DEBD7B80C66B953A15ECF09D7F6D53 +:10DCB00064B0EE3253795F9BC2EA8F3EB47725DCC5 +:10DCC00037936ECF7F14F649CCF65178DEE58FD5C9 +:10DCD000DCF3DD9B7E51D63972833F17EE05BE3AE9 +:10DCE000C0EEF51D6E0D7E778F7A78A345A9FBD126 +:10DCF0008FC86FD88F72ADBC7E3FB61BA04ECBA134 +:10DD000071FEDC81749F2F471D9A9674291DAFA167 +:10DD100030093ED97F35EAD01EF8EE3004878F57A0 +:10DD2000EE1E148283B4FCC33D2D93D570F8700FA2 +:10DD3000D8217D85C3AB0F7D8870E8EBBE295D6C73 +:10DD400007BC5C936DC0FBD6AE386CC1F80AFD45CC +:10DD5000A03EE2E3ACEFE5BB6CC51FA1E3EC54D3FE +:10DD600097F29E4257BDD14D2AB18F62F76C6AE996 +:10DD7000A72BCAF536ACAB25CA758F351EF78FF7C2 +:10DD8000005CE3763BA78E0BD135B1B8C7C1FDEE81 +:10DD9000A32CF35BA354F2F29AEC25620AC4C98166 +:10DDA00017E243FB895FE68D1841F719EF3260DE19 +:10DDB000FC288BFB20CC632B08F82177EC0AE21EB1 +:10DDC000278821BE50E6ABD9C1FCF59A42836F3952 +:10DDD0003BEF1560BC107DB4E9E823C0E8A3B11D9A +:10DDE000E9A3A2A99DD14763754E64063B37033F63 +:10DDF000BF9604C602DE3BA2BE9A2651FA1F1A1530 +:10DE0000A801BA91BDE7A6E55D8A703D1D163F7C6D +:10DE10007DCABE7AC36F6D4BCA4369E04FEE33E0F3 +:10DE200079970237A55F8C85E5C5B658DD5F03FCA1 +:10DE30002A27B4ED85ED6F6D791FF3366CFB6ED834 +:10DE400005EFDB66530C3942F3D6EE5B8EF767D7EE +:10DE500006D87DD8D124E005BDDE3B3C18FF04E1A7 +:10DE600001764F1AC0A31DF96513FF5E2CAB5170EC +:10DE7000819E1F1AC5EE0D89B4B0F3EB211611D7A0 +:10DE800039C4C2CE59E2F7BD2582BF9575BF01FBEB +:10DE9000C74399A6DEFFFDBCBFA489AF2BF854E8A9 +:10DEA000894AD228B87FE44C8C3BD1A2A19FD8A844 +:10DEB00014D578CA7B8F7888F30EAA47AFD83DFF78 +:10DEC0002ED0AB947EBE00FC04FB8D9623006E4AE0 +:10DED0007FA0CF70F8A1EF0D87F9601EB017B6ECE8 +:10DEE0005E22E23D1A7DC46B26DC1B49FB6746912E +:10DEF000AAADF4FDCC685A423D8ED713797D202B14 +:10DF0000533F711A04FA7C3D8FBB4EB6F0FC31C909 +:10DF10003EEA86D15067765C565224EA05856FE169 +:10DF20000E0838B796F8F9754A20C5007853F858A6 +:10DF30000A18FC56AAB452248701F218DEF1D07DEB +:10DF40004BBDCB9DAB2F65DF71EA9FCFE4EBF9C1F1 +:10DF5000F6F5173DBEEF9E09F02D37B73D7203ADC4 +:10DF6000575C7A0ECF079747555C79A17B2FF4EB6E +:10DF70007FE7FCDB5140874DDF98C27E0F55C3E140 +:10DF8000D6E229C0F732F9BD2E2451C93356E5B186 +:10DF9000421BB7CB109529F81CEDACFF401108F8D7 +:10DFA000F44AB1F07E54329E1F4ED1E5ADFE879FFC +:10DFB000C5F932C130002571C92836CF37CC4E3271 +:10DFC000D3FFE09C691A3F177B4772AFB0D2F1DEF6 +:10DFD00021EC7C3533AEAA19EAC4C4C6CF26DAFBDD +:10DFE0000A32136BA7C6C2B8D1C918DFCA35EBDA3B +:10DFF00053BD12C869929A8C7989D388CA3E637AD4 +:10E0000003EDEE08BA2E90E3D78C2C744EE5EDE7C5 +:10E01000E8FF434DE4F6992A7FE32AC75CE7548D75 +:10E02000FD528BF701FDE99FE2EDE1F22C3EE3FCAE +:10E03000DFE2C977C2F9B31E9E390EE17EABA3279A +:10E04000DCF570D4C35D81AB1E8ED99F38A7C68620 +:10E0500081931E2ED348ED48D0630ADCF57079C752 +:10E06000CCE8E29D3413DEABF88EC4E0F80E352325 +:10E07000A11EA49B6811EF01CE8CE2F53747B0BA20 +:10E0800082EFA864C4B71EAE7A3866C6F1F7E358CB +:10E09000FFBD002F09E502E247A19BCCD4AADD31E8 +:10E0A0002A7A50ECEB691C2ED4BE46FB3937DE8A47 +:10E0B0007126B0AFA72584E0965BCED6953BDCF207 +:10E0C0003CF8A9F475BCBF720AE13FFF143C2FCAAB +:10E0D000E45505CE53BED1DAC9D39AA69F8238C380 +:10E0E0005093FB7EA0CF801083E77514EE477470C9 +:10E0F000D7BE67D7D6F570F803FC31B127BC143A08 +:10E10000FBC0C2E34E03C820B097C7BC96110DF206 +:10E110009B34C5868D4B5C71383F380EA757A4637E +:10E1200081B883CFEDA93F428EEDA35A5225C73661 +:10E130008BEED396F89E724CC1D3648E87C9C4BB54 +:10E140000BE24B9389F445D01F480EEDBF5BD9E736 +:10E15000403210F67983C5C1E43FDF6770DFD4BC7D +:10E1600084F9B3F8FC59660B7E5F4302524710CE28 +:10E170002978DF91D7181B5A8792BF4F86541166B2 +:10E18000CFCDC37BAE295CC87751A17598AC828492 +:10E19000F7FDF0759CA9337B218FAD5B7447819DA2 +:10E1A000D721EC1B83FB93FC2340FFE9DBCF35EE4B +:10E1B000AE8076DAAF08FBF1F52F1659FC21B0C31B +:10E1C000E47B3EB9773B95B235EA09857EB3E0FB47 +:10E1D000D4CB81DEFD0361DD5340D5D172E759F622 +:10E1E0001D437663BA04F3ECE96679FF39C42581EF +:10E1F0007DABA7DFEF4BA7A178456008F8298A5DC2 +:10E2000036D5EA1E69A5CF57F3EF669BCE8E18056B +:10E2100078F9C1F474404B4F0A1D51BA1A0FF0EC53 +:10E22000CAF8FC6930C7DFCD3897007A51B1DF43B7 +:10E23000768A6B02ACA7373B7E89D53DC57A013B18 +:10E240005EB1672EE68790DDD441A674741BC7CB00 +:10E250003C73ABCCEECD0F60FEFDEA48E55E3B477C +:10E2600024D891B7AD4ED95407E786D52CFE7E6BE6 +:10E2700095ACF183DD90DD86EFB3FB666F5FA66D35 +:10E28000FF4C60FE7EA157FB9C581234F7EDF69CC4 +:10E29000D7E035C0BCC323313F413FAF7E7FFA7921 +:10E2A000F5F3ADE67ED56A63ED48A7CA2E596065E1 +:10E2B000F650F7AAC7EBE0CABADEE0E7360F48939C +:10E2C00054F7ABB5AD8E2C08776F8C329E02EF7988 +:10E2D000C4CFE20055F2DFC3DD839BE566F181DE4A +:10E2E000E61D16988A76A0E149BF08F6FCB0004109 +:10E2F000FB3B2BE0322CD0F801CC4FEEE107C0BD48 +:10E3000026B45ED6B08BF901F5D5E84F94517F0263 +:10E31000F4CC7A389B1EC0179486FE41D0DF85FC72 +:10E32000A92CB8CF92FBC312A597D45AD67FA3F5D8 +:10E330005DE36A09FC5577924C2963E3C3EFD798F4 +:10E34000A95F55934C2208F5AB5E78F8FDE96BC0E8 +:10E350005F8E7509707F28ADD758FAF7DDBFDEF8FC +:10E36000F0FE1AB86F94FA65EBAC2A7FB737FE78E7 +:10E37000048C910BF047BA3D7F23F0A112AF688A5D +:10E38000E07C1F11A4BB6880974227572F9B8F7E8C +:10E3900045C425E787409E5816C7FF162B8FC346F6 +:10E3A000B1F79F12DD5B90BFDF3A3F02E2CBEF8C0B +:10E3B0003C8AFE5C9395C5E7F7794AD07E52F0B966 +:10E3C000CB2A703FC93F10F8EDDAF1CD71E09764C8 +:10E3D000C902DE43DA24FB9E4CCF007934DBBE82D7 +:10E3E0006E296BA211BF136B8AF00FBC5B65A7355A +:10E3F000F1FB4C9BCEEE1DA8CE631E66CDDD6545C0 +:10E40000FAF38B307E56C6EEC3A0EF7BD32F21FDEF +:10E41000E112407F90F3FB13F0FCA8618F0DE24204 +:10E420001DFC7E82330DCD09F36959BEE52F36F010 +:10E43000D7DEE7703823B5E23D4A65DB44BCFF8395 +:10E44000CE9B700BC4A71B1664B2EFF7D877678A10 +:10E45000FE4CFF67F3C07C1634C4EFC8147B72B265 +:10E46000D9EB83F535558B182F9EACBB376C0ABFA3 +:10E47000374C6F5F9EB42A71E904CC875A6A67F300 +:10E48000F4C64F59DFC4129F8ADFB224BF08EBCF16 +:10E49000FA2681C01597675A529EC8033F9EC8CE80 +:10E4A000E130AC4476A3FDCACF9FE86F37DC43BEB2 +:10E4B0009357DE6C3837EB4A2466FBFD970960778B +:10E4C000B9FBB1E022D3078A7D37E51B6D7C556F20 +:10E4D000E7E6348DBD7F204178B37FA722C0EE559B +:10E4E000EB61FF06A687B57B09790CE190BE2DF59F +:10E4F0001AB84729FD8F063BCCDB027C110FF83C94 +:10E5000087F7FC5410FF8DD05ED120DAFDB07E92EB +:10E510007119F09562372870693CDF6C1E43D79102 +:10E5200075D6605F4E877833F005FACFE3FEBC2FD7 +:10E530000EF4575340C27382ACB3BBA316A8E46079 +:10E54000D379033E7FF3FC5BDAE781D8CBE0BD2DC6 +:10E5500006E617EFDEFBF728904B6F9EEFC6F182C1 +:10E5600076434FBB18E1916B15837167B55D4CC461 +:10E57000AC0390B7352D9AAA31A177BB37FB137244 +:10E58000BF95F4B41F72C01E11C3D8111CCE743EC7 +:10E5900009F8486F575C6EE3F1E6C1241DEEA36CE9 +:10E5A0003C1FB718BF1F6E8AB22F477DCCECA5AEBB +:10E5B000DDA71FBF069EEF13D9FD11E745E4A7B7FE +:10E5C000762E1EDAA6E25B2A39114F5FF53FDBF9A2 +:10E5D00006EDFFD59E481647979C97A9BF7708F58B +:10E5E000F77178F907B0F338EF00B8D7E907DB2FF8 +:10E5F0001D3DFCFA3C1BDAC381E9A01E46AC6B371B +:10E6000002FE5BACF9D7D990DFEAA3002E5E92330D +:10E61000904C80F37A92037415A82676F027B6B54D +:10E62000180C80978C8DC998A7B3899F572EAAAFD5 +:10E630003526ABE862113FEF3A297B87C4AA9E1FBB +:10E64000B031F972724FE96F304FE34313191EC6B0 +:10E65000DE6CB0317DFB8AD17BCD66E877C480DF8C +:10E660000DEDDEFBFA5EB8CF78D161C75888FF3D6B +:10E67000627360BFC67D9B6A20CFB7F113D052543E +:10E68000AF6C28140D74DE378883C5EF0E18D01FC9 +:10E690000FC63D892B0EF6F9105FCF1B2D06CDF965 +:10E6A000D81BFCDEDD7B6D32B62FB18988C7AD2D5E +:10E6B0003971A0375AACEEBB6DA02F8EB5D5C01204 +:10E6C00094789F62AF4D3CB0F59AD1F4CF891D0686 +:10E6D0003BA0DB71E07911F6EB3849488C407AD8E1 +:10E6E0006F743C8F7ABC373AD878741D6F01BF2A9B +:10E6F000F0A79AFFA1345A7FA3558A85FC2E05FE08 +:10E70000CA3E94F91DF5C4B5DE82ACE4DA7A81B86C +:10E71000B3925F3ACE4E947F2F01E9D268733D6A7F +:10E7200063F60EDAD727F730BBE815AE474952E15A +:10E7300050809F82A77A1B8B332AEBE96DFEDFDBCB +:10E74000989E54CAEF4BD79B648717E9661BCB0F83 +:10E750007778FDE654C8236B4CC57FCF499567FB9E +:10E760007BA4E793DA7B051BDB0C06F80EAC628713 +:10E770001083E66D1FEDEB209D49F5487F8D8709DD +:10E78000F27169DD9D2CEE48E50DBF7F0DCFD18183 +:10E790007FF8797A7F8196139BD6AF1888F0F5DBE6 +:10E7A00080AF4270A27C036555AD11E875D1525619 +:10E7B00016F373E9456BDDC89F45EB587EE11E5BA0 +:10E7C00032AEE70CA75762881C00F9272E0E7F6532 +:10E7D000DD799C6E4F353CD10CF352FAFA13E0739D +:10E7E00052E3634FC372157A3DB541C6714A22B5F3 +:10E7F000E7F6AD7CBC6D0718BD4FDC20E7C0FD5FC0 +:10E8000013BDC40E71EC37366C14417EBF01F49C0D +:10E81000CCF81CF4EDC93D0F46FD02F45CBB814011 +:10E82000BCFC152329D9A2E28BDDEB5FD5F06F6923 +:10E830005DF53518976F8B1540CE2B7CABC0FD1561 +:10E84000A3F32AE4FFEB74FC3F95BD2F473BB0DFF9 +:10E85000139CFF9F9841F99F3E8AD91023C038AF7F +:10E8600018C3DF07F7F50FA4BFA05C6DEB2157BFFE +:10E870006672B5CD964AE7AFB8B61BE30CC1F57129 +:10E88000BA7962AA4237C902C0BF96627018C08BBB +:10E89000C215E899DACDB7DF90865CD922E1390F4D +:10E8A0003F47E2F91FCA77020ABF86E499C2B76EF2 +:10E8B0007334D8D553AB56805D1F97E745FA3C2596 +:10E8C000B887C6527D760AF8388C3C38C1E5C75700 +:10E8D000B2FB62F7EE0F007A2EA11E22EC87AC137A +:10E8E000EC8017A5DDB18EDDC33A3C5AD09CBF2B1E +:10E8F000F51F0CEF408FFB418747637C3A60843CF7 +:10E90000D5113EA6C7889083FC400C570F003E5B94 +:10E9100044F5D7CD2AFD754AAE453A55E0707934B5 +:10E92000935F5FC5B07DFF95D38515E285AA732FF0 +:10E93000EA904802E36751607C2EC2F8A7F64CBA11 +:10E940000AE9FDDAF0F46E07FF2A16FE3DA7F54846 +:10E950009F3133ECF81DCB1392332246631FF9B07D +:10E96000DCBDF157E8D701FD02BFF746FF2540FFA8 +:10E97000240CDDFB28DDABF0A7D001A58B6BA255E5 +:10E98000F2414F17CA79A302975774E7954F47335F +:10E9900079B080978E5EF26694FDFC603C9FEC81BE +:10E9A000E7F90CCF21BE027C2BF2E16717E1AF3D06 +:10E9B000D1766CAFF97401E6A9D4F273AB7A3E9FBD +:10E9C000B2EEA5D182E67C4B7FEE34CAE2BE2B5A72 +:10E9D000773EEA480BD1C7346ECF2ED968C273FF99 +:10E9E0002DD00278DBCDFEBD6CE53DBB440D4F0A5A +:10E9F000EA15D14C8E2BF4E1586624C3A8FFF255DA +:10EA000072E16EC8FFF959AB376F34DDC716A377D3 +:10EA1000F6B5E80738AF82F1AFCA33D8211F24C654 +:10EA2000651720DE81240A7CB88FCD332ED5791965 +:10EA3000FAC90EE73890070F737C29F855E0D09B90 +:10EA40009EEB0DAF7B387CE279BB5E8E1473FE9E2D +:10EA5000C2FB5D5C8E7845E0271B712F1761FD5965 +:10EA60004CFE05E54816C173C9977572E4E59F5ED3 +:10EA70008EBCAC912313DAC2CA11FA0BCBFFF11B87 +:10EA800016A21D4B0E87B7637746333D1C0FFA93D2 +:10EA9000F68BF7B2F3DE8739DD528AC4BCC9DA0DD2 +:10EAA00026CC1357E4906D36C9817FAFD906FA168C +:10EAB0007ACD761F9E0CE7C54946079C5F9F92035F +:10EAC00088F753D401AF45FAC8C7FBC7C3C82302B0 +:10EAD000F112EF4783D0EF9C2636219F2C994650A8 +:10EAE0007FEEDE7805D255495E8A00745B5A1723A3 +:10EAF000407BEC54BB01E494B28F2B9619C8B071E3 +:10EB0000C80707D472E40A6F15FEBBCD43E3DC49A6 +:10EB1000720C21471F3DFB3375BCA88DD6D5F12261 +:10EB20005A7FE0FBC48B8E46071E8078D13F6CAEC7 +:10EB30007698779425FF28EAB7C42A91A8E4D6C529 +:10EB4000ECB71F4A2F953C2E455AA9344ED0C481AC +:10EB50006FAB73601CF82B584FC580E34FC37078C0 +:10EB6000AF46587B9BADA31F970BE41382F8E89741 +:10EB70005F2542FC45913B067BACE22F0B9097A1B1 +:10EB8000F0DB7F031C7DB5D7008000000000000093 +:10EB90001F8B08000000000000FFCD7D097894D590 +:10EBA000D5F07DE79D2DCB2493C9427626ECBB039F +:10EBB00009ABB14E086090040710448D380990B03D +:10EBC000640391D2D6968120068A182BB554B10ED3 +:10EBD00014FA51451BB61ADBA013401A143456AD73 +:10EBE000D8AFA561911D8980FDD38AE53BE7DC7B29 +:10EBF00033F34E26026A9FE70F0FCFCD5DDE7BCF4A +:10EC00003DFB3D77492D63793B22199B90B350ED35 +:10EC100006A9C9CC3C161B831F2F6343793E7A0893 +:10EC2000E659986B20636BF27579DE018C5DC79FA6 +:10EC30003BFD69A2153E8E676CFED630EB4933B5BD +:10EC400067D7E17F795D8C265F599F643DD9C79F67 +:10EC50009F8FBF24C1FF334CCF12182B63E2A7E173 +:10EC6000CBDFFF7018B4C7DF55C6DE54DD89568090 +:10EC7000A7DCDC12D5DDCED833F9C713DC91D45232 +:10EC800087DF3D22C67871B9E3BDDE718C79DE5530 +:10EC9000D916C80F36193D4A34FCE264766B82E817 +:10ECA0000F7E9406C5671904F97F43552C6397FEC0 +:10ECB000ADA3F4C59FB8F232E0FB8A7A9D6339B404 +:10ECC000AB685018CB62CCD19579CD198CD58547DE +:10ECD0000D62D05FCEBE48A701CA2F2966AF298337 +:10ECE000D100088741C23FA2357D1BD4573798D841 +:10ECF0006AC85ECA61AC19E1D53BA2D9003F7E0764 +:10ED00001D7EA60FCC00CA6B1D2E0B639BC278FF25 +:10ED10009BC2647B7B3483B4DB92D1EC04C0A7D765 +:10ED200033160DF481C48369F6926E03F499301F93 +:10ED30003DF318804ED9AD3E15F1D2ADD5AE6391FD +:10ED4000FE71F4AD8CE6DB4D6FD73960FC3A81F78C +:10ED50009D4D3B543DE073D898DA6A15D2D228F71E +:10ED600058C4F3A8ECAA6A2C8FCDF7A86E689FA5AB +:10ED700054EDB3005ED878E6D802E5CC07838F84E3 +:10ED8000FA16D61805D998232DCE28281F75C6D96E +:10ED90003800E61DED620AF6C7D8321ABF5FA4CB71 +:10EDA00085FDB238A75200FD0CFB0723BCC87E7658 +:10EDB000368D56EC006F5CF318C51EC05F304DE217 +:10EDC000ABF5CCFE53ECD77348E740BADAEB987357 +:10EDD00023B4EFFA72BF312CCADFBED2AAD078B703 +:10EDE000BBDDB94646F379D80ADF8F9CEEDD6700BC +:10EDF0007886CFF1EC33DA03E63397517F292D1E65 +:10EE00009A47D211770EA68B2D31D4CFA833BEC628 +:10EE100001D0AE4B15CC07CAD39A3F5410AF6955F9 +:10EE2000CD0AD27167D35E8237B5793F4F8111EA3F +:10EE300020DD01725517308FC5161DCD63B145A178 +:10EE400074E5C599892EA87FC4EA5E6C19EA9FC74C +:10EE5000CA1C776215F4BFBEA95BFB7C7B02BCB702 +:10EE6000C1678827D9DF72AB91FA69B2B87F84F3A2 +:10EE7000AB9CDE7200796F47D39FA3482E1AE288BD +:10EE8000BE09878E133D129600CEA078FDA1850A9B +:10EE900083AAF5854033A5239E27B8DD8E31998856 +:10EEA0006F809FF8C71A3109F8F2628CBB06C791D0 +:10EEB000ED2714D922505FB4E7C577CF2E658E5960 +:10EEC0003D00CFFB8B77B26E4877F712A47B7BBBFC +:10EED000818F87213F318BB316FBBBA4B0E938CEBD +:10EEE0004B9842F94B069E97F8FAAB95E3EB11EB82 +:10EEF000A4C596788E272BF0F14B61BC5DB01E7ACD +:10EF0000D7CABFB30B7E61CD9C5F701EA8BF64BB28 +:10EF1000DDA2DFDB9DEE5C3DE793CD08E7C811DEA7 +:10EF20007DC8B7C3F33CFB90FFD398E0933CCE275A +:10EF3000C1FCBECF6AA37E469D696588F72C85B962 +:10EF400002E92ED3D710AEA1C8DFA3897F401EB639 +:10EF5000E378C352AA54038012C7AC135877C6DEB5 +:10EF6000B6DAA95DE608E73EE437ABD345F27C208C +:10EF7000C24AE52B33387FC0F77F40FC05CBD32E48 +:10EF800094A3017E398A437E8CECC88FBF13F0BCFA +:10EF90002DE4A563FFEE3F61FF71CD3AA7029D0C02 +:10EFA0003F12E965D074F8A22A15E18F63C0FF0013 +:10EFB000A06D8E3507E52CA5CCA1205D9B225C873A +:10EFC000ADD40F23BDB93247E7AD86EFE6463B89A6 +:10EFD0007EDFD83EEC676636CC6F1FC01EFC15E1A5 +:10EFE000037BB0B608F5F46FFF69443D6A97F2D72A +:10EFF0003424A238803FAE48BDE0A7F771D20B4160 +:10F00000F40ED673C1F4F6EB05AD9E037C5DE0F41F +:10F010007067229FC5352F52B97ED0EAB5CEE8D1B0 +:10F02000413F083A5C8A707E81F85C0C3288E37A52 +:10F0300046B33E58DE991D0E8B89A476FF453B1CD6 +:10F040001613DFD10EEBCCAD0715C04779836A5795 +:10F05000610AD58FD99C48FF17EB148709E5A441B5 +:10F06000257E78716538D94B09EF67BBA307B1DB03 +:10F070002015F2CFDCDDC98E56C688F1ED9087F100 +:10F080002F5979D6687527C504E893171BBE084326 +:10F090003CF74F64034EC6620BA7D60E830829F0D7 +:10F0A000BD097F5310AF836B5414AC69EE9D269558 +:10F0B000E8D61DFB1BCE5AFE9C0D70BDBC6DB4CEB8 +:10F0C0001DC837F55767EC05F82B23B85DBEB4F7BC +:10F0D0005A2FE433597FF79262D27B3F072B1913E3 +:10F0E000A01FDFEE7382EB6156683DD51F87762A3D +:10F0F000D723008551E63E7AF427D47087AAF527F6 +:10F100008839AA7B027E107F8DE184BFEA9E20773A +:10F110001904E748EC7FBFC5C892A0FC0AC823B613 +:10F1200093707F03784707E2D10F6FAAF55484E00C +:10F130000BD50F5F3B5D900ED0BF6AD1D33C2EB193 +:10F140007007D2B3CEE864487FCF51E11F08BA55AB +:10F15000089EBBD430F4881BE6F7E29154077E7F0B +:10F16000A9FE4A982E12FD46F7149C979AD61A8546 +:10F17000F6705FC395BE2D0348BF4DC5F22B874E79 +:10F18000D8DC03BED1FC6684A687767E95FAC89A41 +:10F1900040FF50617C7EC17CA43434FE4B1944F2A4 +:10F1A000C7501F7AD299B71AE6BD72A0E0A77B9923 +:10F1B0001DE53E98DE46ABAB2226406EFF15EDAA5C +:10F1C00042B8709C942134CF85981F747866A6410C +:10F1D00087F31BC3D06E4A7F0FFDEFB0217EFF4E39 +:10F1E000CEAF7DFE3DAF0D3AC468BE3FC67100F89C +:10F1F000E53A80AF128CC1EA8CC079FB881EE562CB +:10F200007EE5E6489F0AF361BB0C175AA41EE8D6B8 +:10F21000117EA04F0DC2E719ED38E246FAFE35D255 +:10F22000518DF8D1375BD15F85F9ACC67A36A2280B +:10F2300011E7DF2FD2B905F5FC4BCB18F1F3A55739 +:10F240009877134C76FB7E1DF1CB46D68FF8BE9F88 +:10F25000EEF20C5724C9F33A843BABB956877AB720 +:10F26000A7D7AE437DDAB7B94EA7233E70FF2286FB +:10F27000FCE49957F4005FFF6D55EA37E4076F68C7 +:10F280007EEF40AFCD81F49278CB167C908D7843A1 +:10F2900083D0AABFD062F6E30DE8C3526C1DFB63B6 +:10F2A000AC251DF1D4F8FAE95E2DD05FC51BA76728 +:10F2B000205E2AFE60222618F387BED1C8EF9FE5A4 +:10F2C00084F6672E2CAD72E8C19F7A25A61BD985DE +:10F2D00032D66C443FA1BC6E81431FA0CFA5FF7600 +:10F2E000C8D09C8FFD1F1AAAB26580E72B8EE15D06 +:10F2F00058083BD1EE2FA1BF06B02F47D811CFAF92 +:10F30000674573FFD146F620B8FDA1A5731C637A4B +:10F3100074DEDFA1C161D3BDF07D7E901F743486A1 +:10F32000DBB5B6186E8741213B11CE8BBFB7783D58 +:10F33000507471C847510CFDCC5D1F647A808F2ECC +:10F34000B2E647FE8872763592D671F9833FCA5C81 +:10F3500066F1CBE51D23F8DCEF78ED70941DDAE75C +:10F360006FDF17E709C0DF1D4C7FB59DAF33705CC1 +:10F3700046E3337D4B2FA407FBE3D9043BA4F9AF4D +:10F38000BF15C7F9204187745E24F4DBEFB028C0B5 +:10F39000DFCE5F52417C24F3E56D66E68D0DC8EB50 +:10F3A0009B8DB8042E6F8B645E68B737C612477AA0 +:10F3B000269925A39EE9145F3789CFE07289CF4350 +:10F3C00083CFA6A35FF15927FE706F1B6FD7CEF7CF +:10F3D0004BC14FD7FBF3EF7CA53EEC0AF15D848D6A +:10F3E000D3E98A636417F4F7F28DBE1ED610EDE4FC +:10F3F000FA32184F6F5F2B8DC07E7FDF66CA0B0518 +:10F4000097DEA6FB767ECA21802AC01FDCA6BA53EF +:10F410006DC21F9C0CF98ABE57C6D1BA5AF28BD066 +:10F420007B77304F23CA6F307F487AF7B001DDFA1F +:10F43000A372662948B78B3176CE37421EA47C046E +:10F44000E331389D6064EE50EB80AF62245EC39878 +:10F4500007F4E1231B0D64DF0F5FFBF8DE4CE0F7E0 +:10F46000D31B0CD6E530E49C17F6A53E03F57306D6 +:10F470009BAC0AE44FDB7D3D50EE4B5F505DC80F07 +:10F48000A7373C923013D2F320BF650047E946030B +:10F4900095CFD9F828959F15725DFA427C7FD49755 +:10F4A00087F7AF4E403ACEF9EA89694897ED466B47 +:10F4B000FFC190966D531C6302F03D6F739826BF99 +:10F4C0005DC7E6E03C245D99E26EAF47133FD5A6E9 +:10F4D000FB76711F9FD6DF04FF72AAA0E3C4293018 +:10F4E000EF8AA157C8AFDF77209CECC99B912AF91E +:10F4F0008FBEC1FFEF9DDB209FFB95DE41BE9DA02F +:10F50000F3584167B05CA4B74BCC3C9FFBBA9EFC60 +:10F51000CF5C8B4AF886F69163A1FE7BA2BD0FF407 +:10F520002CCA2153B3D78D847663A30D0CEDD0F78D +:10F530007CF3F219D8C93BDBF4C75B02E6339AD5FA +:10F54000F6417F38871982CA9D7A2CCF356BCBC79D +:10F55000F6B8FB2CFA0F63ADDA72C9778FD8B4FA1C +:10F5600062DF81733F9B00F32B39A492FF7C237DE4 +:10F57000FC2EC2AF473ABF5DB80DBE3B2CB072F84F +:10F58000DAE91549C857231486F1ACD3D742CBE347 +:10F590001FA45E6640DF3E7EFA1638E6B6E751DC11 +:10F5A000EF19B1A03D8FF0DFBC1EFB7A3D759B8D3E +:10F5B000C73382ED46B0DCFCB7EC46FEE0B7D23D87 +:10F5C000164A7F83E985ED5CEF06EB89603B21E11C +:10F5D0000A86B7BC4DA7B10F5FA11E191A68278C08 +:10F5E0006427BEC3F570836D68C7F530F831842F8A +:10F5F000CF303DADC3C1DF6AC4760322EDB139001F +:10F60000D20A6BB708B27F16F77E5B401CAAFFB622 +:10F610005A1DEA8DF6F88C411BA791EBD577849D96 +:10F62000A813FA1CD6ABB4CEDF18EE4ED4E3B8C99B +:10F6300046C7968C8EF8F948B4EFCCCF957EACBE19 +:10F6400086FBB18F585D9A3819EB93A889FBA25FAE +:10F650008EF2EDD91B4EF3FC54710D4239D433E7D1 +:10F66000DF6D01F4A93670F883E1898FE576923178 +:10F6700017F907B27CF6E8D07A5C89D553FB9C6712 +:10F68000EF4F47FFEDD3C607D251BF7E1A14E7ED07 +:10F690004C1E9E16F2FAA4B02331222EF014CA1189 +:10F6A000E441DA9DDBE1FB554B5D24573F5D3A9D1C +:10F6B000D267962EA1FA13B60C1ADF9AF367577722 +:10F6C000C0D3C9352AD989D94657AF18F8EEA459FD +:10F6D00047F18513559179BB22B19CD17A72F6B36B +:10F6E00013B67802E27E276C7AA24367F38C8FFD13 +:10F6F00066FABD9CB544A1BD6AE7D7231DECB52DC4 +:10F7000016E37FAC2501DB552ACDBDB6291DC7B751 +:10F7100032677C2CF29791F547B9A90BE7F628B828 +:10F720005D4A2CE7C3BFA11F0BFD7E8A762B849E0A +:10F73000B10B3A2FB438EDB1A4EF22C95F27B881DD +:10F740005FBE8C727647B8605DD613D3615D787CFE +:10F750006EB1C52AF8C3A9F0758EAB5F6C88F85BF3 +:10F7600067F19E6038DE11780D8E03C954C681861C +:10F77000C6F2F9BC6DB36AE24218FF0E15FFF979C3 +:10F780002CD7A31BC35B3C2ACAC3037C3DDE25DB0D +:10F79000A3607C2B25BF3607E35F77C5F2B8A52DA4 +:10F7A000CF9D88EBF6E444A303E336372B8F03EABF +:10F7B0009C7C5FC0AD2338D6377BC27A015C09CD13 +:10F7C000EE1C23A45371310DF8EDC2AA9621DDA0E1 +:10F7D0001D21236B7FB857918B6C689229F42840C8 +:10F7E0001A8672678C724F45BA0C9B55558D71FA0B +:10F7F0009432BEFF70567177B5019F9C7D2B3CA45F +:10F800003F5C22E8CF94D1C968FAB3361B08AEAC8E +:10F81000CD3F9F817C9FB5F92EBD12A08796C71A58 +:10F8200068FE67DF9AD795E2169F9858CF107AEA5C +:10F8300087825F1E1074D8690CCD7F8B45BB6FAC7F +:10F84000CF5B405569F5F9E2D880385B45F965D260 +:10F85000E79363ED34CEF3FABA03C980CFE767319B +:10F8600087078AE66DDD48F1D79DC6BAF1B8EFE4A7 +:10F87000A9D031A4FBFE037F38908C7EE42CFB6082 +:10F88000F423DABF3FF4D24A2C7F7E0E1B8CF84F54 +:10F89000F23EAD603CE69F61B584AF7F6E31B165ED +:10F8A00018B77DBF6EFC0F21BFBE4CC750BF04CF41 +:10F8B0001B4632E81231F519742338FD510F4ABA4C +:10F8C000030319911E926E88BFED90EEDFF21AC10C +:10F8D0002FE19A2AE2DEF3B66E1F8F7C925C6653AC +:10F8E000304E20E1BA913D7931F6DBD993EFD00E5D +:10F8F000BF121B222E1DC20EEF880D618783ED2FD4 +:10F90000B3387763BB1BD9E1E182FF36C606ED7FD2 +:10F91000E07E5908BA0D8DED100FDF1F1B62FFE36B +:10F9200046F1F0DEB172FF431B0F7FC9C8F56FAD22 +:10F930008D3D3C2984BC7413E3EBD6B51AD17EC649 +:10F94000352821F5D9628B51EE1F7E1C1BB05F124A +:10F95000AC8F43E0F728B6EFBBCDB7175B0D89E955 +:10F960001181EE5BBFEBB0DE0D31CE29813FFB2272 +:10F9700046FBA6F62A46FA0AF25E1E14F42914374C +:10F98000B0384F93DDBAC1BED59DD61CF283E43E9C +:10F99000D554ABD64F8C8B93ED9C9F239C699DD8FF +:10F9A000897F093CC1FCDB70DCB8454CB31F23F7F1 +:10F9B00061E2AA3C8A310BCD11A3F86AD758F7321D +:10F9C00003B46B1DC91C9B201F5D68CD417D6A9BE4 +:10F9D000E368C4FD9A9517793C7EE502E65D4EFD2D +:10F9E000F0F93277372FCA17D22D302E1011C7E118 +:10F9F0008888E3720676D21CC7E10A8F0BB0939217 +:10FA00001EBA753E95E8DA1ADA4E05D0D546DF778C +:10FA100042D7EF502EED7137E71FF78CBB05BE19AB +:10FA20001877737CF3144C4BECDF048F9789F30F3A +:10FA30001E0FF82C2BEE26F8ECEA2DEE8F1E8850C8 +:10FA4000BE5DDCA5235E27C485D0776BF2757D484B +:10FA50005FB3704728BB3A232EF2BF7D5E6486A059 +:10FA6000F72D9D1779F1272D46A4B3DCF790F0060A +:10FA70009F1391E5150D4A26AE3F73F65DA375C041 +:10FA8000A5C67FD33AA0E3790F3EEE42E403806738 +:10FA9000AC3AA0CE07F277799B9156EA2AB3FF22BF +:10FAA0001BE3F64D06E6B5537B33B6EFC778FB7E16 +:10FAB000DB563663DCAA1FD37BC47A54B9CEFDA8CB +:10FAC0006894E37E4D2A5B8DF9ADBCBE8A9997613F +:10FAD0005C3A7A848ED903F019E30C67F6007CC691 +:10FAE000E6D93479B94E9E2FC68D77256BBEEF329D +:10FAF000BD9BA67D92BB9FA63E65CE104D3EAD6AD6 +:10FB000094A67D57B0CF81F90CCFDD9AF6DD6B2638 +:10FB10006BF23D6B1FD0B43FCDAA9ECDC6797A9CC7 +:10FB2000CD3D00CE5902CEDEEB8B35DFF5D7D50DBE +:10FB3000F3A120F9141FEEFFCD166C324BC473FAFB +:10FB40007AE769FA3DFF6A5E9302F89D5D6B3819AA +:10FB5000189F217C007E4BEA15F61C8C5BBA5E5B1D +:10FB60003FA7E1E9952990CEF56ACBE7E1BE9C82FB +:10FB7000FCAD2DDFAD733D82EB9DED7122CE28E211 +:10FB80003DAC037F44D2B89737F07897EAE91DC4BB +:10FB90001F5A3AB16FC92F76C12FA6442DBF84D901 +:10FBA000B5FC527A70E7301FEB88FF883E417CE459 +:10FBB000817F017897F895F8B738B47CF55DE19DC1 +:10FBC00031AF91DB0D6DF93FE2B4F1B57E91EEE31B +:10FBD000A8B7AED42F5271BF8DE5F17DFB2BF55741 +:10FBE000071DB26BF6D73ADB4F3A1717185717FBBA +:10FBF0004997703FF1367613FB89FBFE85F800D9F3 +:10FC0000771B801FD80887B97DFF30CCBF7F14AC2D +:10FC100037650A76E3CB38B227FE7DD76AF87A5883 +:10FC2000F45F5C08AFDC8793E772E4F92116C9E75B +:10FC300029FB013CA8F143F1FC9F2D02D7ADDBF776 +:10FC40002FA4F5963C3FC4C4B9BF107E3FE9EF3AFC +:10FC5000FC3589FC81F0786ECF23316DF707C4F94C +:10FC60002E69CF3BEB47EEB775962A7B55DA3F6C92 +:10FC700055C21D9B42D8935EF1DF72FD75A6431CF1 +:10FC8000BA577CE0FAEBD12B07D0AE00DEFB62B9AD +:10FC9000C502F65AF1DBEB5F444411BFB61E54BDFA +:10FCA000BDA1E0B2D91E6D033C368469ED884CAB32 +:10FCB000CCC903F4B158AF3DE727F71183DB676385 +:10FCC000FB80FD27F84EE38FAC1CC2FDB5EC786ECF +:10FCD000DFBF88E4FEC11491AF0C5A1755D670BF30 +:10FCE0006C23F8E90D01FD4C89B750FBA511395380 +:10FCF000E2298EC0D7BB2B3314F227562A0AF921EA +:10FD000067A24753FDB5B89CC9C43F629C29E8BBB4 +:10FD1000C1FFDA6E1C1EBB388F23FB37C7F3F6E634 +:10FD2000F8D1944E89B78AB8B3B51FF2476584936A +:10FD3000FA35AAA1F7A5A6C7F379ADB530E9276AC8 +:10FD4000E2FEE384DEC438BF89FBA3F96313FC71D0 +:10FD50007EA6667F688C13F17D853E77A29EBA539E +:10FD6000D0BDB378BFB38F753F6E27758CF7FB128C +:10FD700043C6FB1DE328DE0F5FEA715EC1717FA4FD +:10FD80004384CD2F3F8FC4B7DB8354D44FF54677E0 +:10FD900035AEBB5A7783FF0EC57DBC2DB41F30F046 +:10FDA000507707AEAF5666B0BD16E4B7658CA17F3D +:10FDB0005FDFA25B1E06F56B3CCC8AF52337F0753E +:10FDC0005BE97ABB03A7698075B065885F1FAC8B60 +:10FDD0008F21BCD7B74C6EC4FD8135F7321B9AA179 +:10FDE0005A569B1B85FED0061672DDF89490B30917 +:10FDF000397B55D417F1E8DF87A0D353824EA00F8B +:10FE0000D6229D87B7BAAFF0FD38AE4F4825E2FA4B +:10FE100074BFCE1B6A3D3F373A771DF2C1406FE891 +:10FE2000F5C35A0BE7B77511AEE7A8DD2E7EEEB528 +:10FE300054EADF593AA607BA4F11749DB2819FDF89 +:10FE400060D7AE5F57A59FC8A87F867AA5F45E8B62 +:10FE500017E343A50D191E82CBA5387AA2BE687898 +:10FE6000DF85F9D2AC2C2BC6239C7F65CAA93EE462 +:10FE70006232AEBFF4EC94D42764C7E368DF69B2A2 +:10FE8000E0B7B5163B3F470D288E00FC976E58B67D +:10FE900017CFEF7CF46B46FB4B47D4D661D8D954CF +:10FEA00040CE922198EA5921C52BF8FED5BDA21F5C +:10FEB000CFBF615CB37FDCA90D07693E470CCC6303 +:10FEC000063EBAB4E73E3BFADB2BE3CD14C793FB07 +:10FED000B24755F7E36484F4AD1508DAFD0D115609 +:10FEE0008C7FFC43F05D46827B1FD2C7BD7C7C05C6 +:10FEF000DAC19665A674C4A37B79921A0770BAD743 +:10FF00002A34EFD1CB938C787E61E68AC1E3504FDF +:10FF10000D61CE9518DF7928968594D3F3F17C9DF9 +:10FF2000585C6560C6689A8411E32F176B148ABF0A +:10FF3000E0FE5B01D0678E985FF9AAF7A3883FECDB +:10FF4000F06F181ECBE53F73AA4A491EC1CE6BE481 +:10FF5000A78CD51993A09F796B6039DB8DECFDF1EF +:10FF60000EFE43C079EFF23A6D7D255BF3399D7F3C +:10FF700061E0EF5BD02E68EB3F95F2E8600EA4AB3A +:10FF80007BB1C58CE784460BBC14AD51ACA85F6651 +:10FF9000AE688CBF0FF2339B5407F2B4C40BEBE88E +:10FFA000EFD3398FCB4D3D693D70D96EEF82EDDCDB +:10FFB000515CFF2B7AF7702C7F28D63D1CD7F1AD12 +:10FFC0009F58189E9B39D606FE18C61ECD6C10C5CC +:10FFD0001FAC6CD0A4003B5A64B02660BCDFC316D3 +:10FFE0002632BEB7650E9C77A5790DF98195E80795 +:10FFF000F2F9911FF8502C67D5D6D7153A9FC3EA6E +:020000021000EC +:100000000DE4079A851F78D65E9B00AE17733D6E90 +:1000100020392DDE16437E68F18A5C23F26FF1AE43 +:1000200018D243E0077ED863989F8EC756641E4857 +:10003000847E8BEB321CAA967E5AFFB8E698A45BAE +:1000400047BF4F4BB793A1E806F4D294A72408FF0B +:100050004ED08B3D164B7E47E182B77A9A019ECBFC +:10006000556174EEA833FF83A5C6D1BE9E5C17E62A +:1000700025B7AFDF68DFFCCA9AA144B7607AE5FD17 +:1000800067E670B427ECAF16867AECA1EEECE1C916 +:1000900050FEB0C2E5EBA1EAF17928A759095C6FDF +:1000A000BEB714666864ECFDA566E6ECC5D8074BE0 +:1000B000AD94FF686922E53F5E6AA7F493A57D28A9 +:1000C0003D29E26852CE8001885F472570F91A9574 +:1000D00020E2DE6C5122AA8CBCFF7C305467C5A1A3 +:1000E000D2278C4D63EC1E272023C0DF997E6F043E +:1000F00012B93DDF62B08E4B44FF719542FABED813 +:1001000075BBA63DF825463CFFCDFA64FACBE99CC9 +:1001100098DD3819F8F0FEFC584DFB6935299AFC3A +:10012000E4043BCD7B525E774DF90385FD35F9A2A2 +:100130003640029E2F30DBF8FEAAD8B767CCC6D770 +:10014000EB56DEF66AD5F02EDF0778AF1E32507D13 +:10015000303D245D67ADD731378036733DCC0DFA25 +:100160003D593B93E4EAFC110BD9FD95DB32DF1DD1 +:1001700001F963DB0CB4BF7E6C45EC5ADC3F3EB644 +:100180002D3E8A41EA5EA9321FFAC17AAB9105E899 +:10019000B7DC15CBE8FC5691D7E440F92FDAEFF93C +:1001A00095CCDBD11F4420513E3E54BD3E85E8E74F +:1001B00024FCBE14E6DD02F933A0AFF1C8F8CC167A +:1001C0000ED71985ADC0FCD9B0BFF5FA3EC071B1EC +:1001D000A0B64487EB01F5503CE9CB1D2A43BE2D68 +:1001E0005C60A0FDBBB91FA91B31CF9421299CDE07 +:1001F0002A9D47642F99A87FD60A1C02ED16FDD6CA +:10020000B489D6774CE4770FF4AE16FC897C74265B +:10021000863963085885E03DF77EFC46ACF7E3D3AA +:100220003B08E7FDA5DEB53201F8EB5C897710E904 +:10023000B5C7E249AE82F17ED2C8F59607E540F136 +:10024000EB4BBF9C2D273E9D69702438485F652588 +:10025000A1BE3AB9C640E79899DE193589D63F3B29 +:10026000888FE53827F5F67108DFC99A0C86FB966A +:10027000C56B54F20790FF787B2FE7FFA755371B1C +:100280000EFDD6286ED6A523DF3CB260389D639A5A +:1002900021D641C17AE0339055772F7F7EDE1E7ED6 +:1002A000CE8665B5E8EF1D18388F157CBC44DEBFDF +:1002B0003C0750D6ED4F47D1E5BEDCD43D1AEDF0FA +:1002C000D90F55E2B3B3DD6A8725023D2FE8F60E5C +:1002D000FB3EE4CF17784EE921FF54B87B6702AEAE +:1002E00057746BD2956E783EF6C4DADBE1BB73AF20 +:1002F000181C24E64BE2497FCC7B696ED7C0F38E95 +:100300001DF5972F99EFBF389314C0E77C7BDD383C +:10031000EB005C77BB841DE2F8B1E3E62AE0C5BAE6 +:100320004EC143C3ECC450CB6A3C773D13C4243068 +:100330004E7842EC8F1F107A45FA09115D787EA63F +:100340008EF3377B5521BF0D7E34FABF529C4F94FC +:100350007A5FEAEB32564BFBC14712F839C6B98ACD +:1003600097DA55E0CE2EA8A8122B0F42976D35795B +:10037000BD19D49735D00F48EE62E7FB43C6579EB0 +:1003800045B62D65CD7C7E41EDCE19BC25CD191D20 +:10039000ED4D8975E30A1BF56F7060FCA454C869C4 +:1003A00079ADE2F5F17990DD94F18AD9C26E06DB80 +:1003B000A70EF628C80ECD0EB2B3AC566B5701DEB1 +:1003C000481C47C21B0CA72BC24278980770A1BDDE +:1003D0002D717B0F4C24B8150750B2033CA5CC35CA +:1003E0002606E701F53E7B47F882E7D5015E31CF6F +:1003F00060B84B1C9FFB70FF18CF8751BC29681E4B +:10040000921EC1FE9AA44B8987E3B7A441217A7E4C +:10041000DAEE07328A1B497E8105509DF67BD74470 +:10042000D467A5EB40FF66F8F947F2D33C56178531 +:10043000FC52C17C2B9350BE7C75D346A2DFBEE13B +:100440007D23CA49A1CDD7531783285CFBD3BCB405 +:1004500080F544109E6F44D76F8A379C955EC6BD69 +:10046000004FB337ABCEB0419A76E21C9187E4607F +:100470008EC763C4F8C61CB1EEBF119C957A7E6E20 +:10048000FC86F076E2277D5BB8F3BA68FD62BF9F19 +:10049000D5333A949E6AF7AF82ECFADF0C3C7E21AA +:1004A000F5F155BD93E225502EFCAE2A2B8F9B070C +:1004B000E9F1B42CD2E325C2AECB714EADDF49F1E8 +:1004C000B7D968F703CA3F5DB793E2FEC6576647E0 +:1004D000A1FF7D6AFDCCB578BEEBD4B69964E74B3D +:1004E0009F9376DE6D0CF41F72D717BDF863E4DFBF +:1004F000AD61149F2FD9EF16EB1ED0ABD0CEBE9EB0 +:10050000EB51B68EEBD552B48703C81EF6C6768B78 +:100510004BDCBD510E02CAC94E2E9EE9FEDD1EE81F +:1005200077F1CB110E0FA1C2EAD391DF6EF5A13D99 +:100530002C5FF8F1513CE70EF6FFA31F48FB0FD9E3 +:100540008D7AF7922E286FC2EE97AB1BD3ADE827BA +:10055000083BF15FC0BF3934FE8710FE8B11FF01ED +:10056000FB20C76B389E6706E1FFC41A4E9795DBE8 +:10057000BA47E1FAF1784D77F2B38E6FEB49F89F05 +:10058000B51AF0CFE35F5A3FAB06F08FEB08C43FDC +:10059000C05BBCDF2EF0EFE0F8AFE178676B783A34 +:1005A000AB039E3D748E61F1AF4D0EF41BCE84F90A +:1005B000C89F3AB35D65D5017E98F483BE60B5BF30 +:1005C000427F4DE27F6EAFE641A87F0A9FFE531443 +:1005D000D261EE761EA4EF807FE6EC82FEB87FFC4F +:1005E00076BFE9952EF1017ED34DD2A982B918D9F3 +:1005F000C5863F1DC17583E2844F6D788F46DCD779 +:10060000A8D7DED7C0331985368C2F38CC6684271F +:1006100035F81E8A9B611CF99F3D3F9FB190E4BC59 +:100620005573BE6D22F319BAA0FF58A7D0FDC6F2CC +:10063000453951390CE3D45504C7E92E8AE6FC78D4 +:10064000B9AA23FFB1CCC8FD48B93FF9AEF00FDE1F +:10065000EDC2D725EF75B1D27797C218D9814B1665 +:10066000A317EF23C07A2A11C7F7EC3111DD8E22D0 +:100670004C807FD528E2366002914F1F649C4F1F4B +:100680008C6CA23839AC545E40BBF8D0129383FC1A +:10069000DAB8688AD73E20F4DD83912B5D681F1E8F +:1006A0008A343A31857E3D7888CE301A8687F10DBE +:1006B000C946BAAF53686E790597BE0F279E78D4A6 +:1006C0000CA0DE06EE37C655E0D75DD7633BD2C53A +:1006D0004F1F6D9CA7323C74DCA355E04B713A2947 +:1006E0009E6382BEC3018E2B682FB1DC6EE5F19D47 +:1006F0000D40278B9FBEC1E5CCC3F703CAF05CE376 +:1007000028C6196404E15F932F33F2FAF0C4AF26D0 +:10071000ACCB66ECCFCC3E10E956863A04D7F74511 +:10072000D15E8C97DF83F1251BA67AE297C97AE622 +:10073000D1F1B42612CFCC8978D34481CFA92398A4 +:100740002F1AF0EE3BA88D77DDE7D3F97A037EEF21 +:10075000D1FB1A913F7566BBC10AE3B8F29421B888 +:100760002E295B7E73F0A6259AF3D7A5425EC7CFEC +:1007700085B5FE80C7211E046145BCCDD0B3FDEA1E +:1007800010CE0788974A9BDD43ED1628140F95710C +:100790003649FFC1D07D201D1F14F0413F3551F86F +:1007A000BD3134BDFA26CAF5731DADABE70BB99B5D +:1007B0002FE56D9B56DEC627DAA9BD827E30E0EDBF +:1007C0004191762617E344FFE312B95C64DDE278D9 +:1007D0002CB2359DCEB708792937F1FEE5F8F788B8 +:1007E000744CA28DFA95F000BF1EC77E74A00190D4 +:1007F0005F4FD656937F348705C4B533FCED245F35 +:1008000077CCB7EB11DD754C8DADB310F5CAF7C2DF +:100810001CA8471F34D6F5AC8AECD84EEEDB14B2D8 +:100820006603233D29E261C2FE8C5523E97C40A189 +:10083000C2EF0F5ECAB17874D118A73110690B638B +:10084000143A3FF137B17FF250F4E28928D785514D +:10085000463DA633582BF5FB776BB7E8FB18DE3324 +:100860005631760E038FC877C2B8D5A877787E8DBB +:10087000339BA24A227FC72127E0E1DE6B407FCA7B +:100880007F2FDF09FD5F7A4BD4B33BE9FB4B8F0B26 +:100890003EF6E4F2FCCF657D1ECFAF92F5F93CFF4A +:1008A000A4EC5FE49F0EAA5F1654FF4B9E5FBC3E14 +:1008B0003FDF837EEB68CED285A314D2537B84BE08 +:1008C000285CEE23FC16EAF6F27434F3E9B26EDC2F +:1008D0006E53A26B0FDA1FD572D282F6F7D564275A +:1008E000E59F4F702F4BC475D424C563447DFBA195 +:1008F00097ECC1C44ECE1FEDE9C2E3F89B92A0BFB6 +:10090000A17EFB05FDAC4E8CBFF57E1C491CAE8064 +:100910007E9EF926F0FCA7233C1BBE493FB392B54F +:10092000FD487F484975BE86F36327E334E745E613 +:10093000FFC4118DF12786E74500F5F397D7A5672A +:1009400042FFF35F7D3DBD04FD2561E72BDA74CCEA +:1009500089F734DB18A5E71B3F31E27DB38A5D8D53 +:10096000C671D0AE12D2DC00B8CA049C60E7F49322 +:1009700003EC7383D01B8C3DCDF7375F3DAB477ADB +:10098000CED7D59D7A0EEDF62825E43ECD66F1DD75 +:10099000D14ECE17EF157AE86A9AB311E7F96B8C4E +:1009A00021403EB7BA93FB60491C5F85C2EECD1C67 +:1009B0006631DB01CF433FE4FB54251B3286603CAC +:1009C000F8CD84D1EF247E6D3CB595C7531B783CA0 +:1009D000B5D0D6BC089437332695AD31DFC1D88465 +:1009E0005F48390391856FF34C325F9D3F269BC76B +:1009F000BB307F76FD636B506E9AC2B91FFBD0F09F +:100A000081E1A8175A3222745690E737E38B8C495C +:100A100043B1FC8E71589E63B2F42A22FC32E28B01 +:100A200037E35DC7905FB03DC641DC465FFC7D307B +:100A30000FF7DB2A9DA7750F8A7087DA77FA87C0D0 +:100A4000AB31C94A69139019FD1709871C1FFCF9BE +:100A500045CDD0DFC9E5498357DB719F25C7903469 +:100A6000D43F7E4682FB72E0F82775AC172E296EC4 +:100A7000168E4B020E03EE5D03BE5DD92A7306ACE3 +:100A8000F3268F89D0E4EFCD8F65CEC038EDBD2938 +:100A90009AFCF4C2EE9AF60FCCEAAFA92F30356774 +:100AA0005505F8B19DFB491E82A7D26209477FEE2A +:100AB000EF0D5FFCE541F4FF36AB0EF455E7EED9E0 +:100AC000F297DBA1D5653C4E45F1473BC5CBCEC97E +:100AD000F3287AA73E705FE8226BA6F33E9DED03F4 +:100AE000C975EE7CEB7E3A77F65DEF03F54A12EBC3 +:100AF000DD216C08DAC3CB551F51BCAE2292CFEF7B +:100B0000E2EBC78CB80F8AFB8AD781DFEFC20FD127 +:100B10003F6CF3503C3BB7FE18ED9B1D48E47ABA9E +:100B20002275811EEF1D55428A76681CE8AB68E08D +:100B300097E646367017EEBB6658B81FDE3699B199 +:100B400058E42B1EDF694A88A17BD7F36BF2A8BC5F +:100B5000A22D9CFA7F4F6D1E47E7095F5368FFA1E6 +:100B600020E5A1E5787EB829DC33E01118B7E077FD +:100B700077E521DE2A76F1F3B505EA9FB316405AF0 +:100B8000569B47DF17A8AC49017F61422EB7BF05CE +:100B900068F321AF0EB3AC46BBAB1A7DBD9E473D9B +:100BA00063B4909E896E7B80C6AF6C33D3F7F72415 +:100BB000717FD7D0C2E11ADBE6A272C90F5393BA94 +:100BC00069D60F86F8CD7A7C97C3D0C2A8FDDD6DBB +:100BD000FD2895F37DBBCFAFE93EAE21FEEAB81408 +:100BE00098F7DB718A95DC90203D7CA56A78340B00 +:100BF000A1A7DAC769E3E7F44C6DFCDC5E618A7398 +:100C00007E12C031F1B1163DEE07B148B315F13592 +:100C100071C4607B49807CA97BEF37227D0CEBDEC1 +:100C200037A29D36419A1B505F2ECE3304EBE90567 +:100C300049524F2FA354DA1D767506F9A933AC82B9 +:100C40000185FCCC10FA547EDF4C6B1AA0E36E1EBB +:100C5000C77F34C5BD02F545730E9BBE83F4667332 +:100C60003AEEC37C57F0039DCD0AF9892D741E75A9 +:100C7000E208BB0EE3FFAB045C528E6F348FC5A25B +:100C8000FD7B2A5B82FDBE77E79DCD4EE8AFF14745 +:100C90009999680FE4B8CF25F17B29CCDA7A0DD782 +:100CA00083956F44D851DE0B703186FB9D7B4CB42D +:100CB0004E8172DACFA87CC3B409EF895446C17A59 +:100CC00015C6CF7D33CC877CDCF866981EED46EFE9 +:100CD00074F77348CFDC377B8FC1F5A1B3C1A4672C +:100CE000E4F7389F273DDB09BC37D25BC17C26E5A2 +:100CF000D35DC3E5A548F069B1903FB790A32B55EC +:100D00005D480EAF3C0640E33EE963CAC05DE8279C +:100D1000D82DF47E9394CB025C0F417941FF183AB1 +:100D2000FF2BFD8D60392C6BB352BFE56D7621EF43 +:100D300036CA4BB92B167263127EC62CC1E7BB5361 +:100D4000DCEF205E0AAA41EEA3681F3F0BE5C9CF86 +:100D500037462BF217F04D624980FC5437DECFD076 +:100D60003F31C5B9886F66411AE89FCC6EF74FAC2A +:100D7000E31200FE892B327478DFA99D7FDBF9E650 +:100D8000E6F87F8F9097E2485F4FF4670D55610E4C +:100D90003C877E398EEFF72C5CC5F1B8D0E0CA45B0 +:100DA000FF62E12F158A97A1DF817A69D8912A63C2 +:100DB000601CE5FEB641CC0E7898D2D683D23713AC +:100DC000DC47110F456DD304BE067DA3FDC5A14EC2 +:100DD0001E4732784D8E8D19184772AB48E733693C +:100DE000CCFA4CE07EDE7A1DC5C3E4BEA38C2B9901 +:100DF000F0BC7C801DFD425F9B4EEF3704C79972AB +:100E0000B8DDBFB0D94076BFACF1CFC374507F2EF0 +:100E1000C3D905EDC9977A771BF2F5BCC9DE570D2A +:100E2000909FFFE4CEA891763F3EEBF4BE9E6847CC +:100E3000EB008F18EFAA5BA3E679B9BF13C1F7C91E +:100E4000387F4B7E0EE6F3796DDD889FAE5499C8EE +:100E50000E5D01BE65017648DA1DA9E7A5FD917C0E +:100E60005DAEE7FAAB3C32DAEBC908B43B935C39D0 +:100E7000C8777DF8791ABFDDD9B47614CAC1A53810 +:100E80003AB728ED46B01CBCB6141CD35E1DED8EDF +:100E9000D4EB52CF4BBB35FAE52F77FE15CD558AF3 +:100EA0007B4032E0EB6E3DB75F77EB2DC43F63E3F1 +:100EB00026E9916F6E5E8F1E137AF498468F5674F2 +:100EC00062070627DF9A1C7415EDF34CDC7F443D66 +:100ED0001FD8DFA329A3C7E03CC627733BFB5DC136 +:100EE000DD99FE1F9F7C6BFA7F58B288F7DD40FFCB +:100EF000172673FD1FACEF9995BFA773694F5F2F3E +:100F0000DA83A30CEC03DAC18608FB16610FC85E16 +:100F100084477BBFCE1E5C4D9B5988780A610F1EAB +:100F20004AFE16F640F2A1941B2927522E82E5486C +:100F3000CAC5849FC23A11E9F41EBF5750AEF76C80 +:100F4000A3FD467BC46094CF763F6E9742F2D6C134 +:100F50004E08F9F1CB8BD66E48B990F222E5A75C2A +:100F6000C8C5EC20B9D8A7D63D330AF7CB92DD6BC4 +:100F700093E3FD7252B623D83E74CA57185964B32E +:100F8000E3AA18F25539A4817C65EA441E9E49BE45 +:100F900035BF68D94DF2D36FFEFBFCF49B4EF8E9E8 +:100FA0007FBE0D3F75F4633FCEB2033C57B240DFC6 +:100FB00066F8F96DC23B8CFB0FDDF97A00D6970419 +:100FC0007793318DE23E13AEB32A8A2F0ABE947412 +:100FD00096FEC06C11773893E27A07E1C5F5C082BE +:100FE0009BD37B4467535CB311D727B3210DF40324 +:100FF0003AF37F9B6F51EFBD7193743E96FC9DFB5E +:101000008DC79243FB8DC7B1FC9BD2B5209789F861 +:10101000DE8F0B30DE38E1299167CB0A108FD34683 +:10102000C8FA9F3CE9EC81FA81C9B838C539DE536A +:1010300045DEB3F4F018683FE119E68F9B43FDD815 +:10104000ECE8F6B888C2FCED95E71F3BBC86E8519A +:10105000CBE5CCDDA2E7FB3F229F05794B407E44E8 +:10106000507E036F1FA56F6181E745909F94219C7F +:10107000CEAE00FF0186DF7F05ED85556118D7A84C +:101080008CDBF8D615D46BF50AED45B5E381D514A4 +:101090003853C5FBB9945F73D8093EC203BB78BE11 +:1010A0004F4AED931EBDE837E0DCBDA14E71D2B9C9 +:1010B00083118AB75B46477CF749D1DA27FCD16BAD +:1010C000BF67781EEF56BE6FBFCFD68DBEF7996E45 +:1010D00061FCFBB2439F7FFE5E0AE7EF3159D121ED +:1010E000EBC7A5A8BC1F1137A0F1A1684A5DE87B3A +:1010F000B013C5B8CDB85F42F8DCF624E2B7D92802 +:10110000F1FDF293C8776319D3C4CF607CCADF9F27 +:10111000F272418D9E4FD71984AFAF9BEF8014A917 +:10112000BFFDF8F204D1CBF435F87684C0B75DFB8F +:10113000BDEFEBE835ACC3F7826FE7483E766AF85F +:101140003D5AEF22FE8C8E53ACE84757B8C2D6E02A +:101150007AC12F9FBF27BE6C96FB031DE4EFB5023B +:1011600094BF0A8947CFEB4FA2FCBA74EDEDB93CAE +:10117000B6F33573F601BC52C80FBE7FE4F9FA2707 +:10118000312E097C41F594D707C01D2C8F7541F98C +:10119000EC20F915F247FA03ED01E0A927EAB7B808 +:1011A00063467B009FFC4CD0E9A2B827DA3C9AFB4F +:1011B00093CDDD78BA2385FB8FCF097C6E12ED9B32 +:1011C000C303F090AAE11F1FAE5B02E64D78BA3F61 +:1011D0004ECEFB93827CD063CD365EBF2DE5A32738 +:1011E0003DD9FE7C707FAFA67C528078F1F7FFF18D +:1011F00061F423EE1778DB9172E4B02752D039C145 +:10120000FF4E21F007BD63518EFCA174E48F1F7661 +:10121000E44F4FD0F7F44E7767DF7B3A7EEF0CFA5E +:101220009EE13DEA9BFF5ED02D3F88AE7941741D63 +:1012300013942F9479AF46FF4ABD5C5CFFF4E30939 +:101240007118DF54E838BF9F9F4F93BD996F95FC8D +:101250007BE630F2AB9F9FCF129E27D709BA79CE9B +:101260003D897A7812EAE151FEFC14D443943F5F41 +:1012700080FB617E7B7581EAEFAB91ED2F92FD7A69 +:101280006085ECEF33CA4B3A32CF25B277F70BBD0E +:10129000C33CADA4F7E735F0EF3F7DFEF3C35F2B12 +:1012A0000FB54178D91094F704B55F7703FBB622E8 +:1012B000E8FBC782EAD704E5D707E56BB4DF17CDB3 +:1012C00052480E8B46F0FDC960B90CE68F2F52DAFA +:1012D000E363EDF65C8924FF4E235713AA79FEFAE7 +:1012E000F3FF29A8890CC8A7B0891EB2EF305AC0F5 +:1012F000FD41D0B91E15F8C1D089DEBCD899DEEC0D +:10130000136CEF79FD3FF0D724DA2FD2F825FB5488 +:101310006DBE51957047BDBB2832605F955926E27E +:10132000BABAF3FD9B8889635203FC224FF84467E5 +:10133000C03C65FB715F5D5771BCF8D4F0899B714F +:101340007F68B4D8D7B4F114ECA58AF6BA52C46F4A +:10135000C6E1395D6C17EEEBB930D00F6275BD7028 +:101360009E8D3F52F9BB50D5401FC05311B3D37966 +:10137000D39978EABE3BD447472FF90D7CB7EF47A6 +:10138000EA12B4D34797C4D239A645A9DCEFDC17DB +:10139000DD356136E41B231E267DDBF8C4584AF791 +:1013A000AACE95AD56E83A357962645FAC8F263C9B +:1013B0003936C44F5C06FC9D996A2738DC366B428F +:1013C0003DFADBAB0DB45F082D7E45FCF3A469301C +:1013D000AEB78B96F5A7FDB0E29F4F1A87F7B08A9C +:1013E0001F37D03E498BCE4A7122F7EAB1742E6A7C +:1013F000D60A917AEEA2F4CDFFFCBA1AEF69B5BE17 +:10140000A0D0FB0E775CAD7B67109E9BACE94EF7DE +:101410002EDE8075009EFB3EBEBEB717CF219F0813 +:10142000ABA273A4D09EEE8B955EB3BF3B310BDBBA +:10143000ABD6E5D0FE1494A3FF7C6A95BA09EF41C0 +:10144000154559C2F1FCF6A9AF18C5754E3D6EA2FF +:1014500077228E47BA67AC8FA3FBB8E8E9B3538A0B +:101460003D4A013C4CDAD067626212969B047DFBD8 +:101470004415011E8A74EDFC43F6A42486E727A5D3 +:10148000F699B805E671EA97BDE97CD8C154E7E45E +:1014900054C0D72FD29C5352E3115E6EB7DEFC0FBF +:1014A000DF8FFCE385E204E4AF8752395FBFD1569A +:1014B0009C10F8BE77C9453DF1C19B46FB227A27B7 +:1014C000303C4DC17536F0412CC6CD6789750BF0A7 +:1014D000F3929D21FCABE1A92AD1ABF1A7F1D94848 +:1014E0005F3F5F0F7F17F519AD37205FB121732D77 +:1014F000DAB993A625EC440FD67EFE91ED0B233C82 +:1015000019B68579C332307EEA1C87FCCD12EB7A9E +:101510004DB604C8A168FF770F3FE7FB77688FEBF4 +:10152000BEBF7BFED712B89F21DB9746593CE85CD3 +:101530009CB658F4488FA3FAA5A7F03C5AC90B06ED +:10154000B203252FC43FD68AFA07F806E36BC1F32E +:10155000FA63AA81C7313A934BCF18AD5CB231130D +:1015600071BE9DC965CD86DC899B233B97CB522BF1 +:10157000D74FE35EE0EF51960EB5E8717F73F40B41 +:101580006F6DA17B740BC286E0BD89D2174C44AF4E +:10159000168BC563BD0DEF1358F431903E9BCAED19 +:1015A00069BD909F5C95E9CD4328A57B1272DFF061 +:1015B000EC92679EC5E397E79877DA70C0DF6527FE +:1015C000E7D3CBBB548A3F06EF23961FDC69CC617F +:1015D00037B18F7883FDC332D622DEDF0DFD7DF07B +:1015E000FEE1ABA9C1FB8706BA4F5E2AF60F73373F +:1015F000280477E9127ECF3F3796C78D4F2E05FA24 +:101600001B69DE1EEB103C0FCDED4E2953BC66F876 +:10161000F5AE0D0B288ED913F184716EF16EE2894F +:1016200030473AAEF34B5E0823FC96FE6AEE5F7ECF +:101630009985F7FA0AE202D7D5FB912F387E19DE99 +:101640001F94FD9C5EF6637AA731F745581FC37C53 +:101650004A63D8ABF76720BD92D2719F53B62B5D1A +:10166000FEA35EBC1DACAF611D5DB44AE5EFC7ECE7 +:1016700036911D04594F6401F72C67AD38683472F8 +:101680003BC6128709FFDAEEBF9F761CEAF1EA6ECD +:10169000A5B88726F127EF5115E9F8FB74853A853F +:1016A000EE578126A37B499753B95F7B3A959F6795 +:1016B000284A77D0FD9CF2B526C7F20CDE4FFB7DA1 +:1016C0004F58DF95EB9A4B683FF3F7268AAB54AE41 +:1016D00008738645F1F3173B06D0F96ABD11F05146 +:1016E00066E7FAE2B2986FA57DD25D749F41CF8E16 +:1016F000E8A1BEDCC2F563790CE03D92338A6E1836 +:10170000BE67C7E8DC24F69B3428607C4594433FE1 +:10171000F6287FBF4D3A5683711B6CDF7710E2319C +:1017200076DA7484EF1595E41990B47604FA7DAFF7 +:10173000A899B8DE2E5AB56F1CEADFF9DB07E38DF6 +:101740000956F4EA07643FE60BFAB7887367C59059 +:10175000C777B622D2B83CB9551E2F8A485334EF0A +:1017600010C9FAF255061EBF073D8F8AA57CD9C75E +:10177000D46FB9A53901F56FF96EC330D4D351696F +:101780005C2E8B97A5651F01BE2A3644D3BB8365AB +:101790009E0223E6CB6A15CAFBBF8B4F473E3DBF77 +:1017A000E2B528E49F1361BE9E68975A178439E812 +:1017B000DEA195C7EBCEAFE849F79566599B2DF8AA +:1017C0009EC1AC45DD6DA8BF8F5A7D46AC3F5A9790 +:1017D000A1C3BCD36ACDC6BC537F1BE5CF8BF32D11 +:1017E000F4837CA5703A976DDB67C4BF4F3244CC5D +:1017F000F7E22B1FF4C2F84F797A732FB42BC0078E +:10180000BD5210CF2F2964972BB6F1F3EE920F2A19 +:10181000900F40EEE6093EA8D8F5DAF7511E2A905F +:10182000FE433AF211F0F37E2ADFB1711CE3DFEFE1 +:10183000473E91760CF22B0C368CDFF17C661AA7B2 +:101840003F948FE1E59E01FC1C5DFB39048D1C7407 +:10185000465F571AB787C5CB4CA46F5D695C1E5AAB +:1018600056ED8E42FA5D7C65DF01DC6729DF0156AB +:10187000DA1E421E043E2A71FE51043FF9179538C4 +:10188000DF28FFFCDBF95EC86125E3F393F3ADD4F9 +:101890008BF9CB7AF1FD24C12F654CE06B576F2E8D +:1018A0007742CE508EE9BD0E313FB74DFB0EE5F7C6 +:1018B000C5FCDC2265D6BA28C40FD217F50F3E103E +:1018C0006994FA049A5CDCBE91CEF14B7A49F857E0 +:1018D000093840DF39636C7E3AB674F24E6495E0A5 +:1018E0009B638F7749AF07FC9DDF4ACF6C11BFEA3E +:1018F00003C6937C23C7CB7D79D2DD386FE8DF87C1 +:10190000FDCB718F7A22F4D8CF51C6E543C22FE5C3 +:1019100032B7FAA1BB074761BB8B96EE0370DE9C22 +:101920008EABD2ACF4BD13FD05F8DE59AF50DCFA36 +:101930009858E71F7BFCB5A8E2017E7E7F427C279A +:10194000F90C7F303E26E16DB2F1387030DC520F79 +:1019500049B8739FB8EF6E2C97F0E3BE51209F4AB1 +:101960003C4A7E95F7F582F996784EDA4FB573FECC +:10197000AE4C3D46E7773A9407F727FCA213E25CAA +:10198000796B3CE371FF1589FB35F78A188B0CB432 +:101990003FD28EC0CF1A7D80FD69BFA716E73C8B72 +:1019A00074BB90D68DFA3FC7EA8C39D06FD999E6CF +:1019B00071F8CE9DF443EFB8EA53A3315EB58B9F27 +:1019C0007793FC5276613FC941B9B8FF54B4EA83BA +:1019D00082E1C8EFBF35D0BE4ED1E3638DE8DFCFE3 +:1019E000DD327318A201EF41A05E3FBB796826BFCC +:1019F00059604D9886F721363F33ED01289F55AF4A +:101A0000D2BB0DD80FCA6FD1A399145F3D11D65226 +:101A1000300AFDF81FA856F4E36FDF32F4316C7F13 +:101A2000BBA56B0C3DB6B13996F24E7D34D907E9B2 +:101A3000F7CA7380D5E2DEC75F84DE3FDC9E2AE210 +:101A4000FC5F752FDC8F6FDD1846EFAC141AED7557 +:101A50003E1C6F4F175A67541AF1EA23DD5B25BF0E +:101A60006C8E9199938650B93909CA0F1A9A1F45FD +:101A70003B72F051CB607C3F92A9D78615737F9A59 +:101A8000EF3BC66ADF2D91707C24C60FEE4F7EDFE0 +:101A900084EB081BDD4FA4EFCFAEF8ED34B48367C1 +:101AA000B7F6B4E1BC4FEF09A3FB03A70DDA77CF7C +:101AB0006EF5DE57F07D29796FF5749AD68F93FC19 +:101AC0007EC37B377FD39E83BCD1B9A50B4B19DD79 +:101AD000FB7E398DD1F76322BEDA89E7084B6A4D68 +:101AE00056BC077312F91EF7B376ABFCFEA599CB73 +:101AF000C1C9DD9974BFB7E46F3C5F52A778F13E6E +:101B0000F2FEA79FA0F30AB3C1CFC4AB09EDFEF369 +:101B1000BAA7A7A1385C76B857E27DFECB5BF9F98E +:101B20008A0EEF321CDC7920C9DEB9DFFC5DFBCB0D +:101B3000320E119FAEBDCF2FF12CD74F6F023F8CCD +:101B400018E2C7DB674BE790BF7C61A99BD24BCA09 +:101B5000B1B5B7231F5BA2E9BEC01FEB9F51F1BD1A +:101B6000A8F25D83AFE13A78546434BD93F2D9D2E0 +:101B700025B48F7A616915A592DE320E77C7AE461D +:101B8000FAEEB3FACC06BC9FFB4664B4B003B69041 +:101B900074EDECDEB19CD7B91F70FA4AB8CF6D9DD9 +:101BA0001985F36A7C3EB66124D23522DA8A7E5FDB +:101BB000A93847726A3DF7ABCF98A37F930FF43DE6 +:101BC000B3614A02BE3737BBF1DE69585EB247B136 +:101BD000E27AC0B1675214AEDB3ED5B744E1FDA84E +:101BE0004FD7CB7B555EFA3B54A3F2D8146C3FCA57 +:101BF000A767F60CBE758D7C32F2829EEEBF9E8783 +:101C0000728A935C0BA73809FCC4E2B991D9AFF38F +:101C1000F84AFB3A57ACF36E17F37E34DD26F73102 +:101C2000A83C77042F3FBD61E744ECEFEC668315D9 +:101C3000E1FE6CB381FA9F07EB331DC07B662B5F1F +:101C4000F7601ED7CB67B7F2F5CDBC3ABEBE295FB1 +:101C50006070F2FBA25A7ECC0D6847EFFB74F25E17 +:101C6000C83C279FDF3CB09738DF60BE8D6175743C +:101C70008FEC9B9E170DE6DBF9925F857E68E7D7B8 +:101C8000CEF844E013E51DF955F2C3BCF57CDFDE68 +:101C900056373807F94EF247F03B59D546C6DF575D +:101CA000D485D37BB89322ED06B40F53E25AC620F5 +:101CB0005A3E4EE77E809AAB73E2BD37566D0AF905 +:101CC000CECE8A74EE57457465C4EFDE742B3FCFD9 +:101CD00029EE7FC914269286767B5284ED0B3B3425 +:101CE000793AFDAE7BF4C0CF936EB73DDADDC1D853 +:101CF0002FD30BEED1C37C2665DA767783FCF3BF56 +:101D00009AC0F3B7D9861A20BF4C9978CF18C8D794 +:101D1000A73B9F4A0F18E7EC962E69383F28FF191A +:101D200096D7C5BB7F8E69A5B80F7649691DB424C7 +:101D3000C3DFFEFD3D96A37FB4FBF32D0696EE18A0 +:101D40008079097FE8B425DDF9ABF4F88EE5C58C20 +:101D50003D4EE7F53CFC1E0EFCB8CC09784F8AF3EB +:101D60005BB1BC975313742FC7C1EF9FC9FB52F2ED +:101D70003E545FFF7DB20DB7729FEC9281FF1D2A2A +:101D8000C5A9BD0FA634FC89DEF9A9F6B09630A22C +:101D900083F69E4D39BE53771BDD0BA2FB874C6F3C +:101DA000277D3357FA3B68AC87F9DF296089FCFC53 +:101DB000C1A3821F4F2F653D7A80E89F7FB739CA44 +:101DC0000E705C98E8EB85FA2032DCFD27C4D7E979 +:101DD0000DD5A90BE3F01EAAC9910FEDCF78F97DBF +:101DE000CE32E1B7B2CDF1422FA8BE3BA15D534642 +:101DF000DF4D6887DE177C7521C397FE23D42B192E +:101E00007C9D04EDE83C5DDEF2BBE2B1DD85ED4F8B +:101E1000F4980D709B0006BCA7351EFA1C61A3F751 +:101E2000AA984AFBCF5EFE7E929E79A26CF8EED510 +:101E300033E9E23E11DD13947492F8EF4017181A5B +:101E4000FD599D991910EEBE6C03FDFD2F491FF938 +:101E5000CEE2C2DD3CFE427724451EE348A7CDE238 +:101E6000EF9F75B08B6F91BF0A62E9D1E89F0D3388 +:101E700043DBC9111B8DD8F5776D2FFF9D2EFC928A +:101E8000C16C70E03B92A5A2CD58B5D08EEF5B2D12 +:101E90008C37D37B250B5FE84EFCC196FC9005B6D2 +:101EA000631B62895F5666A884FFB9F58CDE1D2A24 +:101EB000A84FA6F394F9F5364AA3DA12A9FCEC6F01 +:101EC000DEC9E27A89D3A7E07FBA8CA6734BFFD331 +:101ED0009B52D6D97BA79166BACFBBF020B76B0BCC +:101EE000A7CABFC7C2EFAFBB0438AEC81A8A0BB9C6 +:101EF0003ADC53E7EF57BAF0BE007EE734507D6717 +:101F0000EF574AFC9A04DD82DFB39C7A303391DECE +:101F10007F14EF594E17ED9AC5BDB3CEDEB5BC4F59 +:101F2000B47B226A5C13F2DD746769C8772DF59E75 +:101F30003007FACF86D4487A47E13E37F8979AF5CA +:101F40004C8B1EF1302D9BBF733975BAB6DE90FDF8 +:101F500039E97343768777920CA88F4D2E6DFBEC91 +:101F6000AEC20EF5657DBFF65DD15423D94F3DBE9F +:101F70003B0BF969E25D51F40FD1FFBFECB410FFE8 +:101F80009BC43BB8CD2C2B11F5C2ADBE27FBFFDBAC +:101F9000FBB1C1EFC406BF03DB7FEB424D7E60DDCA +:101FA0000F35ED6FAB5FAEA91FEC5BADA9CF6CFA3F +:101FB00099263FB4F9394DFBE1473669EA47B6BC8B +:101FC000A4A9BFFDCC0E4DFE8ED63F68DADFD9B690 +:101FD0005793CF61EF68DAE79A3FD0E4C75AFF57CB +:101FE000D3FEAEC4139AFAF1F6F39AFA097DAE68FD +:101FF000F2058E2F35ED3F37BA577745BF22EA0CF1 +:10200000F1AD3A4361F844F9E5A62966D4076BBA05 +:102010000A7D24F86FB9B0D3AC07A37BAC63D56C51 +:102020001FF15F3DFFBBA0C1764F7FDEE5C4F81F07 +:102030007B8DDF6B8B067F521F307E8CD3CC02FFF3 +:10204000EE5D6C9E55938F77256ADA77996ED7D4BB +:1020500027B9FB68EA53E63834F9B4AA119AF65D59 +:10206000973835F90C4F9EA67DF71A9726DFB37681 +:10207000BAA67DEFF56E4D7D5FEF1C4D7DFFAD5532 +:102080009AFCC0BA259AF6B7D57B34F5837D359A8C +:10209000FACCA65A4D7E68F37A4DFBE147BC9AFA1A +:1020A000912D5B35F5B79FA9D3E4EF68ADD7B4BFE9 +:1020B000B3CDA7C9E7B0839AF6B9E6F735F9B1D63B +:1020C0004F34EDEF4A3CA6A91F6F3FABA9977ECED8 +:1020D000843E9F6BCB85DF53E0F897E6FBF6F76E07 +:1020E0007728741FEA5CD76EF27DC5963015FD2403 +:1020F00017C5996C781011F515DE27B7F1F33985FE +:1021000014AF8A237F884C941DCF0B81DF1085ABE1 +:10211000B68C0CF4AB23FCFE5BEAF5CC9BF7DFDA64 +:1021200084FFDCD5EEBE88F231AF6EFB387A9F9823 +:102130007956221CF2FDBF7783DE6D95E978F3199D +:10214000A60FF0170F86D5A60EF99A38C178F305B9 +:1021500086EFC1B6F72BE222F8C7BD1706F4BF160B +:10216000D617F8F7236B979AE96FC7FF6CA995F21A +:10217000EB962652FEFF003A29BF47008000000080 +:102180001F8B08000000000000FFED7D0B78544518 +:102190009670DDEEDB8F249DD07975779EDC3C490F +:1021A00048089DF0D8003E3A216040C0E635044919 +:1021B000A4C1A84143BA81F84F7475BB311002B273 +:1021C000B391D11095C1860164199D092EA3D1093F +:1021D0009AF09AE03A4C601CC5D91937A0A3E28E58 +:1021E000101EE3CFEE8FC37FCEA97B93BE9D0E382A +:1021F000FE3AFFF73FFAFBB4385575AB4E559D7369 +:10220000EA3CAA2AAD5E898922636DDE1C4A9FF3EF +:10221000DA9998C9D8366F31C1DBBD0E82FDDE7206 +:102220004A777A9D94BFCB5B41F01EAF8BD2BDDE67 +:102230001A4AF7793D54FE92B781E09F7A7D94B6B1 +:102240007B9B29FF156F0BC107BC6D04BFEAF553DB +:10225000DAE1DD4BE91BDE762AEFF47610FCA6B757 +:102260008BE02E6F0FC187BCBD041FF19E26F8982E +:10227000B78FD21EEF6794BEEDEDA7F277BC57097A +:10228000BE8EBFDB19FC2ACD9FE431263097E67A5B +:102290001EC2CCC92632F600FE4B82FFE24688CC35 +:1022A000C2D8FD8CFF3ED7B09A76139477FEF23FEA +:1022B0008502C674A58C8D1F0F6962F6CEC634C622 +:1022C00026B075E64F7218D34057D76307FB094E07 +:1022D000191319D6C3DF752DFEDFC7583CFCBF9418 +:1022E000E5784C836953091442FBBE55827F771A07 +:1022F00055D7203EAB8D1CBF695A1395573E2CF81D +:102300000D02635522F3E98B18FB7D5854011BC164 +:10231000D8258F2E47C47221DC0E8304F88F3A44EF +:102320000E7E5D2C8EB1A59D861D9BD206F1AA84E2 +:10233000EF35F0FD2B561A0CAB643D3AC403F21D89 +:10234000DA18C69EB7B8A64B90FF608AC6A787F674 +:1023500099C99FED8C64EC2D8B6B06E65FF2DC7700 +:102360000C1B7FC06CCFC67E661BBAE21741FFFD17 +:10237000C7B5F69DD2F0F3E16E29676CDC0DCADFBC +:102380003C97EC023CCAFFA275E1FC9FD04556F891 +:10239000F3012F49E0784A1A553ADBEA5A82F87C71 +:1023A00019E9B9470353F8E56DABF6AC812155AE99 +:1023B000CA1AE182EFEE822563198CCD65928E41B7 +:1023C000F97CE6389A064D2D642E8217311FA56FD1 +:1023D000C5BBAAB19DC5CC4FB06BB22135D4B88274 +:1023E000F172CB78B9657C94F471ABAB8EE3E520E8 +:1023F000BC4E4CBA231BC7A5E0F59655A27A73587C +:10240000FF76C4EFCB83173F113286D2C7774017D0 +:1024100026681EEB313DAC73A38ED1F78D8F087EFD +:10242000A46B852E2A9991B7FB18E40B817402F4F2 +:102430005184FCD29F3A3792E8E449091A7C7092A1 +:10244000D6A71F0BE3D4F8B3052DD1875E00FC1E81 +:102450008803FA481F9E0EEA9A210DE01FA0AF677D +:10246000B0BDF3AFFF5D0ECE97FBCD4912CE57A3A3 +:1024700006D601E8D8F7B6D6BE5B92991460ED9403 +:10248000317EA46B26DAED73C7E07AB1A54EA8DFE2 +:10249000AD650DFBF387F6FB2AAE17B47FC2A62B02 +:1024A000F753BB9CCF95F29FE2FAC563CAEBAD5ED2 +:1024B000F569AD16F03F71E89C5E1A13621C0D6F52 +:1024C000E76606E0EFEE3833DD6142E4FAF2E74515 +:1024D0000EE69F94E944A11FAD3ED2B5C314881700 +:1024E000EF17E8F9E74437D140CF1944CF9FF8E020 +:1024F000D3390669C42248FB606ABA2075BD60D62C +:1025000023DD2C67764AAB9993D20760F9917E9DC3 +:10251000BEA7F438EF0FB276CAAF2BBED782F47CD9 +:10252000BFC6958A702DEBA57C37EB2FB3C1FC2D70 +:102530006C5E7BD40658CF6F796A5A02CCEF3CFFB1 +:10254000B2A398CEDD257CE293883F7A10AF3EC1DE +:10255000B33E11FABFFBA592F549903F47CBD78513 +:10256000FD2B5F17457E048F1BF8A1978FCB41E3AE +:10257000D24695ABF8A1F209E610A09DFE8306FFB6 +:10258000CEB400FE287EE8DF93508E89FDF7E07A16 +:10259000BBDF34C4E07A3F08E21BC72938186B80E0 +:1025A000FE90D62A63882A88DE1F62E176ACF7B9EE +:1025B0004CDF9FA730A2EFCF05E66040BF1774A69F +:1025C0006601E55AAACB5604F8AC60BE2606E56E55 +:1025D000CD4B05384F2325D7A744D71FB53715A6B0 +:1025E000A1FCF7A70A28FFF719EC8D69AAFD845D05 +:1025F0008F4021E361389F3FC076C70EC54B283E10 +:10260000F69F421463063DF3198B88BFD944E4EB6F +:10261000443DF157234E6D06F6E3943CA6A1ED9F91 +:1026200090F1EDF94A4B74EF83F1EC1642F5C3F7E4 +:102630002B43F8603F243F2C8CFAD1A7713E56FA09 +:1026400063A6BE6427D0756A844B978682C116C77D +:10265000E58B99CB979EB44F33717DE64CDEA8C8CD +:10266000656A8FDDC6E5D1099DE443F844499A1DAA +:1026700024D7809CBDABF897A7118FBB8CA62E2DBD +:10268000A4EC16DD9FFA947D307D70FFBD4BD97FA1 +:102690006FE1FBEF1C99B5EF12BBBAF17BC6EC3AC8 +:1026A000C42F97FD5E998F6DB8DF2AF271C87E0B3B +:1026B00003EBC5F913252B8374B5C0C7BF3A25DCDE +:1026C0008F7CC436E7D2F8F4B2FC0CFEDE5AC15857 +:1026D000A651C613FE4B70195966CE209C54635602 +:1026E000C1291E9BAAFEC80649559EE6CB51956797 +:1026F00034DB5570564BB1AAFEA836870ACEF59743 +:10270000ABEAE7ED75AAE031ED15AAFA633B5CAAE6 +:10271000F2C2AE1A55F9B81E8F0A9ED0DBA0AAFFEE +:1027200077A77DAAF2497DCDAAF2299FB5A8E05BE3 +:10273000FBDB54F56FBFEA579597B07F56954F3541 +:10274000EE57C1D3CCAFABEABF80FB16F0CF1DB6BE +:102750006E55FE0CE9B8EABB3B734EAAE017E47570 +:10276000F62D0E27BE682DE7FBD16CFB07AA765825 +:10277000E768BEFE613C6F7BCF1F0B514E6ED7F4F6 +:10278000A721DD4A5A7322F27166F1DC4340662CC0 +:10279000DBB1AA14C55B4EF95387301DEDDC5F8AAF +:1027A0006C925F71F210A605AE8BA5D01CB3D74416 +:1027B0001FC6B4C85338D58AA834CC3D8CE944DF51 +:1027C000AAA928575F785C3F1AF9282A46A14F0723 +:1027D000D1677D8286F8B97EB1C98FF2C732C52430 +:1027E000329013961F5AD6B1024C8B9A316DF61A5D +:1027F000995F0FFA809751BAC96B66FE6C2067AF7C +:102800008DE0FA93F795A7433B23AB4433AA99E6AF +:10281000518F2548D0BEF5E5969C5D76C6D6EDB0C5 +:10282000CFD7E542FF199EC53BA2014E638E05300E +:102830007F1698233699B1253BDF76FAF287C29747 +:10284000339D4D2417C4F65CD4FF947637967E6E84 +:10285000D79821DFF74BE71198F7ADF1E1F41DC2EE +:1028600025995FA75D470BB60BF99EF6107CFC4CD3 +:102870001ADF7F97A4737D0A8784EB66E5CBC6AC2D +:10288000A0A78C80B9DC3AA9E10CEAF0A2D927A074 +:102890007C62D7E07B902B89582983E0DBC3014E13 +:1028A0004058626C7F96EBC7D8AFD5C5D8D900FA2F +:1028B00049A851C35B619ECF660EE2A35BAAF18972 +:1028C0003006DD8F9D763BF4B3AD0AC60BF0563D66 +:1028D000D737947AA3348CF6F72FD3F87ECEAECDCB +:1028E000B7A39EF4A53C9EE7BCFD8B3ECE447BEB9C +:1028F0002AA589351EC105F2CD5AE9B4FBA09EAECA +:1029000011E62384DEF28B3491BED71D7E4490A065 +:10291000DEA76912C189957E1A77520DB41B80BF5C +:102920004DF40966C8B73DE613103F9BD96967F0BF +:102930001D335A88FED7C83C616BF8CBA28F410F7C +:10294000D3799D76ACA7BB13E8331F27D46366B851 +:102950004EC9E347B010EBA3A4863E0D73DC409F45 +:102960008F4A7DD443FBC5DD26290BE8FB85C5A630 +:102970008A1D21DAFB549E9F0D31EAFE2D5A3E1F1F +:102980008ADCBE6CE6EBA8F0F19A68A692E36B5283 +:10299000C65B6F84AFB5CDC85C01F86E857ECCD0C8 +:1029A000BEE1AB55661C3FE8D04EEA4FE4F264C787 +:1029B0008F72C86E0A5EC721F408943FA208E9A38B +:1029C000CFDF087C68A8D2DB516FB2FE4393807BD7 +:1029D00073226B1150BE5853CA7A44DCD74457AEA9 +:1029E00033843E7933BA54D64FD99F83D74B773D42 +:1029F000E3FD129CEF7FD531D4C7561F8F8F710531 +:102A0000D0534C3AA7CB62D6A245FE98CCDA29BD6A +:102A100085F5527A1BEBA7D4C1CC22A6A5CC4E6972 +:102A20001973523A9D79282D672D94CE64ED94CE7A +:102A300062BD94823D43A99399C9EE9A07FB37A6DC +:102A40000B9893D2EF310FA599E99C7E2B580BC1BF +:102A500077B3764A3B80EF243DFA018C9476829CD2 +:102A6000C3F44D9073987679252665A31F2087D2ED +:102A7000235E3BA5C7BCC594F6781D54EF6D6F3936 +:102A8000A5EF789D949EF05650DAEB7551BD53DE5C +:102A90001A4ADFF57A287DCFDB40E969AF8FD2DFB4 +:102AA000799B291DA5077EC6F9CDE92B447D3EF50E +:102AB00023BD4302F9EC91E5D26187E699DCF1B8D8 +:102AC0006E1A66403A285B2320FD5973340E3FA4EA +:102AD0009B72560BF742BAE104D7DF0CD648D20FEF +:102AE000AD6DF58204ED76087DDA0858CBE9E9A9E9 +:102AF000738D209F4B3AD9BA083BC2194F1981EE0A +:102B000076E83CFD3BA0BC64A734D7087BD6E4C87C +:102B100053FFB18FC3543EE9086B34033C2B3DFB9C +:102B2000A93881E381C2EF7B3B73E6AECD443C25FF +:102B3000C2F3C534302C51BF7EC444FA7561DBD971 +:102B4000420DC0931A4C45681706D4EB42BA1FAE2B +:102B50005E70B9F2DDB65596469C870D9F805A0E81 +:102B600059A9197D85ABF3D5ED6ABE5EFF4C7B8319 +:102B7000FE03EB0937686F7F96A3327DC2FF7E3A72 +:102B80000FA66FDDF58FF66BC80F648EC1FD74570D +:102B9000349733FDA09FEE04BC77C5C8F0C64C1A2D +:102BA00017CA435CB70D9BD2FD3E80778539571F0E +:102BB000C7F27FD4D87742D1AE70D7A65C8233C932 +:102BC0003FB121C69313938FFA3CDF975A931F0DA1 +:102BD0009302F8BF399DCBAFADB75CE9DD81764498 +:102BE000B38665C1773B9B976FCC81767EBC19F429 +:102BF000078047DC5ABD310BCAD3376A266A65198C +:102C00008778FC7873F59E4DA85F258F8EC98676F0 +:102C1000336479991ADB57B806E8BC55AFB6A79567 +:102C2000F49F647EA98666CE826C4D95EDF41D3AC4 +:102C30005611B8DFFD4CC6EF57593CD5DDCEFD57D8 +:102C40008691E1FE2760FC2523B9BFC3B2CE48FEC2 +:102C50000E4BF27F9DBC03CA2DDB347654E9446BE6 +:102C6000ED5A1DEAFB8B593BF2E30E817FEF4BE1FE +:102C70007A21280AE97303ECF2ADDED38B3203FC30 +:102C800084B60A9F80F67BC9C85AA10FF79FE40754 +:102C900005B4FB2D152EC11589F68187CACF65B9FC +:102CA0007E920EF8D92AE1FB40FD92B912705DA127 +:102CB000DF8A76D2F35851607FA7B3F83CAC073B6C +:102CC00099F4D5757AC22B78BE4E65971EC0F695DD +:102CD000750C2EFF7E06B7AB773D015D201F4CE2E1 +:102CE00076F389DD89A43FCE690D77A0FD74E2A952 +:102CF000D165046F99EC403DF2C4EEC9D3319DB368 +:102D00006526D53B21B01EB487E76CB95BC4FCD403 +:102D10000CC00BDB3BA3277A9CB3E541F9FB47CB07 +:102D2000B0BC58E3FB09DA91C58DFB22D04E9E1C46 +:102D3000F94A12A627347DF5DDD0FF5D66F62BDC5F +:102D40009E9D1BE3FEB11CFE31F7A9741DEAD7BF9F +:102D50004B4FA7F59CCF1CC4075083ECBA5BF6F62B +:102D60001E064D8ADDD6DE3F15CC5CE6E8301FC17D +:102D7000B4B4CB5E86D357D6E33C82E9F45E4F19F8 +:102D8000AA2FE5A75B8E60BA24D7F53B9C9F17FF5F +:102D9000E17BAFBC08F0C8C7EBCDA807653ED137D3 +:102DA0006327F9EB740CF9216B92A7458B046C74C3 +:102DB000C6A07C78F6695183FBB921AD250C61C3AF +:102DC0007DE91AB40B7745B7D4D0B8B3C219CEE3B6 +:102DD000DBB00F215D64453B63909F802F691D3EF2 +:102DE00093E9D310ED3147637E18CF1FA817CEE1CA +:102DF000F303F55AC204EA274620FB13D406DCBFCE +:102E00006DF2FEDDC63C09381FD648CF0EF4EB64E8 +:102E10009570FE67919C2EB07AD344FA849CCD962F +:102E200016CF9DB80E5697E8EB0BA43BD80607F4D7 +:102E300091748219DAD75B050E839C21BCF0877EE2 +:102E40000C8BC9427A8D82BFB502DA0BD033701C6D +:102E5000F34C83DF2974179BC1C73542A6BFAC650D +:102E6000BC3D05DFB80C2E9F016F4983F868657C77 +:102E7000601C9A007C02EAD1F806F066761BD20547 +:102E8000487A81A74C1203C75FAD7184A15D647A53 +:102E9000F5FBE84F8942390278FE53F72423F269A3 +:102EA000F0387232D208DF46D087516F9FE9E2FCDA +:102EB000DB58E911C83E4218C79F2C3AD01F68352D +:102EC000AD167401E3B526F37D7A66A5A71BE5CAA6 +:102ED000CCE2083BD2F79DAC7D9D99F3F7914CC0B5 +:102EE0006F141BF899D8C441BDF0474FBF7B1297B0 +:102EF0003499B597E4E2FEF9F8FDB370FDB63E3AB9 +:102F0000B307F14FCC79AA3B061A745E94D77D19AA +:102F1000F7EBA46C133F0E1C479207E040BF448DB3 +:102F2000BA1CE841052B7465131AA271BFD144E4A1 +:102F3000CF9C817A4A9486E43BC829614148FD339D +:102F400088AEE4F957D6E7AE8C4C5A37AB89AF035D +:102F5000EBB71B1746CA8355D609FA6D04361F0115 +:102F600074DF58A6F50B68D762FD28ACCFE29D91BF +:102F700043D769874E9A3903E5F4C31AF36E367462 +:102F80005E81DC7E4B7AEDC371540EF9A291FC7D1B +:102F900001F86A43C1EAF5B859FD6DAC6BEE8CB42B +:102FA000A1F989C90B66E23E9B58CB68FD83CB47EC +:102FB0003DA65E57B237C7A3FF88F9BBBEC17ACE24 +:102FC0004CDE5586FA7CF0BA2A74971A1B7A5F1089 +:102FD00033395FA646D84F95935E21929EE04C11FF +:102FE000E303EDA20D197C1FBAFD3513ED43EC236D +:102FF000A31FB75C7B57EF93B9B00EA5573468AEEB +:10300000B0A3EF1CFAE14C48A7FDEADDD5FF0AF5B5 +:10301000A67D651A87F96FB0BE19E810F1F5809D9D +:1030200001F0DA2FF6B4A0A3A4B192D971DF55FA5A +:10303000D923F7F30B9DDF49F23557643B490E82E4 +:10304000651E402F0069897E78197356B690DD6839 +:10305000CDCC07598D6EBDF625B45FFE49CFD0EFBC +:1030600038AF42D295C0F8E7554ABA65E8C7175954 +:1030700039EA11F32BEC943FBFD2CEF38D3C7F4164 +:103080008583F217543A78BE09F2613E1656F87BF2 +:10309000BDD0EE42538CA4413F78A593975F355045 +:1030A000F93B600F6402C98787F949DEB77CA6E166 +:1030B000F1124FB85F005C0D91453D12CEDF7D1AD5 +:1030C0007B162486149199017EB6C2E9D742F9F3A2 +:1030D000CC9F8013F946F56A6736E4BF912C9A714C +:1030E0007C6F38C06EC6F9AB1569DEE907F01B3599 +:1030F000C914CFD821FBAD7D2B8CE467055D87FC1F +:10310000AC6C45A2ACC7F0F26DCBCD7ED4C7400EFF +:10311000D23AF6DF27921E00F2F0ED1CD48B5ECA85 +:10312000B4874948B76A7EB3542F2FA1F62A99195C +:10313000EDF25995BCBDC697347E0DEA55A679339C +:10314000910E1AF7323BDAAFCF569F2A8B45789B08 +:10315000DDCEE5875A2E34566F392EE1783C1A734E +:1031600016D5E77EAD464FE92EAD30C8CFB4DED2DE +:10317000A0FC182A6FEC3DD84E4255A97D13D4B35C +:10318000C038D18FBD4DCFF37DF7881467B0548B15 +:103190005DE68241FE4E91A7D0827C1845F245C57E +:1031A0005FA35F52C33F92F914F85DC471F97631A1 +:1031B0003BC9955DEA7A20273528AF52DAD4F96702 +:1031C000B204C52FA59A87E079B67AB8DC0B1EE762 +:1031D000E0B8BAC246D1B8347C5C28D7203FD77457 +:1031E00088F2732B45BB24A1BC6B3F85E31FF5928E +:1031F000C8BA009E555D3413E969D6660DB94366B9 +:10320000B35E920B371BB7E2DF081E67F0F8366437 +:103210006869DF1CD007D71B491F6C7DC4A4C1B8E7 +:1032200022E85BE1E8573897551A9E09F33022539C +:10323000D6D7AF6BB93C6934119DEAAC8FE504FA7F +:103240001F84D1A523B0BEEE7AECBC728A1BE9685C +:10325000DCC172AC58966393FA607C2AFF73389392 +:1032600002E6F7D6FE18157CFBD54455FD12102E4C +:1032700081E5538D79AAF269E6712AF80EDB1455BF +:10328000FD19D254157C67CE9DAAFAB3EDF355F023 +:103290005DC54B54F5E73AEE5595CF2F7F4855BEA7 +:1032A000D0B946052FAAF87B55FDC5AE4655F99213 +:1032B0009A2755E5C1F693929666723FCF569BE7E3 +:1032C000A483E48B4B70460EAD67A914FB03D73D76 +:1032D0002A82EB53C1F51AE5F57841E0FDB1FE48CD +:1032E0000DF29DE27F63ED912AFF5CD7E4C9C63EF3 +:1032F00013FA72ECEF23DDB213DC1FC5FCFC3BC5F7 +:103300007FD5FD04D483F65647A65B71BF43BFABA0 +:103310004B0FFDF935E4BFB736D70BB40F6EAEE7F0 +:103320007E95AB7AE68A0DC08385F37EE5788E8242 +:1033300027734470FF6018CFDF26FB959E43BF5272 +:1033400036633FB0287E7817B59B50ACF7A17F4617 +:10335000A8F6087A945B2E66364828079753FF979D +:103360002BEC2358887956D256AF8D39A07D5BBDA2 +:103370006FAD1EC656973969CBB3D0BCCDC3C81F3D +:10338000F368E6942D6B81E7FF2153A2754910F98C +:103390003C3F5FF7C6B93DD05F6B95A508E56A7005 +:1033A0007992BBF3E2B11B943FBFF2D50FEEBFD1D0 +:1033B000F7751D679A02CA87F58B56243247001DA0 +:1033C0004886D07EF91FC874E59EAC273FD6335A95 +:1033D000D793C8CF1726FFD7C4BDF0DD79E9CA3D22 +:1033E000A8A743FE0F301FEAD1BC9ECFBC44E729FB +:1033F00052F340BF47FD3B2C34DD1E94DB17AD95E7 +:10340000FDE8075A1DA997D0CE4F327E467EEA0EC0 +:103410001DB7AB83EDF7E707ECED76B2BFF7CBED69 +:10342000EC9653AD997FCF8C3E265AE4F84088F94C +:10343000D046B50928AF12ABC54F02F9A23B524F97 +:103440007E048B49F63B986A547E01C56FD01D7986 +:10345000BF80746FE95A417E7AF417607B07E57587 +:1034600009F6172419FFB4E8E3D81BB5CF06F223F9 +:103470008410FD04E1A1F82782FBF1A33E81FBCC7F +:10348000CA70D22782C77D39B3E450663CF248FF48 +:10349000C93B507E9FD2D17E381CBD8449E1CC1FF0 +:1034A000D07E6F26B7EF23726254F991F644E60F8F +:1034B000F45FB364F32711320C5BCC487DDFC65157 +:1034C000D8DFDBBCBF133ABB8DF441D8F6D0FE7B0E +:1034D0004FE6E7EE5C4669AB6C97B7011F63FA9C59 +:1034E000D74CFAD936E03F84B77B254AFDDE1C4A2B +:1034F000777AED54BECB5B4CF01EAF83E0BDDE723D +:103500004AF7799D94FF92B782E09F7A5D94B67BEB +:103510006B28FF15AF87E003DE06825F457D5044D0 +:103520003F7533A56F785BA8BCD3DB46F09B5E3F4D +:10353000A55DDEBD947FC8DB4EF0116F07C1C7BC2F +:103540005D04F7787B287DDBDB4BF9EF784F13DCEC +:103550002B8F93B1E65E2FFA2B5CA284FADDB3AE1B +:103560006A33EAD7B6651A338AF336976605FA39AD +:10357000B655F2789F6D9586FC40A087FA519FB3AF +:103580002D7BFAF8342A5F40E55BB149304AACAB99 +:10359000B8FECA56EAA99E150F02C177DB6A2BFD59 +:1035A0005A805BB2C3A9DCBA4A24BBED798D273AB5 +:1035B0009BEB5D24BFAD3AAE3F28741021FBE9229E +:1035C000B2444A976573FCA33242EF2319594AFC6F +:1035D000A4B907C767AB82F121BE55F5468C5F5A87 +:1035E000EF83F149A43FAE3A047824C378117FC039 +:1035F00087FCC26C19D797AD55EB08AFE465F3941F +:10360000786734DAE96D9EFAB9846FA5487ECD36C5 +:10361000D7A1E8FB504ECAE77CACF1E14E7FFE50EB +:103620007C3282F0DFC6B8DD900CFAD2FE10E300E7 +:103630008B47A9C7FD788F1943FAF126CB7A62B27E +:10364000C0F98F3D2C12FF6D67A0F7C177CF817E47 +:10365000E7433950BA6F15FAAB1ECD724DCC023C20 +:103660007E248D3F24021C53CEDB4FAF17F7A01EE4 +:103670000DEB7DAE09F2373EB8D989B671EC6669BB +:103680002DB25BDBB25713D0FF952CA8D74749CB9F +:10369000653CB63B787BCFD58BE44FB6AE3A90769F +:1036A00084F75B86FD268EFA7D18BA613216481AB9 +:1036B0001419C955E245EC2FECA1CDE5D85FFC66A5 +:1036C00087D25F21F6F775E769E4E365565708BCD2 +:1036D0008693273793238BB322E3488E24B1249417 +:1036E00023CFEBB8DCF29DE4FA241D869934B41F95 +:1036F000257EAEC4D383E3E835323D241942C76149 +:10370000570DE8FD3EAAB7DDB1C949E74B303E0B86 +:1037100045AB756C05AEF3EA9270F3DA10F4A0A431 +:103720005B508E01DFDF8B4623B5B3B99CB7A3E1B5 +:10373000EDDCCA56115C6232FB42C86B257D5A6EC5 +:10374000E7812C4EB7490FBEB4F118AEEFDB3A3A21 +:1037500013F49CC6BF11ED04DF092DC9D7446DFBDE +:103760008E3D017835CBE3794EEFCFB523FF407B1B +:10377000F92857915FF2C97FC16605CCBBF2DD5ACB +:10378000D98FFDA36B1BA229BE5CB52E0CF5A33609 +:1037900066247AB0EA3CD18501F46045BA0C411F39 +:1037A000FBB2F44A3CD5543211E3327C5F9E8A72FC +:1037B00009F03E581D45FBE1D465EFDE3916E05BAC +:1037C000AE8876D4CB9EABE5E71327FD5143E726C1 +:1037D000DE7C9CDB7DB7FDB7B21EF47B27C8E9B366 +:1037E00068E7417A4B33B377C1BADC526D22FFCD23 +:1037F000AD57C5B381761AB9A4C7A37DC1FD3553B2 +:10380000FAA13C80FE267DA6AE0F33AA453D23A13A +:103810004F9D6FAB3A70661AF4D356CB3F6EBBF632 +:10382000FE71847DF51AF29300F529F49340FE4D64 +:10383000D19780E716371A19C973EB32A319E541FE +:10384000B7259CE45FDB6213E9A11B325787A19E79 +:103850006CA8AA8FC674A4DEB7037DA7DDBBFF7D6D +:103860009E2D81E42D3F7F8184590CFAC0BD7AAE34 +:10387000E4F8FAB64CCB4479A9A1F2C3BBFF7D8B27 +:103880000F7D07AC85F090342C910F7E00BE9BE23B +:10389000D402DF2F40674E44F874AEAB07E54342D5 +:1038A0009CAF1B8BB69ACE56D2F9E2CA38E2335D92 +:1038B000B587E931BFB2C818C8E70A9FFCB5FCFF5D +:1038C000B41CE7BB991CB859BB37E3F79FA573BE7F +:1038D00019CE9E360C234F15FB18CF9A638A6C4B7A +:1038E000FBEA597D48FDEAF66CCE67C57A7E3E64F8 +:1038F0004EC5F4728AC3F8FA443CC79693CDF9A931 +:10390000CD124971E2B674D6857103DF720DF7F7F7 +:10391000C4F1FFDA2AD3C93FD42A78A27D19783EB0 +:10392000C29586EBD706731409FDB7A672B9CEFC13 +:103930001E33C6ABA19D9A40FCC1DEF3A9E9989164 +:103940003E4CFE0B2DF19EA40FF0B7A35F1CFD179C +:10395000C1DFDDDAAF866FBFAA864B984E054F35C3 +:10396000AAE16966356CC9E67AFA1D3675FE0C491E +:103970000D27A71C09D3F073EDA6017FB344F0BB5C +:1039800099017EA00D9A7601E725A5AF96FCB2AD10 +:10399000A9DCDF935CAFF67324B296B53102F96D02 +:1039A00054F9B6FC5502FA736CD5EA7C9807158C6D +:1039B000CB8AF4BF24D7959F8D71E9027EEE3A4BF6 +:1039C000EBE9CDC575688B233E4A93CF050DDD1F0E +:1039D000B7D0B89576900F7C01E345FA0F842FE6B7 +:1039E000BA2667C7733EF005EE97F97D3AE403A562 +:1039F000BFE1F841E1C762396EA29CABB922B7A51D +:103A00009CABA997CFC775049DC7B9925C46E78167 +:103A1000AEF4AE090FC577C867BE6CCE77986E94CA +:103A2000CFD720DFF9F49CEF30DFF0D52A6728FDEF +:103A3000F0BCBCAF3CB437CCFC71C0F856B647AB59 +:103A40006077478239F0BCD343F80F74BA37333A02 +:103A5000475A2B0FE78B33BFDBD308E95B5A970B31 +:103A6000D76765D6593D8F33F5EB51FE9E97F7DF4B +:103A70000D82DD385AC094DBA58D66BB11FDBDCC2F +:103A80009FA1F257287E87D52BD2AC3180FF8801C9 +:103A90003F82D34CE74DE333C98F1135D571372BB6 +:103AA000043CF7CC986F04A2DC854E5590C78F6517 +:103AB00097FDD0973C385E03FAAB02CE2319440F32 +:103AC00023B97335954901E7CA5B65FFC5001F9BA4 +:103AD0009697607F3FCC96783C8679D672FF9FDAC6 +:103AE0005F66B86A53B533D87EB2AADF56D92F7253 +:103AF000F3F6D5FE37C3D5F461DACF0E6ADF1CB218 +:103B0000FDC176D57EBCAF111F6F433E18CEFFB509 +:103B10005F96A71B6C9E5EF47FE918D89514070684 +:103B2000FA98886A23FF69C3F979535DB2DA0FA660 +:103B3000637E921FCF47D690FC48603E8ADF59983B +:103B400087F2D7474DE7F1BB60B9711379C1988708 +:103B5000A1DE00FDA9F2573FC2F7D346C1EE423CB9 +:103B600083C7F3FF8ADDAB891CDF4BFA734AB86465 +:103B7000B881DEDBEA7525E3F71BC23D3518EBFEA5 +:103B80003CBB2E763DE83D1B30C6087C7635BB71CC +:103B9000BECF84FB24A78FF5711AA227CBDD961D1B +:103BA000DA007AB2E85D69A8F75A34F2392FFCA13D +:103BB000BF6CBD65E7A610FD2BFA9B025B2B008F47 +:103BC00000BA6D95F5E681FE9624EED006B4633119 +:103BD000B80AA93FE55CA3D25FD337EB6FABECF734 +:103BE00052FAB3DEA31E9F55EFA1F159E5FD47E957 +:103BF0006F2B8E2F045FDDB43FD98E1EE86FA97A3C +:103C00007C568387C667D572FFE1407F4DDFACBF2E +:103C100036F91E934DE6D3E1CEFD370E9CAB761AF6 +:103C200051AEB429FE40797FBB14B4BFAD96F737CF +:103C3000E5FB4B71E9E4DFBDD433DF186A5FC3FDF8 +:103C40008CC97A2493F54826EB9108CF997AA63E41 +:103C50001EE8B0F0C5B6F922ECE3731E3A333E1508 +:103C6000E0192FF6CF17615F9AF3E2990349F0C983 +:103C7000CB2FBECCCB7F78E64A32949B7CEFCD2F06 +:103C800003382A96EFC70ADE4ABFB78DE27AA3BB94 +:103C9000E173EEBF04F98AFB5663AA87A17FF14264 +:103CA000727FD432A8EF4EE9B72C0F312F4AEA6E5B +:103CB000384F7E46147928FFE6E1BF40B4CF53EE7B +:103CC0006794ABEF6744456D22FD2F8CF9CD28EF4B +:103CD000228C0EBA4FF8D628BE1F2C64F60A6E3717 +:103CE0004859F2390DBACF31BF586ED77CCBCFB11E +:103CF0007CA1C6B11EEDD9DF4EAA8A47F558391707 +:103D00009737787F72D7F51B9C1F0EBE3F39E7238C +:103D100081EBC223B8BFA53B57E2F7B902FC86A8E6 +:103D2000F70E379FB5A3B87D3F389F0E3E9F310EEB +:103D30003E9FE6FEA8B5B0FEEEE87ECB13C49F5DC5 +:103D400021E76BC8BC06CD5FFD28A6D8795AA4B779 +:103D50009BCDB732AFCAF9C14641CAA2FDEA4F793D +:103D60002AFD8331BB142A8E83F419B8BFEA6D4E45 +:103D700086FE195D9C3D07CF9537FE451BF25CDE44 +:103D80006E793ED64685D3B9CEC6283DD9DBDD5106 +:103D90003319FA9745D3749A97B2A8723A6FA98DDE +:103DA00065ED688F069F23D78EB89BCE0169AD68FD +:103DB00041403A702ED961A4F889B9E886E7C8C5B0 +:103DC0009B9D238F99C9CF9147E9257459B445EA42 +:103DD000439E237F6C14DFF7BB713C71883F8C27B7 +:103DE0006D701CA299C7D1313F02F2F56617237F8F +:103DF000BA3CDEC7E47550EA1BCC1E86F240ABB776 +:103E00004BA8A768C3F93E61B069584E08BFC8F710 +:103E100047E9E8FB4F72CD34AF1A23D7CBE7FC5A02 +:103E200008E94F7A7594E24F0A4D67C3D1C93C0D3A +:103E30003F47A7F0E102939ECEF72D30D94AD10F2C +:103E4000B20008EFB39880FAB72DE2F78145BB0DB9 +:103E5000E9E737536EFFF96F18BAF9B97C3E35437D +:103E600047F7E34E09CC618F197A7ED5E98C9E869F +:103E70006E9ABB669D5987ECF7E2F2EF15617B867F +:103E8000E353751689EC9F7746A15CA84E5B1F0F24 +:103E9000F0A2CA421DDDDF94E344EE082EC79FD195 +:103EA000BA4E8EA278D1E751A54847627F2AE2A395 +:103EB000C48902EABD372A9EEACDE1D7C5A0DE1843 +:103EC00094D3677FEF62B41EB6507A12DA4F2C306B +:103ED0006E23CB07B4A302F3D17E6201EB272C2F14 +:103EE000B6F68590174A9A60DB92520D7C9E90D070 +:103EF00042A992FFAC435BEE0FB1AE57E575FDC62C +:103F0000764C1B603B71D08E01FBE52ACEDB17D5CA +:103F1000A72CE36148756517C98EB1E9153E9388F2 +:103F2000BF06611EAF04FB4575DEB0D5EB4BA1FBB0 +:103F3000FEF2386D2BD646A31D03551C489FDBBCF3 +:103F40006D29659983E3C8CE91E9138DB689A817C9 +:103F5000F35F725CCB0CF497249B34743E012653C0 +:103F6000752F616E59F4B4383445DDCC6E92D02E85 +:103F7000EF253D3FE1BA96F820E1F0628671ABA4EF +:103F8000B87601EF030DF423DF6FAE97E3B9575C0A +:103F900065348E04EBC0FECEC80E8DF3CD4579742A +:103FA000E5698E51C28FD5E5C971FCDCC2FDD5E152 +:103FB0007E09E83AA9B6574038010C38F4C5275CA9 +:103FC0006F4C6B4279F25A04F98BB56D99CC07F2BC +:103FD00027557445E5E03CFBA5FFA6C990070BDF1C +:103FE000AD7C209CF4B336A16506D925F769582825 +:103FF0003FCF981CEEC728C8E1FC9F606B4DA91EFF +:1040000087E9D344375F97CF6790B31DF4D9119FE9 +:104010002DFA581CD47B9A75A1E9739BDCEFC07E06 +:1040200021CF5F187319917FB582933B39F7EEDB8F +:10403000B7CF82CE1346E75536C97A8DD24E444E5D +:104040003B1546D81D0CCF450A6607DF07CC3E9BC3 +:104050000FD6ABF92B6D487BEBC11C791F496BB2B6 +:1040600061FDB24CBB0DFD94C1F7551AD326DA7031 +:104070007D1A670CD0A931705FE84ECB7E1FCF53FD +:10408000997A742CF01C5970AAC77321B1372897FC +:10409000CF97371DE2E7429B4C45BD780EA1C9146E +:1040A0005744C7FE4CFC9CA952DF643A46F2DE64DA +:1040B000E7F15613EE0F02A2C7E7A13BED18CD833F +:1040C000526F5A0E97AB267B17C3FB5BE1763FD549 +:1040D0000B139D3E0DE01F16C7E8FE4F9891F35558 +:1040E00004AC8F3180EF957E6FCBD1D1BC352517D5 +:1040F000F596107E22DE04674DB6221BEDDB38DF1D +:10410000D06F63B442DF9CAF1F97E75B69A7513E56 +:10411000FF7A4F43CEFCB258F41339D7E460BBA604 +:10412000E546B483B491E36FD8DE8661DB6B5E282D +:10413000B7F738F28536B2C88CEDE9505E84A0C37B +:1041400067E476FE57E3ED30B374DF97605A309F33 +:104150002D94DEA3A4468CA38F1BFADD3796BFEB0C +:10416000D47E2490BF7B71FC2B93CF1E2BA11CEE21 +:104170003FDA2EDB278A9D6191DBDE2EF07BE83E65 +:1041800021DC4EEF36C87687254C3D0F83F741F989 +:104190003A5CAEE0E7E62EC7318A6B04F3F3E577CD +:1041A0003E8A0EB44F50EF736473BB0453B44B1C80 +:1041B000B29F0D61F41BA09DA2F0FD805FB742FA93 +:1041C000A75B003F03C86F0DB42B247B88BE0DC9CD +:1041D0007D69C8E7A9F23B0543F6D75C2EA7854762 +:1041E0003F4B43FE2E8BEB4FC0EF82F9FC8547AE71 +:1041F00026E0785E983170CE86E243AB17A7F37B5A +:10420000D9C7FF1CED0AD1FECDEE7F459DDDB486FA +:10421000F4C0E55C0FFC5BDF07DBBE8CEB9D1D8211 +:10422000DAEFA4CDE57AE75FE47DCC7A55A4F72DEB +:10423000CE65B92E201FB60AE6E5287F531FE1E7B9 +:10424000E6563F5EFFD90321F84118EDFA734E8020 +:104250003D5CDCAC273F5AA3297DC48DE21CC3AF73 +:10426000B387CB71797D4B1E35F2F3242EAE175BED +:104270005CF7D33995E0F323C3D53B24CB3DA5BEF2 +:1042800001DB4779629A47FE804B6823A0BF4D96B9 +:104290007BC17876E264C8F36304B9127568451887 +:1042A000B6AB93EDB1ED8A3FA3A2C8E808F85EB7BC +:1042B000B8C8581A402F8D8C9FDF0D6EFFCEDC01E1 +:1042C0007D5AA5AFE8709F45DF509CF8A7013943A0 +:1042D0008A65B8CA8E51FA0F3E3F16705E2C8CF379 +:1042E00029B7675AF1DC18E8B76B2B968FC4F96DC4 +:1042F000155D2F58611EFA3F30D039E70F65BEECCF +:1043000093F972B8F5F3B143A08C31F6043B829770 +:10431000D6804EC68F40FE68CCD494FB438CB35CF1 +:104320001E6708FDFAD6DCAFA75F97E686D0AF51CF +:104330007F7604C51F0261D49B1D21F4EB1382EC30 +:104340000F90CFED9CD0491D7D300F276E1D616F02 +:1043500094E89E91C35E04F6C38B6732516F9F232E +:104360000CBCC723DB318C60B02316225E739967C7 +:10437000DF0302C5515AEE48A3EE045C8F9BADA744 +:1043800024FB1137C23A61DCA1F5DAB219A1E20CC3 +:10439000FF38402728BA02EF07C02A04C49586C414 +:1043A000CB82E263184E1938FFAB1D5AFFAE62751F +:1043B000FC6AE335EEBF30AC60FE27043C1FAA2E3A +:1043C0009F5FAE0B8ECFA9E25A0B9DBA607C7C88B2 +:1043D0006FB28C6FCAB607290E3E2D45E4FDAC6462 +:1043E00064CF07C7BD0C85BD0E2DEAC3158CF4F74D +:1043F000603F369E1725FF5E0563CF0974DE5A7D48 +:10440000DFE4E959E7F8FB1C2DE5D88F2D53C350A5 +:104410003F0EBEAFA0C49BF0984CE07D69E5DD2265 +:10442000CB620DE1C77CB753B9E29787FAA6124B6E +:10443000C0B9EE556CA03EDDA3F2851EF7D6D65965 +:1044400014EF4F1CEF29EC82A2243BA37948AA6603 +:104450006407C03CA8E2FA86945D34CE4B358CC527 +:10446000F238A0AA3C017670A44F18BF2ACE0FE301 +:1044700054C1C176E7CDEC4D434AE60DE5F9CDFCDC +:104480008D06395EF8466E641CE93B63D818D47714 +:104490002C8B9FA6F5B804EB817E59348442C5036A +:1044A0003743FB6807BA905FE2D1DFC454EFCA30EC +:1044B0008748F7C984628EB310EBE4F1E17C46FCD7 +:1044C0006D0807950BF859986C70E0BC1B0C00C385 +:1044D00090053D332640BE56F637AF1598883033E9 +:1044E000DB8DDC4FA8BC6BE3A7776D86EB0774FF11 +:1044F000BE30ECCFC7BF53FA19F28EDB0DBE27FBDF +:10450000CD1CFC7D19F91D95FE879BFFE1DE6DFB3F +:10451000C3D4772770BF6732D16BE520BD12BC4C86 +:10452000A647FC1EE5C2BD4AB1AD770CDE373CFBA9 +:1045300070841DFDE003E3F0DDA9E5EFD1FD75ED2D +:104540000DE0619348BE0F8C4B6EEFAF1D17FD025F +:10455000E4DA06BC3484E74F2A199D27B0B84ACF65 +:1045600089740E00C6A0921301EF13407B1B0EF15D +:1045700073AF5BF19D0B71B05FD42BD06EB0554221 +:104580007E083B4849AB19BF1FACE0D5A8073D1AD0 +:10459000E952C3F5E8D9A63E11CF35E9E2FA45E480 +:1045A0001FE7682EC707E8379ED1F90B6D927CCEC6 +:1045B00071A4C4DF4DCBE4FB9BD2CF84D11A59FE4A +:1045C000F7D2FB47B3234ED54B76C6F2F6C52F4440 +:1045D000FFFCEC11A7EAD3002ED867E170D2A92B1B +:1045E0006966C6ECFBAC0BD19F3F3BEFD495748062 +:1045F0008BF6D978F9144646CEF87D090BD19F3158 +:1046000061B459D5FE5B38D7F1DF3CD51A3421CFE0 +:1046100063DF365A394FC9E83EADB3F397A7312E61 +:10462000E954F647872E48DF81220BDE23937F7102 +:1046300051140F9D29D3D99DF8EE5214FA2DBB6861 +:104640007E470DFAE99FFE6BFCF482437997CACC52 +:104650002A81FF1B1B982B2C2380EE9943739D9F6F +:1046600003A6B881828FD2FF10BC6069C59840BC98 +:10467000B6513B0A5E170A0DA48705C7872E08FDB1 +:10468000DBF19C54C4CFD62FC275BA10D99F2A0033 +:104690001C9EB79ED6ED427CFF76C11E00EBF83A19 +:1046A00056EF2BA275FCA3D6513D7A02BEDBC5DFC7 +:1046B0006F6896E3504FC6BB7C689F01DDD1B9326D +:1046C0005F8A9EFC4865E30547A03FB06E34F7CB98 +:1046D0005C92D3698616CF49A04BF70181AD85FA6C +:1046E000EE6B97F5A89FCCEE3CA3473DBAEEC01900 +:1046F0003DDE4BAD4318DAA9DBA67784D2FFFE324C +:104700005AABF2972976D7D194ECF5E877ABAB1694 +:10471000E81EDEEAD7B91F6EF5321C256377DFB2DB +:104720009FFCB855CEEEF5982E657D47F1DD88C526 +:104730002EADEADCC0929A08553CBECA13AB8297F4 +:10474000B6C0EAC03EBBB42149F51DC35DCF82EFC0 +:10475000280EFED0FEAF90D771B16D732FFABB1645 +:10476000BBD47ACCECCEB5620CE2ED11EC1ACEFEE5 +:10477000127EB7848F10D200BD0AE67D5A07D7A3F8 +:10478000EA2A8C649F54220CF35A59ABF5E39373D5 +:104790004753F454EEEE10A8DC2D97BB6B046E5714 +:1047A000CBF275A98CE3928327A7D175529FA337CB +:1047B0003300DFA515E5E7881E657D43195785C4DD +:1047C000F58D0D29EFE9B0DDA5DF17586C1A8D4B7B +:1047D000A5472DA951C3551E5D909ED5A743F9BD90 +:1047E000B4419DFFF3D1F2BE9EC7F2909FDE182D1B +:1047F000889F1807E13FA5BC7702EF815DD23A0F91 +:10480000227DD6EABB0A70DFBBA47511AC94437E4F +:104810001DDFAFB8BEA201CEC3EF1B750E33DEA7FE +:10482000F5AD14886E97B000BD276DB03EC1DAA11A +:1048300070BF2277C39CF5E40F3D2898516F281371 +:104840001D22DE836F1CC68F7E51E68313AC2F1FA3 +:10485000F1CA46228575CA9E3F82F699ECB796F951 +:10486000308E943D4E20BFC49D80714311A622C955 +:104870009139B03784419AAD6DAF20F93E566FE65D +:10488000EF62DA58A0BC70FC331370BE1075B20B27 +:10489000937BE8FDBD396D9B2FA25CCCCC70143DA1 +:1048A00005F83D19C6FB7FF275C1BF16DAA9CB3FEB +:1048B00046F2D30AE481FDD6D96439DAA1F6CF5A9B +:1048C00051AE21C1CCCAA77E1394F832D015EDC3E6 +:1048D0005DA5A49F58E57E9F2D94B8DDFCA07C2E9D +:1048E0008DF9D6E2F9FABED18CF295F41BFBABCA76 +:1048F0000431285E50371AE679A5AD4F75DEE95BC5 +:104900006CBF01E92CB87D18BE2A5E394D7B2D8A1B +:10491000EE771DCCB0DEE8FE94D6A83EB7A4338770 +:1049200007DDBB53CB9FD9F6A4A07B771941F7EEE7 +:10493000F282EEDDA9EFF92D744E09BA77A7BEE732 +:1049400067B0CD54D50F93E6A9E0889CBB55F523FD +:10495000EDCBD5E7AE8EFFBC4248C777067D7D2EF6 +:10496000988766E08DE298C17D242F0A2A431A3E7B +:104970002ECC846973A1A10BE9A43991DBE786E30E +:104980000FDBBAA01DE388978CE86FFC89E02F4508 +:10499000FBC4289F5319FD1853ED33AF1570BE5259 +:1049A000D2DBF25CB3F3617DF2F74A49FC1DE0DE35 +:1049B000D1B83E467C6C03F9E6557EAF78AC6C47C7 +:1049C00028ED3C5F5832350FBECF7FCC3183E2EC0F +:1049D0001DFC7EF04E3D8FA7F85EE5E75BF33BFAEA +:1049E000348E00FE3E99C7F590679CA5141FA9EB75 +:1049F000845D16F9A9EDAC1EEF65D4757647E17EAE +:104A000056E03CAB47BFC960BEBCCF89FDE168AF93 +:104A1000FFAC3D743C6D6D9E9EF8E3982CD7AB1EA9 +:104A2000D672BB913966E1B971455E57EDE7E3ABEC +:104A30005AA8E7E760311A1D426E839C3EAB96C3CD +:104A40000EF57E708B7F3DCA0E90DFAA7A4B174C15 +:104A500027BBB712E436F231C87375797213C917E0 +:104A600090E7AA7C77DE803CCFBF0EDF9D766A425E +:104A70008EF3708148F378DA3595E6FF199847F49C +:104A8000A73D3364DEF87CDE6CBE5EC6B50F58B75A +:104A9000E07ABF2EE0EBF6F230F2FA7D795D770A2C +:104AA000BD45284CDDCE70A2DB254663099E7B38D0 +:104AB00096F26513C6E1AA7E2ED03DFD7FEB3E6ED9 +:104AC00041FD5FBFFFA805FD61EEF6A316B04D598D +:104AD000AD4E5A8B7A3CD0851DF59EBA8E2EC27F84 +:104AE00065FBB86ECC5FD921D0FB3DEE0317A7D391 +:104AF00038595F13C60B770E83D78FF2B8FEBE37D7 +:104B00004FE27E3017F489FBFD0183DF2F201D80EB +:104B10005C42BC5E17F0E535B673A3B122941EF576 +:104B20006FF27C1FD9A867E8AFAF85EF711CC75241 +:104B30008EE98D4847FB05B2B5DDED27174660FBD2 +:104B4000F53A86FA8582DF1729BD1FE2F83FA8D61D +:104B5000A1A78035566B69BE3FA8D7523BDAFB74DC +:104B6000042F5EC1CF551CAEFEA82909DAFDA05660 +:104B7000A07B0C53EFFBF3318417AFE0FA5A303DC2 +:104B80002BF41A4C9FC1F43B844E6BBE199D1EC979 +:104B900093EFD5E4B102DCE761DDA759917E1EE118 +:104BA000F7E32BAE1DD6A17F33BDC96C7F02E03188 +:104BB0005AFF7A0BCA89C3BCBCB07687C0E58D7436 +:104BC00037F26152B39EA1BDFB7E1E974BEFE37A95 +:104BD000C5E3D0FA058CAF31B1371DE5529A1C4FB1 +:104BE0007A45C72AF6535C90CB9B31AFD954EF96E8 +:104BF00037E571BD43918340E6AEFDE4976D4FC448 +:104C00007B142FCBE74153E5F6B232FAA7CF85F4F8 +:104C1000AA4C2F67643C14F8B24CFF6CDBCF681FC2 +:104C20009F2DC759663674D179CC3C83EB5394875A +:104C3000B352DFABC57DAE39FDED7C3A678D3725CC +:104C400026E2FBC9FC7778D2A7DBD660DC2F379C45 +:104C5000D631ECE053741E382C6BBC35549C434960 +:104C6000DD57257A8FB0EE6A3AA50A3CF7D0397D38 +:104C70001FD90117A7139F5CB5A9DE2DFC54C67B75 +:104C80008CF23E5D27F7F3809C168B8B06EB29F3A5 +:104C9000809E651C6F58D62E5AAF35AB5821A9752A +:104CA000EC29FECE66ED4901DFBD58A473E84C3017 +:104CB000DFEF8D60251F8BFC1D245736C64D8C748D +:104CC0002FFB84D74C70AFD746F029AF44E9AD61D4 +:104CD000CE887C6867E1114F16CEDBE1945627DE63 +:104CE00057BCF08E4EA66B33BF2F2ED3DAE54E2D78 +:104CF00033629CEB00E8E3C220FEF75C4DA4FBDDD1 +:104D0000BFC3FEA09F950DBF217967AFB9381DEDD8 +:104D1000A2C2DA334D08BB1BFE3C1DF5890F61FFB3 +:104D200020BD1EF47B9B8072E424BDD35D79358663 +:104D3000DA7959D33F1DF9CBF7A640F76F3EECB8AF +:104D4000A8B7F2FD89DC73782F1CFDF2B3F2A3B98A +:104D50001CE92CD4D0FA3A24D53BEBDDA3FF2B0A77 +:104D6000D7C3D820FD7A0A7EDFA365C8BF9B4AFB64 +:104D7000A3CC21E4EF69F4DF65F371B0ECA1E51594 +:104D80007A5F169E93AC90E938B8BC3C7FC03FA1D7 +:104D900073CAEFEB0801FEA12AC6DF3F05BBA72BB4 +:104DA0001CF8B8AA732AF967AA3CC20DFD33C3D117 +:104DB000E1D74DEB18F7CF2830DA8D817E4DB41B4B +:104DC00099AA7F1F7F072B25F386F774DC7D891452 +:104DD000CFAF6B6614EF5A797534A5E75FDF2021FA +:104DE000FF18C3FB5BE97E6BB686EC8C953EB5FE87 +:104DF00033A580CB8529057CDE5CF9602FE5B00109 +:104E00007B09ECA27BF3B95D147588A9ECA5E07C65 +:104E1000B2978CF23D1D1013AE5742E07D474169B9 +:104E20000D7E97CA5A88CED93BFCFE72F038D7E483 +:104E3000733E55F87A31F235D26F07E7EBE076E74B +:104E40001594AC413EDA384C7CAB5CE6FB956D8C3E +:104E5000E6CBDD1643F3F4056B7396025D7E0178B5 +:104E6000E03DD20B4E6744347C7FC1E58CC0F33DFE +:104E70008A1CA86B0BA7EF3666CE8BC573A3CD48F3 +:104E8000F7D0DEF98EA9469CE77BDA38FF29FD7D55 +:104E9000D8B53816F96982AE5F6F87F2E4CE335128 +:104EA000A8F74D787D7E2CF2E17078FEFD1819CFC1 +:104EB00086C4121E9787BD70A26C4F007EEE27BA83 +:104EC000E89DFA871A18D16FF7ABFF56877C7CBE36 +:104ED00033C28CFBE6170723E8BDCA0B6F1AE83D07 +:104EE0009A5AF97DD52F747D7348BF7C5D4BF722AC +:104EF000DD6FFE472BF2A3FB55039D3B7CA873C3DC +:104F000045DCF76A3B679CC377566B5FFADBF2C3FD +:104F1000CA8654D28B14F83FBC4627BEF37B5EE4AE +:104F200072E2A18E7F217DF7A16B970BF07CCA17EF +:104F300007FFC744946BEEB72E4F4479E6FEC5E5F4 +:104F40008958EE7E2DC2134A5FB95EC0FD3ECA7E0F +:104F500099F6AEA8F20FAD90E9236D5D0BBD073D4C +:104F6000E1E4027BE0BB0F13B2344EAC3FE1B76526 +:104F7000B1F7057CB7AE57A438E3F8936511D501B6 +:104F800074794F814EF12F7E23BF0E93DFC719F046 +:104F9000E3F4F2777F36F68AFC7DA31A81EEA183D3 +:104FA000FE32E45E1AADFF8A587ADF8889CE3BC7AD +:104FB0008C47388BDE05623EE3D1CC003D6971AF92 +:104FC000A6CB007454D169E822FDBE573C43B0AC77 +:104FD0003FDD73F1D3C83421847F26E7D43494E3D2 +:104FE000C17E1AF84522DE8ABE55E971A520FEC1B0 +:104FF000FE9BA51577907F28D87F93D62B6A668F66 +:10500000C7F7DFE93A2F8CF76923F28BA287E2FA20 +:105010001D08C1FF6BC67039A6F0D5BA5E1EFF5DD4 +:10502000D75B6ACC84B456E6AB03B09DFAA0FD759D +:105030009DF377A31F61DDB545116360BED6BD3B0F +:105040008F3D81FC6F2E3566E177D7EE302ECC1F79 +:10505000A497E0FEA68CE1F272404F1866DFCB9772 +:10506000F1FA5BED7F3963E4F36CFF87EF7F6087D4 +:105070008F1DC3EDF025DC4FC2EDF0E07D4391C7FD +:105080004ABB2E799D87CA63FE7748C05E2679ECBD +:105090001A2351BDE4CEB9B16447BFBB2056320DCF +:1050A0006D3F43B46B62F287B6AFE8716E9FE3A8C1 +:1050B00011ED1C8796FB491708F4BE99A2F7B99D1C +:1050C00002E9E3EE4A9D1FEB2978F52EE07ED585B7 +:1050D0000E9D3F4C18D40F15FD71A0DC2E50B9A2C7 +:1050E0004F2A7A63AF93FB71178CE7E5B786B91641 +:1050F000E17C7DD81546F91326F17CC69C479300C8 +:105100005EF43D8111FFCBFAA442A7C1FAE6A5CE19 +:105110008C1BBED7B34DA64F85CF5283F843D9BF62 +:105120009AF339DDD7E1FE1D8BFBF77FAAF4F2E09D +:105130007661FF7E08F16F461D12BE1FFF5BD1191D +:10514000CA3EFF4AD60BFE5E59BFDE232588AF72EA +:105150004E76B87DB54ED66F862B6FCEFF7AFCBCEF +:10516000471EDFDF8A9F778EF9BF439F1DD00BF567 +:10517000A1C7794741C94FC6C0BC866B3D749E73B9 +:10518000B8F7CD1E95F555B07355747C3445AF41D5 +:10519000BBC85DC3FD03CDD1D2AFC97E39AEA5F783 +:1051A000571E92EF733E78D54C692DEAC9902ED9DF +:1051B0007B92DED95D52A3C6BF197DB7F8FDAA3434 +:1051C0008AEB57B132F22B5575469BF1BC7F737C4D +:1051D000FB31E42BDF6EADB43BB0FEC6D1727D2354 +:1051E000F7B7D544D3DF8F61417A40952758DF5711 +:1051F000EB0553643FD170FAC12FBAC3B85CE9D153 +:10520000129FD739F9DF55D07772B9E06E0823BF06 +:1052100009DA6B88D7670D821FDF3D5F29D7FB4C0A +:10522000EC25FF13C5D3A0CAB9CEA72C0EB2DFD48C +:10523000F1A395BB7E4B7233388E1473408E0B0DE9 +:10524000C48D26D2799095604FE29FBC724BD25D9F +:1052500038FF801FF393DC71A8FC30977A3E22FB65 +:1052600073C9EB3CFE33247ED43C93C78FF0DD95AD +:10527000107EC8A5238F1DC5BFA374B3B8515DC7E9 +:1052800049BA473244FF08D23BAE8D51FB19478AD9 +:10529000DC8F3BB25330A37F6AA43C8F7FB7319C35 +:1052A000F4EAE97FA88E4579A0ACD3F9B97C5ECF4A +:1052B0007F70A504BF9BF807D11C06E3FAC507F56C +:1052C000BF49E2B06494F0BBFA08B463CEFF6175E5 +:1052D00004CEEB2F20C5BF2FF1DA6931A43FD22BCA +:1052E000CB2DD80FA30BC8BF2CFBA545D80F230788 +:1052F000FD39C1DF6D97BF6B063385FC98AFF3F8BE +:105300007E73826B26C1CFA633FE1EA683FCCEFF22 +:1053100002748DFEA23C182CC69F7F1ACED661BCAB +:10532000A839DEF536F1D1B31A09F908BEA73893CA +:105330006FBF44FB234E19C6730AF4FC5D46EA0CAA +:10534000D66BB4BC8E0960C7623C09B05980F1E6E7 +:105350003C39AE5310CE446CFF499D6B13BE97F998 +:1053600064B7685F4B4C608FC577BF83E34B828324 +:10537000C7C5953893121F1F2ECE24603F059CEEA3 +:10538000F8B91587807173259EC4BEE7A4205763C2 +:10539000B187CEF73F53C848AE7F8B719E25F92168 +:1053A000E24835C86324CFD571C54D39AF109DFE95 +:1053B000B5F1C43D63D8B71CFFE2F3138CF7F8E8EE +:1053C0004B16B2B7BEFAEF51B4CF765EA6FDF042EF +:1053D000BF41BE8FD0C7FDEC9D3AF22F5C00BB2DC4 +:1053E0003E609F3D9ACFDB3DD43995E8FF406F5931 +:1053F00004D63F2FE76F7C77C1FCD94897BD22BD0B +:10540000078BE7E3D00E3BD02B4E40BDE55B5C97AE +:10541000EF8F09B12EC6F0D0EF4CE4CB7C945FC087 +:10542000E963EA07DCFE72D7F3388A59960BEE720D +:105430003DC9C163291641F19F5B43C5595EEFA782 +:105440007DA36A8540F71CBE719CA5A35BDEB78275 +:10545000FCD3E5D3496E0EE7B70E889BABCAB715F0 +:105460000C9C8723FF75548199C61DE3292CC1B379 +:1054700087CAF8BFC575B8736C083AFB16DB5F695D +:10548000FF6EDB9F92F7DDB6BFE63B6E7F6DDE778A +:105490001BE7DEF11DE37FF53B6EFFCC773C3FAFB2 +:1054A000E5FFFF73000370709C3FF85C4070BCDF49 +:1054B00070FC3E1F966D1036F777416A8C7AB542C4 +:1054C00000512D46EFA27708664DE271B08D65461A +:1054D000FF0E61F07C80325F4B0BB91D61CEBFE8DF +:1054E0008B85794E75F496C5A29F6C127F87FD82DD +:1054F000FCCE2A13CDF4CE18D44CC0FBF1CD61A163 +:10550000E3AA61727BC3ED23CF1796DC31369EFE92 +:105510006C43C8FB1D2FC8FE47730723BF2413A588 +:105520008479D4AF9480FAD088233C3FAA8B397613 +:10553000105E52DA3CB207A534C46F8B1CEF8D9914 +:10554000999D86FEE818D00B311EF814C605298EE9 +:1055500065A67A4A7F1F8CE5FD6DD13181EE5BE552 +:10556000F2F34CACF9A02A9EF78EAEEBE36502C5D0 +:10557000F39623FEBFD274E5EF4C938918E637FF0C +:105580008099E28C2726BD487F775689EFAD31F3AD +:105590002A87D16E063CD61C1C47F4BBE4D0A4F786 +:1055A000F1E93377A6680F754F51F1179C96FD1DF1 +:1055B0008ABF40896BFD5EF6937C88FE17BA1F2276 +:1055C00051EA1DABF9B6F727EFD810FCBF45E0FE56 +:1055D00021DFAFB87F689CDE9E11786E72B33CAF5E +:1055E000CBBA78DC42F1F7EC93C733EE116D97013B +:1055F000F6D2714D63F4B8CF8F6B4A09C7B4C0E1DE +:10560000D7E07DF0C5D5FB35CAFA85A2A3D6B1B2E5 +:105610001FA3A79FE27AFF1214E7FF602C3FBF3061 +:10562000AF90E3F101D82408AFC9121B517D1C7162 +:105630008B591B2A9E54057631E2B9AC99E3ADCC67 +:105640007755973415FB3973B4BF09D3A29AB4A91F +:10565000E46FAFBDD884FA9BFBDAE563B793BF4C28 +:105660002FA13D714F9FDAEFB60AA3A5F18427FD64 +:105670009D5ADF0C91ECE3713344A29F98AA30B29B +:105680005F63744C6B42782ED78B8ACAE3A622CC18 +:105690001644933E58D42345DF973FE8078B995132 +:1056A0001F8FF374B3F8AAE24FBB35CCF11AAEE703 +:1056B0005F1B5F5DF9CEBB74AE541997322F4A9CC5 +:1056C00074B8F8AA72CEC15D7E45752EC32DF64F13 +:1056D00047FFE3B88367F4F2394B33FE1D6125FEC3 +:1056E0003AEEF58B147755E2AC6ECF45D2ABE13B89 +:1056F0003D7E3F0E963F2106DF17E2F1D757F19E20 +:10570000941EEFFF99E9BED41BF2FDC54E183FE68B +:10571000BFE9CDA1B4CB6BA7F490B7985277E7451A +:105720008AD77E38561DEF53E27997B4CE3363D5CE +:10573000E723090E8EF769C3B9BFC6DDA3A3BF97E0 +:10574000E17EC748F2BBA47319DDEBFAF2A46B2427 +:10575000E25D87F1B600BA38EFB087E13B61E79DC3 +:10576000F6308CB38DEB3EA7C7F32F7562AF1EFDED +:10577000618071121E4D741FB8C8CFF77696D0DFC6 +:10578000E3BA695CACE36F1317FB9FE541012100AD +:10579000800000001F8B08000000000000FFB5170C +:1057A0005D4C5367F47CB7B7E596DF0B2A3F227256 +:1057B000C16298A2DCC240A7311674AC135C8A4A5D +:1057C0000201B5662E92092DD9CCC2CBD23A8901FD +:1057D000DDC3B2B864F3A92683E8B687FA93AD6E49 +:1057E000550B0B84252EE2C39C71C9520D3333BA7D +:1057F0008162DCD85CD839DFBDB5BDD8BD2CDAA458 +:10580000393D3FDF39DFF9FF0A003007DAE756B9E3 +:1058100006E74CF8A5CFC6FF0F3DA44F8CE3DDBDD6 +:105820004BEB2617C4F1BB3EC9356903F85D9CCE2E +:10583000942B00F687CE5A1C041FCFAC7621FCEDCA +:10584000C2DFB54A3A80F7D24C2D20EEFD66A6960F +:10585000F8DEAFD27A02E94FDB7BD78E975E047019 +:1058600096416B10F9552EC17182E0B8C3FA4645D6 +:105870005C6EC02538E9FC80AD349BE8C75CA5D9D7 +:105880007B13F4F539456700E939AFDAAC89F409DF +:10589000BB19A006E90C5CC124F66B5581DBDF7FE8 +:1058A000D22A4F4A7A1CF1DB1DCC36E0DE50813C17 +:1058B000591EC7F7D38F02FC6E6622D40274E9B971 +:1058C000B86472D7AAA8AF3B3F6A8152A24C5B5C16 +:1058D000AB305EDF4BFDAC1260F8FCBEE268051732 +:1058E000952017A04D3F37E0DC5B9CB110C07F3D99 +:1058F00005CA98461391DF4A3F148E2A22DA69A717 +:105900005F78E5B6FCF7274CAB11BACDFE68C2BD97 +:10591000DA9D82C39AC9ED2E6DCE207931CE2F212A +:10592000A5D34BB7AD22CC5128E413F417C25A02C9 +:10593000D2A8AD366EEF06047EB0A17C9B5388A43E +:10594000A09DD6704A04506F955304DF8B087BCD21 +:105950008112467CF126E72B6F3611BF4FAE2A0429 +:10596000F4E3E7CB16794109BFDF6434218EAAF353 +:10597000D3FE523CAF763195DC6AEF34F2F19341BD +:105980007EEED6E3B23334FC7221F75F36019ECB54 +:105990001D03388E7677F618CFED6E75DE61743F95 +:1059A000F8A07F33CA814D900789DE6B94A33A3B00 +:1059B0008DF11F007026D64337D5410D41C6E1E772 +:1059C000E813D54515062A58113F37BF7E4674F9AE +:1059D000F9FA62F00CF117517D560DD828BF4D022F +:1059E0009401E1F5922D419F5F15B99E0F6501FC71 +:1059F00028D717DE3EC8307E7D8F5F915A506E4AA1 +:105A0000AE97CAD2E3B8F732D6531640F5F06C031E +:105A1000C5FB589881154D79F3F1BE28577DB16EBD +:105A20009CAD4EBCA7E6DF31CCF9443AD5819A0D46 +:105A30009A5F2061BCFC17586010ED55353D1C493C +:105A4000A3F8B9B2D53285ECD80EA523EE6D126B52 +:105A500018E12E3C40F80E1690F0E7F62B9D5B0007 +:105A6000ED54B7D8AF52DC5B3ACCAA1588DEDA40E9 +:105A7000F46B5950372912FFC47BA9C42F67AA556C +:105A800021BEB39EF88D5F4444AAE7AD14A56578A6 +:105A9000B7CB288D7DB3C1EA0E501F5537A311F443 +:105AA0006F47873540FEB5849BCD90CEEB41A0BEBD +:105AB0007B5BCFEDB7458F32A3489F095767915F56 +:105AC0000BCCD316156135EA2EC84178E1BE05B07E +:105AD0001FBCE2B44546B9733E4CAC05E04B9FC4D5 +:105AE00061C827836339C0D7BE7C0EC33E85D32FE0 +:105AF000FACA398CF8540E477C6B35A8CA3C9E957F +:105B0000E1FB02DD27A75970259B6F7EBD3E62F940 +:105B1000AA0BEF29A67B3EBAEA2E9693C8C7205A55 +:105B20002C14D66AFDC930675EE7C306B2E381E88C +:105B3000613AA760BE610D46218430EFBFEB6FAACA +:105B4000529B6FD902B893F167F4FA048722D03CD4 +:105B50007A4BD2FA7F78C55F3C9E5248B9B21EF3A9 +:105B6000E61937410AD28FD46B737FBE9EEB184F74 +:105B7000C0B8DDC078129CCF6FB5F8CB281FAD74CC +:105B80008F24E7A7F4FAC40A30BB32B49C32BC4F6E +:105B9000476C0E6020B2308F1D211649C53EDF19BB +:105BA000DE744724D8C3E096717E3CD77DD8E646A4 +:105BB000A589F3B6338D26F9135C4AD5E22C593406 +:105BC000D86FD5F65A935D8B730C6EB56B75719467 +:105BD0009A05EBFBE879163888FDE7A918BB4E73E8 +:105BE0002CCF01D08BC3C7939F1E31D13C0F99EFAF +:105BF0003D99E3D81F798A0C1D3994370C26F6415C +:105C0000817E0724C06D9463911C616E25CA2D1995 +:105C10009F257D9FD8156E2F77579001BA5004FEAF +:105C200083345F462D50771AED779D637090FA3B71 +:105C3000E00205F7FDE8F11B874F21DD738EC9B443 +:105C40008EBA8357F99EEF162778FF78C2772DBC5E +:105C50001E8337357A88390249F23A40FB1DED6ED2 +:105C6000467F686E741F300552D06EC339ADAFBD2C +:105C70000E4B40417CACE81D91F09DE719E4D11C2E +:105C8000532616A511FF80190225DCAFA6BA84FDA4 +:105C9000845F85FC8EEDCFD8FEF1C0F45821D56B22 +:105CA0002753230ADF3FB78CFB052F921BDF2FED15 +:105CB000A16133CD1BDC4306B9DD8E863B343F71D9 +:105CC000CF18E94B0EDFE7F98028AF53DC2F067EB3 +:105CD0008D3D63E16D2C095809157338CF3655CACF +:105CE0003CDFAD6EC6DC181F497075919F7091C97D +:105CF000346FE7C7ABD1AEF541A39F412FE677C81C +:105D0000A2D5C7D03A16F0A37C23A294F7A18B7B2F +:105D1000FC0CFD1CAA62AA40F120218CC7163D3E56 +:105D20002F801F6E4BFCA9706CAE1AE035AC612B56 +:105D3000D653A35E0F00016EA7F9E3D408BD238EEE +:105D40009A83F92A7F97F8F97D6755E0FCD414E827 +:105D500049D6AF6BEC75B36A0DC93DF3F7D32E7B13 +:105D600092F7D347F876223B7BED4C24BF30BE2B15 +:105D7000A9BFEF155DCB1C41F481C9B58FCE755914 +:105D800022ABA9BE1F98DC1C8FF191EEA1FD828B86 +:105D9000EF16F591008CCF8723E567CC949776A218 +:105DA000C7EE5B1297E3B8E969FCA10ACFDAEFA16D +:105DB000CA9AA7FD7E86FA17ABCF577F6EB2BC1D7D +:105DC000A2F997A47E7ED2E71FC01299F7CB933831 +:105DD00083B68764E0753CAAEFF57EA6FC487BC8D5 +:105DE000FF9D190695F85CEDCFD0F47FA6EB8BC133 +:105DF000511DF69B35B9F9F627F439FC8BC9718A28 +:105E0000EEBDF2A4004A82DFAB82A9A024F85D199E +:105E1000CA31E0F6C862837CF578A9815F33B1C2EC +:105E2000C05F73BDCA80BF145D67905FFF6BBD012B +:105E3000DF30BDC520BFF1CF6D063CD6BF7558B968 +:105E400089E73649AF1BE40A3B8D7E15F518FD2A1C +:105E5000EE35FA15D35BE237FAB7ACDFE85F4EF602 +:105E6000835C85DEA1FFFC9149FB60203CC3F334D9 +:105E7000359D02133447C4A8B61FC266BE17A6F0EC +:105E8000FFE2A2843C2CA7D73FDA19092FB3D2B97D +:105E90000F9D362BBDDB2E510D603EFE05D7762EB5 +:105EA00017E00E00000000000000000000000000ED +:105EB0001F8B08000000000000FFE3E36660F8515C +:105EC0000FC1D3B81818367221F84301B7334368AD +:105ED0003E16060601207EC7C8C0F09E91043338E6 +:105EE00010EC7E20BB0A88277150CF7D43112FE52F +:105EF000A19F5D5FA0763D1518787F83B083100366 +:105F0000839B300383B40884BF5F0455DE5108C10E +:105F10007E2E41995D9F81FA018DEBBB318003009C +:105F200000000000000000001F8B080000000000BF +:105F300000FFE57D0B7C54D5B5F73E731E33939976 +:105F40004C260F4242004F08202A842140088838FE +:105F50000990068D9A080888CA000142483211A9A2 +:105F6000975E6D672214D16A1B2D6DA397DA0141EC +:105F7000A3450D18E840031D4C41BC5A8D0A4A5BED +:105F8000B541313C0A4978E8C5D65BEF5E6BEF332B +:105F900099736642A2B6DFFDBEDF177FFE36FBECCB +:105FA00073F65E7BADFF5A7BEDB51F2359C613D345 +:105FB00015847C057FD71372482484F4EB4E3B0B89 +:105FC000683A8E107F8E39B0552024B4EFEFED245F +:105FD0008590B34DB355732621FBC79843D7D3F2B1 +:105FE000B381FC8099964FDD79C421D17CD54E5187 +:105FF0008272D33E2B7EDFB1510840DE6B6EFDF125 +:10600000B534DFB553249B69D5246437915442DA03 +:106010002D84FDA9F1985F6A65D9AA4DFBEF82F640 +:10602000CA836662A5DFB737896EC8AFDC2A040869 +:106030006DAF6AF783CA005ADFB280D06855697EB7 +:10604000EB638A1A4FC803FBFEEC68B31372DA677E +:1060500021AA82FD286F1C494845607BE100FA7D3A +:10606000C536C165A2F5576C3CD701F45534C9C398 +:10607000445ADF8A061B5147B0B6BF22D05ECB0719 +:10608000D8DE4E7928B457FEE53D0A11A19FB21B18 +:10609000BEABA27440BFB5764FFBEAB13D8D9F55B4 +:1060A000CFD1F6E87BD52F0A2EE862B58978808EAD +:1060B0008EDDD6B94FDBA17FB5CAF0F8C87E2CDCE7 +:1060C00005FDA8086C520AED40DF2665E9C8EEFA26 +:1060D0005634FC879EBEFAACFE9E8872637ADA471D +:1060E000593ABC3B5F4188BB91D64BA480523AAA37 +:1060F000FBF907422221E3A17E91A896EEFAA9E4DA +:106100001107FE23F49F940FFEBDF181AD99DD725E +:106110005BE9049975CBEDBC93CB51EACA8DAC5FBA +:106120004B7F0CF2A0F4D4F99C983EEE4BC37483E1 +:106130004F45BEFDDC3702D37A9F0B9F3FE9CBC3AF +:1061400074A3CF8DE953BE224C03BE127C6FB36F94 +:106150002EA65B7C1E7CFE8CAF1CD3065F0D3E7FA3 +:10616000DEB71AD36D3E3F3E7FD1B71ED3465F1DCB +:10617000A63B405E346DF205F0BD5DBE064C83BEAD +:10618000467CBEC717C4F411CE47C764922F513E58 +:1061900038DCC449C54E928ADDF932CD2795B07CF2 +:1061A000EA1DFE7C85E6533D344FF932A032946FF0 +:1061B000A6F90135AC7CF0FDA4C042F383FDAC7CB4 +:1061C000C823EE022BCD0FA963E5C337FA0BE268B3 +:1061D0007E7880955FBD2D5460A3F9AB1B5979760D +:1061E00033996AA7F9EC10CBE7BCE19E1A4FF3395B +:1061F000AD2C9FFB817FAA83E673DBD8F793CE0497 +:1062000044D51E2D871DB2BA9850596DF4CF704BEE +:1062100013695E51EF212ECA1FFFAD6E299DF24317 +:10622000766379C83F1FCB9B143796BFE32FC3FC1F +:106230002ED983E5C7FD552CAF78B0FC73FFBD9810 +:106240000FCA7E2CB7D4FA585EF163F980DAF5589C +:10625000FF1E3980E5236B1FC3F23D4A00CB1F5F51 +:10626000FBA47B1ACDAF113C3F073CD2B49C640128 +:106270009E1AD34A289ED609642EE0F707003A8A70 +:10628000CB75E90AEAE18E3FE43E0DFA8B7F299057 +:106290005FFACCC399F8FDAFB01E99D623F65E4FD6 +:1062A000CE9B79BA7A72DE2CD7EA6980F7D658FB92 +:1062B00056CF8E3727E9E979B342AB673BD213DF7C +:1062C000B77EE5BC35594FCF5B955A3D7B909EC458 +:1062D000BED1D37444CF9FA62361FEB4203DFDFA06 +:1062E00046CFB8F7F4FC19F75E983F6F603DE97D43 +:1062F000ABA7E93D3D7F9ADE0BF3E708F66B50DF75 +:10630000FA35EE7D3D7FC6BD1FE6CF47484F66DFBD +:10631000EAD9F5A19E3FBB3E0CF3E704D633AC6F40 +:10632000FDCAFD48CF9FDC8FC2FCE9C27AAEEA5BB2 +:106330003DBB3ED2F367D74761FE7C81F58CEA5BBB +:10634000BF72FFA2E74FEE5FC2FC310950CF98BE8B +:10635000D113FC54CF9FE0A761FED8B09EF17DA37E +:1063600027AF5DCF9FBCF6307F520490FBC4BED5F3 +:10637000136CD7F327D81EE6CF20ACE7BABEF52BB7 +:10638000EF849E3F7927C2FC198EFDCAA77A0FF4CD +:10639000105A4F7CCFF5EC39ABE7CF9EB361FE8C42 +:1063A000C67AA6D37AB27AAF6752879E3F933AC233 +:1063B000FCC9C37A66F4AD9E3D1D7AFEECE908F394 +:1063C000271FF97353DFFA35A953CF9F499D8C3F9F +:1063D000630FD74C75D0723A16BA44FAC9B567DC68 +:1063E0006E81E64527CB8B4E1701BF44D4FC0DD2FE +:1063F000EA16E9F7F66D89390F9348BFA3A014FA9E +:10640000154FBDB148BF23212F4EE7E724BA93743F +:10641000F9E4A201BAF7FB950CD195F79F7BB5AED5 +:106420003CDD93A3CB67944FD2BD3FA8A64097BF56 +:1064300062F50DBAF733FDB7EAF259EB6FD7BD3FFE +:10644000AC6E91AEFCCAFA0A5DF9558195BAFC357D +:106450000DFFAE7B7F54E303BAF2D1C18775E563CC +:10646000428FEBF2630F3DA97B7F7CEB665DF98485 +:10647000A3CFEBCA27B6EDD0E5AF3DB9C7E0E7D96A +:106480009DEDD7F0BC08B827CCEF4F57D0DF0BC538 +:106490002B985706D8D18FDF1FBF543D4EE5ABBCBC +:1064A000B2584DA1F20599123AAEE70F28BFB28D4E +:1064B0003EBF7792E74A277D7EAFE219ED8CE19FE0 +:1064C000523C08240D52D504A9B1FC4199E1B120F8 +:1064D000E3CBE1C7E8F75E53D7F0449AEF2FE6D756 +:1064E000035E9E124C88D33891D4C07B716682F3D0 +:1064F000820733739FF647E075FD20AA874277BD78 +:10650000EB654F1AF8199B6BDFF6831FB26E10ED27 +:10651000D700429E16DE0EF987D2EF072D4DF3D03D +:10652000FACC0AF5D323DB5768FB23B1FD0668FFDD +:10653000C51EDA370FC9D3B56F195CAE6BDFA2D0B9 +:10654000F69DD41FA8FD236F9F0A6112212F0B7F98 +:10655000C4F6CD83CBB1FD07153A5F896C3F2EDCC5 +:106560007E10F4771FB43F3E46FF874CD2F77F7012 +:1065700085BEFF0AEBFF2BB5C778FB71D8FF16E18C +:1065800018EBFFE00AD67F33AB37DCBE23CCFF43EA +:10659000D0FF377BEA7FD6647DFFAFA8D4F7DFCC8E +:1065A000DA7FA7F6146FDF8EEDBF2B9C62FDBFA2D2 +:1065B00012DB57CC1E17E047C988AB09D0F6C9409B +:1065C0006A98FA035C683B908E48A2A026E4516169 +:1065D00008D2716F1CC3DBE771146F686FFCF89C05 +:1065E00004A865CBA5F32E8EF515DBF215B04B583C +:1065F0004EE72B4B38A9654111F14D369803C3285E +:10660000BD1D41D10FF9B20DD705C0FE79CD644152 +:10661000097C2791103CFFF467A33647F6CB982EF0 +:10662000A993DBDB22F42D3C8F2A20236A287DD31B +:106630000104E3BBF31FD37910A1F38B0FE83C8374 +:1066400050487E22B3F63EA2F325C8B7D1F9129482 +:1066500013528BDFD1EA0EA751FA4B38FD1F4B4C7A +:106660005F3FBE4308F8A97E7EFEBD31384F5DB066 +:10667000DA4699DE4DC7427FB22E4FFBE5073975EA +:10668000ED3607360BC85F15F8558AAA49C8E2F5FA +:106690001994D7DDEFBF4FC59E4E597F1B71CBFDBF +:1066A000E9FB77AE12063969BBB3DDE61C364EB89E +:1066B000334CA8D724C39447C8AD4D63645A03290B +:1066C00075CB1FB745B43BB3489F9F5DA2CF77C83A +:1066D0006ED944E9EA2815C8265AEF9CB9FA72AD7A +:1066E0001DBB2989C999B75792CAE89B03690E3C1B +:1066F00076A29CE73AD9B71A3DDEC5329DC2823CEC +:10670000FDFD08C8D59F82EFDDEE64FD36D23B5714 +:10671000B6B84B683FE72E1403806F23FD7FDA671E +:10672000739BB269BAFEA7323145F7C748FF3C8F69 +:10673000B13F8D328CC3F3CB8DCF196EDAB9FC3FEC +:10674000067CD0F404E083D27F9CE3A3DBAE327CF2 +:1067500078CD9E9B010F5D4F8804E5CAF1721BC77F +:10676000CB923A3D2E08F1C820C76573859C8723DC +:10677000703087E36059BD1E377712BF9C1E432ED1 +:10678000F3366CFA619A1ADDBF0F396EE63FB21F1D +:10679000F913DD4F26A7BBB89CEEACD197DFC6E559 +:1067A0007A2797EBDCFAC70E50F3416E570332E8B5 +:1067B000BBF73E4D9E6D3A797AB83C8D74DEC5E5E7 +:1067C00079D7F7983C8DF4B67179B6D55F90C990BA +:1067D000687A8DF42D581DD51F05E4B9D01F5B9E36 +:1067E000DE607EF2F188E7558D33928F47E8D98AD3 +:1067F00086525D7E79609EEEFD65F50B75E54BEA90 +:1068000096EBCA17AFBF5B975FE8FF9EEEFD05AB47 +:106810006B75E577D63CA42B9F5FFE982E3FCFF398 +:1068200084EEFD397337E9CA67973CA72B9F59B4AB +:106830005D972F75EFD6BD6FDA77D52D80CF378E68 +:106840008804FC89CF5C27302EF8994B76C13BC772 +:106850007D2AE2BADD3702D3933E17E2FEB42F0F52 +:10686000D38E608B1DC6093A2E2E2589D4CC9B6E03 +:10687000AE5D3F10C66982E3E916D3AC5AFF6442AD +:106880007E6D5291DFC5F50A098D254480C186D3FE +:10689000D1254694B7F5525E4F0D7F727479715BC6 +:1068A000ECE7DEC7175EE18C1177E9D65392017EE3 +:1068B0004F27F7BB8DE5950229897C4EC803A8D7E1 +:1068C000E7F8B85BA930FDAFDC915E401C900F0D7E +:1068D000AFB95C7B8D14E4FD0127593A3D5E567FCC +:1068E0008DCEBE1388CAF603BC8DD53D5FD170AD89 +:1068F000EEBB33FB45A4BB1A6CC54418164B5E3780 +:10690000811D0EB50C9E390AE874BF6182712AD8C8 +:106910000FFDC233BEA2E4E312C8AF04D393BEB9E5 +:1069200098B6FB3C981EF79563FAB1AF06D336DFF5 +:106930006A4C3FF2F931FDC0B71ED33FF9EA303D52 +:10694000EAABC7F43D5F00D3C3BE064CDFF135624E +:10695000DAEA0B62DAE17363AAE95D6FB83BC9C793 +:10696000E1D380BF1838EB786055EDFAC9DD383BCC +:106970006FBAAFD63FB09BCFC5F5668E87541D1E4C +:10698000BE806033E2AC97F27A99E3B0A7EF6397E9 +:106990007B37FF6BF036DEC4FCCC6F8AB76E3C658C +:1069A00018F094D51B9EFA89E3BBF134DEE4647ED3 +:1069B0000FC7D38FA01F31E61505E084F48BF0D705 +:1069C000DC3616A7E6EB09D45365716ADEF61AFACF +:1069D0006E2BFA758111306E9C1FF1B7E110873F65 +:1069E0007FD44C277D3DF7CF88939EF9EEC6F9CD35 +:1069F000D2001DBCC646975BE3185FAD265244E843 +:106A0000B8F6D0B0675C8B46625E2249F07DC05517 +:106A10001A1FA35EEA2B037F7BE3EB9AF8CFB3A1A7 +:106A2000BEF627FF9E0BE97813F397E35A44F4DB95 +:106A300049E86917F0373C2E995D6910DFEE1AA618 +:106A400038D16F08D8F5FCF3D37C6E37FF1EA23C1B +:106A50006AC571B72E0DF937F4F3E1E97DE05F6F98 +:106A6000F6BD377E2E0A0CF897F0B337FBD89B5D46 +:106A7000246EF5C520ED7FE7BE51390FAB60078767 +:106A8000B0795A0FFCD6D6A58CF47CFF6BE2B833F4 +:106A900055C371EB6042DBF988EBCBF9A62B1340B1 +:106AA0002EB41E9C1F74EDE47E7E2F723D9BA9AF19 +:106AB000CF6BAC2F4121C268DA6EBCA29004426A4F +:106AC00044CFA322CE6F5C6D7E881BECB3B9D6A8F1 +:106AD000306F3CFD6648851AF5F185F3879E76C0D8 +:106AE0003C6C659AC9793C861CB5B4AA31D3698FD0 +:106AF0009CAF04F5F9F375425123CEE7D48459A332 +:106B0000609C713A8F0F05BB9F86A956CFCA34C5CA +:106B1000799CDADDD30D59096CFE1760F6645B22AF +:106B2000DA9BD33E0BBEFFCFA6A7A77A347A0869BB +:106B3000229F58C09ED3B2AC9EDFEF511FA48B0A98 +:106B4000C43749B3FC39CC37ADF4FFAF8640BD1232 +:106B5000E6B57ABD8DA2DF3C1A9E6FD3B547BF5311 +:106B6000B5B557F8AE67BD9348BB867B2ABF57F9CA +:106B7000FAF08A06AB53EFC726EAF2DE60BA53E7B3 +:106B8000D7C23FC071AF1124C05F25875FA7645F84 +:106B90000F78DA0CC14398BF08ECBD2A4B9BE25139 +:106BA000515D5A019F8BF234FCAB73FE4CEDD4A9BE +:106BB000D765027A46BEA454E5F2A920E2CD444C42 +:106BC00034BF98BFBDA86945318C5BA74C6CFE50A3 +:106BD000464A1C303F2E2775B9104F3D4B4C45A0FF +:106BE0009F67C93B8EB111FA784E54B0D2C5EBF510 +:106BF0007E3C9DDFEBF2CBEAF5F9A5E4D6545807CD +:106C00005FBA41260101EC86BEFC98E8C47A9791F0 +:106C10009A75306EFF9CC7BB1639899441E9ABFA6F +:106C2000CD2F7317523A2E896CFCD5D67197273128 +:106C3000FA2B660514377DFF93A6B1B7510B44BFFD +:106C40000FAC83756D7F29716D25D1F2FBBAF41BF2 +:106C5000E9D5FC81A8F5644E474A83E00EC4B063D1 +:106C60008A24303DE3F6EE6AC9A98B83E4423E22D2 +:106C70000EF28DF194427478DA2C7A064BE3197E89 +:106C8000000F82D4A578BE4DFD6951F55F2DF5FB4F +:106C900027D63F90D69FABAB3FF79F4AFFD028FA4D +:106CA0000B62D55FF59B1776F9A93DA978E9670EC8 +:106CB00042C7C953525DAA8BCAB572EB0F1D6E9ABB +:106CC0009E94FC0EC0EBA98058144BDEABC3F27649 +:106CD000DB0588BBC13F69FDA79FFF11C6233EDFCF +:106CE0002A3B319ED6600E99A93E56372D2F26D9C4 +:106CF000983FC6F20F9E13211FD4E3AFE2D99FA5A0 +:106D0000C2FE0A8A141E5F0AA13F5BBDE5D3421C86 +:106D10009F4817EA91F13B68FF5212DABF854A4259 +:106D20007439A513E3045ECE176FD38FCE890EF8A6 +:106D3000571BCEDF8DEF9773FF74B9149FD26EA3EC +:106D4000FF9E4026803DD4F84102CC3F5DF3DC2F0E +:106D5000B28F517ACE6C79DD2144F049D3A3F38D03 +:106D60008B7FB547EDD9DE76503D8BF483B4F14A85 +:106D70000D72BFBA99A59572C8712DD5FBCA4DB2D7 +:106D8000CB4F1F57BEF0F4334F421CF38F66D73002 +:106D90005AFF8A170EBC3789E6576C97538A5937C2 +:106DA000EC426AB75CBCF4FFD539DD72A878F98093 +:106DB000A28E62CFEF4FEA96C78AEDFB15322A9A70 +:106DC0001F531BF72B6DF61872693C56087EC29A4A +:106DD000E7FE4B81F8E2A97D02E99F19839F9B0E94 +:106DE000A01F007C4239723985E56678DF4BE502E9 +:106DF000F65A9393B1FC466E4FA03E7524E2F9C556 +:106E00003DB4FDF23F995DD0FFF217EF71403F4E68 +:106E100048350CD7BFFC612AD8AF72D99FEAC49419 +:106E20003D2F7FEABB88B7656F7F3715E349C49D67 +:106E30006EC2B1C79F0EFD5BB27136F66F29F120AD +:106E4000EECA7F29960468FA99448AB6C7D08B0E99 +:106E5000AE17273653478CF6EF04CC1FC15EBF2315 +:106E6000E2BE2A42EE26A0FFDFE57DA11E02E63F3C +:106E7000B330391D904C5CAFA8B71989D72D0FB628 +:106E8000827C4E0F72F78775162F91FC9C1FC2579C +:106E9000B45EF1EDE9FD997C882AE5F2EFE8383F30 +:106EA000159EC3FBADB2DB9AADFB8E7C95D9DDFEA2 +:106EB0002ADE3EA53B0EC6E713A9B1FDD501B2A659 +:106EC000F7749C8EC057847E337DDFF210D36F4DF4 +:106ED000DF03A545507EF130D31FF80EC63F4A5759 +:106EE000A83F96EF9F25A03DA0F3E6587ABD45E662 +:106EF0007AAD2FD77042E996848408BC40FD49C81A +:106F00007F5C5F59BA817E17612FBDD09E23BA3E48 +:106F10004D6F9771FD3F05FA7F4DB7FE938D4CEF96 +:106F20007BF69FFC2C6E23079E7912F495EAA75FEF +:106F3000057D954BA0DF7FDDD6F2DEED544FFFDA05 +:106F4000A8E9A9DE7E1AF5B47CC778124B4FFF6A18 +:106F50007791987A4A9FC7D4537B1BE2F8FF94FD40 +:106F6000D4F89728EBF9A7D9C39EF868B4872F4ABD +:106F70002AF2D3680FE9DF61921B8D3F0D771ADE8D +:106F80002A7E5D7505D89D302E35DC8571A9E12EF0 +:106F90002A7EABE39FB1FCCF106BA274CDB7D44F68 +:106FA000817984A58BE0BC2B7F9688EBA6968B0419 +:106FB000F5BE80C8B86FF07D53CD78F043A7FCFDD7 +:106FC000B6B3F7527AE713BFCCD6E5EB64F4EBBF68 +:106FD000FCEAABC9B43FB773FECEA7ECBE89CA6367 +:106FE000AE2484E2289DF324E24F4882F8AC403E70 +:106FF0008EA0637EB93E0F7F5352BBEBE9EDFDAF30 +:107000003B0FF9A6E9DB3EB676F52EA443B179290C +:10701000124FA52057CA3FEF38213004ED529B5440 +:107020001231AF7A9CDB9DB7A7CD1C0FFE4BFE9CA7 +:1070300051090CE783717EEBE5F6EBBC5F4D00BBBD +:107040007EBE390BE7AFE70F2D8E8FB56FB285E3AC +:10705000EC005F57E9B40B7522C57D27E942FFC5F7 +:107060006FB792AD31D6FDBE2F9BF8E483CB8DFE7A +:1070700089546E73390EE7D14F137222E436EBA6B2 +:107080005392235A0EF0F771C43CEBDBF217700DEC +:10709000FC6DB1B61596C488D7FD84F36FCA2B5F1B +:1070A000E0FED569CDF912F0719A5DD4C5391ED4D0 +:1070B000F475241909744D7965F9A3E3298EBD8708 +:1070C0004417EC57F5369F533C31E6BB467E42FDF4 +:1070D000E0471E909DC8AF2372C912E0EB91D956CC +:1070E00002EB96EF2AAEAA58744E37B378C83C52DA +:1070F000F2D938E1FF3EFEE6CF890F15507E9CB7EE +:10710000B3FDC0D1F8637A7FDE29046A05C0A1C847 +:10711000F2294200E26485C4F3E86401F5FDFA480F +:10712000FB951F2C7D01F6D554370B4E132DAF96D2 +:10713000DA14C0B137B85D02FFFC4695B831DE20E5 +:10714000D58C9A1511D73A204BC8AF96BFDD7E2754 +:10715000F0F7C22C3301BADC23CF3960DCBFD03C5E +:1071600016F5A0A77EFDC147A64C93A01E82F8305D +:10717000E2A130C5A6CBCF9E4A06BAA8DCA698DB12 +:10718000EE71C590DF3285E1ACCFF6CDF2FF997D8F +:107190009B4CED1BC3B51C69DF462B51F6AD7F2C14 +:1071A000FBB6B256ED0FB858B937AB3FC875E56BB3 +:1071B0004BFAC5B26FAFFAD8FCFD35BE0FBB7320DA +:1071C000B56FA323ECDB406ADF62C46DD315CDFF3E +:1071D000ECC5BE59FE77F4EF55B06F31FA3B52D192 +:1071E000DBB7A2E65AB46F450345DD7EA82C85CFF8 +:1071F000E77AB46F0B7F361BF3B2CB16033FC05751 +:10720000B06FAF713B07ED809D5BA438B1FDBEDA76 +:10721000B9D2BEDAB9FF253E6B766EE520769E23A5 +:107220001A87CCCEADCC64766EE55E66E7560E630B +:1072300076CE68DF0AA2EC1BFBBE7A04FD1EE78B4C +:1072400099BFB8839617CF955D16FA7EB1AA9D5F58 +:10725000A8191F69EF162912F239CADEB9CEE13931 +:1072600090DEECDD5B60EF86A21D1B0A7A64C4C76A +:107270000D436DBAFD7247BE68FFF54BA02F7F101E +:10728000719EFDBE89CD8BF67DD13E16F46E37A77B +:10729000E75185C9B3C3E7477B3A7524D3F7AA43BF +:1072A00071384E543709ACBFF70B0115C681BF5D6D +:1072B000C2F9F29D7BD97C798E99F183FC9BC8CE73 +:1072C0005D50162C8CC0C3DC4B1518D79C2B110BB2 +:1072D000F8AF0B0EDD700AFCD60597D6A3BFBB0036 +:1072E0009EC3BE89ED6DEB3268BB772E1770DEA1B1 +:1072F000EDEF9817B6977A3F767E73EC7D1A533888 +:107300003D53EE1302B02FA7B77D102F72FD9B23C4 +:10731000B621BFC85B62CCF8A4F65E984F2EC69724 +:10732000AA55CC6F0EF389F24D15A2F944255DBC28 +:1073300030B59B2F77EEA4FD4DE9B9BF1ADFA2F758 +:10734000E1B8713EB380BFD7131F343E47F59FF3BA +:107350009DFAA9B89FC7C88F46CDCE5C4346815ED3 +:10736000BE6FF23C3A1E70F49F942F94CEDBE60D74 +:10737000D39DE7D9C5F97293E7D8B45415F8486A94 +:107380000067B7976F3F904AFB778B3B330742E626 +:10739000B3FFA67820FED062ED423BA8E130CDCC11 +:1073A00070F8578EC323039CD370BC090A4ED4AF28 +:1073B00090C1CEF17D645ECA67D05F6F908F4F142D +:1073C0009FA09F85DA780572A1FFBCA999C9C55B0A +:1073D00023A05C6E265D0781EFD529822B44AB2A62 +:1073E0000C6EFF21ECB77AD54A9F839E970BAECDEA +:1073F0008C1DF6F4D498389662E1183709468C9BB8 +:107400000BE0BD24D8B768C6F6EFFC1EB347463F75 +:10741000658AB9F508D033E5DF64B2091E06E87F56 +:10742000113830FA31517AF035F7FDA472FBFD2A9C +:10743000C8C10EFCEE52C01FF286D8F8A3957B257A +:10744000751AF24D9343908E2FE3981C60A9DFC804 +:10745000E75BB43CE01FDE6F1664F87E06954F32A2 +:107460002D9A6AFAE2A08677B31ACD2F8827A4470F +:10747000D80DB06F91EB96D5C1B7914F37ACA2EE56 +:10748000991ACD274D3E60072FC7AF28FD09EE8F13 +:10749000B97FEA9BEA4F9A59AF3FFBAC5DAF8F864D +:1074A00038DA5E01ED0A694ED4C50FF2CC6C5ED6B7 +:1074B00062F520CEBB5E935D9BD568FB7315970B81 +:1074C000CC5722CFEF4D850EC1BAB1D34A3ED1FA87 +:1074D0003D84E12C723C78D5EA41F9F554FF045E15 +:1074E0007F4FFE9896FF0EB407FB16557D7BC6F1C5 +:1074F000488B27F5D6AF6966663FBE69BFB476BED6 +:10750000EEBA8397B462FC4D5B7FD82C7A7E2EC393 +:10751000FCB848D0AD7350CA71FDF29F50FF58E5DA +:1075200032F543FC2844F9FCEAB6A7315E7DF6F952 +:10753000633783FEACF8AD482C549F3AB6C5931020 +:10754000DB07A2809F50D124E27A169142B93323FF +:10755000FC0C42D6307EBC148F76A7628739504C23 +:10756000BFAFD8F54936C4DD3A1E60F6CFFF3CC741 +:10757000A3BF2D1BD6FB2B24B68E6F94CFBD1C9FB3 +:107580006776DBE682FD161AD879D78AC639B23912 +:1075900022CE506596595C7BB70DF759FB9F13704F +:1075A0009F32D01779CE52DBFF79E63966972B826E +:1075B0007200CECD56346CEF803878C55133FAAFB7 +:1075C000DE86730AF8A7535F7A01FD236F50D4C596 +:1075D00041A3E28F0D62C80CF1B3A62AB403347F35 +:1075E0000CF38DB1E3F0BDC5C956BCB477979FB21B +:1075F00070C5CBCF3AF0DC6CEB5607C6211B2E1FB3 +:10760000FF8F8A37363E74D978E3698E8F5F99F59C +:10761000EB35A42119E39094BEDC9218718B30EE07 +:107620005FF8EC29580F3BB3E3AF4F01BD95FFB8AE +:10763000F0D47DE08FEDB33A61BCF63E7F04D71302 +:10764000B4EF76733DEF78EE595C87E9F8A3D9057E +:10765000B575EC3D3118D6233AB67F910A71DB55EA +:107660007BA7E33C6DD5CEA9FD498C798096026E4F +:10767000037D580732CAABA5A96530D07996CA1BDD +:107680005CB670FCB8B18AC5E3551E37DE167BBD0B +:107690002D2A4EDC34F396EB60FC6E925D2AE943B2 +:1076A000BCF83095E3E83EC86FDB439ABD8F29BF35 +:1076B000B3F00F2AA7F70DF2FBAC69C9AF9E84B2F5 +:1076C000A6E41EE3C5A13EF04D5BCFDB62767F6C86 +:1076D00006BDD9F16B8CCF83DCE85C8374BCF0D938 +:1076E0006088B39C94BBEEC2FD337BCDB82FAA62F9 +:1076F000EFFBA83F1D3BDFC6F532C2D7D53A48F8AD +:107700008FAD83F0399C774B3C8B3373FE431C5A0F +:1077100075E0731E6F6638D6E2D03DC59FD32D6CE1 +:107720003F91B6CE58B5E5CF0A31C4F5853C90D32C +:10773000B1CBAE8B6A7C70021F2644AEA7C48EF319 +:1077400087D7DDB8BC407EE07F85D74B687E20C4FC +:10775000CF03C2FB24863DE8D8C4D6613AE4D8FB07 +:107760000FB5F595148B414F037D5B57E98DFEAF47 +:10777000CB1F19269BE3A3F974E6CBD8767C824510 +:10778000F876FB612A85A8F57F0BACCF371D5360D7 +:10779000FEA18D635A7FCFF079F299E7453CEFB1B6 +:1077A000AEB105EDB8D15E5413161F34D23B83D36E +:1077B0005B1D64E3C4991DF1013BADE7CC2BBB110C +:1077C000CFD5DB8E297E5ADFC1869795B688FD52CC +:1077D000304E0422E83FF3E2FE6CB67EC4E6E5C616 +:1077E00076E6F076BCCDB1DBF16E3BA76B6785BF6B +:1077F0005161E7772EDFDE69C93D07EA3BDD2A13D9 +:10780000D8BF7FBA512C0AC4687F9245D6E2F24CA9 +:107810006FE87889E71DE3D9F946314941FF7A5588 +:107820007CDED18414481515E2146B6AD9FED2357A +:10783000DF77A581BCD724DE86EB6D7506FE3A5353 +:107840009CF910BF704E2B19077035DA9B44B7496D +:1078500047FFAAF8A2FE701E7F2DF7C788E4C2F387 +:1078600097A2A3B008FA233A4D4E6B8CF505D95E6A +:10787000423C117C919DFAF392E4CBB12AD4A3ED62 +:10788000A3A9B4B41EC442A71BB70A4B79ECDDFC14 +:10789000594EEC77E7363E4F7013D599CAF683C13F +:1078A000B8D1B923219B8CC60F899BE2D1C69F0B0F +:1078B000DBF6EF077BB4D641DC8954CF285755312E +:1078C0000BCE8D8EB1085980D3736FFE96D66B6D3B +:1078D0001671FED069D7F685BA1341CF6CE411DC7E +:1078E000FF0750FE2AB99B4EE3BE4002AFA476DFED +:1078F0002B315DB4E3BCE7FC46160710C9D5BF9831 +:10790000CCE2702400F4F3F16405A7F33CA4F07E0C +:107910009982E73A96BDF6726E88303944F22BB9F7 +:10792000487FBEB4DEEAC8867579E277B7C2399976 +:10793000325E5FBF12FDB953AA7E7ED0D3255C4F65 +:10794000FFBAB4F010D8BF32CF52B4EBFDE7EACFA4 +:10795000A51AF75921BDB02F8CEADD9342F4BEABD6 +:10796000F2E6C7D6C17C397AFF151901FBC92A484E +:107970009C0BCEE7AC68D097EF03BB7915B093D8DA +:107980002F17EFEB95BF6DC37F3179DC65F9EB0AFB +:10799000C1FBDBE231AEB2ECB5C5689FCC697AFEC3 +:1079A0005A553D7F6D238C7CD4F339DEA5E79B3699 +:1079B000FFEC89CF0979FAF3BE463E4B84C71B0220 +:1079C0002C0E11B5BF2DB809E936F2D9C8D7760B00 +:1079D0005FF7E27CA57F25965466B281EE74298418 +:1079E0007A61D4A30C7B48807F0F4A09D4E257AE5A +:1079F00078B4EF69BC3F4219FBCE067A2402BD2E53 +:107A0000D42338D10776DE463E70B65B41589F904E +:107A1000AFAEE9599EF794FEFED822FAD546C0EFE4 +:107A200068D42B766E378904D664829EBA9C306EF9 +:107A300037FA2C6A9904F79F10B56C28DC7BE2C4F6 +:107A4000F4C77C1F4AE74882FB821B431753C13EA1 +:107A5000FD38A7EB66B07BDE25A404ECE0CD716CAD +:107A60009EB298A77FB72ADCAE4E7BED7AF8BE595E +:107A700056E15C7867F356CB30C80745BC7FC49BA2 +:107A8000587715B4DFD12C33BACA2C816110BFD816 +:107A90002B63BB1D6593F17C65D86F6B66FB403A29 +:107AA0009B3F712C8EB0E71DC19F5E05F1AC274C4A +:107AB000B1F79F0CB79AF8FD35DF70FC6D8CDA7F5B +:107AC00037DCCAF6C7FD7808ED4775E9793E0E3315 +:107AD0007DB896CBF9F74B6FC0FEEF6C1654184784 +:107AE0000AC53B6E1C45FB39F188C4E3302C2E39A6 +:107AF0008EBFBF9BB8D2801F13AF2302E8F3C43FF1 +:107B000012DCB735AE6629CEAB7EEBA038CF8675DA +:107B1000528A5BB07367ECE8BF8F6F9574B84C9C6A +:107B2000E6698179E684A304EDED84A3FAF23C12C0 +:107B300010B19D36FDF36B4FEAF305568E6F074982 +:107B4000057C6FF85244BA3ABB88EB015A6F67D98B +:107B500000BCEFA6F3229CDAA5E9976251AC717ED6 +:107B600026E081F2EB0985E0F8F2C4523BC6EF5FF4 +:107B7000595A71058CEB9F7FCF7345AC73E011763A +:107B80002981EDAF722750E229AED70A8CDF75E963 +:107B90002531F6EB6B38D670ADE1397D699C27D67F +:107BA000BEC40FADCC0F29583A4250605EB64F208C +:107BB000C0D78E073C973D37E3270F64003DDEE0DA +:107BC00005F4B32DCD823B969FB1CAEA60F3BE07A0 +:107BD000FCB5B01FEF5EAA94601F7BAE7703CEABFF +:107BE0006E87A02B7C67A95B88E7709758C866886A +:107BF000674B75E9B7C603EEA7CE5847E97DB2C417 +:107C000084727E427621FDFE2A4230BEC0E3B50377 +:107C10006F269B22CF23FFC09AFFB095D6FBB0D52D +:107C2000897249F6B804A0DFF5DFFFE500BDEEBCC0 +:107C30006446390EE0F31FEDBBAD9C4FA3E3DC6B54 +:107C400001FFA43C05F5C3E571A865C9702F01E5E6 +:107C50007B8C7554CD2F4DF250DB46E949B29BF039 +:107C60007E2EE276AB4E6DDF19E1EF45E8030909A0 +:107C700004F6A569F654681642F114FFE32CF610D9 +:107C8000CC3392CA69BF2909566261F5B54A67C209 +:107C9000E7AA719F3BC5652E1C6E22B8AF0D36D288 +:107CA00042FD9A9DD5ECF3DA4482F666ED635260AC +:107CB0000DAD67A3D46685F849A65B2D80AD444918 +:107CC000928AE7BD0795337DB465FD3231ECAF5044 +:107CD000651FF30F7141ACF5BA8FC3FCF2BC00FC19 +:107CE000CA3ED4F50AB8352E2B6BCF75C082FE790B +:107CF000D86E703FAC908FBB133F35B1FD02A1EB46 +:107D000071BF9DB68E66B41B540FDE1541AF3E9514 +:107D1000089ECF75D3FF72B52D7711F6838F93B977 +:107D2000C19A16F4DDC4912D80C76B5FC7BB38A222 +:107D3000ECC884373C6B80DE6F6A3F8C781813A2E6 +:107D4000FAC8E53352857B2A9CE13C94B75AF9FC8A +:107D50008EDB9B94D271FDD1AFE53833F257D36BF4 +:107D6000A3BEE7AC76B598B1D60032C1D80E11BA31 +:107D7000E950B3C01EBD21827FDF994FF142E9BABD +:107D800017F40EFCF38B8119809B0DCDDFB1827E41 +:107D90007CE3F1A3997E1DB1BFFA27A2A7C3CAF65F +:107DA000873B800FD5FB2FF2F12384720ECB95EA2F +:107DB00047643C44C3BD11E79A5EAC810B33B2F01B +:107DC0007C1C01F98842230AD64C363A81AF9A7F4F +:107DD000BD26ECCF26E2B99E554ED6DE1A59F3CB1E +:107DE0005D16E8EFAAF882FE975B17F55EA2F3979F +:107DF00088F3305EA90BE767DE4B0A09247F0B7E10 +:107E00000569EBB93A7EA5C4C5E05707E8D1F8FF8C +:107E100027FB936DECCF836A777FAE259EDFB6514B +:107E2000BB907B4F7D3AC305399C16890BBE5ED94A +:107E3000937EE751FD06D72D4A9F0D7A3CB199EA12 +:107E4000B1295A8F5D7209DE5BE7DA6B437B67D439 +:107E5000EB8BBC5F5E1BE37B8DE8991107F37153DD +:107E6000D760C05DB64A928B29B1D94191ADAFB60A +:107E700026EBC691E8F1DD8F7652F32F35BFD2F8AD +:107E80005ED8AFE4E38616CF148214FFB4DFF7C7E1 +:107E900079E6015FD738D9FC130E9A82BFFC03AB99 +:107EA000E70EA0CF46FB1007EB1A2342992C5E1277 +:107EB000D2E95B4FFA6533E84F6348C271CC4FC7D4 +:107EC000B16142CFF4F48B4B64F452AB027ECAC072 +:107ED0005CC21AAB26B8AF7B6036BB4766600EBB90 +:107EE000F7F1DFE3D87ACC7D716CDCD0D21F584B30 +:107EF000EE817EC912F19B73BE39DD402AC40FEFBB +:107F00008F73DF0DFCB014B9B11F194EE21228DED9 +:107F100032A44601F6372455AA028B1B1236EE40D6 +:107F20004AEBCB2856F361DCCAA0B616E22019CD85 +:107F3000B1CFF56C8893BF5DBCAB29EA3CCA8638EB +:107F4000E66F1F54687F938BD9799470DC86920F0B +:107F5000FCED88BF0D3BDBF1195B0FF527323E1BB3 +:107F6000E75F2030E897C4F33F5488644DC2F9912D +:107F7000DF04DF992C383FB2115723D8CF97E2584E +:107F80005C759DE05A0FF99F485D16B86F47C3FFB7 +:107F90008F27DFEA92E82B8EEBCE67C39C95EAC36E +:107FA000F320AF8EC9E787AFC51E740D6678738B5B +:107FB000BAFDEF9ADC82B24E6E56888744DAEB78CF +:107FC00005E7F71D429C0BE6431DCB0546A760E184 +:107FD000E703247D9C86DB436D1C78272E13E9B7CD +:107FE00011FF18BC1FCCE2B2003D1AFDE173A4865C +:107FF000739EC673A06959E1B84D3AEE932D51E0D6 +:108000008E2F72BED986FE97D7C1F4DF8887FE60B7 +:108010003C2E736E92F2AB15E4DB5FAE49047BDB62 +:10802000FFCEE30E90AF910F9D827FCC4158DFFAD7 +:10803000831C739F8896A6A50D28057F342D3D0DC2 +:1080400053ED79BD5D8A19073CCDF5EE1BE3B59E76 +:10805000580CF3C3D3D09FB39E77DE73A3BA776176 +:108060007CBC3E8EF1BB5ED1F8A826809E75E75D94 +:1080700009EC7E924476FF9093C97383CF522A49CC +:1080800091EFB9D11FE947DC33E68111D82093ADD8 +:10809000886B16BFD1CE655043C7E497C8E8FAB9DC +:1080A0006F4C29EC9F916DCC2E5DDC301DDB4B2598 +:1080B0000F588753BE2E2D31B920AE7376D19F1C39 +:1080C00070147C51466B2EE0FD88E8916DE331D44D +:1080D0008DF3B76573954088422AA59E1A2426978A +:1080E00019B8EEB8D01473FFB3DDC6E6DFCD714E1C +:1080F0004CD3D20697968D8DCC0F44396978A47AEB +:10810000985E36AEFB9C30C5470AB46FD4A74E9933 +:108110000461DD40B387299CFF9A3DD6F42105F424 +:108120000CD6014BA87DD4E43984BF9A8AF14AFC6D +:10813000139A5FFD02E6038EEB0AD0DE51FD5F8FDE +:10814000FA3282D96F2BD8D3883865E7DEF707C1BA +:10815000FADF87DFBF100FEB407F91BAE2C17E9E4E +:10816000BCFFDD783837F4E1FD2C5E7197611E3578 +:10817000C1C6ECFAA3B6926CE8D702DF7FE77A2299 +:10818000704956B3758DE501D1709E5C7F2F4F55B8 +:1081900063B2E19E1E3FD65BC5EFE732CAA192CB28 +:1081A00061F9B64D4A860AED7BDCB67E706E8FA013 +:1081B000BD3CD9148FF3118D9E45DBC6283077FA6C +:1081C0004BB399AF7FB7CA6C5C7017C37A9687F3CD +:1081D000CD48E7C17D36AC6FC9CFD8FE9485B4AD2C +:1081E000D5D4BE7A9AD9790B633F967CA816F6A7A8 +:1081F000C25BF29080F36278FF7E3A4E79563F88F8 +:10820000EB5EC67E1AEFCD319E5FD5E653CBB8FC50 +:10821000CB8807F52FEA5C6B335B9F36C6FFCE1F1A +:10822000CAB261FF6D3CFE914B26C079E81D87867E +:10823000245CEE3EE533FC1E26B8571AD2933E82EC +:1082400069B64D65F76434BF7D2FE0AA3AB81DEFDB +:1082500019FBBAF6A6AAF99403F6306B7687FA9161 +:10826000AB013FA44CD0F997D59B2E286CBECBF820 +:1082700070077F7E07F4371BF659AB3F9A4CE57CBD +:1082800047A57C31F21E32BF4D7FEEA6AFFDD5FA79 +:10829000A9F55B2BAFE2FBD18CDF69F8CFE6782C38 +:1082A000DB52BA6E0065D19ABD2706F3F368784EAB +:1082B00047C397113FCB484961BA108193E647B154 +:1082C0005F9A3CCBEA16F2FEFBD3F8BA5E1AC48F73 +:1082D0007AC38D111F1D72DB60D067233E3A7AB8D6 +:1082E0005FE42736E62794A9EE4288675137769DEA +:1082F00033C24F3929D51DBC0FF46C0BC379C4F8B8 +:10830000CB9CB9D7651CCF57C6ABFDE13E3D94DB96 +:1083100044D81760F6C37B5A3BED3EB76BA8047C8C +:108320002FC2F4B4AFC435746877F9D2272E38C0A1 +:108330008FEE1C41308ED311AFA7F7773611E9F9D4 +:108340001D9743A5D4FA8F3F838DDAD28AFB1DDABD +:10835000BFE471A02FCD45B1FAF927FE1DE1F786E4 +:10836000DDC5F54C9B972CE072BBAB99AD672FDA5E +:10837000588AF230EED77A43701666D0AA3C8D63E5 +:108380001490BF513E4B5CDFC17D605172228FF073 +:108390007D011EDCA753562F62DCC328BF7CBB9334 +:1083A0009DA3576B701EB7428ABD0E79A5DDF4B54B +:1083B000FA63ECC7C22601EDA491FE655B6AD70D96 +:1083C00020D07FD6BFE87E8406A25DE2FDD4FA55B8 +:1083D000465C78FF40D4FA50DBF524723FF5F2E6B4 +:1083E000C5B82FBF9AF69FB03812C68534FA357AD1 +:1083F0008DFD2814CFC81688E3AE165C609FA3EFEE +:108400002773EBEE3F5CD8B07F20C8AF5D62FB66A0 +:10841000DBFD02CE0B3B3F206C7D60BD80EB693DF8 +:10842000CAAF99ED07EA598E350ADCE757B651888D +:1084300029C765F5F9AEA111766A7960866BA88EB9 +:10844000DE46DC1FB2A2A154F77C809DC793B8FD25 +:10845000EE4DDF484D62CC3893A65F9ABE69FA971D +:108460006F57D93C470A1CCCC804BBFE18CE4BA89A +:108470005DBEDACED707E6D157AA9FB8A05B1F58DA +:1084800092C7E4B3442CC6E73DD957CA079D7D1E69 +:1084900067D7EF7FF8B6FDD1FAA1E985D63FA35E95 +:1084A00018F9AFC5D58C7230F21FE882F9C11B7B79 +:1084B0006D810704D07746A77FAF15E9EC482B7094 +:1084C000C139C83FC00794CEEAF4DB315F239694EC +:1084D000DA715EC7E74DE3FA163FC8E17ED64EABD0 +:1084E0007B2C3B4754920CB89852DB36D3E2A4F86D +:1084F0007C647421DC2B3AE5B1B69910FA5EF2C8BF +:108500009842B85F7ECAD6B6772D2EEAD7D58E2D83 +:1085100084FBE55780DD80F60796DB10573DE58943 +:10852000E7F27995BD3FCE5C329FDDCBCCCA2B29DB +:108530008F2D743CAB3C3CFCF7A09F95ADC545101E +:10854000B7A98488371DCFAADC8E902D9B8DE79329 +:10855000E87BDB6C9E5576F0EB2EADC5F1ADF2B04D +:1085600084FA440EB1B8A844FB6AA5DFAD8DA37EA2 +:108570002FE5EFDA248B0BE6AFF4B91FE6B56B936A +:10858000DCAA1AF15C931F7C0774AC35B175FBFD56 +:10859000AF0D4F68BBCC78BFDF4726C33CA4C5678F +:1085A000C1D4589EAF38F17C44BE89C5358CE5BF37 +:1085B000D2EC2C51330017D5871416AFA67FE04FAD +:1085C0005611A617D5849DEBAA3A4CF01C4BF5A189 +:1085D000423CC702FBFC3FD6E1F05F738EA51B5700 +:1085E0008C4F059230598AC0F534BB559717FB9BC9 +:1085F00046407F8818E78273186286A96607EDBF38 +:1086000078054D293F24A74B84FB5AEAA64E11E179 +:10861000BEA93532DF3F6262E7CCB5F69A387FB447 +:10862000F4B4BD6407C8FDEC5BADB936B67E81F32A +:1086300061ADBF6B04371160DE7580E0F9809C147A +:10864000D202FCB311771EE0ED3D7B12E7375B37BA +:10865000A67F1990BACCA697558AF7571F5984FA66 +:10866000E04A30DD9349F36FD997B17C86E9422621 +:1086700085F0DBF67296BFC6746108CDBF6B5FCE26 +:10868000F2B0C04907B623F68A42FF486887E37D07 +:108690009BFB1AC0B76462F117E91505D753B47D87 +:1086A000216BE9440BF0F81ED84D88A7D416FCDAEC +:1086B00006F1EA02B70AFB3D36F37B83BE69AAF1F5 +:1086C00055B49970FE0329F0FF43CE4F4D2EA4C937 +:1086D0007D0DEC8B258DEE6B601DEDB4DDD306F6C4 +:1086E00066EC1BAD53C07E37BDF3A75CBC9FFC0A94 +:1086F00056CFD837E89C90F6E7EC6F066D8A5C8F12 +:108700003E6DCFFF14BEA36240FF54509DE40EAAFD +:10871000876BDC4455B260BEAC9F2F3611669FB6A6 +:10872000D94ACE825CC9C0108E5B45F6924EC86BAA +:10873000F69CB426F5695F9B92BD5A847139292352 +:10874000787411D8FFDFB17B3D04B71BF773BE14FB +:10875000BED78CED0FB1C1FE10D07F1749F3A7F241 +:10876000F8178B2F9394DC887930EF07FD7E1AEC95 +:10877000379F6063FB0768BF44B0AB63888AE958E2 +:1087800088676581283D98DF431A8FDE47EB7FDCE1 +:10879000CAE2499606A28B0F66C7B338CB4C078B4B +:1087A0000FC6C98DB782FF10778E38C17FE8FCA550 +:1087B00022E1FE22C97923AE8F1D3411A0F7593969 +:1087C000E084F599AEAB247533E9AEAF93CB5BABE8 +:1087D000F77145BD0AE272731DCC3F7D369FE07E86 +:1087E000E8AE534A00D64D93322C3591F19F2BF9C8 +:1087F000770F390B32E321FEBC378E40FB13F6C5F1 +:1088000099400EBFDE9663053CBC043CA27C483216 +:108810003BEF86FA922E507A33F139DB272FA9638A +:1088200012287F27DD6057E1BEA967AD8D37E07E56 +:10883000D0174C78BFEE4B8AAB14F22F9D579D603A +:108840007F9FCD6C8CC3FEBC60C2FEBC14D775F597 +:108850004A4AF7C323587C4AB21109ECB2642A5041 +:10886000EFA6CF73E3D93C49B3D3CBE399FE3C2EBB +:10887000103C0F2099F2517FB4FD3A9D5D04F7EB57 +:10888000F49BD52A028EE34AB5B851488478CFE4E8 +:1088900012827EDB64BB8CE772607F309C1B9BC2C4 +:1088A000EDEF940F2A713D814AE030DC7FD962E719 +:1088B000F768F175C5EB394EAE236D22F891D75D9F +:1088C000222E88075D7F498AE9474EE7F53E23104F +:1088D0002981BE977F51950077F944EFE74DAF2F7F +:1088E0003C05E3E0548BE139F889488F1BCFF74F03 +:1088F000771AEE4F8EE7F3D6C16470E43E316D1DFA +:1089000068BA38F209F4538B1417F065BBDDFD3EED +:10891000AC7BFA5B6572B938E2333EB69F6FC4A593 +:10892000385CFFA1F8B4032EAEAEAFF35B69BFAF06 +:108930001ECAEA071C825DB9F29729C960E7CDF12A +:10894000CCDE68A9863BC0973381E1CB39BA5B3F67 +:1089500057C567E27B9ABE01EEA09E3D72607EAC79 +:1089600075658AD75580D7ED7682F3B31FA55BE690 +:10897000829E69EDEC8967F837A6EB6A57EE87753A +:108980001DFF676CBC9836E0921239DE7FE86438D0 +:10899000F3AA75336FA6FDF3DA655CBF49E5E78B93 +:1089A00022F1921E81170D771D7616EFD1F03375E7 +:1089B000F7BB223C9FFA1921CE4C129E8768F8998A +:1089C000E267389C72888D13BDE1C7DDE59C06E641 +:1089D000310A3787186E0A283EF0F7B77AC08F1130 +:1089E000374FF58A9B2FF13CFCAABD532FBB6E1865 +:1089F000F4E9F77D1AD389B6D8FB828F727EEF56E1 +:108A0000EA6ECC067B7193899D7F9348C6AD14E7CF +:108A1000BBE3B47BE56BB220BF5D62F6677BB31945 +:108A2000EDCF76BBC78371D7340B9ECB2692A70DB3 +:108A3000F6F5BB0658D4C8DFD1F82EC761A31C9A3F +:108A40007802FCEFD798FCF36ECA811BEC487A19C8 +:108A500093C3B893CA2611E2428EFCFD80AF4FE06B +:108A60004E2DC0C37105EF25AA3EAEA05DFCCDBE64 +:108A7000B70B21BEA9ED1F9EB0E7EDC28291F03E7B +:108A8000C3D96BDCAE6A793C4A0176D2702FFDC443 +:108A9000F07926FDBDF225809FECEE72E37DEB734D +:108AA000E084171D776E6D734D07B360BC6F7D4E0C +:108AB000889D1F9B7DD43D1D4C65D47DEB1C0FB75D +:108AC00091D65D7162F4FDDF747C3E160FF1FBD729 +:108AD000430AC4C11B959A6BD87CA2260BEC8FA6C7 +:108AE00077F847F9D6F8E108DD7DFFC3F8F8F38899 +:108AF0004B62F738B529B84EF82861DF35F271EBD3 +:108B00002BAEF739AB5E9C0FF6706CB91BD76D5767 +:108B100039457CFE1312B26481BC5C12AE7734CA54 +:108B2000EAD41342F77B442A1961A7E57BFAC58D85 +:108B300085F6EF70784C0EF02BA4AE43F0DD84493F +:108B40003963C16EDBC7AC4D86714CA39BD255B463 +:108B5000D5DE4D87465727C7C91D8E8526C778F6AF +:108B60001DD8A1E0B1760B7CAFE1A071EF3926FFF3 +:108B7000083C80FCBBF1202C80BCC6071B4FB5FC19 +:108B80003F1F0FA181209F1EF1007108C7B7C2438C +:108B900016F055C303F5D7AE02FE68FE5AA3C2F61F +:108BA0001D6A790D0745F67C7CCFA510DC3F44F6A5 +:108BB00059D9396D4F22AE57BCEC646D747ED83EE6 +:108BC00098BA9864B283F9EBDAEF898C0909E8570F +:108BD0008EA106E10EF4E306A23D74717E9176410A +:108BE000807B37716F7906F897A164D08B31E6E20C +:108BF00010E07F876D4A06F88739B6C95980AF5DA6 +:108C00002356BD0E43D6AE01E52F6F51BBFD27CDD8 +:108C1000EEB5F06AB5F66F7430FB74BD9B9D0F0224 +:108C2000BB1D498766FF412C4087109A63FACA86AC +:108C3000F6BAB90DEC39D041F9BA5F204DE01FE426 +:108C40009BDC2953C1CFEB179280CECEBD5F0C8643 +:108C5000386571F3AB4781DE626D3DD4A55F0F359A +:108C6000FAD19ABFA3CD2B347F489BCF82DF04E596 +:108C7000D9FCB9D3CCD6AD26872C786EF9F1F3EABE +:108C8000556EAEBF12ED4731EFC72DA415E9D2EEF8 +:108C90001DB999F3A3F8109D876643392137513EDA +:108CA000DCC4EF1DB9C9A5BF57E196BCD8F78E68E3 +:108CB000F5F4F6BE717CB8D6B06EF46DD3433E7653 +:108CC000CFC87FFAD83C77D210D12FC1809A97CEE7 +:108CD000EE6970323E1C52628F57FBB9FE4E32B5C0 +:108CE00065C3B9E5FD7BFE8EE3E32B7BFEFE1EF83C +:108CF00089134F4904F6B54E3A352E01D7E7F3D222 +:108D0000703D59ABD7FB69938DB0E7881FED77575E +:108D10000E527ADC0AD067C1F4B7671EFF29D477F8 +:108D2000F1B84422CF4D142A9EA110C72DE4BFBF35 +:108D3000735060FE92567E90FFEEC5F31CB7B021D3 +:108D400042BB8FC41C21E79BF83D199A5C6F3A59CE +:108D5000744ACA8E960FFCFD33E20B5A5CA199F35C +:108D60008FB4FC11CFB77CA7E96E09FCF3EFA4899F +:108D7000C41DD1EE0C95CEE023E21C2F3B0C7E4AA5 +:108D8000CB733FBD998E2BDE3744DC4AE86DDEFEA7 +:108D90007A36E45BC598F78F18F9FB9DE6BBF1FEC8 +:108DA0009121092AD2D35BFB93AEA638190D722705 +:108DB000CCCFCB65F77718E5FBCA9EFF486E1BD971 +:108DC00033BF7B92BF510EBF3D5380EB4EBDC9C335 +:108DD00088DB7DB49F7EDABF10EDA79FFA63AFF802 +:108DE0009C98FFBD2F0DF31A5EBD7B9F4E067F4EF4 +:108DF000C3E9F464869B89BB7F9A4CECDDF232F2C6 +:108E0000ED7307F36BE610D7EC9BE93F770AAE787A +:108E1000B4177ED20AFBB34A388D730E17A2FF41F6 +:108E2000F87910E33836471C89E7DE7BFDDD9BA12E +:108E3000F932985BE37805BFC702B8368E53456FA9 +:108E4000D449E0B2154AAB981DE37EBA469751CE9D +:108E5000474809F6A3273A8D3830D2ABF9E7DAEF65 +:108E6000C0507E4C4FA2F5DDAAE663FFA2C661CEDC +:108E7000979EC6DF9EFA959CC0E3DE1CFF174E4E00 +:108E80007B0BD8DB93BE19E5662CD7EC47213490D9 +:108E900083A91FFC912109A9A80F859714E2A6E3D5 +:108EA0000C19A83FFF4E8AAF40BCDDE364CF7AC205 +:108EB0005BF52513F12477E34E0E3E6603DCED9659 +:108EC000EA6C101FBDCE5EBA06546FDAA705B3F088 +:108ED0009E8736138190D9F4E6732D1047F01E2536 +:108EE000783EA0A079FF54C0E9EFA5569C47755E77 +:108EF00024E4B1083F33D8BCC6067E5830859D6F48 +:108F00003B984874FB90F72730BC068F9FBFD91D54 +:108F1000A3FC122F9F49DC29D9382EC763FCA3700C +:108F2000BD09FB3F4D701D4801BF659E80F385CE96 +:108F3000BD130EA4507A3BEE4C443B333DF8E0DDCC +:108F40004E2A88C6FF1E8BCFBB160A78CF40A1EAF7 +:108F5000C27C615926EEDF98F08FE499C5503E43FC +:108F6000C6F9CD74B1528278D4D9342107E68B7B0F +:108F700084B65AF81D5C7F296B8738FDC930FF7CA9 +:108F8000A738790CFE769CAAE587E1EF0312C33C73 +:108F90006DD5CE0BFBCDB47CD56C01F7EF4E77666B +:108FA000107F047E0AD753798EA5B86CEE5F00B8A7 +:108FB0009E59A43F3738BBC4460291EB168213EF8B +:108FC000213BC8F7697709FC5E7CAEE73770BCCF00 +:108FD000999BACFBAE94303FD3BB5364F771E4B3C1 +:108FE000DFA1D6F4EB46AE8737F0F9F13C4F868E21 +:108FF0008E6288D288403F5B47BEE5621B0ECFA5DC +:10900000E20787E7D3F66E1C6198D78A956B111734 +:10901000696C1D6F36EC8213C16EEADFBB254F9F72 +:109020008FA1C797B5139A3D98BD57C475C3D9F999 +:1090300094CF0289F2D3BFAEBD9860721D8078D004 +:10904000AD97DC788F4E94BDF8A0E81BD98BDF502C +:109050001DCCA37AFD64021F370791416037A68BB0 +:10906000DB7E0A38EAA4E3A639068EB471479BEF8B +:1090700017523D06DC90336C9D65FAA534DCEFA4F5 +:10908000CDF7C37684FA25AE18FED26F12B274F70C +:109090007A84ED4A845F22E77E7BBF643AF5479588 +:1090A0001CA06F20F18F457B8671C942D81805F14D +:1090B000C1B47318E7F14A74FE8AE3F3D3882FB082 +:1090C0007F4252B77E18FD152DCE3CD6A9F9537AB2 +:1090D0009C84E38DB3D87DA51A4E0A819FA0FFB36F +:1090E000448CEBF4861BADFDDEF012A2F6084C5664 +:1090F0008F78E1FAF775F1F2176D7C194A86F6055B +:10910000271A3E34BC18C79BFF34C4837A1A6FBA3F +:109110007A196F0E8C90D1AEF7E6D77CEAE4F3EAC9 +:109120000427A6375C351B7F97682CD811F037F9D8 +:10913000B8158E6BD5339C1C685B24C1FA9117EC73 +:109140004766B71CB478F0FF00C6C481D500800024 +:10915000000000001F8B08000000000000FFBD7C25 +:109160000B7C54D5B9EFB767EF7924334966924940 +:10917000323C841D082121090E21BC1137490811F8 +:10918000A20CA8888FD6011F6020094DADD5536F62 +:10919000332181526C3D58BDD67BF4F43758ED41F4 +:1091A0000D75080183277026A098F0D020F8C07AAA +:1091B000DA6829451B92185A0F6ACFF57CDFB7F69B +:1091C0004E662683A5F7DE73879F2ED65E6BAFF5BE +:1091D000ADEFF95FDF5A9B4AC09F0A50B315209844 +:1091E0000650F9E1864A4806E83B20011403D4966C +:1091F000C9411BFEB5B4FDB1C745DD0C5689DF5131 +:109200006126C0F5207E0B950EC5E60658E695BC96 +:10921000721680D62EDEBFE19225A862FD7AAFF9E4 +:10922000E31E9BE8FB35FF5F03C800B8517F7F1941 +:10923000FD0FFB2FD3A460185F5D363BBAFF8D97FF +:10924000CA3F91A6022CD7629EC34F3E93A7F2223B +:10925000CCBE24AC5744B78F7326B9CFD9F12FE3D6 +:1092600061FCD732C0C5F3656F51F7AFE977EDC840 +:10927000F2483D526601E8ACB77119DB5E6E017FC2 +:10928000C881254D50C4650052010A9DB8981958EF +:10929000BF64010DF9086313E0F7B93A1D1386DFC7 +:1092A0003F88E30770DC308E1FC8013854EFE4FAC2 +:1092B0006BF51EAE5F93822FA4E37F87BFB0A8B883 +:1092C0009EC5EDDF51FC38DFE24B0A8F3B9BD69306 +:1092D0004F0B8371B49E3FF716FDE30D30DCBFB634 +:1092E000FD338BBFF0F2EBF95BF3E7A7A83C3FCD72 +:1092F000AB150CCFBB44011883EB5C9A1BCD5F63AD +:109300009E58F9C6CA6FB9FE7EACFC56C4ACC79075 +:109310000FF4A2328D8AC3FF4B26D0A65F5E7E4338 +:10932000F2B1F8B3BD0523DB017EC9721A1E4F9757 +:1093300017742BBE42419719F5BA52B70BD4EF40C0 +:109340000ACAB9B213C28948D8F5E72B3E51A8F42E +:109350004AF071943E037C6CC85B1E1E7FD125E4ED +:109360006BDAF0BC8B146477113D1F0B8138EBA8CE +:10937000A17114EA1F60396CD9615A15C2755C631A +:10938000813B7D54268A32E094B87D93D3C4E3F6C2 +:10939000FFC56682AB015E3E985902489FD7EA3C02 +:1093A0000613014266E0F7BF4E52B9DFE6240824F7 +:1093B000E0FCA074DBC85E9412805CB43B65B4250D +:1093C000D88843362B611FD961BF578106B4DB2F84 +:1093D0008DF70E056E0714C9E68F734C8D59F47E18 +:1093E000B87B1EF69B55A4A8DBB08BCBAA7E87DA90 +:1093F000FB0E589DF45EFFFEEF7798699CBF8017C7 +:109400002984D70E5881DAE73BCC41F21F8BE4E385 +:10941000B209EBFD030056EC3F7F55B814506ED7F0 +:109420004077A313CBB924C738F27B8DD69BCEFEF1 +:10943000C3310AE5B44097D302DD6F951E90D98FF2 +:109440009426C941C81AF653D7EA325A806C253A95 +:1094500016B4E17AB1FDDA4B4A5CBFB4481F77E13C +:109460009F4121935C08D17ABBA84DF8A312D01478 +:10947000C0294B6D31EDE497909E45CEE8E773C966 +:1094800077A25EEF8EF14BF833D1BCF73BC5BC8BB6 +:10949000E4BF26F7E0FA5FB668EFCD437A074E9A4D +:1094A000E1597C0EE7B13267245FDAD0AE83399799 +:1094B000B78BFD07133515E97999F4C741F5D19AB2 +:1094C0003AF5F2FDA7F60C94607778B97985021326 +:1094D000581D4F7B3286F93D82AF3AFF63F9D9229E +:1094E00041931DF9BCB0DD5B46AE65041F3B918F17 +:1094F000F85EC980C6F35C291F0DFB78F95CA246B3 +:10950000FAFEF2B9D11ACDFF2AE96BFAB0FEEF3FAD +:109510003B9848FE13F9A82AA817032E9BF759D6A3 +:109520005FA1F7A15139C16D586FD1F5FCE5C48138 +:10953000A3F9C4EFEB4DDE67691A65E3C41585E452 +:1095400037B7969CC577240DA407D17E24D509771B +:10955000601940FB217D0BA402EB93194240F336C6 +:109560006AF034950BE6AB29C4EF411CB3DB41E351 +:10957000A929A4E7F0D78B337D8523F9DE528F0A22 +:1095800085F3B4D6DB34251B605FBD93EB6DF51E10 +:109590002E5FAD57B9DC742CF9C1208E53AB593412 +:1095A000256DF87D57AAB08F05E86788AE052005C0 +:1095B00003A8730B1ED6F55E91829B249213AE27EF +:1095C000829F2897C19EDC08FE36294D9366B235EE +:1095D000B0BC8BF24DFC3E06FFE0F35923FBA3DC4D +:1095E000A3EAAA4B627EE6BAB42417963F74F852F7 +:1095F000A86C916E397C01B8EE12F55BE50B38FE74 +:10960000F4F0427810E3C374140CF1157FB713FD26 +:10961000333A2C40F2C180CA7659A4D3A37D2E4997 +:10962000E7703E329DAFC7E07BD6CA30E9D13EE855 +:109630004923BE17DB7C76B428A443C855936EF645 +:109640004838DE9C748B5726D226FAA66F44FE75E6 +:10965000A4E384D8BFA32363AC8AF6A6296FBC4FCA +:1096600076ADD91C61812BCCBD3D11713C139E712F +:1096700052BC229FF635F2BDF377C901F66B8873B1 +:10968000C88F759E4AF686719E6B2ED9BC56D27FC6 +:109690007A11EDF56062F254F2CFD05DC6EBB8D628 +:1096A00026D6916FF617BBD89F850F9FC0F7FE6D2A +:1096B0001080FCE935DD1FCA80F4949AF2327B9069 +:1096C000CEC3D2E4142A9FFC5D720197A7927B89D6 +:1096D0003F074D7695E67DA75E2DCE467DD1DE72A5 +:1096E00098001DD682B71C0A9527EAA1381BF5E51C +:1096F000AD7A1B9727EB9D5C9EAAF7707918DB4922 +:109700009F5EC776D2B737B09DEA5DD84EE5311C73 +:1097100097CAA2DB9378BC96DB922CB48E83C9D017 +:109720006CCC4FFA144E0CB78217E03F1EFB6AABAD +:10973000ED2A8C97567FA1340DF9F4B3AF2A14ACFF +:109740001F5B3CEEA1BF60BBF967A61FDB90DE9BF1 +:109750004E395A8F63DD9EAAFCD841FA792C119DAF +:109760002399B5B94B433AA6936F1CCD6CD760369D +:10977000D6D3F47AC07C5DD97C8095A53DF9E042D2 +:10978000257159AFB3217F57DAFDDFA3BA25B0ABFE +:10979000A2EC2AAA6388247B97CC41B6F7B1927BCE +:1097A00005C6BB950EFF7F12BF0D7BD1A43FA491D0 +:1097B0007F98A949E072B3BC8393A4E1E746BF95C3 +:1097C0008E45FF49FABADE25B37DCD982F6941C792 +:1097D00048FB35FACD38AB9691FC669E2F6FA2728E +:1097E00059858BEBBE55B39AC8FECB1C977BBF94B3 +:1097F000DF7FD06566BD2D51B05F9C3868F49B8ECD +:109800004A46B87BA02B31F82CE9F5697F6312D664 +:109810001779B28A64DD3703D75D3BB6517BE5EB40 +:10982000AD6C57DE242FE1F299A89069D8BED02103 +:1098300079C3642AF33F6A4AA376A7E425B62DD4F8 +:10984000A69D28A6F66CD9BB90EAA7D5320A51A7E7 +:109850009485F32E60BFC5B9295E1BBE772AFCD064 +:1098600045D2DF85B949DE04F2F34AF0E91AAA7B52 +:10987000ADDE0695D6F15869328DA34A5E13D65BEC +:109880006E28FD1F4447892F052489DA5D0AE1D738 +:10989000277FF7C33227F66B192701D9CFA970DECE +:1098A0009F88FE859D896A02F9698BB38CDE6BB156 +:1098B00048CE4D5CF79552FF408E597D1EC73D7EC8 +:1098C0009B9DE341E55B058C838EDF3686E342E5B5 +:1098D0005BF34BA83C6E1278BDF2ADCA0A6E3741FD +:1098E000989C4AE5EDDFE2F7B697FEB0CC8DE31F1A +:1098F0001BEF62DF82722A5622FC24F60789DEBF44 +:10990000BD9AFB7748990F9DC5FE170B528AAC385C +:109910007FB93B21AA7FC55857547D49F6A86225D7 +:10992000C24F56166445D56F28968AB323FAFBE6D4 +:109930002744D55794B98AB323FADF54392AAABEEB +:10994000F2A6ACA8FA42D31CE13FEA617E99B0F3DB +:10995000F965D9208C89FCA953F47D03DBEF263B04 +:10996000EF12F8A9C885F809E552D655CC71B9D8D7 +:10997000AEFBAF00747B6692FF17BF2E1C8FDE8399 +:1099800020FE99497848FC1676231E207CA460DCD2 +:109990008EA0A7CC111DC72B40CD27FF5BD1B9846A +:1099A000F154B96779199A31F231FABD0AF9618136 +:1099B0004362E82EEA32C7A5B7626CF4FB06AEAB91 +:1099C000D0E96B31F99B52098B05B46EC235C67A6A +:1099D0000C3A2EB79E0AF98E3214FFDF5C572CFD2D +:1099E000001B797F114BD7A04BC78188A71807763A +:1099F000A6323EC49F3B1E3E30704F25FA3757A417 +:109A00007F7348EEE58597F76FC6B897C37BC6B8F6 +:109A1000C6FBD02CF3FCC6FB43CF5529FEF39DD8E3 +:109A20003F29CE73B714FFF973D1FD17286AA3033A +:109A3000EDF82848DE00F1FBB8AA10242B3DAD3527 +:109A400051B9E843BF427874F1D9401395F37A8352 +:109A5000C7ADB8FEEB726595F20D061E8A5DD78C18 +:109A600054B14F3A7A49B5ABD8DE1250EDB4BF6865 +:109A70007958B5D33EAA45830ADA2F6A134D1B697C +:109A8000BFA1E56389F59C54E1E7F352058E31CA25 +:109A900067657F5E2A96D5B69E47098BD47C316078 +:109AA00021307094705EC1489C7754093A68BEA317 +:109AB0000F071DBE083F7EA5386F14295B3AE9A742 +:109AC000A445FA91525B8216E93716395D51F5AF1C +:109AD0009CAAD8C77B4645BD779D9A15D50FF16BDB +:109AE0002EE1A0460BE42AE4474D895EC277B17CA3 +:109AF000FC177DFD5E8793E01398DDAAEC8F13972A +:109B0000BCA5827FB1CF57A48A7DEA6F683D586EAD +:109B10004F15F435C93E01E21037933EC4D6714F5C +:109B2000BA8AC6C3913DA4775EBBE922426FF84E64 +:109B3000EAD5D729A8CFDEE9A6EF4EC4FA23A98B30 +:109B4000447D9E69CF04ACFF34B55CD4AF364D374D +:109B50007B017E058BAF2BC37ABADBE74FC579FB60 +:109B6000CD8EAD12E219C52441917B78FFFB8805AB +:109B7000E3290A16954C7321AD76ABD82FD724A0D4 +:109B8000FFA3FE259A4AFCAA4930E4DC9341711DEB +:109B9000EECE3491BF30F66F760BBE87EFE7D8FC80 +:109BA000B5425FC2C92AFAA5FBF72FCA24BDD89EC9 +:109BB000EAE4F5E7EF99E7217F85747D97FAFD7F69 +:109BC000A46B533CBA9ACC629EDE96FC528ABBF9D7 +:109BD000E3511CD2B0BC70BBCFCF1342A82B8CCBAF +:109BE000358F84F54697C54B387DFB907CAFAC6CC8 +:109BF000D4F313B25DE88D9C62DAB81BCB9FEBFA0D +:109C0000F214CD3B83E61918B71CF5019C03E3560B +:109C1000148A3AE9832C170D10DE1EF8569297F736 +:109C2000C763077EFB03ACBF7747BE9770F4078915 +:109C3000823FAB82131A7BB03ECD1ABC2A8C743E95 +:109C400094E67F96F4E0366B7012EB9B6363128DA3 +:109C50002F69C0FB10637F87FB38D5327124EE1F5C +:109C6000392FD888CFB7CC117C36E6459EDA28EE5E +:109C7000BC375B3C37E8C0F95B88FF063D4374C0E6 +:109C80005827C7031079A445B243E461FF60E2BCE2 +:109C9000492D191FD6F79C35F1BEAECFD85780E6B7 +:109CA000583D939B789E392736C94C6C00FFCCD425 +:109CB0005948AFB6ADE77DFA8CEEE87DFAAC4E7F41 +:109CC000A903DF9BF57EFC7CC83C7DDCD910942980 +:109CD0005ECFE989EE374FDFA7CF3B1FFDFCCD54A8 +:109CE0003DBE8D86D191798E3A7DFF33787C420AD4 +:109CF000E929F93A19F96E5165989D3AEC375AEB12 +:109D0000B15F0EF9471B9785A79D7711FD6DF5A8EB +:109D1000D016F2931E2E0D7B2A3C0D77C2D4887983 +:109D200074BD37F838F8BEE0E3B49EDC9FCFC7BA05 +:109D3000B9D30C4175789D73753E0D82E0F3A0D3C5 +:109D4000C27C9ED9F5CBE9617C64F598408D585F63 +:109D5000829A086A843FB5E7A646D565433E3ACE67 +:109D600098AE8F9FE41D1D358E81370CF9BD9A5A30 +:109D7000DE493864BA631DE38E94D913A2C62D3E22 +:109D80001E2B27641CE17624F29F08D79F56A270F1 +:109D9000C62C77803800B33F546270C97699EC685E +:109DA000EED9E8E7E6B4CBC8ED72FC84A93F9FEF9B +:109DB000FEFBF9E9D2A2F9995611CDCF745F343F79 +:109DC000335745F36D943F9A2F63D64D896ABF6A26 +:109DD0006351547DFC8373A3FA6761008CAC4FDC44 +:109DE000BA24AAFFA4ED2BA2EA939FBA2DAA7F5E04 +:109DF000704D547BFECEAA2B927F61A82EAA1FB174 +:109E0000D7F40DF2BFBAED1FA2E6F9EF96FFA23428 +:109E10003D2FAFCB7F998E435C1AFAC7A2E138453C +:109E2000E915F293AEF637BEA0FC4BA044E5BC5357 +:109E30006009781BB1ED09D927915F1B83AC36A16E +:109E4000DF6832C13AF2F78F9A4C9C8734ECBC2A17 +:109E50004DE08BAA34E1F79F469BA6F866F0CFEC65 +:109E6000DE9E4478433699A09BE29AE265BF71C6B4 +:109E700001E16B713E7934705EAB3479F6B299A82A +:109E800087F29B32EF1FE5D17E50717D8DC71F3F5A +:109E900041F99F8B0E9B4AFA2AA7FA0314B7707DEB +:109EA000A1E761245E79AF3E3C89F649467D95671E +:109EB000E366EABFEA8E859368FF3AF4FC8E8E492A +:109EC000651172885CDF8A38F8E87B69223F67C4D5 +:109ED00087DBAC6A630FCA6B9A2CFC3FC685EFA583 +:109EE000E1FA3F901E360B9C1530D3BA314E72DE2C +:109EF000DF8580BA0ECB94E178A47E8D4AF5C184CB +:109F000068DCF9261144FB085B2AC7FF5B0D7FBBA9 +:109F10002E8FF936E888EE3F78F744C1CF6F23D70C +:109F200090DF672C621D06DDE7753FFCA9EE877B9D +:109F3000C9FF46E49BD7ED783C89F0F5995C81A791 +:109F40008DE7CFE8727D264DE0E9F53B139C9179D2 +:109F5000C7EA902BAA5EDB36CA7936420FD71BEBD5 +:109F6000F04B0AAD63836E3FD59D3DC9B701E3F168 +:109F7000A7D370DC9A1D17BFBD8FDE370D648838FC +:109F80001AE0F96E790F18D7DFF21544E1D297D2B3 +:109F9000447EE525A20BCB95583851DF56626C778D +:109FA00051F9C6FC72B23B7C1E96B0BEAC13CC8499 +:109FB000D396FBB3CCC4F453E07D672F2E6D5F9A2C +:109FC000CAF3DC043E33C5C577BF5D9D44FD86C63C +:109FD00033C61943B959D42B57C09C41F99A6B2405 +:109FE000C60D389F8D9EFBEE18B399E2AF31DFBBF3 +:109FF000E0BFF00EEAC50AF0F2B8C6F800A9517E3B +:10A00000F803CB901CED24BFBA2E5398F239756734 +:10A01000AC7CFED1DF30F0EB0790CEDF557DB15741 +:10A0200042BA7FBB7AE057FBF0F9AD4FA1DFC5B56F +:10A0300066DBFD87D322CEC3CEDC7D91ED0CF1C86B +:10A04000F34F92337AC9EA25FBF8A0EAA59C48BCF5 +:10A050007F226D6127BD07B3D3E29E47C4EE2BABD1 +:10A06000483FD96E55C699865EDEA7EB65DD0B933A +:10A07000F9795DD2D07A44FD7999F3577507ACBC74 +:10A08000BF7F47D787AA17BF9819999F6B41BD54C7 +:10A0900073A8747249E79C2AF266CFF1C1A9D46F04 +:10A0A000A3ECEF213D3978E9E364AAEF79F34B5E45 +:10A0B0000FDC7465F4F723F322F95C9B34F02EF97E +:10A0C00093EA7D5695F250A5FBF28EDD8EF59A4E01 +:10A0D000F43BB89E0BAE9E234FD37E6ABF04949789 +:10A0E000AA0927B073AF69958294C7AA6ADBBD65D8 +:10A0F0000CD6AB9A971793BAD6260B3F56D32205A8 +:10A10000693CF0A7317F8A74DB287D35EF1F0BB0E7 +:10A11000BDEFA818FF5C7D78EA59F44F7D2D9F9D17 +:10A12000233A36B459393F762E296C1983F35ED819 +:10A130002D8502EAB0DDF6B9C43E6A5DE8310BCD8B +:10A14000BBEEB9E5D9040FFBF69DB4907F5CD7FA5E +:10A1500058B9FEBC5884FB20DBC5FA9D1D9322F341 +:10A1600049F721FC83C8F881F40508F78290E309D8 +:10A170005D3EABDA273612BBD0AFED7D5A62BFE64B +:10A180007493DF3BB8EBDFFF95E6DDFF2F9398FF7D +:10A19000C557C67FF005184FD4E8F3C0F95316DA57 +:10A1A0001FD6B49ACFC53B17FABEDB77957BC6F0B6 +:10A1B000FE3616576FB18038B79900C1E7291E38AF +:10A1C000062CAB919E1F5107A447710E58D660DD37 +:10A1D00046764671C2E308C6DB17D7B9159E0FF75E +:10A1E000081BE39D57D6EAEDA56A8F85F270359E70 +:10A1F0005E0BE9754DF813715EDFF651B91667BF56 +:10A200005CED167ED3D003C3DEEBD2A7B05D98879A +:10A21000E260C8C6765FB86680E253DD7ED40EDAAF +:10A2200017B8FC034477606F824AEB2BDDF7C9CC8B +:10A230009E8879FEA4DB8751AF79F9A3A966E2E78E +:10A240009E8FA62A49C3CFFB321CEBE2E555AADD5F +:10A25000224E6F4EF69D8FB683046F18E7AD69B737 +:10A26000F3F907DAC1968EE2483BB875DD0ED2F3FA +:10A2700076D98B1601356DCBFD0DDC3FC94BE291D4 +:10A28000DB1606480F65A78FF513FE8AF3CDD4CFF2 +:10A290007D2652AEDB7F1BE991E2084F8ACC6BD45E +:10A2A000987A7ED121915CB76B269AAF08D86FC996 +:10A2B0000E5F0FEF9F8A3354DAC71E9E510EC4A75C +:10A2C0009F1E90385F6B4EF56FCD22F91E95B9BF7A +:10A2D000E5F00B013A97EE9B06C5449FB1DE9F4E19 +:10A2E0000B838CE36C2E042F4DBB79FF2D1ED2DF28 +:10A2F0009FA61F617C61F78680FC4A23E206CAE7BD +:10A30000D80B42611A2721D7572CE33C796E27F3EB +:10A31000CB62F57B291F944D755C874DF1AD23FA17 +:10A320006CEE44B19F1E7B6579BA3EB27F85CE1B31 +:10A33000FD9C2FE9330B3DEDBB0A185FF31D9D39E2 +:10A34000D4A409BEC1762E6BDB3AA646C6DB44F028 +:10A35000DBE879DFFE5BBC44BF3951D7F78C44B6EC +:10A360008BD8F9FF99F499E46E5AB3358BF84C7C8D +:10A370005347F67B5AEF67F003147F2ED92B92AA2E +:10A38000C5CB0F8D77973C4E72DD9CEACB7515F0EF +:10A39000F1AC00C39EC4B87687FDFF5764FF1FE988 +:10A3A000FCDCA2F86DC4DF4D7ADD6CF1A94EB67FFE +:10A3B0009F4AF30FAD6F74FCF5B5E9F6BA6582FFFD +:10A3C0001BD7B74F5F9F3915F58DC64B06EE674E0D +:10A3D0000E0648FF9A92A078133E3EEC2AF790DDD5 +:10A3E0006D39F4C538B2F7A624AF0728AF7560D62B +:10A3F0002AB2FB2DA36F63FDFFF485BC2239629E58 +:10A40000136925ADE4BF7E69ACCBE2CFA575FC42F4 +:10A41000D723635DE96EDFABEE88BC118C755F916D +:10A42000FE80BE9FF3EAF117F7739CFFEB87442F82 +:10A430009D27EED671B7023ED61B3B7855C6551AFE +:10A440001CA37B1F8D1D26D846CBA6E454C4395DC2 +:10A45000B26C32367D9A0DB7E6746C4CED6FBAEB88 +:10A46000963421BDFB21200B7C169DAF004DD2A45C +:10A47000C83CC56B55F1F314CFF81BC92EFF569E8F +:10A48000624ED8B4DA92F2F7E72BCEBAA3F73D9F2B +:10A49000BA55262A942BF431144E0C8ABC174CA7BB +:10A4A0007D5333F112FF7B06D7CAF62DF5E5DA5C52 +:10A4B000684FEEFBB76D1D8B76972DD64FF546FA9C +:10A4C0007BA7C03D43F98FD7A630EE463F27F3FE6A +:10A4D000DFA9D31223B762C46BC0F78852A3F22757 +:10A4E000E1235F26937EED4A55DF22B90C74C97CC7 +:10A4F0004F2441E9B1B8E2D8D93EC203E8F78BD383 +:10A50000C53EC4D626CE176DAAC67E31C1E99C26AB +:10A5100047D8C579B7C89F571FF9609C0531DC053E +:10A52000D3F1E4021C7FC3DE96644AC3AD3FF3F669 +:10A530004CBA9253A2F81DE9B8FE4FA51D3936C298 +:10A54000A95B8353893FA1F08414F293850A049494 +:10A55000A238F1F1A922DE14D73CC587FF50D83EBE +:10A560007D2DE1E5DAB0582FCD61C6A6BC36E07A84 +:10A570005F5B632A8D57FB6F074693BF7A295DE0C7 +:10A580009A172F4D11EF2BA050FFAC7497AEE741F7 +:10A5900013E50B5FD2F38C7D974CDCCF98BFB06D89 +:10A5A000A1EC443D28086F3FC479CD76AB4AF24D0B +:10A5B000780E043FDA131877D61E5C0C14E7FA5DA8 +:10A5C000E095B07D57E2C06F491F060E58553A77A7 +:10A5D0004D706E87541C7F977E4F2B0F15B2C5317F +:10A5E000FCDC982FA1FDE7941324BDE0F3DF0465A4 +:10A5F0003B5CE388E47712D35DA2EBD5AEC4B089AF +:10A60000CE450626E15E87E91AA613785E83CE3C26 +:10A61000F6FBBB2C03E77EE066BA9CA4077920E832 +:10A6200084F6C92AF9D104A7C6EB4870AADE8034A3 +:10A6300092AEDAA908FCD06E1E25E73577D8AE6B4E +:10A640001387EB36B4855D13403F8FFFD5363A8FC5 +:10A650001FAA9383993DFCFE2DE92F6C6B1ACBF951 +:10A66000BD808CA2B66399944AEB54797DE845B5D8 +:10A67000F422C107BAAF67B789F6A1FEA8E70EAA10 +:10A680003B443FAFD5695F92C5F64287D74378F028 +:10A690007E297CEE5AB4D7DEC77C2905B8AE5ED3DE +:10A6A000A1079AB1DF9F568772E83EE97356FF1AF9 +:10A6B000D2CF573E5CF34821F9DB5D666F25F99DEB +:10A6C0009EC0CF1887BF6856B745D81D8C1DC8E0FF +:10A6D000FB8031F3D49ED9F433C2D7FDFB2595CE50 +:10A6E000BDFBCD03E388EE9AF63F5AE8BE64EDFE6B +:10A6F0008F184F4B19FE1A9A6F765B03DF6B9B0323 +:10A70000DBF95E1BFA43BE9F18F2087F32783AE706 +:10A71000D98608393C912EEC0D06FCE3295EB5EB99 +:10A72000F67A90F6DD58EEEDB875228DBF57CF075B +:10A7300018EF35C0A131C4F74DF01A97C6F3FEA04B +:10A7400052417A96FFAEED4E2DA2FFA3E902BF3D26 +:10A750009A2E70667686BF89E85DDFF1B12599D6BD +:10A760007936348EF6B921454D71C6F12343F61B77 +:10A77000634FB5CA8085FAD79E07F62B28EFA6143B +:10A7800094DF4BEFB64D598DCFF7A24C5228AEE275 +:10A79000FE94E2EF5EB36F0CF56F78E7F3A9E4C7C0 +:10A7A0001E484FE7F57F7E60FD78E21BEA7F492275 +:10A7B000D9D96E60BF66D86901D929BE5F40FA5FFA +:10A7C0004CF53CF6CBBB2CDD4BD82EF79A80EC1227 +:10A7D000F59FED01F5DF49F8AEC089F6C0EF4F6691 +:10A7E0003BDFD56DD21827A35F9FC4F5921BA9BE8E +:10A7F000ABBBCCC9764EF7058AC85EC387789C1080 +:10A80000C024129D04BEA8FC883B99E936FCE5E70C +:10A810006ED0E3869AE2C575D86539CA3E22E2A4B5 +:10A82000A81B71F4C933DB9E407B81EED428DC0F7A +:10A83000EF0BBFFF5D3D56D5BD3E775933AEB3EE4E +:10A8400084CCED07F57D5E58D793437A7E86E28609 +:10A850003A5DDCEFA5E733B04EF75D676A1B4B0945 +:10A8600063CDAED87E98CAB9BE502941C8F9ABBAFB +:10A870000F9B8599E793FEB51EBA2E9FEECDF59FEF +:10A88000B1420292D8FAE5C06F5FC4B53D7010F9CD +:10A890001F274EE17258FF106F8D01CFC8F67EC999 +:10A8A000F023BD4B481FFB5AE5E13A1252838A4D13 +:10A8B000F577D23FDD16C0BA3F437B9F54E2C7997C +:10A8C000FEF7493FFB4F7E994166B9F7B4D8C7B749 +:10A8D0005AB47CD29FD609B8B58DA3A7AFA58B3C3F +:10A8E0004FB115E29E4B7EA5C7C19C003C22F1FEF4 +:10A8F0005C760651EE175A65CD82F8E73C0456CED9 +:10A90000237FA3E76FEF01FDA7E11F94CFBD7AF589 +:10A910001EC22B18B7EE7D62C4B9BF89F4696DBB46 +:10A9200004FF846B5FF74CFC7B09465EEBBEB61DF3 +:10A9300047C6A03CAB9E8BEEB761E89E7B88F7BD17 +:10A940001B9AA3EF1B7C95AEE396893091700BEABE +:10A9500013FB07B3029D56D4DF5732FD9F105E7E76 +:10A96000C924F8847E95EDF213B71E674A843F1A16 +:10A97000B8007C8F286F67E830DDD799DB9CE5A5B0 +:10A9800039E62AA27D6E5B16C719508232DD3798F0 +:10A99000ADF9CB195F07B4D3742F649DEE27C1893D +:10A9A0007F28BFA3AF6B9D8EE7EE0B46D33D07829A +:10A9B0008D34CFDA9DE2FED1FA9DF1BF13A8D5C741 +:10A9C000D9F0D4C923940EAC0E45F7ABD5F953DBBF +:10A9D00016FDBC057812189F117DCFFC4AEF43FC91 +:10A9E000C92CF0C5DBFA3846FBB519C27FD62079F1 +:10A9F00024DF0D4139487AB34E0A240B7C0B8ED5E7 +:10AA000048F75D86BEE8F765EFD6F97397AE2FBCC1 +:10AA10002E7CBFFA192948E78077FF249AFE7B42F3 +:10AA2000ABCB491F62F56A5DB399F16D156CB4103B +:10AA3000BE8DD5ABAA217DD96EA13816AB4F357E20 +:10AA4000E932740B5CFE7F4BF77A7398F34CEBFFA3 +:10AA5000A7E4A53CD4BDADDFB1505E74A47D08F978 +:10AA600056197AA2AFEBEF5DCFED867CA7C01496A6 +:10AA70006F45DA15EE83A2F1F46ECB509E92F37C13 +:10AA8000839D13383F6EE851EC38E53A2E5FFC1495 +:10AA90007079A1ADD44EF8A2FFB8C92BA99C7F4C08 +:10AAA0002E443E4C3F2003E18DFEF6898F0790FE39 +:10AAB000A213C53752BE7CFA098C3FD8BEA7B3F8A3 +:10AAC00057E45F11E1A4917D2FECCA4EFBBD83C713 +:10AAD000E1F8DD7FBCE8F14AF2C3C7CB8A695C09C3 +:10AAE000DBE97E78911E871A8E17D97B22E2D1FD91 +:10AAF0001922DFBEC5F3FB47695FB078B7D94BF9C0 +:10AB00008EC566FFA604A4AFE805C9DB80B31DE9C6 +:10AB10003EF4248D8BF6A452BE66F1EEEF1DA2F634 +:10AB2000DA5D12D3DFDFBE287F17C5C7A0ECA5B85A +:10AB3000D7DF7E57C1BD84730EDC537057C47C478A +:10AB400052855F597C9599E371EF68FB2F2B29CFD4 +:10AB5000A9ED60FFD0FBEA1E0B7F57B04B020FAE92 +:10AB6000F388E7F0AF890FBDFB4E5A08E497B69E15 +:10AB7000B4F4C4F1CF467901B77161CEBF6EB7F0BE +:10AB80003DCABD7FB0D07A6B9EFB88F369556D12CC +:10AB9000FBA7AA67E4A04A799E03AF58483F6B9A87 +:10ABA00025C8CC8A6C37733BF951AAFFB159F865B7 +:10ABB00043EFD7E87A6EE8BD61076B74FF75D7D6AF +:10ABC000683DBF17B42DA3F1FD7B9A57F33DA07BE1 +:10ABD000B6C7F75F861F5C4BFB528C2B6B9F8AEED0 +:10ABE00077DF907E07D8BFC7FAC95732F4F3D83C55 +:10ABF000C823FD1E0CAF19AFA03D7D7EB26A3CC4D8 +:10AC0000C93B1ED7F180118F07C3268E67B1FDFAAD +:10AC1000DA2E5A288ED676FE99F16B79FB672C874F +:10AC2000CAF60EBEAF7A3DF837101FAF6FB73B09BB +:10AC30004757F608BB5FD26E0D06256A0F35917C2B +:10AC4000FB0F8AEF3B02AF4A8CA340F77F6B757E08 +:10AC5000AED5F9B716F76763E8DE8ABEFFBE2F7779 +:10AC6000C711BAE251A33FDFD0753899F8B8048410 +:10AC70007F5A1212FEC99087115F46C6D1816F9329 +:10AC80003CD7B75BF9BEF852DD3F2D6D16DF93C59B +:10AC9000FA8BFE517691FFDD2BE88D8DA735ADD176 +:10ACA000FDBB32D2D9DF0FEA78F813C3DFE8F2A890 +:10ACB0001C003BE5E797A8B237C86F752B347FE7D8 +:10ACC0005489CF633BD58929F1EE4B19E59B3ACEE8 +:10ACD00037EACB284F86FD43CEED8EC87DFC8D999B +:10ACE00002AF54CD910324CF887DCFB2A2ACB8FB84 +:10ACF0001EC844BADF187BD74FA645EE7BB41D397A +:10AD0000A4673FF23C5E49F78C6A9B857FE89B8D88 +:10AD1000E3A6108E07C6C5B5CDD620ED4F6A514FBC +:10AD2000F87B30D20FB2BF766911E907EE1B1C9990 +:10AD300048CF723AAAC4F52F6FC3388EC32F2FFBAA +:10AD40008CF5AA2B5BAC1BF996196F1F61EC1F6A7F +:10AD50002E099C6A3CAF517A781F51D32EEE49B729 +:10AD60001EFA625C16D2DB7FE03FC6ADC67241A61A +:10AD700088BFAD25A18FE9BECFE7BB6C71F1E8902C +:10AD8000BF979AD80E6ACC3D198C57F6232E9C8516 +:10AD90007EF3ED4F79DFD17A28E14ECAC7F5ADF1E8 +:10ADA0008F777E839C1A6013E3DA4DD0C425E19E31 +:10ADB000481CB8D629EE0FDDABC749AA3F8C7A7D77 +:10ADC0002FF65D5014CFEE035BE64923EDDDF01B5B +:10ADD000D5BABEAF2FD8B1858EE063F151B56E47BD +:10ADE00088FC392EC6E2A21B33A3F5B4E1ED44C6BC +:10ADF000B9FD5DB29372C4C8D75F8C26DC87F87E3C +:10AE0000429C3CEBA7BA5EF6EAE7BE0DB365E69B53 +:10AE1000698E280D1C85FC637DE93FE908521CCB37 +:10AE20003FF8CA0492FFFA9DD1E745243F3FDFDF98 +:10AE30000AB2FCAA43763E4332DA5F3AF8CA14D229 +:10AE4000B386B7BFCC1172F922C7E2BE3C7D46295A +:10AE50004962FF6B92C4FE77AFD2934CFBAEDAFD32 +:10AE6000B22FF2FEBC21E7BB75FD0145ECF3D765BF +:10AE7000AA5C6F68177A613A204A9C7FA5C8F3984C +:10AE800079FE11ED25A82FDF10B780E842D9D79AB7 +:10AE90000758EF6A4F9A989EDA938319D911EF05F4 +:10AEA00068DC4CF27B0D1B80FD881DC8BF2EA5EF12 +:10AEB0000FB1BEF4FD04C65947263C5229CEAD64FD +:10AEC00020BFF5C0DB559323FDFF053DEE03F1C127 +:10AED0004328E70931BFCE874DB042CF13083DAEBE +:10AEE000D2712CEEAF9AC88E63F757578A931B0E18 +:10AEF0005881F2C7B51F58F93ED0E707D6F2FE1DBC +:10AF00002EF927939F01BFFF6A2A1F38B876323D7A +:10AF1000FFFCE07D5773DE53DA1495AF08107D1EF9 +:10AF2000C2517F79F776C2975D0AE390A2AED3EF64 +:10AF3000D2F9EA9E56337F9B59BD77C6E38124C27E +:10AF40004F454BE9BB9D3D9D0AEB1FE22A0347D9C4 +:10AF500019479D28661C85E3F8825C161FABA47117 +:10AF60004F9414533709DBC99F4D271CE518C6556C +:10AF7000063DFF9C29F8D9DF91C0F9130926083D49 +:10AF800083EC28BA37B4BECE3864439B1CF5BD862B +:10AF9000F1DEEE4C71AEB0D7D0B390A4B11EED1679 +:10AFA000E586B63D19B48EF5E610EB4943B359B4C6 +:10AFB000EF1225D0F9CD0CFED83840FC39468F5021 +:10AFC0002E4B2CC1B184DB770F9D07EAF73982E263 +:10AFD0005E5D63E744FE6E68B0738F3B5EFC394E86 +:10AFE000E73348DAD12CB1CF896DAFF3887CC6D175 +:10AFF00033C22F1E5DE89F1CCF3F06A044ECFB250B +:10B000005D7EADE68A78E7861B3D22DFB4736CE097 +:10B0100028E971EFEE043E37EC7589FC6C694B97BB +:10B0200042DF9FAC6F9566503C5A9FFB1E7F9F820C +:10B03000F562F683E1FD7C6E5ADDBCBB5C8B43C7D9 +:10B04000B51E111F97E8DF018FD057BDFD1478D3CF +:10B05000F57DDA23745E73AAD2EC14DF9989EF4A86 +:10B060006FD0FDF98DD79B19379D02D52CCE3FC4EB +:10B0700039C532DD2FDFA0FBF911DF3B3F039BE930 +:10B080009C22F67B67C3AFDFAC8FBF02341E37F65E +:10B09000BBF59B753C78B32FFAF9A54C1D07E6402C +:10B0A0000EF9F310C617BE1F9197C0717A69E1A41B +:10B0B000B83883BE0357F5EFC0A934E4DE90F71E1D +:10B0C000C7BFA31D677ECDDF139C49800971CEC524 +:10B0D00086E39FE13F6E12F2D6CF2DAA9D824643B2 +:10B0E000EE17700716991F33E43E46E7FFFFF13D68 +:10B0F000A05C5022F325CFCAFE311E3A9FB0F53234 +:10B10000FEC615701CC4758DD3D735CE1A11DF2E2F +:10B110008C5A1D577F87D7971A1071C4CD65479EEB +:10B120009571627548E2EFFBAAC3625F5B5D26F62C +:10B13000B539AD02A7AEBC490A6A12BBC3D3449F5E +:10B14000A13FCB6C020F187A32C42F5D7FA89DF00F +:10B15000C10D3A3E88D5A3C9D05D4EF9E65B34C92E +:10B160004BF72A477C3FBF6ADAEBE4EE2FA73FA8F4 +:10B170006FFCEF22C4EAD1F73DFE120FE5D3BA0708 +:10B180005716E2B847F3FE388EF4A6E63276F32D72 +:10B190008F88133B1D81A37CDFA4453FEF6FC96BF4 +:10B1A000EB217E7402E3C75E57F7963A81ABF9BC98 +:10B1B000BF3A9CC0DF4356B7DBF9BBB0EAD686C4C2 +:10B1C00029E47FDB65AF1DEB95AD27CB889F95C547 +:10B1D000E23E4AAD5DDC8BB3B9FDB7107DD77B3B5A +:10B1E000A2CFF92D3DBFA8FB063D8FF56B1B09A330 +:10B1F000A5FFF7F99B8D3A5FEABA2E664CC1A9FE0E +:10B2000090E6AF267DEC7FFD450B1DD7D54E79A589 +:10B210009CAE886DF4A8DCEFFAE68E264AF31AF4A9 +:10B2200077643AF9F95173702CE3D2822BBB0FD3B8 +:10B23000B0FF8DA914A7FA3ABAA65A22F4BBB70EEA +:10B24000FD731CF9358049B75B854B495AA1E3254D +:10B2500061C7B5070E67503EA297ECB780CA7792D8 +:10B26000B3B1ACDE7D2A7912E196BDA21CC219ED04 +:10B2700032F703A527E7E6A448FA36337D17426282 +:10B280001C809E9C1B0B23DB1BFF5FDBFFD3A427D3 +:10B29000D5B69E28FB37F884BB7CFE3E3770D0CAFB +:10B2A000F708E8BCC61521C757747F340B374B64C9 +:10B2B000A773E87C7A22413B05EEA0BA026125958E +:10B2C000CE8BC3B2B87F3796FDF74C7DFE594AB896 +:10B2D00083EEE9CED1CF37E74237F75B00035C6AF4 +:10B2E000E0E4EF8B4BC0CBE56C5B7829C1F1825079 +:10B2F00088BF9F096728AE7336FD3BE638F21EE62D +:10B300009B02E70C7EC8740E26EE1BC5AEA75BD76A +:10B31000C7599AF03B041DE87EEE6C08F1B9FB3585 +:10B32000D0A39FBFC75FC73CDCF7D1B9DB35683B13 +:10B3300089CC8F20F79F4FEB91E3ADA767298B193D +:10B34000CA9C449F14CE307D6DBFF275F4D36D4D11 +:10B35000CA57DF35D0F783E2E1734B6FFB1BEFD3A6 +:10B360007D6249D3F8BEB197BEC7A67D4E58E91D90 +:10B37000F2631300FEDDB3E637646FC6F71AE00729 +:10B38000BEE711FBBD062DF77CC6F03D35E3FEEDB3 +:10B39000CEE00A95EE6FAC72DBF8DFAD29B28D9B83 +:10B3A0004E79CA87D2FCBF21BDFA406A9EC4832869 +:10B3B000C1198C6375BDB283369BD62F69C6F7223F +:10B3C000C0FA32F4EF0164007FB763B78AEF691EF9 +:10B3D000413DB4A5B2F6AB740F1A1E2E55092F6F5E +:10B3E00071D9BCF45DAE95E8B50FD3DB6813F72FC8 +:10B3F0008CFB6BB17C6CB419794AAF8D7176CC77CC +:10B400003E77DAFCFF9BE8BF3FA924937060FECB38 +:10B41000F33D7C3F29C15877898DEBC3F71A193763 +:10B4200036D17D6AA4AB311DF81EE2E1A49C14BAAA +:10B430001FD5D825EE5337A607D87F9BFD12FBF307 +:10B44000C6CED24E8A07830E0BDFAB6E74F934AAD8 +:10B4500007D22144FE9FF83EDFE0BB6998EF21FD53 +:10B460005E5091EDD75751DE7F9A1B4AE9BD696165 +:10B470006D12F1C0F81E06E5E019954ECFA3EF7BE3 +:10B4800081E2E4FB17861C503158999DBA7C0DB9B6 +:10B49000388DEFF83525EA3B7E435E8F240AB99854 +:10B4A000E926CC447E57A57163E561F0FDBF008FAE +:10B4B00040AEB13049000000000000000000000074 +:10B4C0001F8B08000000000000FF3B24C3C0F0A356 +:10B4D0001E81EF4A313030F1A28AD112EFE364606D +:10B4E00010E062603005E2FB3C0C0C3380F44C2031 +:10B4F00016E566601003E21A20DE0DC47B80F819A1 +:10B5000050FC3910EF00E21B3C10FDBE4C0C0CFE51 +:10B51000401C08C4C140FC958181E11B03F1F67316 +:10B520000A33304C1547F02F03D99F24E9E7FFC1B8 +:10B5300086430CE96BDF71A07DF3AC107C46207B69 +:10B54000BE15AA9A0556F8CD588826BF088DBF1893 +:10B550008FFE720354FE5A4D34B3B581E90949CDCB +:10B560003A4DFC6E41C7AA40FFA9013100ADF15F21 +:10B57000CA68030000000000000000000000000096 +:10B580001F8B08000000000000FFE57D097894D5BE +:10B59000D5F07DE75D66269999BC816CAC4ED844A8 +:10B5A0000B7442421A10DB618B6811834B051798AC +:10B5B00008644F2620F5C7DAEFCF40005151438B86 +:10B5C000355AB40304051B34D88041020EE0822DA5 +:10B5D000D5D86A5DDAD2A0C81A93801BFE5DFCCE76 +:10B5E00039F7BEC9FB4E2682B5FFFFF5FBFEF8F822 +:10B5F0005CEE7BF7B3DD73CE3DF78EE218C7948B1C +:10B6000018FB12FFBEC798DDC6181BD79D32562304 +:10B61000D24A2DCFCD58D003FFCC62ACDCAD85979C +:10B62000A7333665871AF95E12E43748613BE46D4B +:10B630007B9D54DEBE9EE7236ECDCFA0FCA33AC80F +:10B640004BD0DEDEF2C06550DEB943661BB1DB9144 +:10B65000713696C2D83107E37F5990CF66ACC0C926 +:10B66000B3E51BF6CDC5F6454D76E684FECA7715E3 +:10B67000CEBC0CF28507558655CA372FD3FA43BE88 +:10B68000382C3560BE63329F5F68A71CDE0CF53B2B +:10B690003C2D2937B8183B55E5605E8DB16A774B74 +:10B6A000CAF5A3182B096FCFC57625F5920F973AE7 +:10B6B00065C7E697FBE1BAB64A3EBB97B1D22DF11A +:10B6C000CC3B92CFE14BF8FF58A31CF91E942F8678 +:10B6D0007532E8B790D5E43219C75FAB79DDDDF09C +:10B6E0003B55A5D33846BE7C2B8C03ED2A9E967C19 +:10B6F000B8C40A1B0B34C0F8EDBB9CB337B9707DDE +:10B70000CBB4116E5CD7DD1AD62B0CE7EF747A71CF +:10B710007E1BB45C282F59BF412B18D5DD5FE996FD +:10B72000BED679D50E4D0D98CAA3D353558C794703 +:10B7300074E74B18F33740BF4C096BB346777FFF74 +:10B74000802532968CFDCBCCEBE8EE1F2049DF4301 +:10B750006FC13F015EA13D6E82AB81B7C53AFCDB94 +:10B76000DB8DB7B3BAC0A3D2996DEEDF481F403C62 +:10B77000C07C6A104E90AE11F3F34C649314E8DF72 +:10B78000E367BAC47A5F8F91D6A82C9FC1580B4249 +:10B79000A3FDCA78C86B6C11F331F69315D9FEA9D5 +:10B7A00090BF9F05E6E2BC57488122C413630D6930 +:10B7B00048BFAB24361BD7FF039C3494AFEA07F491 +:10B7C0000970AF9996BD4996C4DC93305FF0C4BD53 +:10B7D000E9D44F21F5A3423F43CFDF8F9E9B63E91E +:10B7E00047CF2D32FAA9A47E9C17D64F4DEE04EB1D +:10B7F0007C724B8C7EEEA47EDC17B62EFD8A89D639 +:10B80000F95C5146FD244EF5B100D4970D7A602DB8 +:10B810007E19CA5DF58963EF6566BA98BC12F9DFD7 +:10B820000D5C62A68B849C380B1D26FAFB58F2D067 +:10B83000937EEC5B220F834412351A5FEBAF915C71 +:10B8400098D4DF41F93BFABB482EDC312170B10EB0 +:10B85000F3C0B1593FC86B816FEB31E81AE629B1EB +:10B86000344CBD364CA3CBEF56391C260FF8DB8881 +:10B8700023D03E68EB1C9108F9F5D2A45F205C361A +:10B88000331BC1274E6695582FCECE483EDD9D9E78 +:10B89000BD296482D3EA41807FA9BBDFD56A200D30 +:10B8A000E96B2BBB2184F4B66A10ACA73F634F85CC +:10B8B000AE8F8414683FA8200DE169D780BFCDE327 +:10B8C0006B30FE281AFF191C77078E3FAEE7F8F69B +:10B8D000213996F11D838B2CE33B34181FE87D172B +:10B8E000BB558C0FF09BC0D8F3A15B687CFBE022BA +:10B8F0001AFF6E8D1559C68FEB1AFF051CF7A5DED2 +:10B90000D63F648275FD834BACEBD7F8FA5F650BCD +:10B91000C5F871B4FE5F8716F0F50F2EE1EBB7F3B3 +:10B920007EBBC6F774C1FF751CF7ADDED63F74A2AF +:10B9300075FD179559D76FE7E3BFCBCAC5F82E1A27 +:10B94000FFBD50195FFF456534BE660FF8908EB499 +:10B9500001719561189F0D0486482519E5A7746447 +:10B960001FC6A0FD3A3684E070471CA7BBCFE2801B +:10B97000DE5CDDF28E8581A3409E55089A2FAD9F37 +:10B98000A4A19CA572907B0BC5541734C9B4DFB039 +:10B9900075F6F070986F7B931CC2FC827597876573 +:10B9A000DAEFD8BC3C6CA7B0087EFFF0A1D11BCD6C +:10B9B000EB8A4E17D6A8C75A2D7CC4E7139ACC46FB +:10B9C00056C2FCA621118CEBCE1F0339CA407EBEA5 +:10B9D0000F7214D3E32A8C07DF8F829C659A996FCC +:10B9E00096F17D3CC4DE1C99827282FF1D5338BCE7 +:10B9F0008F2D91C208FFCFD62ED2503E2DAC890795 +:10BA0000A077CF2328F0D4B9CB1EDE28113CBD0887 +:10BA10009F1B891519FB33A0B51F80B6B0B6AFA523 +:10BA2000DD2D2CBC320DEACF5F933F4887F5DF3C1C +:10BA3000DB3E56C6FD83F907D8888FD9005B0E63BD +:10BA4000B31BD7AA032073E36CF5FD5653FB3901F2 +:10BA50006BFEE6226BBE5D0DAB36D4378A25B60190 +:10BA6000FABDB5D25A6E8C9328F5E17815E3FD2026 +:10BA700085CFF7564CC7E2679DF03A57E76D8DF9D1 +:10BA800004EF525984F6CBD66446F84FA67A019D4E +:10BA9000AF3B7ABE7355873F0FE633F74E99E019F7 +:10BAA0003DFFD6BDF17EDB18486B3F569104A3D70E +:10BAB000133DFF794BA3D7A3931E961F8AFECEE9B1 +:10BAC000249A9E824D93FA1E35D52B6FB8B2EF5152 +:10BAD000137D956E9965C91787E758EA17D6E65B17 +:10BAE000CA17D6145BCAE7AF5E64C9E787EEB4D461 +:10BAF0009FB77499A5FCD6CA7B2CE53717ADB5E482 +:10BB0000E7041EB1D4BF71F6064BB96DEF25D720FF +:10BB10001F55BF2533DC373E751D7B00F5C14F5DDA +:10BB20008A0FF171A22A8DF8E0549597D2F6A64CAF +:10BB30004780CBC1025471162E6B08AD9E88729956 +:10BB400091FC2C5EB633141A08DAADE425F8C9B5B9 +:10BB50001A8B00094BAC4F171D77CAA6F2D6F39487 +:10BB6000D702A367F62C975B637F0F6ECCBF08E507 +:10BB70004E6FF200FE06E03ED721F6F7E8F232897A +:10BB8000E599BF33B69CF8FC9C90B3651A9707659E +:10BB9000CFF69BCC3C988F8CA8FCAAF11A00A82861 +:10BBA00027513B4F467A002EB0D0CB500B7FB7EDDC +:10BBB00093695E152813C6A3C8C95B23A19C891C81 +:10BBC000187CDD689C87FF7E09F9AE2999F6F5B6E9 +:10BBD000AAE97D8F2A889F3C4A4F54CDA6F4585538 +:10BBE00080D2A3554594BE5F5549696BD5524A0F23 +:10BBF000578528FD53D56A4ADFABAAA1F49DAA5AFE +:10BC00004AFF5015A6B4BDCA4FA9C10F5DF237490E +:10BC1000E8ABC2AE809D87F267C55A5640DD16E29A +:10BC2000735F1AF2F959D76723501F3FFB8E9DA10E +:10BC3000BEDF1BBCA2E9AD773CFA495F290803FED1 +:10BC4000337B963BE3389E9C36369D813CBA67F841 +:10BC500013BEDB46515E4192810DC937CB1DA3DF78 +:10BC6000618CF0753E3C317FE7986B011FC71EFD6C +:10BC70006B36F67B4EEC7F710764DA875964930F5D +:10BC8000F165821BED6B9D3B84BC3F0FFC3EEA825D +:10BC90005FCB6006E9044927FA3BDB68670AC2B15B +:10BCA000393E0CC4CFCE1EDCE4417E5C9C66D38F53 +:10BCB000C68083919637A4EB2EF3FED364CD9FAD5F +:10BCC00091A637903CF6265C3F1AE94AD78F0E437F +:10BCD000FCA7516AF4B3384DD38F02BF9EDA3234D9 +:10BCE00081EFDF61BE0FD62712BD825D48F5FFD51B +:10BCF000F3E9AD1F633E8C35B20F1C280FA06CE832 +:10BD0000F9ED9D1E78573ED1F2105FCDEA67A82F5E +:10BD1000C4C1FF5F0EC17E15CA1BFD061BE490FD6A +:10BD2000DBF8BDDE321EB4F31A3637B6EB9D6E1566 +:10BD300076CCA02B90571A1ACB64273A75EBBE929B +:10BD400068C9079BFAE9967D06FF01FC0F82524104 +:10BD5000BA291354D4A1B8564B30BF23283F012F22 +:10BD60004189D72B77B46A012F91630BEA19B7E5A4 +:10BD70001874E7BDF18F20EF4FFE4665F762F9DFDB +:10BD8000605650AE1AC520F76C909F2F72B735964B +:10BD9000CE40B977D2C6F7F9052CCF83464F11AB09 +:10BDA000C9463DE723669B8EF4FF11FB9D27D364B4 +:10BDB0006FF86C1AAD73FE6AEB3E0BFA99255F586B +:10BDC0006BCD17B06B5390DE0BD6A92C2C215F5A8C +:10BDD000CBBD369DFA2D6495ABC8DE417B05C6BD53 +:10BDE0004D67CA00985FF9738F65E743FE3B36AE37 +:10BDF000A71BF67B711F3EFF92A4B0E687F20F1AD5 +:10BE0000337F7019C3F6E15528A7426EE6DBCC7A82 +:10BE1000E2EFEBCE3F7ABEC67ED2C38F20E6216F23 +:10BE200091FCE11876DA349B24F4AD10A537E0BA22 +:10BE30004D7A6BBE8083912F8FCADF1995FFA7E9DA +:10BE40002D8959E8ED8814C8B72573FA427D41520F +:10BE50003AB5C037E93FAD47FFE5FFD2FE0742FFE5 +:10BE6000D996FEEFFC97F63FACC7FC57C6EABFFC7D +:10BE7000B96D3B43206F4A9E79C8C3601F3AA9D46D +:10BE8000A4F800EF659B577A900E4E28210FD2F34D +:10BE9000C9B03C3D163DEC467A203FA2DF25A15DAE +:10BEA00085FF84FE4F3D75DF4CDC673EDBACEA640A +:10BEB0002F6DB147ECC0AF158DC533D818CA1FE13F +:10BEC000F9BBCFC8986FB2D267C9930FA5A0FF0D79 +:10BED0002845D81311D2972AEA3ECCC57D28C83A06 +:10BEE00089CFA2DBE1F8E7FA907CCCD7127A96C32F +:10BEF0003C49CF0F0AB8041BEF3B23A3EF93B57265 +:10BF00003F6854FD22A1FFD4DBDC49C7C07462DF67 +:10BF100061DF417969C08385B9FE53BDF5E13147E1 +:10BF2000603E6D75BFF1482638197C76B661FE2FEC +:10BF30009EF7F62E8FDB859DD7DD2E4CEDBC4D4256 +:10BF40006F6BE669991AF1A05E5CB641F585E07306 +:10BF5000D9B64D4F3C8A76EABB76DF70E8BF74DB1A +:10BF60004B7F9800F9D2ED6AD20CBE0C9794D28D1B +:10BF70009720FCBF746C371E4A7EF592E61DCDBF3C +:10BF8000FFB84F373E4AB7EFD3D8E89EF098D2B00B +:10BF90004F6B75C5C04BC3915CD4AFAAB77EAEA141 +:10BFA0003D7972AFC452D363C073C34BA427209CA6 +:10BFB000088F024F5D788BAA1F04BCA03C37F01499 +:10BFC0005DFE80903FD89F7714D1F3D3CFA35FF964 +:10BFD0003DBB0FD75FF4F4ED1E5CC771A592D3F59E +:10BFE000632B53FC306E911A4AD129E5DF8B1EFF7B +:10BFF00021D15BE11B3F4CE1F6A0BF9F8DF6A6501F +:10C000003F5CDFC2F537D0FA0A5880E8AEE8313934 +:10C010002F0CE9A70A9BBE3D065F64C89C2F8E6F5C +:10C0200004850BD6771CED12F4B3FE4E0E6F267FFF +:10C03000C82286FCFF43C33FCE1653FE5307C79367 +:10C0400043B609BE026DCF4CAF7577B7207E4E0D5B +:10C05000F2A7A21F2DC894908087F425F42BBF313E +:10C060002D95E38779956CD10EF48029F81DEBB7F7 +:10C07000A87EE7184B3BF6657AF7F84BC4F830EF2B +:10C0800038DCBF8FA7B0A28618EBBB5536F81EF67A +:10C0900071137D99F89BF37BDD3D9CBF0D7E0FCF27 +:10C0A0009A8EE59FBCC9F907DBE1FE08F38AA4522A +:10C0B000F9BEEB259207761689C5D775AAE06B6B9A +:10C0C000B94127306F454A30D10BF6DF87E04FFE8C +:10C0D000B38275D0CE242F83389EA7677F06DF16E4 +:10C0E0000AFE1F255BF99FADE77CDFBB7E15A27DB5 +:10C0F000AE4C0D3FF128F22BF067C88BFCAAE6E1AD +:10C10000BA4FD71FF8C34DC0A7A71B0C3EB5CACF67 +:10C11000683E2D7A76B384F419CDA7A78B401B898E +:10C12000C5A7F03D269F16B5FE3F959F06FCAE8F36 +:10C13000829F210F7B8363B43C3C63F3123CA3E5F5 +:10C1400021FCBDC9B27BD29F417706BD95FCB2FCF4 +:10C1500022F217187469D05D175D1A74D7C3FF6295 +:10C16000815F74F960A405A093BC5D2AD95565CDA3 +:10C17000FC3C0CDABD3C208BE0E4A76D8CD5BC3CCC +:10C1800020C99C0F47E51BA2EAFBA3F27951F503F6 +:10C1900051F94A4BFDB2A6031A23FC472CF5EC4B90 +:10C1A0001F651FC4B0878CFD26D878460B215D0C17 +:10C1B000ECD450DEA9CB410545FFE01E99ECC50E3D +:10C1C00080F12A18A7A33E3D1C02B9B1D2C9EDF0F7 +:10C1D0000EBDD3D307D295893CDF99ACAD42B96788 +:10C1E0007CEF74723F47475EA727D1E4A738D22C73 +:10C1F00093DC6E0DB3E9B1FC20B0A310DE5B596F88 +:10C20000E5DCFF394D760D5E8AF6688DEC431377D9 +:10C21000C1B21B3DE82AE9681E7ACD6CF8BEF05524 +:10C22000998E553AE23C63705E2CE457FA99EC899A +:10C23000132CF4B389E8CF6CE676C5823551FA0841 +:10C240005B43F454E05AA2A13C053BE07DAB3F9731 +:10C25000F34589E8AF68BDB5DC688F275A68DF957C +:10C26000D459CB03C23EDA65F04906CB2039838628 +:10C270000FDAE7422E4F93475D331BF0D1715066C2 +:10C28000789E79B659267C9CADE7E7972C944CFCB8 +:10C2900056C13A491E1A706A437ED27A97576D3B4F +:10C2A000FE9C7D17D2CDCE3F8EF939A46D3BDF1DAC +:10C2B000B11BF3CFBD3DF88FAC67FD297B9DE43703 +:10C2C000EED8EB267AEFD8F3DBC177617E979DFC41 +:10C2D000751D7B3F1F83F4D7B1DC5E84F2AE631023 +:10C2E000B787AAF77C3EA695F6D71584B7A3B2C642 +:10C2F000F5A3E6BF1E9692308555A1DEB0379EF8B5 +:10C3000029F8BC93FC0B1D7B3ECF0EB8FE75EBA944 +:10C3100010E7391D6E36FB599C5F22F78307778F34 +:10C32000DFB40CCFA31BF769F3A17CCA0B7F1F837B +:10C3300072B4E359AE0FB5ABAD8FE3794587FCE13D +:10C340003215E0DC8E4CD59FB1FB94119343A36270 +:10C35000C1E5EFE437B95078680AB74FFFFDE12136 +:10C36000F9B9BC73871D12AEFB8BC37F44B9B0D73C +:10C370004E7469ACF774C332D257CEB7EEE1CA7FC0 +:10C38000173AB8D0754B910B59F7D47F737CFF5A8D +:10C39000F6D2FCA2F9A0279DEFB983F2DBDC3E9A2E +:10C3A000EF05D2FB82FF69787F16F0EE39FFBAAB5A +:10C3B000FFCDD7DD3BDE5F9D2BF0AEE3797FF085CF +:10C3C000BFD3FCBEAE9CDBF4DF94EE0DBDFE159B2F +:10C3D000F7CD0CA83F9DD5B850B1B8B27CFFAB19D2 +:10C3E00050FACAC0038938DFC951E73746FAA6C2F6 +:10C3F000EDA6C9928DEC419628097B90DB51038410 +:10C40000FE30604901E9210306DECFF506C5BB0E0B +:10C41000CF1F5F193CDF47B1146CEC3B01CCEB97AD +:10C420008BBCD59EFCB9C4FC78343A60F0F70FA2FF +:10C430005E3B70A04C7A2FA4A4EFBEE899CEBF97C4 +:10C440006916BBE74AAFD50ECA4DB2DA4B53457FEA +:10C45000D3189FFF3497140E031C260FFA6912FAA3 +:10C4600047270F579904F95C165881F6C55497B5BC +:10C47000BF063CC319F7CDE168570D380E599787B1 +:10C48000701C24939FF4BC70C47913DC32C2182F43 +:10C49000C3141F87639F721FF99D85BD4D474D9043 +:10C4A000575CAB5A909F15B497391CC8CE36ECE553 +:10C4B000DEE0CD84FDAD88210DF82B0365BFD3DA16 +:10C4C0001FD9DF065EBE2E3E0C3C7E53BCBC1B85D6 +:10C4D0009781AE450AF2EB74B417FA62FD0C9E1F09 +:10C4E0001852E8DC4DD80B57781729A4F70CCC501C +:10C4F000105F858EA6ABF01CC4E193681E17B7D9F8 +:10C50000687F70644904F791B50AE5DFB0E9E3108C +:10C51000DF332F7BEEF49D0CFDE67E8DC73DE5F10C +:10C52000F38FBF7DF9E5448C1714782C84FFAF4658 +:10C530003FFF7A168903382D545828A10FFABD25DC +:10C54000F6BEC5EF6DCDE3DF7753BAFB395FFDDE95 +:10C55000E4CABF3A7D0EE4D8FB00F35D980EA3E178 +:10C5600015B35DFD9D660EAFE021161EC2E32AE401 +:10C570003CD339E11D82FE9FFBD3B39968D74EEAC5 +:10C580001895C0E5EB30B21782C25E38CBBC093ECD +:10C5900017CAD7A10974FE795076C78A2BDC2AEC1A +:10C5A000ED5F627C09A41D75AC4646FB8D75921F3C +:10C5B0003754E7609B63C4B7E4AB869F4AE00DFE47 +:10C5C000E46C3C8FE1E32F84A60966BCB5CD38A9A5 +:10C5D0008CE98907FC7BDF741EF54DE18BF63DC2CB +:10C5E00077ABB335372F86FCB85DC06FE6FE2FC83A +:10C5F000FF7969F3061BD2EFA57536CBF96AA92A34 +:10C60000ECB1B16C2CCE6BE67EA73B0BF17250F611 +:10C61000613C67B0F98C1688712E180D4FEC1FFD28 +:10C62000E95B559DF86BB7DA301FE1BAFB2307438E +:10C630003B7A9756531A6B9E03EC7C9E0B59C3EDC5 +:10C6400063D2FFFDE03BA9C315998CF6671D137EED +:10C650008F68FA6344C767B7B030EEAF68AFA25CCB +:10C66000385BCF687F0790DC8F7637F0FBF7CC7EA6 +:10C670009C8B9BB6FF12F5828A6649C723860AA562 +:10C6800055433F6DB02951C67D38C36BC4BBEAA387 +:10C69000AF37F1C5565521F81E98B0FB661CF7E37D +:10C6A000368DA19EE27FB1D383FBF8C7CD99C40735 +:10C6B000BDADEB5755ECAAA948372A9787D1F4307E +:10C6C000AA3ECE92BF4C0EF447FE9A696F5DE28B94 +:10C6D00081BFEF6B923817BC40F916FEFF4CBEBD10 +:10C6E00069C8B7809C67E2A3BE5A0FF9961A4BBE81 +:10C6F0002D96BCA908F7C57B86A6225E17BFAA2681 +:10C70000C7926FDBAAF839E733224EB9A311E4DBF5 +:10C71000B74DF2AD11E45B8C7890BF5FA87C0BFF46 +:10C72000D7F0DF36946F31D6AB6B56F936A6F908E1 +:10C73000C9B7318D364B3CAF5D3B9F7C9392AF4781 +:10C74000FDF8A0EA8B8F413FDB843EFE8C884BC412 +:10C750007150CEE56A3A8D7FA172EEE20B9573FFC0 +:10C76000457036E4DCE21D8CE29C7BD22197738B12 +:10C7700077819C93901EB99C5BBC8771BF5C947C55 +:10C780001BD943BE31AA5F11E1ED834DE90FDF02F2 +:10C79000FD8DF5AB3E07D41FDB2DEFC699E55DAEF1 +:10C7A000A610DC7AC8BB831726EF76087907726C6F +:10C7B00008CAD768FAF0355BE3C1778F3F5EFF2B7D +:10C7C000E497DFCA74DEF8868D9F0FBD36FE7816BB +:10C7D000D2D763623E8B84DC6BAF0A51FF535EE4B9 +:10C7E000EB2B77F138F18A46AE1F56D44B612FFC04 +:10C7F0003377C2171ACEBF788FC452213FCBCEEB0E +:10C80000B3278DF3323623C3440F0B724AC9CFBF0F +:10C8100040610EF4E397BA724FA2FE5B9AC3FDFE2D +:10C82000A5E27BF1ABADABD0FF5DFC8844E7A5464C +:10C830007CAB11E7DB236EA27919F977A3E32766B6 +:10C840008AB8A999BF94C21B62C47F946EB1E67F77 +:10C8500022F86F96DC4AF062AFCB31E3388C7A5D18 +:10C86000703A28E05427D37EDA0527809B37BD270E +:10C870009C00D3333252BAE152FC5B586F56EFEB57 +:10C8800035E016BD6EC37F5D2AFAE90D0E069C7B6E +:10C89000AC5FC01DEC029293D1F058A775F9B53387 +:10C8A000314E09E886E44CE8D70017182F6FD27094 +:10C8B000CB7D974705FD64D64C9A82E10CB330AE30 +:10C8C0001CCA0B6A17BDDC0FE031EE1DEF58DC4EC1 +:10C8D0002F9B600FE039EC566727C941830EDB358B +:10C8E000AE071C14F0DDDDBF7232D9F94D928E7A9D +:10C8F0004830E224B80601AE78FF28A870FC068113 +:10C900001E91FF0E3CF21987E31EC98BFE9D5C63EE +:10C91000BF42BC40FDCC668E97605822BC64B14ECD +:10C920003A7FA9A8957C11845FD306829F219FE15D +:10C93000CF65C693897E9558F44B954CFB65A9A8A5 +:10C9400037D35EF307A4E7994FAA6C03811BFEFB64 +:10C950002A7A3E4F1C50349EDA04BCB6213C5D0856 +:10C96000B74EAE7745BEA0FB504679500959E03925 +:10C97000E5D1735F09AF7106BC908E51BE35E7CB30 +:10C98000982F689258DFF49EEBC5F35033BF17EF32 +:10C9900039C2FB7F4CF2B118EBBE60BAEE859E8BBC +:10C9A000806EF1BCA437BA8E86533BD2F3B7BAE996 +:10C9B000F93567E7A14CA4E73D12F74334275ACE77 +:10C9C000353D761EF7B5D509740FEBEE7C55F56D48 +:10C9D000F4C690CB82EED17E30DF37BB041782F1F4 +:10C9E000A25B1C14EF47F318C2F553B37CDEE66478 +:10C9F000C9D767F5DEBFDB2EC58C2737F423233F6D +:10CA00001AC7C3F8F926186F64F778D1FB83E12FB2 +:10CA100038DFBAFADBBFD9BA8C71BE6E3C5490B520 +:10CA2000105E8DB8A82352E0472AEA73D3254BFC49 +:10CA300015CC5CC8AD6FDC7FAA96DC7BFF2C4DA7C4 +:10CA4000FB74B7EBC6779DE8334F67E27C6FE2DBA0 +:10CA5000B8EF7FECE7E7985936F6D644DC3F26ABD3 +:10CA60000CE9EAE3432AF9A13F9ECAE36EAFF9ED70 +:10CA700001055D3ED7F0983876CD3889ECAC37B0FB +:10CA8000EBF1A8873B987F04C12F13EFED65D4D558 +:10CA90004CF1025F8FDD12AEC6D437A533E935C441 +:10CAA000DB249921DE5AFC7DA7B8207FFB872C036D +:10CAB0005DA0A01F50FBB1075932D69BE04F263333 +:10CAC000667CE3276F5E07F3187F48F679A1DEAC3A +:10CAD000032E17037D7AE47A1B0B98E0358185AB32 +:10CAE000D1DF34FEA8FF3A9C7711E83B784FA4A829 +:10CAF0007943B507F3EB256A1F0C05723DB09E6DB7 +:10CB0000B56772BF857201EA6137C1F5BC5EB04E90 +:10CB1000F261887241F35A8A2F2AA893E842E1B65B +:10CB2000B0C41CBCDFB003FADDB61EDA67E1FE0557 +:10CB3000EDB1DFBA336F5E877207E649EDEBF9B905 +:10CB40007C01B4F322BFD42DA2FE8AD74B0CEFB3E5 +:10CB500014D5F37DA9E890EAC3F2C67D8FD07E3B61 +:10CB600003C6EB978EFB50642ADD0BCA9474BA2F70 +:10CB7000191A4CF8EB601C7F6CFA20F20B52BCAB1C +:10CB800097C0A098E363FE641F42F2B3C0B74CEBBA +:10CB90000BFDBC96939C6E23BA3A43E7ED4701DE4A +:10CBA0000180F71B225EE540CE075AAB695FFCC2ED +:10CBB0003E949F9B344DA2388E852C8FE238668E32 +:10CBC000E7FAE6EB973BC3E8E77B5DED1C88DF0FF8 +:10CBD0005C6EA7EFEDDBB81C6E1FD44AFEF6E3EBEC +:10CBE0005586F758AAD7CB242F8ED7AB743F567EE5 +:10CBF0008CC731146EE3FAC781F5BCDFE3A8B7E157 +:10CC0000B9079643BE70AB11E7C0E5B4617F16E883 +:10CC10003CFEC290BBE562DD3DF6A175CB3424D964 +:10CC200068795B2EE471098B90BD1C2D77CBF11CCC +:10CC3000DD837C191D27E6EAB663900E225F105D46 +:10CC4000571C5219DA31D2076DB91497B647A2733F +:10CC50008BF1CD921FE31A8ADEB18749FF0EE7CF31 +:10CC6000FB11EE2FEFDA19862C1F433C809CCAB1D2 +:10CC700077FEE9A7F0FDE41B0E8C0802BAC927B8BD +:10CC80001B71BE599B793C4FD61BEB52F03E2F9B3C +:10CC9000DA97E44061ADCC0226397152F25F771326 +:10CCA000DF1F74D4770C7C66693505B8BF7ECBC1B5 +:10CCB000F755EF66156364D8EF843D04F6811FF5E0 +:10CCC0009BE25D6B5334131D14EF599B22C3F75540 +:10CCD000221EA61AF7576857ACF1718AF74AFA066E +:10CCE000D338463F46BFDA2EDE6EE81E9EF6D67F6C +:10CCF00031CE8FD6F9A986F222BA9F1EE3F7D24F22 +:10CD0000CEEFCFAD93605E39AFCB14AC9EF3C18C48 +:10CD1000A1E6731D2335FCCAD96FDA98DF04BF9CE6 +:10CD20003FC531BF09DF8DE380EF017F5737496190 +:10CD3000A784F9235A7916E575E4F30AE17FAE98E2 +:10CD4000CACFEB1A33DE58817C3F234B227A60A195 +:10CD500080D63789F4352FFAFD0BB378FB42688F04 +:10CD6000FCD8F808E74F90135E942315EBD7E652F2 +:10CD7000FD3AC98BFD376EC8277DA4284766545EEF +:10CD80007784F4A3A2A62349C8C7C0B7EB501FA855 +:10CD90009868D7518E1BFC68F0F7EBE23E2B73E8E6 +:10CDA000A3F17EC6FF46E68BC1D7F2212ED783F5CD +:10CDB0009C1F83399C5F5FDFA6E20A2F84BF899F97 +:10CDC0008F6FE1FC2A3F76432EDE872FDCCCEFC34A +:10CDD0001F583F45437DFA7858A2FDA6277F73BDB3 +:10CDE000359ABFAB25BEEF7D5DFDD2E06F838FE14D +:10CDF000EF6A1CAF0CF814EF4F46F3F54CB5E10F9A +:10CE0000B7C37CAF791AD603F39DF2DD3B3DAD2667 +:10CE10003909F914CC17283C9ECB902BE50A8FFBDF +:10CE2000FBDAF38B1A3F6CB7FA477E674FE4F1EBFE +:10CE3000752AD1FDF9F8B3079F5D207F5E285F9DBD +:10CE40008F3F8DF1E53DD67E7E27E82DBABF7680F7 +:10CE50006B04E0FA4AFD268AF3FDE8A92333113F6B +:10CE6000A5BB81CE91BEEADD2C82724E09D37E55E0 +:10CE7000D228D33D01A644B2AF739BF998C76D95F4 +:10CE80003EE3267A2A79D61E9E01ED4B767E3086C9 +:10CE9000E2689677525C5AE829A12F875AC7201F6B +:10CEA00094283C7E2C5A2E041CDC0FD7B62B7E36E1 +:10CEB000AE4FDAC2DF8F2869B851B59BCE256E74AC +:10CEC000A8463D3AD70D011DE3FD5D9C9FF9DD02AB +:10CED000236EAC6D2B9713254D2AD981255BB6B7F0 +:10CEE00063FC70C93B76F27705B79CA1FB10539E9B +:10CEF000D946FE9460936C397FEB11B7B9458ED853 +:10CF000031EEB0B19CCE1D217F84F20DB1E397CFFD +:10CF1000175F58FACC9E9D210061E9AF9EF4A07C7A +:10CF200039D5B2D98370877EBF326EBA479C66C34B +:10CF30003D5F19A7790AFF018C738F43D835469C52 +:10CF4000EB96BEA447C2FCB2F3629C7374E9E5DBC6 +:10CF50003E7D1CEF11B43D7BFA719C6FD93F3E7E44 +:10CF60001CE3C1D85E27ED77C1A7DEA2386CA3DD34 +:10CF700026B1DFB56F7D92E2D7DBDFB5FBB0B7F648 +:10CF80003DC707633C60FBF62F52D06FB964CF34C6 +:10CF9000F2EB2ED9312595C5D82F8C14E9367C01BA +:10CFA000F1F3D1F83AD07880E2D63E027CA3FCEBD4 +:10CFB0008ABB6D28E771CC5E116F5B1FFB9E428FB1 +:10CFC000F8DAC6EBAEB91CE57E23D71FCF1B67FB93 +:10CFD00026E0F1DB1780BF7AC32F101B7F1FE13FD4 +:10CFE000004FFBA2F0F769E3C25F3C8A658D7D7B51 +:10CFF0008DB38D5C00DC8C7B100F38FC871CC988DE +:10D00000E75F525C33E26D8617F79F4F07E3FD91B0 +:10D01000136AE75CBA5FB8C7AE63BC68C99EB789DC +:10D020007FDA77BC417E6826EE23B4B3AE3F1E3F65 +:10D030002E8975D6B9797CAE803FC6EF7A3DF45D16 +:10D04000C4E9723A36E2777B8BDB959D5CCF36EE96 +:10D050006794D7FD51C4C376E34BCA413C1DF9CA5E +:10D060007868030EBA90C3DD71E8B1E3A3BBEE2B81 +:10D07000087C21FE701FEA8A3387FCC0B1E4377A4E +:10D080009BC59007ED1B78FC7ABB1AFB5EB011972D +:10D09000FE8F683E0D5F583CFAF9E6FF75E1D381DB +:10D0A000CA4F724F38B5FD2DB61C4F774ADFEC9E44 +:10D0B0006199147D6FCAEB1C87713B4734B483BB05 +:10D0C000EC6CB1DE36E1576F7B4AA678E5550D076B +:10D0D000488E47CB8B0A7C2F25C67C33C57C2B9A88 +:10D0E000F83ED1F6AC3BEC827EDAF6EF227AAEA8BF +:10D0F0003F42F1D22F6FF995D66A8A8BC07D226CA0 +:10D100009A7FDBD3FBC690DC16EFB2448F33498C99 +:10D11000136C8E3D4EB0FE8C659CD25083A6BBCE68 +:10D120003FDE29C57F23F677AA85EB83A71AE4E9BA +:10D13000E118E30F73AAD677A160BFA4F767DCFC00 +:10D14000BD19D91347FAE51277CE3B0949986A14FD +:10D15000AF55BD4CC477FD872F0DF15DEDBE8AE163 +:10D160007C57227C4D7E1E550F30D44BD5B4BC2C41 +:10D17000F42B44CB1B2DC9C6C226FC2F714F4FF593 +:10D18000D279476420E2F370C67115FBFD4B949F82 +:10D19000EA2F0A5B950AF3FB4B48F22D837ED9DF19 +:10D1A0003E1894E7EED97F971EF163D9E257AAB0F3 +:10D1B000771E46BB84BDE0A4F80679AF93DEF9087C +:10D1C0003EEEA4F51ED8F1F913A45FFFC2CEF8B964 +:10D1D0000F582F20AF0A75DEC7F11D9F3FFE57D4B1 +:10D1E0009FB1318C5FF838D447BBA13E9EEC9C8E3A +:10D1F0006713C6A05FA4F085BB66A23C2B8CE7F446 +:10D2000058F84C6AB81AFA3B96CCF3C7B60DA27719 +:10D21000254A9F7553DCE8811DCF55E0BED4FE4CF6 +:10D220003CC37DA9FD05A1E7FF52BC5355AB7ACDA8 +:10D23000F1E3C54CF19AEFF39462DE12AFC4C82F4C +:10D24000417C84FEAAA604BA0704FAAFA59F8FD436 +:10D25000CE3B7C44C7A1FEFCFE53A43FCA83E87AC0 +:10D2600046F9BDCE21E25E39B47375D70F6A9D05CC +:10D270003C5FD39FCB9316AAFFB053F88F4579CF6D +:10D280007E79FD8784FCEEEE87B7AF10EFD044D3F4 +:10D29000EF46D16FE996BF5F1CEB9D9518F3A7EFA2 +:10D2A0003F9458C8867ACA7627BD7F85EF28E07DEF +:10D2B000859D1A3FD72AF344E89D9BDD421E97C502 +:10D2C00045E8DD9DFE621E581FF3CCD1FA34BD9FA8 +:10D2D000F69C93615C59F90B6E3FE2BB7CE7E7C7B4 +:10D2E0007E9E857189F114175FFEC2FF223A28B72E +:10D2F00047E6223F746EB7B38DC8E7DB5F1D8CFC39 +:10D30000DAA64606F7F98AF3BAF206BBF5FEBF586D +:10D31000C7A9AADACBF0BEBB71AFB6A41739F357D1 +:10D3200027D7A35F71FA5F7212BF5BDF733A55357F +:10D330003B13DF5930EA973862CBC577515E7C13D7 +:10D3400039EEEA713FF55D9CCF47AC2505FD3E15F2 +:10D35000A077A33C2FD9923E10FD04FB9DC63B0451 +:10D36000DE04DC8FF6AB5EB2A73135EF3327AA7C43 +:10D3700099CA30F4DF8CCC54601D1D1BCE14F467A9 +:10D380001847EA9C1D4BEE9D76C6D33A4A1CF69888 +:10D39000F79DCF09BA7A0F8DFE643E1EF28731EEFB +:10D3A0007E354C72F88E382FD52B01BB08BF976E97 +:10D3B000999369797F45A9A17AC0A704CF62B64E37 +:10D3C000CB32C96F63BCE2A559994A267E57FE4FFE +:10D3D00017BDCADD7866A124D20B150163B6AE9FD6 +:10D3E000E57E88A2E639107E1ACBD3151949A586A9 +:10D3F000F83D8E3550EA02758BBF5356C9504E9E8C +:10D4000010E7F6E8EFC2B41B5E7792DC0F0D626C9A +:10D41000783ABE07E14DD04DF053F1101EE6635748 +:10D420002A1997173374B493A550807D09F4545D7D +:10D43000353D13E911FEFC180749A607CCCFA3BF61 +:10D44000FC05EA4140A7FC3DBFEFB270358018C330 +:10D4500081C9AF3A99F177E856BFC3CCF6C6A5713A +:10D460009278E7681FC93117EBFEEB843C8A55942C +:10D47000B7D509FFC8C1734497CE22A817C6BB58B9 +:10D48000241E52D728E59499FF3D599037D1A93EE3 +:10D49000D15A1ECD1720D7A2C66D20F841BF9F4498 +:10D4A000F5FB4954BF9F7C55BF069C828E8D3E7C08 +:10D4B000A76265559E801B1FCF21E006F01989EFFA +:10D4C000E8315B9C4F9C87135CE3C46CEC581FF005 +:10D4D0005A1E974E78B92F616F27C641B3A45A865A +:10D4E00076EF0A89EFD3F097E732B563BA83F8F0A5 +:10D4F0001E314EB980F30AC33FD5A3BE93F4AF1ECD +:10D50000F59DBDD58F8B5DDFDDDB7CE263CF27B181 +:10D5100097FE6BE263F6FF75E552C50B6FBF86E7BA +:10D52000B65DF24907D05BF5CCF238D433138FFDEA +:10D53000A395BE703DD331D08AEF38A46FA0B7B8A1 +:10D5400061D6EFD174D21B7DE58B7540DED50FE03F +:10D550007093187F6A1D3FF7BE6509F7D38179E89C +:10D56000C7FA378BFA37390AC9DF70C4C6DFBFBACA +:10D57000A596EB91B7FC58A6F3E91EEF51E13F8069 +:10D58000DF6E5D2A8523E9B1DED76275783F6E9E36 +:10D59000183FFABDAA00F3E6AE9663BD57C5E9D2BF +:10D5A000B85717FD4EC5029627DE21B37E3FEBD458 +:10D5B000BBE467CDA8EE7D2CB416E81EF54FA07B2A +:10D5C0003C97C7EB621417E2D1785C48CB203A4F06 +:10D5D00033E4DFD991DE04DCAF997F30FFAEF3EFA7 +:10D5E0008BAFF4A69AEF1D2AE7E22CEFF554ABBE01 +:10D5F00034946FEA39D05FC154D6CE0D615E533991 +:10D60000E8ADC4FC18BE49722A4D09A35C54F43C31 +:10D6100056887AAF78EFC3A8AF255DD5A567BE0E53 +:10D62000FF6F8E4B26BE5CBCD64BF7B63F8BCFDB75 +:10D6300089F4247B727C01574F7A08EDE0EBAEC68B +:10D6400075A7F75C4FB5E6F391BE7D158080FC6F42 +:10D650003E07CE4FB67BDFF6E2FC7EA332F4BBF48E +:10D66000848FEF4418CACF8607507C889C306304AF +:10D670008EBF46BC6FBABA6A24A52BAA984879BC5B +:10D68000DC8A2AAF487344EA17E974AA776F551AFF +:10D69000E55755F92835E0EBF0D5D0FB938E617C4A +:10D6A0007C872EF0976413F00B90FEE548ABA473D3 +:10D6B00045A75E19C177DFD840D87770597A0DC178 +:10D6C00057D319F935A13EE5ED988754AD9D41F842 +:10D6D00052F44A5608E56FC5078E225C9DDE4B2D3D +:10D6E000EF5ADAD3C646BD7F1A056F83DEB671B82E +:10D6F000DF2F717A8B86FBFD6A8B17E322EEBFB2B8 +:10D70000EB5D29823B98431CEEBFE6E7B43DE1DECA +:10D71000327BBE09EEEEECE904F7FB049CEF1670D9 +:10D72000AD1678A816F0AC46B8537EA4C8FB443AB0 +:10D730009DD27BC4FBB72B111F90CA087780877DD1 +:10D740005488C9301EBA79F1CFEE1274ABDBC81F12 +:10D750002ABBF2FC08777B1287BBC3057820BA0688 +:10D76000B87BB13C44F0545D1CCE509FE341E415BE +:10D77000847B267EE7F800B8F78D1F87F27082055C +:10D78000CE5AD2E40B83FB237C7F4B127C1E0DBF51 +:10D79000248DBFAF6BF0776FFA71B588B7AE16EF17 +:10D7A00027221C51AF7908E0C3340E4FFE7DA4C878 +:10D7B000FB284D16F67F35E001CB1F16FA10C21973 +:10D7C000D31FC573FB3CC956B94F4538F5E1EFF29D +:10D7D000B0A4101B98CD78682FFEA5859817F3C6C6 +:10D7E000F9AFD74A3FB2AE44BD03E97D18E96DDD1C +:10D7F000ABAA0DCF3FE4A55759EE67CBB3FD895EC9 +:10D80000827F4042BDE63EC1876B915E687EDC1E32 +:10D810005E29E8E06EF1FEEE3D827EEE17FCFCA094 +:10D8200041373E7E3F64CD741EC798946113EF204C +:10D830004698394E30D1D7C0349817D9365E4AE968 +:10D840009D4BF68E9DF8367E14F3237D25BE7367BF +:10D8500098BF439BD70FF5A144E3DDD989DEC439D6 +:10D8600074313DA288F720656E4FB6C47CDFB5DA0F +:10D87000B7DF817E99DEE613EFF3A7AF84F1E26BA9 +:10D88000DD6447F50DE4CD590879572DD8550CCBFB +:10D89000B97C70C1BC0B4DF411DF8B5F47755D59CE +:10D8A00080F44AF638A43FA91DEA44F802ACBDE86A +:10D8B000BF7A48CDEB87FBC14389B1FD70B3E2B9B4 +:10D8C000BFC49375A9C59FB04EF5533B7DA255DEED +:10D8D000AC13FB439FA956FE30F683CB447F9FC514 +:10D8E000077E140F7496726E2AC9CFA46B63EF0F74 +:10D8F000D5AA16C2F739AA4773BE0EE56B5C6FEE68 +:10D900002177189D839C0D8CD888FE2F83BE96337B +:10D910002EE7428CEB93C6BA7E86F43E02F7019D59 +:10D92000E81EF701CCCBC334A29B945B6CE47F5818 +:10D9300025F8EC5EC15F6B045F3D807C3502DF81C2 +:10D94000F651FA13C14FEB90FF20DD129FCEF57810 +:10D95000F1BE9761C72C778CA5F71CAB5D36DA0F4B +:10D960009477ED6117DA05FBC6EBE8F791DD597A9C +:10D97000C08DE5590E3FC0434ACCD2915E3E732F15 +:10D98000B8E8ABE25B01FDF4AEB0A2727FA49E9456 +:10D99000C7DE1F45A753F49E80AA5FCBD03FFD7022 +:10D9A00052A513E1FC703C8FD3AACDCF26B8033E1D +:10D9B000B6C59BE2A552675FD5F51E1F76FF702F97 +:10D9C000EF12EC12F2820D0CB16126F9502BDE7BC6 +:10D9D00064DE101B699213CB87E732F4EBF5940FEA +:10D9E000BDC8CBCD5C5EAE9062CB4B437F37E46568 +:10D9F000B45C31D295174DB7DCA7545D3E46F26654 +:10DA0000646CFFC1EFE3EDFC1D6AE6F3E5A7F72CBC +:10DA10000778FDDE0C2FD4830C7FC5F762AC275A44 +:10DA20003E9EB8CAD85703F43ED002CDFBF0F8AF03 +:10DA3000DC57ADFB41E1B9D5A40F149CCBA1B4A830 +:10DA4000763AF111C3D318939D7C7CFD0F3D88DF9E +:10DA5000E3B5E27C7CBD1AC6B8A47D1BEF7A600EEC +:10DA6000C075C1E3329D8FE33D0DD914DFC2B2BC56 +:10DA7000A4A71BEF231E0FDFEE31C73114FCD4E93E +:10DA800047FDBF377A2C581FDB7F538DFF44BB8384 +:10DA9000F946A25D01FA5D6704F5BF9F38E9DD181C +:10DAA000231FDA18EF33C78F18E95BF1D3CE21DCDF +:10DAB000DF8AF73317D29DAB0F9DD7F4CE177CDCEE +:10DAC00063E833C773D247459C35C07D96C57FCA8E +:10DAD000CF498F097F1873F4521E27CABDBD947BAE +:10DAE000783C13D36397FFD37EA4513DECB421B8A7 +:10DAF000FEF2DAD3ABDEA52FD6F3806211C7BD608C +:10DB0000637C78790CBE5920EE072F10E75D067D07 +:10DB1000157FDFD0B3395D46D3ADF4D42544A71FBC +:10DB20001F54C95F5B01F4877A98F4D4787A8F69BF +:10DB3000D913973D780BC0F993433295979D731095 +:10DB40005DB6FF878FE2FC3B7FABD2EF267C727025 +:10DB50001AC5EBB78BF79EBBF8CEC5EDDA1B5C5C44 +:10DB6000AE149CBB97E8BB8BAEC2F335E4DB82738B +:10DB70000F905E5680EFBD4EC0758F78799222E887 +:10DB80007702B61F92BB1CEA15B6723E61134315AD +:10DB9000E48FDE10EFBB37063FDFE0F25AE2450BC1 +:10DBA0005BD750FF0CF4C324535CC802F1FB07851C +:10DBB00078B884E57A88A521DF08F9D64DFFD677B5 +:10DBC000B0DB9DD6751AE9C2AE754EB0D861DDEBFB +:10DBD000FC2EE773A16F14B6E6F07975ADE7E7E3C5 +:10DBE00063ADA77B1D13A97D7B62ECF1EF17E31FEB +:10DBF000AB2AC29B5BAC44BCB75B10BE5DC3F7D520 +:10DC00000AD627F6914CEB2AAC2DB5C42B15D4E6D9 +:10DC1000D3FB7A85EBF3B5DB4CFB53175E42FE97E3 +:10DC2000270DEBC6CBFD6B2E23BCA8AEBC3B917E73 +:10DC30008F3D557CC77B5EEC97E3E984161A534908 +:10DC4000F2EA764FACFB4DF747E3A956E009EC80CA +:10DC50002C139E0CFC44B73FB6B9FC8EF7F01CE2C7 +:10DC600011FE9A50EFF22B0A7FE9B1E1F7A4A0D799 +:10DC700063A00F042E087EDFB2C4CBF50A3F816F8C +:10DC8000033EC677D0E7C208B727913793B13F4E1E +:10DC90000FE7835BF7F8821E26C55ECF6B5DEB59FD +:10DCA000CA42A0C79CD4B83ED1FB7AEE6221C70518 +:10DCB000ACA78B4FF32D7CFADA9A5B389F0AFC9F56 +:10DCC000DC7F0FD1F5B170BC0FE3547A5BCF6B48AA +:10DCD00007E362D0C1B0101B95FD7F8F0E4E68FE2A +:10DCE000118FE03E02FB15EED3C54FDE3FC63CBFB1 +:10DCF000B7E227FD9EF6A59A0B3BA70E4DF61DF445 +:10DD0000D27E27FBAA6149435D813F63FB12CFA30B +:10DD10009FA19F6E45E2CFC6C4D28B5756052EC732 +:10DD2000F38BEAAAA2CBD18FAA0A3D97A19E9BCEE4 +:10DD30007F1723D67B7DCCCDF1BBB2AA92CE3F9884 +:10DD400023C4F494EE7700D8894CF2472B2EAB7E97 +:10DD5000A6A9011DFDDF9A78A7405502ABD3B3D029 +:10DD60005F94941132C1EF1F2E7EEEB2266DBF8EEE +:10DD7000E71A76E81FFD608E81CA598BFFEC456576 +:10DD8000415FC093F11C731C6BF04B12F913CF462B +:10DD9000F913CF5AE69104F3FE0A3B5B7178E81C55 +:10DDA0005261C28F2CE0015F681FBB5BE7EB5C1E1A +:10DDB000EF217D60D54536B2EBD609FFF4CFD02FE9 +:10DDC0004D7051E8BC01C3E0B0BE96C0D7E1C4734A +:10DDD0000C19EDAD08E5DDF862974C4F1F4A984FDE +:10DDE000645E09F37D596415DA0F1D935AEF203FE5 +:10DDF000A03390E606BC7ED6AFE5B084E712798109 +:10DE00008B11CEB57228C30BF57F21776660BDC13B +:10DE100050F44E1F9E5E84F71202A6F3CE21B48EFC +:10DE2000EEBCDC337FD15225EAFCEF6F179BCB5F52 +:10DE300071FA2FC679543BF9FB60491F4874BE57ED +:10DE4000DD75EE9447FBF26437C723D105D2D54187 +:10DE5000AE379D55BC097DC89F3D32F345CB3C7C18 +:10DE600096BC22ECD13AA0533CA732E86398E2B7C3 +:10DE7000211D0DAF81EF663CC6D077FBB8E879F085 +:10DE800098FAB9313F1897E8553E97CBF7E3287ACF +:10DE9000D82DF1F9878AEDDC6E642119F13AC7209B +:10DEA0003C6505CF2732E38FECB5778D7327B682BB +:10DEB000E7759E0BDEC6CFB9A3E733A7F9EE163C94 +:10DEC000EF99D3DC6F3E9E7BCE29BAF8434C77ABFB +:10DED0009DFBE3515EFC50227DF6A6B75E54E32124 +:10DEE000DDF1E6467A9F60AE9BEFBF7359A78AF8D3 +:10DEF0000F305DE3E756615ADF6DCC27F20D2AFA49 +:10DF00001D6E89846FB81A72B7BE18BE1AD5BDB916 +:10DF1000073B5F42B4051AF45C3A1B32DA35F95E0E +:10DF2000E679DEAE0B0E4EF1FB478A83D6D5BD6E89 +:10DF300007C1C15827D4247C74C149BCCF66C0A591 +:10DF40006BDDF1375F85FEF8DEE4DC1CC7E80F7996 +:10DF50009C3C9F57349C3EC12290930BDDFE1FB921 +:10DF6000A1FC7AB7FF2E4CCB1C9D839521C437555D +:10DF700098AF900317A5001C3E1A14B83819E1D1C8 +:10DF8000D2F782F4FEC34E2E0F0EA71B7A6DAB1B89 +:10DF9000E99BBDC8F55AE3F73256ED387EFF8D0098 +:10DFA0009F8F5EE5EFCD95CBDE6BEE22FFB2CC62AC +:10DFB000D921467A58F80D1E76DBC47BD17C9DF3BF +:10DFC000140EEF798DF174CF6EDE52D9F2BEFDBC26 +:10DFD000A53C7E95292D63AEB7D8092B045DF7ECDF +:10DFE00007FD1AD1FDCC5F3A99DE2DD9A9E993C876 +:10DFF000CFF138A7B3F953FD32C6FD4F582D911F0D +:10E0000069FC516F532BE4E787137DC8AEF3EF5CD7 +:10E010009C89EF9754B4703F67AABC28E33F207DEA +:10E02000683FDFEF31BF08E1E4F27B5DA6F39A368B +:10E03000B53243477ABED5E54779907FBDFF5DC4D1 +:10E04000A7E1E730F6DDE7400FC038CEFC5BBC3916 +:10E05000481FF90D4E3FA50EA6C4815CCB5798030F +:10E06000D3548D294E4CE39803D3ECE5427FAA9D0F +:10E0700045FA8327274FC3F7C4F39B9FFC14DB1794 +:10E080002A917D92899EF29B5FFD82EEC3F9F3286F +:10E090004EF75B5B348BDD39BAC19AFF7693359FBF +:10E0A00011B1E6330F5AF303706D267D73FF1E1E08 +:10E0B0009F527A9ADFEF7D1E60A0223CB6D9493E7E +:10E0C0004E296DCEC67887D34FBB6D58BEFBEFDCB3 +:10E0D000EEEEDCEAA47725F7BD17C7E292F01D6AE1 +:10E0E000E7462C3F1DD7908DFE45A84F714BB0BB26 +:10E0F0008E40BB71E7A506BD8629BE69E73FF8FDE6 +:10E1000094CEADF630C6519CDEF5E4D3489FA7B758 +:10E110000E207DEC792964C37E43F770FC4F88F3B1 +:10E1200058E454E916AB3D7E42E8011D27B579E875 +:10E1300017BAB8D6BAEE4BC2D67CA7A87F1B337DE0 +:10E140004FC7F810EFAA34DC6737C57EBFFD73C137 +:10E15000174F3DA519742B8BF71E9937A5FBBEE20F +:10E16000EEEE73DB2503808E4A111643BABF974645 +:10E170008DDB850FD17F92382FEBFCAD4CF03955FC +:10E18000556489EFE8D2FBAA7C69534DFB5141ED00 +:10E19000BE947CD257F7A5DC66DA67CAB61E48B9CA +:10E1A00019FA6BDBA2D0EFEB95CD79E2810949F842 +:10E1B0005D6EC0F96239FAE7DA1A5EF2603DD08B23 +:10E1C000C79AE3BD0A6BC7A54D35F1E9D7A54B83C7 +:10E1D0009FCA740E9FE7725A72F11E46692DFF1D89 +:10E1E000BED2861BAEBB1AE1BE9EDF4FCF56589EF5 +:10E1F0000CFC53B6FD86EF8F86EFC1C7C6F9703EA3 +:10E20000D9F8242DDEBBAD3F43F776EEB571FF4460 +:10E21000345C467B387EEFFD81AB08E512F4F7A253 +:10E220006D2CB53F68037DE4C4E4D06B374395D3D0 +:10E23000ACE10F57535C96959E803E25D4B73A3794 +:10E240004BBE8DF47579F6B5A85AFB97513C3A94BC +:10E25000C7B4378AC3D67EA2F17CA547327EF76861 +:10E26000A4995EA2EBF59D11A2DFB72A5B0A72CDDD +:10E27000A4EF971DADA178D8E871C819688A3BC191 +:10E28000FDD14B7CEC147A02931CD9225E7C28CF02 +:10E29000D3BBA748974010A597B2A95E84EBB56C95 +:10E2A0003AA6CF4B91076499CB03F2336D8B277954 +:10E2B000D0A6B73EF173A4A3FAD1741ED65FDCEFEB +:10E2C0006EF346E8BD58E37771DA749E2F69765293 +:10E2D0003CD5E98F349297CB308E13EB3FEDB4D918 +:10E2E000405F3BBDBDEF648C0B6E6BE0EF8A9F6AB5 +:10E2F000E83B59FB8AFD379AEF8D7DF108FE13DF6D +:10E300004FF5F88B3DB8DFACE071D3A97D2B332AF4 +:10E3100063E0C96897A45566A0BDD279ABCBB7912D +:10E32000EB53E90AF9DDD3C8AF922FFC49F7E9793D +:10E330007778A0BE1BEAFAE1FF3E07E58DE877FC9F +:10E3400040F6DDA10FED3E1F5F9015A0FBE3F40347 +:10E350003630FE7C854514A0B7F9B8AF8CA13CC916 +:10E36000CFF9EB258A235CB0C6BA1E7CE7DABC1F66 +:10E3700016E12F290EC5B8B0064A8BD65BCB8B7140 +:10E38000FFF050BC17C5CB94D459CB198B901FAD5F +:10E39000ACFE4B7B2CB87DCA8CF5F96B3C16B9A34F +:10E3A00092DCF950CEA3F595A23700D29BC4FE1C97 +:10E3B000BC33276D01A41D4B27A42DC8C47BEE7C64 +:10E3C0001F23D38EF898BF8F573A954506F1777182 +:10E3D00018EE8FA5CD526434E61D2CE419CBBFE3B3 +:10E3E000FB20B86EF33D3163DDB85EF377F626C7E8 +:10E3F000AB71CF10D76B2E2F137028ABB75BFC3AE5 +:10E4000013EAA590FBDB787FA995DA55347E69B7CE +:10E41000F42BF65FD8B79913F035A168838C8B790C +:10E42000A84B8E872F89750FE5B080DF433714F432 +:10E43000437E7D10F5CFFE02C039249F849F804526 +:10E440001C305E5C66579ECAB397F3FC3E4FE08A71 +:10E45000DA8160AFA9013A879A2FE7BD8CF71B4795 +:10E4600026065E42BCCCB7F9072BC4B7FE11E417F1 +:10E470005DCAE1F0F0D8CA4B2A63D9C502BF3F9309 +:10E480001AE85C3EB48BEFA3EEAC4ED5ECF7FE8BF6 +:10E49000904709FB5BE95E4FE70E89EE133F221DB3 +:10E4A000A1FBB68F5CE96568C7A7019E50EE3E22CE +:10E4B000B115F85E5E56E3AC452F219EB3E27C7841 +:10E4C000DE5FDE38492E77D1FAB9BE155FB901CFCC +:10E4D0008352E78D1C8B740EEB9E772D7CFFD0E36F +:10E4E000A5F1FAB938DED39687D2178FC2F1F316A9 +:10E4F000BD847C383A8EEEA1A702ACDC7D285D8D10 +:10E500007A541ACBD887FA60DA0CEF58F4B93FE4A2 +:10E51000E1E324DBE479B350CF1BCBF37D7E2CF910 +:10E52000371211AEA57152ED6C3ACE17BFA35EE85B +:10E53000403F82CB84EF299519387EEA509E2669A8 +:10E54000118A0F3C64E0BD99C7E92DD119C9E925AD +:10E550005F4C4A453BEE501B18D420BF0E0D34ECE7 +:10E56000CC888BF4F06123797D61F72DC9E0F75FEA +:10E5700092061BFA0FAFD7A1FA133251AEBEC1F506 +:10E58000F14F5C7EF2575FA6C58EBF4F48E0780A18 +:10E590009E8B636193FF3838FB33D21383E73C2CA7 +:10E5A0006CDA27F0BD4D731C7759D17EFA1D847249 +:10E5B000D642F701CA1BAC71E797C5C51ED7A0F3B9 +:10E5C000E0391B0BF525321E88F6D721A973D5C279 +:10E5D00024BA174BE73BC1731A0B99C60F9EEB6326 +:10E5E000CD77CD3385FAE9AEC7ACF59A3EA77A2C44 +:10E5F000A7D583E3B4EBADB48F04CF29D4CED86FC5 +:10E600003AC2B6900AFCDCEEE5E51DE23CCFA86F0D +:10E61000F4D73E5B13F7DEF8BBE86D552078002E8B +:10E620008F369F217F7459F33E828B410FDDF08935 +:10E630006721137C52AA5B2236E0ED690F6EB87B2E +:10E6400014D890C9FB051F8736DDED9F08E5F8BBA0 +:10E650000F26BE8ECFEAE27312330FD9642E174213 +:10E6600075774F9D68CA8BFA5DED439BAF980A346E +:10E6700095358AB7BFE6C1275E594E4E8B1A11DF1A +:10E68000DF3938CF6DCA3BA2F22EC88F36E5F5A828 +:10E69000F2A4A8F2B4A8FC405EBFCD1D192CFB402B +:10E6A000DE3FF8D415F8FB9E6DFD2273F1058F3522 +:10E6B000F2B62BF0F77CCBB3F8EFD356344B3EC910 +:10E6C000243F2BBACEF35BB5F9A3100E2D2FA31C5C +:10E6D000286B9274D4EB5D0DDB2394C7765E53BB3D +:10E6E000066E3F96351CA176BDF63FD2467C7CEF88 +:10E6F000C8F7A9DEF9CE9FD80CEBEF5BF5761E7557 +:10E70000440A2C4E48EE7E7FBD6DFBDBDDBF2F0A39 +:10E71000DFDBFBF90F901C8DBA071EC4F9B8BAF9FC +:10E72000C480E3BD23CFD27BB47F1CDDFC16AA03DB +:10E73000F14BCE2C53A0DD9FCB8F8F437D0BDFB4ED +:10E74000C57DE36752F812DC8F1E65814B70DC5B80 +:10E75000CB87EFC39F4C38ACB63E86EF956F78F011 +:10E76000E52B1498DF6177EB20FC09B74D096FF0BA +:10E770007C722B7F5145FF1DE1E7F0A0D64136C8E2 +:10E780003F99C0A6537E78EB63987F3DE104AF3F8D +:10E79000BA7590ACA30972F28AA990DFACC7E6F70C +:10E7A000DA04AE371BF39B36DCFF53840B2BE3FB01 +:10E7B0000D5E3376803C9D5B726ADB6680C7DC1F32 +:10E7C000C5939CDBDC76DD55790487501EC611A607 +:10E7D0000A78D37E48725D217DA21FEE817DBAF159 +:10E7E000E91EDCE2A5FDE2D2CAEDA837A4CE1D45A4 +:10E7F000FB45A1C72FE9C9DD69381952A82FE93AAD +:10E8000097EBB28DE22352EF72931EF5A0F83D0311 +:10E81000E03BA20F97C0CB36B19E6D09DCBFF680FE +:10E82000671AF5F39EE47FC42163CA424EF2A7C57E +:10E8300091BE72F306902B20D7D78979AF5B7B0905 +:10E84000F9296E463FF128FCEEEFD76754B7FEBFBB +:10E850002E03F2AE6EBB6EDD2C7F3FF3B9F6BA0D20 +:10E86000BCDC905BEBD2797B63BF4AADE6E3A43EB0 +:10E8700078C9465C47BCC2287E7BE1EC111B97D16E +:10E88000FE7F2DAD9FF9FDFDD00E3F5A3CC4867A28 +:10E89000A9819FC2E1FE5712603D3789DFEF35F055 +:10E8A000648C4FB7E2517F90417F403B353140EB64 +:10E8B000077D620C0F6EE0FA04D21633C19729ADC2 +:10E8C000E3F0FBFF2038B5FD2BE0F44F9F7747C9FD +:10E8D0002190370CFB2F5F7ADC72FFED3F01D123D3 +:10E8E0002A700080000000001F8B0800000000005C +:10E8F00000FFC57D0B7854D5B5F03E73CEBC929920 +:10E9000064264C9249C8E38440081071124344F0D5 +:10E9100031848851693B50D4D87A71203C022699C1 +:10E92000A8D5624BFF0C12790918342250C181021C +:10E93000C55BF506458C1A70448A7AAFF68EADB782 +:10E94000576C7FFF08888F4A32A2F5D297FDD75ABD +:10E950007BEF64CE24A9B4B6BDF93EDCEEB3CFD9CB +:10E960007BEDB5D76BAFB5F61EA6F54C0A5CC0D8EB +:10E9700066256ACEAE642C7C48F1ED61F007CF6766 +:10E980003B19FBF7B4A0D595C9D89FF1EF0AC6E6AD +:10E990007EBF29275806ED8D2318CB612CF5BBCF00 +:10E9A000D4DE00D5B94B3F7A7C0F7C3FF77BA98C36 +:10E9B000E903EF438F8CC1F7EFBC6D5BCF2E84D2A0 +:10E9C000D2193579A0BC86F956C07BEF98584327F9 +:10E9D000F4F70EBE7A096355DFBBE5353691B1DB3E +:10E9E0005D2A6393185BABF873988A250BDBE0BB59 +:10E9F000F02C4B644F11637D1153D80CFD75B82377 +:10EA00005B17C1B81DD795F9C2D05F1F637E86EF33 +:10EA10002D4BA5F73ADC3D4CC3F64B741740C20EA4 +:10EA20007EA1FA19D4E3375A22BB14785ECEC2769F +:10EA30006C5F323E1286FAF3300E7D7F634A640FBC +:10EA4000B6CF828FA0DE71A3371286FEEC2C624710 +:10EA5000783A76FA73321C8CE5AAAC05E1EF28828D +:10EA60003A94592BD9CD0107E2CF3F719673000F2D +:10EA70005F7799683EA9953D4FFF37F4C7D6DB7D98 +:10EA800063A0B0E1AB586FCF2678993B5885F86604 +:10EA90001AFC03B8EA1FC889ACC3E7CC5785EBB1B1 +:10EAA000DAE99F47F0FF205547F81FB6B335B60A9D +:10EAB0002815D666CB00FC0B7858FB43000C633757 +:10EAC000E3008097FFD770D6A9C3F32B5D0AAD078B +:10EAD000FCF96D558CCD67BC7DFEF2D477958958D5 +:10EAE000AA516B1A3C5B73A5BFC746EFB13F8FE2DB +:10EAF000A50DFA0B32F1B725EE44BA09E27769D8D1 +:10EB0000FFEF9DBA03EBF0FD445C76F8BE74E0FBCA +:10EB10003A17A3F9CF5539FCAC355547FC4AFCC828 +:10EB2000B24EC2D7FE903F713C394E72BFF7BAFC6D +:10EB30003722BE00EFD1740FE245A5754D86D7632D +:10EB4000896FB043FBDC56D57D37E033B8CC49F351 +:10EB500095F0DE9C1DBF8C150FEEFF746A739586D1 +:10EB6000F35FC6E99D2DB702E212F16219A8035DB9 +:10EB70002C64F163266588E75AF445847F5147C2C7 +:10EB8000F7F4DF2FAC89EF497E61BA9204BFA02B66 +:10EB90005DD170DD820A5F378B253E375036186EA7 +:10EBA00089CFD582EE245D24E37B35E27BD2607C85 +:10EBB0007B2C3DF9D86F709995F094DC3F6311FA86 +:10EBC000EE213BF00FD0DD1645217ADD72576A64E5 +:10EBD00025F2A73DBE17F1193A7C15AD77EF9214D7 +:10EBE0009DC12BDB2C30419433879D9C8F4B7A4AFF +:10EBF000909F7A61CE7E589FDED7D59D614502C138 +:10EC000058F3EBEA2EA4FFDE67AFE6FDAC48D5195A +:10EC1000D4438861183714FE432B03BC9E34C52CA3 +:10EC2000345E17E057C209FF7AE15F43C580BCE854 +:10EC3000C3061CBF8BCB0798E1121AE7DB296C1DBA +:10EC40008CDB6C52FC26686F5E3A3EB292C3614325 +:10EC50003E6A1420359B589B5231C0F7CDA6132530 +:10EC6000B795F1360DDEBB85F17581F78E2A005F11 +:10EC7000A36D7D4C45BA45FA87F6A5D85E3480FF72 +:10EC8000E6F5BFF913C2DF7CC048178D8F19E7B1D5 +:10EC900034919E8A06E824B592E389D5B0C81880DD +:10ECA000D729EAA9B5B1888A785A56CD4E02E966C5 +:10ECB0001EE99981F4E3ACEC64F3A10C7DC0FC1176 +:10ECC000807B4AF7CE9746C2FBEEDA583E4E37B409 +:10ECD000ECB68B4E5D34B0BE12CE4BBA37A9CC41E8 +:10ECE000E3D177008A7FBF83DE1B37FB82C4F26EDD +:10ECF000FA2ED3A412BDF6E023E41BCD9FA3C038A7 +:10ED00009B978C32E17AA6827C43B9BCB07DECAE95 +:10ED10001584677F09CAB707D380CE099FBE2A949E +:10ED20002FA5EEEA5FBBA0BFA7DCD5FF8D258E1314 +:10ED300070E2F44790BE48A6E764BD23DFCB2E6E99 +:10ED4000296F710CFF1EF017E12DBE359DCB0F4DC5 +:10ED5000A1FAA2FF30EF5C47F0694437B76D2F226C +:10ED600079DCC0DA89DE1A59C482F4BBC8C6C2692C +:10ED700040178BE0B57428176FB1323D61FD9644A2 +:10ED80008CF546210F6E6131FAFE967D49ED352CEA +:10ED9000EA84F6261B8BA662D9696C6F667141EF17 +:10EDA0007FB6263E671D7CBE378B7577D744D4204F +:10EDB000CC7BAB1D745706BED04EEB3365F94E5A73 +:10EDC000CFF40A7FD13DA84F5E35FB7601DDBE272B +:10EDD000D64BE2E75E57F5BB88F714D544F38FDFD7 +:10EDE0006325FC9C02BD8DEB7F9F9BDD3C1BCADE37 +:10EDF00056DD3B7A34A2C95530DB3918CFEB9EB3D0 +:10EE00003720DDB8DD26C2B77C7ECC65A67AD5DD9D +:10EE100002FF2B5223BB8A08DD13919EAA46497D2F +:10EE2000CA26CE82FABB6656D709F5E6EB1D41EC41 +:10EE3000AF07ED07A817B8B9DE28705B687EB22E61 +:10EE4000E72BE906C6A1FE522EE2A584638C5BC8BF +:10EE500041B6897F27F4EFE625293B49FFF6D3AF7A +:10EE60008911FD96052C88D7E7845C794ECA9536C2 +:10EE70002B972B9A6BEE32A83FF741996F1DE095C7 +:10EE80009582DE83EF1B3F4AD1919E5EF9E85FEFEA +:10EE9000FD19B49FFDC0A25BA17D01D218ACDB734C +:10EEA0000A9747607F30D48F8DC0F6386EE3C1B1CA +:10EEB000647F1CB408FB46C8CFC6B4E0D685D04FEB +:10EEC000E393993EA064F6BC39F2E85E6C3F64F7C8 +:10EED000ED817E1B53385E1B9F1B49DF3F610F4E48 +:10EEE00077C33C73AD919F3C8172E3052BD97B675F +:10EEF000597411C27FB6D3AEE07B27705EE95042F1 +:10EF00009B82F3EA76923D047C9AB310BE3BB936FD +:10EF10009BCF4BE0E9E48609C4179BCD7CBCF0B3E2 +:10EF20000ABD7FC21C989103F5134F97FB564053BF +:10EF30005FC012B5003D87EEE3765EBD49DF8178A4 +:10EF4000628753095EB91EA18D8B67627B68E9F207 +:10EF5000AFA37C1C8ECF51DEB304B9D9CBE205C878 +:10EF60004FDB1A467546519F748FF3915A655E5870 +:10EF70007CA01B177FF79499E3357EC84CF47CBEC8 +:10EF8000FDE37CB52AAE7F709C10C86526F98FE43E +:10EF900072425D1DAACEC8FE0C3D972DEC3A63FB74 +:10EFA000EBCEE01D6EA0BFE6FBFFE79D6584DF387A +:10EFB000C945D69E497C79CAEC9F8B74EBAE895AC1 +:10EFC000E627E8F30D82AFEAADC2FE63514B221F84 +:10EFD000CAF6AA6A23DDCB72BDA07F678CCBF7C1CE +:10EFE000ED26C11FDFB4A21E9BC2416685A8471C47 +:10EFF000D8BF4EFD4FF9206AA9877AE1F2A8659142 +:10F0000028914F00DF511BCCFBD45627E76F4003FC +:10F01000F6B36832237DB94805FBB5029FEB5D3D31 +:10F02000B02EA79F7673FAFA236005F03D8F89F71B +:10F03000AC60EF821C7BA64D89E27E60DE16EB2E73 +:10F040007B11F2B55F75E27A6E57488ECD6B9B5699 +:10F05000B215EA4B0F5C40EB9F3699D3E5D2889B03 +:10F06000F4E214211FEBAD110BD9DF3F5118F2016F +:10F07000F44F7674237C945331180F28D70DF41075 +:10F0800049A8835D34A593CB5506F29C25D84B52F5 +:10F09000DEA31C6749F69F913EC2521F71B9C7F4A7 +:10F0A0006C947B522EDFEB0A74B949AE8DCEC6F557 +:10F0B00085F5E47273BF42786D622DA44FA41EE8FB +:10F0C0001F57E891D36A98EB2BEB262A5F7717D16D +:10F0D000784B5927E913A95786A383D7BF840E7E9F +:10F0E000867400ED8D1FB0E865305EE372166D9A90 +:10F0F000C84BE744D28F5C4FDAB89EC432E53CF48B +:10F1000065B27E4CD687C97A30DBC2F59D5C6769F3 +:10F11000CF644FE776C094E51195C1FC36A6F93F60 +:10F12000CE9C3460D784DEB2D9F40BB11E60A3E06C +:10F13000BDC569D36ECA86F690C6FCC857A980972C +:10F140009DF07CBBB07B6BB339DD7B2D9C7ECD5AB3 +:10F1500080953B705D62B4CF8D673217D2A3C4E750 +:10F1600076277C5781DF71FDD4FFBD8DB5A5247C4A +:10F170005FFD9C9DE4EAE7CF3A2356B24782856E55 +:10F18000E82FEB5756B2537B9F73923EED15FAD0A2 +:10F1900083F628D1CB2AAE5F715D272135558F6468 +:10F1A00048FBCA352351044AFBACC9CDEDACC1F6CE +:10F1B00090682F8A5DCFE9CA4AFBCCCFDD3D7762EC +:10F1C0001DE061689FFF8F58E7D081E9E5DF87E7A1 +:10F1D000A180C3C7B11F2C477AB5AADFB9DE06F4F8 +:10F1E00035435D1EBF0BE6D194EF70A19EAB29FCA9 +:10F1F000F52F6F84FA8707CCCC8AEBBC677A1D1B8E +:10F2000035BCFC5D12319FE849E0975BF619EB4D88 +:10F210009DC67AA8CB582FC8707A4E4F20D9E1FBF3 +:10F2200033D0B5D5DAF2C14E80D7FABC95F4D1A768 +:10F23000EE607106CA5B53FC18E2D95AF8F144F447 +:10F240006F84BA3F51B0B402EDC4CA38FE91AF3FEB +:10F25000B7CF2B740D81B701FC319B89F00CD63AE6 +:10F260002F49CE85049F782CFE0F5F84F92F9A9D3D +:10F27000E2BA9B9EF8674EAA427B926064A12D572A +:10F280007F88FB2D786F09AEFFE959F01EC0D5B01D +:10F2900085EBC346164B43BE6D06BBD3064B7C477E +:10F2A000065F875BDAE25551F8DF8E8CDA7108A7CA +:10F2B000F6272D80F4B11AFB4DB093AFCDE07AE084 +:10F2C000967D76D729031EDD867AA82BC7752A91ED +:10F2D000FF84FC61798A96B81F7A57095E8BF86BB8 +:10F2E000B2F558A6C1F857FCE93392F78B97CDA732 +:10F2F0007DC4805D6D25F9B4F8AE203D7F692BDFBC +:10F30000179EDE6AD711EFA7B7F3FDE3E23C47C4CF +:10F3100006FF7B859BDBDB8BE13B45198CC764BC1F +:10F32000BDFFF0555EA4A3F7191F2FDCC9ED8FF7C1 +:10F330005D80AF62FE0EF6F77E17D8EF0AE2F9AAFB +:10F340000F512E2EDEAEFAD04E60879CE48F59BC52 +:10F35000FDCA710B1DD8DFA723A6A15F68C795E87A +:10F3600089C2F70211EED7895D01CFB51D17931D34 +:10F370007774BB95C3E9B6EDC5795CF12795F84A7A +:10F3800033B120DAC71D16FF38E467FDE13D337065 +:10F390005DDE9F956BA2F71F57980BF1E15E968596 +:10F3A000CF172B5A00F9B761CB929989F64E6A862E +:10F3B0004AEB35AD7079568F83F8E97AD4A34DDBEB +:10F3C000817F70FCD96FFFF2464F223FDD5EC54C56 +:10F3D00009F6CBC35F237AC2BF28E06BB1C0D75711 +:10F3E000E52B6BAAE48B961294A38BEF6E29710D1B +:10F3F0006157F4F3C5C39C0FEFCB50B8FF202FC368 +:10F40000B0CF186E5FE62835915EB1F9987F0F9402 +:10F41000D9B02DC6FDF7810C8DDA0F64707B5FFBD0 +:10F42000DD6DFB5E87794DCD086ECF807A21F39735 +:10F43000E3BAEB71573598B18862B2BBD8C3566E48 +:10F44000C76ADC8EDE9CC9F6AE4BD88F77627F9997 +:10F450002417F6623FBDC7FF780CF1DA5CF0F14487 +:10F46000B40F42E73EB3A01FCDD1AD903C77F80278 +:10F470000CE925D43D8B2D281B90C3211FD713C920 +:10F48000F3FA5306DFEF843C71EAE7FD119C7F3B02 +:10F49000DC9C3EB72D4B213FE4364FC48E40FFB578 +:10F4A0007C2AEDA525C2EF67DBFD945F45FA8E2827 +:10F4B000AE3158D7397FF435CC8DA830CE87BB8B91 +:10F4C000C9DFD977609A4F8536C7EE1FAD198578A9 +:10F4D000EA32FBF07D87AF270DE7F7E1EE9369385D +:10F4E000BF86DD2ACDBB21F249D6C2B201B9F033C5 +:10F4F00025F83ACA01E6521C38BE940F1FEEFE34BE +:10F500006B8183FB0B487F560E8D97A7DCD37E8ED5 +:10F51000DF5F71395F978F1EB74650EE7D6407FD40 +:10F5200096206F3F72727D772A43EEEF3A0B50DFE1 +:10F53000F4D76F2A35A19CF88E8BCFDF63E92C407E +:10F540007EFC8D62EC67E91A138B806C5FB206500B +:10F5500003F2E8A3479F294079FFE19E670AE62767 +:10F56000C097FC9D2C7BE578C26F26FDA81E4B340E +:10F570000FC79BEFB3727FE5307E54F93EDBC2FDCF +:10F58000A17D3EAB8E7428BFEB6B48F1A37DDBC73A +:10F590006C24FFE6770BBFACDF3FDA83FB18F97D05 +:10F5A00052FF151E4E4F4A9742FE83D4B238C9E32C +:10F5B000BF59DE7B603D13E43DACF3BF215F34D91E +:10F5C000E2C74632A20F0BE2CDD2ECD0503F65AD80 +:10F5D000E4F415BFC344FB2A4BAED781F2EC8A9208 +:10F5E00094361330A227256D22C601F2734BE9FD34 +:10F5F0007035A7FB7016237F5B0E6B51485EBBB85E +:10F60000DF3E6F3273AD83EAAC11DC9EF132DF1660 +:10F61000B598D65D41FF90C487D40B483F281F3F63 +:10F62000526C443F4AB74276A76AEA9C8BFD0E476C +:10F630004F1347C8FD3FA7A7FEFA3F899E268F18A4 +:10F640008E9E823AD193D736343D093FF179BFCFB0 +:10F65000C201DCBF660B7CDD27E44EFC0E9BF49BF5 +:10F660002B38DF99A2BF9936475445FDE1337F9C83 +:10F67000E8FF7D18EC5FDC27E5A0FD0EE5C895F3FB +:10F68000745A3716EB417F41EAC536D28FF79A623A +:10F690004568AF648F6FD98F74913DB7AC6225ED2B +:10F6A000FFF2DCA80F50B7921F745975E0D488049C +:10F6B0007BE110DFCF34DFE5A7E7D3BBB97D101ABC +:10F6C0006D217B38D4A584719D9B039608DA416B2C +:10F6D00015EE5F096FB0EB3CEEA3AFA0B8CF0F748F +:10F6E0001E178A48FF6FCF8EEF23BD3538C8EF91C4 +:10F6F0001C3F3AF885CAC71FC368FC8E721EAFEA6A +:10F70000B85AE7FE15B17E1DB3FC396EB407D618A2 +:10F71000F959C685FA9C8018186FFE7A3BAD43AE46 +:10F72000CAF1CCD26D5CFF0C960BE467CE9A2C1616 +:10F7300046C46FFAF91C2405D67345BB8C3739CB08 +:10F7400002456879BFBBE9B7AFA400BD66A19F8E33 +:10F750006FCAC268F7937F98D7C97DFCA00900C91A +:10F76000C5D6FF5C577369425DBC3FF0FDDC6B6B37 +:10F77000F248EFF6B723D8A08F65DD6FD7311E357D +:10F78000D0AE81BD6BEB52F8F761C7B5578E063C22 +:10F790002872FCFF5CEB477FA19D19C64B844F4B41 +:10F7A000EADF0CFD3B74F97EBCF64A78E1C10A59E8 +:10F7B000BF66AD1FE0BBCF6CEC8F502ABEC78A1C62 +:10F7C000EFD6AC6DEBD6E70DD8056027EC1A913972 +:10F7D000601FAC7E7B66FB853056AAEB530BEA5D5F +:10F7E000A9E7431E85EC8F647E3D20E4C3DF2C57E0 +:10F7F000F54176F4811124577B66204BC2FE83E4E9 +:10F8000076687980A13D07F64817C2DB7BFCE3D31D +:10F810002F427BEFECDF1F1BA9E37BB7CE45BB3745 +:10F82000744E23BA0DED53230AD0AD4DF00BE871A1 +:10F830008A0B487A5AEA1274EA0E338C73741C529B +:10F84000268589BE5A0AAE83B5CCF7F85F4238E404 +:10F85000BE3279DEBF1EC1F70FA1D2EAAD25D8FFB7 +:10F860006E85A19DB0AEF444D602DA37BD9BB530AB +:10F87000E1BB255D0F123E97EC330F89C75F8FE028 +:10F8800071DEE6679FF6A3DCF828A2904C68D022D0 +:10F890006BA740BDA1C1849620AB8CCCBB91E21C70 +:10F8A00075163606E67704ED268463DF37C353709A +:10F8B000DEF04F8147DB028B489F6EABB339284E99 +:10F8C000543AFF56C2832BC58F7858575A9D83E30D +:10F8D00034CF9AE1A2F808D871D8DE7CD7B7C82F08 +:10F8E00024E15AD765AE453BA70AECB9A700EEFC68 +:10F8F0008C6B6A7DC0C723D5FDE5B73B305E3EB457 +:10F900001CFF6E26A78B362510FE4625F94159A20D +:10F910005FB3B08BDB8D9F8DB018E22B9F8DE0F62F +:10F92000ECA5E1D874249FC35A4F2ADAD321E6FF0D +:10F9300004F7CF2CE0D0F7D03A7179E469D5C93F0C +:10F9400066F3F4DC7B21B65FAAD1FE85693D0FE04A +:10F95000B8BD6B3DBE754CF001D6EF2AA37D4FBDFF +:10F9600027A87832F9BC707D7B9FBDAA1CFD88D288 +:10F97000EE5AFBA89DF4E65AA77E7F2DCAD3DF6915 +:10F980003C1FC0168F4D877E96FE3E83C65D6B8FF3 +:10F99000ACC5F50FEF54A9BDD8117460BF4BBEB90B +:10F9A0006522D22B73444A508F9A3DED0CE918B66C +:10F9B0002BE42FB179020CE3C4D3C3F33405F5452E +:10F9C000923D331DFD55B45FF190BFB65AF0C71894 +:10F9D000A082D3366285B63F8F18B06F5EF9E31C04 +:10F9E0000D1F4ABBC764E3FEF39ABA1486F62D5B7B +:10F9F000153F66427FBD27C6D00E6EEA54689CA6AE +:10FA0000D2272DB86FB9A593F37748EC33007F0563 +:10FA100068578CF1A40A7BA08DFB3958ECD848C4F8 +:10FA2000F3637C3D1983F712FCAB8CADE0F240F43C +:10FA30006711718626E157024D48ED3E8FB45BEFAA +:10FA400016FDB7F3528CBB5989F955C46BB962F0F6 +:10FA500087CBF22AF17DFA91F80CE4DF38D017FA5F +:10FA600097B62AB36EFD29CC6FEBA4F13E34C1BC2E +:10FA7000404E6A053E075204BC57767D3203E98644 +:10FA8000D532E2D7E6AE696A9383C76FD05EC84EBF +:10FA90006DD989EDD93797927EC6F8C86C78FE3556 +:10FAA0000FE7B31C07F7D779EF0E1761BC33FD489A +:10FAB000E0D69FE2F817A490BF351BD6C69941E562 +:10FAC0001AF46F7959F98BA87FBD33F50A8447C6BC +:10FAD000F5302E38AB8CE438D5337C8A7F179437D9 +:10FAE00078DC340EECEF6A115E7C1E710CC419D107 +:10FAF0006F87E3621C0FCBDE9CA8467E7ED0E77B3F +:10FB0000904EBBAC2EC4D7CCAE97DF427D3BD3C664 +:10FB10003A29EE9A64B7C4D3BE19443AED3B737ADE +:10FB2000C73D08D775077D94CF92648F5C7139B754 +:10FB3000CB3FDA93AA233FEC12721BEC471E7F796E +:10FB40009CEF2393EDC8EFF6AF2FB723FBEB7F7746 +:10FB50003B92C317DEC3F328A47C0F897D5F5FC38C +:10FB6000D934D45F2B3DD2AE4DCAF7D82DF23DBA71 +:10FB700087CEF7D076F2F80F864149EEBA2D22AE45 +:10FB8000E5F7CE43FF87BB84E4C02B7B53C34837E4 +:10FB9000673BED6497696E4B14E16A7BDA1AC13CEE +:10FBA000883645E0EB90885759441C2CA344478382 +:10FBB000E2A02540723FFCA499C7ABD2228FEE850C +:10FBC0007AE3E11C11CF62D47FF8D954C277638AFB +:10FBD0009E8EFD37FEFB088671AA3E180FD7F909E5 +:10FBE0007B70BB87E25ABC7FF68255E7F1B3688928 +:10FBF0001BF0B033C2EDBF93A5A6A805E6BD93895F +:10FC00003C9FF532AEC5E7D9B761248FCBA03182D6 +:10FC1000FBB2B5DC5F542FE35587B91FAE5EC4A5B8 +:10FC20004ECE5EF408A658B4292DB5B84FFB7CDD46 +:10FC300034F29FDF79FF2C2AEBD718FDFD8BD03FE4 +:10FC40005F3C103F967EF7F9CC67E1F6F380FFD07A +:10FC500004F68CBE46AB46FD59C45C77A33ED0C3C8 +:10FC6000B07A1743D906251AF10A6019DED3D67A7D +:10FC70005270BD57B799486F85DB4C7E7C4FD2CB15 +:10FC8000AB1EAE67DFF570BD03A88EE038B26C33F3 +:10FC90008B7883E86F053345B13429BC5CEDD26ABB +:10FCA00087D2DFB2BF36738B6D1ADACDF926F277C1 +:10FCB0007F6EF1D791BF38A384D6A9CDD9B2A696CD +:10FCC000B7132F7D6E8F07A8FD328D1B964CCF404A +:10FCD00079FA8287C71792F1B6B0DD584F8EC32CE0 +:10FCE0008918EBF52C3836A798C70D129FBF20F462 +:10FCF000C4E7EB8A04BE7D1694BB72FE2BF238DE9D +:10FD00004CF9BC1C955F5D8774300AE3CA45587294 +:10FD1000BF2ACC84E01F75994721FA4882B7CDCD20 +:10FD2000E929BC96FB21FF5AF893E1FED09325F810 +:10FD3000D8EFC5B865BDCB4271E8F3F597A4641A56 +:10FD4000F7B7FDF5BFFFFE96EFE7D7AA22BFC6457E +:10FD50007269BE8BCFE5A4E2DB1BC5E70EB01F7056 +:10FD60001E6BD50A9423D3BFE9A079341F063982CC +:10FD700071ACE53D05A8D79BAB7B4A305E938C5FA9 +:10FD8000845693F20CDE9BEF81FD08DA0D6B8CF14B +:10FD9000B8C1F1557F616626EE7B4EEE7F19F5D72F +:10FDA0007E3BE92FF8BF17ADC8FFCF16915C8B38AB +:10FDB0008363312E144A89EEF87111DA31DC8E6AD0 +:10FDC000EAB6EE443B717E5B427C0FFFB3DE18EF78 +:10FDD000636B32C8EFCE3A8CCF1B1E4EFA6E50FCCE +:10FDE000AF9DD665B325380EF91DF410E51D9C595D +:10FDF0006262B8BEF5AA6F112AA93376A37D7EC6CA +:10FE0000C9D76B46A6D43F3EB2BFFAEB83D6D957CB +:10FE100082EB5C6F62C1C47E9A709D617D1BC53AA6 +:10FE20009F79FAE2125CE78FF75F5C82EBBCD9DC6A +:10FE3000EE47BE297507AF41FC9CBA3240F615E685 +:10FE4000EF201F9D2F3DDE94448F37FDE3E8B12E58 +:10FE5000311F32593F36F4E3CBA81F3D163D0FE565 +:10FE6000C17C9BF52FEA49FC1BD29F67B392FFE34D +:10FE7000F01F3FDD48F918DD2AD927B2BFC35AB0B9 +:10FE800018EDA3C36F797D6165F8FED385FDE5B5F7 +:10FE9000B130FA59E4BE40DA97C9F278B998CF0385 +:10FEA00099FEDF8CF81BE23CD27FDC20DEB1453EC0 +:10FEB000E576EF6EC5C7FDC79DE44F6E3E34CF8536 +:10FEC000FEE20F22DC7FDCFC7439F98F97445E8AF6 +:10FED000623E19EB565CB81F59B2FBDD34CC03907F +:10FEE000FB5ED8E7DE9F49F935C6FDEF07919369C0 +:10FEF00098370070BF8F70A77AE216A4FB66D8FF10 +:10FF000061DE60B3163F86FD367B18D905955DC668 +:10FF1000FDA08CEF6E0B5848EE6EEB562228AFB367 +:10FF20002CC1A23CD46B2CCF753A7580CF2299FEA0 +:10FF300017907E07E2EAFE5D5897FEA79EADE94462 +:10FF4000BF3D66E677A13CDBEA14F24C23F9F6DB11 +:10FF500087DD91750976C36F23DC4E5822F3C134D7 +:10FF600016D560BD16CDF11FC7F546791F4D92F726 +:10FF7000897519AFBF8545492F35B19EFEBCB0C408 +:10FF8000F792E3F9180737F4C35ACA75F493DDE41E +:10FF9000F0519CABEBCF56637B98EF9B811F96553E +:10FFA0000CD0AF5C0749BFCDC21F1D6A38B10AE94A +:10FFB00037D4A5B8707FDDE8E3F4DB08FB2FCC9BDA +:10FFC0004DE677D669CC131D8EFF7FDDCF779CFF82 +:10FFD0007F3DAC9CFAC7F85BDFEF973F9CEFE5FCF9 +:10FFE000A5FFBE7F9EDD0AE7CBA47925EF5B93FDDD +:10FFF000EE72DF79BEF2F08B247C7CF10FC6C77005 +:020000022000DC +:10000000F230256BE8FD42725CE3AF9687FFE0F8C3 +:10001000C623871E4A3381A8585214F672BBCE6F8E +:100020008817CF501D7E1E3755793E4572DC5D9F87 +:1000300021E2EE9C9F5F7A5AA5F56A12F1E1A64390 +:100040004E1FBEDAE0584CF1D9E4F8E952B67F060B +:100050002E51721CB511F9B8F8CBE3A91765393DDB +:10006000249F745684790AC9795A2F393E1D114C40 +:1000700058EFEA32D8080C41D7362DCC32129E4FB9 +:10008000CBE2F6F44B229FC86BE1E705EE73A6FACC +:10009000711FE335F17CA77C4F607AD62494EF0280 +:1000A0009FCFDEC04C809747CC9D244FC24D0E1F82 +:1000B000CA3FE9C791FDEF10718BF3A5F36F671984 +:1000C000E9BCBFFE4FE2FB8592BEFFDAB8DD16C089 +:1000D0008D811F18D1EF6B18672A1A4CB7C3F533FF +:1000E0001CFD2ECB0ADC9E4578F14FA4FCE6F39470 +:1000F0002FA995F193E82F6207AC3AFA376DE2FC2D +:100100000B5B9F23F6EBBEAA599497CDCF8FC87394 +:1001100036C3D98F1BFBF99FDB8FFDF5BF93FDC85D +:10012000DC81769CE7A9697ECAFB5FED04F8715F0C +:10013000F8A875C8F32CF2DCC597F95DF6F6C3CDC7 +:10014000E96AEFB070FF63E5E793FF34F9F9FB3438 +:10015000F4A30EDF4F58E47BC6FC229EC67625F83A +:10016000B743319EAFF79280573E7F44E8C5F46CA9 +:10017000FF515CA78F8FDB6C2C1D4C9E4A2E179B6A +:10018000030E8A2F3477F2BC97E6E58CE47733FAD6 +:100190004FCBD0AF388BA1BD373523F833FC7EF57C +:1001A000DB8EB09A8E7EF7D90CEDBBDEE3BCFEA9E8 +:1001B0003BF8736C0F2DEFA17846C7EC8F28EFAAA0 +:1001C000EACF9FAEAAAD2478C98FE0B11ACFAD7C3B +:1001D00091C5E30FB2FC43BF3CF1935FFFE3069E82 +:1001E0009F1DF2F85DE88F907EF1543D467EA6E6B5 +:1001F00003DC68AB52F97CD8F7F3889E9A0F4C2B3E +:1002000047FF29EBB497A39D5BF52B07EDF73EBEA7 +:100210002B97F224EA3DC10F513E3A2B2357A35DA1 +:100220005A08E3A0BDFBF1FEABCB116E29FF36A34C +:10023000FF1CC6DFEC34FAC7998DE7D92FDD9B4F41 +:10024000FBCB6247F053EC6FB39DC311DE23CEA30B +:1002500008BF7932FF4BBECF564D344EF6B76D1402 +:100260002F977261B399056DC503F2E478962EF26B +:100270004C445E63F72C9EA722EA0E8F31BFF381B8 +:10028000CC2B8F233CC7B3B4AF961FE618942F40F6 +:10029000FD627E18C505589CFC2DA9E7B81D3DCA16 +:1002A00065217A7202DF519C06E809EDF94BE3B152 +:1002B000E9789E6B7447F452C4F3E17326C2933617 +:1002C000EB358AD3A42B7CBCE2F53D6BC7A21FC6DD +:1002D000F5E665B8A47ABBAB1A513A3523909F4D29 +:1002E000FB8C96521CAFFABFCC3C9FF2502AF917F8 +:1002F0003A0A1A299FB2F76DABE13C4E7219667744 +:1003000053FEE4A8AE5F50BCC0794019322F76721C +:10031000B683F0D61C8ECDA01C9B4B3D2467B54305 +:10032000BFA238B5B6564309C4DACC7E139E430B40 +:10033000AF60E4EF1CD3E132E17A158AFC98BEC3CA +:100340007F9818A4FD8A8C0F44787E93B96715EEC8 +:10035000C3B4153D9787713D0EB84DCD65D85FBCD0 +:1003600099FC2D875219D24F6157F1DD53A15EB828 +:10037000C645F1B0BEE76E2924FF2ACC73CC10F33A +:100380002CCA36F3FE0FA59A509F699B980F47D54C +:10039000DC59D504F78350877E468A3C55193F4582 +:1003A0003F14EAA9F4ECE0D7303FB6FF1CD2B214F8 +:1003B0007E0E49E3FE12E7B2B71FC7F33D3B2CFCAC +:1003C0009CE791C3136693DF6FADA6E03A7CEEE63F +:1003D000F99437669B0CE74206F07F84F256471D7E +:1003E000FA05D76B3016F6AF9939BD686B3D3BD136 +:1003F000BFB8382D4879BA97B545558A9FB94E3D53 +:1004000050AB27EC73B6703DD3BC8FEFCB93F73571 +:100410005FA65F6ECB36DA2DFDF57F92DDF283FEAF +:10042000F1FFC6FD0A33EEF392ED97E47DDD203B4C +:100430003CA9BFE1EC18998F523D300EB7A79DD271 +:100440004E0A1BF275AA1DE27CA1CDD8FFE5235C04 +:10045000345F99BF93B5525F8179FAF11F30F2D7BB +:10046000C93CA27035CFF7099B6C74EED0CBDA296A +:100470007F68248B2A0AF9D37AE87C6D36E611C1AD +:1004800077EBB24751BFDB996F8D4AF25257106E2E +:100490003BE69F50BE6A64EB221CE73A078D63C7B8 +:1004A000FC938B3085C0BF15E5EBF4061E5FC805D5 +:1004B0007D8CF49B3B9AD3A1BD8EE7A1C83C1399D8 +:1004C0001722F1502DF09B3B765111CAC1B54AF06D +:1004D0005171AE99CBFF0D4E715E19EC6BCFC079A7 +:1004E000E43EC6FB0F3798F8796437AF778CD1F9C3 +:1004F00079A02FF839BB8E729E7732283F2509AF3D +:10050000323FE5C9B4E011E497E4F3CB924E12D642 +:100510008FCE476F3BC4EDFAEA060BCDA36FC9350A +:10052000E497EC5B6262A8FFABBBAD9CEE92C6DBCE +:1005300056676151EC578BD8517ECAF5FF32BB1616 +:10054000D6B514FDBE475A6B2F3A05383EDA1AA0CD +:10055000B2CFAE74AA17D2F9D2B928A99ED8F2F9AF +:10056000B55A0EE6DBC40B142099E7B77E3493EA44 +:1005700099F177B0FEEA16CFD73490C37D63E23BA2 +:100580001478FFFF797FC4DB911673197BF7A1877D +:1005900066861D5F41DFFD9125E7719C41BDD3C497 +:1005A0007A56C5C85F24F45D2597875E8785EC255C +:1005B000AFC83F6535221F15233B505F99534E71DD +:1005C0007B07D30FC4B03D8F9FCF8276A2FF956388 +:1005D000B87FDA26E882E549BF544F18E5DBCA2226 +:1005E000377DDF2F8F0F5823DC3FC6C77FE3E90B32 +:1005F00028BE25F36A1973E5CFB980F26C0CF5FBC0 +:10060000ECE21CA6E6CAC773EC2BCDC2EE15F5369C +:100610006730C58BF3443E047BEE8D2BBF5B867C3D +:1006200074E6E0F747A35CBBCA02FB8221E4D8EE84 +:100630001C2EC7FACC8E350A7C57E30C8EF0C2FA1A +:10064000BF953A77061E29A81B31CD82471758F867 +:100650005115F19A29E8C43D87C3E7AE0928987778 +:10066000BAD2CEC7CD0C6A7E3AF7109CA35C077055 +:10067000AF54B8BC868FD2C98E2AD5D3F11C61A3E2 +:1006800038D7AA0AB97149E72615EDF59FB7BE35E7 +:1006900055D306E0FB858887FFA2C8783EA2DCCB55 +:1006A000ED6259CE56F50B90FE56ADF0BC36F31206 +:1006B0007CCEE9F8CAB4659598A77D556A4B25FAB2 +:1006C00069073D4F87E76509752B7FAFD1162FC0AE +:1006D00073E60BEDC149888FCFE7BD7B27CA873B07 +:1006E00073DF7807F324DE300B3991AF88F5EE988D +:1006F0009E06EB79ACD82DF23C6C440FC7C6723F16 +:10070000647F1EDB3885F2FA66CEE1E749AF65B15A +:10071000B61EF89E9C15D03E637211D9913345DE0A +:10072000C58CB70269E8179871435C43393A9C5D00 +:100730007495D7ACF724F0C3D5BAB17E6DA9B1FEDC +:10074000359FB1FE8DC97F1A9B587FD9EE9F8DF4DE +:10075000F4BCC2F33EC3973017D1BD4709A3FD32A5 +:10076000E1995C710E97E727FEABD8773D3399513D +:100770007BD63EDB2E3C3720FDD7AA689FE065B6CE +:10078000C20C7EEF03EABBB822F21C3D14D3610712 +:100790006F75713F2EBC6B817E0ECED3893FAA460A +:1007A000DA52904EB21C267639F252A58DEC9A237D +:1007B00082EEE4B9EA2A8D0530CF02869C83E51BE0 +:1007C00066D78BE8A70E7FC818E7DB691AE55B8A56 +:1007D00031185B41F587045D1F91F2FF079A585766 +:1007E000E04018EFECFA5C1E872E65745EFE6C65C7 +:1007F00009D525DD4BFE01AE1E8DA14145F427E94B +:10080000F9A74E0BD1837ABF49F8BB34130259EADA +:10081000927080B8C9423DC9C8FE9571BA7C9B6C84 +:10082000D7FCF87E0E93757EDE2B4BD4A1296AAAE5 +:1008300040FDFCF2EF487F3B7C419C8725CD46E79D +:100840009386E3A35D827F7625F1914BBB9AF8E80E +:10085000A7CE923B08EE6B9C2ED4AFA53097BA0C76 +:100860002AFD232AF03BCE4F6A8A4F47BEF966ED38 +:10087000F1A95A829C86EF9BF8F7A9C6EFBDF07DDF +:1008800046C2F769F07DD9E0EF773B6D51D344EC78 +:10089000A74AEF217D18A5C95E23E6AD66F1EFAE4C +:1008A0001179B1A3D3E07DD45BA5C63C1336D967DB +:1008B000A3FCE4A4BC92AB94E539C85757DB9ABAC1 +:1008C0007BA0BF97C53A5E650A7EE682E72FCF2DF3 +:1008D000398AFC576B8B6898D7772D8BAEC2C5EDE4 +:1008E0009B167CC45D4CF2E159E4936635383603BF +:1008F000EA67CCEDA36F2D22FE79CE9B39185E49B5 +:1009000027125EA417A43F492FC970F7AFE7D73B62 +:1009100029116F3BD851584ABB8AB1169E77ADE773 +:100920000FCC0B886886AD6534DA352F2F0993DC40 +:10093000B8CAFD00E565BD9C1BFC4F946775177E2A +:1009400052A0E1CBDE796371DF00F0C6FE37E1959E +:10095000F6E3A0BCE30F2D86BCE3E1F84C8E1B420E +:10096000BB50C5FCE49D94471C9AE3F0E1799110DB +:10097000E6C15652FC8AECC2E7146E6F87159BB035 +:10098000E3CE373F99717BAFA9DFDE33E4D77794AD +:1009900073B83B6ED5E5FD35DC5E9CC7B83D394B81 +:1009A000B42F7451BBCCC3EFD8C9FD861D4F8FD572 +:1009B000B15FB003C97E60E9C2CE2C32DE9B837F7B +:1009C0004AD640DEF86633B75FB7997C5594E76244 +:1009D000E1F7E29C91FE8C317CFC64FF626E8E62DA +:1009E000884FF7D7FF4EFEC55277303F07FA5B5866 +:1009F000E62F504C0817F733027D3E1C6398FED655 +:100A0000321AEDFEAB59CB9BA662A2CFE21CA4CF5B +:100A100009409FC506FA1C9D93C9E524C225E9B388 +:100A20009F2E4B93F3CA8217603F1DEECE5F35A316 +:100A3000BDDC6DF5F1BC5A9E27982C0712E059A039 +:100A400071783CAA4AF04CC27193E1391F3E49A427 +:100A5000CF6CC6F961387EC9D658D85931C02F2F0E +:100A6000DB8335087F3FDFACE2FBA34170AB0EA216 +:100A7000AFEB6FE47194502AD747184FC981F167E3 +:100A800089F1AF5FCBE9F0FA7FB110DD02F8518454 +:100A90007FB6689FD5DD447954B36BCC2712ED0047 +:100AA00019B7A913EFCDF1949B9105E6CC34C64B51 +:100AB000EA6EE2F19AEB588B19E1BD7E8EB19F3A56 +:100AC000B6FE13CC0BABBBC9F83C98D31F67198B90 +:100AD0007196A3C28FD007FC82FCF4D3CCC50FDF84 +:100AE0000AF43BF6876515E877BA326BC9EE4D50CC +:100AF000FFF1B6F154FF69D6B7BFF306B6EF28A1F0 +:100B00007A0D26B9E13E08F911F54DD58DD714C1FE +:100B1000B847EDA2DF5BF939026F4AB06316BCE754 +:100B20009D388AF2216B84BCE95BC8DBAFBDD0C9BC +:100B3000535E6FD6C9DF5893C2EFF579ADFCBF2B7A +:100B4000303FB76694A8573C3F1EEB47954FE81ED1 +:100B500080DE268786F86FCEE57EDA09A54A741C0A +:100B6000E0A52643F4DFC4E735B3E2D15CE48F9A15 +:100B70006ADECF04DFB4B5C5F89EE92CD57B736D72 +:100B800069280F259FB5E770FD2CEDA980E0FB6774 +:100B9000FCEFB68D807E0336C587530C4C7E97DF05 +:100BA0005FE5E0E7CB02FE220DFDBCD3FD3C7FB349 +:100BB000DAB62207F7E75F0F5A2A715E2E5BF9510A +:100BC000B46FD2274F9B44F9BE3666463D0774DFAB +:100BD000417C78F1270569486C0E23DD4BBA9A25D4 +:100BE000E9BDC648D7C0AFDB7232BF5C5E1BE8DA36 +:100BF0003E40D7C3D9B900D78F09AEA946FDD53F2E +:100C00004E125F268F3B9CBCC0BF44793A005F27E1 +:100C1000F15F1E66C515237FB64BFEEC42382CA64D +:100C2000189DB329547CE3E960EA307686842F1F4F +:100C30007DAE1583E1C23F4DDA7FFCCF83FBF23CF2 +:100C4000D10EDFF959C6005C30FE2B240F577178A6 +:100C5000B62B2D5CBE087B5CEEE79BE57CBB8CF382 +:100C6000AD4AE1E7DEBDE87721DF7BF9F87EB8CF5A +:100C7000631DE47C42426FCFB1059C1698DB75EE94 +:100C80007AA29F1B58F869B48F963983FF17F174C5 +:100C9000C4143E84FB9C85CC4FF157A08F77721211 +:100CA000EC0D096F329E9A8791A7C9F349C6CFC050 +:100CB000BAC5C8BE93E7D8FAE77B9EF3947689C796 +:100CC00062F4776508FF5486F0472145A17E9EC9EE +:100CD000527CB82F98EE53C8BE98C96C249767D63B +:100CE000727D9EE1E0F687D4FBC3F1C7159733927E +:100CF00057331B993837C7E7954C87D9ACE70E2C8B +:100D000067DAF4AD0B90EFD14ED107E09FE9E07EBA +:100D1000ECEC5C213F58CF24D4F3FDF5417ABE675B +:100D200012CA9FE4FBC9669EE3FED28C738CCA99FB +:100D3000BE7727A19ECFA8ED998472CCE9F27B7390 +:100D4000270DDC1F988CC7D1B92619873B2FFA4C89 +:100D5000E61F193F6B7306C7E238D2CF714689553B +:100D6000E14B151E97E83F588474EC76154D43FF10 +:100D7000C51C1BE82318BACB15BC3017E9ED8F0052 +:100D80000F6E0EF155C0E37535C17B343E2CE1E1A9 +:100D90003681872B855E3DFBB04AF1891A7FE94396 +:100DA000184208BD626611E2573FE94579BFD8593C +:100DB00030A0A2F8FE634EB23316BF5A4FF195B180 +:100DC0005B4C4C4FD093E32229867B3226ECCB3010 +:100DD000D42FE8CC35BC7F61D728437B7974BCA184 +:100DE000FDA2572A0CF549B12986F72F7EABDA50C0 +:100DF000BFA4E71AC3FB533F986DA883C6D070DE2B +:100E00007B9F55D83698F765F16F19BEFFCDB6199F +:100E1000AF60BCF3A4D8F7B2B03F560A785820E9C7 +:100E2000F6DC7C637F5125AA5421DFF3BF05EB7903 +:100E3000BEF634C05C62BF0BDB8DF6C4E22DC67A11 +:100E400043F7A655281B07E779B454E35539C97908 +:100E50001E35AE7926A4CF502ED817E31011EC62C0 +:100E6000CC331B8ECFBF6CFD4BD8E82F5B7FFEFED3 +:100E7000160BD9F58B5F7DAA2A0A8FAC5EE3FADBED +:100E800075E3FAA7961AD7DFE933AE7FFA64E3FA7F +:100E9000BBFDC6F51F516B5CFFCC8071FDB3EB8CC5 +:100EA000EB9F1334AEFFC806E3FAE7B718D7BB7061 +:100EB00099713D8BC24B0DEDC9EB2FE565F19ADBC6 +:100EC0008CEF017A4D097420E96841A081F277C660 +:100ED000B47FCF304E323DC0BED144F7BFC13E6E6D +:100EE0009B72FEF401D28AFCBDC9F4F16FB9C2EE67 +:100EF000147401FAA813E50AD8174F61593756D868 +:100F0000FB81A1ED0B29BF12F579E2BE7838B93625 +:100F1000484F897DF2B07A0AF7C9F6817DF270F404 +:100F20007B1CB38FC88E5A4F7EA51B5D1C8E4FF164 +:100F3000D125E8CF7D82F4F271007032C07B1CE7CE +:100F400003E31F4F9940FE8D6FB328D9EDFF82193F +:100F50009630D8CD98A8ADE23D4F3A95F5426F2F27 +:100F600014FE8F85F6E05BB9DCEF519885E3E6C5AA +:100F7000E8BC147B6DC479DD237102E30820784F4F +:100F8000611C01CA5E3BA79BD352AEF899EE49C0E3 +:100F9000E7FCE94A29D9B56A0AE53DCDBF4121FD03 +:100FA00034FF7F781917FA2CB95CB94CE2B35DD8DD +:100FB00003DC2E48C7C39A1477624107E1CDE7C22C +:100FC0007586FEB81FFF47FC7CCDE30AD32667D0A9 +:100FD00031335A675C6F3C0FA5DA389C8F9B990DB3 +:100FE000F1398105C90EBC5703D1C6FB1BCFFB7B72 +:100FF0006314FAD354F5FF7CAD06E3CF382EFA9F85 +:101000001D3E86FE66D5EB63E8BF1AF4FCC014BA39 +:1010100024A3BFCEF87BF88778917EC23C412FBBDA +:101020009D8CFBBD92FC86235590C098BF63E6E77C +:10103000C3BDDA16BE9F3CE65B634D9837636637E7 +:101040009EE7FB327B08F36D4F27E4C7C3BA0C79E8 +:101050008FE9B43CAEEF57B6365C8671A25E1107DD +:10106000BBA7357819AEB7AAF9282F0EEF5772270C +:101070007C6FF1407B029F6A8E0643DDEC08105EB8 +:1010800056B5B610DD98C53D50ABF36E730513FC35 +:1010900012178E14F6862DCC5C594C98C6F0F7C109 +:1010A0007486F3555DDAE9C47DA8D50BFD25CA2BFE +:1010B000AD9025FAADD7B4B610DCAB9460103BB35D +:1010C0008E66513BE0DBAAE1595478BEF52A92675F +:1010D00016E76D3EBCF76738FC59BDDAE78972C880 +:1010E0003FD22887EE6FB55D8EF85AD9BA8CC69379 +:1010F000786B6F755D8EF58DAD5ED1BE82DA4DB5C4 +:10110000BA82F4711A6821867116ADC789713DB033 +:101110003319C603CD5E5B0499C8EAE1F0B2A305BA +:10112000441F735D1C06F48DE5037DBCB3CC4CFB02 +:10113000D3DBF31DF4FEEDAF8F79D10F7C60011E80 +:1011400051FF8AF9F48F23F06711728869C100F2A8 +:10115000952557237F74866B36ADE3DFDA9FC4BBDA +:10116000C5CE281FD492EF20BBEB7CE10C8D14F789 +:101170005009BC27E30FF04472F47681A7DBEFE25D +:101180007EBEDBEF6094C7CE96C15FD5005D8D1447 +:10119000F2259B05A86C6F05C15282EB6563410B7C +:1011A000E875D6492FDBD1BF83ED7ECD8DA1EA4D09 +:1011B000359E59586E9C7CAA1DD9F1BE4B3F8B6160 +:1011C00089BE74C497AB8145F0CC1FC58E3D781D98 +:1011D00035AFA789F6B43A5E4F17EDE9015ECFF758 +:1011E0003FA9D4206049F1977C47C6D5A351BE2DB5 +:1011F00060FC7CB2B8E7603B13F2C29131AB06DB16 +:101200006F6274BE40B6FF50B4E7384EAC29463921 +:101210003CC7F8FD5681876CC789F6E9149F31B643 +:10122000CBF84AA6E3EC2BF47D99B1FD41F1BDD397 +:101230007136361DDB471BC7DF20DA531D3CEF0834 +:10124000C4213F472FDAEF15ED766CC7F14B8DEDDA +:101250006BC5F82B9500AD433F9F89F8E48E569DF2 +:10126000EAC97CF6EAC80C7E8E59F0996B191BF21C +:10127000DCFCAB2379BE4C9ADEE3F70F210F657BD4 +:10128000864BA3B8AFEAB5101D591D428E083EEC3F +:1012900097234A8B8F1317F7977F193D03E17E8EB3 +:1012A000F2AC00FE909EF3BE6362C1047996DB98B7 +:1012B000C28209EF7B176418EA5937E51ADEF7CCCA +:1012C00019656877548E37B4B3583EF1C76D82AE56 +:1012D00052CA2A0CEDF2BE02A6733E9276B579F49C +:1012E00014C37B674BF574A4EDD357CBFBAB7C36B3 +:1012F000940BB7394765231FFEA475321ADF20EF20 +:101300006CA27489D24B47C956B6EAA25E4AF5C7A9 +:10131000DC3CAF7A65AB8FD78B189D6F5ED95A4B8B +:10132000F5C7812FB1FCD7563F957BA00E160EFB5B +:1013300011F4AF433F3BA17FAC3F02FD63B91DFAFF +:10134000C7F287D03FB66F857EB1FE10C085E583BA +:10135000D00F3E7F00FAC7FAA6D600D5EF6BADA33B +:10136000FA86D62095F7B636D0F3B5AD2D545FDDAD +:10137000BA8CCA7B5AC354AE6C5D43ED16A1371FBD +:1013800013E71F1F9BC6CF7D27AF7F469EF2D5EE8A +:10139000BBA804455E65C893C8C8C37D75A7312F37 +:1013A00010F14770D8391E93E1182BE018CF622B4B +:1013B00052B9DCA038EB982EDFDDA9C0A7235BF87B +:1013C000BA1775C5A93DA7818F3756CC9379C22C22 +:1013D000AF8A1FEFC5F77A9558752A8F37931F8309 +:1013E00079013F55E2DC339179C484706993417F80 +:1013F00027CCB31F5F6E0E27E26D28782BF2787C26 +:1014000043ADECE4F79BD4B64791CD52FC2D74BFAD +:1014100089AD2E10D5A0F40482744FC2F8733360E6 +:10142000930572EDDCE54C8732AFD1B8FFCA5D5051 +:1014300061D8E7A8E73632FD22E8B7CCB84F4A19A1 +:101440007D9BE13B5BDEF70CED16CFDD86F6F9B751 +:1014500014ADF2223E47328A3B59D7AF603900D7EC +:10146000C28E4D045750E0BD57D1F9FDEDFBC5EFDD +:101470004408FBFFC72E812FDB7ADAD78E75F36A1B +:10148000497AD884FAE7E3A7D2498EEE7DC444FEB8 +:10149000ED712C6242793301CC486CBF006F7256FB +:1014A000E9CA1C15EBE54C57B17E118BD3BE08EC95 +:1014B000FF3AA417B0FF1FB143FD4C7EF0C73CBFFD +:1014C0002B4A7ABA44AC6789DC076DD192FDC373AD +:1014D000F3C85F633C07D626F6012BDC55D918EF1D +:1014E000ED1D26FFCEE9FDD6D405B01ECE9C3A2ACE +:1014F000E5F30DBA69C873D1CBBE2ABF6C013D625A +:10150000E4976508FF99CA9F67A1BBAA79749CF804 +:10151000A6CD2CE5989E8E726CA0EE4B27BBA23B0D +:1015200087F0A389F5D9DB1AA4FC00394FED77D3F6 +:101530005C980F5622F24FF7B5DE3AB526211F66AA +:10154000B7A0DF5216AB453D5A5A66F245A827AF01 +:10155000C17F611FDDEEC773FA5A05F3A1181EC7DC +:10156000DAE9BCBAF6854A7940DA914B980E76B042 +:10157000C31165E1B2817E99F0837C47C8F5CF5CE9 +:1015800035340FAD40DA473ED4DDEC33873F867407 +:10159000F7598799B3E509637BA983919E5B546AE8 +:1015A00089E80AA623B4D33D8BDA0E85E515211C04 +:1015B000D3BDF3508F1F4C25BA4DDD524557C37B29 +:1015C0004CC1F57900C7991EFDA0491A57F05ED3AA +:1015D00004CB2EB41BC7225E709CD1A584C7856244 +:1015E000BEFB5A57109E9E15F368CBEFC73B87870B +:1015F000F9FC78CFE9A20EE9BF31CE734365F53728 +:10160000F0DEC6953155D874467CAE33C726CE532E +:1016100006E002389F453855849BFCBF7C7E4D8F89 +:1016200070BF19C8B15A8ABB4E32B1C4B8AB2CA333 +:1016300042FECDC87311BC4EEFDCA90B2E4AACDFC5 +:101640004474FDB8C2E71F766A3C2FCDEFD713FD77 +:10165000C4EBE47E599C7F4811F0F6DFE3369EE749 +:10166000613A586C0BE62D0DB71FFE252ECAA4C497 +:10167000FD30E81818579D64A33C9F75328F4B7F4F +:1016800043C77C332CF1FC8A4DD0E96AA731AFE423 +:101690005C1EB777CE89F5E8B371BEC6B8647956DB +:1016A000C2BD17DDF5E4FF9171CCBE6E9E0F2EFD1D +:1016B0006B4B0409F41DE578E87B58A5F8E592EE3C +:1016C0006BF97DA1871EA07B56A12F1DE9A15EBCF1 +:1016D0005FBFC6E8EF59B03BB02A451FEC575AC46C +:1016E000C2E4D748F62725FB917E9B27F6693E5634 +:1016F0008E71CA93EB8B8FA5E07EA688D1B9DB9162 +:10170000EA93748F3158FBED784F292BE3F7F424DB +:10171000AFFB250516C2F33EB9AE631CE467D837AC +:1017200089F3FFBE17CF7E7D0CF4F396AE18CE8101 +:10173000BCA59B098FE381AEB1EC64AC76A8FBA09D +:10174000B2F34D5FEDBCC0A5C6DFD768EAEA3996B3 +:10175000AA93BCCBCA0778FA8EFD3EAD8CF8274E13 +:10176000BF075157C4E141B8F1FCCB7ED3277313B7 +:10177000E9607CBEC6ED837CD35793BF3546B8CEB7 +:1017800094BD99750D876B1CC2D51B3D919568B7AB +:1017900048B8F60F73BFFAA55F154F938DFA200175 +:1017A0004F53FF129EF65B86866796C0CF4F8EF230 +:1017B000FB4206B77F45FDD56184F7CC63B1EB51A1 +:1017C0003C02BCB3087FDE5359143315F8EBAC145C +:1017D000F45929E48E8FCEA8B0D0DB17537E5EA7D4 +:1017E000C6DB43772E8AE07902DF8B0B0AD1DFE07C +:1017F0003C6EA57B9E42497922B25C2FE6B13F57F1 +:1018000019120FABF3B9BC78F1B5F9D4DFBD6F593C +:1018100019CA83ED22DFF55E57A70DEFEF9578C467 +:101820007A0594214B7C112ABA7B2B3FB3E98E2198 +:10183000C633F1F1EE4BE21B399E2C57E49772BB95 +:101840005439AAE23987FB2E7D93EED9BAAF5223E1 +:1018500099FB37E37F7D12FEA36F667D9DD3CB8A14 +:101860007CF4A32AEFA57D03EA2125FEB332C49FB1 +:101870002548F30FBD6D653B95C1786A14F42BE7DD +:1018800027E72FE1765EB680CE99E07A20E0ABC5FF +:10189000FB524FA40BBD87F3223D71A9C6CF894CE3 +:1018A000D2685DEF9B3C85CEF5EC17F914F14B2C1B +:1018B00043FE2EC333026FF79EFB450CEFA90D7755 +:1018C0009BE95E05A6F578BF0974147A5DA37B9A3F +:1018D000819E6AF1DEA8175F3B9B86FBE803F966F1 +:1018E00082FB403E97877DE7D45A3A6FF3DA672E42 +:1018F0003581FE9FCE57855D128BE1399A8D15FC9F +:10190000DC8043D8018ED74E3520FC8EC9DFB32A48 +:10191000097A764FBE95BEDB688967F9300E744848 +:101920006551EEDFA1FBEFFACF0BBA381E9A2B8F71 +:10193000929DE0E8E6F7E23D9DAF135C08F7417841 +:101940009E32EE33573DB657C278A306BE77BAF83B +:101950007AA64CE2F7D0DC77E9CF5D78EF5EBAC2C9 +:10196000E8FEE84B0ACC06395E5FC4D7A1B3321655 +:101970001B85FCE5D228AFB6337A9B0DED7AC917EB +:10198000A347A9F4DD6A9197BE7A7229F199A4E37D +:10199000B905C157916E36025F3C49764E2C309D99 +:1019A000F0E32AC7FCE3C795581DB73F2C2ED42F70 +:1019B000A5269381DF8A0B38DDC812EC52B277EE90 +:1019C00010B42CF57D5BC4C630BFFFB7E766A5A396 +:1019D0005DDA9627ED3CBF0DF1B55D09A417E1383E +:1019E000FFA5D2BEEFC5D74E34E0B86D302FE4DB93 +:1019F0007B7EEA588FF6499BCB4F7C2AC7D7DC26E3 +:101A0000B11EBC9FFD16FF2BE86F8CBBF97D4447D0 +:101A1000A65C6343FA87F74CD8CF7BADF80B1AD896 +:101A20004F0DF90716BA66CFC0EF16B1E02AB46BB6 +:101A30001775A8867B17EE11F262E1B914164DD81E +:101A40001F2C9CFC2D3A37B6F05C1A8B82BD758F2B +:101A500038177D8F3857C40A383D3B44E915E5DF18 +:101A6000CCF7BE24BD95F9CBBDF339DFB302E8B79F +:101A700049E9B114C1101BA7FC9ECEEBBCD7EA62AA +:101A8000D192047807CD73048B268CD3FFDE391BEB +:101A9000CD67607D39FD0ECCD7417878AFD54B78D6 +:101AA0001CBEFF91063C0EF43FCA80C7C1FD97D013 +:101AB000F8EFB5967E49FF1386E95F37C03FD0EF58 +:101AC000681AB7F7C8FC1FA702DF1D89DEBDEDF954 +:101AD0004AFC1D332BFD7E01EBEAACA673848F33E9 +:101AE0003A677AE7E1DFBD83F99A77EEB2F8708C56 +:101AF0003E737CAE6F083D339AB9C2789F972CC76E +:101B00001714D37C929FDBB4880BF3326DA59A0B2C +:101B10007F1FD1C66291BB71DF5269233927E3422F +:101B2000B2DF3FE5A9F23C3BC907796FCB12919731 +:101B300057EC085E81EBBED4D4DEFC13F8F683D2FA +:101B4000363A37CC989BF633326EA3E12FBF15A3FC +:101B50005F30C0F0FCCD137A70067EF74310271873 +:101B6000C7512FD81DC4BCB50D62DFB8C11EF3FA32 +:101B700012E4E60D05DA57B317DA93E876D22FF7B9 +:101B80004639DDDE50807E2235F6C4FC22CCB7ED2E +:101B900011F776E9168A77551EA3FBFEE6CB7DFF8B +:101BA0009AE4BC8E7C37DAD132CE94867977686B32 +:101BB0006CE4F7BED5A7F27AFD7F8CA07310B0FF5E +:101BC000492D43F9B25FE5FE2011DF3A2BE6D067DD +:101BD000DB5840F9F7221FE46CF74B74AFE4D935BA +:101BE0006368FDEB5FF83EDD0BB73F97EBB1BE439B +:101BF0004ED263F5565F15DE5BB83F97DBAB9D5A5F +:101C000034AD22C17E5D9D574DF2F9E335634C89B9 +:101C1000F18FEF0A79B051FA37B578159E67F9B8A8 +:101C200032FA33D2A307ECF43B51A683BFABA2FB3D +:101C30002D375AE97701AA0F8EDB5C87FBC3348D01 +:101C4000F2914D07ED04CF9975FC7E2DFC16E55DF4 +:101C5000D3C191F4FB56F5A971CA276C4AF195607E +:101C6000DCAFFEE054BAD7FFE486710528FF4E646E +:101C7000EA0574AFF1063CF409F54363F9F3B517CF +:101C8000D37955E7C6D4E0507E10A98F92EFEFDAF2 +:101C90009F5BDEDB85F81967F3A1FC7D4FF1F1B89E +:101CA000EF2BF1D93AC515F9F9D27AD769FA7DBC8B +:101CB000FA8E776F62F4DC43742BF773C9E3D50BAC +:101CC0007DB5DF129F8BBF4B56BF52E05DFC4E626D +:101CD000BDA99C7EAF4FE27D63D23DB74F08FD2486 +:101CE000CB93AF69745F20D81105E81F3A79D84AC1 +:101CF000747672E3043AAF2EC7AB079CB8802F4FBF +:101D000064E813715D9F16F2AA7E25DFA7CAE7304B +:101D10007E0C7FE7307E48A5BCAE3E573C0DE3927B +:101D2000F23D59EF9F4FB74ABF97B53FF7455A6FFE +:101D3000A02786F4647AC1497A3AF4827517AEE72F +:101D4000C7952C8CFECFF05BFCF7C78E1CB292FDC2 +:101D5000DC779CEF6F07DD9FE68817E0FDA1A117F8 +:101D600046921CEBCB8FEFE0F6B69DDFABF846F06A +:101D70006211FFCD11F711E6A09DF7F9217B14ED5B +:101D80003C28299E1066BBBDF4FC702A43FF0F94CB +:101D900014CF63CA012FFDEE0C6B17DFC7E8FB3BC6 +:101DA0000B8263512EDF590CFD3BF0FB53F4DEE751 +:101DB000A38217520C8AB15C315E2EF59B1F2CA4B6 +:101DC000E7CA675EFE7B2AEDA23D46ED216BF0621D +:101DD0009AC7AF9C6CE710F3FCAAF7EE1D2D1841D3 +:101DE000EB28E1063C93DD988C97B30526F17B3B0D +:101DF0001C1FC974D9BF9E5F021FFA5FE8BCF621A1 +:101E0000BE8EEBC659B81C593B81EC63D69662C8AE +:101E10009F5B7188DFC3D0BBC149EBDC67F63F84B1 +:101E2000FA28FE8699F17BEDC022403FC5E4A1F976 +:101E3000E523914FBF642DCFB3FBE8D1F70BE63913 +:101E4000F05CF2FB8673C9D25F089DA4A13FC6E196 +:101E5000D3D3E697717B5D25F8F8EF7A6D34EBF418 +:101E6000BB6BE10DE3C81F71D2A21FA4DF875B77B4 +:101E70008109E94A2D17F277139F9FBC2F4BDE7B18 +:101E8000958C9F8AC262927F4D2C7833DEA17E8230 +:101E9000E959C26146F7FF917BDF8469889A9FE226 +:101EA000B6AC85F4C2E07BF62C5FF2BB6CFFBBF5F1 +:101EB0002A5C2BF4EF9587D350AF7EE0E2FB463AE5 +:101EC0007D8F7A5DE5F36CC30F30AF8305A6144EAA +:101ED000A27692871F28BC5DCAB941F3477AC17EBA +:101EE000F03DE8EB9A42EE7F63AE0C71C82B6CC1FB +:101EF0003C4DA99F428A66C273F3A7DC7A1AD2E3EB +:101F0000A9B5C5192B300FC6AD6725DAD5A1A38CAD +:101F1000CE8BEB78DFF8C5F8FB32FE89E8F7DB9F64 +:101F200061F43B24C3F3E4B49EB989ED730AB99E0E +:101F30009B5F28F699854CE45726E38DAFFB62B191 +:101F4000EE6A79F072DA8726BDB7784BBAA087A41B +:101F5000E7EDCF7F97F2A01E36DE1349B15F18EF91 +:101F600083572C61E5422C5328AFBD611397730D45 +:101F7000AFCE2CB98BD7E95E85693BEFA1DFE35982 +:101F8000B0EBCA12C6E516AD83A4C70505FE12B4B0 +:101F9000E3E25B5517F245C31695E051CD3ED756A7 +:101FA000787E7A8B99ECBB0601CFE9BC601AAD9BB9 +:101FB000C6340BE0FDB4164C23FB75ABF8DDA1A4D1 +:101FC00079C07B6F6A1543E0C7C6D799F0533C04CC +:101FD0001DBC61A2755A80BF0B8970EC54C8BF79D3 +:101FE0003A3F7833D64FC1FE1FCFE9AB9B96D07DE9 +:101FF00036C9F83E6D0B127D2E16F391F84C1E4734 +:10200000E2B30FF189F6D22B5348EF851E5491624B +:10201000D98BDD9FD2BE7CDAA12BDF998ACF3781A5 +:10202000DDA2A39E1DF5B36FA39E5BA3528C7AFE27 +:10203000A1E22C96A4AF71FF39FFF53969A6043DE2 +:10204000A93EC8F1A43AE7A42DA4F7CF7E1DE9EB81 +:1020500084EECBAA4878EFF1C2FEB88361BDEA37BF +:10206000FD210DC769586FA679C975E9C379A07CB0 +:102070006B4F8D20FDF7E5C5A95FB94EFDF48DEBE3 +:1020800020E909DEFBAF429718274CF2E85451B023 +:10209000CA37049D2C7A00C6C5FEB638E9FED2F3D5 +:1020A0001D57E2A37FBD055F531DD7714711F9D1BD +:1020B0004D6F6874C8E044FB5505C8C7F5A02FD024 +:1020C0006F51AFC4DFA17B640F59E91EE6FA4DB72B +:1020D000DC8CE3D51FB79AB0FDD4E1AB26125C4986 +:1020E000EB0A782A188ADEFB8AE205BE04FC813DF1 +:1020F00041FC2DE7930037C101FB29BA8FA8AF0837 +:10210000D633410EBC59C8ED2E78DF6521FAE6F7CB +:1021100061F5CFD795345F57D27CDF6444DFCC17AD +:10212000A4F92C78DB6AC2E70BEEBFB604F73DA733 +:10213000D64DA7799DCAF04F44FE3A5500FD0F21B8 +:102140002F17DC0FF32CFB0BF36CB7D37A0D3BCFBF +:102150008CF80EF617E6F989A04339CFF7343D0D18 +:10216000F3F943CFAA0CFD2EA1FCC0C6A9BC4EBFFB +:10217000131732737A086D4AA57CDFDE6EFEFB040E +:10218000520EC078E7490F26A28753D5FAE6C9D088 +:10219000DFFF073F3717B700800000001F8B0800E4 +:1021A0000000000000FFCD7D0B7854D5B5FF3E73D5 +:1021B00066269364924C12088140983C09908449A9 +:1021C00002888A767804D1020D4F798993071042EC +:1021D0005EA0B5696BCD4002A2450D352A5AD401E7 +:1021E00081A2A20D0A0A15BC032A6245C5578BB607 +:1021F000E526405179C6A05EAEB5D7FFFAAD7D4E5B +:1022000072CE9054DBDEFB7DFF7C1FDF669FFD5AA4 +:102210007BEDB5D75EAFBDE7C23DAACBEF16E2E4DA +:10222000DD056FFFBC17A5F7AA2E81FC58DFCD0294 +:10223000F98FC32CFE144A938BA670FE659B6BA589 +:1022400022C489A6BFFD41A1FC857D36B7A0F20B53 +:102250002945F7CE467E8FEA5A41ED2F0C689F251F +:102260008673B9D844E5EA5D239A502E1E1EE6CA4D +:10227000A0F2F20D61426409FEFB56687F23E93B40 +:10228000520BA56B556F7834A54D2FFD44C9A56F32 +:1022900056378F57F3AB24F7DD347EB95558EDF937 +:1022A000A8DC9E392D4788F37B6D1303D9323F2379 +:1022B00087CB3FB052798D5DF85AF87BAD7D6A0EC1 +:1022C0008FE2B6D2388BA90F914AE9FA18EF60EA8B +:1022D0007F318D9342E37D8BBF1F5C0EDF0ECBE71A +:1022E0000B8AA89F7B6D62F673D95DF5F434DB4DE4 +:1022F0001DF6466D7B573B558825C63CE1A122243F +:10230000BF14794757BE32A4BC2AA47C47BFCFA7CD +:1023100014392F1F7F03C61FD185C7120D8F3B2C89 +:10232000F41DEB728F12D844FF2DB1BAEDCB09FE2C +:10233000E7C6889BD14FA95538AECD47BD0E9E5FED +:1023400089553486E5E3BB87EBE9F3A6FE1AC3E2C1 +:10235000281FD1CEE353BD8976439EDA9BE09AAB2A +:10236000C1A3A74BB785BB4EEAF3A07F552DB1A6FD +:102370007CCDEEBEAE93067C2FC57FFAD2BF49342A +:10238000FB91C08BFCABDADD7A3092E8A74DF1CD42 +:102390007553BF170E7E1D9DEDE6751F5944EB9BCF +:1023A000AFA63E7F98E6DBBE47F56C42BF6FD8FD17 +:1023B0004A0CFDE79B8B0F6EA7EFD52FA789BBDDDE +:1023C0005DF30FC5E385DD17A353E9FBF943F60879 +:1023D000318CE6B9377EAC9DE862475C7BB778AF5D +:1023E000D5D65DEFEFBCB5357AAAA1DE79D11A3D1D +:1023F000CD402F25BB2FD68B5CC69F5FCDEFC2EFA4 +:10240000897DBDC7AAF4BDF4F7FDC65A28BD5FC3D8 +:10241000DBBD36F7136B096EFF9E30CF1682FBFCD7 +:102420001BB32D687FFE8D722DBDCDCBE95F4F2490 +:1024300063FC688BA4777DBC356E0BF7536A697BB0 +:10244000EC1ADA8FA5BFEB93D290D2555E6AC9CF52 +:10245000C43A6FB7B52F00DCE715B14689EBEAE760 +:102460007EB79BDB9FDFF3C963E00F27EE1D904F24 +:10247000644DF941B93E2A3FFF5141A68BFA3D7F99 +:102480004F5F0FF8C2769BFB36A6B7BBA23CD8F7CE +:102490007A7F18A716FDEFB962A40FE947125ECA4A +:1024A000E7FAE4B87E25BFABDF688BFBBED1E0174F +:1024B000BFB779B650B2FCEF697D62313FECE76E91 +:1024C000D6A1744D98709BF8C94A86BB4478EC221B +:1024D0004D960B03BD958922FEBEB0C9FC7D11F15E +:1024E000097C5FBCDEFCBD5C34AD6EA5F92D09989E +:1024F000BF0BDA3FFE04EC6BFDAFC55E14057AFF3F +:1025000036CC544FF835FE401F095F25B41FC1C7B4 +:102510009E5102819558DFBB549E67E8BCDE75A7CB +:1025200070BB8722FF6741AB615D8F5B843591F0A3 +:102530007ADC2E1C89F9E8470885FAF5EF0B0B6C5D +:10254000A126770FFE2AB9047CAF31C22208BE5BF8 +:102550005DE07C42ACD8F74932FA295D53E86D352D +:10256000C077C1E67DE8E7D4BEFD5DE2D754EFF861 +:10257000D840D35882EBF8DDAAA7A11BB84EAFB163 +:10258000884001E1E32E2102F1947FF293E4625A44 +:1025900097CFB67C925C62A47F45CC36D2A39E12C4 +:1025A00024BC3EEF61EFD2FC8ED35C309FD07A5DCD +:1025B000EB6B8657C767B82A6ABBA387CF40F7542F +:1025C0009EF5775578B1EFF7D902A0CFC88D5F3C63 +:1025D000380FF4B9D7E64AA1B16BF6A95E95E62D9E +:1025E000F6A8810C9C637B4F4457E09CD953E05282 +:1025F0000DF3AED9A316E17C39BFFB62426936F711 +:1026000033C5ED44FB073CA0DF9EE0F89B5BFDF784 +:10261000F89FD7CCFFCE657F907003F8C0C6539962 +:10262000E0EFC407FFE6A6799ECFFCC68EBC10ADD6 +:1026300023417F045FB49BE0BC10F82A5A105C8EE3 +:10264000BDAA37D0CD3A44A5D8194FFF327C130923 +:10265000BE842EF8089EA894115D7056BBDBED3841 +:10266000672F38A273C14F694293F212B4F3C90DB8 +:10267000FE5A3A49107F1DBF67E1CA70C80B4D8AE8 +:10268000278CBE97ED55F9DC2ADB1B19C016183FC5 +:10269000C8C9F9D247D54018E527A8A3FF309BEA5F +:1026A0002FBE47F5D08E14FB37DEF6071BD6758399 +:1026B0004DA01C88035C4B34B896ECFDE1670A8D95 +:1026C000B378DF2D0730CEE207140F17A8F3EDE83B +:1026D00077C9438A88574067B6E3463A5BD864CEE9 +:1026E0002F12AD0B5415FCC1FC9DF09E5C41FD9674 +:1026F000EF0E73DD8DF102A1E542BC4AF0D468FF14 +:10270000CFCA583BF700D5CFDA68673C9C0F17E279 +:1027100008F6ABB53541200DB626631DCFEFF96B3A +:1027200032D6B1E677FF9529BA59BFCEFDB437AAA4 +:10273000D7A94821AE4E51C4B7A9A0FB8B538ABA82 +:10274000A96F1B20F7C5369BBF9F87CA0F6CFC8AF9 +:10275000F9C1853DBE81AE6EE8B76BBFFAC32D8966 +:102760004883E102E9F016D70DD827240F62BE3561 +:102770009B564FDB44F9F0976C38B9444D8693F77C +:102780000BF6C74243BFFA3ED906BE807484E40FFD +:10279000B601F21C3DAA9D7BDBF6774CC9E8069E8C +:1027A000A36E1BD7B30D105CEF5977D15CD05B845F +:1027B000C51F0DBE2DBC5E772FC2B3A2D157435D9E +:1027C000AD82EF89A289D3FEA285D34785F0395126 +:1027D0005F785CC0B3100362813FDEF38CCFBECC68 +:1027E000377FACAD217835E8C41F2B025BE8FFEAE8 +:1027F0004687506320EDB546A35154CEB4FB065234 +:10280000B9ED03D5A240DE1DA0AFA7C785FDF7A592 +:1028100073468C71FDF61F2E9988FEAA76A9228C2C +:10282000FA3BB7D326824ED4A7FD027C1CFEC29E83 +:1028300002BEB4571190976B288FEF35A3ADDE80A1 +:10284000012F77A4D8180FD52999F29CB67A0F4D8D +:10285000A27ECFBB4AEC90EB6D87CB26E2BCB125C4 +:1028600096D801D7FEC3631D2958B7582BEF9BD5C7 +:102870007BF5718FB8D07F54EC070C6F63B645447D +:1028800053BBC6A3610146A643F2A1300DAF8DC173 +:10289000F10E7737EBE317E393C4282ADFA94E0440 +:1028A0009CE75C252EACA32D96E8EE0A6A6FF34EEA +:1028B000BC9AFA0D8B8D8B077C6B52D2783DBF8A08 +:1028C000AD6538BF22F1C2CFFBB7B608F9C6FE65C9 +:1028D0002AE3BEE921DECF350E397ED43E95CF51B5 +:1028E00071A543E3DBEFBB4A699C05C9BE47410FB5 +:1028F0009DFC6DC4AB02FC39CB6261F9ACF135E7EC +:102900005AF021BDFC6C8AA4377D3D56F5B2BAC0A1 +:102910003F1ED5E87395ABC8916F98A7ADB745C377 +:1029200057910378DA612F3A84F3A59DBEE3DC3C2E +:102930009038CD013D85EA59D0CFA97ADA3176F4C5 +:102940003BC301FC2EEA553201ED168BDAD5D86F68 +:102950008BD7AB2268E0AB8D3639EEA24B11221833 +:10296000DF35EE225A3F6E7F295A04E9DC6D0C9761 +:10297000F51AA3E4FE792345EE9F0FB5F9B469F982 +:102980007F99AF7BCC7CFD5CEC1FB69648FEFE4683 +:102990000AF55BA5B44E48A1F9AD4EECB003BFA754 +:1029A000EA5D22986980F7B279C68BA061DCCE7AA5 +:1029B000971C3C9FAEF57033FC5DF375321E4ED50F +:1029C00027321E7BEE3FC984C7AEFE534D78BCBC98 +:1029D000FF4C1EFF547DD677F43FB487FEDD26F80A +:1029E000BBFA4DE771C56EDF40F0973B5DC40F98B1 +:1029F0006E885F50B95DF13D7E35E4DB8FC204E443 +:102A0000BEAFC27D835C06FEF00DCE65D6E782497F +:102A1000E0B77ED1CC69CDEE8B13D0DE4D7C01FBCF +:102A2000492FAF11ED0C27F885E88335B4BAB97C8E +:102A3000B76F10F4221D8E4E79E675A7DF42FB209A +:102A40006CDFDFA3B18F2F58DBA778286DD9AB4699 +:102A50001AF7757CAAA4A7B103BEC86DA5EFD56807 +:102A6000477CEFB697970E027EAAC3DA7301F7810F +:102A700097FF968B73E4AB7D4B07E2FB36AACFF250 +:102A800087BDBDDA63E82F5DB8FC96515DA933556B +:102A9000EEFFD0EFDBF635F4031CDB89BD09920BAA +:102AA000ABEB2A0A4EC6830D79EF07FF12C4B75865 +:102AB0001FDA3D5D1D03F9EE439279283F7C8F9428 +:102AC0001B860F10014B0AE4BE0F67834F548FB073 +:102AD000BBA00A47E41D61793B6284C3A550FDBFDA +:102AE000F797E3DB212FA4A17D613CE8F9CA64F1EB +:102AF000EFC96D1B42F64FF0BDEAED345E95DA3A50 +:102B0000659CC2FB283F157CFBAD2FDED6F4D704B5 +:102B1000ACCF019C6B04CFFB5A3F65A9BE2B50CFB5 +:102B2000E768BDE70AAA377356DF64E847C59A7EAF +:102B300026261152AE647E94033BC8E5E7B6D483E3 +:102B40005E527C3EE0C1DFD7E1C1F935344938FA45 +:102B5000125E456220751A8D3B21D5A2DB0F14C091 +:102B60003D449BE333FD5A96C7F2391988031DFD96 +:102B7000B3E34E4BF54E06FC7AFD0F67CDCBF175F6 +:102B8000736EE8F2BCDDDEB20C70B65739597FFCCB +:102B90000045D4EE89596141351A7A8A730DF4F9EA +:102BA000A3910B0EF6267C8C8FF2CD43FFB36FBC46 +:102BB0007E35F2CA8178F772D07371EB48D6EFC2D6 +:102BC0007D37A3BCD2E11B9840533C37C037280661 +:102BD000877C51BC5C27519453D42DFC129E6245D6 +:102BE0008EDF18E52B473FC596238F5D816FD62377 +:102BF0006C6F108DBDB99F737651DE9DFCAFE3E124 +:102C000098368FFD3671ED259ADFFE75319E06826E +:102C1000B7ECCE1B17D450BAD0529410544D70DF7D +:102C2000964A5D57FA8B07F62579EE9C4D83BB4E8D +:102C300083DBEACA34EEE750B81B7479E5170AEB78 +:102C400083FC47F917FDB181BB291F66B9F8C17430 +:102C50009C5B3916B6936C88A0BD457AE43B1A9C00 +:102C60008FD2BE73C4F1F735F89E1821DB273E687A +:102C700009C07E5034760FAFD313D54E8F4A6315FB +:102C80000BB71D7250A9F0B2FEFCD7317FDBD74ADB +:102C9000F36A4EF5DD07BCDD1C6F49FE80E1F00DE7 +:102CA0009D0A796BB49CC73F9037791ED384CBC6FD +:102CB0004299586B81FC31CD25A7B25091FB63BA84 +:102CC000F0DA30DE4CE1E37AEF9DB77BA14FBC0731 +:102CD0005D88E0BE51F8F9FB1C11E0749E0872FD9E +:102CE0009B442BE7757C137DDCDC4BD2C7277D54DE +:102CF000C6FF56C0FD6E64EE803A9AC7D48706655B +:102D0000B07ED5DC9BF1F35D704FD5E886F6EF6FB2 +:102D1000B18ED8BF33A89F693784ECDFF1BDF5F5DC +:102D2000CCF847FBE84847A7FEE4EC4B78B84E5B8D +:102D3000D2EBBC4B597F12C2C5F2D18FB47D5BA8D8 +:102D40003A452F5A9F236ED297089689639625623B +:102D5000BEAFAF106F15D03ABE3E46150D5CD3CB5B +:102D6000EDA668FD4DE93FE133D85B0F8B60AFE125 +:102D7000D4AEF092EFD518827B8ABABD3196CA27BD +:102D8000F627BDC6C0EFAEEFB5C30AFDEE8674F3FD +:102D9000F749D966FD67B2685231FE94E1E67AFBE5 +:102DA0008127A2B3F753A5FE22868821DFF27A0B92 +:102DB0008B713E1D932EDA2F101C1169BE8FB12E20 +:102DC000CB27FF7501C61556399FEAB755B6EB1DDF +:102DD00027798B28509CACA7932253CA25C87F4AD9 +:102DE000F203D2D3F56E4ECFD2798FF2F3F51ECE29 +:102DF00017A4159D40BF256B3EB7627DEE0C97F87A +:102E00002E6F699A00B02A76B71C445A162C9A8005 +:102E10006376D1A1DA8348EFECD4DB6A59BED3E103 +:102E2000BE45A3D35BA2A6FD3087D6E1963DAA8717 +:102E3000F303A64D9FDC0B791BE77BA2A3AA4B44AF +:102E400033245754ABDE2F0197776FDBC1789ADFBD +:102E500027F5A318EECFEABD0CF799FA899C4E4AE4 +:102E60002BFA1BE8CC2B3E67796CF2F6366B12D549 +:102E70002FF42A5EECDB6BBD2210A0FDB7DE26CF5F +:102E800081F5740E601F8FC999F6E8AD027CDA6790 +:102E90004BA37166DEB0A410E34C19556C45BD1B05 +:102EA000BF211920A58B4EBF8BEEF5F95769EB7644 +:102EB000EE6585F1D8B1332D0672C1F25D697D9062 +:102EC00012BFD4F5DD48E0ADE39285E1EC381AC1DC +:102ED000FA86DE6EF9AE48E63BCB07D803C260B790 +:102EE0003C43EB2C0CF2E699677EE2369E2B67E2C0 +:102EF0005ABEFA18FCED2F92BF916473EA11F0BF2D +:102F0000FEFD3CA093F39A9C4D7A4624CEBF6ACD39 +:102F1000AE08FE84FC990869CF1DF96CD258EC2FDD +:102F20008C471C4EE8FC2BF3D987527FEEEE1A6FCC +:102F30005BCBC28F1FA1FCB980C56FA3F3E99C686E +:102F400039FF3BF0DFCD4EB6EBDDA9103C387FB743 +:102F5000F4E37C96628DA8C3F92B02BCBFB314B70F +:102F6000B58EF855E5730FF703FDBD44381845E5F8 +:102F70002FAD8B647EF692CD73AC0EFD3D2AFBFB2C +:102F8000CDBD3F3DBE1BE93D55F93FC5F2A4C5315E +:102F9000FECB7EB56408DAD3F92EFA527F4FBFA874 +:102FA00004C3693FE734EF5FD997E01BB6A1CDD2E8 +:102FB0008FD2BCCD4A03D2A1036E3804BBF30D6996 +:102FC0006E6E5FB03D454DC236EC17F8F8077CEEEB +:102FD0009BE581ECE6CFC7F6135D72C110A5E5F461 +:102FE0004682352CF968BE8FF1D7C4F3D9B577FA8C +:102FF000FBF304E6411207E02EB67BF81C0AF83713 +:10300000623DCFF9B23CACD715F91F069D9DF32563 +:1030100078702EBD407AFC55A87FCCCAF37C71F342 +:10302000BBD1B0EBC4907E1C0E7F485EFB04D4AFD6 +:103030001AE0167E6A3FE0B1EB26023FD53B776D82 +:10304000E47E2A1D1EE8B9E5BB2E1E4C829C78BD8D +:10305000F064800E77CAFC2FC77B3D2A4DB57CE318 +:1030600097327FA488F345A4755A51BF54CA470FBD +:1030700069E79F68CD65FEC8A4EDEE5AAF5F523197 +:10308000CAD7A7F8FBC2AEAD9F9B74DE55A561AB56 +:10309000D865FB2363E725335EBEE77967D7CE2D7E +:1030A000BDBF87ECC21F4EFDC06C033BFA06BB3CA4 +:1030B000A7B7107F01BDE8E7348DFB0BEC5F6AEF2B +:1030C000053F4D52959C9D848FA487C258CEF8BE73 +:1030D000E3CF8E59CDE7B62E67D544483EC8670585 +:1030E000B55F18E5BB0BF35BA89DF3C2EACE861C67 +:1030F0003223CA7B37BE573ADA9331073A3FEF455E +:10310000BE5A25B92BCD207739E3BED7F95917E53B +:103110006DC67CBE6FFDB19104670C525DCF22ADD0 +:10312000A35B7E9CBABD05FCF88130C98FA30A98C9 +:103130001FE9F30BEDFF15DAF73EE233AFD179E289 +:1031400023DC8F738EB1F27ABE6AA93C48E770A186 +:103150001C01846C8D1DCE796F14E16FBC5315BEBC +:103160006EF4453DA5F57A1EF899D02BD254AFB038 +:1031700057AC1DFBF7FBCE5BD5D6478DD0F9A9BB6D +:10318000977076376F39CF5BC247F4015EC62ADF8E +:103190006FBE0E5BD141ACC338671E9F8BE39C535F +:1031A0008FF904C37F18DF43E7193A1FE1F87EF275 +:1031B000D28F15E1B760FF7D6E67FBDA5E5BEBD304 +:1031C000BF257CEE5D92ED819DE805F05EF0CF6855 +:1031D0003BCBB37BA3841F7C65EFD48400EC452FED +:1031E000414F04DFE82D6479B8ACBF770E95537F6B +:1031F000FDC2685FC05E342F42EB9F0646FB157D23 +:10320000B87D8352FB660EDAAF8864BE733420F952 +:1032100078736C709E4ADF9B3FCF14A8775404D616 +:10322000A4A2DEEDD25F43E54935D46FF3922112BB +:10323000CEFF51F9DC68CEF3F68D73321F67FB4C7D +:10324000F3546F5FF8AF7A69EBD5BC5196F7833DC5 +:1032500014E52994A7F4639BAC3F57ABF7914697CD +:10326000B4CF990FF8A6445A41E7FDD24BC2D29988 +:103270002979FBC2EFF3485906DB28E7565C9FC269 +:10328000F4A3D9CB666B7C5BEF0F0D1C23212FCBF6 +:10329000BF390BB784839E679687B741EE3B5ABE12 +:1032A000320A7AFB4C9F1A0C835C39A3D0DB29AF1E +:1032B000A5625CAF1CB74CD7FF82A5C0EBCBED0E6F +:1032C0007137CBF7C102A33EA5AF6F55CB9878A35A +:1032D000DE5C6127FE42F02CD1F66D9AD3D73B7DA0 +:1032E00004F4E9EBE38DFAF4A7650FE4F2FED2C62D +:1032F0003B5BEF8D3F990EB96D22A7FA789D7A0F4F +:10330000D64DE757A097DB25BD086BFB478B29DF20 +:10331000307B8807F6EA89D31C4C6F1D2DE12C1FEA +:1033200037CC8EF0C26ED7B02B8CED06376BFB839B +:10333000F428A61BFFBE28EEA7D22EF395CF65304A +:10334000DDBC600F3CB915E52F87B37FB6325A8ECE +:103350005BF9BB248D2EBD29AB7AB15F8EE9A53216 +:10336000C21DC3E5BF8F677A7A36DC57007C127DB9 +:10337000B25DBCD21ECC8C25FC1FD3E80F7A23FB98 +:10338000F56AA3986E8596F7FD3C9EF538927F7995 +:103390003CDF7D4339EFB37BFB2EC43E5A1EC9F0A0 +:1033A0001C73C9F26395B1BC0FE6DFB7F430FCC5FE +:1033B000C78AECBC5F8EED5559DEFA739D1A849F67 +:1033C0005BA7CF9A25C7DF86F9A8BAE1A3E4DDD4CD +:1033D000CFFC955593D06E7EC5ED5370DEF69AF610 +:1033E00029FB6943F7F3FC4AB37FD497EE9D8CF930 +:1033F000D56407761CA47E1E9C736A11D6D39FEEFB +:103400009B86F53E6F6F7DE14F0477EB8A3FB25E9E +:10341000747DB46F26BE5FD8F31BAE5FBDF2BF16DE +:1034200041CEAFB64A7AD1CFE31A8D7E45866F1E64 +:10343000EA57AE7C9DF581C8EC23927FDEFEFDF855 +:10344000CEE9BD5B5E50A8DDD288BDD59CAA815C6B +:103450009C6B679460B492067C4A3DEDAC2B188D52 +:1034600075F159A49CB8745B881F184B91A0D97F43 +:10347000A8DDD21619BF42F2821DF4195A7F297DA8 +:10348000E77ADFF37B856891DF6377DF7BB55CF7F5 +:10349000607038FCAE199BB0EEE776FD26D3E87776 +:1034A0000D4D2F8757CEFFACB65FCEEAFB65B6BD9C +:1034B000D35E00B9EBFC337D4C7476FEC9C19C3FF2 +:1034C000ADB42B114A977F57785A46727C8DB765F9 +:1034D00024E4E707B5EF4BE35B4682AFE97C4E3867 +:1034E0005A7259FFCF6AC985BEABF34751D492C90E +:1034F000DF032D9968FF8245DA53F88FE0A8783A08 +:1035000069E3DDD20FE1B70C477EE826E4F5711AD6 +:10351000C2251FE969BE8FA54B3BE6F939F69BBD75 +:10352000547FD07ABBA97C70C09CDF9A2EEDE70354 +:1035300043E26FFAA9EDFBC3708E3C21BAF5D73F89 +:10354000A38DF3D4539D713CAAA6CF0AB74E1F6E2C +:1035500029DFDB80EF8F3AF17D6B12F1E5A59863EF +:103560002ACF5F9E674F49FBCD0B79BE249C17E79E +:10357000811782FF8558CA6743BE9278D5F33A3ED9 +:1035800043E7BFF2A34549B0DF7E94AEDBF93C7D53 +:1035900040973ADE1A6CA4EF64433F2E2F386985BA +:1035A000DEEC492CB31AECDAEBF31CD8578B37E47A +:1035B000398C74D6B0ADE010491CE2EC36AB072074 +:1035C000375803F7427E6FD8A6B6F805973BBC5430 +:1035D000FFACF3C0DBA8B768436C3EE46DBDFDE211 +:1035E000F52312CB0C700EDD665E879C16737ED8B9 +:1035F0006E73FE04CE80DEFF7CBBBCA0395F70C85A +:103600009CFFE4835B67819CCB55FFBD2AF4893F17 +:103610004D3884F3F1D3175E8CC6FA2CFD4BD9419B +:10362000E849A17122B46E0AF408FF5685E9E3B2B5 +:1036300078911EF8811E0F819D61A4930AE13F6875 +:103640004DB9BCFE19D132CB4B745559B7BCE064AF +:103650004157BF57B6ACB343CE0B1DB7A7FD2F9C48 +:103660005E37EC6AC5A364D9557563C509F82DD6D4 +:10367000BE3B01F457FC4B85E58AE2E707BD0ABE75 +:10368000DFB663CE0D9CCE9AC8F8D0ED7D8BF72ABD +:10369000C128CABB4649BA5DB85E617DBDA4D11CD4 +:1036A0004757B63624DEA6D95CBE78F7FEFF869F64 +:1036B000BEDCF118C7335C1E271878057A5BC5A7F6 +:1036C00082ED3D159BBF0D3397CB792DD4E7E1BF3C +:1036D00096E3E1AE92553ACFB793C8D0F9F04B5785 +:1036E000516A06E1FDAAE68DAA949BBDC5EC9775CB +:1036F000DA39CEB0CA21829104CFA128BBD745DFE9 +:103700002FAE8F6279615118C99FF99C8A708E43E0 +:10371000F4C4A0DDA977549683AAE2251EAA1E57F9 +:1037200002B0C556C1488AFC1332BF04DE2655D20A +:103730008FD7003FD6CD98174D526FABB406F70325 +:103740002F9DE7C03673BD4A9AE7D138C859E6EFD6 +:10375000D5A29DEBD7ECFE36CCF8DD60DF657D525F +:10376000D76B55C83304A77A4704CBB3C49823401A +:1037700057AB14EFC30E15299DE3A0EF254E962FEE +:10378000E66E94E747338C839083D70D66B967AEB6 +:10379000E2CD04BEC4BA70D6A7A9DC1FDE8BE564F7 +:1037A0009643484E6639AA7D8E9DE3129BF35A825A +:1037B00090C79A1F48F1D00A327FE4F3E89E7096D2 +:1037C0007B9AA74AB9A7795D1F6EFF3140EB0B3991 +:1037D0005AE2B9F99E1C1EB79F2ADB893E520F2080 +:1037E000B93A137A02C1E541B92E4767C5FA4AB022 +:1037F000EEFAFC9B63DBA3E0C712E5F1DF4B6ED86A +:10380000A29D87EDEBC203F0539C548A0E5A0CF62E +:10381000A95B32E4F93172AC77AB568FFD1965962E +:10382000A977FF80E0297BD0E26E48E95A07E1F5ED +:103830006662FE27D785E783EE468E95F6A7637905 +:10384000929F470E171CBF73BBD6EFED1916539A04 +:103850001841F448FD9C2C94F6EDA8E1456C07A4B2 +:1038600035BAB9BB38903519F29C2AB317FDFE9AC8 +:103870006EE0E9A48BF152DE3DB94CD924E1F2723D +:10388000BCDFC85F85B3FDF0A476DEE8EB4174349D +:1038900082CF718D9FADD3E8665DCF7463A28BB983 +:1038A00090B7413773E4B9D84957DAFA12DDF07AA4 +:1038B000B7135D48BA11E26BB42F744B793B44DF08 +:1038C000EAD4B77BD0B7880E9EC8E86DA817420728 +:1038D000C21A18F18FFC2C25A362472AB40449565A +:1038E000E147DC2CCE46C6D75DD6C04A82A7BF557D +:1038F000AECB00ABA43B3A65FC11F95CDF8BF8D989 +:10390000E2FB170B2FD52F4E126CB74A27F926264C +:103910008EDB09A47007AAB0E7508AF6C531B2FF62 +:1039200062A26FC4B3517F5E4B9CC6DC46C27F2A45 +:10393000587E40FBE87C6EEFB7C8F65E2BA503D33C +:10394000E43E6A5F15C6F82BBE734026E864D25881 +:10395000339D24664A39414F1B33DDBADC90087E23 +:1039600050D23898CF9986F0A2AA5DD8A7CF487DCB +:10397000A378F54D934700BE67E33DD8C2A7A7ECF7 +:1039800060FF4A49E39C1F7F083D655B387FDF98F5 +:10399000E97B0F783FADB817ECA20F25335FB12755 +:1039A000527B5FCBD473BFA3748A7FC7DB9023A6FF +:1039B000CC50B9FE1421EDB9A2518E33D9FFB935DF +:1039C00091FA9B3C5AE1F094B67057F232F855B434 +:1039D000F53DA6D17743B898FD9C13700DC84CCD2A +:1039E000861F8224D46EE4E401995AFD31CA06C8C8 +:1039F0004303C7C9FDA7D7473FE8372D53EEB7CFDD +:103A0000B47DA7E709AF5CBF6C4D585B5A34525B7D +:103A10007010A5F3B2C69E039F99942A26AC07DEC8 +:103A20007FAA8A4D0C6F7B31F385A84C37F8828FC3 +:103A30001459A6FB6D8399EEDBC6B4B7DD49F9B620 +:103A40002D39D27EA7E9F30B5D82E582B63192EF84 +:103A5000B56F8964FE73CCD51A1527ED5DACDF9781 +:103A60006A24F1D7BA867BE1372E75DADB707E2CBB +:103A70007C603AFBFB4B9B49BF475CFD5AB37E4FD2 +:103A80007A78586637FA7AA85E0E9A011D95AD5578 +:103A9000980E073678EC7D99CF292ECCAFCC194CF7 +:103AA00007FF2FF384735CF0657AFB3784F791B0DE +:103AB0001F0B0EBA1A3AC8D70BE3163715B37E1A86 +:103AC00099ED63FE355025BC101DCFD4E86F12EC84 +:103AD000A0E04BD6D6BED897AF6568DFE35C994EC1 +:103AE000A6EB70BE6FD066736502BEB655E1169C3C +:103AF000B793564AFAA67DE7C0BD80BBAC2202FC54 +:103B0000E0B8D67EFE0A6BD146CAF777086B541C24 +:103B1000E82B8FE93B90E5FB0CEBF7E92FC428C8B5 +:103B20000DA56BD749B834FA10D623E3E3699C4F4F +:103B3000B7A4E4C3AEA0D353206B6C76E608035D54 +:103B4000CC50981E683E87609F9D9755928F72FA61 +:103B5000BE1FF432696C301D71D8856A25C7AB76FB +:103B6000240A0FE2873A443BCB231D248F803FEA8F +:103B70007C46E72744175E4742D77AEB7C656B3D6E +:103B8000814678DE56EFE0F4A97A97B0124FD85EFE +:103B90009FC8F967EBDD9CB6D467F1F7E7EA3D9C77 +:103BA000DF593F8AF32FD47B39BFBB7E22A7BFAB3F +:103BB0002FE2EF841FE64B3ADFD1F9934E5F3A9F35 +:103BC0000AA5AB058466DC33A0F6CC0F753E887978 +:103BD00058F2BBF893BECEA94A913F11FC50B4CE27 +:103BE00001FF2854CF3EF322E1B9A3DCC9F1A11DA6 +:103BF00042F2C10EA783CF8D64BBD80DFB40C33208 +:103C00006FDB9D8673785EB922AC06BABDA9365CBF +:103C1000580D747D735DAC293FBFEEFDD7FA50FFA0 +:103C20003F8BF12DC2FA1CBBE3D4A37FA4EF8FDF3F +:103C3000713A03EB4E706C7908E3DE1EA1C1D12A04 +:103C4000E1BADDCEF2D2C008A94FE1CF6188732D71 +:103C50004E897DFB3704E7316D1D06DA5DB346C141 +:103C60002EB34A75ADA42A1F63BDE8FB9FB5F52AA4 +:103C7000A90B637C96346AFBD418FF4CF83CDE57E2 +:103C8000B05CA77885801FE9F82FEC419211C471D0 +:103C9000C51150681C8594ADF9B017AE79FD28E4C4 +:103CA00074A5EE10CBD53E8793E32884DF76D6D873 +:103CB0009F527790EB89D6FEA638C8C8E15E3BF8E4 +:103CC00005681BEB56927540609F8B2685EFF1943B +:103CD00069DFCBD628A6F8E27B3355E68B8732AC7A +:103CE0009C0ECA149A13A589CF299D5E897F703CCA +:103CF0006359539E7D91812F9768DF4BB32CA67833 +:103D0000C74319322E6A109805A57767A5DA1732CE +:103D1000DF7373DCBD5EBF242B7F75EA70F483E82C +:103D2000A0AEF68F645AB9DDA10C9784C741E7595C +:103D300014C7E9747B2EE872CCA7F8EF950C3FEB23 +:103D40005915CF3EFD2CFC7B157F0AE3F3A9629841 +:103D500066DFC80E8C9CCEF28FD7A98C84FC2DD741 +:103D60007FFCD37F89467C54CD4E6957A5B40D693D +:103D7000F5EDE56C57ABF6D0FE88039F35FBCD5FC4 +:103D80007DF64FD1ADAC97F893B4F85B8EF7AADE11 +:103D90007982E3C0F4B8AFD07635CA37ACA7EA7100 +:103DA00001BA3FB6709F8DF74DCD1E85F5989A5D8F +:103DB0001713C0E76AF6AD4AE82E2E27B45F3D5EC2 +:103DC00040B7BFD588B59FC37F4884C3F80FADFF08 +:103DD000766654AF53430562D5AE603B8855701C80 +:103DE000C7722D8EB32390C17EE19EE4ED9AF5C497 +:103DF000F049BFEDB0BA6310AF7C418889DDAD53A7 +:103E0000FC20797E9FA37D04BFF085ED2ACB91171E +:103E1000B647F17EA8DE7EFF41C4DB556F56D88DD4 +:103E200057258E30DEAA77AAC261E00F35B00BC5E8 +:103E3000F70CE7D2A7A36A415F4B5A14EF16F8AD0F +:103E40001DEE98DE0678DA35FA5A1AD63292D74540 +:103E500083FF14F89A41CE5CB2F77E8E13A47AE702 +:103E600059AEF96D24C7B3510F6F03CE331B0AD877 +:103E70004FBDA4654735CB05DB235D10694EDBCC18 +:103E8000F729BED1C6FB4693D3CEC04F82F6CFAA48 +:103E90002C0F034EECCBD35A3CABDECE3248B6B33C +:103EA0006878FB0DF6E788AEFA4B5ADAA2D3A9FE82 +:103EB00027BBDFE7D43948EEE325CE23B938473FA7 +:103EC000D919C9F7ED3ED9F9EB092FD178E75AC6D0 +:103ED000F4520CFB6CE0201BD73FB741C601F32521 +:103EE00011D60F5A783E67B62729AC2703DF849F87 +:103EF000333B9F8FB6F03EF6FF7B71ABB3156BC8BB +:103F00007D84EBB24780FE5BB5FB11ED9AFDE57F4A +:103F1000A7FF6AED7B9B52A48D23EF3B083D0EC2A9 +:103F2000A5ED3BD5C9FB6E79949DEF2F2C18E6BE0D +:103F3000711EF8E89B328E51F4773F04FD6FC13B50 +:103F4000F16C6F596E73F741FE8BC336F6132C2854 +:103F5000F01CF5A17E8C9DED4A22B17504ECAD6D8F +:103F60002952BEA85C433B9350DC8FE8CD4FF8ACA0 +:103F70000C58848FF29307A5F2BA3E526EF1DAD94B +:103F8000FF13E4FB92C7ECC28F7B2FFEE7A47E5D9C +:103F9000992AFD0E8F607F515A1917CC8C87DD4E00 +:103FA000A39BCA69546EA09FCA4DC14CC84F67ED10 +:103FB000D21E8972E84D95F9B25E8346A7E807FDE7 +:103FC000B6A5B8CEB3BCBB2B4A40EFB0BC1825EDAC +:103FD00021BF09DF146638AF6F1A24E9B841F3072F +:103FE000FAB748F80017E4F825F6A64CC8B9FAB8AD +:103FF0004BA29B78BCB3DA784B229AA4FF448BC7C0 +:10400000437D1EDF26D8BFD3FE6418CBCBA7FB1E93 +:104010007901E39F7E7230C711B4A50416EDE6F274 +:10402000708EE3AE782A2C08783F7B328AED589F59 +:10403000D9A41CF6595402CB6187A21E5C80FE3ABB +:10404000368729E0A39F29C29E88F22DBD590EA86C +:10405000A8AF633F4905B117C8AF944E84DCF7D9C8 +:1040600096C16C27FAEC0D952F29D0F735F8EE1391 +:104070004D0B7EC6F2BFF43F9E7EEA6F83BBF3AF6B +:10408000546C36DBC3F4F5D7CBEF1824ED03770C73 +:10409000927AC9CA412EE97F8B6C793095E729F96C +:1040A00003AD03EB7FB41F13606F3FD6B22741719E +:1040B00002CFC1CC5F03EFDBA49E757ABB8DFD42BE +:1040C000152F4679D9FE74E7157CEFB042957278CA +:1040D0008545DEDBABD0EE99564467B27D8BF0CDE3 +:1040E0007A6DFB16551B478EFBD9D601D29F10D493 +:1040F000F22FE4F03DB84971E2E6692C5F6DC80526 +:104100005E2F6E8EE4F8791AC78BB8878A9FFD5CA4 +:10411000E2336611EB0774AE317FAED4F873D59DF0 +:1041200057C7E05E817847E5FB1217AD9E3EE0BFC2 +:10413000A1F87A4FE3634B5F7894F94125ED17C4FA +:10414000592DD5FCCB4B9F52589E5CBAFAEA879802 +:10415000EFBE6D13B85F70B6E5FE68E37AECD5F894 +:1041600067577B0FD75F4AF565FB37A3199EAD36BE +:104170000FE0095DC7EFDDFE29F55F6A5FD142F20E +:1041800045EEE5F3BF288EDCF627F095EDE16C6790 +:10419000A3F5E77B46676C2D8B30FF33CF8433BFAD +:1041A00039132BF7FD27749EFAED80E787F7B15D91 +:1041B000EDBDE902E7D0E280B95F1DAEFD1ADFAFC9 +:1041C0008AF7C4C04F5345EB81FE687D7EC4EDDFA6 +:1041D000B171FBD0F93C8E76230CFBF49948A69B79 +:1041E00033FDE4BA9C7976109F676DB192DE09DEEB +:1041F00064E84B6762658A1B3EA0870A97A48733F1 +:10420000635AD81E7046D9C1699B4DB6ABA8D3FC82 +:10421000DA447F89A01FD026ECA98EB54720C7803D +:10422000CF8FCCE73488FBCEA17673D029CEBFBE2A +:1042300059F2DC8478053ECF7E1BF6E3B4F03D7383 +:104240009F264F566EBFDC4F8875AADCAEB03FEBA1 +:104250009276FE02EA5EBADD9FE872A95FF1226EF5 +:104260006B69E3B225A0FBA5B5EBE681EEF5792CF1 +:10427000D5EE5FB7292AC3D3164EFB27FBF2F174A4 +:10428000FCAA598A1E9F275CFAF9457B382CCB2D56 +:10429000E988B24DD45F65A3B296C749D1F55B39C1 +:1042A0003F1D4FB8CD02FB5E9B76DFB9A7F9EB70DF +:1042B000F6044F5296E44F6D29F29E6FFB5BF2BEFF +:1042C000F6C56F0A62E2FE813CC891FA7A7F047FEC +:1042D000166810728FC6E796C2AE4E70666E30FBDF +:1042E00073B2369BF343B69BF3D93BCDF9DCBDE605 +:1042F000BCE75573DE85717B77E109FA36E203A1ED +:104300006F2385BEEDCE94FA36F2D0B79142DFC668 +:1043100077E8DBC843DF461EFA36F2D0B79142DFBA +:10432000C6F7391A9E2A357B29D681E3D4F684EB69 +:10433000F100BC5F2ECC49603E2AAC521FBDB024B8 +:104340009BE5C74E3BD35407DB99F438A7B7A27C53 +:10435000E3B27AC37F7B6475DF146EC7F6E79ADF3A +:1043600049FB73657EB813F68ED6559FAC86D8137D +:1043700088F24D44FD0BB6F6ADC06F55DD2BEC6FEA +:104380006F5DE17EE70772FDD8EEA2C72D15E3DC75 +:1043900003DF267D49C66F7B1C463B6AA85F48AC9D +:1043A00035E4213F359BF3A17E20F035AF695F35C1 +:1043B000311D3C6E6BEF0BBE7FE24907DFF33AA184 +:1043C000D9EDC46C17CB63BA3CDF298FDDA36CC277 +:1043D000F9BD242B8EDB771CCA30DDD30B4D4B2F60 +:1043E000E5B3BCDA995FAB58304ED98C15FB59AFA9 +:1043F0004E8CE673E9160DB64190FF0D700F0E441A +:1044000098E868E8B6B810BF653F53FD61BB5343F9 +:10441000FC96434CE5D3D71698EFB5175D6D2A1F70 +:1044200068EF8C877348FF96069F4BD6B9E8CCE7B8 +:10443000F986D64B563C7F84BF56BC25E5D3329ACD +:1044400087B7407B9F231FFE39EF14E0AFBCC51632 +:104450008BF3BE543B87449DF95C2EB70ABF2BAE4D +:104460008BEECA5DC21B4BEDBFB43625331DDD712B +:10447000345925142D19722437087DE58D2746827D +:10448000AEAAD48DC92E2ABF55096CC545ECD3718F +:104490003B12AEA4F2FFB4F81EC9A2754AB605EFEE +:1044A0009D0F3EBA234DE0BD91136B9F8FE6B83C44 +:1044B0008DFE926DAE08D0C1C62695F514D8CDD428 +:1044C000B82E3AD9D8141F01BDA67C8CE297727120 +:1044D000B449DF0BC547A19AFD8E9BE67BF1902A7C +:1044E000EF406AF35CEE92F545BA6CAFDFB3D7E705 +:1044F0007B52D3472B36BE96790B7D3F3B787F2E80 +:10450000AE8457D6EFE6792FB56CDFDA97D27B1DF4 +:10451000BE5D98D7F2B7C6455F49E37CB95DC687F3 +:10452000FFB5F989C7FCC44FEF6C7AC20EFB418519 +:104530003560871E5CFEE4463BE218AEDBB691BFF9 +:104540002FDA56CCF600FDBEDAA77A7CB3868FF25E +:10455000B1CA0617CDB3FF60C94FCA23641C4BA173 +:104560003AFA35DC13B8B84DC9C3BC6614EDB0E3F4 +:104570001EFF3B1ADF09DD371D87A717F686BDAB87 +:1045800045F120DFD33E9989CB72440FD32FB9393F +:104590009D716908EBD51F0AD2BE708E6487E8D77B +:1045A000875569CF433C12AD73B93DD86B3AE4856A +:1045B00097E5FB0F55740E8DCA87DE2EC4559416F1 +:1045C0008D564D745E333ED2B40F660BC3BEA2FE51 +:1045D00066897EA6FC8C4969A6FA37CE181AE2676E +:1045E000CEEF2A67FE7595E95D97AADBFD6E85E340 +:1045F0007BC69ABF537A3BD3D90DA6F655629AE98A +:104600005D97259BDF653C1395D9A18F956BF7418D +:1046100066FBDAB4EFADFC9D2662DAAF03D33C7FD4 +:1046200094E7A58DFD08BA1D7D36FE9FD6DD79196C +:10463000D1198F89F85BD83B7C6679E408EBA942F5 +:10464000AE4395668FAACA92F6A82AFF113BE29B59 +:1046500009FFD62442497593C2F646AAEF488A93C9 +:10466000F9DBF17DA7F95E07FABB84F2436A31F604 +:1046700057687935CD1BE74235EC47B083E9FD6BD0 +:10468000FDEAF4197ACF3EB41FDF6037EFE78A6D99 +:104690003B0EF623BC4C2F8ACD437C4965CB545B43 +:1046A00071F6E574A6F3FD8BE516B67F751C7E8565 +:1046B000E9ACA3DCEA91F1DDFF181FD55E696F0D4F +:1046C000A5BF45341FF89917ED543C0145D6035E4C +:1046D000FA812E43F092D40DBE743C75E22DA47C79 +:1046E00031FE331CF1114A007CF232BCE878D4FA76 +:1046F0005FE4132C67123C018627A43F312A74FF24 +:10470000DDC2EF20746C50844BF96E3C4CBB24ED41 +:104710003603D3E4BCDB77291EC8EBB32E59F97BF3 +:1047200027BD14C938F51993CCFBB3937E8AE47E78 +:1047300099792981DBFD6FD3D177D18FEE9F098DD8 +:10474000FFD6EF5D2D1AACDD4B1A21467CFB4FC422 +:10475000AFEB72404FE749E779E3D2F0EF4CEDF66B +:104760001C5E1E95CAF1DA3ECD8EA8F3639FD64E2D +:104770001FB798CADD05A0EFFE09B017AF6E4C4B0E +:1047800036BE17E35B65633B6FF28A784E8BC35D81 +:104790000938478A57C8774D8EDFD52701FE88E351 +:1047A000AB6CBD2651D7C77F3A3C59E4205FC8E9BE +:1047B000897561B38D76783D6D1A2CED35FA397EA9 +:1047C000CE72387A36F6DFAA5DD108055ABAEAFD0C +:1047D000912E3ACF57597C8F0F667FEF463ECF859B +:1047E0006B632EEC70BA3C51B1AAB00FCEFDCAFF7C +:1047F00079E5319CFBBE15B604C8A39F7DA00A8451 +:10480000CED079C672C4A7E192AE3FDD12C9F710CF +:104810003F558417FEA625EAFE5C97E95CDD3B0B5D +:10482000E3FFDE41E38EC0B881AD8918D7E3CFC482 +:10483000B8BE151931DDD957F4B466BD94F3B6EAA4 +:10484000F664CDEE0CF91E79C8F7706241BE471EC2 +:10485000F23D52C8F7F8BE4DF32F0C6C68CF837E43 +:10486000EA1F2BB26AF9BC7566417EBF4589F080AC +:10487000FFDCA278FA70BCC166F9DEC4F29075D58F +:10488000D36BDA490633D0ED0F2E3984316E6E8C3E +:104890008835E5C739FA9AEA17BA524CE5D7250E9A +:1048A00036955FEFCE33E57F9875A5A9FE64CF18E6 +:1048B00053FE47A3AE37D59FEA9D6ACA4F9F38C7BC +:1048C000547F6651B1A9FCC6D94B4CE5737CCB4CE7 +:1048D000F979E53F35D5BFA97685A9DC2B5C569CD7 +:1048E000777BA17711DE5F86DE45E92D6F65388D18 +:1048F000EB3A7A9CA5DB77794E697250BFA1DE3620 +:10490000D025EED7800E0768F767BEC0B9D21B7EF0 +:10491000C9A022F5DE237D4137A1F542CB47471ED2 +:10492000B8E8A6352C7A2A7AA695F8C4E82B0E1496 +:10493000A4517EF5538533ADC45F465F7DE0F954E5 +:10494000CA373DB54A960F3B7011E5514FDF20F352 +:10495000D3058B1A8F0CF97A869FE631FA07A96B7B +:104960003DD26ED26DBC69A73D88F080784DE001E4 +:104970006990E813E901A24FA4AF127D96A50B71CF +:1049800090E813E921D23FF1FDF7A47F223D4CFAD4 +:1049900027D2B749FF447A84F44FA4EFD5CFE6F489 +:1049A000837A1FB7FB437D39A747EB6BF9FBC7F54C +:1049B000759CFEB9DECFDF5D43743B4390ED31BAA9 +:1049C000FFAB1A7E47D8ED76DBCE1AFDC28A579E22 +:1049D000A7BABFB2A156B446629FB65A634F39BA5E +:1049E000FC903DF35BAB386590BF5E0FF7260DE1A1 +:1049F000F1FBBB986F6BDF8F89E903F2699D0A5267 +:104A00007D29289F995FBA2A86F8C70FBEA9B5816C +:104A10005E3EB4747F7FFB0B8D4EDA877833878CD4 +:104A2000E8F2BBEB7EEFCEF81A835F1EFE6C3D8E84 +:104A300047F7C7F39F213E47F793EBF141D76AEF62 +:104A400023E97E703DFE47EFB7F09260BE77CD1A46 +:104A50002BCB2D515611C4387A9CCF358E963CC441 +:104A60003B5C53E9E438B73EF41DEF23523D2FDEA3 +:104A700099DBFC25D5CFEDF2BBF7D1E641E53C8FC4 +:104A8000C24B3EB6D75EA3C51DA0BD4396F33B7592 +:104A9000881183FC4129DBE11E55A87D7E571C004F +:104AA000EA47CAFA41F497FE158D17DDB58F06C4A3 +:104AB000B5E4216E6C40B593E3C6368C09F2BDB9FE +:104AC000E9B1D7DED3AA224E38E6C7D8474FA7FAB6 +:104AD0006602CFEFEE730FF0507E5A5C5A6FA4530C +:104AE00043DEB5EB667DE6625D757CE978D7D74B32 +:104AF000C7B7219E8AF1FC5DEB17BA6EA1EBA5AF9B +:104B000053E1A52EFC037F97AF4FD7FAC13EFBFFC1 +:104B1000CBFA0CB7B6F07DCCB04A8707707DD77A58 +:104B2000DDDC2E26E03E78F125F741A44BD27C5FF8 +:104B3000807F968A31135CC0914BCD819D27B4DE76 +:104B4000F2EF59EFE1907A07E20AD67C9D7679BDC3 +:104B5000DD21F51A620BD67E2DED4C37E27C3DE46B +:104B6000B6B11FEDCD703D1EC3EBCCA3751CA7F1F4 +:104B7000A343A296CF0F12D7FC58DFF1DA528FCBA6 +:104B80005ECC72EE78A7596E9CF04D5123C69DD035 +:104B90002B448ED6FCE13768FD5E279AB8DFD07BC8 +:104BA000F23768F269E83DF9E78668F2658A4801FC +:104BB0009F1A2F3C122EEDBD83F12ED96F92462FF6 +:104BC000696E558C063D089F15CCF155BC77908BCE +:104BD00071FD9CBF5E0438FDA108723F938991224C +:104BE000FF23216CF29D03793FB35AF5FD27E42C96 +:104BF000FD5EE6C270DFABD877AF444E998FF728E1 +:104C0000C6158C4B47BB03E3DD2C9F1C70A4B1BCC5 +:104C1000847D658BEBDA7F6FD0F9926E95F7069104 +:104C2000E2DE603A6D96D7E9FC41FE86AC1502EDF6 +:104C300026B8CD71387AFB1FBAC60A6B41CFFCFD8E +:104C400087B97BFAC3AEF366ECA0F1B083BF197BE2 +:104C5000C578CCF7CDD83E169986D939CD7931BDF6 +:104C60003B794EA7E7AEF126086B7CCF78D6F11AD8 +:104C70008A4F1DCFFF025E2F7487D72F060B29376F +:104C8000474A3EA2E3B72AACF31E671F635C44A504 +:104C900043E2E933808C7BB87557F13C3EA917FDA0 +:104CA00081EF4575A3B83CD40E2536C7705E7FC72B +:104CB000ECCC83EF4627127CD7397CEA50C2CBD9A3 +:104CC000FC60264930E2930D0D7CEFFADCB3AA07B5 +:104CD000F27FA5EA5EEB014F7953653FA0F8E695B8 +:104CE00064F809C5E6EEE3A32B1D12AFBAFEB3329A +:104CF000AD88F7A7701524CAF7D5E43D725D1EE8AC +:104D00001F26E38BF5FBCC3DC9072323241FEB1F94 +:104D100026F9AEBE9ED48EF349D4CF48E25349F76C +:104D200045B03EB0DBE54D1A0A7FCA786192A7759F +:104D3000BDBFA3977C3FF05A91F9D068CA8F3F64FA +:104D400013012AEF182F4CF164856F94F2BB16FA09 +:104D5000FD98B044D2AF0CFC20DC1D617A6F343278 +:104D60002BCE948FF2F433D58F19956A2A8FF50ED6 +:104D70003195C74FCC37E57B175D65AADF67F658DD +:104D800053BEAFEF0653FDA4F269A6BCCE9792E4E2 +:104D90002731A076AEA9FDC0BA1253FD147F85F964 +:104DA000FD54BFF74856029E77947F696B9687BC87 +:104DB000AF6A1196915DEF90FC3A5ADE0799E85C74 +:104DC000C4EF916434FDCC0C8FFA8D8A732629468A +:104DD000E1F724AE739BF96061A2393FDE95F72AB3 +:104DE000966E9C2B34FE28A8809E926AADA6EFF3A7 +:104DF000866A7C3457E4B29EFE5DEBEF1B625AFF7D +:104E0000507C5D4E0FCFE705DDD29E6F9C17ECF90D +:104E100046BCC09E6FCCC39E6FAC0F7BBEB11CF670 +:104E20007C6379C121331D8C3862A6832B8E9AE96D +:104E300040A7CFD0F5BAB2D54C1FC2A7F8947FB027 +:104E40005E577F6AA69FD0F521098BD76F825311D9 +:104E50008FA4FCFBEBB52E64BD3AD787F00DF9F6B5 +:104E6000DAE050BE275B78481578B7E4516D9ED7DD +:104E70000DADE527C3B65B7DBFE67DAED155435F83 +:104E800049571D879E0F071F7D34A4FFD7FBF902EA +:104E9000A83F3BFE62B21DF4D12EDF456B031FEE2F +:104EA000DD15B7497ABABC77F23395E3188E599A73 +:104EB00014F0EB8218DF36F0CB9BB36B15F8671359 +:104EC00045D18E4588CBF98FB064E4170C94F77701 +:104ED00045762BDF7FD0F9E282241917D83254F3BC +:104EE000F37A64DCCEF343A5DD24CAE3E238E3E2DF +:104EF0006C79BF83D499E40539C0C7E1F041C0475C +:104F0000B385DF696CB5B9396EC4FF862AE0F783D3 +:104F10001C0BF9728026DF357CE47000FE41EB85C6 +:104F2000E99C1D1C7098E25B876E7399F2392D899C +:104F3000A6FAC376BB4DE579C12C5379C1218F29DF +:104F40003FE2C82853FD2B8E7A4DF92B5B279AEA56 +:104F50005FFD6991299F24DA1F067E072A528F3E42 +:104F6000333455E2C92D387E6FC19DB1F2DEA7A65C +:104F70005FEB72BA1EF7ECD3E83954DE1F68F771A5 +:104F80001C75435FE1E17B180E4D9F12663DC0A783 +:104F9000C52D77DEA3F09BE396F578E54E7D41D3F2 +:104FA0000F7439DD10AFEC35C62B2F08EBFE3DE05A +:104FB000FFD2D63D14FE817639DF869FDAF9DE888E +:104FC0000E57283C33B538DA2D8EEEEFF5D8B225E2 +:104FD0009D256514FD1DF4FE98CDD3CA6FDD5F36A7 +:104FE0009EA7D54FF4D5F00BBB67A5FBBBC75B30C5 +:104FF0004CCE67BEC572F3D46C8ECF32BD83DF3B1F +:105000005BEAFD51B94AB7F35B1023E3A7448CDD9B +:105010000DFAED793C89CF44BB68E4FB475A9CFF0D +:105020004D6B5BEE194445F3ED4DDA7B60011BE8F7 +:1050300061D25892C3F284D8B66557B393E4A2C73D +:10504000EAAC6C3FE9BFDD358B24B8CEFB1B0349CE +:10505000EF017D40B681BEB42147E571AEC19E1B14 +:1050600081FDF64D679C3DFB0584D0CE0BA94F75A5 +:10507000436F4C87FA3CFEAFE3ED43F1A4EBAD4246 +:105080008B334CD7E0D2F1D76977D0F0A7DF7F70B0 +:105090002FB3156D72F23D8A8988DBD2D7AF2547D1 +:1050A000D265AD860FD4033FEAA95EA19A1D03FB2A +:1050B000728770C7B8BAA1433DFDBFC28B8EFF9EF9 +:1050C000EE57F5C41F42F9C277DDB7EA894EFFD922 +:1050D0007B57063E21E368B47509A45BD83F7D6722 +:1050E00094793F6FCC96768D71DABEA2F3DD996725 +:1050F000E61702F6F18655AAC62FE4395E9C52C423 +:10510000EF118B3A17CB33E51A2FD6CFD7850FC8BF +:10511000F7E0AEF516255C45F992669BD848A015D8 +:10512000FBBB8FF366BF931B71FE9E44C0CD263739 +:105130001AB7B44909EC4FB9FCBDECC54EF97E5C19 +:10514000E8BBD98B35FD172F2A60DF86FA65EECFD5 +:10515000D6CE6B8FF07C2BE167BDA50B7E8DDE027A +:10516000F21D31E8C3AAB4F3709C968E3737FC2445 +:10517000F15D79C26F4416CEF3466BB771749DF83A +:10518000D5FD2A9D7EC2C31CAF1F1A1770D6FF4AD9 +:1051900074777E1ADD7FD3D33EE8F4DF7C875FA887 +:1051A000C369891E053E04FFBFDBE857F9F3488257 +:1051B00090FD2731F08FB46AFD898DB9DDDD4FF4A4 +:1051C000ADD8C5F110AB2CBEFF405CF219EA1FEF61 +:1051D000B0DEE53C9080FBF89334BBD3E5F3D6E436 +:1051E000B0D1F27E40875FE5F5EE9828EF73131F8C +:1051F00015D877BA1F7FAA08F642AAFB497C6B46EE +:1052000031FE753F49717014C339B361B10D4F4818 +:10521000B63E7C7B6184BBCB7FD23A40C6E7F4E4E8 +:1052200047997EC9C3FDCDB87415F7732C3B45CAA9 +:105230006B8DF72C039D0DD9266C9867ABADFBDF0A +:1052400019989223F7D152F8D27B1BE27E5628ACF4 +:10525000072C57841E07C47C5ECF5F6CD2F2853268 +:105260007FCB2A996FD5DEC5DAAAD93B304FA498F7 +:105270000FF4F0ED9A3D04F3408A79E03BF81AF21E +:10528000E06BC883AF210FBE86147C0DDF4B445109 +:10529000729E2AFD3DE30DFB03FE9EF106B909FE59 +:1052A0001E631EFE1E637DF87B8CE5F0F718CBE1D4 +:1052B000EF31E6E1EF31D687BFC79887BFC7581FE8 +:1052C000FE1E631EFE1E637DF87B8CE5F0F718CB97 +:1052D000E1EF31E6E1EF31D687BFC7587E739D62BB +:1052E000F207DDACBD3B50BA3E8EE9A339B52829A3 +:1052F00087D6F73F23FFE7C7B654ACF3DE25FC6E35 +:1053000060558447AE73D344B9EE1621D7B97D0EEC +:10531000AFF3ED76992F94F1C2A1F403BFCAF874EC +:10532000E957410ABF0A52F85590C2AF32DE2AFD52 +:105330002A48E157C177F85590C2AF82147E15A470 +:10534000F0AB20855F0529FC2A6807BF0A52F85593 +:10535000F01D7E15A4F0ABE0FB318203FE151D2E7F +:10536000C8F9E9263D94E8D0A487BA4C79C8F9C6B3 +:10537000FA90F38DE590F38DE590F38D79C8F9C639 +:10538000FA90F38DF91BF188716F29EF1BDB41DE79 +:1053900037E6739AFCAFC1863579C3F95791B646A3 +:1053A000298F292E92EB729E9A05FF586BB8921C9A +:1053B000EB213976C56F678DBF92F889166F972BF1 +:1053C000DA2D586FF67BD3BAF98282E38373FE3B02 +:1053D00091CB757F2BFFD1BAE7ED14AC376CCB9036 +:1053E00070E9ED3DC2A522D5EB77E5BBAF173ABE1C +:1053F0005E8FF9A5010E5228F310079177BB331F7A +:10540000F1ED5B2D8A8C0B5D29E37243E9AA49E338 +:105410004B5B2D3B0E4450BBF662C5837B07995610 +:1054200071C8960F3CD5E6439EA8CB89D5E2836B25 +:10543000AF423C900EB76E7F243EC1F7DD46B70BFE +:105440007B198D73CD17C28EDF5B986497F204DAF7 +:1054500041DF1CEA57BC9B0CF4BD32479E7B3EFFEC +:10546000B2ABCAE8FBD0EDB557E11EDDA408D9EE1A +:10547000378F47331EA7342A9BF0FEC9E8EDC28B55 +:10548000FBB1BFD4E01EBADD652FE3715D7CFF4E3A +:10549000EFB7784332DF172C16ADE313D927A1F00D +:1054A000FBE63ADE687EAF627EC4E20FC18EFC2F5F +:1054B000DFC32171F1FBDCC3B966786C21E2DBC488 +:1054C0005EF90EE4E4E1C5AB7A135CBE807C07F2C2 +:1054D0009A2F6A5FE3FC66F90E2493CF48868FCF3C +:1054E000C3417E85DFFF98E2DF68E9E5C6BDE015D0 +:1054F000B604D4DF2E3C500B060979AF559F57B642 +:1055000038620957402FE2957803FD11E798017A38 +:10551000C9F3D8F87D90A956970DFC4697738A5D1C +:1055200072EC4275740CDFF70B91132E36F6E6B869 +:105530008D7F3D8EA483EF932FDF15CE72858FF87C +:1055400007F8E6B93C197759B9ECC39196D4AE384F +:1055500092D32981AD78DFF374EA8EE8510ACB113A +:1055600087C05FDB1A9FE77B82C5AB5EE3FB10174A +:105570001B1F8896F7AAA47FA54CC39B6E6F5AA8E1 +:10558000AD4F99163F74BC5EBECF4BE730BFF7718D +:10559000B1D1C67246A8BC2884EB0F88732B6FB4B8 +:1055A000F1DDD3C56B8B57278AEE7E77C52BE3CF12 +:1055B000B5719734DA384EA85C7B472BF477589650 +:1055C0006A72E8D26DE6EF277242E44FFDFD44AD0A +:1055D0004EF15BAFCC6439A8D6C671EEF35748B92B +:1055E00048EC1001DC6798BF629C05EF58CCDFE502 +:1055F000F528DDD0D13B9A7C34098312DEA75E8A80 +:1056000060BE32ED523FCECFBA94C8E98D97B2E476 +:1056100077AC1DD14B6BA1BC5FFFBE2617CD441CE0 +:105620006501E4B23E4CD71D44D7182257E35743D7 +:10563000BCCA2B30C34FB2F956214E73D246C1F7C4 +:105640009126437EA282D990A70AB02F520AF93E32 +:10565000C64485EFB74C1EBE4CDB07B42F04F311D4 +:105660007EF7C3377E6A00F137B37D3B2C58777DD8 +:105670003FF8FC6DFC0EE664BF62C77B813E4DCFF8 +:10568000D6E93D745F2C88D4EC634E69FFEAB48F91 +:1056900001587E9C27F246C4B32E802DB39FB6B02E +:1056A00084AAA86C599E9C1B79632394AC7FD36E0B +:1056B00032DF6291F79F48FEE3787571A4B00FE581 +:1056C0008BD72AF98897D7E1FA7AD8D849C37A775D +:1056D000D14149E7FECCEE03BD60F95D1926FF4CD0 +:1056E000685A4AF8C63E5A10D3FA63FCD2D0845C9A +:1056F000E11D9F8877C8F5F98A20E202E76AF9DBA5 +:105700009EBDF28F6B9C8C27CE8FCDED7723E23F31 +:10571000FE65FE385FB11A7F37AA4DF17973E53D1A +:10572000C80958DFC8EC767EC76066A64B9E2F215D +:105730007696DB72DDF25D84107B4B69B63C6F843C +:10574000D59D3C8FFD3A6EB657EAF33E6E33DF339C +:10575000D5D3EA5C6937F8BFBA27F1A045DEFB7FF5 +:10576000C412D8F122D16BA0B76F01E6FB08E2BDED +:10577000197E1FCF4F7F47A3934F69EF65E8F474FD +:10578000ACEE22DF972871DADDAA819ECAD6287C8A +:105790001FB1A44EDE27F6AD51E4BDFC1EEC578FC1 +:1057A000CFF99ADF517AFC1711B250C3EF7CFB910D +:1057B000D71C295DF8FD53DDAF6C927F0633106F67 +:1057C0003FB7369CDF41FE7A58D18F017F64B687A0 +:1057D000D76912F134D49F1AE3FB29BE97882307B7 +:1057E000616F5CF0F3B7F87DE19ABD29FCEE61F1E1 +:1057F000EEBCD57847E5EB61BE3B72897E8B9D2E72 +:105800003BE490EAC6583E9717F4D1EEA98B76F6A2 +:10581000E7E9EBF360AE94078A3C729C0B9A3E4535 +:1058200008B34D35D593E77FE83ED4EDA2A1F695B8 +:10583000D0F72ABECB9E027B89DD6057D5ED31B60D +:10584000ACE373709ECFB777FFBB8DAFEB76474D60 +:105850009F5DD8A9CF664FE803B97F9DE2821DBD49 +:10586000CCE9BE11F1F565876C88F01493E2DCF2A7 +:10587000DD92BBE4BB2525B7E6313F9B8F35C9C719 +:10588000BD8751BC8FCB0294C6F7BCDFE7AD7B650B +:10589000C01ED053D0CBF7E0CB5C5E7B9C412E2A60 +:1058A0006D524CEF18E8F91773A51D723EA919C087 +:1058B000DF4DB7A6D8F186D07C128F1037F8BA46E4 +:1058C000277A3BAAC771259352C541F9AE14C19DF1 +:1058D00022C733FE4E514993F93D06AACF72DDFE31 +:1058E000DC28EEAFD845F34E41EA6238090F8CA7A9 +:1058F000F67BA83F378FC3EB511A0CD86037988FCF +:105900007816CACF75056C18A7A451BE8FE25B2B21 +:10591000C7F1AD89B5E7402EB0BAEC038CF260A3B5 +:105920007CCF78BEF6FB11042FCBCB658427DCF34C +:10593000D2EF7D86E2AB5883BFAC29D62C5F36AD63 +:10594000B3617DE6F4F05EC3971A1D97348EE1FBD8 +:10595000F565562FDF97F069F8FEEBB2F0BBE12753 +:1059600099D3FC902D05798D2F7D093CF7069E82F9 +:1059700019FC3ED2B2708E679EE36AE2F976E2FBD2 +:1059800001C20FE4155711E39BE8C48F38C0B2661B +:10599000F3FA76C11325DF656F2EE6FDB7C8EAB3CB +:1059A000BB8C70ACDF9F81FB5B7368DFE3FD27E19D +:1059B000F2F17DCC530FDCC8BFFB063881E7288F9E +:1059C0007B02DE3B22BA61BAD6E9674181DCCFFABD +:1059D0007851C3ACD20E3FECBBF6A9F720E4F30636 +:1059E0005A6FD8FF7BDAA7765C00A471ED65F2DD13 +:1059F000BAD07DABEF577D9FEAFB56DFCF8FD98AB8 +:105A000082894A17DFA1F3BDF6B96EF03449837776 +:105A1000AEB6AE84D75785C1AE376298DCDFF3539C +:105A2000CDFB1FFDA1DF54BD7C6C3003F73DF5FAC3 +:105A3000FAB8F3E3643BEC03D05BEA304B67FDE577 +:105A40005CDF62E21FA59DFC63FBAA04F08F1D0AC8 +:105A5000FBE196DF23E5BEE5CFC87BE16796BFF8A3 +:105A6000F62CAA77FAC18D0B8CF72FCA82925F2C85 +:105A700024790BFC6391260F6CCCF4E50D33ECE735 +:105A8000B2FB9FC9C4FE98DB92770A6FA8D1BCF91C +:105A9000BDA33F3FF3D28757B9BBCE5D7D1E256BBB +:105AA000DEB5153B8D7893F47E7756079F5BA5385E +:105AB000B7E853696331F36191487A8FD2B5EEA1AB +:105AC000F450DCA8B09C575A3732A0FE2FF2EBD22C +:105AD000B553F98D287DBDF4775FF47357877FA6A2 +:105AE000B64E73357A9E3D4CEEC3B9E529F645BCFA +:105AF000FF53ECF8BDCD395AF99C32F3F7CEF5726D +:105B000075F2FBD5D827B89F84F5EA586B93F6CB8E +:105B1000ED97AD5732E4021D8EC59A9D72A1666F56 +:105B20005CA4C9CBB45E8B8DEBB5F871B95EA5CF23 +:105B3000BEF517BC5346F3D3DEA393EF0A94B4EC3F +:105B4000E0759BB3669D2D85EAFD64588A29FEA801 +:105B5000B436CF053BFDDC351B6DE0073F1926F160 +:105B6000164AF7F3B5F8621DAF388F14833F47AF7D +:105B70000F3EB883C6B9755978B4F177ED021A3D76 +:105B800097D6C6C661BCD2DAE27BA17FE9E740E8DE +:105B9000FE3B112EF74509F587FD79628C87EF559D +:105BA000CFD77E372FB4FE431ADDFDDA26DFBF4C98 +:105BB0008A6C7992E33B6A223CE013E9E9AD018CFF +:105BC0000B7A06DC768B7C2F33BDB2F573C041A215 +:105BD0003CC7F520C57B5B10ED1328BFC922EF79C8 +:105BE000A5AA32DDA7E107A637948B5EADFC1E5F48 +:105BF000E7BB5121F46A179BD7E0DD1F7B2FC1EF74 +:105C0000A6E9F4A9F7A3D3A74EBF3DCD6FD7F79C64 +:105C1000DF8914CDCE92E54976D0B80BEE1BC4BF18 +:105C20006BF15DF3B46BEF3576CE374CFEDEC765B6 +:105C3000F34D97FA52CFF36D2E4CE866BEA1F3D424 +:105C4000F7891E43DFE94F6992FE94130A9D63D4DE +:105C5000EEC4B2708EABD3E7A5DBF5BFEFBD878F87 +:105C600086C569F6AAD628C897F3B5DF51114199C0 +:105C7000C7F7A986EFFAF9AFBF5FA7F3E993B5DAE3 +:105C8000F9285AEFC17E1675697C0FF558D389281B +:105C9000BC1373628C844F6F77AB4DDE73165176F5 +:105CA00037DECFBBE9D63CFEBD94858D7D589FBDC8 +:105CB000A92E8DF9C24D7E581745A71EB048E38323 +:105CC00091B716AFBE02F5D7A7F0EFC22D747A4E8A +:105CD000ADE7F6433D9013239BA7DA53591E96FA7E +:105CE00082EE17BB5511457C4F0D7C12FBCBB23FAA +:105CF0001DE7CFE2F5523F9864116BE03F1DD8508D +:105D000034A12FF8C4C38AFC3D9A0DE6F7BC860E79 +:105D10002AFA027C26F45DBC5B6D2D5EE8A782E466 +:105D20000ED8D1163A8B589EBF45E393C79ADBF83D +:105D3000BD7E1DAF8FE0BF78A72AC47E146A271AE4 +:105D4000A8D907FF1FAF8F7B3D0080000000000037 +:105D50001F8B08000000000000FFB57C0B5C546541 +:105D6000DAF87BCE992BCCC080C84512878B84850E +:105D700034C080D7DA518150BBA0BBB9BA218E653F +:105D8000CA650650DB5D77D7FE8CA1A6667DFA4515 +:105D9000A665ED80976AC376483428A8C90B99593F +:105DA0007F62376A2FB9635BE62D40BAFCEDBF6DA9 +:105DB0007DCFF3BCE7301751DBFDBE6FFCF97B797B +:105DC000DFF35E9FFBF3BCCF3963348C751B186324 +:105DD0002A8B8E413968488964998C8D09695F6185 +:105DE0004C89C3F625DB45C64640FB7C93C8621947 +:105DF0002BD731FA7D8FBF1F31761F3C37C3F3425B +:105E0000A934D607FDD737CCA072C9D6C26DAEF182 +:105E10008C250925B1936360C0E36AB6078A25CE55 +:105E20001977302BCCD3A48DD225C373B52B29C7BA +:105E3000E09F6F49E343490CC69D69D4CF77437B0C +:105E400081694E41148C5FBA332A5B32FBFB5D6F74 +:105E500011181BC958A573461C4B61CCF1DDE167D5 +:105E60004CA9B01F98D304F37FE50977BBA08BA39F +:105E7000AE2D4982233CAAB3A758A07F95D8316F95 +:105E800012CC734E70EF4DA0FEE63853C0FAA1E578 +:105E9000E93AC6CCE98C39FFCF8734CFE7E2893BBA +:105EA00016C07887737F04CE53F5F81FF201326C69 +:105EB0009D68CFB2E4E1BC8D7B4D121C747B6356B0 +:105EC000099CE3BEC7C746DA332F9FF7B668B6A86A +:105ED00004DACBDB18C157695FE88ED420DCED5EB5 +:105EE000A6316169629A6828CF486C9507CADB526F +:105EF000D8A2B9067FBB0DE100EB9E89DC9254026B +:105F0000ED157B9F48324379D6C8EBA57B7F7A9C01 +:105F10004540FFDD5A0DE2D5AE621A0B8CBBD7258A +:105F2000D8DC50B2F268C61210A36E7D9991B159B7 +:105F300096709AAF627B0E63B9FE7DC1736A3FAB08 +:105F400062C5B88F31F503D9CBA1FC8BCA7B1FE2A8 +:105F5000F32FB57A8B2B19F16226BCFC658B548428 +:105F6000EDAEFB053656C0FA7E631AAC5F16C96A01 +:105F7000717CA1F4579B04CF571C10B2B5307B78CD +:105F800066B7E61E039116D159B589D3D98A7675BD +:105F90005122E07F458B402D0E9557331CBE2A2F92 +:105FA0004D66E680FD56B6B668CCB08EA319CE0914 +:105FB000FD1D9E539AA5785EB685B17CC027FE89EB +:105FC000F86B3EA5B937003FD5AD1C2ECE56DEBED0 +:105FD0003803903B99B66213D2A0DE2650BD3E6BCB +:105FE000C2FC35AAC07AFEFC3569589A084E4C3579 +:105FF000905402F0DC94D1A341FC3BD7CAF3425D3C +:106000001DB05E0D12E548DE9E6AC0F1661AAF3C17 +:1060100077B646D178AF336C03BB0936516D50610A +:1060200059EF344460B9B356CC50597173611609B5 +:10603000E0DF111691C52261CAAA5E3D4012503BB5 +:10604000705884F6DC48FB83489F710CB802E83333 +:1060500091790506F4DFDFF9592ECE7FCB18DF17D3 +:106060000CB6AE5E337D7E01D0C3268B7C8E4C5F3A +:106070002ED2F1C84340AFB0BFA7D56C833E07CF47 +:1060800057C2E6423BCCC208CFDF84B9F7C0DFAFCE +:10609000316F22CECF74DE541CF79ACCA7255AC399 +:1060A0000601F6F59B14FB63B88F3B05F5F86C1100 +:1060B00071208DC57EFD6AFE9C6D79C2A603FC4FE2 +:1060C000E7E867A345E66240A29A51F106A463C1DE +:1060D0006663AB60FD07330FDDCB802E1E1ED03113 +:1060E0002D9CAF5ECFCF3D7D20EC9400FD468F2AE6 +:1060F000165916F437AB5829F43F94297A55D89F8E +:10610000E9DCD89FE90A6DBE0C599681FCD0887AEB +:106110001BF5EF78F31B01CA44E9E2E1483857E286 +:106120002F054B3DF4291B3CFDF4FF85B2F452537F +:10613000CBEFA1FC75A4BD19517772B0F8941D5036 +:10614000F6B0C9A3B364F2F902F7DFF1AB6F22A294 +:1061500045FFBEFA074EEF7BD98AA5CE22C0B8E92B +:106160001D92579B75F97EFAE361E3A9D48FE1395B +:10617000FB0DA25B10B0FFE10F717FD37506AF146A +:1061800081E3D4177C3AFF38661E1D75FA4646280F +:10619000F83E91B158DC3C8C1FB8687037C1B96FBC +:1061A00091F94FA1AF1E8B48F8E991F1A4C091E994 +:1061B000B222917EEBD58A5EF085B34C3F7FD6E864 +:1061C00038FF0C5E126D38FF60B9D6CD608AC18E83 +:1061D00054D2275792A77F0079CA40D7BC976AFB51 +:1061E00033C20FF94A07FC78970C2FC03FC3F9253B +:1061F00079FEBB64B8DD6510399C7E120227996E6A +:1062000014BA50F62F98635869B41F9FECD7DD4736 +:106210002393098FE3FF83E3EF13C2DF3727D60110 +:106220001BB151FF984578FC5FC09F57B4FE0BF837 +:10623000EB0EC59F577F3DE2EF71D1D284FC800801 +:10624000C8A1D226C2F9580623FE2F93C22C9BE088 +:106250007C76E4FF9B88EF8F22DF2BFC3EA6D837AD +:106260001EF5E449C69EC17DF9440FB5A766A71087 +:106270009F5FC7BA13B01DF09C3717F12ED876E890 +:10628000242C7DFB5E86F55D1506CB1E386FBF5B4B +:1062900074A961FE8628F78EA5B06EC35D991617A6 +:1062A000B63396D58672A03CCC827ABE218ACB8545 +:1062B0008605E9A4870F7E2725ADC2732C08B33469 +:1062C00041FF866CDF2313A0DE30D66C7141D757B7 +:1062D0000596BE1DC7CFD1D13A0D7338DD363C329D +:1062E000DA8D7A05F4CFF37AA83F591EC6F09C0DDB +:1062F0008DB68468A0CB9722ECA3B361FFA3244E94 +:10630000D70DC9D00EE536A164C17D38DF78BE6FE8 +:10631000DF82B017F7C22CFA341059D07E7295B1D3 +:1063200009E5A5429777A5737937C6756A07C2C98B +:10633000359D65D4C2FC7F93E94B81BB60636C558E +:10634000B41FFE0A9DC5C8701756737A734D97E542 +:10635000623573D70B085FE60B07F8966941414237 +:106360006934D9ADB8EFFAE5801709F7CFE17F526C +:1063700064E59E61F8E747282CF3884C04E48F32EB +:10638000C6F9A30CE908E96F15D05100FD31DF759E +:1063900051A7C3653A82F16B8D25D370BDCF853F80 +:1063A000E463E3897F4AF3875B67563697030BF410 +:1063B000F699D89FED8E14515FAE30F1F54E647FA3 +:1063C000361AF5C5C95FBD791D96C7234A6ECB86BF +:1063D000FEDB167C5D84E2FC6F093E359EE36F0BAD +:1063E000FEFF68B443CA56BF49F4FE43F759281963 +:1063F00032504EAF047DA615B0E474B0F23E467440 +:1064000090C86A896EE365FD050CA3473975F300F2 +:10641000D88ECABCF0FF4797746C89CE5F9FC6A226 +:1064200082EA33740941FD0B4DC941CF6F8D1F17AF +:10643000F47CA6393BA83E3B635250FFDB2DD38250 +:10644000EA774E9C19D47F8E6D4E50DDC64C241FCA +:106450003AEA8A733F01BBE1B5BA92DC4F5497E345 +:1064600063AAF6D07EB305E824DB3B5F3509EA91E9 +:10647000875626437D53CB115E4F3CF44532E06690 +:1064800073CBD1F92AD0DB536F3CF4450AD41F6D8E +:10649000E9E2CFA7C062A340ACB6BC39DF05F89AE9 +:1064A0009B62DF8AF89A77A9F6288AF9F7D7CCBDDC +:1064B0002F5942B930677406EC2737C5FE103EBF2E +:1064C0002BF69E759100FB1F7D5BAB463CBF985D34 +:1064D000B215E9A1FF22A7F353889791FF7E099691 +:1064E00003D9618A9CBD923C54F8AD03F4C61215E1 +:1064F000C24947A5B7CE44E5A1BA782A8FD499D925 +:10650000128063575D0695C7EA2CD47EBC6E229537 +:1065100027EA6C54BE5B574C65775D09950AFFB25C +:10652000BD960D6A2442972AEAB4CE4F8F57D263A4 +:106530002028D969059FD0F94DBDAD399BCE759DF9 +:1065400009E959693FDAF9815904FA9D6AD5113D83 +:106550004F35749B75565E47B9B8FB22F38A11BC60 +:106560009F2AB05F8C271BFD98A90E03F54B1B8457 +:106570007E59D8EFCD0494F7536B3516B4639E5013 +:1065800033971EF66F14DF90701DE320CA6CD80598 +:1065900018D53A905771A06BF139F4633A28770F08 +:1065A000F2F54647D72E47F934BACC60A9E7F29501 +:1065B000E44BE2086F02EE2F71A586DA8D628F1927 +:1065C000E5605F9D7716D269812CE70A345CEF3075 +:1065D00011E4BD807CFB6D5722DAF3EDDC9E2FD0F9 +:1065E00096EC44FAAE5671FE65317AF71E5C47D5DB +:1065F0005DF12CF4EB894DB46C4268C51F64696091 +:10660000B717D61467A2DCED615B88AFC15EFD13DE +:10661000D2DB8F3381DF459948609EF8E2F0A64DCA +:1066200002DAADD7E7215DCED59A0F30E0075FF6ED +:1066300000D1FBDC48731E7A0ABEECAF793DCE7CFC +:106640004080E7263630BF00EA55CFE94D9F04F081 +:10665000A9D3131554AF694B307D12C0A755F80765 +:10666000FA47B7092A94BB0E792BA704FB05C4B7D8 +:10667000B3F8730DDFDF8006EDD88BD966A26FB05B +:106680009749EF0FCC34BA9B60BF71236AB357A010 +:10669000FD9469CEC37E49EA8108F463FABF5515BB +:1066A000BBC9EF1988F8C9783F7D3DD321517B28BC +:1066B000DDB5E6707FAF26CDB019F1501DAFD351D7 +:1066C000D971B188919D56928676B94DC3FDCBD0D4 +:1066D000F17B73B81E495EAF21B940A208B66C0BBE +:1066E000634ADDC52632D6F88BB021BF07C0C93456 +:1066F00063653FC8356247415A507F1BF61F7A8E4B +:10670000F61CF38F4F7949BB63AD4A5E0FE96529EB +:1067100073A33F182AC7AB72A365B9C0F1FC748C90 +:10672000BE11F19C26017DE750C94C50268633B23C +:1067300037135FD7BB913E77EB39FDA789BCDC2DC2 +:10674000F2FE9A30E6427A57FC874DB9F629B979BC +:10675000348F97E6915AB291AE139887D657EC24AE +:10676000A51FD8437A1202AA8174C4D754491C16B3 +:106770009E2772A615E58C44FEB0B14F03E4775F07 +:1067800078C4AA40FC55E37843E0B8E9344E19EFE9 +:106790005C25B24F47905C243A72A689E42F564B91 +:1067A000EC8880FE16EBD6A09E53C6F5821CFC1426 +:1067B000F0F047908B587E08F210D7FF33C8432C77 +:1067C000FF0AF210DB4F823CC4D207F210DB3F0617 +:1067D0007988E5BCBB8D56E49F9AB669ECD3207EE0 +:1067E00050DB7D01F5DE69C3D39143A6A3DEE4E16E +:1067F0009FAFCBE17E45EF2D1C9FFDA0BFD1FF00D9 +:10680000BA5C6B8ABEB21EEF37B2F91E80D3B67C7B +:106810006E87F427F0FAD21C35D56D22DB8EE3B7F4 +:10682000E56BF8FA2962393EB745F3797BD345B277 +:106830009FA64E9EB624079EDB62A13DC75FEFBDBB +:10684000813FB78DE2ED437A567E3E25D7A4F8EF1F +:10685000E9DC2F65642701BDD3FC4AFFF726723EB1 +:106860000CEDEF4E138BDDC3C0E32D996F892FD054 +:106870009E463E480EE08B6A33F18542870AFD55FD +:10688000E57238A769653A07DD42F0431D83723A25 +:106890004E4FF625C0C5C6E03CBB05995F42F901E5 +:1068A0004AD4070A3F287CA0D07B22F09910ED3F04 +:1068B000C7CD21F4AA948FCAE7E88E35FE9CF0DAA2 +:1068C000A136A1DF7733CC87E313C5C177EF46FE4E +:1068D0008C359AD1F52C7CC8503B9C1CEBFAEFC24E +:1068E00043910B5780C76570D0F0F25F8503C939BB +:1068F00094E348BFC3C8ADFD39D1B25DCEE9F744DA +:106900008E6D1FD251BFA057A1DFD0AF67C3DAD9B8 +:10691000DBF2397F287454053A10EB8978CED4CB5A +:10692000E59E729EA1732E6324FFD2C2787B289EBF +:10693000957305C8BFC33901F11FC6B87D711DD855 +:1069400017E84F4DC935D33EFA477E56B695F9CF75 +:106950007F470E6F7F4A94881E14FD32D42E488BD9 +:10696000E66406E91D66423FAF534BFCEE057FE649 +:106970002518873E219BE43FBF20E37170FE58112C +:10698000EDBBBEAF0D2ED4637DA3064E0A30BE6FA5 +:106990003B18366497D86E1340EFDE073A06F5D4FD +:1069A00005907B2C9DB173721CA1CF73F124FA73F7 +:1069B000353B24A603504A3BBE9A87F4B4B4536DCA +:1069C000A2B8D0F6C78E213D9E6E15CC6897F4B55F +:1069D000C2F1A1BFB3C1E8D643FF22A863FF650699 +:1069E0008DDBCCD7A3F883435EEF537D750AC68554 +:1069F00066EC5013DC973E2FB9D13E3BBC7DA50A17 +:106A0000EBA7DD028B837145D2EAAE04A8573E2D79 +:106A100058B430CE61283A8BF182CAE799C50BF39E +:106A200057B618C9CF5DDAA0FED817605F94BBB720 +:106A30006AD0EE29DF19DC5EB93BB80EF822F9EF17 +:106A40006886F600F9FC6D8E3186ECCD712C1BED5D +:106A50004DD6C0E3B98A7CBFDC6E757139BA82CB82 +:106A60006DC6BE8C457F5FEAFC2AE96303AFCF9118 +:106A7000EBA7A0FEF9571C2F0A5CAAE5B53F4F60B3 +:106A8000560F9CB7BA536F42FFBFBAFDEF1118B74C +:106A9000AF09F3517C9FBD2299D0DEDBD826B91017 +:106AA000BECE0EFD2E11E0567DE03D8DD988705F83 +:106AB0004EF6CAADCCB51EE3DC5E5164DD4447DD65 +:106AC00014A766B681A5384F5FBBDE847640F52BF0 +:106AD0001F74DD8DF50302D3231E47FB884E96EE0F +:106AE0004086A52DDD26E4FBE94442BC229E3D9173 +:106AF00084AF658877C433E01DF12C213E71BC5111 +:106B0000E3E6742251FDF4731CBF0ADE8BA4CD1A98 +:106B10006CAF6CE4789EB163CFB630A2033593E9D5 +:106B200080F07E7A27C7BBA6739D6614D26F630878 +:106B30001DB46B87E800F777191D84E0BF02F08D64 +:106B40007220940E42F1DF93C3E506D8DFA79F427F +:106B5000FBDB087E01F3C7234656F51E8D81F5CA7F +:106B6000A2CF3B9743FBD8F89758DA088A7F15E401 +:106B700062FC6BE63BEB105D3DB35EC8467AA957FD +:106B8000FBF63C81718BA8708AE3F427CFD9F932E8 +:106B90009CBB20FA9BA416D87FCD6B5ABADE28C9BD +:106BA0001587EC358C9729F174C033C5C99C1D5AE3 +:106BB0001E176B2DB405FA73FD09FC5C859A81B232 +:106BC000E5E817C07CB88E60E37E5E55078F172816 +:106BD0007E59951237680E8E1B08A677A85F452E42 +:106BE0008F5FA5C6DD6C463BBC7E01B387A55E4DBD +:106BF0003FF078CCD3B2DF7445FBF10A7A42B11B87 +:106C0000992B386EA1C8A96513F91E8FFEE2B86AE8 +:106C100004C6FD760B848F8A0E904F70DE0AB7DAB9 +:106C20006D1602F849EEFF19D21BC0ED8CABF6A031 +:106C30002821DD1968BF0E993EAB918EE0BC95D638 +:106C40003722F09C0E59AE38DA8D147FAB645B8A24 +:106C500090EE2A613DEF30F454F95C0BF929D7A28C +:106C600027C5CEAC6E0DEEB7317748CE8CFF1EE057 +:106C7000BB016439D77B2E99FE3223F1DE6F9099E8 +:106C800023919F87F49FC0ED3745FE5CBF1D583CA4 +:106C900060DE716E1D5305AC7FE373A6A0FA784FDA +:106CA0007C50FF9BDACC41CFB3BD1941CF738F59D4 +:106CB00082EA79DD1383FA4FF8D016549FE42B0E45 +:106CC000EA3FE54C49507D3013CE7395FBC15BE341 +:106CD00085A0FE33CDFAA0F967674405D5070D32CC +:106CE0007C64BB52B1775FCEE5F66E68A9C0F776DB +:106CF0004BF03A8ABF7EE7C4E0F5E6D882D7FBA125 +:106D000078D90BFA54057EC273A05FB1FC1DF8134D +:106D10002AF0139AC19FC0FA8BE04F60E9017F020D +:106D2000DB5F027F02EBADE04F60FD20F83F586F64 +:106D3000AB2BA6F295BA126ABF16FCBAE4758FC9DE +:106D4000EB1E97D7FD77E174429EEF5D79BE6E9C96 +:106D50002FCDFFDC593C56BC04FC3C2DFAACC68759 +:106D60007EC30A5F11C62D06DE9218C6A599DD7D89 +:106D7000AC2E06F5D9088A33B39281B731AE527D75 +:106D800020D5B4C98CFAEC0FEFE2F3BE56C98C7C67 +:106D900079A8EDEF1138CF854B61745F4A7A10EF17 +:106DA0001BBF6154DF04CF310E3AB3050408E93745 +:106DB0000FE9B70B694ADD4DF7BD25CD2D1AC45338 +:106DC00015F2293C7FCBA30E7EFE5C63D07313F6D5 +:106DD00087B24AE5A638C2B936653E2FF577A4F1E9 +:106DE0007BCF73CF1D5E3F05F56FCBE211787F5EE1 +:106DF000D5FC5EECBD57C1C7E7075FC8A4FBCA76E8 +:106E000098CFE09FCFD9AE96EB7CFF8EB496A26868 +:106E1000541CCD021B0BC505B685EE5FAADAF63809 +:106E2000506E5565DCAD66009F7E8F24C737F8BD78 +:106E300091C3C4B81DE7F92202EF575FF71CBDC329 +:106E400086F8ED381C81EBF6B74A41FED3682BB7C4 +:106E50008F475B3584BF0BAD8723F05E77A3E730A8 +:106E600087BBCA4BE73F24D7FBA12478B74974FE00 +:106E70008A4B62D03D768655A27966B68D35E2B9E9 +:106E80007A3C7CBD1CAB99B7A72D5E82FB3F1EBF31 +:106E9000204F227B100435CAF11B66EF413BA4CA88 +:106EA00023D986F3EF0AE479BBD49C4EDF4ADBDFBB +:106EB00085F2F878F1886CD2118A9F69E5766F9136 +:106EC000C69E867AA4C76036229D3F589C6A44FCC1 +:106ED0001EC212DB8B7769EC06BCC7E6EBF598BAED +:106EE0002390EE7A5A7325B47794F9F2E57587E822 +:106EF0007B086F2EC253B9BBD180F3F8F1C7DB73A7 +:106F0000AC26EA7FDCFDDE3CB4AB7A32C2C92EE9A6 +:106F1000D230F2A7AB9AB95DDCD391D818784F92F2 +:106F20006395FDF20C91F0DAD7A696FBDDBD8705DF +:106F3000F553D3392FEC0EDE8FC97DEA51B4C71D4E +:106F40004F4B0CF5A2435D1B8BE7FF6C67F0FECA4D +:106F500065383BD4DED8D8007A75B40FF18D81E85E +:106F6000BC5DE11333E153C1634F06B7E77AE2F941 +:106F7000BDA4A3650FD1F5E5F1A4EE64F41F127F63 +:106F8000A9A378E7B5FC67C56E08F0AF18FA8BEADD +:106F9000E2D43C31C56F1FBC966BABB68E44BFAB21 +:106FA00084FCCA1E06F62CACE9447B3A92F21FB66A +:106FB000E1BA83AD6ABABF76EADA667D0276D9A015 +:106FC000051805F63DB8532DDF7BD90C68D72E95F3 +:106FD000EDDACFCCF67C09F4AF738D48E7736486A5 +:106FE000911FD327CBBDCF5B92EF24BBE1986442C6 +:106FF0007F688687DBC18E666ED7567B92FF632AD9 +:10700000DAEDCD6ACCD4608A1DE294ED90D3B2DD86 +:107010007B7ACD8086FC9B4E813D968C792A5BBB2A +:1070200012E1B9337316D9B34EA999EC8965DB83A4 +:10703000ED07B06F82EA55CF85DA17727CCB13DC8F +:10704000AEF887DBAC4376C638F4670AA5A971C8E9 +:107050000F2FC87855FC9B95E32D94B7B351659ECF +:10706000A5C421105E359DFB2B70DF6E479885FC13 +:107070008D55AF105CFBBFE47E4C7F3C2378F4332E +:107080000EDFFE364EE7356AC18DF9483540B6341D +:107090009F4E70AFC138B36B3082E41363C5C8171D +:1070A0002B16707FD586315F286B157E08D1ABB764 +:1070B000A87C5254809C68B3A650BF020DB3A33E77 +:1070C0005B69B4907E1BA3E3767AE16A4F36D2C344 +:1070D00018F0C7B501F1F831860101FBED7E80C7DC +:1070E000FF9578C21C95491D15A01F195B43FD959E +:1070F000F941A2F0F1D79ADF04F31BFCF303BC23A0 +:1071000011DE5F582DA4B793E628F7FFB5C497CAE0 +:10711000792E00BD611C1863348837C7CE37C89FED +:1071200073B2EEF538AE2882EFA308F783F5305E30 +:10713000FE5196E7B179BCBC4D2E15F9D590677B11 +:10714000DF0AF59579F63F5949AE99883E57CAB49A +:1071500002F64C9C6F18F9BBE21D89F0FA05F003AA +:10716000F2FBC25AC19C16642F713AAFE14DEC3C60 +:10717000F3F44E4538B86CDD1998D7C6387F2D5AD0 +:10718000A537A705DE0720BDA3FF5102FFF2D12FCF +:10719000E3BF7253C56D9457B52AD68CF71735C81F +:1071A0000F29D7A6FF50BA87DF4EA4B76AA6B5A0AD +:1071B0007EA9690B7D6E51A13DFE4D085F24C97407 +:1071C000DA6817E87EBDF15B158FA3950A1437BB0B +:1071D0000B1A914EE987FDCAA7B9717ECCB3A0FB0B +:1071E000AE861839EF2B86EEE17E229FFF2E95F7B3 +:1071F0000DE4EFA36A4F32C6718E3AF93DD502E62F +:10720000A17BDD52D64D656F78F5012F4DEE1A8DBD +:107210007EF807762DC5911AD7361951CE66B1B5CD +:1072200026BC1F033679EEFBDC2BDB1BA1F7689431 +:107230009F95E7C7F3CABC92F83CA0833380A3F8BC +:107240009CCBC757BD7F2002E17EFEFEFDF37ECAC8 +:10725000D00F02B905F354D6B664D0BD8C8B7567D8 +:10726000E4FBF1ABE053C11FB49983F00A67B90E98 +:10727000E0339F0DE4636ED3B5F0A9C039493DF00A +:10728000630425E8319243A17856E05ECD6AD53C8F +:10729000FE56FBEE02E8FFB3B5A219EDCACBF07EB5 +:1072A0000DFC78F5FC91D728903F7B257C29785AF6 +:1072B000C8BC54FF308A8FFB70A144F1C3FF697CC6 +:1072C00035E4D94BF2AEC2B7A17C7A25BE5CB42AB4 +:1072D000847F43F874882F2DF02F007FF65511C45A +:1072E0008F0A7E1D66F09351FF75182D6E76393E1C +:1072F000D1DFC5FD54B60AEC49E187F0AB8FFCE362 +:10730000507C01ADD8501F54E705F3A982C72BC9A3 +:107310002D45EE7DC4BC474D02DD67703EFE85966F +:10732000F2E994FB0CE5DEE2D13CAE6F42CB8FC0BC +:107330006EC17BA24D193D23D1DEEBD528F3F07B46 +:10734000D78FD6748FC67CCD8FA6F1B257C3F34CBE +:1073500094BA2D8CC7033F4AD0BA106E1F09E3A61A +:10736000A31DF091F0CB3B783D4E63C6FA82B8E99D +:1073700026A8F7AA95F8E183B2FC7653F9D18209E1 +:1073800005D44F6047101E668195D03A82105D0C7F +:10739000FBF9E8E76373F05E4039FF03793C8EF454 +:1073A0001BF91C43F1F65F09146F5F04AAC384F74D +:1073B00002D39F284E81F693BF4ECDA6FBCA15C1BE +:1073C000EBA3FE4DA638E5569AE7964B03EAC5991E +:1073D000FE7D0DE9CD828BBC7DC9D8A07C665BF4B7 +:1073E00038EE27BB5323518F297A6DF0D87E436046 +:1073F0001CF5AC1C771EAA8F7B2429502FBEB1F739 +:10740000E1749CA75CE3CAB218308FF9A924B41FB9 +:10741000CAF73E944E76EDDE8DE9E89F94373D9CA9 +:107420006EA37AB89DFC23153FF7F97D93766D0A1C +:10743000B0A36F9DC0EDFB52DD1B8568DFCEBAF1B6 +:10744000F37518B71FFB6B81E2700B59F73AD4B78D +:1074500065199CAF58838EE43FCC47F7A47BC6DD0B +:10746000BE1BE5FEF18CBFAB97A0FECD53D17C6572 +:10747000CCBD390EE36F1B048ABFF9FB8FA67BD707 +:10748000C56B054D7C0CEA519E77FDC7BC2882E395 +:107490003D1BB2BBB0BD6C356F9FA575B7F6E03C28 +:1074A0004F6828CF0A14654A49C03DF61FF3F83DDE +:1074B000DDA2CD72BEB1BCCED86DB18D81E7FCA38B +:1074C0008C7F56FE01C9833B65BCDCB6FABD23F157 +:1074D000306FA4DAFE67942BEF3E7E3A0DE55941FA +:1074E000F4D94CA4F3B11AFB931578EE262DC52BD5 +:1074F000AD5989521CF4CFB97FDA63582E5ABDF8C2 +:10750000C90A8CFB6ED7911FA6EC6F856016D15F00 +:107510003DDCF8D37B106E671EE779A42B1AAF8F82 +:10752000BB5AFEE2B3753C1FFCF93A1D952FD49966 +:1075300098198EB8AF2E9EEABFAF3353C9E673FADF +:1075400052F2A6AE345FEEA530CA5BB66ED0511EC5 +:107550007DAED6F6551EC06BEC0DCEA68DF2B9C62B +:10756000C2F86C57F20C848375E3F22E34614FE558 +:1075700071FFEAED9E0D496487AF3EF54C053CCFA7 +:10758000CC2FF90EC7EB765EA478C1E1F687CA105E +:10759000DEE54D5A7E3EF9DC671E4F8F7B12E3BC61 +:1075A0006FA9C97FAFD979EA998D50DEBB79B92629 +:1075B00090DE7FE879BF95F7732DBEBA121CFE7579 +:1075C000BE7A3889F8A709F82AF3DFE7AB9AD56BBA +:1075D000087E73F34BC6E6C3FECFA85D49C84F676C +:1075E000C6DD4C74EEEA1408FE8A1C57C6A7E6F303 +:1075F000FBE82AD1B399EC48598E7F059E23C2F748 +:107600008DF6CFD2D18EFEAA6DC155CF7DB00E3D85 +:10761000228C9BE9A80C7D9EAFB1A7625E71BEC8AB +:10762000EDE7D0E7B7E72B71781EB7C59F1090A79D +:10763000E2848D4546A3FE13BC6120979D6DB79EE5 +:1076400055A1FF067EE1C7C17628FB3840AF5F69D0 +:10765000BFD72AAB711E955FEE4EF85064DE003D39 +:107660003EC917C6BC01EB0EF92BD0A6A1FB9E04A8 +:10767000920B8837CC87EA6B1FD784F5B31A8EC775 +:10768000BE83E097F1B80C93F2FDE73CDB7E3E0B46 +:10769000E56CE879AB5F394FF4E1687BE8A240E73D +:1076A0009F79569575EDF3BFB1F77C16E2EFACDA32 +:1076B000978FFE579FC6978578A87E95CBF37F1549 +:1076C0000E4A7BC5060D8F130A26F2230BA50B1459 +:1076D00007E83BC6E300D5EDBB489E0E76F0784C3C +:1076E0008DD85D1487F18BDA535D28CF06E3B95F3F +:1076F00006F3DB28CF2155D683AA81A43920D71ED3 +:1077000019A207EE0F9E41FED5E03C1E07E561651C +:107710008533B42BCE213F437BD9AAE4F548E767F4 +:10772000DC2373503EBE9DF58F6A8ADFBD1E6E92CC +:10773000C88E9530C778084E43E7704B3CD18729F7 +:10774000767138B305F4ABD198EF24BFFA38BF9FF8 +:10775000ABB981F3137B85F39373ED1B9AF880F932 +:107760007E25F393624FCE7AFD1FC4970FE7DA9E12 +:1077700040BE0C475988F3C547521EB5F21E8772AA +:107780001F69E890FDF862899ED7B4490CEFE5586F +:10779000BC91F20A8AD916CAB79CC53C53795E8F50 +:1077A000EFD129F07CF6EB522EE6A1813D4DF7DBBF +:1077B0004561F634CCD3EA150519AE1EEB9C007D6D +:1077C000F67E3EF757A74A02E9B1818470B253664C +:1077D000CE7796E27E957E5A91EB339887EC2CE635 +:1077E0001EC8C27B55E61DC8C2FB56A5DFBCD7C369 +:1077F0006B492F328F755EC03AA7F379BCF30BBC8F +:107800001F07795223DFC3164ADF6E437F6B45277C +:10781000BF7FEC15933FC03C3317C019F17A1EF0BF +:107820006A43FD6367361BF2CFF8916EE49F9A7D41 +:1078300002C37CBDEA766D13C685AAD5BE58A4E7FF +:107840008D6DEF6B909E6BF05E763C8E6772BCDC4C +:107850004479BF3526C6EFF5DAAEFF00E376CE6396 +:107860005C8B3A55EF513C00E536AE57D5DA42FE17 +:10787000BF8379C9FF773407D3CD603C8FE787F2A8 +:10788000C9E97C73107FCCDCCEF9631EE6731B68FC +:1078900038C55F67C6C7915DE21FC7F16093CEAF81 +:1078A000433BA63F45A07CFCFE30D75AB48F5CE931 +:1078B000DCAEE97FED052BBDF7A3735B7F8CF93C54 +:1078C000B2DD3B73C3569514B09F991D3CDED81FA3 +:1078D000C6CA0F12DEEDD7213E7CB92567F231BE54 +:1078E000A31978770AC683441E1F0D3D875D8E6BF2 +:1078F0001C67FCFD2865DFB31313B93C636EA2A3BC +:107900002E39BF5BC9D751C6DF324150EED1B89F87 +:107910002458AEFA5E1ADED7609E2BDED760F93BA4 +:10792000391F16EF6BB0FEA29C0F8BF735D88EF780 +:1079300035586F95F361F1BE06EB785F83E52B72E6 +:107940003EEC71DC2AE5F16D7C0AE9A20B796D94BD +:10795000BFDE1B1D521F15DCBF375A08AE8F12A8A1 +:10796000BF69C2C6A730FF7893922FC5CC46B4C377 +:107970002AC2F9FB1AA9067BEC04F4F38B77ED45D8 +:107980007F1EF89BDE9F2B885E504AEF97C46819D4 +:10799000CAA3DB27D8474F80F1C78ECD48DB4A7298 +:1079A000524FF7ECBD3FBB3192E27A6F494C8225D2 +:1079B000A765E4AEB5427D9A4120FA85F96E2A5159 +:1079C000FC4C986746C762AB8ACB0713DACB85922B +:1079D0006309AEB322419F8B72F888D59E81FB511B +:1079E000E05D346A591ADA455D6AF307189F75BD80 +:1079F000A366E85729713CA5DF93D669F9B8BF990A +:107A000019A96B73707E60369477360D6BC6FDD9FD +:107A1000C470A19EE4975985F2207F02A79BE96676 +:107A20006E1F7B35665534FAF561D362F05EB74B55 +:107A3000C6F33119CFC7653CE33D57818ADF7361D7 +:107A400089F75C5886E6A32DCF2FB14D20780F24FF +:107A500005E6B3CD92DF97000AA1F7D49C721CF320 +:107A60004B59EE34E695DCCAC779689E2A398E7781 +:107A70005E1D7C6FA88CF38F6754CEBD89CB6B16CF +:107A8000A9E179BFD73117E615CF7D3981E2507D65 +:107A90006ED1A506BCCF055E4779C65EE6FE2E8B8D +:107AA000E77C33777F1CF5AB97E3A9CEE8EE747CD7 +:107AB000AFA34FE62FA57EF03B9E97E4CC81BA8121 +:107AC000DE23A1F339E776A74741BD4FD08B485F4E +:107AD000CE26FEBC47E63F678A3C9F7C1EA6F32469 +:107AE000213EFA3B5F4EC2F7103719BC4BB9FCF789 +:107AF000A693DC66DE74CC6F3A2F784E62BEF1AD91 +:107B00006D29A5986F7F5EED7906EBB3DBD2785DCA +:107B10006839690A7C3ED29384F9C8B7B6A59662E3 +:107B20003EF2F9912DCF445902EAEA974EE273CD25 +:107B30008369A5989F3C5BEB3E568774F37B4E5F51 +:107B4000FA7D074E237CAADAB9FD3E7DDF810B2F3B +:107B5000A17E3E60A4BC8275139209DFF5EDCF6E65 +:107B6000467AEB6B51133F6C6A7EFF99DF503F2DD5 +:107B70008559666B3D560CC994B41DBA1BF7353B4D +:107B8000DCF325D6174FBC89F6317B04E7EBA51350 +:107B9000734A914FFB0EECFB05EAB3D99160D8E232 +:107BA0007E5ED0137E2AF78F2BC0B8409FB1BB0CEE +:107BB000E7AFFE9D96E71FEC8F9B8E7182FF9CC006 +:107BC000F3312A6ED89284FA567CE5F9BDBFC1F82C +:107BD000E6EFF474DF5313CDEDBD4AA9317F39E1EF +:107BE0006FD75ECC5BE97B5E4FF7AF151893B3E2BE +:107BF0007BAC63293EFFEA3FFF5E8678289476EEF1 +:107C0000C5F62F77EB4584438FC6167933F2618F23 +:107C10009AFCCE0AB95ED13B82EF27DC5744F88B41 +:107C2000D99284FAB672C4AFEEC07DCF96B63C83CB +:107C30007E0F7B564B770E679F07B8C1B8B37BD4D6 +:107C4000984903FB30AA905ECE0B5BCA9EC4F9F73D +:107C5000F07EE7F55B089EAE3DD7335C0FFA31D47A +:107C6000C7E785AD41ED67F73C9B857EE9B9DFCD80 +:107C700026FF54A173855F2A776B83F422498258CB +:107C80008C5BCA3F938B1902E259E70EEEE87B92B8 +:107C9000F9C79F6B567B3500A30A2D5B8BF9CD0A84 +:107CA0003F5426DE5A8CE7AB141BD3D17EA9C8F50E +:107CB00095215F9CD5335D3CF47B5BD65B95AD6BCA +:107CC000E6A01D7CA5FDFC4596475FC97CF8559B49 +:107CD000DE1D78DF185AFEB58E994FA8FCF585B5E4 +:107CE0005AB2E595F9DED6781CE8AF554773F971BD +:107CF00012FA37831CFB93ACEF16AD0AEEFFEE04CD +:107D00009E4F59ADF1A5A3FE53E67F7B8289DB87A9 +:107D10002A5F3ACAABD071B32559DEBC2090BCA90A +:107D20006C154ED1FB2408D2583F3C2B752E37E6FC +:107D3000130D8787F87C190F12E6F170BEAA6CD676 +:107D4000DBF4304F55982F02ED2587D117817650FF +:107D5000DF2B126B92D117A3CC9FE25F4F89535652 +:107D600078D436FD70EBC171D04F5E867F03285604 +:107D70004FE47C53DE164EEB31932F1FE9B67C6740 +:107D8000F0383CA729801FFBDA76C506FAEB0CF722 +:107D90004DF751A7886FFAFFF931BD075E29B2B5DB +:107DA000784F794EE0EF83409DDE073927DF775625 +:107DB0007E6D0843FA39F79583F8B84FF0919C7BB4 +:107DC000B1CD4672AC4FED2339B76B6211AF47F9B5 +:107DD000CA506EBD38F1A7243FFA127C65F89ED2D6 +:107DE00066A58E2FCC811DD0D1B690E4C96C89E7F1 +:107DF00051B05D6A138F1371782F93E1C4D886DE7A +:107E00003AF243D466B4973A272AF7421AFFF92583 +:107E10003F3FF531F3BE56E4CF7203C57DC0BE6A65 +:107E20007E09EDC005B1168CA787C24DB95F8C895C +:107E3000FE6629E2E91DA37DECC43CBCCFF4919F12 +:107E400001D44EF67CF56B5AF237FBD5037B517E9D +:107E5000B98DF67113019E0E4DF77A547117D4BE89 +:107E60002E34ED6721BD911CE1F4D697B98BBF0785 +:107E700022DF4F4E92F100FA8C35227D081CCF870D +:107E8000DBF69F4079D3D79D4A723A949FCEB63D98 +:107E9000168172E343D0EFAE8078C0878B9FA57CBC +:107EA00080F9980702E53D6B83CF37F8ED8FC92F36 +:107EB000649B03DA911E1B82EBA17041BAF406F1B8 +:107EC000818BF67D3FF21BC0A76A7A7735C261A825 +:107ED0003E17EA5240FD50483DA43F2BE1F6C3FD5A +:107EE0001318CDEB18EDED253F7E1FCFEFAD07BD8D +:107EF00046F503E1743F2DEE03BD15C3F516EA8B7D +:107F0000AA886E8A5FF51DD0D2BDCA83ED9F25E198 +:107F1000F9811E294E53D5FE722CFAF7EB2698698B +:107F20007ED08FB1941773A03D16FD11A5DD217A87 +:107F3000D2E5F70CB2507E28ED4EC99B4E79E54252 +:107F400077163E5F27CB1987087509EB8CCEE110B9 +:107F500038DFB37689E47C28DE56C9F40AF2218B37 +:107F6000F2395EE1F103451E54C872E510B667723E +:107F7000FE3729F75278CF847C3F8C9CF85A8123B6 +:107F8000ABA5F8CEFD13CDBC2E8FA77979FC89E780 +:107F9000EDBD7A3E2B2513C79995F745FDF228D5FF +:107FA0002F5F500EC4931C78501D0BE7AA7C46B07F +:107FB000D4C3908AD23545D09D2D532D2FA2B81A07 +:107FC000E6E71A2EDF57281D454EE4F8AD14B91F19 +:107FD0005EB957A0FBA5736A7E6F07F286DE0F5865 +:107FE00056B0A608F9EFBE18A726D05FBED6FC4B48 +:107FF0001B82EBCB6AD714C50DC3E795ABB6768D64 +:108000006497CF57616F2C8A355FDEAEECFB9C5EC8 +:10801000D9E774F5C84078CC5F533412CA65BA7F8B +:10802000171EFCDCE7DAB55ECA572D5D43F7C4B70F +:108030005CAA0D8AB35E6BBE0AE6A67B902BED3F71 +:10804000B47408DE5E8C2B31E0AF3DC467C03701ED +:10805000EBC5CBF43A149F285F3C06FD53665F3CAA +:1080600026303E115AE29B3322E58AB8A8043E2C02 +:10807000B30C030FA5FFD1893CCE1A3F91D3F1A8D1 +:10808000D9553B5E6214D7E941F97BA5F74CFE2236 +:10809000EFEF07BF6732239CF7EBD49B30FED3DFB3 +:1080A000F90DC587FBD719E6F37B07034B80E75D26 +:1080B000F1E39B02E3C0AB26713B24DCCAED9D9A41 +:1080C0000CF5D5E34B99C6A1F812D91B99E174DFE1 +:1080D000D2D7F605E9B7FE8E3C13DE8BF475BB0DE7 +:1080E000C86F35FFFC7FB1A887FB3A3EA5BCB4BE84 +:1080F0006F3FA37CB58D72DEE0A13639DFABDB6C60 +:10810000C4F6FEE2BF1761BF4D72E98F2FF0F898F9 +:10811000522AF18300FFF93BD4537B4C1B1FC554FB +:1081200099CAB02D24BFC07F8E46BDE18F2B98E346 +:10813000868BC304C615D2543CAE8025C615D2D258 +:10814000785C01EB1857C012E30AD88E7105AC6356 +:108150005C01EB1857C03AC615B0C4B802B67F2907 +:10816000BFE7D10F828BC73D0D24F757627E33C026 +:108170006F6527BFBF5AB947A27B617CCF03F5DF8C +:1081800065793BAD72DE8E672BDD07D61C902C889F +:10819000227C1FC4958EF93B0347311E54D32258CD +:1081A000D698B17D3EED636347DE07A5D8BE476D27 +:1081B00011CD444F1C9F8D825B8F7CD5B187E257D8 +:1081C00005719D94EF5FD32C308CBBCED3723FD919 +:1081D00029416B0EDDAB921DEDD47693FF52F59CD9 +:1081E000600E7CEFBB66E2459213CA7DF552FE88B5 +:1081F000393D7AF392203D6BE37957F827ECC72994 +:10820000E777931D1260172DC57B6C6C97BEA5F7A1 +:108210004D9CE0E08E10AE9D7755D9D1B21EF3B5DE +:108220007E68FE55E124F9DE3A9BBF4752FCF89286 +:108230007D0760BDC12D5AB2536E9F60BF6D521E47 +:10824000E619D828EE72B4534F7ED6275BAF0F8A5B +:10825000BB144AD751DC63855A20FD7DC46A9F3B1D +:1082600009E87246F1BD146F99116F243E56E8F08B +:10827000496BC94F70DE15E3F977980AB5ECE7341E +:108280009F9CCFA5E0A9B05E70E3F72C16330BBD21 +:108290003FB008C0877151E5FB1F8B18CFAF50E886 +:1082A0006AC55681E88ABEBC10F0BD8445F83D1011 +:1082B000D07FF76AB9FD9B28F27BF2C44D3C8FE278 +:1082C0003E66A7FC9165487D12E9D7D77CD06E0F3A +:1082D000BF2E89DBF7E6389C7FF17135E50717C6BD +:1082E000DD9E6E273D5F40F91382F76EE9FB1BAF01 +:1082F000263F83F3278EAAB9DC0178929FD585F4B7 +:108300004AF11E3B95C7EBCAA99C22BF1F16FA5E15 +:10831000437FE7CB2D38BEB0C66041F85FF13DC06A +:10832000B0ABBFFFE694F3EB12C59E5C33C2E36BC8 +:108330008305E15118D749EF89A5CAF33F9C5BB289 +:1083400009F1698B602E5C1FEF69B6007C8BF040F1 +:1083500002C6D13D367CCF66A05330513EF56572E2 +:1083600074EB3ACC53A949134C18AF2D0ADB5218C1 +:108370000BF317A524D377766ADA781CB60F4A4E2A +:108380000753DC92C0C7AA62317ECFF1E8CBB53F7C +:108390003D29CFDF3E5BE6B3FE8E2F781EF1B5E3BD +:1083A000B4BBE9FB1C4C4FEFAFD30FF635FBC6D186 +:1083B00014AF55E868B039AE09E9A845D613A5A5AC +:1083C000EFA9D18E68CCB337231CCA965C5C174BDF +:1083D000E71C3E4EA6E4DF87C6C902E5EDFF46DE98 +:1083E000FD89BA5A2ADFAD5B4565779D8B9E07E80C +:1083F0008B2308BF1F106F7D7BD230F156A6334709 +:1084000092BE05BEE7F1ED90F82AF0BB18C0EF333D +:108410003AA2EED980F64883C682F7CD98FFBCD247 +:1084200040F2E1FD49C3C65915F819282E3BC8F49E +:10843000398887E919A92A119EFF6D921014E74423 +:10844000BEC17322DF60897CA352F9F9E6690DA3EE +:10845000EF94A17DE022FB404FF85DBF06E40AD413 +:10846000EF65A620B9722144AE8023F3337A5FAC66 +:1084700043CB3609FEFCCFE9505CCA1946CE78B82A +:108480009C191DE6799EBEB3501D46F9C5C0EF4448 +:10849000674737F2BCBD25AC84D61D46DED07B3E97 +:1084A000F78E1838F914F4BFF76103D939EB139636 +:1084B000E6FF77E4CD9F2771783C81DF73505DED57 +:1084C0007B0E9B05BC8F5DB1906523BE95EF39C4D3 +:1084D000C118F27BFFF5EF398C983C12BFE7E00A38 +:1084E000FA9E43DC15BEE7306AB27161E0F71C46C4 +:1084F0004D1EB130F87B0EC685F89DB2FFC1EF3935 +:10850000A44FCEBBFC7B0E374E36FFA0EF39803D2B +:108510009B89E34FE4D8C66399289F3BF4FDE5E3CC +:10852000F23D6497682FC5B228C2A5A276D16DC569 +:10853000F26DD1733FB6035F4C4478153D967D03D1 +:108540007E972551EBA1BCF227ADB64938FF6BB938 +:10855000B6C9F83C34DE5F2F9F0FF6730BF60BCDD8 +:108560001F53E8E2AEC95C0ECD93CBA9F5C3BFC7DC +:108570003F6F32BF4FBED6BE61BF77E07ACAFED929 +:1085800096C556DC0FECF74EDC27ECB7044B66883B +:108590000E7A0FF8727A75C9FB62742E908FB33F12 +:1085A000E1F62895E92A7714DA0DA31E7047E17EDB +:1085B00047350EE8F17D90DFBA06F4683FFC76F5AA +:1085C000801EDB7F6BE3F9DAA1F36F9FCCFD91F4A2 +:1085D000A903347E0CFCDD4DFEC14014DA6DE9E5E3 +:1085E0004734AE147A4F6DF62741769399F87B8C19 +:1085F000DC36E60191213D8CD9C1781E63410CE93E +:10860000B94A1DEF5AF9C0FD22D2D13837EC3B8070 +:10861000FEAEDFAE1A0C7EAFD74BE3AAE425C05EF8 +:108620000B7AEE643CBF74942C8FD05EC4EFD939C2 +:10863000CB8FD077A6C08E0B998FBE7930944F59CF +:10864000ADB3BFE63353BE6250BFA577FF663DFAB8 +:10865000B5E5A55B35E4172F69598FA5C3F19E26B3 +:108660008E917D19D41FECCBA0FA65FB0CD947F590 +:10867000FD17D7C70DB32ED0C156A413850E8EAAF1 +:108680003DE3D04F3DEA0CB3F0F71D3CF45D9A2674 +:10869000F9BDF45DFF39DDCAF365395DC0F81D3FF2 +:1086A0008C8EEAA9BFF21DAF6B958A1C1CFACE8D89 +:1086B00086B9285E39CB4872AE46F6FFAA9798C8AD +:1086C0001E51F8BA5AE539B51EFBC51879FE9B8ACA +:1086D000D1F7AB7AC45194CF4D3FACCF4AA5FBAC98 +:1086E000D87A8F17E71DB85DA0EFB9158473B95A12 +:1086F0002896389E85E74744FE5D81A7517E4898BD +:1087000047C1BF37302597BF3F10CFF877DB98CAF6 +:108710001CF29D36391E7AEDEFB4F1EF92CDE7F7FA +:10872000720D5125A5CBF1F9821BE8F9C1EF521F5B +:10873000B1E2FE2A94EFB4717BBF614E063D7F55D6 +:1087400030AF413DE17A805DE93B6D7AE4FB80EF3B +:10875000B3BD87F8BAD6F7D994EF0F1C5D70C32369 +:108760007B391CBD78EF5533CB18E4AFFF17313C94 +:108770009ED2C05600000000000000000000000073 +:088780000408350000000000B0 +:00000001FF diff --git a/firmware/bnx2x-e1h-4.8.53.0.fw.ihex b/firmware/bnx2x-e1h-4.8.53.0.fw.ihex new file mode 100644 index 000000000000..48d7612907ee --- /dev/null +++ b/firmware/bnx2x-e1h-4.8.53.0.fw.ihex @@ -0,0 +1,12028 @@ +:10000000000039D8000000600000063000003A40CF +:100010000000191C000040780000009C0000599866 +:10002000000082E400005A38000000D40000DD2007 +:100030000000C7CC0000DDF8000000780001A5C872 +:10004000000056980001A648000000C00001FCE82E +:100050000000F1D40001FDB0000000040002EF88B0 +:10006000020400480000000F020400540000004594 +:1000700002040058000000840204005C0000000636 +:100080000204007000000004020400780000000078 +:100090000204007C121700000204008022170000F6 +:1000A00002040084321700000604008800000005E6 +:1000B0000204009C12150000020400A0221500009A +:1000C000020400A432150000060400A80000000489 +:1000D000020400B802100000020400BC001000007E +:1000E000020400C010100000020400C42010000030 +:1000F000020400C830100000020400CC40100000D0 +:10010000060400D000000003020400DC0010000020 +:10011000020400E012140000020400E422140000B3 +:10012000020400E832140000020400EC4214000053 +:10013000060400F000000003010401240000000098 +:1001400001040128000000000104012C000000004F +:100150000104013000000000020401D00000890603 +:1001600002040004000000FF02040008000000FF79 +:100170000204000C000000FF02040010000000FF59 +:1001800002040014000000FF02040018000000FF39 +:100190000204001C000000FF02040020000000FF19 +:1001A000020400240000003E0204002800000000B9 +:1001B0000204002C0000003F020400300000003F59 +:1001C000020400340000003F020400380000003F39 +:1001D0000204003C0000003F020400400000003F19 +:1001E000020400440000003F020404CC00000001AF +:1001F00002042008000002110204200C000002008A +:10020000020420100000020402042014000002195D +:100210000204201C0000FFFF020420200000FFFF5A +:10022000020420240000FFFF020420280000FFFF3A +:1002300002042038000000200204203C00000000DE +:100240000204204000000034020420440000003575 +:10025000060420480000001C020420B80000000131 +:10026000060420BC0000005F0204223807FFFFFFE5 +:100270000204223C0000003F0204224007FFFFFF6F +:10028000020422440000000F010422480000000084 +:100290000104224C00000000010422500000000074 +:1002A0000104225400000000010422580000000054 +:1002B0000104225C00000000010422600000000034 +:1002C0000104226400000000010422680000000014 +:1002D0000104226C000000000104227000000000F4 +:1002E00001042274000000000104227800000000D4 +:1002F0000104227C000000000C042000000003E840 +:100300000A042000000000010B0420000000000A85 +:1003100002050044000000200205004800000032F1 +:10032000020500900215002002050094021500202D +:1003300002050098000000300205009C0810000033 +:10034000020500A000000033020500A400000030F8 +:10035000020500A800000031020500AC0000000208 +:10036000020500B000000005020500B40000000610 +:10037000020500B800000002020500BC00000002F7 +:10038000020500C000000000020500C400000005D6 +:10039000020500C800000002020500CC00000002B7 +:1003A000020500D000000002020500D40000000198 +:1003B00002050114000000010205011C00000001FB +:1003C00002050120000000020205020400000001F5 +:1003D0000205020C0000004002050210000000406F +:1003E0000205021C0000002002050220000000138C +:1003F0000205022400000020060502400000000A59 +:1004000004050280002000000205005000000007E3 +:100410000205005400000007020500580000000813 +:100420000205005C000000080205006000000001F9 +:100430000605006400000003020500D80000000665 +:100440000205000400000001020500080000000190 +:100450000205000C00000001020500100000000170 +:100460000205001400000001020500180000000150 +:100470000205001C00000001020500200000000130 +:100480000205002400000001020500280000000110 +:100490000205002C000000010205003000000001F0 +:1004A00002050034000000010205003800000001D0 +:1004B0000205003C000000010205004000000001B0 +:1004C000020500E00000000D020500E80000000742 +:1004D000020500F000000007020500F80000000718 +:1004E000020500E40000002D020500EC00000027DA +:1004F000020500F400000027020500FC00000027B0 +:10050000020500E00000001D020500E800000017E1 +:10051000020500F000000017020500F800000017B7 +:10052000020500E40000003D020500EC0000003779 +:10053000020500F400000037020500FC000000374F +:10054000020500E00000004D020500E80000004741 +:10055000020500F000000047020500F80000004717 +:10056000020500E40000006D020500EC00000067D9 +:10057000020500F400000067020500FC00000067AF +:10058000020500E00000005D020500E800000057E1 +:10059000020500F000000057020500F800000057B7 +:1005A000020500E40000007D020500EC0000007779 +:1005B000020500F400000077020500FC000000774F +:1005C0000406100002000020020600DC000000010A +:1005D000010600D80000000004060200000302200B +:1005E000020600DC00000000010600B80000000068 +:1005F000010600C800000000010600BC0000000069 +:10060000010600CC0000000007180400009B000059 +:1006100008180798000D0223071C0000325E000036 +:10062000071C800035960C98071D00001AEA19FE79 +:10063000081D43D057860225011800000000000065 +:10064000011800040000000001180008000000006C +:100650000118000C0000000001180010000000004C +:100660000118001400000000021800200000000122 +:1006700002180024000000020218002800000003F5 +:100680000218002C000000000218003000000004D6 +:1006900002180034000000010218003800000000B9 +:1006A0000218003C00000001021800400000000495 +:1006B0000218004400000000021800480000000179 +:1006C0000218004C00000003021800500000000057 +:1006D0000218005400000001021800580000000435 +:1006E0000218005C00000000021800600000000119 +:1006F00002180064000000030218006800000000F7 +:100700000218006C000000010218007000000004D4 +:1007100002180074000000000218007800000004B5 +:100720000218007C00000003061800800000000290 +:10073000021800A400003FFF021800A8000003FFF9 +:100740000218022400000000021802340000000019 +:100750000218024C00000000021802E4000000FF32 +:100760000618100000000400021B8BC000000001EE +:10077000021B800000000034021B804000000018B3 +:10078000021B80800000000C021B80C000000020C3 +:100790000C1B83000007A1200A1B83000000013806 +:1007A0000B1B830000001388021B83C0000001F4B0 +:1007B000021B1480000000010A1B148000000000CE +:1007C000061A1000000002B3041A1ACC0001022716 +:1007D000061AA020000000C8061AA00000000002AF +:1007E000021A1AD000000000061A1AD800000004ED +:1007F000061A367800000006061A3670000000025D +:10080000061A500000000002061A500800000004FA +:10081000061A501800000004061A502800000004B0 +:10082000061A503800000004061A50480000000460 +:10083000061A505800000004061A50680000000410 +:10084000061A507800000002061A4000000000025C +:10085000061A400800000002041A62C000200228A4 +:10086000061A20000000016C061AB00000000028E3 +:10087000061AB1400000000C061A32C00000001237 +:10088000061A335000000064061A810800000002B6 +:10089000061A25B00000016C061AB0A0000000285E +:1008A000061AB1700000000C061A3308000000128E +:1008B000061A34E000000064061A811000000002ED +:1008C000021A2B6000000000061A3000000000022F +:1008D000041A300800050248061A301C0000000700 +:1008E000061A31C000000008061A5000000000027D +:1008F000061A508000000012061A40000000000294 +:10090000021A2B6400000000061A303800000002B2 +:10091000041A30400005024D061A3054000000074A +:10092000061A31E000000008061A5010000000020C +:10093000061A50C800000012061A40080000000203 +:10094000021A2B6800000000061A30700000000236 +:10095000041A307800050252061A308C0000000795 +:10096000061A320000000008061A5020000000029B +:10097000061A511000000012041A4010000202571B +:10098000021A2B6C00000000061A30A800000002BA +:10099000041A30B000050259061A30C400000007DE +:1009A000061A322000000008061A5030000000022B +:1009B000061A515800000012041A40180002025E84 +:1009C000021A2B7000000000061A30E0000000023E +:1009D000041A30E800050260061A30FC0000000727 +:1009E000061A324000000008061A504000000002BB +:1009F000061A51A000000012041A402000020265ED +:100A0000021A2B7400000000061A311800000002C0 +:100A1000041A312000050267061A3134000000076D +:100A2000061A326000000008061A5050000000024A +:100A3000061A51E800000012041A40280002026C55 +:100A4000021A2B7800000000061A31500000000244 +:100A5000041A31580005026E061A316C00000007B6 +:100A6000061A328000000008061A506000000002DA +:100A7000061A523000000012041A403000020273BD +:100A8000021A2B7C00000000061A318800000002C8 +:100A9000041A319000050275061A31A400000007FF +:100AA000061A32A000000008061A5070000000026A +:100AB000061A527800000012041A40380002027A26 +:100AC0000200A294071D29110200A2980000000054 +:100AD0000200A29C009C04240200A2A000000000CE +:100AE0000200A2A4000002090200A270000000009F +:100AF0000200A274000000000200A27000000000CA +:100B00000200A274000000000200A27000000000B9 +:100B10000200A274000000000200A27000000000A9 +:100B20000200A27400000000020100B400000001F5 +:100B3000020100B800000001020100DC0000000119 +:100B40000201010000000001020101040000000197 +:100B50000201007C00300000020100840000002837 +:100B60000201008C000000000201013000000004BE +:100B70000201025C000000010201032800000000E5 +:100B800002016080000000010201055400000030F5 +:100B9000020100C400000001020100CC00000001BD +:100BA000020100F800000001020100F00000000155 +:100BB00002010080003000000201008800000028CF +:100BC0000201009000000000020101340000000456 +:100BD000020102DC000000010201032C0000000001 +:100BE0000201608400000001020105640000003081 +:100BF000020100C800000001020100D00000000155 +:100C0000020100FC00000001020100F400000001EC +:100C1000020C100000000020020C2008000002114D +:100C2000020C200C00000200020C20100000020444 +:100C3000020C201C0000FFFF020C20200000FFFF20 +:100C4000020C20240000FFFF020C20280000FFFF00 +:100C5000020C2038000000C6020C203C00000000FE +:100C6000020C204000000034020C2044000000353B +:100C7000060C20480000001C020C20B800000001F7 +:100C8000060C20BC0000005F020C223807FFFFFFAB +:100C9000020C223C0000003F020C224007FFFFFF35 +:100CA000020C22440000000F010C2248000000004A +:100CB000010C224C00000000010C2250000000003A +:100CC000010C225400000000010C2258000000001A +:100CD000010C225C00000000010C226000000000FA +:100CE000010C226400000000010C226800000000DA +:100CF000010C226C00000000010C227000000000BA +:100D0000010C227400000000010C22780000000099 +:100D1000010C227C000000000C0C2000000003E805 +:100D20000A0C2000000000010B0C20000000000A4B +:100D3000020C400800000411020C400C00000400EA +:100D4000020C401000000404020C401400000421B6 +:100D5000020C401C0000FFFF020C40200000FFFFBF +:100D6000020C40240000FFFF020C40280000FFFF9F +:100D7000020C403800000046020C403C0000000518 +:100D8000020C404000000034020C404400000035DA +:100D9000020C404800000007060C404C0000005BBD +:100DA000020C41B800000001060C41BC0000000329 +:100DB000020C41C800000001060C41CC0000001BE1 +:100DC000020C423807FFFFFF020C423C0000003FCC +:100DD000020C424007FFFFFF020C42440000000FDC +:100DE000010C424800000000010C424C00000000D1 +:100DF000010C425000000000010C425400000000B1 +:100E0000010C425800000000010C425C0000000090 +:100E1000010C426000000000010C42640000000070 +:100E2000010C426800000000010C426C0000000050 +:100E3000010C427000000000010C42740000000030 +:100E4000010C427800000000010C427C0000000010 +:100E5000010C4280000000000C0C4000000003E880 +:100E60000A0C4000000000010B0C40000000000ACA +:100E7000020D004400000032020D008C021500201B +:100E8000020D009002150020020D009408100000D1 +:100E9000020D009800000033020D009C00000002CB +:100EA000020D00A000000000020D00A400000005DB +:100EB000020D00A800000005060D00AC00000002B5 +:100EC000020D00B400000002020D00B80000000393 +:100ED000020D00BC00000002020D00C00000000175 +:100EE000020D00C800000002020D00CC000000024C +:100EF000020D010800000001020D015C000000016C +:100F0000020D016400000001020D016800000002F2 +:100F1000020D020400000001020D020C000000207E +:100F2000020D021000000040020D021400000040FB +:100F3000020D022000000003020D02240000001830 +:100F4000060D028000000012040D03000024027C44 +:100F5000020D004C00000001020D005000000002D4 +:100F6000020D005400000008020D005800000008A7 +:100F7000060D005C00000004020D00C40000000427 +:100F8000020D000400000001020D00080000000135 +:100F9000020D000C00000001020D00100000000115 +:100FA000020D001400000001020D001800000001F5 +:100FB000020D001C00000001020D002000000001D5 +:100FC000020D002400000001020D002800000001B5 +:100FD000020D002C00000001020D00300000000195 +:100FE000020D003400000001020D00380000000175 +:100FF000020D003C00000001020D01140000000978 +:10100000020D011C0000000A020D0124000000076F +:10101000020D012C00000007020D01340000000C3D +:10102000020D013C0000000B020D0144000000070E +:10103000020D011800000029020D01200000002A05 +:10104000020D012800000027020D013000000027DA +:10105000020D01380000002C020D01400000002BA1 +:10106000020D014800000027020D011400000019C4 +:10107000020D011C0000001A020D012400000017DF +:10108000020D012C00000017020D01340000001CAD +:10109000020D013C0000001B020D0144000000177E +:1010A000020D011800000039020D01200000003A75 +:1010B000020D012800000037020D0130000000374A +:1010C000020D01380000003C020D01400000003B11 +:1010D000020D014800000037020D01140000004914 +:1010E000020D011C0000004A020D0124000000470F +:1010F000020D012C00000047020D01340000004CDD +:10110000020D013C0000004B020D014400000047AD +:10111000020D011800000069020D01200000006AA4 +:10112000020D012800000067020D01300000006779 +:10113000020D01380000006C020D01400000006B40 +:10114000020D014800000067020D01140000005963 +:10115000020D011C0000005A020D0124000000577E +:10116000020D012C00000057020D01340000005C4C +:10117000020D013C0000005B020D0144000000571D +:10118000020D011800000079020D01200000007A14 +:10119000020D012800000077020D013000000077E9 +:1011A000020D01380000007C020D01400000007BB0 +:1011B000020D014800000077020E004C00000032D2 +:1011C000020E009402150020020E00980215002065 +:1011D000020E009C00000030020E00A0081000006B +:1011E000020E00A400000033020E00A80000003030 +:1011F000020E00AC00000031020E00B00000000240 +:10120000020E00B400000004020E00B8000000004E +:10121000020E00BC00000002020E00C0000000022E +:10122000020E00C400000000020E00C80000000210 +:10123000020E00CC00000007020E00D000000002E9 +:10124000020E00D400000002020E00D800000001CF +:10125000020E00E400000001020E01440000000143 +:10126000020E014C00000001020E015000000002BD +:10127000020E020400000001020E020C00000040F9 +:10128000020E021000000040020E021C00000004CA +:10129000020E022000000020020E02240000000EB8 +:1012A000020E02280000001B060E030000000012C0 +:1012B000040E0280001B02A0020E00540000001069 +:1012C000020E005800000007020E005C0000000F34 +:1012D000020E006000000010020E00640000000B0F +:1012E000060E006800000003020E00DC0000000390 +:1012F000020E000400000001020E000800000001C0 +:10130000020E000C00000001020E0010000000019F +:10131000020E001400000001020E0018000000017F +:10132000020E001C00000001020E0020000000015F +:10133000020E002400000001020E0028000000013F +:10134000020E002C00000001020E0030000000011F +:10135000020E003400000001020E003800000001FF +:10136000020E003C00000001020E004000000001DF +:10137000020E004400000001020E01100000000FE8 +:10138000020E01180000000E020E012000000000F5 +:10139000020E012800000000020E01140000002FC0 +:1013A000020E011C0000002E020E012400000000AD +:1013B000020E012C00000000020E01100000001FB0 +:1013C000020E01180000001E020E012000000000A5 +:1013D000020E012800000000020E01140000003F70 +:1013E000020E011C0000003E020E0124000000005D +:1013F000020E012C00000000020E01100000004F40 +:10140000020E01180000004E020E01200000000034 +:10141000020E012800000000020E01140000006FFF +:10142000020E011C0000006E020E012400000000EC +:10143000020E012C00000000020E01100000005FEF +:10144000020E01180000005E020E012000000000E4 +:10145000020E012800000000020E01140000007FAF +:10146000020E011C0000007E020E0124000000009C +:10147000020E012C000000000730040000D2000022 +:10148000083007A8000B02BB0734000031B600008B +:101490000734800036500C6E0735000037591A03A8 +:1014A00007358000286127DA0835FF40401802BD63 +:1014B00001300000000000000130000400000000C6 +:1014C00001300008000000000130000C00000000A6 +:1014D0000130001000000000013000140000000086 +:1014E0000230002000000001023000240000000251 +:1014F00002300028000000030230002C0000000031 +:10150000023000300000000402300034000000010E +:1015100002300038000000000230003C00000001F2 +:1015200002300040000000040230004400000000CF +:1015300002300048000000010230004C00000003AF +:101540000230005000000000023000540000000192 +:1015500002300058000000040230005C000000006F +:10156000023000600000000102300064000000034F +:1015700002300068000000000230006C0000000132 +:10158000023000700000000402300074000000000F +:1015900002300078000000040230007C00000003EC +:1015A0000630008000000002023000A400003FFF6F +:1015B000023000A8000003FF0230022400000000F7 +:1015C00002300234000000000230024C0000000033 +:1015D000023002E40000FFFF063020000000080097 +:1015E00002338BC000000001023380000000001AAB +:1015F000023380400000004E023380800000001063 +:10160000023380C0000000200C3383000007A120BB +:101610000A338300000001380B3383000000138875 +:10162000023383C0000001F40C3383801DCD6500BC +:101630000A3383800004C4B40B338380004C4B40D6 +:101640000A331480000000000233148000000001FF +:10165000063220000000010206328980000000C826 +:1016600006328960000000020632322800000004C1 +:10167000063232000000000904323224000102BFA9 +:1016800006323180000000200632500000000400C5 +:10169000063240000000000204324008000102C08F +:1016A0000632400C0000000306326B6800000002A6 +:1016B00004326B70000202C106326B10000000029F +:1016C000043274C0000202C30233080001000000AB +:1016D00004330C00001002C50233080000000000B3 +:1016E00004330C40001002D506329000000000A028 +:1016F0000632950000000040063297000000003CD2 +:1017000006322450000000B406322AD00000000245 +:101710000632308000000020063280000000012CDC +:101720000232323800000000063250000000002073 +:101730000632510000000020063252000000002056 +:101740000632530000000020063254000000002042 +:10175000063255000000002006325600000000202E +:10176000063257000000002006325800000000201A +:10177000063259000000002006325A000000002006 +:1017800006325B000000002006325C0000000020F2 +:1017900006325D000000002006325E0000000020DE +:1017A00006325F000000002006326B780000005215 +:1017B00006326E080000000C06329280000000A085 +:1017C0000632960000000040063297F00000003C10 +:1017D00006322720000000B406322AD8000000029A +:1017E0000632310000000020063284B00000012CD7 +:1017F0000232323C0000000006325080000000201F +:101800000632518000000020063252800000002085 +:101810000632538000000020063254800000002071 +:10182000063255800000002006325680000000205D +:101830000632578000000020063258800000002049 +:10184000063259800000002006325A800000002035 +:1018500006325B800000002006325C800000002021 +:1018600006325D800000002006325E80000000200D +:1018700006325F800000002006326CC0000000527B +:1018800006326E380000000C02322A3000000000E0 +:10189000063230000000000406324018000000024A +:1018A00002322A340000000006323010000000042A +:1018B000063240280000000202322A3800000000F0 +:1018C00006323020000000040632403800000002DA +:1018D00002322A3C000000000632303000000004D2 +:1018E000063240480000000202322A400000000098 +:1018F000063230400000000406324058000000026A +:1019000002322A4400000000063230500000000479 +:10191000063240680000000202322A48000000003F +:1019200006323060000000040632407800000002F9 +:1019300002322A4C00000000063230700000000421 +:1019400006324088000000020720040000740000F6 +:1019500008200780001002E507240000322600005E +:1019600007248000246E0C8A0824CBB064F002E7C0 +:101970000120000000000000012000040000000021 +:1019800001200008000000000120000C0000000001 +:1019900001200010000000000120001400000000E1 +:1019A00002200020000000010220002400000002AC +:1019B00002200028000000030220002C000000008C +:1019C000022000300000000402200034000000016A +:1019D00002200038000000000220003C000000014E +:1019E000022000400000000402200044000000002B +:1019F00002200048000000010220004C000000030B +:101A000002200050000000000220005400000001ED +:101A100002200058000000040220005C00000000CA +:101A200002200060000000010220006400000003AA +:101A300002200068000000000220006C000000018D +:101A4000022000700000000402200074000000006A +:101A500002200078000000040220007C0000000347 +:101A60000620008000000002022000A400003FFFCA +:101A7000022000A8000003FF022002240000000052 +:101A800002200234000000000220024C000000008E +:101A9000022002E40000FFFF0620200000000800F2 +:101AA00002238BC000000001022380000000001010 +:101AB00002238040000000120223808000000030DA +:101AC000022380C00000000E022383C0000001F446 +:101AD00002231480000000010A231480000000008B +:101AE000062210000000004206227020000000C8FC +:101AF0000622700000000002022211E8000000002F +:101B000006223000000000C0062240700000008065 +:101B10000622528000000004062267000000010037 +:101B2000062290000000040004226B08002002E955 +:101B300002230800013FFFFF04230C0000100309EB +:101B4000022308000000000004230C4000100319C9 +:101B500006228000000000A0062285000000004050 +:101B6000062287000000003C0622404000000006DC +:101B700006228280000000A00622860000000040AD +:101B8000062287F00000003C0622405800000006B4 +:101B9000022211480000000006223300000000026B +:101BA00006226040000000300222114C00000000BC +:101BB0000622330800000002062261000000003007 +:101BC0000222115000000000062233100000000223 +:101BD000062261C000000030022211540000000003 +:101BE0000622331800000002062262800000003046 +:101BF00002221158000000000622332000000002DB +:101C000006226340000000300222115C0000000048 +:101C10000622332800000002062264000000003083 +:101C20000222116000000000062233300000000292 +:101C3000062264C00000003002221164000000008F +:101C400006223338000000020622658000000030C2 +:101C50000216100000000020021700080000000219 +:101C60000217002C000000030217003C00000004D3 +:101C7000021700440000000802170048000000029C +:101C80000217004C00000090021700500000009066 +:101C9000021700540080009002170058081400003A +:101CA000021700600000008A021700640000008034 +:101CB00002170068000000900217006C000000800E +:101CC000021700700000000602170078000007D01D +:101CD0000217007C0000076C02170038007C10041B +:101CE000021700040000000F061640240000000246 +:101CF000021640700000001C02164208000000019D +:101D000002164210000000010216422000000001ED +:101D100002164228000000010216423000000001B5 +:101D20000216423800000001021642600000000264 +:101D30000C16401C0003D0900A16401C0000009CAA +:101D40000B16401C000009C40216403000000008B9 +:101D5000021640340000000C02164038000000104B +:101D6000021640440000002002164000000000015E +:101D7000021640D8000000010216400800000001D1 +:101D80000216400C00000001021640100000000185 +:101D90000216424000000000021642480000000007 +:101DA00006164270000000020216425000000000B9 +:101DB0000216425800000000061642800000000291 +:101DC00002166008000004240216600C00000410D3 +:101DD00002166010000004140216601C0000FFFFD1 +:101DE000021660200000FFFF021660240000FFFFC3 +:101DF000021660280000FFFF021660380000002075 +:101E00000216603C00000020021660400000003412 +:101E100002166044000000350216604800000023EE +:101E20000216604C000000240216605000000025DD +:101E300002166054000000260216605800000027B9 +:101E40000216605C00000029021660600000002A93 +:101E5000021660640000002B021660680000002C6F +:101E60000216606C0000002D061660700000005223 +:101E7000021661B800000001061661BC0000001FD8 +:101E80000216623807FFFFFF0216623C0000003FA7 +:101E90000216624007FFFFFF021662440000000FB7 +:101EA00001166248000000000116624C00000000AC +:101EB000011662500000000001166254000000008C +:101EC00001166258000000000116625C000000006C +:101ED000011662600000000001166264000000004C +:101EE00001166268000000000116626C000000002C +:101EF000011662700000000001166274000000000C +:101F000001166278000000000116627C00000000EB +:101F10000C166000000003E80A16600000000001D3 +:101F20000B1660000000000A021680400000000648 +:101F30000216804400000005021680480000000AD6 +:101F40000216804C000000050216805400000002BA +:101F5000021680CC00000004021680D000000004AD +:101F6000021680D400000004021680D8000000048D +:101F7000021680DC00000004021680E0000000046D +:101F8000021680E400000004021680E8000000044D +:101F90000216880400000004021680300000007C55 +:101FA000021680340000003D021680380000003F19 +:101FB0000216803C0000009C021680F00000000722 +:101FC000061680F4000000050216880C01010101CC +:101FD00002168108000000000216810C00000004B7 +:101FE0000216811000000004021681140000000295 +:101FF000021688100801200402168118000000054E +:102000000216811C00000005021681200000000558 +:1020100002168124000000050216882C20081001F9 +:1020200002168128000000080216812C000000061C +:102030000216813000000007021681340000000003 +:1020400002168830010101200616813800000004C4 +:1020500002168834010101010216814800000000C7 +:102060000216814C0000000402168150000000049A +:10207000021681540000000202168838080120046C +:1020800002168158000000050216815C0000000560 +:102090000216816000000005021681640000000540 +:1020A0000216883C20081001021681680000000812 +:1020B0000216816C00000006021681700000000705 +:1020C00002168174000000010216884001010120FF +:1020D00002168178000000010216817C00000001D8 +:1020E00002168180000000010216818400000001B8 +:1020F00002168844010101010216818800000001D6 +:102100000216818C00000004021681900000000479 +:10211000021681940000000202168848080120047B +:1021200002168198000000050216819C000000053F +:10213000021681A000000005021681A4000000051F +:102140000216881420081001021681A80000000859 +:10215000021681AC00000006021681B000000007E4 +:10216000021681B400000001021688180101012046 +:10217000021681B800000001021681BC00000001B7 +:10218000021681C000000001021681C40000000197 +:102190000216881C01010101021681C8000000011D +:1021A000021681CC00000004021681D00000000459 +:1021B000021681D4000000020216882008012004C3 +:1021C000021681D800000005021681DC000000051F +:1021D000021681E000000005021681E400000005FF +:1021E0000216882420081001021681E80000000869 +:1021F000021681EC00000006021681F000000007C4 +:102200000216E40C000000000216882801010120DB +:102210000616E410000000040216E00001010101AE +:102220000216E420000000000216E424000000046E +:102230000216E428000000040216E42C000000024C +:102240000216E004080120040216E4300000000534 +:102250000216E434000000050216E4380000000510 +:102260000216E43C000000050216E00820081001F8 +:102270000216E440000000080216E44400000006D4 +:102280000216E448000000070216E44C00000000BB +:102290000216E00C010101200616E45000000004C3 +:1022A0000216E010010101010216E46000000000C6 +:1022B0000216E464000000040216E4680000000452 +:1022C0000216E46C000000020216E014080120046B +:1022D0000216E470000000050216E4740000000518 +:1022E0000216E478000000050216E47C00000005F8 +:1022F0000216E018200810010216E4800000000811 +:102300000216E484000000060216E48800000007BC +:102310000216E48C000000010216E01C01010120FD +:102320000216E490000000010216E494000000018F +:102330000216E498000000010216E49C000000016F +:102340000216E020010101010216E4A000000001D4 +:102350000216E4A4000000040216E4A80000000431 +:102360000216E4AC000000020216E024080120047A +:102370000216E4B0000000050216E4B400000005F7 +:102380000216E4B8000000050216E4BC00000005D7 +:102390000216E028200810010216E4C00000000820 +:1023A0000216E4C4000000060216E4C8000000079C +:1023B0000216E4CC000000010216E02C010101200D +:1023C0000216E4D0000000010216E4D4000000016F +:1023D0000216E4D8000000010216E4DC000000014F +:1023E0000216E030010101010216E4E000000001E4 +:1023F0000216E4E4000000040216E4E80000000411 +:102400000216E4EC000000020216E0340801200489 +:102410000216E4F0000000050216E4F400000005D6 +:102420000216E4F8000000050216E4FC00000005B6 +:102430000216E038200810010216E500000000082E +:102440000216E504000000060216E5080000000779 +:102450000216E03C0101012002168240003F003FCD +:1024600002168244000000000216E524003F003FEF +:102470000216E52800000000021682480000000055 +:102480000216824C003F003F0216E52C00000000BF +:102490000216E530003F003F0216825001000100A5 +:1024A00002168254010001000216E5340100010009 +:1024B0000216E538010001000616825800000002ED +:1024C0000216E53C000000000216E5400000000096 +:1024D0000216826000C000C00216826400C000C004 +:1024E0000216E54400C000C00216E54800C000C066 +:1024F000021682681E001E000216826C1E001E005C +:102500000216E54C1E001E000216E5501E001E00BD +:1025100002168270400040000216827440004000A3 +:102520000216E554400040000216E5584000400005 +:1025300002168278800080000216827C8000800073 +:102540000216E55C800080000216E56080008000D5 +:1025500002168280200020000216828420002000C3 +:102560000216E564200020000216E5682000200025 +:1025700006168288000000020216E56C00000000CA +:102580000216E570000000000216829000000000B4 +:1025900002168294000000000216E574000000009C +:1025A0000216E57800000000021682980000000084 +:1025B0000216829C000000000216E57C000000006C +:1025C0000216E58000000000021682A00000000054 +:1025D000021682A400000001061682A80000000A6C +:1025E000021681F400000C08021681F80000004079 +:1025F000021681FC0000010002168200000000208B +:1026000002168204000000170216820800000080F3 +:102610000216820C00000200021682100000000068 +:102620000216821801FF01FF0216821401FF01FF4A +:102630000216E51001FF01FF0216E50C01FF01FF84 +:102640000216823C00000013021680900000013F39 +:102650000216806000000140021680640000014004 +:10266000061680680000000202168070000000C09C +:1026700006168074000000070216809C00000048C7 +:10268000021680A000000048061680A40000000288 +:10269000021680AC00000048061680B0000000075B +:1026A000021682380000800002168234000025E401 +:1026B0000216809400007FFF0216822000070007A8 +:1026C0000216821C000700070216E5180007000723 +:1026D0000216E51400070007021682280000000019 +:1026E00002168224FFFFFFFF0216E5200000000013 +:1026F0000216E51CFFFFFFFF0216E6BC000000000B +:102700000216E6C0000000020216E6C40000000146 +:102710000216E6C8000000030216E6CC0000000422 +:102720000216E6D0000000060216E6D400000005FE +:102730000216E6D800000007021680EC000000FF39 +:1027400002140000000000010214000C000000014F +:1027500002140040000000010214004400007FFF4A +:102760000214000C00000000021400000000000031 +:102770000214006C000000000214000400000001BC +:1027800002140030000000010214000400000000E8 +:102790000214005C000000000214000800000001A8 +:1027A00002140034000000010214000800000000C0 +:1027B0000214006000000000020200580000003215 +:1027C000020200A003150020020200A4031500204D +:1027D000020200A801000030020200AC0810000054 +:1027E000020200B000000033020200B4000000301A +:1027F000020200B800000031020200BC0000000329 +:10280000020200C000000006020200C40000000333 +:10281000020200C800000003020200CC0000000217 +:10282000020200D000000000020200D400000002FA +:10283000020200DC00000000020200E000000006CE +:10284000020200E400000004020200E800000002AE +:10285000020200EC00000002020200F00000000191 +:10286000020200FC0000000602020120000000003D +:102870000202013400000002020201B00000000167 +:102880000202020C0000000102020214000000011A +:10289000020202180000000202020404000000010B +:1028A0000202040C0000004002020410000000407C +:1028B0000202041C000000040202042000000020A8 +:1028C000020204240000000202020428000000208A +:1028D000060205000000001204020480001F032904 +:1028E000020200600000000F020200640000000706 +:1028F000020200680000000B0202006C0000000EE3 +:10290000020200700000000E0602007400000003C6 +:10291000020200F4000000040202000400000001B2 +:1029200002020008000000010202000C0000000189 +:102930000202001000000001020200140000000169 +:1029400002020018000000010202001C0000000149 +:102950000202002000000001020200240000000129 +:1029600002020028000000010202002C0000000109 +:1029700002020030000000010202003400000001E9 +:1029800002020038000000010202003C00000001C9 +:1029900002020040000000010202004400000001A9 +:1029A00002020048000000010202004C0000000189 +:1029B000020200500000000102020108000000C8ED +:1029C0000202011800000002020201C4000000001F +:1029D000020201CC00000000020201D4000000024B +:1029E000020201DC00000002020201E4000000FF1C +:1029F000020201EC000000FF0202010000000000E2 +:102A00000202010C000000C80202011C00000002CA +:102A1000020201C800000000020201D00000000014 +:102A2000020201D800000002020201E000000002E0 +:102A3000020201E8000000FF020201F0000000FFB6 +:102A4000020201040000000002020108000000C8A8 +:102A50000202011800000002020201C4000000008E +:102A6000020201CC00000000020201D400000002BA +:102A7000020201DC00000002020201E4000000FF8B +:102A8000020201EC000000FF020201000000000051 +:102A90000202010C000000C80202011C000000023A +:102AA000020201C800000000020201D00000000084 +:102AB000020201D800000002020201E00000000250 +:102AC000020201E8000000FF020201F0000000FF26 +:102AD000020201040000000002020108000000C818 +:102AE0000202011800000002020201C400000000FE +:102AF000020201CC00000000020201D4000000022A +:102B0000020201DC00000002020201E4000000FFFA +:102B1000020201EC000000FF0202010000000000C0 +:102B20000202010C000000C80202011C00000002A9 +:102B3000020201C800000000020201D000000000F3 +:102B4000020201D800000002020201E000000002BF +:102B5000020201E8000000FF020201F0000000FF95 +:102B6000020201040000000002020108000000C887 +:102B70000202011800000002020201C4000000006D +:102B8000020201CC00000000020201D40000000299 +:102B9000020201DC00000002020201E4000000FF6A +:102BA000020201EC000000FF020201000000000030 +:102BB0000202010C000000C80202011C0000000219 +:102BC000020201C800000000020201D00000000063 +:102BD000020201D800000002020201E0000000022F +:102BE000020201E8000000FF020201F0000000FF05 +:102BF00002020104000000000728040000BD0000DC +:102C0000082807A8000B0348072C00003406000022 +:102C1000072C800037960D02072D00003BC31AE8F1 +:102C2000072D8000382629D9072E0000124537E3EA +:102C3000082E22203BBC034A0128000000000000AF +:102C40000128000400000000012800080000000026 +:102C50000128000C00000000012800100000000006 +:102C600001280014000000000228002000000001DC +:102C700002280024000000020228002800000003AF +:102C80000228002C00000000022800300000000490 +:102C90000228003400000001022800380000000073 +:102CA0000228003C0000000102280040000000044F +:102CB0000228004400000000022800480000000133 +:102CC0000228004C00000003022800500000000011 +:102CD00002280054000000010228005800000004EF +:102CE0000228005C000000000228006000000001D3 +:102CF00002280064000000030228006800000000B1 +:102D00000228006C0000000102280070000000048E +:102D1000022800740000000002280078000000046F +:102D20000228007C0000000306280080000000024A +:102D3000022800A400003FFF022800A8000003FFB3 +:102D400002280224000000000228023400000000D3 +:102D50000228024C00000000022802E40000FFFFED +:102D60000628200000000800022B8BC00000000194 +:102D7000022B800000000000022B804000000018A1 +:102D8000022B80800000000C022B80C00000006637 +:102D90000C2B83000007A1200A2B830000000138C0 +:102DA0000B2B830000001388022B83C0000001F46A +:102DB0000C2B8340000001F40A2B8340000000002C +:102DC0000B2B8340000000050A2B83800004C4B451 +:102DD0000C2B83801DCD65000A2B148000000000A1 +:102DE0000B2B8380004C4B40022B14800000000111 +:102DF000062A29C800000004042A29D80002034C2E +:102E0000062A208000000048062A9020000000C802 +:102E1000062A900000000002062A21A80000008671 +:102E2000062A200000000020022A23C8000000001B +:102E3000042A23D00002034E042A249800040350DD +:102E4000022A2C2000000000022A2C1000000000A2 +:102E5000042A2C0800020354022A3010000000014A +:102E6000062A404000000010042A400000100356CB +:102E7000062A6AC000000002062A6B000000000457 +:102E8000042A840800020366022B080000000000E8 +:102E9000042B0C0000100368022B08000100000046 +:102EA000042B0C4000080378022B080002000000ED +:102EB000042B0C6000080380062AC000000000FC00 +:102EC000062A24A800000014062A25480000002431 +:102ED000062A266800000024062A2788000000240D +:102EE000062A28A800000024062AA00000000028C6 +:102EF000062AA1400000000C042A29E000020388F1 +:102F0000022A300000000001062A502000000002C2 +:102F1000062A503000000002062A5000000000027D +:102F2000062A501000000002022A52080000000188 +:102F3000042A6AC80002038A062A6B1000000042B5 +:102F4000062A6D2000000004062AC3F0000000FCE1 +:102F5000062A24F800000014062A25D800000024C0 +:102F6000062A26F800000024062A2818000000245B +:102F7000062A293800000024062AA0A00000002804 +:102F8000062AA1700000000C042A29E80002038C24 +:102F9000022A300400000001062A50280000000226 +:102FA000062A503800000002062A500800000002DD +:102FB000062A501800000002022A520C00000001EC +:102FC000042A6AD00002038E062A6C180000004210 +:102FD000062A6D3000000004022AC7E0000000004D +:102FE000042A29F000100390062A50480000000E21 +:102FF000022AC7E400000000042A2A30001003A0BF +:10300000062A50800000000E022AC7E800000000D7 +:10301000042A2A70001003B0062A50B80000000EDF +:10302000022AC7EC00000000042A2AB0001003C0E6 +:10303000062A50F00000000E022AC7F0000000002F +:10304000042A2AF0001003D0062A51280000000E9E +:10305000022AC7F400000000042A2B30001003E00D +:10306000062A51600000000E022AC7F80000000086 +:10307000042A2B70001003F0062A51980000000E5D +:10308000022AC7FC00000000042A2BB00010040034 +:10309000062A51D00000000E0210100800000001A6 +:1030A0000210105000000001021010000003D000B8 +:1030B000021010040000003D091018000200041066 +:1030C0000910110000280610061011A000000018B9 +:1030D00006102400000000E00210201C0000000088 +:1030E0000210202000000001021020C00000000299 +:1030F000021020040000000102102008000000015E +:1031000009103C0000050638091038000005063D8E +:10311000091038200005064206104C00000001008E +:1031200002104028000000100210404400003FFF41 +:103130000210405800280000021040840084924A87 +:1031400002104058000000000210800000001080B3 +:10315000021080AC00000000021080380000001057 +:103160000210810000000000061081200000000213 +:1031700002108008000002B502108010000000005C +:10318000061082000000004A021081080001FFFFC3 +:1031900006108140000000020210800000001A802A +:1031A0000610900000000024061091200000004A44 +:1031B000061093700000004A061095C00000004AF7 +:1031C0000210800400001080021080B00000000196 +:1031D0000210803C0000001002108104000000007A +:1031E00006108128000000020210800C000002B5C9 +:1031F0000210801400000000061084000000004A45 +:103200000210810C0001FFFF06108148000000023F +:103210000210800400001A80061090900000002424 +:10322000061092480000004A061094980000004AD8 +:10323000061096E80000004A02108000000010808E +:10324000021080AC00000002021080380000001064 +:103250000210810000000000061081200000000222 +:1032600002108008000002B502108010000000006B +:10327000061082000000004A021081080001FFFFD2 +:1032800006108140000000020210800000001A8039 +:103290000610900000000024061091200000004A53 +:1032A000061093700000004A061095C00000004A06 +:1032B0000210800400001080021080B000000003A3 +:1032C0000210803C00000010021081040000000089 +:1032D00006108128000000020210800C000002B5D8 +:1032E0000210801400000000061084000000004A54 +:1032F0000210810C0001FFFF06108148000000024F +:103300000210800400001A80061090900000002433 +:10331000061092480000004A061094980000004AE7 +:10332000061096E80000004A02108000000010809D +:10333000021080AC00000004021080380000001071 +:103340000210810000000000061081200000000231 +:1033500002108008000002B502108010000000007A +:10336000061082000000004A021081080001FFFFE1 +:1033700006108140000000020210800000001A8048 +:103380000610900000000024061091200000004A62 +:10339000061093700000004A061095C00000004A15 +:1033A0000210800400001080021080B000000005B0 +:1033B0000210803C00000010021081040000000098 +:1033C00006108128000000020210800C000002B5E7 +:1033D0000210801400000000061084000000004A63 +:1033E0000210810C0001FFFF06108148000000025E +:1033F0000210800400001A80061090900000002443 +:10340000061092480000004A061094980000004AF6 +:10341000061096E80000004A0210800000001080AC +:10342000021080AC0000000602108038000000107E +:103430000210810000000000061081200000000240 +:1034400002108008000002B5021080100000000089 +:10345000061082000000004A021081080001FFFFF0 +:1034600006108140000000020210800000001A8057 +:103470000610900000000024061091200000004A71 +:10348000061093700000004A061095C00000004A24 +:103490000210800400001080021080B000000007BD +:1034A0000210803C000000100210810400000000A7 +:1034B00006108128000000020210800C000002B5F6 +:1034C0000210801400000000061084000000004A72 +:1034D0000210810C0001FFFF06108148000000026D +:1034E0000210800400001A80061090900000002452 +:1034F000061092480000004A061094980000004A06 +:10350000061096E80000004A021205B00000000113 +:103510000212049000E383400212051400003C10E4 +:103520000212066C0000000102120670000000008A +:1035300002120494FFFFFFFF02120498FFFFFFFF37 +:103540000212049CFFFFFFFF021204A0FFFFFFFF17 +:10355000021204A4FFFFFFFF021204A8FFFFFFFFF7 +:10356000021204ACFFFFFFFF021204B0FFFFFFFFD7 +:10357000021204BCFFFFFFFF021204C0FFFFFFFFA7 +:10358000021204C4FFFFFFFF021204C8FFFFFFFF87 +:10359000021204CCFFFFFFFF021204D0FFFFFFFF67 +:1035A000021204D8FFFFFFFF021204DCFFFFFFFF3F +:1035B000021204E0FFFFFFFF021204E4FFFFFFFF1F +:1035C000021204E8FFFFFFFF021204ECFFFFFFFFFF +:1035D000021204F0FFFFFFFF021204F4FFFFFFFFDF +:1035E000021204F8FFFFFFFF021204FCFFFFFFFFBF +:1035F00002120500FFFFFFFF02120504FFFFFFFF9D +:1036000002120508FFFFFFFF0212050CFFFFFFFF7C +:1036100002120510FFFFFFFF021204D4FF802000FA +:10362000021204B4F0005000021204B8F00080004E +:1036300002120390000000080212039C0000000820 +:10364000021203A000000008021203A400000002FE +:10365000021203BC00000004021203C000000005B7 +:10366000021203C400000004021203D00000000094 +:103670000212036C00000001021203680000003F08 +:10368000021201BC00000040021201C00000180834 +:10369000021201C400000803021201C8000008035E +:1036A000021201CC00000040021201D00000000311 +:1036B000021201D400000803021201D8000008031E +:1036C000021201DC00000803021201E00001000305 +:1036D000021201E400000803021201E800000803DE +:1036E000021201EC00000003021201F000000003CE +:1036F000021201F400000003021201F800000003AE +:10370000021201FC0000000302120200000000038C +:10371000021202040000000302120208000000036B +:103720000212020C0000000302120210000000034B +:10373000021202140000000302120218000000032B +:103740000212021C0000000302120220000000030B +:1037500002120224000000030212022800002403C7 +:103760000212022C0000002F021202300000000999 +:103770000212023400000019021202380000018413 +:103780000212023C00000183021202400000030604 +:103790000212024400000019021202480000000652 +:1037A0000212024C0000030602120250000003063F +:1037B00002120254000003060212025800000C8696 +:1037C0000212025C000003060212026000000306FF +:1037D00002120264000000060212026800000006E5 +:1037E0000212026C000000060212027000000006C5 +:1037F00002120274000000060212027800000006A5 +:103800000212027C00000006021202800000000684 +:103810000212028400000006021202880000000664 +:103820000212028C00000006021202900000000644 +:103830000212029400000006021202980000000624 +:103840000212029C00000006021202A00000030601 +:10385000021202A400000013021202A800000006D7 +:10386000021202B000001004021202B400001004A0 +:103870000212032400106440021203280010644066 +:10388000021205B400000001021201B000000001A4 +:103890000600A000000000160200A0EC5554000035 +:1038A0000200A0F0555555550200A0F400005555F2 +:1038B0000200A0F8F00000000200A0FC5554000037 +:1038C0000200A100555555550200A10400005555B0 +:1038D0000200A108F00000000200A18C5554000075 +:1038E0000200A190555555550200A1940000555570 +:1038F0000200A198F00000000200A19C000000005E +:103900000200A1A0000100000200A1A400005014C8 +:103910000200A1A8000000000200A45C00000C004E +:103920000200A61C000000030200A06CFF5C000067 +:103930000200A070FFF55FFF0200A0740000FFFF0F +:103940000200A078F00003E00200A07C000000006C +:103950000200A0800000A0000600A0840000000576 +:103960000200A0980FE000000600A09C00000007E5 +:103970000200A0B8000004000600A0BC0000000384 +:103980000200A0C8000010000600A0CC0000000348 +:103990000200A0D8000040000600A0DC00000003E8 +:1039A0000200A0E8000100000600A22C00000004B4 +:1039B0000200A10CFF5C00000200A110FFF55FFFF8 +:1039C0000200A1140000FFFF0200A118F00003E0B4 +:1039D0000200A11C000000000200A1200000A000C5 +:1039E0000600A124000000050200A1380FE000003D +:1039F0000600A13C000000070200A15800000800DA +:103A00000600A15C000000030200A1680000200085 +:103A10000600A16C000000030200A17800008000F5 +:103A20000600A17C000000030200A1880002000043 +:103A30000600A23C0000000400000000000000009E +:103A40000000003100000000000000000000000045 +:103A50000000000000000000000000000000000066 +:103A600000000000000000000000000000310032F3 +:103A70000000000000000000000000000000000046 +:103A80000000000000000000000000000000000036 +:103A9000000000000000000000320056000000009E +:103AA0000000000000000000000000000000000016 +:103AB0000000000000000000000000000000000006 +:103AC000000000000056008C000000000000000014 +:103AD000008C009000900094009400980098009C46 +:103AE000009C00A000A000A400A400A800A800ACB6 +:103AF00000AC00B100B100B300B300B5000000009D +:103B000000000000000000000000000000000000B5 +:103B100000000000000000000000000000B50100EF +:103B2000010001060106010C010C01140114011C25 +:103B3000011C01240124012C012C01340134013C1D +:103B4000013C01440144014C000000000000000061 +:103B50000000000000000000000000000000000065 +:103B60000000000000000000000000000000000055 +:103B70000000000000000000000000000000000045 +:103B80000000000000000000000000000000000035 +:103B90000000000000000000000000000000000025 +:103BA0000000000000000000000000000000000015 +:103BB0000000000000000000000000000000000005 +:103BC00000000000000000000000000000000000F5 +:103BD00000000000000000000000000000000000E5 +:103BE00000000000000000000000000000000000D5 +:103BF0000000000000000000014C01510000000026 +:103C000000000000015101520152015301530154BF +:103C100001540155015501560156015701570158EC +:103C200001580159000000000000000000000000E1 +:103C30000000000000000000000000000000000084 +:103C40000000000000000000000000000000000074 +:103C50000159015E015E016A016A017600000000FF +:103C60000000000000000000000000000000000054 +:103C70000000000000000000000000000000000044 +:103C80000000000000000000000000000000000034 +:103C90000000000000000000000000000000000024 +:103CA0000000000000000000017601770000000025 +:103CB0000000000000000000000000000000000004 +:103CC00000000000000000000000000000000000F4 +:103CD000000000000177019A0000000000000000D1 +:103CE00000000000000000000000000000000000D4 +:103CF00000000000000000000000000000000000C4 +:103D0000019A01C200000000000000000000000055 +:103D100000000000000000000000000000000000A3 +:103D200000000000000000000000000001C201F3DC +:103D3000000000000000000001F301FA01FA020196 +:103D4000020102080208020F020F02160216021DEB +:103D5000021D02240224022B022B02630000000039 +:103D600000000000026302670267026B026B026FD1 +:103D7000026F0273027302770277027B027B027F7B +:103D8000027F0283028302D102D102EB02EB030520 +:103D9000030503080308030B030B030E030E0311B3 +:103DA00003110314031403170317031A031A031D43 +:103DB000031D035E035E0362036203660366036919 +:103DC0000369036C036C036F036F03720372037563 +:103DD000037503780378037B037B037E037E037FF5 +:103DE00000000000000000000000000000000000D3 +:103DF00000000000000000000000000000000000C3 +:103E00000000000000000000037F0391000000009C +:103E100000000000000000000000000000000000A2 +:103E20000000000000000000000000000000000092 +:103E300000000000039103A603A603A903A903AC95 +:103E40000000000000000000000000000000000072 +:103E50000000000000000000000000000000000062 +:103E600003AC03D9000000000000000000000000C7 +:103E70000000000000000000000000000000000042 +:103E800000000000000000000000000003D904DC76 +:103E90000000000000000000000000000000000022 +:103EA0000000000000000000000000000000000012 +:103EB000000000000000000004DC04E304E304E769 +:103EC00004E704EB00000000000000000000000018 +:103ED00000000000000000000000000000000000E2 +:103EE0000000000004EB052B0000000000000000B3 +:103EF000052B05340534053D053D05460546054FB2 +:103F0000054F0558055805610561056A056A057381 +:103F1000057305CB05CB05DD05DD05EF05EF05F2E6 +:103F200005F205F505F505F805F805FB05FB05FEA9 +:103F300005FE060106010604060406070607060E2E +:103F40000000000000000000000000000000000071 +:103F50000000000000000000000000000000000061 +:103F60000000000000000000060E06140000000023 +:103F70000000000000000000000000000000000041 +:103F80000000000000000000000000000000000031 +:103F900000000000061406170000000000000000EA +:103FA0000000000000000000000000000000000011 +:103FB0000000000000000000000000000000000001 +:103FC0000617061D000000000000000000000000B1 +:103FD00000000000000000000000000000000000E1 +:103FE00000000000000000000000000000000000D1 +:103FF0000000000000000000061D062C062C063BF9 +:10400000063B064A064A06590659066806680677B8 +:1040100006770686068606950695070600000000C8 +:104020000000000000000000000000000000000090 +:104030000000000000000000000000000000000080 +:1040400000000000070607190719072A072A073B7F +:104050000000000000000000000000000000000060 +:104060000000000000000000000000000000000050 +:10407000000000000000000000010000000204C079 +:104080000003098000040E4000051300000617C05D +:1040900000071C800008214000092600000A2AC0F1 +:1040A000000B2F80000C3440000D3900000E3DC085 +:1040B000000F42800010474000114C00001250C019 +:1040C0000013558000145A4000155F00001663C0AD +:1040D0000017688000186D4000197200001A76C041 +:1040E000001B7B80001C8040001D8500001E89C0D5 +:1040F000001F8E8000209340000020000000400040 +:1041000000006000000080000000A0000000C0006F +:104110000000E0000001000000012000000140005C +:1041200000016000000180000001A0000001C0004B +:104130000001E00000020000000220000002400038 +:1041400000026000000280000002A0000002C00027 +:104150000002E00000030000000320000003400014 +:1041600000036000000380000003A0000003C00003 +:104170000003E000000400000004200000044000F0 +:1041800000046000000480000004A0000004C000DF +:104190000004E000000500000005200000054000CC +:1041A00000056000000580000005A0000005C000BB +:1041B0000005E000000600000006200000064000A8 +:1041C00000066000000680000006A0000006C00097 +:1041D0000006E00000070000000720000007400084 +:1041E00000076000000780000007A0000007C00073 +:1041F0000007E00000080000000820000008400060 +:1042000000086000000880000008A0000008C0004E +:104210000008E0000009000000092000000940003B +:1042200000096000000980000009A0000009C0002A +:104230000009E000000A0000000A2000000A400017 +:10424000000A6000000A8000000AA000000AC00006 +:10425000000AE000000B0000000B2000000B4000F3 +:10426000000B6000000B8000000BA000000BC000E2 +:10427000000BE000000C0000000C2000000C4000CF +:10428000000C6000000C8000000CA000000CC000BE +:10429000000CE000000D0000000D2000000D4000AB +:1042A000000D6000000D8000000DA000000DC0009A +:1042B000000DE000000E0000000E2000000E400087 +:1042C000000E6000000E8000000EA000000EC00076 +:1042D000000EE000000F0000000F2000000F400063 +:1042E000000F6000000F8000000FA000000FC00052 +:1042F000000FE0000010000000102000001040003F +:1043000000106000001080000010A0000010C0002D +:104310000010E0000011000000112000001140001A +:1043200000116000001180000011A0000011C00009 +:104330000011E000001200000012200000124000F6 +:1043400000126000001280000012A0000012C000E5 +:104350000012E000001300000013200000134000D2 +:1043600000136000001380000013A0000013C000C1 +:104370000013E000001400000014200000144000AE +:1043800000146000001480000014A0000014C0009D +:104390000014E0000015000000152000001540008A +:1043A00000156000001580000015A0000015C00079 +:1043B0000015E00000160000001620000016400066 +:1043C00000166000001680000016A0000016C00055 +:1043D0000016E00000170000001720000017400042 +:1043E00000176000001780000017A0000017C00031 +:1043F0000017E0000018000000182000001840001E +:1044000000186000001880000018A0000018C0000C +:104410000018E000001900000019200000194000F9 +:1044200000196000001980000019A0000019C000E8 +:104430000019E000001A0000001A2000001A4000D5 +:10444000001A6000001A8000001AA000001AC000C4 +:10445000001AE000001B0000001B2000001B4000B1 +:10446000001B6000001B8000001BA000001BC000A0 +:10447000001BE000001C0000001C2000001C40008D +:10448000001C6000001C8000001CA000001CC0007C +:10449000001CE000001D0000001D2000001D400069 +:1044A000001D6000001D8000001DA000001DC00058 +:1044B000001DE000001E0000001E2000001E400045 +:1044C000001E6000001E8000001EA000001EC00034 +:1044D000001EE000001F0000001F2000001F400021 +:1044E000001F6000001F8000001FA000001FC00010 +:1044F000001FE000002000000020200000204000FD +:1045000000206000002080000020A0000020C000EB +:104510000020E000002100000021200000214000D8 +:1045200000216000002180000021A0000021C000C7 +:104530000021E000002200000022200000224000B4 +:1045400000226000002280000022A0000022C000A3 +:104550000022E00000230000002320000023400090 +:1045600000236000002380000023A0000023C0007F +:104570000023E0000024000000242000002440006C +:1045800000246000002480000024A0000024C0005B +:104590000024E00000250000002520000025400048 +:1045A00000256000002580000025A0000025C00037 +:1045B0000025E00000260000002620000026400024 +:1045C00000266000002680000026A0000026C00013 +:1045D0000026E00000270000002720000027400000 +:1045E00000276000002780000027A0000027C000EF +:1045F0000027E000002800000028200000284000DC +:1046000000286000002880000028A0000028C000CA +:104610000028E000002900000029200000294000B7 +:1046200000296000002980000029A0000029C000A6 +:104630000029E000002A0000002A2000002A400093 +:10464000002A6000002A8000002AA000002AC00082 +:10465000002AE000002B0000002B2000002B40006F +:10466000002B6000002B8000002BA000002BC0005E +:10467000002BE000002C0000002C2000002C40004B +:10468000002C6000002C8000002CA000002CC0003A +:10469000002CE000002D0000002D2000002D400027 +:1046A000002D6000002D8000002DA000002DC00016 +:1046B000002DE000002E0000002E2000002E400003 +:1046C000002E6000002E8000002EA000002EC000F2 +:1046D000002EE000002F0000002F2000002F4000DF +:1046E000002F6000002F8000002FA000002FC000CE +:1046F000002FE000003000000030200000304000BB +:1047000000306000003080000030A0000030C000A9 +:104710000030E00000310000003120000031400096 +:1047200000316000003180000031A0000031C00085 +:104730000031E00000320000003220000032400072 +:1047400000326000003280000032A0000032C00061 +:104750000032E0000033000000332000003340004E +:1047600000336000003380000033A0000033C0003D +:104770000033E0000034000000342000003440002A +:1047800000346000003480000034A0000034C00019 +:104790000034E00000350000003520000035400006 +:1047A00000356000003580000035A0000035C000F5 +:1047B0000035E000003600000036200000364000E2 +:1047C00000366000003680000036A0000036C000D1 +:1047D0000036E000003700000037200000374000BE +:1047E00000376000003780000037A0000037C000AD +:1047F0000037E0000038000000382000003840009A +:1048000000386000003880000038A0000038C00088 +:104810000038E00000390000003920000039400075 +:1048200000396000003980000039A0000039C00064 +:104830000039E000003A0000003A2000003A400051 +:10484000003A6000003A8000003AA000003AC00040 +:10485000003AE000003B0000003B2000003B40002D +:10486000003B6000003B8000003BA000003BC0001C +:10487000003BE000003C0000003C2000003C400009 +:10488000003C6000003C8000003CA000003CC000F8 +:10489000003CE000003D0000003D2000003D4000E5 +:1048A000003D6000003D8000003DA000003DC000D4 +:1048B000003DE000003E0000003E2000003E4000C1 +:1048C000003E6000003E8000003EA000003EC000B0 +:1048D000003EE000003F0000003F2000003F40009D +:1048E000003F6000003F8000003FA000003FC0008C +:1048F000003FE000003FE00100000000000001FF79 +:104900000000020000007FF800007FF800000704AC +:104910000000350000000001FFFFFFFFFFFFFFFF69 +:10492000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 +:10493000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 +:10494000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 +:10495000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 +:10496000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 +:10497000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 +:10498000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 +:10499000FFFFFFFFFFFFFFFFFFFFFFFF0000000023 +:1049A000FFFFFFFF00000000FFFFFFFFFFFFFFFF13 +:1049B00000000000FFFFFFFF00000000FFFFFFFFFF +:1049C000FFFFFFFF00000000FFFFFFFF00000000EF +:1049D000FFFFFFFF0000000300BEBC20FFFFFFFF42 +:1049E00000000000FFFFFFFF00000000FFFFFFFFCF +:1049F0000000000300BEBC20FFFFFFFF000000001E +:104A0000FFFFFFFF00000000FFFFFFFF00000003AB +:104A100000BEBC20FFFFFFFF00000000FFFFFFFF04 +:104A200000000000FFFFFFFF0000000300BEBC20ED +:104A3000FFFFFFFF00000000FFFFFFFF000000007E +:104A4000FFFFFFFF0000000300BEBC20FFFFFFFFD1 +:104A500000000000FFFFFFFF00000000FFFFFFFF5E +:104A60000000000300BEBC2000002000000040C089 +:104A700000006180000082400000A3000000C3C06D +:104A80000000E4800001054000012600000146C04E +:104A900000016780000188400001A9000001C9C031 +:104AA0000001EA8000020B4000022C0000024CC012 +:104AB00000026D8000028E400002AF000002CFC0F5 +:104AC0000002F0800003114000033200000352C0D6 +:104AD00000037380000394400003B5000003D5C0B9 +:104AE0000003F6800004174000043800000458C09A +:104AF0000004798000049A400000800000010380D7 +:104B00000001870000020A8000028E00000311806D +:104B1000000395000004188000049C0000051F801D +:104B20000005A300000626800006AA0000072D80CD +:104B30000007B100000834800008B80000093B807D +:104B40000009BF00000A4280000AC600000B49802D +:104B5000000BCD00000C5080000CD400000D5780DD +:104B6000000DDB0000007FF800007FF800000487E4 +:104B700000001500000019000000002800100000CF +:104B80000000000000000000FFFFFFFF40000000E9 +:104B90004000000040000000400000004000000015 +:104BA0004000000040000000400000004000000005 +:104BB00040000000400000004000000040000000F5 +:104BC00040000000400000004000000040000000E5 +:104BD00040000000400000004000000040000000D5 +:104BE00040000000400000004000000040000000C5 +:104BF00040000000400000004000000040000000B5 +:104C000040000000400000004000000000007FF86D +:104C100000007FF8000003E000001500FFFFFFFF29 +:104C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 +:104C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 +:104C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 +:104C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 +:104C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 +:104C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 +:104C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 +:104C9000FFFFFFFFFFFFFFFFFFFFFFFF40000000E0 +:104CA0004000000040000000400000004000000004 +:104CB00040000000400000004000000040000000F4 +:104CC00040000000400000004000000040000000E4 +:104CD00040000000400000004000000040000000D4 +:104CE00040000000400000004000000040000000C4 +:104CF00040000000400000004000000040000000B4 +:104D000040000000400000004000000040000000A3 +:104D100040000000400000004000000000001000C3 +:104D2000000020800000310000004180000052009F +:104D30000000628000007300000083800000940087 +:104D40000000A4800000B5000000C5800000D6006F +:104D50000000E6800000F700000107800001180055 +:104D600000012880000139000001498000015A003B +:104D700000016A8000017B0000018B8000019C0023 +:104D80000001AC800001BD000001CD800001DE000B +:104D90000001EE800001FF0000007FF800007FF8B6 +:104DA0000000023E0000350010000000000028ADA9 +:104DB000000000000001000100350804CCCCCCC587 +:104DC000FFFFFFFFFFFFFFFF7058103C00000000D7 +:104DD000CCCC0201CCCCCCCCCCCC0201CCCCCCCC3D +:104DE000CCCC0201CCCCCCCCCCCC0201CCCCCCCC2D +:104DF000CCCC0201CCCCCCCCCCCC0201CCCCCCCC1D +:104E0000CCCC0201CCCCCCCCCCCC0201CCCCCCCC0C +:104E100000000000FFFFFFFF400000004000000016 +:104E20004000000040000000400000004000000082 +:104E30004000000040000000400000004000000072 +:104E40004000000040000000400000004000000062 +:104E50004000000040000000400000004000000052 +:104E60004000000040000000400000004000000042 +:104E70004000000040000000400000004000000032 +:104E80004000000040000000400000004000000022 +:104E90004000000040000000000E0232011600D663 +:104EA000001000000000000000720236012300F331 +:104EB00000100000000000000000FFFF00000000E4 +:104EC0000000FFFF000000000000FFFF00000000E6 +:104ED0000000FFFF000000000000FFFF00000000D6 +:104EE0000000FFFF000000000000FFFF00000000C6 +:104EF0000000FFFF000000000000FFFF00000000B6 +:104F00000000FFFF000000000000FFFF00000000A5 +:104F10000000FFFF000000000000FFFF0000000095 +:104F20000000FFFF000000000000FFFF0000000085 +:104F30000000FFFF000000000000FFFF0000000075 +:104F40000000FFFF000000000000FFFF0000000065 +:104F50000000FFFF000000000000FFFF0000000055 +:104F60000000FFFF000000000000FFFF0000000045 +:104F70000000FFFF000000000000FFFF0000000035 +:104F80000000FFFF000000000000FFFF0000000025 +:104F90000000FFFF000000000000FFFF0000000015 +:104FA0000000FFFF000000000000FFFF0000000005 +:104FB0000000FFFF000000000000FFFF00000000F5 +:104FC0000000FFFF000000000000FFFF00000000E5 +:104FD0000000FFFF000000000000FFFF00000000D5 +:104FE0000000FFFF000000000000FFFF00000000C5 +:104FF0000000FFFF000000000000FFFF00000000B5 +:105000000000FFFF000000000000FFFF00000000A4 +:105010000000FFFF000000000000FFFF0000000094 +:105020000000FFFF000000000000FFFF0000000084 +:105030000000FFFF000000000000FFFF0000000074 +:105040000000FFFF000000000000FFFF0000000064 +:105050000000FFFF000000000000FFFF0000000054 +:105060000000FFFF000000000000FFFF0000000044 +:105070000000FFFF000000000000FFFF0000000034 +:105080000000FFFF000000000000FFFF0000000024 +:105090000000FFFF000000000000FFFF0000000014 +:1050A0000000FFFF000000000000FFFF0000000004 +:1050B0000000FFFF00000000FFFFFFF3320FFFFFC3 +:1050C0000C30C30CC30C30C3CF3CF300F3CF3CF324 +:1050D0000000CF3CCDCDCDCDFFFFFFF130EFFFFF86 +:1050E0000C30C30CC30C30C3CF3CF300F3CF3CF304 +:1050F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFF0 +:105100000C30C30CC30C30C3CF3CF300F3CF3CF3E3 +:105110000002CF3CCDCDCDCDFFFFF4061CBFFFFF7D +:105120000C30C305C30C30C3CF300014F3CF3CF3B5 +:105130000004CF3CCDCDCDCDFFFFFFF2304FFFFFC0 +:105140000C30C30CC30C30C3CF3CF300F3CF3CF3A3 +:105150000008CF3CCDCDCDCDFFFFFFFA302FFFFFB4 +:105160000C30C30CC30C30C3CF3CF300F3CF3CF383 +:105170000010CF3CCDCDCDCDFFFFFFF731EFFFFFCE +:105180000C30C30CC30C30C3CF3CF300F3CF3CF363 +:105190000020CF3CCDCDCDCDFFFFFFF5302FFFFF61 +:1051A0000C30C30CC30C30C3CF3CF300F3CF3CF343 +:1051B0000040CF3CCDCDCDCDFFFFFFF3310FFFFF42 +:1051C0000C30C30CC30C30C3CF3CF300F3CF3CF323 +:1051D0000000CF3CCDCDCDCDFFFFFFF1310FFFFF64 +:1051E0000C30C30CC30C30C3CF3CF300F3CF3CF303 +:1051F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFEF +:105200000C30C30CC30C30C3CF3CF300F3CF3CF3E2 +:105210000002CF3CCDCDCDCDFFFFF4061CBFFFFF7C +:105220000C30C305C30C30C3CF300014F3CF3CF3B4 +:105230000004CF3CCDCDCDCDFFFFFFF2304FFFFFBF +:105240000C30C30CC30C30C3CF3CF300F3CF3CF3A2 +:105250000008CF3CCDCDCDCDFFFFFFFA302FFFFFB3 +:105260000C30C30CC30C30C3CF3CF300F3CF3CF382 +:105270000010CF3CCDCDCDCDFFFFFFF730EFFFFFCE +:105280000C30C30CC30C30C3CF3CF300F3CF3CF362 +:105290000020CF3CCDCDCDCDFFFFFFF5304FFFFF40 +:1052A0000C30C30CC30C30C3CF3CF300F3CF3CF342 +:1052B0000040CF3CCDCDCDCDFFFFFFF331EFFFFF61 +:1052C0000C30C30CC30C30C3CF3CF300F3CF3CF322 +:1052D0000000CF3CCDCDCDCDFFFFFFF1310FFFFF63 +:1052E0000C30C30CC30C30C3CF3CF300F3CF3CF302 +:1052F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFEE +:105300000C30C30CC30C30C3CF3CF300F3CF3CF3E1 +:105310000002CF3CCDCDCDCDFFFFF4061CBFFFFF7B +:105320000C30C305C30C30C3CF300014F3CF3CF3B3 +:105330000004CF3CCDCDCDCDFFFFFFF2304FFFFFBE +:105340000C30C30CC30C30C3CF3CF300F3CF3CF3A1 +:105350000008CF3CCDCDCDCDFFFFFFFA302FFFFFB2 +:105360000C30C30CC30C30C3CF3CF300F3CF3CF381 +:105370000010CF3CCDCDCDCDFFFFFF97056FFFFFD8 +:105380000C30C30CC30C30C3CF3CC000F3CF3CF394 +:105390000020CF3CCDCDCDCDFFFFFFF5310FFFFF7E +:1053A0000C30C30CC30C30C3CF3CF300F3CF3CF341 +:1053B0000040CF3CCDCDCDCDFFFFFFF3320FFFFF3F +:1053C0000C30C30CC30C30C3CF3CF300F3CF3CF321 +:1053D0000000CF3CCDCDCDCDFFFFFFF1310FFFFF62 +:1053E0000C30C30CC30C30C3CF3CF300F3CF3CF301 +:1053F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFED +:105400000C30C30CC30C30C3CF3CF300F3CF3CF3E0 +:105410000002CF3CCDCDCDCDFFFFF4061CBFFFFF7A +:105420000C30C305C30C30C3CF300014F3CF3CF3B2 +:105430000004CF3CCDCDCDCDFFFFFFF2304FFFFFBD +:105440000C30C30CC30C30C3CF3CF300F3CF3CF3A0 +:105450000008CF3CCDCDCDCDFFFFFF8A042FFFFF4D +:105460000C30C30CC30C30C3CF3CC000F3CF3CF3B3 +:105470000010CF3CCDCDCDCDFFFFFF9705CFFFFF77 +:105480000C30C30CC30C30C3CF3CC000F3CF3CF393 +:105490000020CF3CCDCDCDCDFFFFFFF5310FFFFF7D +:1054A0000C30C30CC30C30C3CF3CF300F3CF3CF340 +:1054B0000040CF3CCDCDCDCDFFFFFFF3316FFFFFDF +:1054C0000C30C30CC30C30C3CF3CF300F3CF3CF320 +:1054D0000000CF3CCDCDCDCDFFFFFFF1302FFFFF42 +:1054E0000C30C30CC30C30C3CF3CF300F3CF3CF300 +:1054F0000001CF3CCDCDCDCDFFFFFFF6305FFFFFEC +:105500000C30C30CC30C30C3CF3CF300F3CF3CF3DF +:105510000002CF3CCDCDCDCDFFFFFFF630BFFFFF6A +:105520000C30C30CC30C30C3CF3CF314F3CF3CF3AB +:105530000004CF3CCDCDCDCDFFFFFFF2304FFFFFBC +:105540000C30C30CC30C30C3CF3CF300F3CF3CF39F +:105550000008CF3CCDCDCDCDFFFFFFFA302FFFFFB0 +:105560000C30C30CC30C30C3CF3CF300F3CF3CF37F +:105570000010CF3CCDCDCDCDFFFFFFF731CFFFFFEA +:105580000C30C30CC30C30C3CF3CF300F3CF3CF35F +:105590000020CF3CCDCDCDCDFFFFFFF0307FFFFF12 +:1055A0000C30C30CC30C30C3CF3CF300F3CF3CF33F +:1055B0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF73 +:1055C0000C30C30CC30C30C3CF3CF3CCF3CF3CF353 +:1055D0000000CF3CCDCDCDCDFFFFFFFF30CFFFFF93 +:1055E0000C30C30CC30C30C3CF3CF3CCF3CF3CF333 +:1055F0000001CF3CCDCDCDCDFFFFFFFF30CFFFFF72 +:105600000C30C30CC30C30C3CF3CF3CCF3CF3CF312 +:105610000002CF3CCDCDCDCDFFFFFFFF30CFFFFF50 +:105620000C30C30CC30C30C3CF3CF3CCF3CF3CF3F2 +:105630000004CF3CCDCDCDCDFFFFFFFF30CFFFFF2E +:105640000C30C30CC30C30C3CF3CF3CCF3CF3CF3D2 +:105650000008CF3CCDCDCDCDFFFFFFFF30CFFFFF0A +:105660000C30C30CC30C30C3CF3CF3CCF3CF3CF3B2 +:105670000010CF3CCDCDCDCDFFFFFFFF30CFFFFFE2 +:105680000C30C30CC30C30C3CF3CF3CCF3CF3CF392 +:105690000020CF3CCDCDCDCDFFFFFFFF30CFFFFFB2 +:1056A0000C30C30CC30C30C3CF3CF3CCF3CF3CF372 +:1056B0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF72 +:1056C0000C30C30CC30C30C3CF3CF3CCF3CF3CF352 +:1056D0000000CF3CCDCDCDCDFFFFFFFF30CFFFFF92 +:1056E0000C30C30CC30C30C3CF3CF3CCF3CF3CF332 +:1056F0000001CF3CCDCDCDCDFFFFFFFF30CFFFFF71 +:105700000C30C30CC30C30C3CF3CF3CCF3CF3CF311 +:105710000002CF3CCDCDCDCDFFFFFFFF30CFFFFF4F +:105720000C30C30CC30C30C3CF3CF3CCF3CF3CF3F1 +:105730000004CF3CCDCDCDCDFFFFFFFF30CFFFFF2D +:105740000C30C30CC30C30C3CF3CF3CCF3CF3CF3D1 +:105750000008CF3CCDCDCDCDFFFFFFFF30CFFFFF09 +:105760000C30C30CC30C30C3CF3CF3CCF3CF3CF3B1 +:105770000010CF3CCDCDCDCDFFFFFFFF30CFFFFFE1 +:105780000C30C30CC30C30C3CF3CF3CCF3CF3CF391 +:105790000020CF3CCDCDCDCDFFFFFFFF30CFFFFFB1 +:1057A0000C30C30CC30C30C3CF3CF3CCF3CF3CF371 +:1057B0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF71 +:1057C0000C30C30CC30C30C3CF3CF3CCF3CF3CF351 +:1057D0000000CF3CCDCDCDCDFFFFFFFF30CFFFFF91 +:1057E0000C30C30CC30C30C3CF3CF3CCF3CF3CF331 +:1057F0000001CF3CCDCDCDCDFFFFFFFF30CFFFFF70 +:105800000C30C30CC30C30C3CF3CF3CCF3CF3CF310 +:105810000002CF3CCDCDCDCDFFFFFFFF30CFFFFF4E +:105820000C30C30CC30C30C3CF3CF3CCF3CF3CF3F0 +:105830000004CF3CCDCDCDCDFFFFFFFF30CFFFFF2C +:105840000C30C30CC30C30C3CF3CF3CCF3CF3CF3D0 +:105850000008CF3CCDCDCDCDFFFFFFFF30CFFFFF08 +:105860000C30C30CC30C30C3CF3CF3CCF3CF3CF3B0 +:105870000010CF3CCDCDCDCDFFFFFFFF30CFFFFFE0 +:105880000C30C30CC30C30C3CF3CF3CCF3CF3CF390 +:105890000020CF3CCDCDCDCDFFFFFFFF30CFFFFFB0 +:1058A0000C30C30CC30C30C3CF3CF3CCF3CF3CF370 +:1058B0000040CF3CCDCDCDCD001000000007010051 +:1058C00000028170000B81980002025000010270FA +:1058D000000F028000010370000800000008008033 +:1058E00000028100000B8128000201E0000102009B +:1058F0000007021000020280000F0000000800F004 +:1059000000028170000B81980002025000010270B9 +:10591000000B82800008033800100000000801001E +:1059200000028180000B81A80002026000018280D9 +:10593000000E829800080380000B0000000100B0F8 +:10594000000280C0000580E8000201400001016003 +:10595000000E017000038250CCCCCCCCCCCCCCCC93 +:10596000CCCCCCCCCCCCCCCC00002000CCCCCCCC87 +:10597000CCCCCCCCCCCCCCCCCCCCCCCC0000200077 +:10598000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC57 +:1059900004002000000000001F8B08000000000031 +:1059A00000FFFB51CFC0F0038A277033309CE345E2 +:1059B000F0E981831829D35FC6CEC05001C4554099 +:1059C000BC0B883FB132307C66255EFF352904DB95 +:1059D000488281211E88D7883130A84922C41DA45D +:1059E00019182603F9A150B147403A5F8A32770F60 +:1059F000169CA68029E62A8760A7639147C6196886 +:105A0000F24BE550F99904F40F34BEA28ECAFFA2FE +:105A10000AA113A0E257D1E4BF42E53BA0FEBAA61B +:105A20008EDDDC4E32FD5DC302A101FC99B04798CA +:105A300003000000000000001F8B080000000000B1 +:105A400000FFED7D0B7854D5B5F03E731E3393798E +:105A5000E424E43181104E1E2068080384888AB74C +:105A6000271030F6D27678D5582D0EAF10F2866B0F +:105A70002DBDB67F06084978A8C11F11ADD5E12913 +:105A8000F6821D3122B6880328D2ABBD37587C552B +:105A9000EB1FD10B8A90442A6AEFB5E5EEB5F63ECE +:105AA000C99C9309047BDBAFFFFFFD7C9FEEECC735 +:105AB000D97BEDF5DA6BADFD18C93181A40D23E476 +:105AC00022FCFB0621929D1032A1379DE32021D7B5 +:105AD000184292662FFDDD921442DCBAE2BF49A360 +:105AE000A9BBFEE41A9A5F5FECF0AFA44D5B1F4DBB +:105AF000786A092DBFEFA12FC34FD07CFAEC79ADA6 +:105B0000C5B47ECE24C90F5D1D1AAB1002EDE7D8D7 +:105B1000C276015281E5979030A17F92AFE8F845B7 +:105B200084B8E89F2497FE37891CB2A5603EE4D173 +:105B3000A09E029946483631FE55607E36FC09F536 +:105B4000447767D0EF759E77E513EC7F8E5F0ADBB5 +:105B5000E94773F20372C84DD3C6086D49C71DFBF0 +:105B60005D3908F9C00C99E46387B6D8FE6FCA0F97 +:105B70004C7514D2FE670B08FFF9D94936DA82CC8E +:105B8000A6EDE13B224E1F1ACC679FD9E8B8DFE0B3 +:105B9000DFDDDF40FFA7C05F4B09A1E5CB1C0C9EFA +:105BA000E4D9D9C530CE8919D71643BF73A61332AD +:105BB00088564D9D3DF69044F3EB1A89DF4EDBCDC0 +:105BC000290D1CCF81D9F8CBA79302E8978EEE6000 +:105BD0007D5FC4FFEB38EF643EDE3FCC1E2B10FA36 +:105BE00041F6978AA95D72A0F953D14B486A052DF9 +:105BF0001F1953EE9F769AD0F2E4E9E6F64013724D +:105C00001D2125C49372EA1AFA7716C9BA2842AD43 +:105C10006A0B8CEEE50F6B4AFFFDF922D001FA12F8 +:105C2000FBD61F6A9CE9E9A0F85A377B9687D0F427 +:105C3000F5C02C0FE0EFF5D9B3108FD6F673666779 +:105C400027025EFB1BEFFE063AD008FA3DC7B3B54C +:105C50007E9048EA23F4FB393AD1C331FDDF01934A +:105C60004D256409301B4DB325D5A6D2FA6C8DE8BD +:105C70009138E39502B1693B92499928E352F30FB9 +:105C800061BB3726D94AC371E67307EFC7551AB807 +:105C9000670EA56FD674127551BA1229AAC6E2759D +:105CA0005D8A541A8E03C7DD1C5E42687BCFC0E15B +:105CB0007165D802D09F32470CC4C2F50380674299 +:105CC0006F4AA24CEEE6F818FD72BFFB6C508F33A2 +:105CD0008FBB008E0990AAEC3B0E8F0C7C9301B217 +:105CE0009682FC43C26324E0FBCC1EB9240107E585 +:105CF0008FA1F01715AE2DA47BD41214B256EC4729 +:105D0000F4A42403BD5711DE0F29514F517E1542D3 +:105D1000AB848BD75C6A9E123965F035F0A93B19CC +:105D2000C7BF1C5E48A018E55231D48878C007E38D +:105D30002BF94DED02A5CBBAD1E57E946F8A219067 +:105D400033437EE1DF57F43B37FFCCBD9CD291CA91 +:105D5000916B39D38F8ADF2C67EB928EB50820C800 +:105D600064B9490F1012244077036FEBBEA278BCD0 +:105D700004BF5BFBDD6FC8E7603298C927933F051E +:105D8000FA07BD79D37E07F0F53ADF5E07CC6B5D8D +:105D9000FE5E827A8AD3C7E8D795AF5D52CED681B0 +:105DA0007C8D80EEC348A79EF2D1A7C6027E76A660 +:105DB0002AF78B747E3B9308EAD9756B48782BD011 +:105DC000B594E5B56F69E1B5748E3B9DBCBE98D6C0 +:105DD000D3BC06EDA9BEDB3A490B87687E6B8B8D81 +:105DE000B51FAB85459A1F319184148A4F6DC5C28A +:105DF000954E5ABE75A3EA17B55EFD34A225672DF0 +:105E0000B4DFB2DEA60AF0BD8FAD233BF3493844C0 +:105E1000C7DFB139F99B23693E14B2F987D34FF23A +:105E2000F8FA45D9A5442802B4313A9C21795CAEF0 +:105E30000402E5A9BC7CCB7EFFBF8EA4F03D365D9D +:105E4000F2AFA0453BD6CF4CD0289E766881043F68 +:105E50004D7FF0C07CCCEFCC0C2600DD766E9C9F95 +:105E6000004CF1C0E6991B46417B61D2611DE96C93 +:105E7000D6FF471F283AEC00384B999E4F6A0D7E9B +:105E800053A2F9BC4912B9894E21CFAD21DCDB1FE9 +:105E9000B211584FFBE86D8BBE4ED4CD7957EBB4A1 +:105EA0008F817F5D0F160920DA3B3586E7413792F7 +:105EB000F08AECBEE3EF5CC8EA13295D800E2EBFCA +:105EC000625967965AF856477970713CB95A751CF1 +:105ED0008F487A8990D68B57FA9F4662F0E97AF01C +:105EE0002881F5E98AE76381275DA07C0F83AB9C5D +:105EF000EFB91E1CF7CA5763E3F1B121EF1EA07F73 +:105F000022C577612404EB507A61240AFCE2C95768 +:105F100034B00B9A0931C9C5A1D1FB7C1D203713C0 +:105F2000223E58AFD78D7E83C98F5681F830E66FF9 +:105F3000B4F7E4B79358FBC1A88772F8CE537869D9 +:105F400039BB87CB594F7F84AD4724731CC2754F33 +:105F5000E161755E1C7D4CC80A94CB9749E07A815B +:105F6000A6DECDED51A7066CAEDF0079B7400291F9 +:105F700038DF4D13D87AD242745DA0E9A3442F16BE +:105F8000709D4B66FAD7B22EF5D19FBC5D16E9160F +:105F900040DF68D43E803487F831CD23014C4792EE +:105FA000564CAF26114CF3493BA605A41B5343AFF7 +:105FB000F8892A427EC4C4FAC920E7A4DA638BE5D3 +:105FC000BBD06432B23ECE3C9A2D787390F8EBF899 +:105FD0001D025FE748A68AFC43F87AF16EB018E824 +:105FE000C55428FCBBDBCCEFE224BE0E38EA3D6989 +:105FF000805733DD8D5454CD7C5A6DF0A944241C58 +:10600000C7321FC463CCB8D6FE5673FBC6989F9C9C +:10601000A2231F496E66CF5038F4BD71F0D1280815 +:106020007C9E41ABDC3AB229BF4B49B6C85A9A6B49 +:10603000744F76E8382F3F894767EB7CACF02ABE77 +:1060400081C1B3A9079E0ACB3AFA97C2F34FA6FEC5 +:10605000A44CB21DD60BA28670DE56BCF6F9DE4209 +:106060008FFEE4D29169D6574A8AD70287859F0668 +:10607000687F7CE34BEA7FE4C3FA1B21412AECA949 +:10608000F90101E67FAD401A13295EC868A2EDA0B0 +:1060900070CDF56ACC8E8B693719F491660BC97493 +:1060A000BECF92EE23D03EE427911DF4B367F36D8B +:1060B000A55B697DAA9FB663FD05401EAE1D6D0BF5 +:1060C00040B9D19F4E9E32F547FD2E11F0E136E8E2 +:1060D00063F1C3E4B136B41F957CA26F89235FC717 +:1060E000B97C151D71EAB09EB8CA94B0331BFA8F03 +:1060F00014433EB59AF8615D9FD4CDE651C6E130B8 +:10610000E69DFA5940007E6AF7313BC05548D03FC2 +:106110005432DA74F01FDDB40EF5427E541753503A +:106120003FA23FD81F9E3D5F3DED0BD07E7DD4B991 +:106130006A07BE92FCE9A09F578F56C860FABDF867 +:106140003B3BF6FFB9A762188999CF470DD1B10B38 +:10615000A9C170A6E118A6671BDA31ED6C780BD3E4 +:10616000FEE94A598EDACEEB7EE2D7C01E100F3F11 +:1061700047340FC01DD5755C171CA212B32E808248 +:1061800006FF6FD3D8BCF0DA6CC46B08E64DD56758 +:10619000787836E05B0A009E873822C2D27C867708 +:1061A000C03FD001CA8B8E3CB702F15C4DC6029E47 +:1061B00037C9A40CF43CE013D6897D82ED0E800330 +:1061C000F2F369FEFA8FFAC1FB5986F78C97299E84 +:1061D000004E494B64C6AD8EF2953B910B12D7270A +:1061E000BD7A92F9D9BDF6BDF6EF00CF964689ACDF +:1061F00085BCA6684A11B7F7414A8215D3C1DFDCD6 +:10620000563EFD28D80BB9E25787645A3EB45E3A31 +:10621000D911234F596574FDA476C2B0E5E6F2ECBE +:1062200090394F07407F34B7C55C3EC4C6F5AE8792 +:1062300078401EADF35AB6E85771FDD3550D24EAE8 +:106240009663F202C3A79117BC133B42747ECB4600 +:10625000118C034CB7B1F5B315BEA37C712F4FD78A +:106260005BFA315269A2DB46C6303D196F7DBADD5B +:10627000563CCE46FB6BB04D1E67A372E4922204DF +:10628000EC77975BD1E3F993D36D128E9F20B5EB3A +:106290002285ABFB3AE2DF4AF1BE4CEE8E827C2CCB +:1062A0002BD6FC215047FE30CA6312D56162F61529 +:1062B000C153027050784A6C384E04FBE9A6380787 +:1062C000FB7D99CCFA5D364A236837F603E75536ED +:1062D00019E10CD80409FD344E97551539F74DA333 +:1062E000D94E559F05FD67260567C17846B96F7E73 +:1062F00029FA6319C3CCF42B77D467017F540622A3 +:10630000D3807F4E7B5F6C92E9BCB73610BF44F1FF +:10631000FF9E2B701BF457737BFD08B07FDF065E7A +:1063200098002A3B807AACA564A55FA2E572891427 +:1063300095293FCA130FBF2517401A2A86388B9319 +:10634000D4337D47F54B2235BD1C23F58F217EA22A +:10635000803CD072556F25600F38A8DB703286EF15 +:10636000944C731E6CFAD87C7F7AE3722998E727E5 +:106370008703FE09DAE9DD49CC7F9226FA0B00DEBD +:106380007BAFFFA606F0FCC46633F967567F4D5A13 +:10639000FE6F69791068E2FEB6B4FCD5B4BCF1803A +:1063A00097569C9763CA32940B05F02432F907BFC5 +:1063B000BE671DE478F85BCFDB582F5737BC35F844 +:1063C000C3E120A71D833FA4C4592D0591FF423E80 +:1063D000F0B5281C92998F09784F1362526E1718E6 +:1063E000F69B9C5A887494DCD2A98E98F5DDC08FF8 +:1063F000B2FCDDC11F8E87F46D4CAD7855A4200131 +:106400003FD068D713B718E0FAEF34E2A979C41F78 +:10641000A53873A4B0786A7A5E280AF37252FD092F +:10642000EBD33D235F6BC5F081C50F3B94AD203F9F +:10643000B48CB6615CB36578E49002F90C6A40D123 +:106440007A67CA5D21886D4CCD637CE3F4B3F5D4E3 +:10645000353C8C7E98A1BFBD1C1F5EAD1CF5B3679B +:10646000A2D9DE31D601272BA2F436DB51CE94A679 +:106470004FC582BE7E9A539B761AE569A4B93F2325 +:10648000DED16EE3F18B6BC9B5683759E212FDE1DD +:10649000CD6BF87113D9BCDCD34918FCE6F48951F3 +:1064A000C49BD7CFF066D89B1E3EBF9B4A2304FCFB +:1064B000BE9EF8F3CD0C6FEBAF8BA27FB77EEC29BD +:1064C000B467BD851D263FCEF81ECAA1FEFCC4766A +:1064D000A8A1F618CB1B71238AA7E91969BDEB6146 +:1064E0002BB7DBAD7453279262D0634747A7158360 +:1064F000DEBEB784C24EAB3C7A589762F0ADF27EF6 +:10650000D47C86DF7BCBD87C697BF4D3EF9D9893DA +:1065100004E366F2F8B0117FEEF1CBEBCD784F28B3 +:10652000B4C4852D7EB7EA67F4524BCCE5AB395F36 +:106530002B22A7572A19CEE835303E4F32F8BC84BB +:10654000F17932DF37482FD10E011D924A99FF4D64 +:106550002C7EF34D291D8C5E378FC8003FFCFEA9B1 +:10656000DD3E669730BA26717EBCEFC61102C87157 +:10657000728926407D723EC35332C513AC77C9A5DC +:10658000CCEFF64ED4B05D5209A35B0B7C4CE15FBF +:1065900003748A891F3B4B5B75A07F6BF14E1D74A2 +:1065A0005932C5E1200ACFD4520A1BD89DB45F806E +:1065B000D75318C5B85A524970D8A5FC7A42A2825E +:1065C000CD87F8106C684BE93C25587E6862B22094 +:1065D000D07EEFA77CC0F180713C178FA3DF5F787E +:1065E00012F5DCFDF04D36C8A9F6EB1C9A27A5364E +:1065F0003FF807F797E608F1E2E7C6BCFB83CB2A32 +:10660000C712F83531FC7295C8E3DE16FE5D4722ED +:106610006A2EC857486FF7A5F5EA0F83FF7AE4653D +:1066200012E3CBFEF489A187DD2418B265F7D51FEC +:1066300092CEF8DE9E174079EB03EF24C6AF528A64 +:10664000B9FC3691DB7F865ED19207142727A10023 +:10665000AE7722D74F4FDA020BC554F0BBC3B84E0A +:10666000B8C874AE37199FCA9CFFA6E633BDE24A8C +:1066700089B076978DA73A90DFD634A8A81F5AC65E +:10668000DED59E43F1B06678931FBE738C6B19B94B +:106690008DF6DB3C7C79702B0CC0FD30D4BF22AC76 +:1066A000838C5F8D7D30030E9219D2619FCC097E61 +:1066B00011E06724DB5F902412B58FEB1DDF954757 +:1066C000E1CD6769289FC10DFEC9EBB6E02A9C6F3A +:1066D0007E6B94A29BCE9BC9CB6A21425C22CCEB01 +:1066E000727C1EB231BE8E9FF6F75D02ECD3C4E120 +:1066F000DFDD22DBA7592D478850087E1BED89F28C +:10670000C9EA6C6A97C781A391F36BD52E67F8C36A +:10671000187EAB892499F275FB33C21FC6FA117734 +:106720000AB84F51CDD158433AB200CFEF291AF6EB +:10673000576BEB48837C17E94E5B027810038F8B15 +:1067400074FD7752BEC4B8907B60EBD6E5F0A781AC +:106750000CD18540CBE4A90F79988E17DC07E3694B +:106760002A2BBFD271E3F0F50BB17C4DC457596AA7 +:10677000E56B7F14F9DA9D12C57AB79FF1B5C18F29 +:10678000899C1FAD7C688CBF9EC7AFD6723E5F33BD +:10679000A1498570DFDA519B309EE62CDA5C017CE2 +:1067A000DE32AA250C7CDE64F035DF17A1FE2EDB7D +:1067B0001FD35AA3B04E2672BE56D4EE06907BEB82 +:1067C0007C5D9338BC3405BE06B8395FBF07F893CB +:1067D000FDDD08AEC1D76B07CCD7BA456F9BD3FEA2 +:1067E000FC27D9C2D71E89F1E767C0D7004F0AB38B +:1067F00063DC3E96CA7EEADFC7E9E70689F9996B52 +:10680000B91CACE572B0B61F39F83F22F303FE9A0B +:1068100072308BC98143A2E58993AE8C1F25B0D31A +:10682000E3C87B9E24FCB5E1DE3443BC723CFE270A +:1068300030CD84BEF434D2CF44E7C0E43B8FC9737B +:106840007F72BE76687C38FE5364F4A7F82E9226D9 +:106850005C39BEFF5A7015727E36F04382C528B788 +:10686000317A663AC02BA9869E7904D3A979AD28DE +:10687000A786BE81580AFA2B6A2BC63B9C99AD6845 +:106880009F39F398BE31FC24EB7C8DB87813D73355 +:1068900049792102EB9F3D85703FAA9EF95199CC21 +:1068A0001F30E2D586FDA8187ED4D0BB709FA77993 +:1068B000783DDA97CD37D63BE2EDC336FBEE77F085 +:1068C0004D5FD33EEB1A5A0EFDAEC9BB9FC4B3C396 +:1068D0008C7918FB464E3E6E731EB5A8605CDF32A5 +:1068E000FCDE6AC73467B2FE7ABEE77A57EED1BBE8 +:1068F0002C8F76546E8C9F6FE9C7E00385E843A325 +:10690000103718E41E09E74C9A84043FD8C74D920B +:10691000209D72901E7BA95A891640FF2766BC9C59 +:1069200085F6B23DB806E4BCE9AB8003E2A9AB53FF +:106930005EF3C6969F9DF1E6B7C16CA5DFD5E27EFA +:106940008E8348B1FB6327DCDBD17E4BC837C7E9B8 +:106950009C14AE0902C413CCE50A8FBF2899E672D5 +:1069600099C75FA4144B39E70FB934BE5E7993EB36 +:1069700015DF02764EE7C41C16D73B712B4F6730EC +:10698000FE3EC7DB75F334C2F5EE5F531F25E5F617 +:10699000C2EF9BE2C7F822996547BB3E2B859D2B32 +:1069A00020B1E726E05F6BA24462FCCCA18197FF97 +:1069B00008F1D4610BBECA063C6B15EA615846DB90 +:1069C000A56C9CC76342F72818CFE63A8BFBF5020B +:1069D00045E3726A120BF4DBDB2185EFBDC0523A4E +:1069E0008F7B0591BFECC03722D0298CA98B44B195 +:1069F000DE433A309F081BE6B9E08751BF4BC433F2 +:106A00004C611BC68D7ECCF643D688786E83A80376 +:106A1000B4BFC9ED2AF89742887EE71AF877BE40DE +:106A20006B31C8C4E0B208C693ADED7C53D839A031 +:106A30003E7AFBAF4FDF375273818F542C37E81CFF +:106A400014F54E6942DFF25F8981F312C6AB58DC60 +:106A5000CD5A5F2AE91740DEACE5C20B7F3A057ECE +:106A6000F4AA6764F4A3A73C2347BF41F3355B0452 +:106A7000F4536D079DE80F773EC2F2518FA243FB9E +:106A800073DB058C07D5D9DBEFBD01E28ACF880423 +:106A9000FD8D7019EE8B9DE27326FB59BE9C07801D +:106AA0006AB61C9A0BDF57ECB713D877A8796EF14A +:106AB000B76FA0F9C5C764F4516A76AC50607F65C2 +:106AC00049588840BE6B32C1F143FBC4F00EDABEB8 +:106AD000CBDB9E36C70DFB2B0EA25D45E1F6B4A7BE +:106AE000CDA6F4A90C3F350DBEABDC2DF8C1FF9847 +:106AF000F2CC8EA319F4BB9A27043CA750B5CB4522 +:106B0000B418BA9C6A13A3DF80F8339D27F8C58BAD +:106B100049EB34C07BCD8E0D8A1613B73CD330922F +:106B200068F6DE7CCD13741CFA5DED93821FA658C7 +:106B30006B2341E08FCEE79C65DBDC30BF15CA08D4 +:106B40000FCCAB5981768BC3F3F6C17E7A65788B17 +:106B5000328DD6573EB245298FE1A7AA5DD7102DB9 +:106B6000863F4E6DCE4DBFD47A7B86AE5BB1F0547E +:106B700012A6B788145666C4EC7B76C8499C3F457C +:106B800053FF06DF875E2718C70A3DEF41BC1A7422 +:106B90005BA632BD60D0EDBCCAE9287517CD88B3BD +:106BA000AF7A2FD0C10EF12A15D3FB1B7C986E6CE7 +:106BB000D0903E9B007F57E1BE06967B279162886E +:106BC0008B7875A2C2529F3C5D2F96214E1260F9C0 +:106BD000B4DB83827689F91BE92639380F825CB7EA +:106BE000C94F4C96E8BABE49092E257E3ABEB47705 +:106BF00072C97560A705E7C8A9B09F1DAC60F1E830 +:106C0000880FE4A289EFCB7C4B66F2D694A1607C1E +:106C100064D3F78BB6A1ED41185E367DBF7C27ECBF +:106C2000ABD17EE6CA54AE1A65DA4FEEE5FB499B5E +:106C30003BD1D44FDADC0AA39FC5D88F7360FD6CBB +:106C40009A7BBD199EB995463FF5D88F6760F34A88 +:106C5000BB6392199E3BAAB19FF4DBFD681F8806B7 +:106C6000FF9076DC1775EF4E1AB796C4F2D1E41F89 +:106C7000C3781E2A55B17C943831C1244F497AB269 +:106C8000293FA874B0A97D6A20C7549F5E76B58558 +:106C90002FDDA8BF314F818A26B138AB325841BDB4 +:106CA000533CD881F9BB06BB51EFDC757DF02AB0AF +:106CB000F70056D0F37729C1316A1CBEA1F3120840 +:106CC000C6CF341BA47DEC32BEEF3979C85723DE22 +:106CD000A7DFD7D9BA4724D1FC434AF12330EFAD1F +:106CE00032B3E38D3843829DA0FE6BCE2EDA168A36 +:106CF000C16BCB50CA2F426FBF2D72D007FCB87347 +:106D0000F56F574A14BEA6A10A1E6E7A5CFEEDE12D +:106D100010B5999B8796FB00FF7685EA8FD8F11511 +:106D20003A7E3E8EBF1BC6DF2B333BD93ABE3D6752 +:106D3000A2697C475685697C8742C7A7F2B16FF587 +:106D40003B7C7C8ABFEB0979567E07C7B76755E065 +:106D5000F8CD0AA9308D9FD033FE01909FC3FDCDA1 +:106D60003FE77AF3FCB32ACDF357D8FC8FAEFE8011 +:106D70008F9F80F37F59FE80CD3FAB92CDDFCEFA5F +:106D8000ED19DFDB83FF5761FEAFF537FFDC49E626 +:106D9000F90FAB36CFDFCEC67F63F5277C7C378E0D +:106DA000FFA6FC099BFFB06A1C5FB107FDC047CA84 +:106DB00090847AF09FA961A461405DA3E3403A9278 +:106DC000C5A937C83908C75D098CEF3E4FA0FCE65E +:106DD000EED5A7244C2590EACB5ACED355BB8B15C4 +:106DE000E62F84D05F58C4415DB85FC4F58C6CB4A5 +:106DF000878753783BF78B21C82FDC78239E5BACC9 +:106E0000B313DC77A75630FA1FFFF1C0E8ADB1F33A +:106E1000B2A68B5A65CBFE1383C738EF5424ABA6BA +:106E2000FC2988A7503D7C12FC1F9A9E96E978B4F5 +:106E3000FC43F083AE8A951B762E8C7677229FCE0C +:106E4000EBBB1CFE5312C3F7A93B05DC47F87CC320 +:106E50005205F4D9A25697C96FA8E374EA7ECE8E84 +:106E6000FB8DC679BE5B501409F9FDC16F1D05BBD2 +:106E700071F1E641A6EF6E27E1D5701473C1FA797E +:106E800043553AFFDBCAECE3448C6BEB43581C9C44 +:106E90000C81B84959DB067908CDDC52269BECF908 +:106EA0005B83E6FC6D15E67CA71C966D60CF2C110C +:106EB000C816DAEFF7EB65CBB900368E5749E676A0 +:106EC000251BEFBB948619B4E8FB908E836215E90D +:106ED0003A5765DF1AF0D4DD2D9328AEC71DA9B847 +:106EE0000F144A45BF2DA8B2795BE19D2B3BF400FE +:106EF0008567EE8F44C4A715FE8E832EDD46EDF325 +:106F00008ECD7F90217E6C9D8F15FE3B965BE7A317 +:106F10002AB03ECC0B59CB199F58F9A96E7FF13698 +:106F2000B33D7BF3B658FBB56AD70C537E49F85690 +:106F300053FBC59BE799EA17B52E31D52F68596ADF +:106F4000CACF0BFDC8D4FE8EE52B4CF5DFAF5F63D7 +:106F5000AABFAD6283297F6BF02153FB5BCAB69851 +:106F6000EA6D07477D07E468D5EB229EFDBDE03E54 +:106F7000752FD89B17DC12EE737E44ED159083338A +:106F8000D45E81B473FF78F4A7A91E2C874DA2F9B3 +:106F9000CA98552D99A09709EACF7265C2AAD02444 +:106FA0008A17B0D7A97C889B15121D04CE4C720F8E +:106FB0001F778B31F51D97A9DF4C057D7CDF7AB1FA +:106FC000237E79DDD679C3D4387E6AAFDC9221B0D6 +:106FD000CE7559CE9F1869B5E53CA7B1BF7D81EB51 +:106FE000D96A85E983EABD1993617386FAE523E2DC +:106FF0009D9BECF93E22B00D48B0FE53811F869850 +:10700000F66BAA76E59AE4FBEC2111E1AA059D4016 +:10701000F5EA1752608D0272163D92356B34C0A1AD +:10702000AF5540EFEC4FC575FD6C43E936D8AF3F27 +:10703000D310C0F4A386324C4F350431FDB0A10209 +:10704000D3930DF59876342CC7F4BD8610A6EF3691 +:10705000B460FABB86564CDF6AD88CE91B0D614CD4 +:107060003B1B744C0D79E8D1BF016E0F1B1BD784FD +:10707000DBC37C2E8DA93DE7C270FFF7BCFBF3118B +:1070800060EF9F7FCB8EFB6CFDE1CBCA6FFDD351D0 +:10709000477BA53C3C089D636BBD3381D1C9692307 +:1070A000A5641CECFFECF4CFCFC7BCC42EF584FD67 +:1070B000333C71FA85785DFAE5E944F4EE829994FF +:1070C0001EA71EFEAF22E8F702AC7F60071C1171FD +:1070D0001D26D16D7EA0D795E24D78E1F759102F8E +:1070E0003BD783BFF62C888B5DABA8D8FFF9363B26 +:1070F00081F8D2F9032EBCCF75FED8362FC8E33203 +:107100009F188E3D47614D6B22D961B7C9EF36E7B5 +:10711000CFB70AA5781E9A6889B347035FA961387B +:107120000FD2D9E0C3D4E867994FC171CEECCA65DC +:1071300071337E5E83EC4E427EA57E27B6FF9F862E +:10714000A7BF7E0C780869231F38085E71BB98DBE7 +:107150007FFB7EF949FA4C81F82A39207F0EF682AE +:107160009DFE77111C652261DEE8B72E2286EC6356 +:10717000A07CB7693CFA9D66F8F417732EC5B7E694 +:10718000FB34220468BF469CA40AFE80F330F5025B +:10719000C6AB8C784997E46E11C6F4C64BEA78BC4E +:1071A000B8C6D1A10469D1B9B6DC4BEE9F9E69384F +:1071B000A6C239AF0A47AB02CE4F45645409E8B9BD +:1071C000736DABD2C01EAC12CFDF152F7E9B6767ED +:1071D00071BD2561B9DBBC8E72FE20B45FA39C1D1E +:1071E00072749F8AC99FB5313BDBDAEF04FBC0F6AE +:1071F0002D6A771F9F7683D6174FB5FB3F55303EDC +:107200002E11535CC9C0DF7B4A60829DE2A972D710 +:10721000FB688F7E248746DC7D09FDD4777E6E9FD8 +:10722000E97C7288B4C338F327F2818876CB3B744B +:107230003DFDF815999DDBE4E7807BF695F9BEFEF0 +:10724000029E9BDF5685E7843EDEF78F68FF2D2484 +:10725000012FD281B416811D798ED84A014FE7C81B +:107260006BDEF13174B8953A4A40EF052D663B86E6 +:10727000DABFA6FCE2CDE67C39999906FAA47CA394 +:107280004CC202CECF547FB35DC57E1793FA265809 +:107290005725EE8FCC57893484EAD59A677F5634C8 +:1072A0008FC211B4333FC888BF2C49667660654AE7 +:1072B00058817DC20FDAC67FF70620833DDC04715A +:1072C000289248FC3B485FFC5E29FC56788DF5BA55 +:1072D0004F1C88C321EE12E2EE03D6DA056ECF868C +:1072E000303DC0E76DF805C72CF915767EDE5224D7 +:1072F00022D0FD9CEA08D912B1DE1F8578DC5EBB86 +:107300007F950671FCC06A7B6A6FDCDF6897640F4B +:1073100062F959E1D5723CF720450BF0DE218FEF81 +:107320002B9C1FC4046F019C23F540DC1ECE753AD4 +:10733000BD5B21DFE4A9C0F31F7520EFB4BF7BBCA8 +:10734000D38E419CDA415AA33AE55FBBCFB21FA06E +:1073500099F32E904BD0675080E7A209C6B95C2301 +:10736000CDED3C7E73FE312E8F7481433EEE39DFCE +:10737000E67047E13C0999289DEDF1B772C0DF63E3 +:10738000F0C3FD56687FA7CADAD7F27DDD3BDF9EEA +:107390009C9E7C097D54F7A540C231EB489DD4AD3D +:1073A000001FD67D2961F9D7D69B1A5D5563F4E697 +:1073B0002B4AF059FB04A627013E818E13BBDF64E4 +:1073C000BD877002F861422F3F7C6D385288497F3B +:1073D000BFA7048FC583E36BF7EFEBD3FF09E0BBD7 +:1073E000FFB1FEF3FAF4DF110FFE9A67F7EC0BD151 +:1073F000F5B5F2170F78E110D3C7526B1A9CEFACBA +:10740000DEB1DA0B72F99114F2025D3F0E8B71EF6F +:10741000E7A63B0CBED3DD708FB096F3DD999FAF2E +:10742000FB36F82F9FEF90558C0FECB247ED942967 +:107430006BDB9630F9D8657F9FE59BF1BC53DD7E11 +:10744000B3BEA87CFC81340D0F5585B8FF1C45FFE9 +:10745000A076FB7F4C03BBAB8E74A3DEB37E07E349 +:107460007F998CF6C03C25B16FBD710EAB8EE3A544 +:10747000AE6D1DDE13AF6BBBF934139A0EF43BAD4A +:10748000DF5570BBDFE1309FDF34F042C2CCEE5FEE +:10749000F5C48305EF53B8CE6E7FC52BE4C7F22940 +:1074A000D37FE7230B1EFBA5D6BF5C7552FD186B7F +:1074B0005F1BEBB4B69FFB2B07585A2D47BDE00F5F +:1074C000566F91F1BC7BF59E6D3B1F86F8CCDB7649 +:1074D000FF70DA7FD59E97DEB89EE6AB9E9253A6EC +:1074E000B369B8E19EA2419F3AFADFF271BDF4A8F8 +:1074F0007CFA25451BCDCA7F9CDC4B97AAA70E2999 +:1075000064745F7C4C891C52D87EB6853E91F7A787 +:10751000815FB1EA892F14D05F1F1F14487A761C4F +:107520007C6E7909ED63C013D293D3AB877E96F658 +:1075300075942EA8172DF4B2B6FB98AF07D02FC4C0 +:10754000E3297F3FF94BD8B7F99DDD0F78A878F292 +:107550009FBC309FD3523DE3F39FAD4E83FB20157C +:1075600072284DC59495573CFA03E4BFC5C77F9078 +:10757000C6CEC5EA19FC5C5706CC73D12373709E46 +:10758000E524887C58F13376CFFC82444A9F8A23D5 +:1075900027F739D83A767AAB1D37114FC34202FB31 +:1075A00018AF89E11D180F64E70D7F60EC3F91650E +:1075B00098BFE060F45AE430EEF1D1A524967FB78D +:1075C00037B7039DCE0CD5D3218E5C47A410C78757 +:1075D0007091F62B1E9F9ACECF1D685211FF8EEA36 +:1075E000FF29500EEDDB65DD5960FA8E5CCCEE1D97 +:1075F000FF4E3E3E853B01ECD7D369D41E8C33BF92 +:10760000030E639DA676560C9FC5C83B93FFED6B9A +:1076100098BC1BF21F9E510AF59F9D607204DF818A +:10762000FD42E18AA663FDA1D902EA073B89C69320 +:10763000F3ED32977373BD955F28FC12ACC73D7CA8 +:1076400003E324231DD0BE2DDF48BF8FD5AB30AE62 +:10765000B76FBF861C2FE6FA60AD451F90475207F3 +:10766000B47F5B2D87773E0CF24BE535A481FCCAD5 +:10767000F85EC127BB8FBCF13D2AB79F440CB935DA +:10768000EB55ABDC56EC9D40E2C9ED276E3F892BF4 +:10769000B7B43CAEDCBA3B909FFFD67AD5C0E3D3FB +:1076A000163C1A7AB23F7C5AF5E4B71D5A5C3D4944 +:1076B000FF9D20457DF9D1E04383FF2AFFA506CF3A +:1076C0000BF5F0A9C1873D7C6AF0619F78A4098F12 +:1076D000D6FABBE16F3A85C07332C6CFAB0FB0FDAF +:1076E00067FADDD12185882F1D9739D27A74484AEF +:1076F0006C3E6CC9472CED754B3E60691FB4E4EBE2 +:107700004DEDABF71F51D8B99EA8A99DB8FCA7E4D1 +:107710008338F101631DAA6BFB5409017FB8BBF1EB +:107720007B79250979205EFEBC88F1F22E8AE3265A +:107730003A4ED7EE6C7C8F60B593C557BAD46E2F96 +:10774000D893AB9358BE3B5569023D6894773B593B +:10775000DCAF2BD0ED4D8AB1EFDE3F20A21EEF084B +:1077600093D2787E28DE40A1F8ED20FDD5B3FD80D0 +:107770002EB0D761BC84AC30F0E354D19DB51CE28F +:1077800035AD22DE6B5BB8E2162F9C23E93A90FB05 +:107790009D325ABEE8D722DBA60CE952468C1FF870 +:1077A00011096D9A24C0FEF57AE49F0507985FB829 +:1077B000707D7C79A8E4DF95BBEF5440EF527FEEFB +:1077C00064ECBE87D14FC52396F203FFC8E5A6152A +:1077D000E31F95DBCDF5411E3F18ECE4E7BEC792F1 +:1077E000B1DC7FB7C5DE0F9E2AE67FA78CD2A7EB60 +:1077F0009848E03CC1F90322D2E7FC6E767E00E3B4 +:10780000FCD701BF772BB1E7A9CE827C5DD5BF1E27 +:107810003BFBCCEF8BEE063EDAF74EC14F697A7632 +:10782000DFDB237E05F967DFCC7A87F46D3FE5A0C7 +:1078300013F755BA0E7A90FFBB9EFF4DD6DD907FB1 +:10784000CE8EF1ECAE835F14003F75ADB457801E51 +:10785000ECE2E7EF563DFF454107AEBF8D48C7A9B3 +:107860004EE64F9F3FF05FEFC1FD81F307E8ACC0EC +:10787000BE38E842F9AAFBA513E36F5DCF7F511430 +:10788000EB27FCA5F3A9E5FB9D5D1E52B617E04B67 +:1078900062FB4475BFBA6E1BBC2F51D3764859406A +:1078A000EBA7BCF0A702D0AF5D7B99DDD429773C74 +:1078B0000AFB7981350F34CA945E9D20648369FF89 +:1078C0006BDE280139EA8B973F615C71A0F858FCA8 +:1078D0007F0D3E049DE93F4F184C852907FFF8DED8 +:1078E0003BA0270EDA912F8DF97E125981F6CCE557 +:1078F000E6DDF4FFDCBC85E840E6BD03E63DE1EFF4 +:1079000077DED7C0A1A1D4BE72D097CF9FBF0BF3B3 +:107910007B3C7E847780FCFED2DFF9FCAF98EE7B67 +:1079200029DDBD979FF7877FE7F3EE9FEEBF9ECBE4 +:10793000E9AEC27998BA17FE84F05DA99E9312FE53 +:10794000BEE5BDBFF91BF6FE5A9BBF35271BCF9383 +:107950003AC0B0707B66B6407871EDC8992AD89D60 +:10796000623FEFD54C48607E9528B0F721C850168D +:107970000F24DCCF82630DF80E889BDD3B93DC4D3A +:10798000687713C9DFAE53BCACBD7ABE1FCF1A9166 +:10799000716F05219F39C98FF16E8BBFD928105D9A +:1079A000A0F6AE74F5378F81DF238FB445ED0598CF +:1079B000BE0F69338F63CAAA62F287DCF9E6BC5353 +:1079C00033E7EDBC3F0761F03B7C240CF16C71D4D4 +:1079D0006115CED3896325024FA538496B08FC0E8B +:1079E000BBCFFC7D5202E17EEF5F86C78A0416A7FB +:1079F000128571ED3AE071940DE3DC78481BF1E2F9 +:107A0000C7F7BA08F7AF7BF1DAD40EF894C03F6637 +:107A1000F617FAD584FBD312EF421A69D39DE676A6 +:107A2000DC8FBE2C9D185DB2AA399D9699E862D074 +:107A3000210E7D4C7431F07CA5F4B1D2C58AFFEBE8 +:107A400013185FF7472F832E996E1DEFD7C9DC7F80 +:107A500028013F13F2990182FBABDC7F905274BC8A +:107A6000A724AA7EBC97007E5C941AE02FEFDE86E6 +:107A7000F1A4733F7FFFDB004FD5AF44E2A0F8EBEA +:107A8000DCED2151F85E0A2BE09F56B689B84F40D5 +:107A9000A468D1AC987D62C30FA8FA8507E753B9F3 +:107AA000D71E9E4EBFAFDCF74101DA612BBBD1CFB1 +:107AB00009FD5C60740F7514C03E70A5C4FC112BE9 +:107AC000BFAC4960F196B3CFB9CA20AE23EC62E7F0 +:107AD0007F2B23B7C8F698734DA10499C59B9E735D +:107AE000A15E083D21E0F928802FF6DCA9E1879C02 +:107AF0007D4260F0ED97F19D98CA5D4F75427CAA7A +:107B0000F22DBB1FCCF8BA5D9FE27EC8945FECF10A +:107B100076A01F2E9AE2127DE201BB44E48FDAB612 +:107B20001AF443681EF9A236C2FDEF2BF457AB7E60 +:107B3000F1FC3EB87056F5F4E35E887F9D69DFE1A5 +:107B4000C5B8C0AE4BC7E7FAF8FF9135DCFFFFD6EA +:107B500069764F3BBEFF7F06FEA076F1D30996FB08 +:107B6000ABBB06B1F71449B4E852EF7155EDB9F06B +:107B700028C4AFCFEEFDE45180BBFACF7F7814FC70 +:107B80000A72D0A9C27D82BA9FBF8EF13EE3BBDFED +:107B9000703DD0F9C4E3182FED7C9BFA1FF45FE72A +:107BA000F3A7B3C0CFEC7CEA8F69104FB9F3F9A902 +:107BB000F86ECE9DCF4C492771F4899102FF86075C +:107BC00010AFB5D2ED48DB11F47FCE51BA83FFD9A7 +:107BD00013D789D4B07899C6E339BBE3C7C7FBC4D0 +:107BE0006FDA667DE7C6424865BF460610C7394171 +:107BF000E939660074DCCDE375916F5D328E730EEA +:107C0000FEA0F43A6BA1E385B6458F3D0C756D83FC +:107C1000FA8DE34407803F23FEBE3F41FF2201E48B +:107C200068EFBF60FC0CE8379D4EB873CF852CD849 +:107C3000BFF848EE9E8BEF853C6F57211E51F9FC33 +:107C40009B284F9DCF1CC7F836E171F04ED2F38FC1 +:107C5000C52BF999CCBAED1E16FFE17480F890E6B9 +:107C6000C5721E07627C6DC487FA8B0B8D71B17370 +:107C700027C6BE40CDF67778BCA5976EC244A0D784 +:107C8000FB97DCCF30F0A0021EAE8D8D7BC68FC37C +:107C9000F5C43D2D74037A42BCB327AE49D8137B9B +:107CA0007561E1CD7871F4CE2D2C5EDA29C73F8F56 +:107CB00065C441AF7659E29FE181C53F2F378F2BD5 +:107CC000C5D3609786FD5AF175F6ABF8FAFD5BAE49 +:107CD000819D5FE8777FADDA7C1FE63D2538DD05C5 +:107CE000FB6B6DEF2B04CFA774B3732B7CBE67F9CE +:107CF000F9D3B33F17312ED6143982FADDAA3F8C5F +:107D0000FD572BBC7770786BF7B3F5E3EC5E4FD87B +:107D10004DFB397BF839E4EBDADDEF635CEEE8AE7E +:107D2000A7958E98F516D68F70CC7CCE3E79A8801C +:107D3000C579E3DF1BAB71317BB3EE40FC71EA76B2 +:107D40007F6A1AA72A1451981D70E9F1CE48FA2DBE +:107D5000D0DF997619DF4D3A1311E3BE171C70C9B5 +:107D60007C1FA195C90F5D47F19EC071767FA7F07A +:107D7000B5043C577FE7F1D277E0FDB73BA95883C4 +:107D8000DDDFB682F169DB4FF42140EFB6E3DF13AC +:107D900061FDDA07F88DB1FF8B4ED44FF150FD50E5 +:107DA000F46EA010D8D5AA77AE7DCB66829F8E9355 +:107DB0000EEB4223ED07EE83C0B939BC57EE9D565A +:107DC0000AF088AA4D750A7DE721BBF97D55DEAF23 +:107DD000AC9AEF2190AFC66BD08F6F268B4B66CCE1 +:107DE0003252169F0C19F787CA13C2ABE87C7FAFDB +:107DF0000637BB285E7C9E8DD92F1178276AA20694 +:107E0000F6D3632E7EDEC14BBCECBC833B64A37A0D +:107E1000FD61FFF60D93089E67D8067CD9739E819D +:107E2000440B802F8D767DEA2DE71D32E1132A5A0F +:107E300022873317EE2550FDB26A86772BE41FF1B7 +:107E4000B0F7CDB248F72138DFB08DDBA3D960158C +:107E5000E7F67DE7ECEBBE6F9632A578E9303F851B +:107E6000D3F55F53E15C7CCA2DC54F0D5169852D5B +:107E7000631ADCA34979BC786C06CDCF5FFFF4347C +:107E8000ACFFF7E2B15934FF937B0EB2FA2A01CF6F +:107E9000C1BEB0AE761AF0EFD796FBD9143366B9EF +:107EA0007F05F0772EF0EE77176970AEA25BE1EFF9 +:107EB0006504A0DDD0890C7F99EE779F027F6598DD +:107EC000AD6305F0EB63CF7F9184F716F9FBA12A30 +:107ED0006954E1DC152D9A78F112E7F3FABCFBCC7A +:107EE000F5CB8D49C177813F9AE78DBC6F1A1DEFA5 +:107EF000E18A710E760ED0F24EA39A82745DC8E9C3 +:107F00004AF83DCB457C3E8BC590C202DFAD5C7F1D +:107F100019EF51578B57F41E3587ABDBD5EFFB6755 +:107F20007F00783393827F00FC59DF3F7BC515B813 +:107F300000F519E55FE27D5CE33D33EBBB6844EAA5 +:107F40008EFB3EFB56FE2E5A7FF0FE9B3B28BA6905 +:107F5000FF392F687B8F51391BB350F1C3D1CF311B +:107F6000CB0BFDD220C226047610A71F3CCF88F78A +:107F70001FEE22B85FDB651774F0AFBBFE49457D8D +:107F80009EB9703AFA5F5DAEEC089C33EABA5BC307 +:107F90007D3D8A0101E469E881C428F887541E3ECA +:107FA000B7C8C3E766FE378FDB7551DBDF81FDA9FC +:107FB000BC3F6AA0C5DC8BED12999EEE6AD0108E94 +:107FC000A1247408D6FD818E97E3E6EB37A7CF4650 +:107FD0009B9EEB9E80F81FEE8EC1FF2877BF74CC6E +:107FE00077333AE6BBE3D0D1FA6EDD7BAEE058687A +:107FF00077BAFC28BE5F677DAFCE4ADF3AA9F5218C +:10800000783B2BEDC0A7B8FE18F41BB37C2CD2290B +:10801000869E93008E31073EB501BC061D1FECE71E +:108020003C79A99BAD73D6F1D2CA3A0607E3B49F57 +:10803000E5D64CF70E0A1C457E89CA69BA8DC587FC +:10804000FAB6EFB7FF9C4B9DF32C5059BF14FF734A +:10805000004F06FE6F75F3FBEA7DF17F3BB4A3F89A +:10806000BF1DE63F00FCCFBB14FE0DFBBF8AEB87B4 +:108070002AD89FA27CF41FDACCB41C3AEE34D18DFE +:1080800072B06487C8F731D9FB5F863E59725DFDD7 +:1080900021B817B9E46702F2EB42FEFEE527FCFDCA +:1080A0004BEBB9C1F2B210EACBCB9F1F0CA33EAA97 +:1080B000DA652EFF6777CFBB975978DE172435AD89 +:1080C000F7BD4E2BFECFBBB9DE58E8B4C57B2FD72A +:1080D0004887D6DB4CE7CC33A6F4F483FEA0CFA6CA +:1080E000BD89F1B87F9509C4137429A510DE192044 +:1080F000854209F45BCCE5D7E86FD872F3FA9F1D8F +:1081000032DF43CC6D31DF431CDE6ABE8778D56633 +:10811000F33DC45161F33DC46B768D33E54747AE03 +:1081200037B51FB37FB2293F36FA4D53FBF1C7660F +:108130009AF213DABF676A7FED5BF34DF5D775549A +:108140009AEA6FF86899297F63F73F9BDA471731FE +:10815000FD78B8617911DC5B30F07278A96253A1C7 +:108160007CE9089B5A105B9EA66B059016E9E07FA0 +:10817000F5272F531C3F2A8A5DA78B896CD26F533A +:108180001CE67CD46DFE7D8F972C7235A47E52CB7D +:10819000089A1DBC240FCF6353F93AC6F5DBB10131 +:1081A000EAB7DFA07CD5469B206F952FE3BD019AEF +:1081B00086D88FADB0779F1F729AF9D4D78F5EF9AA +:1081C0009DDB3807D4CAFA53CBC64B263931CA3F98 +:1081D0002A8C2D17164FC77340FDF5ABF8165CB30C +:1081E0007D10BC3B3C0F53A3BCA9CC16F7DCDF676A +:1081F000EEBFD07FDADCC78EFA0CF07CCEF7DA2641 +:1082000038BF567B7B37FA511976335E7AF3EC5DD3 +:1082100063039E471A483EACF7C6FDB64534E1EB12 +:1082200036CE77D1DB33D3E09C41663FFE55A18744 +:10823000E9EB471B42D72C04C21187E95E7956B49B +:108240006E1AF839C3F879EB4DB6F8E7A0923C0CFA +:108250002FE9A048C15E50DD682F9C2B7FD70B4FC4 +:10826000C7DC680F2679E838F3C7B417B1FBD4BA76 +:108270007FE6E85EB80D7D94E50E6C02FD92E59315 +:108280008896DD179EF4DB832DF08E7863B2CDEFF8 +:10829000C67CB700E3D97F4CC8203A5EE39F458493 +:1082A000AFF1F075783EC8EEAEC7B8AB314FC2CF74 +:1082B000091871E60BBED98980CFC6AB7BEE07E10A +:1082C0007B9017DCC176E8F7C24619C76D9C2C98E5 +:1082D000EA8D794B9BBF8DF7BEB2DC6CDEE574DEB8 +:1082E00000B73D93C1D5F8A8403211AEFFBDF428C8 +:1082F000F835FB5CF8DE07C5C710C0C7393DFB7316 +:108300009B31793AAF9A41EEAD6BD19E89EFA74E82 +:1083100037E6A18F34D13BE32A33FCE24619FDC690 +:1083200045496E3CEF106E8872FA9AE7DFE49BF9DC +:108330009D5B295CAB4E88F8DEB6D6D1BAF428FD39 +:10834000AEBCCDE50F6B7DF17F4E63F052F8A77B9D +:1083500040DE364FC3F9E3796A80FF31813C9C0DE2 +:10836000FC172C453E186C23B06FD3C74EF0307904 +:108370009EED51D97B35BE722687BE85D76CA7FD91 +:108380009579FA5DF76FF3B075FF364F9C75FF7204 +:10839000EF075797B51F8554D445B43708A91F1167 +:1083A0006B47533D560EFD1B7931F1C705D06FFF6A +:1083B000769ABF6544F6E5ED34B0CF800F0DFBEC47 +:1083C0004E8FD9AE8CD1BB3FF430BDFB43CFC0F450 +:1083D000EE8FA1FDE9EF45E3DA35A94A7CBDF7B49C +:1083E00087DD1FAC531582E703FBD90FD8C9E5DA47 +:1083F0003AEFFED6A5CBF91F392E834FCDFAFEFCFE +:10840000312D11F454CA0742DC77B7862CBF6D3C7E +:10841000D06B9BAD7833CCF76716FE78684D9FF52F +:108420002BCCF1188E8BC76A8A479B098F3B3C97F0 +:10843000B00FBFB6BEAF30DFF3E9E4F8A67ABF09EC +:10844000C63B37EBBD22886BD4CEF91CF5FED71E98 +:10845000A7CCBCAE187E391D6705E0A173D69F7905 +:108460007CAE03E34AAB9EB92A11E25835930D7AEC +:1084700044F07DAAF3F939489773FBEC3AC0792EA2 +:10848000999D133DB7EFDAA310F7F8A4E158722CC9 +:108490007DCF3D79BC48A6FD9DDB7BBC48C2037700 +:1084A00061D33BD435177F5B1470F7DE4BE8E137BF +:1084B000075B8F363A597CE54138173786DABF6A51 +:1084C00012F2657A9AED5E28171DBF1DFC215C39FA +:1084D0003FE62FA659B24AD03316C17ED33C37EEC1 +:1084E00067F972C9C86CFA9D12AD87E3CCC4F96A0A +:1084F00098C0EF04B84E44F1F7023CEF7660F83EC6 +:10850000F143B2029EC2FFBD1A3C09784F3AAB0953 +:10851000891AC4778A6E1E4753690AD3BFDDB73AFA +:10852000F0F78C8405AFAA53A8FEDA3C93FD8EDDEC +:10853000F9630B92C01F695599DEF20DEBE163B44C +:108540008B07E76B371723E6757C574055191D924B +:10855000336C6B8A358CC7F9F398FE25521AFF3DB0 +:1085600029CAB71ECDA6431CD8F8CEC5BF2B52FCD6 +:10857000BFCE037846DBFCF04E8FFBAB6F38CA9260 +:1085800069FBCC28BE5F5E94C0E19DC3DE07EFFBB4 +:108590004EE345D37D18B5D4FC4EB727D0B414E2D2 +:1085A000FCD0EF6DC9F8CE8BB99EA2389196BB0B6B +:1085B000CDE5AE0A9A8FE147EB77D6F6865F92AEAD +:1085C0003238F63738100FBF6C50FD79948F0E3467 +:1085D000F8307FB041C334DA3012CB0F37F8312F87 +:1085E000DAF46C984FFAAF7F9014BBEEC2EF549D53 +:1085F0008CE1C37572E4ADF9808FDF8888AF15AF69 +:108600008E47FEDE349A8E3A86BD677332C6FEFE12 +:10861000E9F257D24A285F0DF9D1AFD34AC6C3EF6A +:1086200096B0F31770413AF61EEE7A25A0F993E062 +:108630007734C6343B86C2FBA4C15BC9589423FD82 +:10864000C589F0BB0B7B336CB47E9A94D7ECF807EA +:1086500080ABDE64E7AFE7E7331F9F6CD6AFE3BCC8 +:108660004CFF660AC5E3BC71F8097E5300FDAC39C6 +:10867000C6B907331E8954BFE1768AEBE6EFB3DF54 +:108680005F4854C7FBE1BDF7CD5EC3CEA9F7C5BEB9 +:10869000E7BE99FF0E44E2E1256817293EF63B103C +:1086A000290A7B0F8904934DEFEDCDE5FDCC06063D +:1086B0009AD0571FCFE6FD151D790EFB83DF9788F3 +:1086C000F5EF87F0DFC3D8CCF5D3743550EC4DED22 +:1086D0006D67D45BBFEB59776D21D10BF6430189F0 +:1086E00080BD04ED8A69BBD40F0302DCEF33CED723 +:1086F0003E0BF8CDEFFDDD937D02C3EB933C7D8A0D +:10870000FF4E49D4139807E3FB163C12DA0376CAEE +:108710003EBB06625274E48FF87E94F83BC501E7D5 +:10872000FC530FBCCFEEE5D93A1438BFB8D25B7C0E +:1087300013C45145A53E03F3F74E6F81FC839EFAA7 +:1087400087D8A3DDC537011FA4F3F706080400018D +:108750000E08AAE18F63FD43B34E65649FCCF22BF4 +:10876000BD37368732215F3F0FF808F28DB4BF7DE9 +:1087700049C121C0476EE186E6633742DE687F0368 +:10878000B6FF895765FE8F3B980DF64A4F5EA57977 +:108790004F4C5E6279E260A931BF9A237FC473D0E7 +:1087A000B507D83B5DA907660830CFD4FD3310FF6D +:1087B000E7D5B7BC2B348C878F60EB048B971BF409 +:1087C00030EEE1A6D983F77963F8619DD76CC7C411 +:1087D000DC27BC0FF0DDD31F8FAFCB36F69E4AF7F8 +:1087E0008FD8EFC60D037B5484B8B986692EDCA3FD +:1087F000A7FEC170125C3998D65FE3CD413A5EB5F1 +:108800003BFBCDA95A2F5FA7642977803E4EB5F870 +:1088100035D95C3F8F508B7F93482B370AC1B5F019 +:108820009E6C688FACE27D935D19284767B98E22F4 +:10883000F583315FCDEFBFCB2B836B47811E59C4CE +:10884000F46E5576A058A6DF573D978DBF0B67F0A5 +:108850005D5552246D9CBBF75CB791377E47E42190 +:10886000B5D509EFF218FB5AB5FB3764C13EFDC719 +:1088700087DE463B71496236C259D3765C81DF6937 +:10888000A96DA37C47BFFBD8D963C7A35FF287C894 +:10889000A06F02BEFED068C3CBDDFDD9552F52FDBF +:1088A000A6D385EA688303D39D7AFDD5E00A9CF0C0 +:1088B0002EB8C949F9E9F11C5D05FEEABCB71EF501 +:1088C000D8E38A3A0AF8AFD3FBC366E0E7AA24915B +:1088D000F3EB0F5FD6F3F87E3DCDEFB9B7EDA6BF52 +:1088E00068DF60A1D9FEA97BC48DFC41ED92DF0257 +:1088F0001FD56EB68560FDB339DAF1BE7327E81B6C +:10890000D45FE6FB991B05A60F4373581CFA72F758 +:10891000342BBE7491708CFDBD2491E9AB0A29847F +:10892000FB76155F7AB1FE2F1FC769BA0FDA771C85 +:1089300037D61BE354F78E837C52FDF661F4CF5F8C +:10894000BCDAB0AF75D4FF773EC5CF6138F574E8B7 +:10895000E741D9D027D4CFA47886E71E793E24F901 +:108960000879A947FFAC6D2EC904FAF6D613B37E79 +:10897000D2254AB79712783E747F73C9A438ED1395 +:108980002CED738CFC4FB17F2B3C0F3A7BF30EDA4E +:108990005EFA93BD270FF06DB059FA4B36C6DF86ED +:1089A000FD19FCB7C7BBFB6578EFE9A5A440F11042 +:1089B00066DF6820875B24157F87D1C0F31EBE3E2B +:1089C000557C798D09FFBD782F30959F6ED04CFB7B +:1089D000A18B172EC37B3F7BF83A564142EC3EDB1E +:1089E00023B9A67DD0FF0FC7D785A3B81F384AFE8D +:1089F000C6708C32E9815E38F24DE55F170E316941 +:108A0000766936EC53ADB1A19F90660B3972C06E9A +:108A1000FB5FECF71A203407E799A8616CDA57CEB0 +:108A200039609F07C6798E448E49E3409E746D0578 +:108A3000AC533F91D0AFA1E50E3919866ED5E1FD5B +:108A40002B2A95D85F4E75B08619F5E6776287AB0D +:108A5000A458A2E5E3D579B8EEE594DD5507F6FD17 +:108A60003677E1CF571393BCA27DB25A588AF6C726 +:108A70009AC4179B61DF383D81D9330279B1F95827 +:108A800046BC7A26AF2DF7BD7813C431B6AED4AE4E +:108A9000067F6EAB331C390CEBF93D6EFC3DAADC56 +:108AA00075E116F8BD0A71830DD74B3129BC6B2BCC +:108AB0009C177860841FEC8BAD60D740FB356E5CF3 +:108AC000FF5B1A42682FAFE2EBC0F6F5935438E72C +:108AD000DCE8969261BD6B91EB6F05B85EBAEF640E +:108AE000B3E33AD063FE96413CEFCB80754DCB713A +:108AF0008CE5F514195B576883C18534F2C3FF44D4 +:108B0000AD12D43327D10E6B742FAB043B8ED6BF7E +:108B1000ECA0787A3C99E385D7E7F4E8A593CDA05B +:108B200007C515BDF9123AEF1D3F637AEA09DA3F2E +:108B3000BC2B45E713827718BB4749E8872524C13A +:108B40006FC7D074740EFB9D5BAA17BDE8C7493888 +:108B50005F631F4919C57E0F1DDAC37A9390918315 +:108B6000FB98CA0CF65E83E271E3FD66E37756DD9F +:108B7000C4F8A7B37829DF677159DE4370AE5F8907 +:108B80009BE94E783721864F15CB7B0B1209CC071A +:108B90007B4B54CDE5BF49E4FB4A83D8EFAD0EB71C +:108BA00085D02EA35284E935248AF6D968D281F97A +:108BB00031E06DE6C2352C0D2F8E8D27BAC8E2BB91 +:108BC0000111ECC7B45B8D784CF0F544BADEBF966A +:108BD000C8E336FC778C536614E27E7D6612AB5F89 +:108BE00015C8BB0FECBC8D33A6619CC6B0EF8CF5ED +:108BF000D2B0DF16729857AB425C7BC1B0EB163A2D +:108C0000593E75B6FEE068886BB6530B341BEE2FE9 +:108C1000B3F86AF9E6E234B0CB161EBA15EDE44CAF +:108C200095D9658B36CE5082A3E1DEDA3CF4078A13 +:108C3000374C48847D84D54E7FE27585E867E2FB3A +:108C4000B903B5C7B6A65D3519E471AB8D1290CAEC +:108C5000FB4BB2EE1E0B7CB1210FEDCCAD09C1C6B2 +:108C600024DAEFD67FD6FCAB68FEA74EBDF0388C79 +:108C7000B33A81D5C3BB51C09B3DE712B6E1BBC936 +:108C8000FD8D6F3D97F052127B7FCAA8FF6F537E18 +:108C90007C7D0080000000001F8B080000000000A9 +:108CA00000FFBD7D0B7C94D595F8FD66BE796566A9 +:108CB00092C963F2220913C24B5E4E9E80224C126F +:108CC000C243B44C102A20E8F03490A7485DDCBAC7 +:108CD000FF0C043050B60657112BEA8462C5AABBBC +:108CE00041A31B35EA8080B8D66D44DAD216FD8FD9 +:108CF0004A1510488AB5D2FEDD65CF39F7DECC7C47 +:108D00009319F0B5FFB4FE3EEEF7DDE779DF73CEE1 +:108D1000BD73E912FC4D612C94A43056CAD8C151E0 +:108D20008CF58C618CA9DE2406CF4D066FD2E2341F +:108D3000C6FA7EA367BBE1F517666F92C3C6D82556 +:108D4000D12EFA79AA99B1A089B1B3CD6E161CC102 +:108D5000D8996633956B961F98C6A09F9A0E85B9D1 +:108D6000F2195BC5DA36633FAF3B9269DC55013DD2 +:108D70000B8E64F47709FE5BBDFC28D55FDDC9EB83 +:108D8000D7B20EAABF92314F073C6BF75A59D01C8D +:108D9000AE5FDF51AC691F4AD251BFD725FB063BFE +:108DA0009C8CDD5B3DFCBE2A789F565D62F6E1FA45 +:108DB000588EE313ABA8AF87F73AE6EB88B1AE77EE +:108DC000045CDE49828A4EACEDD0B132C6D63AE0C0 +:108DD0009F2EC61E50D87C6CB7F6F715192963C2B2 +:108DE000EDD62A9E0CC798F8706ABCA86781D48813 +:108DF000B2DA67C4F5355E34D2FBF30EB35F0763B6 +:108E00001EC9F43F702DAC7F26EB5319CC539F90B5 +:108E1000388E5DCD588B2571373E67BA0C7DA10821 +:108E200038303353717E33F82BF6EBC469479471B5 +:108E3000D83E40ED67D98EA90C4073C45E7303839E +:108E4000F737B090CA0A06CE0FFAFD28B2DF5923D1 +:108E5000B5E51BDDDAF2EC09DA32637E82D74F9A90 +:108E60009BCA4E1AC2FDFE04A6D611032EB70258A5 +:108E7000B17EED5E4BE064041EEB3B9235E5C6AE81 +:108E8000ACC0C988716AF11F59F05F135F779D58B4 +:108E9000F70746DFAD0EC05B3D0B1971DD40C146E3 +:108EA000EF58C6AC16E6457C1DD86FF1B012E8CF7E +:108EB000666EB7007C1BBBAB9525F0DE6A87EF3092 +:108EC0003F2796E16935F0FA8C05880EE08FDA3994 +:108ED000BD99ED5B15E413B7ABDAFECDE7DD00FF1E +:108EE000DD93024F953DAC2446ACA30ED6911E5E99 +:108EF000C739EB0765882F58CF6FECA5481746A6F2 +:108F00002485D7F3ADE1B55C0BAFC65D36A237184B +:108F1000E7BD4418A761A7CE6F84B2CEDC63447E60 +:108F2000B917E93C06DE721C4A4C3C6F433CC7E073 +:108F3000A7EDACFC3EE4C71CE41F18C7B6EE2765DE +:108F4000278B818FAA3717FAA0BE4D05FE86715474 +:108F5000F8BFA908C8D93B6D5532D0E9293BE7C312 +:108F60000D892E7AEE50BC0AE2355DE7C947FAD585 +:108F700027B843CCC1F1A366421960CBAEC162F9F8 +:108F8000BD1EE8EF21981BCB168409F078C8C2CB30 +:108F90002F39CAEFDD08E36E4AE6E50D3FBDB9D5CE +:108FA0003F09CA16599E43E5870C6D413DE0DDFF40 +:108FB00082C9F5443EB5F728585E3032F0044C4D76 +:108FC0003F8465235EA62642E720B7F42F9A769B5E +:108FD000A05ED0EEFB2784A75CFF39FBF13C362670 +:108FE000667F7E4D7F79DFAC3F18BF537775F8FB06 +:108FF000D4C49D413D6FE7C2762CA7E7033FF49FA1 +:10900000FEA2896D85E22306769B17DAD55D2C6377 +:10901000C10839D423F079B6D941725BBEAF43F9A8 +:109020003D06F9A987E4707D47AA46FE4AB95C7FF0 +:10903000F15A4D7F398E7CC257BDDA43F2ADFEE264 +:1090400064FA1E12F2F46C7326E989F8E30CD2C8B4 +:10905000F5F0381359B0F872E34CA2EF721CE6CB6E +:1090600022B9BD06E70C24A43782BC87712E0C758B +:1090700025255F469FD976029145AC679B1A3463DC +:10908000FFDBDC071CBE18FC20E544B8BD51DB1E2D +:10909000F4231B81F4ED6348B7FFAC7ACC91FAD48A +:1090A00066F038506FA8F68A232E37344D7E6486DA +:1090B0000A286951393D7FD9B681E8D16E701F41C8 +:1090C000FCDAED3A971FBEAFB7E93C48272D0E7387 +:1090D00000F1BD51B9C1817243F66B07318FF3B80E +:1090E000601B427A3DDE7AD58B89540F669219A9AE +:1090F0001FFFF7C683C5170F1C8FBD31F1880BFA10 +:10910000574B746E0BE00B91FA71041D44F763DF4B +:10911000A9C69C77743D09FFB8F836841211FEE7A2 +:109120006DBA198118F32E4D56BE9B9E5A1425DF39 +:10913000937F3B3C88ED95D00F0AF249FE9626A31B +:10914000FC2DBC9058E922399FEEB573B185E3B68A +:10915000D88E9A7DA48F98ED13D9BF3E3EFD49B8B5 +:1091600018DEAA64881F6004867AE34A70B02B4137 +:109170002FE29715AA0CE5D3403A6FA7F9F4D777F9 +:1091800043E711EB6F51DD0EA46BFD751E33CA99D9 +:10919000F58E39E6109437AAAED9F92087FADE02A7 +:1091A0007B12D6B729ADC81C8B8F5AC16EC4F92D5E +:1091B0004DD669D6239F661DE7DFE8F75B92B99E1F +:1091C00068DD3FB1C753129F7E40D279518F9BCB50 +:1091D00054C756589FDEC0E76B896307CA7EE3C158 +:1091E0006BCB7E0BC96975A83980F644F4789B5423 +:1091F000778F07BE6F82F9F8B19CC3C7DF54A23ADC +:109200007643D71657023347D437384B08FE176CCE +:10921000694C0FDF37213DC6989784D3BCE4EF68D3 +:109220003FF9A2E832F7B7C3D9100D5DB6C6A2CB9D +:1092300079A8374BF9FC993972FE4393BE8E7C8C2A +:10924000A69BB249CC837C9701CF76586FA7CA669C +:10925000EC437D80B6D64498DFCD36E600993E39A2 +:10926000B57C6732ACB7ACE78091213F743A691D99 +:1092700075A27DF4B8A6148E3F538A839E49C73DDC +:109280004F4F01F876F624B814F8D49902FA300654 +:109290007C8F08BC33D6C69F6A681CF28FAC5FB661 +:1092A000887976C3F350026B3583BDB24FC807C6C9 +:1092B000EEE74F151817C699FDCAE8DD642F8AF549 +:1092C0001F02B580F5D3D343E314FD77C0DB5E58AE +:1092D0007D04DEEACD21C2DBDB46DF6B089FC6E3FF +:1092E000A1742C771E3D9387F870B670FBB5EF25FF +:1092F0006B00E96E207ED6D3FCEA2E0E62FEE28180 +:1093000078AB5383A45FEB2EE6D17758B7DF9C127E +:10931000FE3E1B6C8609B02E66E67042F8C4C2475A +:10932000BBE06B890F50EBA3ED021F08A78FC43E73 +:10933000A71FEF4EE36606783F6BE6EF996724DFE1 +:1093400087097DFE51425E00F7331F0D07CE467A36 +:10935000505DE9917AA7CEE2B96F3EAC9BBDAB6799 +:109360004FC06359A5AD15EDAB65264F12DA5DCB45 +:10937000DED32BEBF30984C4072B043CCF32F75D1B +:10938000883FFF368BE309C29F76FF97BFA3BCF8E7 +:109390001D68BFA24BEF46937169A5CD8FFD96F571 +:1093A000543C6D87F72B5BAD2E06FD2E9BE2FE0431 +:1093B000EDBD65F7595C1BF271BF38A43C0BFA5D3B +:1093C000FB60BE03E581759D37D3EC0693E07EEB31 +:1093D0004C2BE06D93B264895208AC7D7FCA1615A0 +:1093E000F0ACFE57E56716285F757FC116F3758CE4 +:1093F000BD82B21CED59FFD09968DFFE12A746F678 +:109400002EB76F7F794427CAC55BA6820A18E5ECA0 +:10941000D4D960CE2B538AB79861FCF4144FA10EB7 +:10942000C65B93326126F6B7F4BEB17FDD09DF7704 +:10943000A4CC9AA9E613DE447BEFCCCAA1D06E92ED +:109440002CCFB354427F695616B6A72700BF0F0929 +:109450008F8FF67767BFFDBD60E6D41CC04B4553C8 +:10946000A50AFDBF9E72DB9631573136FE817287A9 +:1094700007C63F98B264A615F0DF6994F5976DF1C1 +:10948000C0589DCCF78601BEFFF1FEBA9966A89F31 +:1094900096EA2D74C0FA53CDF76F9991FB1DF865CC +:1094A000A412BD4F2C487112DF1C4690E6ADEB3381 +:1094B00072FD2AF83D87D3717F792494ED11E54C34 +:1094C0005EEEDC105B7E9C4EE572B93321F6778F41 +:1094D000904B00EFA00EE9B3CB1A18961F9627C049 +:1094E0004FE609C45FDBB93C01BE9A63273E8ED9C3 +:1094F000DF37E55F803BF5D3A97AACE8BF90720D0A +:109500006666C571BE4C7669E47559CF5292B7BF95 +:109510004A157CEBE2F071566AE50A33F70C47B85E +:10952000C8768BC53AF3474BFF52D088FCB9D6E2D8 +:10953000C9C0F9ACDD579EC12E6387D75D2CD7F823 +:109540004BC2EB984AEF07F40BFDB944FFEE315FD5 +:10955000075EC95780571A7DBFD23AC3FD69FD3BEC +:1095600003FBE37E9E017AC5187B9E1B53B85E41C8 +:10957000F8EB22E4DA4A215F416A913D7EFEC5ABF9 +:10958000766FCD8F1C7703F50FF87D7A0AEE2F41A9 +:10959000BEA21C2B533DB3B07E594F8A03ED79A078 +:1095A000B78D82DE54A43789E7CE94A6725AEF763F +:1095B000C5B13B861DF81339AF36C583F649C622BF +:1095C0009F7E49C4FCA4FC87FE3B45FF259C9E1F53 +:1095D000EDA7E7C5C83FC22FC4DC40DF6307CE5FFD +:1095E000C136CE08FDF5822580F39170FBB6F42FCD +:1095F000ED87BAB87A2A91DA651C0F26BAA09E21A7 +:10960000C5C5F9B9E3E3C46B515F75E999E2E2EBD3 +:1096100046B95126E5A4BFE748854A764C582EBB8B +:10962000C89E917233683687EBDFBFBD67C646942C +:10963000AB26BE2F4FD383142F0ACFE3E514AE2FF2 +:1096400027F89827961D7824D92EE508ADE3E17513 +:1096500095EC63589F5DE8D709213FF9B39E4C66AE +:10966000C23EE1F090FA7BB629F4AFDC4FA6A547E5 +:1096700059063BA5415710EE1FBFCF89A0FB63825F +:109680000EA2F1F35DE513C0C18F70484DE172C8C1 +:10969000096505ED0B15F417C0FF5CB5CDBD353F71 +:1096A00062DE362E8F9D7A1D976357E08BB454FE91 +:1096B000BDEF253BF173181EDC8EF92F01F7761DE7 +:1096C000ABC17DC1211DF009D2A28DAFF3FC8B5936 +:1096D000D4EFE7293AB9FEEF452EB71B613CCED750 +:1096E000643FD6BF3CA85D3B7FDEDFDC544E8F6518 +:1096F000C73D8568C70CF3DADCB85F28EB9973C007 +:1097000000E5E1DD8A036B4B3A1FDEC1F914A84B7B +:10971000C0E5AD6722FBB5A5723AFABED631FC387A +:10972000A757C4CBE2083ECD4DB57178C1FA4C08BD +:109730004F552B47E5F3FB9B87F78001D65B07F07E +:1097400040B12DE1D6D9B1648305F9F83873231FF0 +:109750009FEF58A21B8B78DDC9C8BEEB970F0FF0A7 +:1097600075487B14E8B203E9F2EAD45C1A6FD87149 +:109770008F750C7C1F867613FA953BEC01DC574CF9 +:109780004EF5CD4D4578CEEDAB64204A1AAC4DEB8D +:109790002D11EFFBEB77417DA2639F7E2CCEF3363C +:1097A000C6B6BAC2EB81A9FAD11F5A6F043E2DA0EA +:1097B0007210E1D669E4F5FB16338ACF34E8FB8CEE +:1097C000F81DF4F72CA2CFA3BA14C42FEE9BD06ED1 +:1097D000AED37B7314DCD76798DCA807601F42F414 +:1097E0007EC8C2540BF4FF263C514E57E9EFD88F88 +:1097F000F0AA2A50DC2D24AEDA85DC6041DC37CDBE +:109800009E62257A645FDD39B41AF5BF95E309FAE3 +:10981000318B7ECCE6A230FFFD3AEF2ADAFF48FD1D +:10982000764851A89F43D78DDEDD12B12FC2FE507E +:10983000FE1F52AA73EE40FA17FB3AB20FD3C27A58 +:1098400017ED95225B24DEFD627EA13CA4A3487B3C +:1098500014EDD37E7BD6DFB1653AC8D9F1333A82B5 +:109860003A0752D1F333FF01D65105F6AC05E0704B +:109870005B2A973387F2FDFA449CDF30583FBC3AAD +:109880009CE01BD3640B8F932EFC0FE946EE2F4810 +:109890004FE0CFBFA7723BE727695C1EFE218D9783 +:1098A000D31363FB2BBE10F55413971F5BCBB9FC8E +:1098B0008FAEB741F4FBADEDDE318A667F0F76EFF8 +:1098C00086546EF71AB95F88C713960AFA063B8763 +:1098D000F014B6AB783C50DAA15FF4CCA3F272F38B +:1098E0007BD9E8BFBFED9FE6DD87F4B6F2377AF2A9 +:1098F000579C14F18295C9BEF464DCBF27C4F6AB53 +:109900003C27D675BA99911FF8538C1B82EC3D8980 +:10991000714328AFDAF9E034E4BFD52C40FEE0E52E +:109920003B37515C707940612E05F7695EEE271672 +:10993000F858BD47AFF14BDFAE361993C784E977CE +:10994000459B366E58B3AB5853FEF6F669250B446B +:10995000C8A1B0FC9946EFA3FB95F41E6DA77ED479 +:10996000ECD2F8C397EE1C46EB97F5973137AD77FD +:10997000596B8166DEAC95F349BCF949BA45BBD455 +:109980001F739E46CDFB8F00FEFE08FFFFD25343A0 +:10999000691E2DA9BEFF40BA09CFC3CAFC1ABFDA9F +:1099A00024C727B05666E17E49A023FFE5EC81502D +:1099B0002AA7FF6F0FF7D171F605E3FEBFEE0BCAC2 +:1099C000267139CCDA14360C1EE3A76AEDB4BFA0B9 +:1099D000BE2BC5A795EB6B61472D5FA4AD7751D426 +:1099E000BB28EA5DC9BF12699F290528D7787F0D7A +:1099F000828FF3CF1C35BAA0DEF8346EC716393D1E +:109A00009750EF6CB3248E437FCA364B5E00F552FD +:109A1000FFFABA381D6D33483F8A3B03E1D6FE5F3B +:109A200077B6A888C77DB00F007958FEE841168A3E +:109A3000905337AE533CCB01DE7621EFEADC7C7DE0 +:109A400075EEA07128F4935DC7E795D3B15F5123FC +:109A5000DAE5D4087F5F9A41B3CFCCC1324E258D71 +:109A6000CBE39C9AA03214EA65EFDAA3A8D85F870B +:109A7000427A33BB0900134157D925DCBEB9B1A4E2 +:109A80005D5936260C87565DF51807E0A735DDEAE7 +:109A9000467D738FD337240DE7792218C4EDFCF887 +:109AA000133D2ADAEF3F757A0AD29C6138B8F48EFA +:109AB0006CD4A7D6137C9E6DFDFB63AE6728A24DC8 +:109AC000FEABDDDC9ED1B3238CDB87A4AFD2378C19 +:109AD00024BD27E7979E22F4453AF33D67A3FAADEC +:109AE0008CF0C9683DE91B86EFE6F62CC7775581F7 +:109AF000770FBEAFCAB8AAA805DE176C0BAA4BA198 +:109B0000DDCBBB62FB83CB853E81754CC2F5C9754D +:109B10005C492EC87A86387E0AC90FD619B1F71F5C +:109B200030227D2F7F346D21CEB76EA39199943072 +:109B3000FC7FEAF4CEC6F96477B42B081BE9DF9307 +:109B4000E34AFF1D7E47FEFCC828F996D35F5CFE02 +:109B50005FA7F72C8F94671B8D8427693F87E7C722 +:109B6000EDFDD5695CCFBEEAF42EC1F934746D27E2 +:109B70007FCFAA3D1F1A63F9ABA3F9E24A70546A7A +:109B8000F8BEA06EBE3980EB2F7F54253AA8DD6861 +:109B9000A43859DD33FBB89FE71EE6463951D7B1EB +:109BA0004F590EE3D63EB34F591101D74175010508 +:109BB000E733C22EF990CBAF68BA473F32DA2D8730 +:109BC0002D5C4E9C2DB7F91580EB5983AF0EEB9DA4 +:109BD000CDB2BAFDF9613CBCB96FFA11CC37B03FD8 +:109BE000670AE2B355B73BD30CF55A4719DD485F16 +:109BF0003F75FA36235C52546F27B64F4EB3BBD72E +:109C0000435B978915A1BCFBBA70181F4527E3EF8A +:109C1000E1FCD3857288DB9145C83F8134BBB4A792 +:109C200048AE1D36F0753CC7F87CFF9EEA7990E897 +:109C3000F8480A8D9B5D1754D09F9D7FE639926B43 +:109C4000B2FF309D791E89E4DF2BCFB3C388F45671 +:109C50002BE450F9A37B948F23E6FD4B30F4916EF7 +:109C6000B29F01BAB4D1F7FD33D3A83E33B9F0BDEA +:109C700042ED6AE1FB8A087923D71143EEECC3F584 +:109C8000D84EF41CE47227C8FD8D62BED1F87C1555 +:109C9000E51F7C9A06EA99DE1BFD23312E7A78486F +:109CA00002F527E54034DFBE2AE81CE5A5CE46FED6 +:109CB0005AB22BE5FC64BD2267C5FE3482430FC156 +:109CC000A17E974AEBA9327A87DE11C10FBF16FD3C +:109CD0001DB8F90323CAFD07FEFD5DA2C7FA36854C +:109CE000E2F1ACED5DE33CD447FEA7F46867CEE259 +:109CF0002601DBF1C2BB84A7599D5C2ED777EE53BA +:109D000097D9C2749A7FE6C0AD4867F51D2686FBD9 +:109D100022A0BFDF207CA2E954C247CADD78F8B494 +:109D2000CEE07294F98DE44785FD543EFA29A4DC17 +:109D3000FE7BAA4EF809F8FB0B69BC1CA61FDFA727 +:109D4000088FB0DCB5105FE49F293A60C67DB85B30 +:109D5000213F7F5A258767E4BCAAC7C6979BCE548C +:109D6000A137D450DE1C7B58BEF7CB7FD1FE0B81D0 +:109D70006F781FE4EFD910D4F372FED1F8CB77726D +:109D80007D1B83CEFE1BD711ADDFA43D20E9E6C9C4 +:109D90005DAA468FD89D46EACF0E1B739CC78E7274 +:109DA0001ECFD861E0FA6CC77A7300E5C99B0B78C7 +:109DB0005E997DA13188CF43BAA575F8FD50361F55 +:109DC000BF55A75B83E5D60D36D64278F5243A4BCE +:109DD000917E1219978F5C1E3EF03C9767757E5BF3 +:109DE00080C13FEB7C739753DC39CDE2C6B833F3C7 +:109DF0001D34CEB30FA42BD773FB8D2E783FAB83CE +:109E0000F39FC403C853A22FC90F12AE617872B872 +:109E10004B7E92F8F8BBF46703BD7CA7BCAA3DDA81 +:109E200078DCDB46DFD54EBECF3A6C70A19F86C78B +:109E300017E2D16FEDBAB7B34F821DB53AF32D7A61 +:109E40004ABE85FDAC86BF2709BC1738B9BEAF74C2 +:109E500072BAA92DE920BEAC3DD944FC6C9BC1E58A +:109E60009AED84561E33F6CF62BDDBA85D95B563CF +:109E70001AE677543DAE3870BF1F4F6EDEAEF0FC71 +:109E8000B84F77BD9188F972EC2BB0F2319E62E148 +:109E9000EB9DEBE472E2EC5E0038D17B93F172F65D +:109EA000FB95FA63C1630AC2B356C0FAEC3395134B +:109EB000FF847EECBD49EE61B0E4CF9EB9E9EE3F90 +:109EC000C1BCCFEE99E246F7655A8B97E8A7CF69F8 +:109ED00071E37E03C4F70CF417AEEF7823F15A68F0 +:109EE00077FAE9AB8B506ED78A799E795EBF0EE127 +:109EF000B2E1C97F9B8CDF6B034AAA09C7D9FBF883 +:109F00007F6763BEEA9E46F217B53CFDBA11F317B0 +:109F1000748176FE7E6F9203EB9DFEF9F6C908EF21 +:109F2000968E16FA7EE6E7ED543EF0E4BFBDF67776 +:109F3000F4E37813DD58EFCCF3FB092F753E95F26F +:109F4000DBE2D1F58E7DFBB9BC443D8F7C309FCBED +:109F50003149D7927E4F3F79DBC448BD21DFB70A34 +:109F60007F4E6B02D7239F09FEADADE0F1CECF9EB1 +:109F7000B5CCA7FD8131341CF7C57563385DDC2D88 +:109F8000E051D77187A1C146EDA99FDF02DFE373DE +:109F90002CD0E72723298564CF25CAD7F957AA0FE4 +:109FA000F526A0BFE7E6451F2A381FEB9826432D6C +:109FB000CDF369FE1D561DF9BD6C6D6C3FFBBF38BE +:109FC0006DC22EE07C90DD599DE3223960720F8BCB +:109FD000B087B36B7C2D1827BE7EADCFAD073CBEDE +:109FE0007CEAE8B441507E72A4524CF8D72B5CCF87 +:109FF000F96D344E3DFAC1818F760B3E497730F5CD +:10A000001A9203DC1F50A532D5467EAA3E9213F564 +:10A01000AD420FEE117E6E735FDE4D766A67BB2632 +:10A02000621F06ED6C362AF7E5FD10F34A67F8E784 +:10A0300093DE711969BE67A43C607EF27B4A7E8B19 +:10A04000F61BA1BCC1FCD1579DE55D281FE5333D42 +:10A050008EBFE4EFE2FBB8744F17CA15B63755A3AD +:10A060000FE2C99503379FE77AFB950F890E1B9086 +:10A070000E717CDF498DDE5E4EC215E8F0A50F89BA +:10A080000E977771F9DAD0556EC4FDD40EE1D76919 +:10A0900010F4847484FBE8BF3A93699C86C9A1E1FB +:10A0A00028A7CE0BBA3BFF12A7B7433A1DF9010E02 +:10A0B000ED1EDDDEA20CD48F4A8D97F0DD00F8E6B0 +:10A0C00076F3DAA36867D5D73037F26B43A7E0079A +:10A0D000B07B11BE0D5DD5CBB1BF416933C9DF0D7A +:10A0E00076C9B441506EA863A5C86FD9BB2A5E4239 +:10A0F000BA605D7C3F9E5D03F62CD24D5ABD5B9FDE +:10A100008F7A8FDBBDD78F2CA3F63B725D14E7F2FD +:10A1100057318AF3EF40FB19F55DD6686E3FFB3689 +:10A1200092DDC55C09E437653E750DD66FF02F6290 +:10A1300094D711CDC72F29B40F680858291F685626 +:10A1400017B77F1ABA381F9F93F0914F43CFADE4F2 +:10A150008F7FC1C4FC11FED0375F9ACEF5EC8B2601 +:10A16000D2B39F357BD8C7B0A0B785BC9770AC6D14 +:10A17000CBD721DD32769309E7B14CCCA3CDC0F526 +:10A1800046B2D00305DBF83CD474E1774CD789A7FD +:10A19000519BE7E2F0937FE19C188FC8225DE8397C +:10A1A00018BA7E7990F8A4EE19DE5F9AC9537867E1 +:10A1B00004BD4AFB289A1E0BC4B8D9BB0E2A284CF2 +:10A1C000B277CDD1F0F9F5352CD808EBBC7E972EBF +:10A1D00038651CD94D0B499EAF37B258F92A23D2A6 +:10A1E000B9FD5695EA2D44BF76D5CD3677A43FB953 +:10A1F0002AC1A3B3A01D5724FDD8DE128C1B9D4A93 +:10A20000B7BB116FE3D25DD20ED3D85B03F7DFDCAF +:10A210000EBCA1CD3F0EF71F81F509F329AE09DA77 +:10A220008DFCDC0E688FFBF7DDD7FE9CEFDF5BB8A3 +:10A23000FF020407C999546F09FA8F9D05DEB55CCA +:10A240003FD9DDB1D6F3AA93AFE7C0CDB716E23E52 +:10A25000B161AE8DF8E1815794A59CDE4011E2BE5C +:10A26000DAC7F983017F3CE1227A243BAAA1C91B0A +:10A27000884D8F9C5F1AC0AE423B1BE8710DB793AF +:10A280006D8CF313A74BB9BF47B91569CF4A3E8D03 +:10A29000E67B49BFFD7CFF35F9FDBC81F3E37980A6 +:10A2A00003D27B3F9DBFCCE97CEB7AE047F8BE153B +:10A2B000F8B12542FE47EF7F709EB81F90F2F61E60 +:10A2C000A777513ACAA1DD6F6DC650AB948F0D2FA1 +:10A2D0006F197E39BBCB8C95A15F33F06B24FD6089 +:10A2E0008CD65E444F3FEA09EBBAD8FE8FBBD26DE5 +:10A2F000DFCD3F3F302FE5AEF4D2817929E9A87355 +:10A30000106FBBAD01B48FA51F297A3E4B049F4946 +:10A310007CCAFD03C621B0FEFD82EF37897A8F88A3 +:10A3200067C4BE84F8C1A5F37D4879F671F4916CD9 +:10A33000F77DF9B5E438522F46D38D8CA3E07AAA85 +:10A34000C7C4AFD7B65FECCFA2E8F829C15F0B80D6 +:10A350003770DE6D86E017C48F77D819E513F8994A +:10A360002715E371AF8DE07C34B26F38B6B766FA6B +:10A37000BE44BA927E5D7C8F71AA5A11BFACDD6B70 +:10A3800008449E7FB93783D138BD76B35F0FFC9107 +:10A390009BE9DB87EDFD15CC1D443DF38F168A2B21 +:10A3A00081815B8AF2A691851211CEEF25FB5E209A +:10A3B000FAD5F70C47BFE33925340EDF9F10FEDADC +:10A3C00013C25FFB7ED77BCFBE02AD17BF726EF1AB +:10A3D0008F91CE5EB4E4217D9CB0F4E7BF25A1DD72 +:10A3E0007D81B9922E770E699159EF5523FC67272D +:10A3F000ECB1FD7F6F0B3C378A782B5319EDC3B757 +:10A400006770F9193EBFC4E3ADEFEBB4FE37F91C3A +:10A4100093C1E1DF19E71C506106DFD7740EE1FC40 +:10A42000D8D7AE50BCAF66DDFA3FEB412ED4ACB509 +:10A4300007E9099FD18EAB71F8833A289F3070B934 +:10A44000047F73CD6561FD07F5D449C8337E07C528 +:10A45000BF960AFDB5ACE9CDBFA15FA14665E6494F +:10A460004518C7F21E1E049F3EB52D4F44F1BFF2A2 +:10A470004777A6A37ECA58D426F2C1A63AD0FE5585 +:10A480003C37E82F592F676FA96427131D00DE1E84 +:10A49000CCF0F6221F2F4AE27EC145775A03FE0810 +:10A4A00079B857F06134FD7C10E7BCCD97191501E0 +:10A4B000EC6F61AAF76FD4EF9DE73472EDBC12FA2E +:10A4C000C523485F77D8DD4FF0EEF222F363D20563 +:10A4D000FC6B310E04A2B1B7B067F8BA7CA4E3BE3E +:10A4E000BCDFA15FABDBE4F0BBF0BB91BECB76F190 +:10A4F000E241F1E3402E23D247C34585E86169F785 +:10A500009BC751AE37A821A293A5661BE1B1E1A27A +:10A51000CAE9A9D5703624DB03EED7A47AD232601B +:10A520009EFE7B2725533C09F889C3172A459CE3E7 +:10A53000F832C3372803E0F79035F136DC7F5D3021 +:10A54000BB92308FADD108F4703575E73547D843ED +:10A550002CC7AEA583EEB7FE86F35A6EF61951AF3F +:10A56000AFF034D179B14549C152C79848BC4FD2F8 +:10A570005F1AFDF5F17E49C897F78D3C6F64209D09 +:10A58000733C6CCF10F5B239BFBC9FC76A9EC3E75E +:10A59000287842BBF787887291280F17F5D279790E +:10A5A0009AE097F7C7F17AD1E32C15E37C99E1990A +:10A5B0008C7082764123D2C76B163A67C44A40FE3C +:10A5C000A1BC5B934B762CC8B96908771827984CC7 +:10A5D000F54CA4675813C841C0676FA98BE0B3B5A9 +:10A5E0001CE805E341AF9A281E24F12BF11A8DCF08 +:10A5F0008519CA77CB4F1F18BF5E98513A307ECD70 +:10A60000D850C217D14B8CF31FF1F0F56B3BC70349 +:10A61000F0EBF20CD283C1B1917CB349C051CAB501 +:10A62000F713B478FD3C9DE3A15ED4BB84761FDABA +:10A63000D1EE3EE2BFF75378FDB402AE97A45DFEC3 +:10A640004F022E5FA66B9F52CF44FBD1BF14F2E2A4 +:10A65000CB74EE4707BCDE8DF395FA09E44C301954 +:10A66000F878D1EB2692336C631FE5D540BDFF83AC +:10A67000F05A64EABB3515F4CA0FC1DE311651BB7E +:10A680004B284706ECEFC748BAB033D4DBAD190E00 +:10A690006E1F94F4F1B8D748BEAEA50CE48772657E +:10A6A000FC630C210BE4F06B22BF42C1BCAE146210 +:10A6B0006717F60770FF978CD230DCA3C73B21E801 +:10A6C000E0D10C4525BC15B242C4DBADEF7E6E5F18 +:10A6D0000C5D9E13E765934DBE76ECE7ECDD6F9164 +:10A6E0009D7EC2181CDE668BF1DD187CEC2125FCFA +:10A6F000FDB6A7F47EE3D5987F7EF6C19B61DD4B66 +:10A700007BF46E1C72E93D5FBC331EEDEC1E03C58D +:10A710006B40DF6F5371DE4DDCAE3CA1D3D2C1671D +:10A720007769F73DAF0B7A90E772A5DC91FA7C155B +:10A730007373799390B81BCB1FDD713B9DCB5DCEBE +:10A74000BC873D00F7D36B66925D7C3BF3515ECFD7 +:10A75000B256ED39DB156DDAF2ED3B079CC32539B6 +:10A76000BC2A10FD5EF8A52B63EBFBF3822E3F3372 +:10A770008AF8FD7A53CCF8FDEF85FC09C7D9FBB404 +:10A78000F1FB572F1FBF6F8C8ADF87ED88E8F83DFC +:10A79000EFF713616F60BF9171FCCF2A62AFE3A343 +:10A7A0000C69B75835F9199F0CB05B12E97BE3458A +:10A7B0004B9CF9D8E8FD672B638FD3D73F8E365F6C +:10A7C00020DC9EE709C8FDB5A493C68B59A4676534 +:10A7D00059DAC7E17639F43DFABCBAF46F4BBEF8EA +:10A7E0005861E62CF2476D1776BC9BF2333F46BBAF +:10A7F00008F972BAEBB5104C71D98F270E578784C0 +:10A80000F9267A1D405F674211F2D898694F23FDFF +:10A81000EB666E3A9727E8FED6BBABE87CCFFFBD70 +:10A82000A73223326E2AF7530D46698FD934FA9630 +:10A8300045E9E3655D6F911D06F6D770143E7F7A9A +:10A84000F56ED2C32B99371DE9BDF7D511746EE5AE +:10A85000DBEA61399F9BFC4B0C3CBF358DEC8739A3 +:10A86000623E3775733B5067F618681C0F7339D218 +:10A87000698BCDE70B425485F275FDF347E71D6305 +:10A8800093C4FC156C0FF0BD4E3CD9525F26CEDB55 +:10A8900084E3EA310D269089CF96896E173EA7286A +:10A8A0005E95CF83E3791A6BCAC1FA3A7348CFD762 +:10A8B000093348C7F6FDF0A2B25D9437CEBD70EB08 +:10A8C0000A7C6FB3933C318A794CCF04B988FC6D14 +:10A8D00066665CB7C9163C4DF133F1F457B8888F02 +:10A8E000FD4318F9411258079D3FB5D9CEF971B112 +:10A8F0000EE650B06C715C08E27EE29CC3E6C7F3E2 +:10A90000C4202F6765A23F5FF9D54AC40BC867EE24 +:10A91000178AF75D0DF2F31142DEA588F9B50879C3 +:10A9200097C5DC8AB8C780E4DDFDF69537E07E2662 +:10A930008D79F7A3BC7B387106C5FD32988FE693FD +:10A940003A43D5C82DA7575BCE98AF46CB3B05E71A +:10A9500097E5D3BE37B3139497A404BD9997526972 +:10A960001F3612FD310621378E59783EC26631CF2F +:10A970003B3353886E8E59785EC2B7B65BDCDA7DA6 +:10A980007D430A3FBF7F3EDD6CC6F1C08EB913E147 +:10A990000776CC077E16CEDF2C9CD24179029B6FC6 +:10A9A00054DC1BE0FD66BB6BBD0AA4EB9FA9707F66 +:10A9B0008FEA28C77C9CF63C871BF3441B45BEF7F7 +:10A9C000668BA3F619F2639A783DD6B719E396ED34 +:10A9D0005B1D0EAC9756D937CD88FBAA15CCB19B21 +:10A9E000C5A0F7AF808F60BE3FC732E04911F46366 +:10A9F0003DE2BA85D620BEEFC17F17F0F29432DC7B +:10AA0000BFF2BF82EE423A77C93C7AD2978DDD859C +:10AA10006FD860BC82B985E4AFF756F2B82F1372D5 +:10AA200060BC1C57F0D9B561BAA7EF85A23CB45BF6 +:10AA3000F87FD34C3CAEEB8021CAC49143AC9FC697 +:10AA4000F9C1CDE41FE7D36B58F80FFBAB0CF74F00 +:10AA500072696AF87398EF60A822B3BBA50EEA8DFD +:10AA60005783FB91AFAF15CF42F13C547E23E9E50C +:10AA70001E9DCD65D4713E3717A0ABC3AB47B894CC +:10AA800039B6B4603FD729417AE6CDD8DE82D39F6C +:10AA900023FC4CC999C6009E376B99007826BFC825 +:10AAA0009F0FA3FF5AFF2FAC18F174CC20F59E27FF +:10AAB00089E7FFB9683DD50E3E5997CE337B2EC24C +:10AAC000F9283FCFC6D0748BF8FE97A9554997D780 +:10AAD000BB3C0F30254BCFE5E30C1E876D9C6FA66A +:10AAE000BCE546710F03537DF93F8CF0AFC8B8C584 +:10AAF000BB06367F5F8CFD464A16B707E6DCC0FD15 +:10AB0000C28D221F477E4FCCE27EB2BF644E7B37A0 +:10AB100093EC3D1E6FFD9D945F23D948945F11F225 +:10AB2000E58F245FCADF8E277FB4DF85FC99E72994 +:10AB300036D0BE40C82129EFBD22EF6801F31810BE +:10AB40004F3DE21E95A3E5AB480EDDCC7CF4FEF74D +:10AB5000153CFF0008D380FDDD34436B3FCDF36A25 +:10AB6000CB37CF8FB6AF383EE4B80B7CDAEF73A4A7 +:10AB70009D3C436B272FFA87AF9249CF67FCA2FE1B +:10AB8000D2E0703E5163543E5183C8276AEC2A3CA0 +:10AB90009416914FD4D8CDF3891ABAAE944FC4ED20 +:10ABA00029AF29B01FE324DE5AD294EC0D917F72B5 +:10ABB00010F34F8AC2746EAFB0F33C0CE6A1BCA296 +:10ABC0001C8795CE5DB4EA8AC88FDB9A68D7F8DD1A +:10ABD000B7AE7755613DE9BF95F9434837B1F6C344 +:10ABE000D9597C5FB343E17E74FF0233ED3B9D0591 +:10ABF0005E4D5CC1A967C7D1AFF86EA64BD6273FA3 +:10AC0000C90E832FAB189E0185D17989FEF67AB6DD +:10AC100091FC905172CA99EAA6388033692CF9F5F3 +:10AC2000E77517923F92D92CEE614AB8FF7973DB32 +:10AC300055CCEB69EC6E5797DBC27437364BEC435F +:10AC4000ACCC8AF4DAEFD77BCE447EBD6493B730C8 +:10AC50000BDAD71983E4BF8BA0577A1F4F5FDE2E24 +:10AC6000E8C550E15DB002E6D7FB8ED18DFB6B0AE3 +:10AC7000CC41FFCFBF944C7E49750E233DB5B19CAE +:10AC8000CB935EF493C13A3E4DE6F7FA6CAC66A402 +:10AC90005FCFA74C233A5EC502873DE847DB0574CA +:10ACA0001879CFD21E6DB98E7590FEA97B66003DD6 +:10ACB000937C94F2B89EB9F4068C1B746ADBB3A142 +:10ACC0005A395C28F447F1BCA92D98FF50ACE3F247 +:10ACD000912D770F9A43FBF5458E4F2C28727FA15B +:10ACE0005CCEAEEBB59FD273FEE77AA154F41FADF4 +:10ACF000BF4A853D3719E417EE6FA57D06F5A97C9F +:10AD000050D7ADCFD485E75922DA49BB50EA0B8939 +:10AD1000AFF2098CE179B5BBB2847C1AC28620BE41 +:10AD2000A17FE21305375829D4BF1FF785D78AF1D1 +:10AD3000801EFCA8BFFD3A7300E96BB3D244FAD27F +:10AD40008CF63F3CB72A3ED20BFF5EE3D7237D4C07 +:10AD5000644D37DD00F526997BAC28B7804EFE3177 +:10AD6000927E5A58306F9FA2A123FA7E36F9ED9851 +:10AD70007424F55AF0F7DC9E99C5BC74CF93E70FA5 +:10AD8000DCEE3AA8F07D26D89F07D1EE7A5B3793A8 +:10AD9000E864262C03EB5539B4F89F9EA92D47DFB4 +:10ADA0000FC5D05A284374487806549C4FF4BD51BF +:10ADB0001E29F79856EEE5B3AF78DEF896C33F420A +:10ADC000FF83751D1B89F60E58AAC48FD1F4B027D6 +:10ADD000EB7B8FB7ECC98A116FE9157EE56B58687C +:10ADE000E533CA407A3B7F689D3E33822E257FBC87 +:10ADF0006CE07913CAEB3CAE35C1CCC604112E25EC +:10AE0000DCFF28F9E31AA4D39430FD9589F787A4D1 +:10AE10007C19CC0623BD5DD76509EA013F85A2BF39 +:10AE20006B90FE8AC2F689DC77B44C184067F998BB +:10AE3000170EF64C01D295B44F8A958E163CE7FD5D +:10AE4000FC4BF7B6E07C23E8EA2D84C35905E88A79 +:10AE5000FC6A03F4ADF67B14DD49FC4B7BBA9C35F0 +:10AE6000D17E676E02D7B3C1EADB49CF82B824BA7C +:10AE70007B730EA7BB2AE621BA2B675A7AA9346BDB +:10AE8000CBD1740923EAB474E723BA8BA6D77874BC +:10AE90003718E94EEADBD42BD3DDE74877DFC58FDF +:10AEA0003990EE3ECF72C6A7BB687A93F26C9FC50D +:10AEB00051897675638D42FAA1F89DA12D581E51D6 +:10AEC0009F4F76F6BE6437D9DD8D4DFC7B498F47A9 +:10AED0008F7933056BC5F77C6F25961BD7C177E853 +:10AEE000BAF418CFAB197A0FFF5EB8A1E90DBCBF59 +:10AEF000A0D1CFDBBF7C7A339D870A6C16EDCBDB0C +:10AF00002AB1DCD8CADB7F8A71AEAB31BF2DD082CB +:10AF1000EFAFDA96EFE6DB6F6ED74F11EBDDA73CB4 +:10AF2000F706B56BE3ED6E3F6C4E60E427E0F6FA92 +:10AF300064B1CE29BBF83AD33EBE7E860BE86345AA +:10AF40009F9FECB94F74756524EFE2ECB3CB95B6D7 +:10AF50001C7C4E4739A647BCBB5BF543781C743755 +:10AF60000C717536F7D3C8F821E6295447D817571E +:10AF700067733B44D64B4F61747E8DFDCC4EFE72A1 +:10AF800019DF0C3EC414D407B8466197C48C774EC1 +:10AF90002F6822BB62FA6019E70CA94B61DCC24B37 +:10AFA0009F4F8BE5472ACBE6F6F329917721DFD730 +:10AFB00004F2754817FB9048E8FCF09077D09EDBD0 +:10AFC00097CC34E7DCF6E5F3F2D4ECBC7F6ECD0130 +:10AFD000F8EA9A54BCF78BE52994B7F2831E164C15 +:10AFE0004A1C38FFE92A0B1A290F8ACF7F658B513B +:10AFF000DC57C2E5DA3C813F366918D1EF5C81A7A6 +:10B00000EA6CA1178B5931CAA979026F3F343719FD +:10B01000B8BE6E3344C98F79D9283F1E8E6BCF6B73 +:10B02000BF47C9971A31EE4A61C7AF627DE43FFD61 +:10B0300044D8F1A71EE676FC6AD641FED3DE9F71A6 +:10B040003BBE1E9687F412ED07ADDDAB2DD77768BA +:10B05000CB0DA0DEB1FFC6AE28B93386FBA57B1FA2 +:10B06000AE2F433F64CDCE77C8FF5D23E54C402B28 +:10B0700067C040E772E6A151E4BFFAD6F2E319D8FF +:10B08000D59569F24BEFC97646F8775EE4792E0DD7 +:10B090008CFB117AED236FC17D2C8BD24FD172A521 +:10B0A00050C815E9FF90F25BCA9B42C6F514EC77D5 +:10B0B000DFF1609B283BEFE16CA1AFC4FE4DFA4D80 +:10B0C000A47D5488F611D2D7A82622BAB07E72BFCA +:10B0D0006DD247E8A5052566C47B9119F81BE1A64A +:10B0E000B78DF5D934F4F168F6E5F783DAEF51F46A +:10B0F00023F7630B05FDDC84911818FF0F721FB84E +:10B100008AD3CF5CE63D84F4F3FBD59C7EE4BEF0AD +:10B110009BEF033DFAC87DA0DC4F7EDDFD603FDD87 +:10B1200058C03E86E7B15CE917E0F1FD4685D3459E +:10B13000FD9CDF3D56C5C2F2E2683373AB8670B941 +:10B1400065A6C98C7E971603DF2FCD99F57ED9D2DF +:10B1500008F913B4971F40B8B16E27F977EBADDA51 +:10B1600071362B3D77FD11F7558F5AC9AF74E10841 +:10B170002393E5C2AE11940FFE9981C75BE57C6E07 +:10B180003FBCF7B510D45BB9EE9662CC2FA8550240 +:10B190002FD6C1B70FACBE7791BF6B7541712F67CA +:10B1A0000FC527E4B8F1FDBA7E92C7C6035C3FF72E +:10B1B000290994DF0BEF8747C6E9FE3888CBEFDC1F +:10B1C0004CDF07B81EA9475BFAF327F813B4301B0E +:10B1D0009412CEA708E74D707FCB5F98E78A79136A +:10B1E0001B23E204D03E66BEDB7921CF47617201AA +:10B1F000CC6765BAA717D77F4AC4854F8938E2A9BB +:10B20000441E57FC7B7F7DFEB40DE27AE894883BB8 +:10B210009E4AD1C69B64BD44F13CD96CF66E346045 +:10B22000BC9E793782FE703D646AA27C95451C5FA6 +:10B23000BD2F256BEE11C81A543E6A10B4FB99D38A +:10B24000AB1F04E32C6FD39E83EA15F7DBF60ABA33 +:10B25000E9B5F0A71C376B50F5286CD7BB80DFB37E +:10B26000DA5F9E28CB5EEABFF7BA10C9A3FEF28F61 +:10B2700042E29C3AF793C8F840BCF86174BC30FADB +:10B280009C6974BC7FB1E43711EF5F24E4D4E26EB3 +:10B290001E6FB8D5CC360F82EFB7756750FCB82655 +:10B2A000D13F5C13EFF75BBF519E87A4CFDEDC9EDE +:10B2B000FEF8F8CF22E2E3F5223E5A2FD7D7A95D58 +:10B2C000DF6401CFEF313E3E799073607C3C3A9F62 +:10B2D000E245B4330C613CAC7170B855E9EB2AD14E +:10B2E0004F7C6139A33CF7356F2D6B413FF29A2DAE +:10B2F000E296556177D70B38C75B97D3AB632E8D3A +:10B30000BF3E81B922D693E54BD194C9928FC83301 +:10B310001D5493AD699FDB3444537FF0BA519AEFCB +:10B32000F9FE224DB9A0F51A4DFD616D159AF2880E +:10B330009DD76BEA17B22149E46F3BA2475F12BB6E +:10B340002A3047F37DF4DE859AF69FB2A61D93A0BE +:10B350005EA7457B2F33F37B7AC69485F3A9C77626 +:10B360002CD5F4C3824A50290BDF33F699B8A7795C +:10B37000790F8F875CDDB55A334EADBE8EF0181D48 +:10B38000EF2D627DE4376E0828EE201B18FF5DD597 +:10B39000D54EEDAE64F7C878C8C64122DE97CDB26F +:10B3A000395D47D3858DECC30BBBF4E47F2C64C3BC +:10B3B0001F9A44F032B0806B20FE2E30EE17BBF0A7 +:10B3C0008CDD8D7945B7BFB58CE663CAD4D205DE76 +:10B3D0001F18B95EEB482D5DD8DD5A3A489AA0A5F2 +:10B3E000836878277BB474C142F0BFCBC03B7586BD +:10B3F000966EFEB7E0DC81F0B586E15B7CD0D3626F +:10B4000023B8F1BC35699F99843D141DD790764EC1 +:10B410007090B0BB453F322EB159F1935DD51F7787 +:10B420009C10CC0BE6A33DD5C4B85FC97B10E56F7B +:10B430000CBF24BD8FE79794709D9BC0F5672DF3DB +:10B4400092FC3E66E1FEA493D5ABC89FB4923591C1 +:10B45000DDFDD99CE9C2EFE8A77A57CA5318909F3F +:10B4600000F6298BF0D7AE068B1AEF1F8A86A7D27B +:10B47000AD04ED786E98754B7DE0A3FC150FDEED05 +:10B48000A989FF68ED5FE65122E597B487E5781258 +:10B490009E52AEC9714CAC499F897C1125E7D8C832 +:10B4A000E8F893D69F23FD41328E23E34CD1FE9BD7 +:10B4B00008BBB8558F71D2C1F92D78CEB7D8E1212C +:10B4C0003F6129EBB905DF4F3077B4A82EE1BFB853 +:10B4D0008AF5FB2FE2EAAB2BC4B56FF22BA147F242 +:10B4E00007C6B3657C1C96FFF11FA1F124C5958B9F +:10B4F000F398F3F20827D2D340BFA6FBF82BD08FE6 +:10B500005ED7978AF5AA30313D22DEFDA612A2F55C +:10B51000FC907936459EDB6F601DD36E217F32E84B +:10B5200049BC27A793FBBB5857B43DAC92BF590702 +:10B530002B41BAAF651171DEFCF0772AEB079665F7 +:10B540001ED295EC89A7F18272CAA3E0F9534CC8C8 +:10B5500041B9FF8CB7CF93F918F27E4F9977549485 +:10B5600023F8751C1B87FD03BF95E594A27F01F8A6 +:10B570005389E4C7FE3C25FA3E801FA3D62FF33142 +:10B58000F4F612F21B2D8B5CEFD78087B45B7E9CA8 +:10B59000C3E8E9C871D1B33EE1C46F3DF8B9A4472F +:10B5A000933FDA68840D0DFA135E1479811D5ABB3E +:10B5B000FD961C9D801BDFF75C095EF1F121F2F81E +:10B5C000043EBEAE1D26F3F8241C970C84FB0A0D26 +:10B5D0005CFBF78FFD705F110BEE122EE74A7B7E4E +:10B5E00081F8D2DB8FA523BC17A67A5763FDDCE375 +:10B5F000A14F145D785E55FAB394877BA14B4FE75A +:10B60000FF1AAEE372B0E1253D8986F3DD268AB3E9 +:10B61000D674BD4176E1D96610B406FCBD0C187233 +:10B62000D865FC0851F08EB74F92EBD99023F6E520 +:10B6300062FD32EF07D6B93927665E473F1CB4DF9B +:10B64000051CAAF46392F01C597FBE92DA97177911 +:10B650005F5FF43A2A7278FEDB29B3F73EECEFC362 +:10B660009E9C1DD85F95BEFB7036C267AD42E7BB9E +:10B67000A698F879DC2C715E6F42A8C98DE79933E2 +:10B6800073F87D66237EA4F7621CF9FDB577A6E00A +:10B690003934D9FF084547E747197BEE837F2CC132 +:10B6A000F8E62237DE6FBFD824EE2FBACB1A2C0073 +:10B6B00039F2BA91DF476518D244E766FA92F5E4A9 +:10B6C000D74CD3B3A9487772DEF2BCAD7C8FF701BB +:10B6D000605EB17C3FA5A5AF780DFA7B043DC875CF +:10B6E0004FA9EC2B6EB285E12FF33CA3E15325F873 +:10B6F00043EE431BF05E5BD0BFE7CDBC1C7DAF6D5E +:10B70000FFFE7458FF3D36F6C8B87E83C593341EDD +:10B71000F951DC6BFB17872789DF77A4BDA7F6BC3F +:10B72000C8B797BF5312EFDE9BFFCC51BE977B8209 +:10B73000E2E585CBBCFF7870694856997A359D73F0 +:10B74000F75EAEDE2BFFAD8FB9DFBE28BEF7DFD3CD +:10B75000F96AECBCC55EB1CE707E6188CE29F7E790 +:10B760002DBE547ED97B471AF03ED20838C8BCF6AD +:10B7700006BC8FB43846BFD09FCB76E57B87AAC482 +:10B78000BC1A308F3035F23DA7B7F03869222F3020 +:10B7900094887CFBCB2E3D9DE3FFE511DD8CDD31F4 +:10B7A000E69D9BCBE132CAA9121F8D0EF2FBB5E3D9 +:10B7B000D593E779E4B9D8E8F97556846EC5F9638D +:10B7C0009E72ACF11CB97C3F2BE7DD99C2F1D1F040 +:10B7D0009A89DF9BAAF27CF2CE94D04AE2138716B4 +:10B7E000CFC3041E3BAF0FE5D1B9B299DCEF108F88 +:10B7F0001E26A7FACA51BEC87BEECAD426C511C1FF +:10B800008F57A28730DCF51ABC0E84BB91BECB7E6D +:10B810004F1F157CCB3C36DCCF2D11FA6EC99E5ADA +:10B82000B287E57EE9F44E3DE56F9C663CAE72BAA8 +:10B830004DA1FDD0521F63EB402EAD7CA27833AA00 +:10B84000AE2599B09614FE1E7F1F66E9C6A8F8BA09 +:10B85000D85F49BD2AC75FBE4D6B17D7B06D7F4615 +:10B86000FBE9F4512E3F56B026D23F2B1FD0F6579E +:10B87000B367D6A738CFE8BC8011C28F372D57ECFD +:10B8800057CA5819EA8F354F7C6EC49F6089C71715 +:10B89000F8FB4F4387F1DF7DC227FE8E083E6FC95C +:10B8A000F5FC2017FD3EEFF2F9AECEF5CDC9457F90 +:10B8B000C9BB7C7E17EA2E703DB32B8DF45B8BFDEC +:10B8C0002E92FFFAC15CFEDF8BF735009C4C26718F +:10B8D0006FBAAE499F48F64D80E8EC43E71D737E92 +:10B8E00040657726F243DAD3D36760BFCEA7AD1E9B +:10B8F0005CDFD6724F21FA2FB656F3F3A166138F91 +:10B90000DF077E39F100865386766CAF40179DA322 +:10B910007B7F10FD42ADBA3F1FC6BC98D6C93C5FC5 +:10B92000325D17DA3F28623CA7359089F17DE768E0 +:10B930007E6F4E9ABEBC90CB7F6E2736085C5CE86B +:10B940002A207F62AF41FA173B2C742EAB8EFF2E5C +:10B95000C628C6F12FF3EA700E9176F1D966A6F9E2 +:10B960009D86511D4AD09048F7A8503CA86E4330A0 +:10B97000FD16D4674FA9144F93F34B7B3DAB02E305 +:10B9800066528FDDA238B8BF4DD8FD0B98FCE3712D +:10B99000B7F9829E16087BFF162B87F752E6CEC3B7 +:10B9A000760BCD2C5107AC764B654729ADB3D690BD +:10B9B0008C76858C1FC5B74762FBC91A7E61E7E7A5 +:10B9C0009E95BEE1D8C919F4415D863FDB853C698F +:10B9D00018CECFFFB1A1CC83F1CA86D746D0EF30C5 +:10B9E0009912783C1CE49619EF113A84FA1ED6BDE0 +:10B9F000EA158BC85B0A8873CDFCDED8C639394599 +:10BA0000741EF1781FDDFF71DE10CA23FE067984F3 +:10BA100037A6BE92FBBB1FE0BDEB0DD960D741F945 +:10BA200074EE9F7879486825DE1B9992778997474D +:10BA3000853EC1724E5EC26C2A178556EAA13C3E15 +:10BA40002F939771030A0436356FF06C3FDA2DC9D6 +:10BA5000C22E7087E8BC77C3CB237491FE58771E43 +:10BA6000976767843FF94C3EBB6D0EC27B64ECFA6E +:10BA70006979D2DE6EA3F5C9F5CAF62C3376BBFF21 +:10BA800010727E9538A73DC5CA5A2D3CFEE74F047B +:10BA90003C1CEC1E41F1CB7FCD4DE1FD3B42744F90 +:10BAA0008FEC27FA771CE4B8AB15FE7B59E7A3F2BD +:10BAB000BC7E97CBE52B8CB391C619EAE1E79BE7F7 +:10BAC000E41422FE006FAAC09BCAF7C9ED7C7ED0A9 +:10BAD0002FFEFE13E88762F4FB1FFC0AEAE787E704 +:10BAE0001D4D2727C538AB5A78DCB62FB980E869D9 +:10BAF0008A55DCF752A25DC7F83C6E9FBAF392C537 +:10BB0000791D09AF0C85C6691170CC090D9F33F6FC +:10BB10009BAFFBAFFF4BEB8EC09707EF6D39D8C5DE +:10BB2000EF371E9FC7F185F49C4276E0764D7F6724 +:10BB3000D647B59FC0285FAE21A580DADF2BEE6F18 +:10BB400095F7D961BBFC71DCBE45BB57DEA7C1FCD4 +:10BB50009359641CB2FFDE8C0E71BF70FF3A6F28E0 +:10BB600011EB7488753A22EF33ECE7CF637D79737C +:10BB7000ED03E9B81FFEFDFD8D2912FD69F83C5665 +:10BB80007FC8D7F1F072551E9727DF1B5EE43CA3F8 +:10BB9000E0D90FE7A8F94978227F53BB315ABA940C +:10BBA000F3CC11F43980BFF3BFE578E27ED9FABB5C +:10BBB00079BE387369E9BABE335F87F909B2DD0728 +:10BBC00078C0A034EC27BC214FEC2773584E9CBCA6 +:10BBD000476F9E33A67F91DE47EF277B93E5EFD932 +:10BBE00069FD1ABD4EFE7B39FE73FC7E836BA3FCA0 +:10BBF0003C188F7ACE166E17D62FDAF263027E03C8 +:10BC0000FD547D7938BF1253C5F3F83B5BABF34A63 +:10BC100067AB6077942455DC990FE5A6C7C693FC03 +:10BC20002E1954F1793EC8F3358F4DE0DF47577C2C +:10BC30003E04CB791379798AE77994F760B4CC9E86 +:10BC40009A15B62BEECC73D1B8FA4A1DDD6B67425C +:10BC50002306D6637ADD44F98012AEF19E25265D77 +:10BC600053ACF3BFF7F4D3038FBF4CC07FBAD01FE0 +:10BC700028FC052155E32FE84DE4E7CF7B5FFD92DB +:10BC8000CED7DC9BE75B9F07ED1BAD676FCD87F2DF +:10BC900006EB0714EF533C6087A01FC6E5608B607E +:10BCA000BECAD9AD5EB49FD86AB75925B80AFF1885 +:10BCB000DEA907F07BE5B5A77E3C880FE3C5794C8C +:10BCC0001472A0F1B5BFFD15E3C48D676C6E341B13 +:10BCD00027763F7C27DA5F13BBDFFE1BD7C3FC3C14 +:10BCE000909CF744F47FC2FB095D269AFFC4EEAB3B +:10BCF0005660FD6BDFEB2E403AB9EE44B005C5420D +:10BD0000EFABFF3E48730E887D7AD97CD1B8F1390C +:10BD1000098F3F01A093081E3FE7F0F88AF2D9CEC1 +:10BD20003B8F6E0E9193547BDE0AEC788A3B5F600A +:10BD3000096E8C7BC873FDD17ED5E3D5B03E787F8C +:10BD40005D1FCC20C29E9E72D10C82245C2E67C9DE +:10BD50009A72A5394B53BFCA91AFF93E3DF32ACD34 +:10BD6000F799AE424D79D6C8899AFA37BACB35E5FC +:10BD7000D913666AEA577BAA35E5C26087A67EF1C9 +:10BD8000912EEDF7634C8F78283AEE7E039FA5271E +:10BD90003DE49E2D3BD5F4063E27FE858323DAAF96 +:10BDA0007CCDC58E37F0BDF42B479F9F927EE69BDE +:10BDB000F5B68031B63F39532D08DF83A0D7F1F3B4 +:10BDC00053EF25FBFE807893E7A7A6A05F1990505C +:10BDD00075DBB99FE2EF325C58C4FD6EC711319438 +:10BDE0004F6E277FE57143D3B37FE47903B928F71A +:10BDF000AEEB9BAF59F7948B3ECDBACBD9AA283C7A +:10BE0000DDA1295739EED6D49F9EB95EF37DA66B8E +:10BE10004B149EB66BCA37BA1F8EC2537B149E9EBC +:10BE2000D27C97F4DD2DFC5FAFA1DF0A9E93423DEB +:10BE3000958887C9A7FA081F137ADA2A114FD71CE9 +:10BE4000EF207C9504BD95282ECB8E34BD81CF206C +:10BE5000ECCBB0DD81E64C7A1E6C7691FFEB70F393 +:10BE6000487A1E6976D3FBFF689E40CF5F357BE83A +:10BE7000F99FCD33E8D9D3ECA567477307D57FAEDB +:10BE8000B98BFBCF52FBEFDDC845BFC1795DA8017F +:10BE900023C68EC15B499E9E4F089DC7F2067FEB6D +:10BEA000ECA92034F0671D902F7F209E452E4FFB7C +:10BEB00060780E1ECCF8FD19227FA343E729443B8E +:10BEC0007CF4E30FDEA7E632B669BD37137F3A187C +:10BED000CB662813B2E9F7901EBCCF93C3D8B3A8A2 +:10BEE0004AE8BEF7076763B957FC9EE7E0C71F241F +:10BEF0003BFC5BC7D93D03E2ECA307C788B33F7B9C +:10BF0000CA65477FCFD1AF46D8111E4785DFCBC367 +:10BF10000A0DF83B1CE56AA101F5ECF138E7215464 +:10BF20005379C9E0525CB77B1EE5915F6FA0DFE1FA +:10BF30009BA3F0FDAFAC97ECE2FAA0F74613EDA798 +:10BF40008EE93C2B903F7A95BEC710CE373DFE144C +:10BF5000E9A95E7B5F1EC2AFFAF1BDBCECEC7B4C85 +:10BF60007147940D1C3E958F3F39DB6FFB5EE133CB +:10BF70001BD7110D9FB9831D7C5F11F4E4A21D2016 +:10BF8000CBC7AA3DF514572CF70CC3751CF59A388E +:10BF9000FF7AED8161E437F294CE8BF0FFF40C363A +:10BFA000D0FAE7A2DE443FE8427D20D6EF159E1F7F +:10BFB000CCED3DA213DC672EB0D2BEE0988EDFA39D +:10BFC000105DDFEEE2FBA3CFE2DC879C28BE57DCEE +:10BFD00054FFEC0BD05FEF5A0B75DDEB1D41F658AB +:10BFE0006F13401768BAF754D339FEDDE41620A169 +:10BFF00038EF2DF82FF8FE6CF79D5FFC06EA7FB056 +:10C00000D6EA261DE21845F05B282A2F4E3593FD0F +:10C01000B4784E6E05EAC55B44BCF056BB9A4E61DF +:10C020004335D9E8807E96DB0A370304D9CAB46A5F +:10C0300023FE64534DCE1D9BF1B97AE87623F25866 +:10C04000DD987D9BD18CAD07162E25F9177AA7199F +:10C05000E675DB3ABD8BEFE7E4F9DADA6F94F722A5 +:10C06000E9F798C84F0220D07E35C9A568F649493E +:10C07000824E1F182CE23163D9D84BDA78D74EE4C0 +:10C08000A3B38BDF191E271EA1FD2EECC7DF8A7B11 +:10C090009EA3EF4F91E33A5C7CFF75CC089489F640 +:10C0A000E442AE07C6CDFF7C4329AC7F5CB7434773 +:10C0B000790DB7D5BF8078B8D025F068605DC84FDE +:10C0C00037F9977CF01B424C9AE6DCF095F4A5BB5F +:10C0D000C75119A92F4B42DECA487D39A1AFAD1215 +:10C0E000F5A2D48FC1E61A218F9B488E1E6C5E4745 +:10C0F000E5C3CD7E7A1E696E15F2B88DBEFFAA79B2 +:10C10000A790C701218FF7D2FBEEE6F9F47CADD9F9 +:10C1100047CF85A9BED7116E328E3BD7ECA3BCDCCE +:10C12000430F9B18C6F12E749B288F0338E2B1474A +:10C13000D2304FC944E744A3F395A2E57C3F3D7458 +:10C140000EB8B7E56DE4F7FE3C23B41707C7A7A701 +:10C15000A3CC6547B9F4F1E0F324878EBA5C76B4DA +:10C16000A74F3E2ECA1E97DD00E53F0DEE25FD715F +:10C17000D4E7B29BA0FCC9E3BDFCBBDF65B740F9C7 +:10C18000D3C17DFC7B8051D0FFECE02F488E9533EE +:10C19000E520F247A5397F2AA80BD0D7E507912FD4 +:10C1A000A6672E998A7CB160B08BE872A66BFD41C0 +:10C1B0002CCF1AD9AEE215151E5BE1466C5791568D +:10C1C000AD62BBA939776CC476D3866E5723DBCDBD +:10C1D00018B36F23966F70B7AB689F2E4039561A0D +:10C1E000EE4796E57729A7653EDDD5DD5ED207E30C +:10C1F000BABCA40F245C2AE6566F42FF676397E23D +:10C20000C0DFA5A998ABF4273360EE6203DE930A82 +:10C21000F2FAFF3DAE77AC87753662F91A2AB7ADF0 +:10C22000FF06FAED7F00F6E231E800800000000032 +:10C230001F8B08000000000000FFD53C097854E582 +:10C24000B5E7CE9D2D64924C360842E2649924965F +:10C250002C43B6261064480CEE3001F944651910E1 +:10C26000C2164804EB17AB7E191A17E0698D6BD123 +:10C27000AA6FC4B5AFB6E461D458091DAA52D287DB +:10C280003A5510B47974A488F0999011DC78D2C72B +:10C290003BE7FCF766E6CE248014FDBE078693FFDD +:10C2A000FEFBD9CFF9FF5F008053F8B3027F603403 +:10C2B000FE38253D8C046804F167BFD16DB295034B +:10C2C000AC34078CA0A32F41A3AB1060AF0E9676C1 +:10C2D0001400A424C3FC7A0B968DB0740B96E75D12 +:10C2E0006803480568DABA206E8185DABBE36660C8 +:10C2F000FB4517E2AF38CE52056E54E0930AD49B4B +:10C300009C89344F9A4DD21FCAC76F8550784A0610 +:10C31000E8B79A3DBA048044937BAC0DC7ED9BFB14 +:10C320004E835887AF88D6316CBD1EEBE300326C6C +:10C33000561E1FCA8219545E09ED46C846B8F5CF8D +:10C34000FBA422DA97C52723844E435F205FECF9D4 +:10C350005416FE63063D54E07AE9036E6999D7707E +:10C36000206056EAF1673974EC706622DE5ED47E96 +:10C370006F04BF18BF43FB7D15E28DBE377569BFE3 +:10C3800003545B0F8D433002CBB8DFD912FE5E85BC +:10C39000FF0D8F874967C0C3A4A1F010B51FF01A25 +:10C3A000418EDED70ACB6EA673E4BEC09DCAFCD117 +:10C3B000088121F7A7F245F4FEDA05FEF502FF2514 +:10C3C00036E7745A5FDDFC389053008E6D35794D39 +:10C3D00099DCFFA93D2944179375832D9A3E5B5B39 +:10C3E0006783DE00B0ADD5CDD0D7BA14F476803FE8 +:10C3F000B53673F9ADD6162EEF68F530DCD9BA8EA6 +:10C40000E15F5ADBB97E57EB462EBFDBEA65E86F8A +:10C410007D91BF5F3B7F6586DB124DFFD5C9CE4561 +:10C42000C48F9E7BAA13993EB8F753C8AB9E1AC817 +:10C430006FB644C30183659D94C0658F11F7E1D940 +:10C4400016E36DC37DFD738CBB89C619A8097EAD4B +:10C45000437C434A80F1D030D2BD9ABE4B461C3A51 +:10C460008966F5E412FE0EEB3CBF0764D9569BD3F8 +:10C47000A5473E381A8F551700DC82650FCEF3783A +:10C48000AAAB85FA417EC048E39CA23F93717C0928 +:10C490006677F03A10A21C0EC408E8B1492C8FD17F +:10C4A00050C8DD40BA9FF960E0E91319B68233CB7A +:10C4B000C570F8A893AB039E32A46765ACC384D55E +:10C4C0007D12F8A412845346D6008ED3976ED413EF +:10C4D0009C14445650C7C39FC9DF226386F1CB1416 +:10C4E00048D4946BCDA335EDEBAC999AFABEF45CCD +:10C4F0001EFFD2B48B34EDFA46579AC5BC532F2396 +:10C50000D865746F5C80740956991C9BB0FEBD9809 +:10C51000F822280698161BBF89E07B31195E6A371E +:10C52000EDC0C914C07D4E937D238B105597DBC69B +:10C530006BC7ED995363C37657E65769D721C12579 +:10C54000B4DFAB1D5334DFA7575EAEE9EF32FB9388 +:10C5500008ADF5CE7ACDF7C696AF419F0C30B1E568 +:10C5600024E84B01C6FB3A34E394EEECD2B41FBF8F +:10C570001B6412EB927D8E3709961F74CAC42A156C +:10C58000879BDF2458F5A53F83F6014EB059519F94 +:10C590004B8ADC8347023D962729E5CAA0B72D8147 +:10C5A000E87012F2F548BF8930C2216363A9F2BF77 +:10C5B0004E101F4C5220003207F6AB164B80793AD2 +:10C5C0008BD798456A05E51BF5C106C991A6473882 +:10C5D000470E5450F928048A08CA3A979EF86B2AE5 +:10C5E000348FA5B209DC69043F4874BF4F7CDC2F4F +:10C5F00005DAC4E282C9C4CF753FFF68DE6DAC17AF +:10C60000621C265CDFEFBAFE914A6BFDBB3FF591E1 +:10C61000376C217E6FB27ECD7852CB8D2DC7197FBE +:10C620006AB96F2DCC77E192DB0D689F1036FEAFB3 +:10C63000CC760AEDDA3AA25323FCC9B8BA20D41E4C +:10C640003ABE18C47731EABF7A5AD304C2D7DF5D45 +:10C650004E6C576F1072089E45F54E1CA73E46293A +:10C66000834FD4A72AEDA1B29ECBE96A7D95686F6E +:10C6700057C77B58B41FAD9695F12E52CBCDA29CD7 +:10C68000A9CEF7A02817AAE5FF7071394EB43F6113 +:10C690009B55EF2908E9FF53AADD180FE3C96EA0E7 +:10C6A0003D9033C91E48BB1A981FA2ED85B65EB1F6 +:10C6B00017F37F237B8CC5448FCB63DF21B9EE90CA +:10C6C00080E4BAF17683D38BF37F9ED451B4C61243 +:10C6D000C2DFE7B7087CBB6AE39C32B65FF96ADE6B +:10C6E00026E223396EF7C885F8DD3A56C77AA74E99 +:10C6F000B63881E87BAFD0FB6AFF48D8D0F2868697 +:10C700009E51F5B2C4F3C16CFCC1F9FAEF1BF5F40C +:10C7100006C2598E3F9770939929F4DC48D4AD95A1 +:10C72000F8F336EA5933D23D251B9C3A6C9FF21A36 +:10C73000EA67A2F141BFD0C7AFC5F824149C958F1A +:10C74000BDC9F66FA18C528EF87B2DCF9D97897C49 +:10C750007A34CE9F4B7CDBD0B28DD7758DDDCAE3AA +:10C76000833558108ECFE2CC28FC979E01FFA53F61 +:10C7700026FE718203A4CF752874B4BEE596B778FF +:10C78000BFCB95EFAC5F3243EDB82C47978FC639DE +:10C7900032081F0E854E0774B60A055F5713BEFA9E +:10C7A00017FB7313B1ECF0F947BAD93EEC2A97881E +:10C7B000EECD7140743F2AF98BF60E41FF8ED60EF6 +:10C7C000B6CB5B5ABB18BE8473D0BA557CDD108DD6 +:10C7D000DFF967C0EFFC1F13BFA3F401A303FBAD98 +:10C7E000DA073C4E85FF8011C2F44C2BF125E2277D +:10C7F000A14BE2FA3AB92021A0A98F13FE528E7301 +:10C800003CF1E9CA19BBAA37482179981C0B1D31A4 +:10C8100049CCD70E85AF1DC4D72AFF223F96EA1117 +:10C82000CF6F9DC47E43E037C4BFC0F3A878BA3B46 +:10C830001AAF1B888EA7C1ABB6FE07C66B27FAC717 +:10C84000A43782AFC478376546E3F9770A5E557C32 +:10C850006F53E47F383C6F233CA79E7F3C6FCBB483 +:10C86000F1B891F81ECE3E45D2475DF710725A7E60 +:10C870002E723A2DDBAAF8DFE8771646D3FD6DA2BB +:10C88000BB5943F79E33C853CF8F294F91788B8480 +:10C890008D12B83A2CD1DF3FCB1C56DF9D173C4E92 +:10C8A0000ACED6F86793BF756BFCB329186169FD92 +:10C8B000D89B34E53AEBAD9AF697A6ADD5D45F6E2A +:10C8C0005BAFA9BF32FF014DF96AC763117EE6D3A2 +:10C8D0009AFA7AE76F34F5739BB76BEAE7B7F468B7 +:10C8E000EA1778FEAA29AB78DCDA0A1C2F6D6B35C3 +:10C8F0002BF1D3650CAB03FE5A12838B0F07D9DFE4 +:10C90000ACF4B7D7B24BB2AF83FDD1329FAB96C276 +:10C91000AA8A9DCD6F12F4B55A95782D8DE15BAD45 +:10C9200036D6EF3B5AF319EE6C7528F15A25C35DE4 +:10C93000AD4E254E73318CB40BAF66BBA764213D61 +:10C94000A6BDBC4407B880E97FF867C15E5ABC77D2 +:10C95000BC8EE2DC35CA5E8E577FB3FF36E4AFE3B0 +:10C96000CD2607957BB71F31D80AA3F965EEB732FC +:10C9700038C3F86C6ECB5F0DE467CD450FBA630822 +:10C98000399D9AA5637E20F703502FCC368321056D +:10C99000F5C1ECD992A30DF8BB079218FADC583F09 +:10C9A0004D0F3E1396EB2D7A9F299E97E632A33FBB +:10C9B0003D4B2C134C7AF0503DA424739C7E0D7D8E +:10C9C000B4A13C3865B818BFCF223F1CFB5D6FE9AE +:10C9D0003090DDBD6EE72FFA6FC37AB8D353CEF136 +:10C9E0003D5C6225FD2D793ED69D1A37BCBC2035B5 +:10C9F000E150185F4F25194EA5F8D1E17752DC7A46 +:10CA000093C1F19C2DBADF05CA7EA7C912FB6FC185 +:10CA1000D74DDE4D52483E717F3B4DB8CF26E201E7 +:10CA2000DA67B3C19757447EF676F6B39B2AD716DA +:10CA3000119D9A2E913E311585E29DA6962FD98F94 +:10CA40008FD4CF91F04CF190C36F65FEDBDFBA93CA +:10CA5000F9458D8B7A5B7D5C2E0BB86AC3E3A339F5 +:10CA600093FF4DA6B8A7EA4B11FF4C3CE9DCFB5302 +:10CA7000DC77A0D5FF2FE517D4BC829A6788CC5B02 +:10CA8000A87A64DEAD75096EDCEF9A2C5106F3943A +:10CA900074A6A35E4055DFDE9A156597EFC83ABDD0 +:10CAA0007ED6D6FFC0FAF96CF9BF314DD8D548BE55 +:10CAB000DF37E30503AD53E5EF48FE9F437D70FE8E +:10CAC000394D92D7837A7AF69276C344E9DCF97DC0 +:10CAD000B9E5A0888B23EDC2F7B60736A69B5C2B81 +:10CAE000737C61926F72501E44A5434734DD3ACF88 +:10CAF00040B7CE1F936ED176F1E0BC73B38BA0F13B +:10CB0000CFDFCB8AF2273EC83ABD1FA9ADFF81F720 +:10CB10006D1D6B63B87244EF3C5927EA457C620196 +:10CB20001DF2EF8057E6B87469667B3CC533501937 +:10CB30008C277DB7AC5B06F20F41EFD48F46FE5CCD +:10CB4000A2F0671FF83E247E5C05F77E4109982518 +:10CB5000D54BAE223DB7F40943084FFCAF93F32702 +:10CB6000AB947ECB2D9D46DAEFF267B5EDD4711A0A +:10CB70005F8AC81F575FFA19B0DDF073DE6F55A7E3 +:10CB8000B6DF77597129876259164B08EF67D2A72C +:10CB900047C9AE1BC2CA275B39BF203FF3E0039EE3 +:10CBA000B121FAC46447F1715CF6E9F9585BFF23DF +:10CBB000F3B11CF7AC91E8F97DF978BFDD9945EB4D +:10CBC00056F5F3A0DE79C3C47A67A0DC26F2A43759 +:10CBD000FDAE2D9EF8E40438881D162AF9D2856A28 +:10CBE000BE749D365F3AB9CFC779B94907BD6D713B +:10CBF00048F789BD1ECEDB55ED76B759B0FCD35D45 +:10CC00004E99FCA3F16FB9645AB7EADFA8FE4E480B +:10CC10008FE5B0BEE3BC6BF6D9EB3BD52EAAF63060 +:10CC2000D20E5606DB6BC9FE4DF8B6E34D82E72BFC +:10CC3000AF1E69F7DE8B137AE2A8C157BE97FC8C52 +:10CC4000D7631CCF41F4FAAFCB167EC64CCF02039C +:10CC5000CB1F091FCADB0C456EAE4F765F974DF5B3 +:10CC60008ABDD0999D06B2A37572DF23D7125FF9F2 +:10CC700065CE1BDE7CC707BFFFB5EDCCF98526EB83 +:10CC800071F63F868B339A74E0A6F8A2A4D6564A72 +:10CC90007E0CC56D944754F38A91ED9FB0D7ACC814 +:10CCA000E63C57B5DF49EBD928D6331CBD9A5ABEAE +:10CCB000D0E431879BBFA9BBDCBA304C3E5ECA16BC +:10CCC000F12ED2DB7AC81CA2F7D9F2C5FFB7F865FE +:10CCD0009A0C1E09ED6CA1E415FE2F083F780EF8A2 +:10CCE00019CE8320433758F97C6A2138182E021751 +:10CCF000C37CBBDB4B7C3360088E24BEEA7FF5BB74 +:10CD000002E29BFE8B27B657C1F93B5F8AF4FF0610 +:10CD1000C6DB78FE8157BEDB43FC397087E1ACF49B +:10CD2000C6EA646727F151E479CBBB53643ED7016F +:10CD3000FD7A968B7AABE80397A4721BEBD84CE68E +:10CD40008B90DE1CF5B4AA371760BFC24F74ACD706 +:10CD50006099E4B563D3AE808E45AC7071A657A6DA +:10CD600072A7A82F5C99E895B05C581523EA6F4A22 +:10CD7000F44226C5430196CBF900AC0F1780D08B47 +:10CD8000378293F78991419684FD176F3597703EEE +:10CD9000160239A4FF8B288E1A224EB7E608792F87 +:10CDA000CE12FABEB8469B17F9305BC91BDB6B4A43 +:10CDB000721056E738F7121D8B93FC1B1E2AA37CBA +:10CDC000900E36A17C7D56752B9F77AAFD1AED3506 +:10CDD000BD84BFCD1270BCE2E936799F13E78C2386 +:10CDE000C3CFCDF2EDB507A8DD115A7BF9F078C5B8 +:10CDF0007E1CF747CB9587D7574CB11BE7FBF14318 +:10CE000025CFCBE5FF79E6EBFA3B0BF84CC1437E2F +:10CE100072A3DD7D9CD76F04B0D0FA9F14711440CB +:10CE20007306E547973C65D2919FF1119A63C80359 +:10CE3000F81BC6DD04FF1BE367827FC7F899E02774 +:10CE4000183F13FC07C6CF04177F3B1E8322808D3B +:10CE5000394E4B4E79E81C3072BD861C81CFC1F92A +:10CE6000BB8D3C7F9DDDCDF81DA4F7EBE0A573994C +:10CE7000CD89C10B924EC36F03DDDFF0F9E9707805 +:10CE800051CF2523EBBF53E85AD4A967FB5FD415D4 +:10CE9000886F086B77418E91EB0B5F39184FE31F5A +:10CEA000B50EE2D729E196A7E944F982672D330848 +:10CEB000BF75766709ED1BE53C83F651D4F5C18358 +:10CEC00013CB787CAB64A375041FE5B821621F9176 +:10CED0007850F7B539D1BF81FA6F7E258B76827A8B +:10CEE0000784DC101F4943ED772DF3CF7453B0CC8A +:10CEF0008AEB9D7E4A6E1E0AFF75F6298CE77754F1 +:10CF00007E53CFC715FE52E976AEF21D391E906BE7 +:10CF1000847EE76AD2A536B24B27E3C92FAC57EE21 +:10CF2000197475E6BC47FBF4EC94C16E633ED6C839 +:10CF3000DF62855F5458D86D7411BD36771FCA59AA +:10CF40006461FAE42CC6F6B372EC9ABC6761D589C9 +:10CF5000C71F4AE1F6569AEA3A78BACE8AE3DF600A +:10CF6000DEFE366D69AEF593BA442CCF4F93761042 +:10CF70005C60CB9C9A64A3E57A79FD37E64FD94192 +:10CF8000227595A39EFDB929A464C2EC43AD3996E0 +:10CF90000E1F07CB75D6644DF9D2B4319AF697DBE4 +:10CFA000B235F557E68FD3D4ABF35EE528D5B42B75 +:10CFB0004E0A66515C87FB60B980E764AF5DA27D75 +:10CFC000EFBE621C96A73D3FCB416ECA66A57EDAD6 +:10CFD000965A2FD16300F1694487EA70E5FA471F3A +:10CFE000A2C122E286C6EE6776386DE710370C13D1 +:10CFF0002FAC00718E3F5CDC10192FA0FE7C90F4EA +:10D0000067F1ABD758DB70DCCD55272EB0E13EEF92 +:10D01000CCC13882EC8D12470CC73F837222D904F1 +:10D02000FFF4C8F0DC10FC03F00B851F059CF63EF6 +:10D03000FA3305DF5FBF7D4AFA8DF3071EC5EF5750 +:10D040006044BEAFD8E8786F0DE5A7DE9181CEF9D8 +:10D05000E124AE03EB1BE87739C4F7B0E8E9BB463F +:10D06000A7F0770FB9A6AB94FCDF1F7314BFAA71AA +:10D07000FB5DA3CB42F570F3279AF670BB74B7A69D +:10D080007C67A6B67CEF94BBC3FB0FE797356C5C5F +:10D090006074A39C363C2C39BD43E88BC1F5A428B1 +:10D0A000FAA17B09EBDB43DB97196D71D1ED57E1F9 +:10D0B0007894B76C18C6DEAA7AEA3A199A87AA7FDA +:10D0C000479DCF717EE7FB08714FF6CDF39AB0C351 +:10D0D0001F25B88DE17CB22F479C7BF43FF6C01D25 +:10D0E0005FD379EEEB22BEEA4F14F6A3A8F3339D8B +:10D0F0000E61F108C15F45D6808EECD2C0D2580FC8 +:10D10000A09C352D8BF3E88AC98F087E681E4F5E80 +:10D11000C72D0F9A91CE1FEB741ABB3C40C11696D7 +:10D12000FB9EFDD98C3BE9F702712FE97CEDB32F13 +:10D1300007847DAD117A631EF19F62B7005556D307 +:10D140005D3068C748CF105EA89C6BBFF5FD87C9EE +:10D15000CFEF117A83F20A37B05FE0B468F30D1DA8 +:10D160002CE7F8BB2DFC3ED759EB8FB7DA8D96F341 +:10D17000A84746D8B5798721F4C5FB57223D9B5E69 +:10D1800097F95ED0B1ADF60408D31F91786CDA2818 +:10D19000B39CABE5A35BE5CBBC6C0F8319F585D1E4 +:10D1A000F806A783E57FB555CCB77AD23733C84E9A +:10D1B000AFEED68B4B2FC3CDB34E065BD83C9BB79F +:10D1C0009996925D53D73F6055F449F75749530AF2 +:10D1D000045C3B847D45BFC090427E41BDC4F1EC00 +:10D1E0009EEE513584A73D12F86C253CC435665C33 +:10D1F000DF4C311C7DB7505E14D2F2F99EA51AD7D0 +:10D20000AAF1ECACEE5976F2633FEC5CB807290763 +:10D2100093ECD9CC4FD78287FDEE3D89AE74CA938B +:10D220004C53EE3FEC490CF691BFBD6752AC44F74E +:10D230001970FC3B697C755F7B0CAEF466DE9792DF +:10D240002F75FE443E157BF671A2AA67EBE4DBA7BF +:10D250005C49E7F773C04AF1EC7459F8D5F04721FF +:10D26000CFAA5E6D92FC496CAAED33A6DB114FA3E9 +:10D270005A7EA9E47DDB35F700CFD6AF1E8CA35FC5 +:10D2800094987F563944BCB1AAFAF347AEC5F95712 +:10D2900061BC4FFEDDC2AEEDFB087F91F1FD607C0D +:10D2A000F52FE67BA3E333D732DADFCD771CDF73CC +:10D2B0002D44C769837181EA5F3E17CBE7D6A85832 +:10D2C000857C28FC7A645BEEDE35587FE42F0666A9 +:10D2D000D73727FDEAE8AD58BEF9B958C6F391240F +:10D2E000F0901D39B229CFEBC1064B74C15EB26F0D +:10D2F000B0258ECF693E7B32EFB72F517EF2B776E5 +:10D30000F643487E6CE8C27C46F78FE8FBCBA3B9B6 +:10D310001FB8C5BC0D8A5CCA2F14DE5F4DF52F24E3 +:10D32000737E42A5DFE127639C14AC7D05BE222BF2 +:10D33000B2DEE792E710DD5B5CA17B69BF847CF91C +:10D34000D508F706DAF7F2C7FFF3C389B89FDA17F3 +:10D35000AEFE5515AE6FD907A940E384E83AB4DFB5 +:10D36000706C6BB6907F053F2B5E8CF11E0CD32743 +:10D370002B3B1235E5A6AED1DE83617A68F09E7252 +:10D38000A3C4E7048D8A5CED37BADBED94D7A5FB27 +:10D39000A94C3F711FB584CEAB08FFF79918FF91D8 +:10D3A0007CF6A25D396756F33CC9604E23B9750B14 +:10D3B000FC0DDC97B789E2319F3D49F13B82B933DF +:10D3C0000AC3F9B377D51B9CE731897B8F31439F23 +:10D3D000EB77DA13B97D83F94B4D9E6955CB094D37 +:10D3E000FE675501B01F50D2662BBD89CE8714BA97 +:10D3F000DC9FEE7A8DF1DEF1C0ABBB189F4FDCF203 +:10D4000031CDBBD3C2F4835D4A3C16116F3598BF52 +:10D4100050E4EF698D7F7EE8B1BD4594FF38F4CAD2 +:10D42000B822CAD32E94FD877E9DC9F79CF6DF866D +:10D4300070CBCEF7392F1EB9DEA87B0C92D0438D6E +:10D44000B48F64BAFFE37AC7CE722EF4C3810D8520 +:10D450008C3F351F3D7064E878505DA73ABEBA3EF8 +:10D46000757CB5DDDFEC225FD06FF41791FD5F4175 +:10D47000E73061FBEA8FF717255AE8BB55F81349E7 +:10D48000580EE3B77FF5BC2AF27C6AF05C56C947B8 +:10D49000EDD3ADFD9911F9AFAFE321833B5CEF7E96 +:10D4A000CF732A75BDEAFDDA7EAB85FD9B937625A9 +:10D4B0001F9F0EE9D40EEB1D3EF2BFB7981CE4C7C8 +:10D4C000279A5C908BF86934FAF8FE9ADA2FD1E447 +:10D4D000E6EF9179F9814423D0BDE58154E5FCF76D +:10D4E0002B60BD4271E8169CB7AC56D7BCC512D2B2 +:10D4F00087AAFE2C1B87DF0BE81EA93EE42720DF4E +:10D5000094156BDB87F6A32DFF7BAEA06359B26E3B +:10D51000C838B92457C8651B74C8429E851D9DA88C +:10D52000E01D0DBF1CEED7AC52F4FC40BCD9430744 +:10D53000BB13B78A7BAB13F5BEED04510B404B1206 +:10D540005D99F489F1BAB4FA9C6CC81CB6CBE3D8E7 +:10D550002E4F50C87DB7D4CCF75B43F75CFD32C18A +:10D560008B21C8D009563D412403C34BC0C5702A46 +:10D570003433BC0CDA195E011D0CAF023F43F8894D +:10D58000AF0DD81EDC6E65FFE9F2253AB2CB65D748 +:10D590000EED97CF52F0353C3E50CB579C3B3EA60C +:10D5A0002AF77287C5CBD87CE67B152F26E24FEC95 +:10D5B0001703DE34829320C0E34C2646CEA678DDE6 +:10D5C000C6F77E6BC1C9E5BAB3C44765C0AD77176E +:10D5D0000C8197DAA1F9649EC22703B9C0F851E91A +:10D5E000F548AE8DCB2ADD30504C237B104D4FC813 +:10D5F000A07596C5D61CA7A722B73F5F36538F7A72 +:10D60000B4ACB4660DA9905FE64E15E589352FD30D +:10D61000517DFBF3978A72714DA9C1815EE8DACB27 +:10D62000665E82FAD9ADDC2737A311A07B6372B6A0 +:10D630003817762BF7CA4D72E65ABA2F66BA0D58CC +:10D64000DFB86300FCECD722B791BCB8451C7BB3B4 +:10D6500055D0AF3AD67D4B2ED933B32FDE8674B872 +:10D66000796DDD28B29BF718C5F89FA4DAC6BD8195 +:10D67000F83299C4BD5675BF58EF89C17240B2AD3A +:10D6800069C90CAD4B5DC759CC7BD7E9E6CD4F7767 +:10D690006F203D023607C7156314FBBE65CBC4344B +:10D6A000F430701D565E47202E774D0B56DD91EEFF +:10D6B0007A84C61B88137CF808D1297578E8CB7565 +:10D6C0003E943BC4F781B5DFBCEA23BDF4292E04A8 +:10D6D000C7F94DAEFB715A47932E90518AF4FB4522 +:10D6E0002C7A000521BE96909873100F6D4EF01A9B +:10D6F000595E947736CAF9992A17038B713CC44F47 +:10D7000099CB558BEE2254CC6E7E9360A5BBBD1693 +:10D710006B689E17683D4D72B081F8E468E207C6F9 +:10D720004F596EC70AFE54F459F7B69EDBC688A25D +:10D730000BC2E4B269DB89AFFF86746F3A66715041 +:10D74000F3903C3EB6469CE75A34FA4695D3095DC1 +:10D75000263E389CB8F5A2C5D46ED207BDD9A4B771 +:10D7600027F706DAC87D1EE8DE3B46C889EAD77F80 +:10D77000239D8B7DF9CC8CFC914010F9235E9C831A +:10D7800073FCF48A38075FADE43DA9ECE17D8B784A +:10D79000548D3B57F6BC2DDE8579F06F05BD2B12FD +:10D7A0007F963E71E355C46F91EF8BD478B449698D +:10D7B000B7A2D77B37ED27F2BD5113C5A345C3BF31 +:10D7C000376A7AA296E3D1C8F746BDB94AFE4AB194 +:10D7D0008FA0F8A14B9436B43F0BC78746AF09F72B +:10D7E000B6FAC9350E2B95D32D0ED6C7573D0EE18F +:10D7F000EDE18964E619559E97AD93D8BF56F15A6D +:10D80000FCBCC949EB287E7E14FBCDE8EF8B7BE99D +:10D810004A3E91DE12D07B83CD89C12CBA67BAB95A +:10D820003BDF41FEF81F5A9DF00F43687D6A3C5074 +:10D8300027BF544BEF878E2DC2380B3FADEE79A634 +:10D84000CD8CE5D5EBE95510A584F313C8AF2ADFDD +:10D85000298397C601EF43D5083B153937A5E9C0A1 +:10D8600016868F18DB08B00D910F3029F48BCD4F41 +:10D87000D2D4C7392ED0F44FA8CCD2D4B7C588F7AC +:10D8800032E071FA0B2A42EF48129D3FD1F4830037 +:10D89000FEAD08BD17B9277EEA4E7E4FE26FE03C31 +:10D8A00045F265259AF62679AB4CFC5DFDA55E43F5 +:10D8B000CF9F52A61BF156B91BFD1C9C67429FB619 +:10D8C0003E26E001EA17B35BAFC94B986CDAF285EC +:10D8D000794A9E622C8CD5E42906F12EF8FED86197 +:10D8E0001DF34505E4FCAABA8CF06C00AF2D1A6F4D +:10D8F000C740F85DC7C65A1CF4966A42CFCB32C9FE +:10D9000041AA4B8BFF51B3B5F81FEDD6E27BCC5249 +:10D910002DBED39BB5F8BEB0458BD74C8F166FD9B3 +:10D92000EB2668DADBDB6B34E5BC8D5768DA5FE445 +:10D930009DA1298F7BF17A4DFBC28E859AFAE2AECA +:10D94000E59A7A95CF86E383F1BED511FCA603DD77 +:10D9500069F8A074E7CF35F3FD50F49F9FA7E80561 +:10D9600085FED72B76E5DDF8C3F792B84E8B157A96 +:10D970007030DF506DE078EE3D5B726D1CE905C5DF +:10D98000DEB9147B07394F89B255941D7E71BFA251 +:10D99000649FAB36DE46F72CC4FD8A8AC3EDB50919 +:10D9A000D43EE21DD6F44A4973DE1DF92E6BA667FC +:10D9B000AD9C20D1BD44713F31F21E84FA3EABDEF6 +:10D9C00019A339271FEEBD969A5FC278018C142FD8 +:10D9D000E8CCFC3E31DA1F726C94D95F73B3FFF66A +:10D9E00067C9CD79A76BCCFE0CE2EFECB1EEF5790F +:10D9F00088B7A33A878DFD3DE5FDD6006D8CDF2FFE +:10DA0000F5CCA43CE90086BB94D7D4DFB36326BD34 +:10DA10005BC4E55B031522ACA63F8FE6B91FA4717A +:10DA20000E48D6BB4BB1EFBB133ECF207B66A27333 +:10DA3000FE123EFF7E382FFCFC7B14EE0FF56D408E +:10DA400067F3F079EECF258E533EA7C1AAC2E477E3 +:10DA50009D41794F2AE2B6B90ABED4B86D8E32FF25 +:10DA6000011C6229EAF3B95D7F66BCAC48EB53E266 +:10DA7000BD668715C7BF71ACA584EF7B394B1D22EE +:10DA8000DE57E3B831F2F7B1B367BA87B522ED8854 +:10DA9000269E86979287CC5746E6C542FB16E31F23 +:10DAA000581FCB76E8C0FA74CE3F86C63FCAF985C8 +:10DAB000B9CDDAFBDDF35B3ED2F0DF02CF279AFA75 +:10DAC000404AD03006F71F7875F4D41B107FFDAFA5 +:10DAD000982A289E45BAF5E49587C60FDC97778982 +:10DAE000F01BCEB4CFCF791DBDCAFD5A759FFB5B2D +:10DAF000F77139D01A88B8EFE4D1C4BF2A34FE09CF +:10DB0000F2C98F0E4A231C43E57366E78B38A95789 +:10DB10007977DAABBC3BED55DE89F62AEF427B958F +:10DB200077A1EABBDD5E099C74BF648EE47A6A81EA +:10DB3000C4EF760FD13E9B96078BE85D635371600F +:10DB40009E24F3BBDD23F47D8877BB459295F46971 +:10DB5000EA35F46EF7F008CF51B2D8D9F989D75029 +:10DB6000BC70D828E4A3F4C56F66D27BBDC753DD73 +:10DB7000C789BF3F95641FF3F3EB129F2B8333607C +:10DB80009C7116EF7ABFCB13E73427F3C4B9890A27 +:10DB900047E60BBD564AB09CE8726F2EBFBBDA68F1 +:10DBA000E27757389F5317761F22F27D5CC91F4DCD +:10DBB0003ED21F6ADE27215F9C37D3BB395A67CA22 +:10DBC000FD26F16E2EE0CFA07776740FCA45F2BD28 +:10DBD0001B9CE21D5EDEA6F0F73009F9CA3DBD458B +:10DBE000A079A7B7B2E7C07ED227AFE5B993F353C8 +:10DBF00043EFC756C66F677FAF20DFC6F3E27A797F +:10DC0000FFA817EE24FA9CC77C61567E79F4FFD7F3 +:10DC10006038BCF52FF63F5A90197AF716F6DEAD4C +:10DC2000203F2CAFA7AE3F34CEE9E542CD7BA9E53E +:10DC3000438FDD934B72867411F948599A3F63887C +:10DC4000FED3F305FDEF4F774DA0F997378BBC60FE +:10DC5000886FDA6FF998E8DC6319F23EBFDA3F7239 +:10DC60009F2BB7F5303E709FF3687F61FBBC8CF053 +:10DC7000A5EEB3BF7BEFA305B673DFDFF77D776E4D +:10DC80001A81716DD2507976B43E617E9949ED3F2B +:10DC900056AFED8F0E39E5B1BB48DED16FE954E2E6 +:10DCA0001EB2CBC417AA5DEE54E22029B083ED0268 +:10DCB000CD4B7271B7E461FBA8E63BDA24B47F94E4 +:10DCC0005770AF617B215F6871105F7722EFF94970 +:10DCD0001EF4CE58CE7347C4D73F8B75DF4478BC53 +:10DCE000F9AF35A328FEDEF2972B94384ED8AB72ED +:10DCF000853FCB697EDA474102F36D99B2BE0A7364 +:10DD000033FBC955E091455E43C993ACDFC1F1DFF8 +:10DD1000FF011A14AFAAD043000000000000000069 +:10DD20001F8B08000000000000FFFB51CFC0F00374 +:10DD30008A739418187A351818366B32306868313F +:10DD400030883120E46885AF7153A69F9B9581810F +:10DD50001788F981581088D73331306C60225EFF04 +:10DD6000115104FB9E2003C351207F1990EE1466CD +:10DD7000605805641F03E22F40BE801003830C101F +:10DD8000FF1561603005D2C1406C03C4C745F19BEB +:10DD90007F82807CBC082ABF1B8D9F278C5FFF255C +:10DDA00011FCF20F08C863C33216E4C74722057A94 +:10DDB00007023729A2F28FCA33303C546060D05139 +:10DDC00082F09B91E4ED8062C7E421EC2992C0B817 +:10DDD00007CAB5286237772A50FE0450CE4B8934E3 +:10DDE000F7DCD341E5AF3484D000BC3E14E4A80393 +:10DDF00000000000000000001F8B08000000000071 +:10DE000000FFE57D0B7C54C5B9F89C3DE7EC6E92B4 +:10DE1000DDCD262121BCC22601440DB8400CA04115 +:10DE2000370F5294A8E1A1A2226C782421EF22F6A8 +:10DE3000621FBFDDF088C4521B1FC5D48B7651B062 +:10DE4000D18B3640D058175C9E458B6DE845A0D5E8 +:10DE50007A13405E06B240A5B645FDCFF7CD9CDDF6 +:10DE6000734E36266AEFFFF6FEFFDB9F1DE6CCCC35 +:10DE70003733DF7CF3BDE69B8964BE91D88713F20C +:10DE800025FC6E25E451891092184E9B3C93C69F49 +:10DE90009409B1ED7E24EA3B99840C9E6B7046D1C7 +:10DEA000A25F08644E4B0621C9658D7546FA3D791F +:10DEB000917DBCE808C319987CE4BABD09840C7252 +:10DEC000D3F66682BF2FE97F3FB737C69174C87912 +:10DED00085A231E1FA4A9ABC48FA7B87AABE9B1414 +:10DEE00075A6DD48FBFB51FD20B785901FC3784622 +:10DEF00042A9CB40B2E8B8785D6F2EFD3F3A0EAF35 +:10DF0000CDE85B2910221A1CB1442424262348A002 +:10DF10009DBE9F673CEDD74908A736AAC84AE74986 +:10DF2000C8B49608F57289807888CD76257BE97823 +:10DF3000577D2EE2BC570D22A49DD62792D34E6862 +:10DF40003A95C461BDC72D2306427ED5AE3F120768 +:10DF5000851B9B19245E15DC060F210E13C5AFC768 +:10DF60008CE92A8F9DA7C9C4710D21AB3D0E4C577A +:10DF7000794663FAD8D027DB7306D0F90C32D8E99A +:10DF800048488363A6DD91118627C72D30E73809FD +:10DF9000C92629AEC4545A2FD140C84D84DC42F35F +:10DFA0007523081949EC8450FC3D93BC2CCA9D0193 +:10DFB0007907E6450371C37C6332032E91E22DC6D7 +:10DFC00069CF951CE1EFF81B80DF5F782C15D6C177 +:10DFD0007D1BCCEF19E2ECF0029EDD46E7265A7F6E +:10DFE000A5EC4C5E4AE18A46DA2E83ADBB94101E46 +:10DFF000DF4CC01FED8FCCC9D5ACD730184722B449 +:10E0000073DC05EB6471B2755A097415611DE6F293 +:10E0100075586577D919FD384924FA11ED5AFAB1C6 +:10E020006468E98F7EB19FBA9EE769BF4D42ED3BC0 +:10E0300053E93CBD4B0CCE4DF4DB60A15100F80A16 +:10E04000BC25C480FD2AF9416552A063B41A9E170D +:10E05000CBE9F7F60E73CFEF2D06E252E872532AA2 +:10E060007C77C4CEA0E3266647EC4C6BCFF187E902 +:10E0700024D925C940EF0E4C1B0447AC00E37C4774 +:10E08000249B049C7F72A4F6FFD3ED08F1E17A375C +:10E09000F07554DA513C203D791F8B463C88503452 +:10E0A000390CE7171CCF17AD454F434A48E3685872 +:10E0B0005F9A5F87F463A6792BE69BB0DC1ECA3FAC +:10E0C0008BE5C9AC3E5D5EBA18BDE3555917DA6EF3 +:10E0D00003C29142705E44389650BF9B303F2094FB +:10E0E000FF25D61FCAEAF7B71F25EDCE0D9EC2F950 +:10E0F000BF2E3B009FC2DBD6C0AD942E0E6E107CAF +:10E10000269A0FEC8C41FE757EFD0C9F89E267D745 +:10E1100038930BEA9FDF9883F9BCEDEFDB245A5E5E +:10E12000B55D94206FD879D6D641F15B636A7FFCE8 +:10E1300066FA3DB85D242F6077D3719F9DE2B448A5 +:10E140003E63F9922896ADDAB06B1EC02D6B339109 +:10E15000280AA7EACDD23B6FA6F9D20332812A550D +:10E160009BEA8C83697E894F6881FC8A9D1F603F92 +:10E17000DDB9A40CF6F739E05B942F75DBDA93EE8A +:10E18000A6DFCB7D5B0AA07EF966C1094B5CBE7E33 +:10E19000D78700BFBC551E2152F815CD31C4A1DA76 +:10E1A0002F79DB17DF09E3AD7A472694ED91B2AB07 +:10E1B0000F199118A44623E0B56AD31346E09BE7F4 +:10E1C0003C07B01F059F552FD37E68BBEAD70427B5 +:10E1D0004CADDAC0F8CD8537A3E6BC688179D51996 +:10E1E0004741FB371F3542BD525FF1EB510E18DF3F +:10E1F0000663018C73FD0663898A6F5634FF5633BC +:10E20000AE534DE903DD19BDAFE739CEB7957C3983 +:10E21000154048DF92CF3843C5879E33C421FD5750 +:10E22000348BC411811F78DFE7FB608795F103BE53 +:10E230005E4BEDC01AC2EB75C9CED74F0A66CD88CA +:10E24000C0E71EE7F2A391CB8F27417ED0F4692E61 +:10E250003FD671F9D1E471E2F7673D93305DEF711C +:10E2600061FABC671AA63E4F11D67BC13307D38D26 +:10E270001E377E7FC9538669B3A716BFBFE2598E8A +:10E28000E9668F17BFBFE65983698BA711D3AD9E8F +:10E29000264C5B3D3EACF7BAA719D3364F0B7EFF39 +:10E2A000B5A70D53BF2780E94E585F9A063CED98FD +:10E2B000EEF61CC374AFA703DBEDF79CC1742DC74A +:10E2C000BB2D9BE448146F36174139185FE8CA919B +:10E2D000693EBE88E593E67A738C349FE4A6798A1A +:10E2E000C7C195811C13CD0FAE65E5293F24B966E2 +:10E2F0009A4FF1B2F2B4B5AEDC289A4F6B64E5A345 +:10E30000D67B73A3697E948F955FB739901B43F3D7 +:10E31000D7B5B0F2B17E9267A1F9B101961F7FD057 +:10E320009567A5F9F1ED2C9FF5A137CF46F3591D5F +:10E33000ACFD4D5D81BC589ABF29C8CA6FB94AF27D +:10E34000ED03402E0B98CFB5E4E4C7D17CAE9DE53C +:10E350000B86164B8E08F4B753EE5808227C86B015 +:10E36000D125517EB3D3D8F110157D64A1F0AA4B0D +:10E37000A2FC3320934550FEB0F03A96078C641906 +:10E38000943F2ABC8DE5BB650796FF5C38C0F2461A +:10E390000796FF877008F37B651796EF10FEC4F2AF +:10E3A000461796FF5E3881F9FDB21BCB3B852E9652 +:10E3B00037BAB1FC49E953573EED2FDFE09E2EDC22 +:10E3C0000872DB5D8672596A49067E59CFF9FF04EF +:10E3D00040062DAF1F644439B8F3F3AC174581D321 +:10E3E000F600C897BC04FA0585335B48047D82C2F9 +:10E3F00011FB8673CB179334706EF9A24C81F32016 +:10E40000C289EA1F9C9D5FDCA41DCF17E50A9C1200 +:10E410009C97B57FF3BAE5CB6CED78BEAC54E0D4F5 +:10E42000209CB8FE8D27204FD4C009C8A50A9CE5C2 +:10E430000827B17FE37119276BE0B88C4B1438754E +:10E44000086750FFE0048C376BC763AC50E03C8634 +:10E45000781ED6BF79B94C53B4E3315529709EC2AA +:10E46000F1A4F60FCE6EAB163FBBAD21FCAC473826 +:10E4700023FB37AF5C9B163FB9B6107E36219C6BF1 +:10E48000FB0767B74D8B9FDDB6107E5E43FC8CE9C2 +:10E49000DFBC7263B5F8C98D0DE1E70D1CCFB8FE86 +:10E4A0008D676FA2163F7B1343F809209C1BFB3737 +:10E4B0009EFC242D7EF29342F87907E14CEE1F9CDE +:10E4C000BD495AFCEC4D0AE1E70F08674AFFE695A3 +:10E4D0003F508B9FFC8121FC7C807072DCCD4CA96D +:10E4E000A470ACBDC3D93F4C8B9FFDC342F83989A2 +:10E4F00070A65238E97DC32948D1E2A72025849F20 +:10E50000F308E7B6FEC1D99FA2C5CFFE94107EAE38 +:10E51000209C3BFA37AF82E15AFC140C67F8B955DE +:10E520001A877286CA4E27D8E7DF199AE31232C1DA +:10E530004E6279D1EE24A0F7888A3E43DA5D22AD9F +:10E540006FD91C37FE31A2D66B728D064ACF56AA00 +:10E55000E5A9F59AD849D11A3D2ACE15AFC9274C5D +:10E560001BACA99F5894A6291F38E73A4DF920F70C +:10E57000784D7E48D94D9AFAC36A7335F9E1CB6F6D +:10E58000D7D44FF5CED4E4D3D7DCAFA93FB2718155 +:10E59000A6FC9AA6724DF9B5BEA59AFCF5CDDFD7BB +:10E5A000D41FD3B242537E43DB639AF27181273585 +:10E5B000F909079ED5D4BFB1FD054DF9C463AF6815 +:10E5C000CA27776CD5E46F3EF36B4DFD29C1DD9A08 +:10E5D000FCAD9FBDABA99F43FE53AB6F9B3FD0D417 +:10E5E0009F6A3FA129FF4EF2273A3D556B1FAFCCE2 +:10E5F00021CCAF3288D9AF01AB11F3C6C11666A7E3 +:10E60000584B1C2729FD18772F740CA0F4033403F2 +:10E610007651CEE0B26B3AE8F7EFDDE4BEC64EBF0E +:10E620007FCFE8BEC11E41BFA1F4269064481D06FD +:10E6300048F5E58FCA8CDE73875C1DD549DBD7189A +:10E6400082A3E268FE2331E73EA0C7F90603EE830A +:10E650006891D442BD681341BBE9D1D4AC17BDAABF +:10E66000FDB06618D5338430DC35B23B19F528C3CC +:10E67000F83AD09BEA87D1790D2664D18A71BBBC68 +:10E680002368FB6125C9E08F3019993F24D4BF91DD +:10E69000F69F81FD2F81FE6B7AE9DF943649D3BF67 +:10E6A00039A54CD3BFD948FBB713F290E126DEBFA2 +:10E6B00019FD36CB564CC6FE4D2965D8FFA3466AD8 +:10E6C00077A9FB8F0EF5FF8881F6EB3130BBB9C718 +:10E6D000FCD36ED2CE3FA55C3B7F239BFF4A432EEB +:10E6E000EF3F1AE7BF6A450E9B7F4A399BBF89C13E +:10E6F0000DF56F0BE1BF01FAFF692FFD9BD2B3B59A +:10E70000F31F5EA99DBF89F5FF94E176DEBF05FB8F +:10E710007F7AC56D6CFEC32BB17FA3C9ED04FA31BE +:10E720000E89AEF5D1FEC9506A250D0472A1FD40D7 +:10E730003A3A1EFD08771AD2701CDF8B66F47625F4 +:10E740009AD21BF2332FB3C37D947352BBAA9AD3D0 +:10E750007AC5E61C23F03D2C4F2264311FEAA23615 +:10E7600011E99B3C6DF28DA4E3BDD0267A21BFE870 +:10E77000E9293EE0AF352632BF08DA492400DF3F01 +:10E78000FED99817D4F3D2A78B1BE55391FC45DE35 +:10E790005C32BA968EEF0210812A7F9CDA71601883 +:10E7A0007F48ED1E42ED9F1332EBEF236AEF41BE2F +:10E7B00083DA7B6838933AE657F3BADE1F41C75FC6 +:10E7C00044949F0BE7792F6E290A4F62FBF7F85AA2 +:10E7D000C107EB317F790C457E783CC5DE044DBE28 +:10E7E000C6C4EA076F137C2F0808C30DF899C1E16E +:10E7F00011182FCDCFB1B3364777DEB15FB0D17DE1 +:10E80000B466085D8B309C59C4250FA4EDEF5E56AD +:10E810002C836BA75D1086819FB066A14C02683780 +:10E820007B134906270E3ADEFBED0CFE0C977C525B +:10E83000ED479B239B5D45743C738A451CFFAC6987 +:10E84000DAF23FED8C7119C6D274CD53D8CFDD45C5 +:10E85000DAF27BE768F3F7B9B5792A576590AB0F21 +:10E8600094E9BF53B42481DF31F41B00E37C90E3CF +:10E87000E1C15AD9AB59576A761B95727084B809B1 +:10E88000CE0BDB8B3DEBCF5FAECD177BB5F9856B48 +:10E8900074F039DD9CE2EB7F1CE883A6A7813E285B +:10E8A0003E4F72FA08F3552D7DDC139A06A30F65CF +:10E8B0001EA724B604A7D633FA58DC1813991E8A6B +:10E8C00043F4E052D397420FF3383DFC99D34369A8 +:10E8D0009396AEEE23BED5C9B4FD036B77E13A1D26 +:10E8E000118A193DFC40A1870E0D3DB8393DE8D78E +:10E8F0006F1EA787798F307AD0AF6707A7878EA65C +:10E90000CB3249EBB9AE741D3479BA0EBA75B7A3E0 +:10E910001F8AAE47447A58109A379D38CD2FE46548 +:10E920003DD68BD30396A701DA09E209DBA7F7AC42 +:10E930004FF984265FDA1479FD6BDA36AC3DA9FA1B +:10E940005ED5F2F25AB57FBBA2798B26BFC4F7A67B +:10E95000A67E69D32E4D7E71E33B9AFA0BD71CD26B +:10E96000E48BBD7FD4D49FBFBC5353FE60ED594DA3 +:10E97000F903651735F9FBDC7FD3D4BF778EF0132D +:10E9800075FEEEA2A89FA8EBCF9A16A7C9CF700D6F +:10E99000D2D437ECBCF62EA0C783EF8B04F48F4F94 +:10E9A0009DA7D1FFF9A95376429D931E07EE83538D +:10E9B0009ED1989EF138719F9CF34CC2F442DB1EAD +:10E9C0000BC8152A474BE0C8A674E596BA35D9207E +:10E9D000D709CADF8A956FD4798712B21494638AF3 +:10E9E000EFC22623094C204400E1C4C7151455E5A5 +:10E9F0001D7D9437514191D0B3BCB023F2F79A27D3 +:10EA00008B87DB239C7F84F73519027A52772FE7B7 +:10EA100024950229527F276405F281AD5C4FA93409 +:10EA2000327E51B975502EB1413E30AAF6ABFA6B29 +:10EA3000A19B6C20D049BA663F97365DAFE1F704E1 +:10EA4000BCCF89406F1334DF2B9A6FD6B4EBDA2535 +:10EA5000E2B8AB819750B9FD2A297A52043E15D805 +:10EA600093326B0C8CD3F514E6DB12518FECF2343D +:10EA7000AF85F3C7739E164CCF78DA303DE509AC0D +:10EA80008573C0939E03981EF7B463DAE13986E973 +:10EA9000479E0E4C3FF49CC1F44F9E20A6C73C9F5E +:10EAA000617AC4437E02700E7BCC98FEC163C7B40A +:10EAB000DD938CE9058F0FFB51F65D5F747786CB94 +:10EAC000ED73407F11E86CBB78AC6ECDD0309DBD4E +:10EAD000B9F223A43305CF854D264E0F491A7A0883 +:10EAE00080ED7723D04B1FE54D32A7C3DEDA472EEA +:10EAF000AF79E1BF87DEAE7C4B7A0BD3D3101D3DDF +:10EB0000A5F7454F1FAAE9E98AC1CEE420A7A71FB0 +:10EB1000F3736B7DBF51123BA70CE977AEDB0C8022 +:10EB2000AAA5FCDC84906998BFC4FB5E49C1B5A36B +:10EB30001EE81B0D72EBD2E8BF8F8273874BC7E8CC +:10EB4000E2A7F63E3F3D9DF48E7717DA43253EBAA5 +:10EB5000E80911C61BCDF01A6520D3C878421A46C1 +:10EB6000BEE45C90817989C4437B9F734684F33A09 +:10EB700042756BC06F5F785D69BD3216E09D7AF6B5 +:10EB80001F59905EE1FA75F41E11F57C1278D109D7 +:10EB9000F80DC925933319FCF3C191463BEA09648A +:10EBA000BA167FDEDB35F86B4855CECF1B93117F4D +:10EBB00023AE8C1AD40FFCF5C5DFFBC2E70298F731 +:10EBC0007F033EFBE28F7DF145E272BCD646E7DF74 +:10EBD000BD73CCF8C71CC007BF1ADFCA799C7E3C46 +:10EBE000F992F4B5E8B83B49A1E3F614885BD82460 +:10EBF000DA11FEA5D66B62615D4270FA584FE1ED05 +:10EC00003FA780BD7F3E550B2F4B07EFD281176D7D +:10EC100060772D4D5ED87032C23A2869554B5D83BE +:10EC200045AD87B669F3971A85692D382E47ECEC08 +:10EC30003120276A1B18DF5E8EA90267697209F608 +:10EC400073AE393D96D97B3EC60F36C721BF38E734 +:10EC500029C3FAFFECF1F40647190F21ADE484193A +:10EC6000F8312D4BEFBD7EAFF42CFDC588E7DD7E7E +:10EC7000F90AE88966FADF9760771009F30ADC9AE7 +:10EC800016D16BBA01BE6FD6F447DB399433E22F4D +:10EC9000D3BE6ADF48E49442B7545ED483BD80E7B4 +:10ECA0009B4B1AD47A5955CB7735F99AB6471AD473 +:10ECB0007A5C05FC83F25F522B484037959C8CBAF6 +:10ECC00025CB1A818EAF18824F808F08AC5E95B924 +:10ECD000C3E8A69FCEB7B275EB6D7CE73CE65488DF +:10ECE0003B283337E2397259CBB5F92067CEB7AE3E +:10ECF0004C02F95B215EFA5E5184F6BF94042E5FEC +:10ED0000E4A056CFE7F441285CD5BCE9CF12C21786 +:10ED1000CD7719985F460FB78DCB91BEF053BDF9F3 +:10ED200050C1CD8E9E78AA6EBB6874235FA4FFCBC2 +:10ED30000AE349C15FB154D426D171973777A2FF56 +:10ED4000E28CEC1DF583AFE0973DE767493E15A3E4 +:10ED50009A9797B4433F0B26F18E88E3DE0F281F66 +:10ED60003FFB5B99001F225769AD2C74CD70BBC768 +:10ED7000400C5961BB67416B4521E0FBECEBD3D103 +:10ED8000EE5B448A6CB80EA4310BEC9CF3C480712A +:10ED900055E7C91F6C1354EBF0B164E478A65C30FE +:10EDA00089BB3410BE7B10D85FA639F5EDE258F868 +:10EDB0002E297690F025CA15B780F11773D8772FD2 +:10EDC00031D701FD527B4A63AF517B4A93A7F6943A +:10EDD000265F426626413C45C9D332F10988274D5A +:10EDE000F941C98EE32B25B5F5A01FFD9CFBE1166B +:10EDF000D8893484CA87AA379ECB2AA6F3E9929889 +:10EE0000FF4B890F584265C5205A5E5EE633BA2C27 +:10EE10003DE777A275C23D94F3033C160770BFD15E +:10EE2000C7E26B8843CAE2AA4F5AEFF31FD82ABA47 +:10EE3000A26C508F7E57C69BFAF5E7AF9F2F214FEC +:10EE4000E23CCA9B67601C568F78073E1FB9597019 +:10EE5000F922EC27511634F12E0932C39FE2D71A5A +:10EE6000AECB5F0F7995DF6BA2AEFC1BF39701442D +:10EE7000C35F8A25F7703991F113C0BF2005717FF8 +:10EE80007D63F8C93DE05F2FDFF84F843F54BBEF4F +:10EE900029FC89FFD4F18FE831FEBC48F0ABDE7865 +:10EEA000F57588772CFFD5CF6C84EEB7B35263929B +:10EEB00093AE7BE5A6D53617F01DC96B837D71D661 +:10EEC000274E8B440FDF9779DC1F715904F0BBC2CA +:10EED0003F29FC73AFFCF84EB0A3AE6C92EDE84F47 +:10EEE0006D36054C949EAB5B971492B198EF64F924 +:10EEF000472F02FDD7B4C9C7D5745AFECB9F254111 +:10EF00007C10A5942186644803689F546FFCB80068 +:10EF1000F48D1A12C4FDAA6F07FD7F168FF2B0D8C8 +:10EF200018DBB31C1D3449D09EFD6A5A7F7C51B456 +:10EF3000417ADB69E06FD4B244BF90BE5D19B73B44 +:10EF40002A64EB00E4AB13C944E0AB0A5E888FD9B6 +:10EF50001D2B5F7E666C271D57D7C6DFDA0415BEF2 +:10EF6000147BE952CBC25FFCDAD13B1FBF40F7A351 +:10EF70005ABF55E494A38DDB4B7E9656CA011BC441 +:10EF800073556E909D5EFAB9F2D5175F7A16FCD96B +:10EF90007F34394752F815AFEE3B7213CD576C9161 +:10EFA0000714B2695884A4F0FAD4D0FF968F0FAF3B +:10EFB00047F9B67D46C718F6FD87F1E175A9D8B2C5 +:10EFC000CB48C6F4C4475ECB2E638725C2FAB4741F +:10EFD0001680FEB7F2E5BF1A81EF9DDD299081A969 +:10EFE00011F0B9611FEA8780275C4FBE5EA1F5D39F +:10EFF000D5AFA1EB027246BF5EFA7A859CBF005C7A +:10F0000088B3A1F4FDDAAF210EEE4F2627E0A1EC84 +:10F01000B5876C309FD3522DA3F3E7562701BF2B42 +:10F0200093BD49764CD9F7B2E71F46FA2B3DF470F1 +:10F0300012F357BA061950767A07C13C17AFBF1BB7 +:10F04000E75942DC488765CF89453E9A7E2A916917 +:10F050005B22EC934B7C9F9C7E812E2E9DE7694525 +:10F060002EFC41E472E1BBE80F7D98CF856A909851 +:10F07000FFD4CCD6EB806CD0C8D110FD6E7C14E5EB +:10F08000C7B961AE8170EE561396172847C4435333 +:10F0900007B275627207DB51B99307DFA17EBBEC43 +:10F0A0008A1AAB69877246E97F19EF9F8E3B1AF483 +:10F0B000B7D34991ED91E146850F503D434567AA8D +:10F0C000FDCEF6FFC606B6DF95FDEF9B310DCAFFFC +:10F0D0007298ED23680772978E2B3010CB77CD1680 +:10F0E000903F984820D23EDF28F37DAE2DD7D30B3A +:10F0F0001DBF24C4AAE806FA89C77540795FF234B7 +:10F100006DAFE2A335D0AFAD275C651F97727E70FF +:10F110001EF8C1F5617E40D627F62B5EB452F6BDCF +:10F12000F42CEC5FBA5FBD0ED8BF7211CCFF93CD4B +:10F130007B8EDC4FF7ED272DCABED5F255FDBE2DD7 +:10F14000DBFA30C69FEBF7ED27436B49C47D4BBF1D +:10F1500047DCB7433BFE47F8AA82C724A396AF2AF1 +:10F160007CB2377CEAF9E416D98178D5F349FA3BC9 +:10F170004CB27AD2A342870AFD95FF47D570E0478B +:10F18000213A55E83044A70A1DEAE7ADC5A3BEFC05 +:10F1900023F02D527A297A53C6F3954A3F8B03A662 +:10F1A000EDF60FC9447CB950CC91C6FD4306A8F3D7 +:10F1B0003E5DBE4557DFA5CB17E9EABB75F95A4D51 +:10F1C000FDCAB63D46827410D0D41397FF3B393147 +:10F1D0002112DDFA98BFA1F5A211EE39D45882D8D8 +:10F1E0005E5E41BC101F19DC21E2B95137C5713D8B +:10F1F000F83736A7FABC948FAC8E627E856E7BD0D2 +:10F20000164FD3D5712C1F4C34D6031F54BE07A301 +:10F2100098DFB1BB28688B53D95B9D7E11F9788745 +:10F220002FF2BD0D2A6970DD3B7AB9D7A19C8F758D +:10F2300047DBC6627FD1293EA0C7A9A2256539F860 +:10F24000A11A4527E8EC8BEAEEB5C17955B73FFD29 +:10F25000AE39F4FBE27744168EE37549835476D0D9 +:10F2600019E25D972D405CF05AA49F857E66172DAC +:10F270005A1B793F94F37625966546E0BBD40E3948 +:10F28000AE3EEF51E094ADD77DF74FE7FBA611ED11 +:10F29000FFF28DDA7237B79F7F64E4FC671C19C7F1 +:10F2A000ED57E6BFE17C7BAA9871D71CBA3EDD071B +:10F2B0004462A2F94B7E11D7E7D266C107FE37E25E +:10F2C0004DC4FD574D8246F57D882ED85FD7F4CECC +:10F2D000C7BAB6FF39EB074047AF7F30F6DF69DAD0 +:10F2E000F5FA1F47BD05F9378EA67C407AD6CFDBED +:10F2F0001985F102DD3BAD48FFDD3BDE4BF901E452 +:10F30000DF3439619CDD3BFF3A16E8A97B85A90C07 +:10F31000F860F730E6BF5DB9E3AF633B50FEAEC2C5 +:10F32000756C361A999FC9FF8F8FE0DEC2253F9D0D +:10F3300015E8173CAEBEE6D7513E82F0FF9AA5BE57 +:10F340000FF46DE753CDE343BAAD64CE56185F1C9E +:10F350008B7FA8796BF28B75B4FFAAD65DC685B496 +:10F360003CEFEDCFC7621CFD56A6375D903B9E87F4 +:10F37000F8876DC6EFAC94299E2FC026A346F65D94 +:10F38000A63579B08F7AE2E573F4A7F5171FEF1A67 +:10F39000997DFDAF8F0FC1C5F89FD5671660DE7FE1 +:10F3A000FBE803F4839A902E95F97ED25287FA4CAB +:10F3B0005FF33EFBBF860EFA3B6F21D09F799B4DDA +:10F3C000FFDAEBFDB8D181EBA2DF073DE97CC7F79F +:10F3D00030FFAAD589E3ED27BD8F36FD3FB6EE5B42 +:10F3E000E9BADBFA9EF777FEC5E7DDFBBABF338FDC +:10F3F000AFBB1DCE536BDEFE1CC7F775F95CE9FF92 +:10F4000052BA57F4FD7643AD3D938E6F0E69B482C8 +:10F4100062715FE2254BA603A2702F0FC0F83B3844 +:10F420005F8D6057359998BFCD241858BCDADD82BE +:10F43000E247443BEB4EAE5FDC39B40CF5903B5DEC +:10F440003F417D8248B5ED39B47E7BEE4227C66AE6 +:10F4500092F1C7DC909F3D85E7B5F6E6EF04E21236 +:10F46000A87E7F67EEF403A0E7DEE512510FA62920 +:10F47000EABFEFA714B0EF93B4F6D07D6E6DFEDE59 +:10F4800039DAFCDD1CDE3D848DFF9E22C1077E58EB +:10F4900053CE5389E097352D9689900A7146B5ABC6 +:10F4A000C1EEB8BB48DB7E1928672A7FE337C5E386 +:10F4B0006F43785C8A78213922DE03ED138F7CDC80 +:10F4C000EDB3C7F920CE9A484E86C77BAA9CE83791 +:10F4D000E7F6B8CCDBCB9635EDB09F659D1DAED879 +:10F4E000D3BDE19B70FB1CE1A485F12FBB44B4CFDD +:10F4F000659D7DAEACCBD75D0F651DBFEDBA3C07FA +:10F50000EB7263785D865A5C04F6ABCCED877C8B3E +:10F5100093E587161176AEE8C3FAD20017F1668438 +:10F52000E3D197988B2BE09CCC3C5A407FC85D6B15 +:10F5300045940FE60C01C7553449C6F8E38F0D45D5 +:10F5400059B0DE851326567F9F0DC309F85CC2F1C2 +:10F550005E426A517F2557BFFC323B0BCE2508EA3D +:10F56000BF4B5C84DC41EDB8926C21100DF16A1246 +:10F57000F1C68E073FB9408E6BFCE4DA3CFC6E4965 +:10F580000AC3E9AB7E6FFCE59F9DFE17E567C729BF +:10F590009174423A12BB97D476F77C3FC3634DA572 +:10F5A000E04B43BA0BC8EAFBD30566B60FFEEB8708 +:10F5B00013904FE6FC744C2CF30764E27DC41A6E82 +:10F5C000375CF23A62C10F76C99FCECF73F36C6A93 +:10F5D000BEAAA487B81DFE9F109748D3EE7CA15108 +:10F5E000043B8B04D1FFEBCD8FC27BC5FA76A3CC55 +:10F5F00006BEAF6BD12F003F11EEAFF27994D2A6C9 +:10F60000B1F1AA755B7BC759696CCF7580DF71D585 +:10F61000F9DDB7C52FD8FD80D743511D054511E64B +:10F620003B89E3AF70F7DFF0FEEA4C7FAA0C7899D4 +:10F63000992F6ACEF99D66EECF984026C0B80A771A +:10F64000DF669B0CEB724074C27DD51AFF45A33B6D +:10F65000C2F9B11E9F001FFCF027646709E0F3C4E4 +:10F660004FA208D8D5EFF173C90CB8CF9181AE1E67 +:10F6700017F81D73CCCC4FB8CE6CC77456618E9CF6 +:10F6800048FBCD68B58F8350B5C1BCFE3AB303CB00 +:10F6900087F0764ABDC195AC5EA7D15E1D69FEBFFD +:10F6A0008B12F87999F37B93847FBD75CBF9A935DB +:10F6B000900BFA41BEE267D1D335C1FD71699AE082 +:10F6C00003F90DF630E60B05D41FDE53EEAFCF6421 +:10F6D0007256A17B3D9EABCDDAF7021EE7787F889C +:10F6E000D387826705BFFAF12AF529BFBA55ED9F86 +:10F6F000BAAB6DDC6BA0DF54FB05BB8182AA963AE6 +:10F700008CB00F6BDA9E90E17CE63E07834BA4A29F +:10F71000B1EAF8837566160FB267FCCDF3804E2E02 +:10F72000AF35812C24AE45176DC087DF33387F0F8E +:10F73000716CDEDF8964D357F0AB0F3CF6F27C5975 +:10F740000D3715E733AB32470677DA0395BBE48113 +:10F750002A7A5A678EC772E5FBE04A07BE0F42FB62 +:10F76000C371781F3711B84F92D1D28EF76C1FA892 +:10F770008D637458D6B2CB88F954CD7B224A3FFAB8 +:10F78000FD34BB501BAFBC30AF6328E0A5D014588C +:10F79000E68C40A793A39473CAAF29275C946EC7E5 +:10F7A000FE7F2427962972A203E3E395F602DFE7A2 +:10F7B0002A393130929C585AE71808EBB07447FA4E +:10F7C00040D8244BDF999A14494EBCEF61E7CC47EF +:10F7D000F97DF6EED9544EDCA09213B3A3904EF40B +:10F7E000ED3E51F6495F724259B7FFCBFCE67D9082 +:10F7F0001311F6F7173A39718FBF18E5C43DB345B9 +:10F80000CDBDAC4FFB94133949F7615E76C644A079 +:10F810009FF7B97D7394DF0B807E405E6446D911FB +:10F820006F7AB9D11B5FFF537FF9FAFF109E15BEA7 +:10F83000BE94DA3FA6D4487448909E97DE47F9BA42 +:10F8400000F4C8F8FAD207B99F53C7678B80CF6618 +:10F85000AAF92C6B5FED6672A1A62DF599B9B4FCDF +:10F86000FE46D909A2F2FE30DFCD52F3DDCCA85E10 +:10F87000F86E19E3BB97FD13507FEA6D7E7FE6FCBF +:10F8800096F2B311CE08F431676E8CE6DEDE897134 +:10F89000BFC9D806FBE53D11CF793FE67AC0C171FB +:10F8A000BFC9047DFA493E9E797C3D2F7848793E58 +:10F8B000C55FDE22A64F576D16117FD5AD6CFF5781 +:10F8C000370B3E07CD178CFF1B9ED756EC60E7B574 +:10F8D00074068539AAF5AF78AFA31ECE092A36087B +:10F8E00078DE0CF71E009FA51C9F25CE0A3C5729E9 +:10F8F0006DD2FAC11BA26D2F901B101EFAC3AB78FC +:10F90000FD425310CF1D0A7F293837209FD4B6AB54 +:10F910001A71FB59B04F2A9A75DF9D0D78AE0437E6 +:10F92000D441AFAD6AD1967BF8BC178B818C6D1436 +:10F930003EF93DB3F3F478F7E8F153F62DF173880F +:10F94000E227F39F879F25FE5D785EF075F1A2C7E1 +:10F95000475D143F1F184F32613F7E6C70217FF16D +:10F96000BE2BE2BB4E8B9E18A9790FE5A71C2FEF8B +:10F9700019DCF583A05EB580F54AD76FD99744F3BB +:10F98000735BC8383866286DD2CAE390FC6F75A0E7 +:10F990007C9F5BBB4580B8DAC5FCBE6099EF097CF3 +:10F9A0003FE6C1E554DED3FA0BC79BDC705E7E28D0 +:10F9B0002A88FC53A1DF9D40BF946FFAF9384E0CA2 +:10F9C0000EE6A39C6A13ECB82F03514C6ED17582DE +:10F9D000776DF64CFE6B015F17E65F6A63EB584389 +:10F9E000D70DF675819FE75B983EF880FF223BE7D5 +:10F9F000F4EF92D9FB380249407EE744FB5C918FDB +:10FA000070EE9A93A45ADF1D9D8CFE37094EFCE0E0 +:10FA1000A3FFFB36EBDBCBBA2AFA4C7FD757C1D317 +:10FA20004EDD3A1F8A6A2F9C80E7728213DF0BF249 +:10FA3000C7E179D1C946F6FECD41AE1FE9F705D839 +:10FA40001FEAF77866C0C0212E7A5A14C69562BFA5 +:10FA5000694C3F53F329FD3B485F376EA986B4A339 +:10FA60005E168E7F74DF6E06B93F4DD0C449D11942 +:10FA7000E1BEFF27C097A3BE023E4936A37C79C8EA +:10FA8000CEBEEE196624F01EDAE53532D2D1BD06BF +:10FA9000C7916CE02F8FC904F6C7E583371E9D3BE5 +:10FAA00000CA45A48FE2F72654836BA598C5AA9196 +:10FAB000E247985C3AC1FBFF1395D7AE6B7897A0ED +:10FAC000077BE27C70BF74B673D75407F85B320FC4 +:10FAD000AD8673CF5979F62347601D1BD8BB4FC73E +:10FAE000D7E4A19DF6D07705DC67C7E87A019CBB17 +:10FAF00067A71E3942C7F7E09A443CB79CEB4ABC63 +:10FB000007CE31E71E149D0E5A6FE15D560B9C7FA8 +:10FB10004E1F2D12B70A2F0F9276F4EFCCADFDEEEB +:10FB2000DDB04FCAA83C84F79CCAFC87A60E84FCB3 +:10FB30007A01DBD778DD46B8E7D9DE74D19849FB86 +:10FB40002FA1F500DD35EB59BD9A8D02BE1758E2A5 +:10FB50007F02F964C946011FC469A7FAAF99C1F5CC +:10FB60008129D1BE9EB6A7F952680F7037C6DD0352 +:10FB7000E79335749CD87E521D9E5397D076B498E7 +:10FB8000B46FFC2EC25BB25E2070AFB06C52EAE381 +:10FB90009300DE41D909E54777FDDC08E39E47FB8A +:10FBA0001B44E12F143BA6427DF203C18EEF2E15BC +:10FBB0005E8BFBBA9BEF3B621FCDE21404A2DCEF2D +:10FBC00093D4F12A25D169B89F4A96D7D5C3BC3AB8 +:10FBD000BC89A906A4A78B4690E32729BEDD547FE4 +:10FBE0003D616471307BBC278C1D2AFEB9323A1D01 +:10FBF000DB2F6ACB413EB39814613C85BB8EE92371 +:10FC00009DABA37CE057EB94ED29F07DCF6A137E8A +:10FC1000BFF02A933B178675A07FFBF47A99C0BD8D +:10FC2000C795EBD3D7C13A9EDE2C3BE1DC407C8EFE +:10FC3000C51194BECAFC647BD633B8A79B197FCB91 +:10FC40007BEEEE02E0DBA5944F99707E5A3E56E2C1 +:10FC500028473EF55C14E34B7A7EA5E753658D1B80 +:10FC600022CBA1650591E5D0D07AEE378D2C9F6B24 +:10FC70008885E9BBE3C978F06316570D9BD704F478 +:10FC8000FC20BB70D01E78F3D39F81DCADB4E23B87 +:10FC900065D5927D9DC0E88300FF9FEBDFF229ECE4 +:10FCA00087B2B951F80ED929580FD8476B13F01CF9 +:10FCB000BBC4578C7857E2794B9BB4F4AEF821EF74 +:10FCC000738BC4A5965F6531C4A5AA77F447946E7B +:10FCD000693FF3DB041FB0CAA33FEADCFF7026E6EE +:10FCE000ED38AEE55C3F586B45BA3EFAC8C5D54025 +:10FCF000B7F37E2810D0DB89D75D0FF2B0BA497018 +:10FD0000809FB8F487AC7D296D0FE33EFA73465FA0 +:10FD100094CE1DB00FAAD73FB11FEB6F141C00FF8C +:10FD2000E88662D427CABC22C1F28D9D684750790B +:10FD300085F1687BBC6212EC83EA55263BB86215FC +:10FD40007A52E8B393BFA740CCCEB1B3683B67B457 +:10FD500003F9B29E2EC53942489E02FDD47819BDE2 +:10FD600075BE2A3B618BF44D9FEC1EBD427F22D0B5 +:10FD70005F6698FEF6ACCF33023D9EF60918679198 +:10FD800007F40BF4F9B2E29F2116B51ED5177DEAF0 +:10FD9000E9B007FDC1CB58E961FA54E8514F87C774 +:10FDA00025720F8CFBA1D551388FBCFA37EF59CE95 +:10FDB000F6199ECFE5D53F9204FBBA446271400A22 +:10FDC0005EAB241637D6635C4FD71907F5677CBA4C +:10FDD00071CC8A0EC9EDF120B7A93E4A02B49FDF6B +:10FDE0006C7E11E32BCFBFD27927EA376F513A00EF +:10FDF000FC6FB69200DA213EE447E5AD22C66913F6 +:10FE00002990354B65BF2B713115BFB222BECBB7E0 +:10FE10009A7C85B47DF9EB27C6625CC20AA67F7B1B +:10FE20005F11D83988B7632CDC3B2A97587C8E5EEB +:10FE30002FF85D34B3C3BBDE8C99037A9BD0CCDE44 +:10FE4000172C6FB95736A9FCBBFBA265A51E9E9364 +:10FE500079E93AC3FB0A303EF5FB764A5C4ED7CBD4 +:10FE60008CFECADB64D4E7CA9BB75C8078CDF263B2 +:10FE700026B4776B9A2F1AC19ECDFBD5ABEC1DC46F +:10FE8000365113A7D7233EAE590C9820AEABB50A16 +:10FE9000CF7168BE13F32D3C1EED6BC66F55FC6A27 +:10FEA000C7EB5E8AC28A6DBFB4E17B85ED9B6C783F +:10FEB0005FAAF9ABE3557BC4C3B534F078B83B4EC9 +:10FEC00013E48F91E3E1CEC13F28217D16AD8D87EC +:10FED00023CD8CBFD17166457A0F35A477BDFAE981 +:10FEE000F310CFDDB5F593E761DC955F5C7E1EE234 +:10FEF0006CA88268073DA5E695F731FE5569171F86 +:10FF0000C3EDA0977F89F1C317FE687202B40B3B63 +:10FF10004EA780FE7161CBDF92202E78D98EA9E8A2 +:10FF2000DF59B63D0FDFBDEDCD9E05FAF5F5237E19 +:10FF300059BF6E7B5AF7603CD079BAEEC027427148 +:10FF40008E2D552C7ED4C1E31B37478E17EF11CF72 +:10FF5000D83AEBAE29C01F5B999ED0675CE361BACB +:10FF60009E37F4631D37F3F8D5963BBE32AEF13CB5 +:10FF7000FC83AED7B8186D7CE8A7AD8B7FF12C94CD +:10FF8000B526F41AD718E807FE9478F4CFA35DD904 +:10FF90003189B0DEFF81F1A4B07E850EE0D79FA647 +:10FFA00080BFF88C1C44BF44708709EF6B96EF3814 +:10FFB0008AFBE9C2F64318EF4D785CF80512FAB1F6 +:10FFC000F85DEE03AAD96865F1907C1D205ED261D0 +:10FFD000C3EF3C2E92D1B5122FD95B9CE4B298347A +:10FFE000FE3E0B8BE7ACDAF8018F3F0CAF9B30097C +:10FFF000D6ABF32BE350153CD8010F13D571C0914C +:020000021000EC +:10000000E3524371C0BA7583F5043E1E8AF3A5F925 +:10001000A110EFE9138E468A2BBFB081C50F5F9008 +:1000200023DF8F56E2826B6274FBD6D7BF78E0BEC7 +:10003000E6F175F1343FC6A1A11B055F5D5723F3BF +:10004000F72763846F64B785EE9B540AFAFB2C4F45 +:10005000C4C07D99D64E23BE93A2D8557CBE5DDC2C +:10006000DFD6F58A8871A2F52D7B90BFEBF9473575 +:100070003F47D18F77231F6F751B931F5D5BAD3E8D +:100080000B85D3B5FB4DA4EBEACD9D18A7BABF797C +:100090009BB14375FE0CF2C3A71A7FD76BBBC62278 +:1000A0003FE7EFA2E9FBD9CAF9638D3F723F359B69 +:1000B0002F6AFAA9F0B618ED96BEFB3B27B9EE05FC +:1000C00078E7DA991E75AE459CE68BD0FFCF626467 +:1000D0006E5737323F3895A3F83E9C95BD0727DA17 +:1000E000A2512F5B669D740CDE215D6635625CCC8F +:1000F000CA3A1E47F3236732ACF74AEBED04C6BB9E +:100100001AF0ABB2EF65BB9B803E27271765AACFDD +:100110006194F11B0718884FBD8FADD306827D4ACD +:1001200024EF5018C79D697F95402EB67B987F9F1E +:100130005C3D3102BEB74BF67D09146E7BBEE00418 +:10014000D76C4FBA67F0437E0697F61D5DBC5347E8 +:10015000E777C969403DD16A08D86915628D6A4F51 +:100160004603D7411C52125EA5C07889C73CE611F0 +:10017000703FD446A8DA0AF59C92E65D95D849927C +:10018000EE9D15727804A5570BA757C55F6765FFED +:10019000A6703BF0FD96B80C5207E4BBD6EA467D4C +:1001A000E2299B0BEF3FD2DF6888938827D14EF579 +:1001B000BB50B45FCD7D3BDAAF261FE7D2E613A676 +:1001C000492723C99B043E8E02D18278889B6AE02E +:1001D000FAB2AB70645278DC7189C41980F23B2C9E +:1001E000788F806E2FAF7A1E168B76DC747C1A3E69 +:1001F000119BD1E135B0716ABEDB8903DF47A7E30C +:100200003DAE1BAF266FB5707E271109F89DC5DC8A +:100210004E38FE2F69F0BD4A2A8A4F224C64C238FC +:10022000E93021DE2596CF83F6AFA96F07EF01EB0A +:100230005F0B870CB5ABEFB5DEC0E5E0114B518A23 +:1002400085EE93ACE1B518B89D9D2CB84E4EA065D7 +:10025000FE01C89FD296E7615C8AD0C8E86AC45A9A +:1002600082FB664490C755AD8A463DD56426DEA81C +:10027000F1703F8E78E5F1D08B8F9F3F395618286B +:1002800028690DA535DACE1FCC352CA68BD00245BA +:1002900014FE108B6B0CF45F3FC39D6C1807D31BCF +:1002A00056BF7728EEDA6BC16368A81BBAFFC0148B +:1002B0006421F82E08F10EDD0F72B851C953C60E35 +:1002C000EF06344687F22E33E5F78D692C7FF3DA9B +:1002D000A1F5F07E4DA7BDE8660B8CC76CBF0ECFB5 +:1002E000C302F19AF7D57B932FCA38476F0CE4C14C +:1002F000FBC7B707D9FBC523ADA17BFC288F3759B6 +:10030000947C00ED8BA2D643C8D7AA5A0E61B901DE +:10031000F2341D9E10C81B42E779BF654C41F2B50F +:10032000145E6B71323CC1B1D03266BFA4C1C3B898 +:10033000FABDD9613C482B6ED0E1E186AF85878557 +:100340006B6FA887F755FA3B6F4A170B005FD373A3 +:100350000CF88EDBC46316F4BFD05F14CA230E679B +:10036000432FF7BC153B85C22957D397D24EA1AB7B +:10037000DEE8269DD8AF63EF836AE9E7DF2DAE871D +:1003800000DE328B2BDD9688F3C77705A6BB8B8BFF +:10039000F213C2744D2CEE09F0AEFE11CB821F5A3F +:1003A00054FEDAE9394BC5343ADE1F0123B8313C3B +:1003B0009FC4E5DEA851749E892E03C6D51FB1B82F +:1003C00057403BDB9C600062CB2612F704410CF7E0 +:1003D000A3EC8FFA1DCC8EAF2F36F856B0F360FC2D +:1003E000BB1D61FAE8D0D14790D1475B27D247B512 +:1003F000BF93D1475B5D6E343F57033BBA9104C74F +:10040000C1BA37590A0BA461946E6282F54037B2C3 +:10041000F7B682C228C4EB3A185F8FF5E1E352E6E3 +:10042000D5DBFA361E48FB7106D899070D781EA653 +:10043000E04DA9B7C3C2E246FFCDE67E11FAA99905 +:10044000D4B11F966FEB813F605C87EDE0CC5DD04F +:10045000DE369BAE9023DC6FE3C115F84E78237F28 +:10046000D73B9604BD20D77BC707DB3F217C80DECE +:100470009301F8E8C4FDF20ABF6796DD26B840CEC6 +:100480000F8F61EF90BC6E6176F5BB1691A74CAFF4 +:10049000493CB85B04FB2B7B9501EB27429AA19E5C +:1004A000FF2A5E5FD2F8DD957555E88972D218781B +:1004B000CFE4F978F71E2DFDC4C7A4A9E029ED1EED +:1004C000F790A245945026EE5DF010C8554A3F3E85 +:1004D0004DBB317214E02D443F943E23AD0F6D7738 +:1004E00088AD6B7C0CE80B5BF62E15F15D8E7EAE55 +:1004F0006B16BC4749EB67C590DAADB47D562C4D01 +:10050000219FC0F303797E084BD33F741A04FA7D10 +:1005100003F7CB9EE5782592FDBA996320CFF4B816 +:10052000ECE418940BCABE856754E05C5BE2E7DB41 +:1005300069C13403AC9BB28FA5A02160A5422B4DAD +:10054000721820CEE15D8FBB08CE0B7BE33BB75F1B +:10055000CBEE81EABF7FCEC7F38DF5EBBFF4B82FAA +:10056000FE39E0B7CADCF1F84C9AAFBEF632FA6950 +:1005700057C454DFFC55EF68E8C7FFEED5DFC40071 +:100580001DFA3F3345BC3F35CECAE8F180670EB651 +:10059000CBE2EF0492814A1CB22ACE15CAB85E861D +:1005A0004B9986DF51CFBA055920ACA7578A87F6F9 +:1005B00031A978AE78AB2EAE55392FBB25C0FC8063 +:1005C00059B1BE42ECEFFA74F6F7493E63FA9299DC +:1005D000FE0FCEA1A6F27333D731FB5E1087590907 +:1005E0008DF9083F3615FD5A3944FBFE41D640AF20 +:1005F0006480F2F454849767D695A713F45B916BEB +:10060000AEC3F94D252AFD0CE546A313F8F1F4D14C +:1006100094FEF9F7CBF4BFE126327F86CACEB8CD7F +:10062000715F51BE466F69C477857EFBB9383F5212 +:10063000FCC563213C1715413C801E8FB90E6195A6 +:10064000D5D113DF7AFCE9F1ADE0518FB79C0F9D56 +:10065000F9F18E9EF8D1E3237C7EE95B0BEB3075DC +:10066000B488F24BC17B4FFCB0F5FAEDB5B49E00F7 +:10067000F442F10DF84C1730BE272B86D34F6C3A5D +:10068000E2370B14C001480F98D7E3558FC7AC046D +:10069000DE3E81D5DF0FF81A89FC00ED2165DDB261 +:1006A000D26BF7C641DEC4E84CD1ABA772BC50BDDB +:1006B0001AF5E6BC442BFA9B40AF9E9A14C65B5ECB +:1006C000151B57DE48CB0B609FFE0AFCD1B1080614 +:1006D000DFC5BC95F05FE0563C5FCAE25905DFB765 +:1006E0007EA6D593A7FA0BCE82FE3DDCE45E6505BF +:1006F0007F8C1087E77914FFC775F8D7B6B36BF313 +:100700007A7CFC0AFE31B927DE147AABB372FD7C29 +:1007100030190AFAF2D8373363817F137F7C44BFE4 +:10072000C4C4634521389C6E919E05E20E7DB7A737 +:100730007F0B3E76904A49151FBB5372AFB3DED88C +:10074000938F29EB3585AFC714E2DD057EA62944DA +:10075000FA4BC81E480DCFFF792BF7B30D2143602C +:100760009E5F581C8CFFF37986E64DD54BE83F9B86 +:10077000F79F6DB6E0FD1B1294BA42784EC3F79313 +:10078000BCC6F8F0386465BD536A09D3E7E6E2FBFE +:10079000D9142FE4CB98F038B6590509DF0FE2E3FE +:1007A00038DF6CF6429CDBD392FB0D2BF83D848343 +:1007B00063717E526014C83F7DF9E5B6BDD5504ED9 +:1007C000EB95603D3EFE0A91F91F823B4CBE1752ED +:1007D0007BD753E9F64639A1D07136DC7BBD01E801 +:1007E0003E28C2B8FDFC5C65E74576CFC145ECAB61 +:1007F000AEA7F0F65D62F702F228DB817A7AFAEDB5 +:100800008B4EF349701EB4D3D3AB22CF1BF8FD5BE4 +:10081000453FBB6875BF0FEBDEC0EFE3FA2F8EBA22 +:100820000ED6E71BD3D5612D5D29F444E9EB38F4EE +:10083000D39DF9F13A50CBDFCBBC9C04F251D1E30C +:10084000C3FA8AEB63A8D79B3E3FDCE6EEB27E8517 +:100850003EAFE8357DD92364AF4446D371CEE3EB98 +:1008600033D7DC2EB38BC6418CD36F8856DECB7367 +:1008700044833E39AF21ED95663857AC637EF90766 +:100880006B658D3DEC86DBBED89EBD673B7FB9B600 +:10089000FC238AEF41F1F8CEADD68E86FD91147E11 +:1008A000CFB767BF062FC8C97923A3317E4EDFAF0C +:1008B0007E7EFA7EF5FD3570FBAAC1D838DAA9D262 +:1008C0004FEC3616477D69CD93CDF0145E6FF8730B +:1008D0009B87B8D47F6FAEA3217A4EA4F7681478B3 +:1008E0000ABEE7C2CB98E00FA895FF1EE99DDD6C1C +:1008F00037F313F4D6EF88603EEA8386A70322E835 +:10090000F5238204F5F0ECA0CBB050630F307BB937 +:10091000873D00EFA4D07C65EB2E660FB4D4A15DBB +:100920005149ED0A903B1BE01D90C17C401968279E +:1009300084EC5E88AFCA867732B95D0C4FA7A537C5 +:10094000B2FA331F4F37358C00BBD59D0C2F93CE99 +:10095000B45DFBA899DA57F5A9248A50FBAAC8769A +:10096000ED77D64EA2DC3BDE25C0BBA434FFA865E4 +:1009700072FFEDEC99B6D18F82BF81DA67B7D95497 +:10098000766F6FFBE3669B03F1D9DBFEE8B417CD0E +:1009900004388ADF82F221E407FE28BEFFA342F476 +:1009A000170B7853E8E5F6E50BD1CE88BAE66A0A6C +:1009B000C49365733A70DBB85F3686C1A9896170EC +:1009C000264A6E37F4D3BDFBEA28F03BBF3BFA045E +:1009D000DA797E2BF3DB1FF49415A9E3DB6B6D0250 +:1009E000A797C010D87F77DCB82701EC956C59C069 +:1009F000F74EFDB2EFE9F199C09F66DB57D2296649 +:100A00004F36E2FD327F5460C8C32A3DCECFDF4D62 +:100A1000F55FDC3F441DFFDC6ECDABB531F822C085 +:100A2000CFCEDC7B0CF480DEE44E58AEB804902BC5 +:100A3000E4EAA1243C5F6ADD67039F68177FE7E073 +:100A40007CEB9EA40534ADDAF29F36B0E3EA383E83 +:100A5000CE4BEDF85E53E57611DF13A1FD263D0088 +:100A60007EEBD68559ECDE1FBBAFA6C8D5F19FEF54 +:100A70001952C49C8978FF4CD137A798BD3E189F66 +:100A8000BF8EFD1DCC29BAF7C96EE5EF93E9F5CF0E +:100A9000676CB2E22FC3F8A96576D64F6FFB2BFBCC +:100AA000B304E253EDBF6C2920C2F8B33F4BC2EF51 +:100AB000E70FA43D5508F63D919D2301AC44F6A2F5 +:100AC0007ECBCFA7E86F2FBC7BBE9367DE6EBD3CAD +:100AD000EB66246E2AD704D0C7DC0398D391C907EC +:100AE00045FFBBF533ADDF55AF072B7232D73F6EF5 +:100AF000D510027877CCC2FB1307248CF7D2EBC950 +:100B0000538305BDE8C34F207D6D6D4D8F017BFE86 +:100B1000DF609F00DDB65EC6F783AA49E01E78C796 +:100B2000A9BA55B40760FC24F37AD8678A3EA1E0DD +:100B3000A5EDEA1EF358DA7FF645837D0505F176CB +:100B4000F02F68574FF8FDC1049067FEA084E707B7 +:100B5000D917F7C62C54F145FF55037E7FFBEA6E8B +:100B6000EDF760FCF5D06E8B81D9CB7BF7FF3D06AE +:100B7000F8D4DB572F21BC903ED1536F46FD3BCFBD +:100B80002A86FCD16ABD9988D98721DE6B6A2C152B +:100B90006B42EFFA70CE87649595F4D42B42782798 +:100BA0002E09F0D0431F56F0ACD3333EB2713D77DF +:100BB00018190FEF5EB65D4DA8C07BC7FE18FB0A83 +:100BC00094CF4C8FEADE7BEEC9E9F0FDA0C8DE9D34 +:100BD000B82AE27EDABDB36278876ADF524E8AEBCA +:100BE0007665D0C50B6FD1FA57F64533FFBAE4BC32 +:100BF0005E7D4F225CDFC7F11518CCCEE9BC83E1E6 +:100C0000BDA86FACCF74F5B0F7FF61433D39580014 +:100C1000E262D4FA4E23ACFFBFD98A3E67FCA52519 +:100C200006F88B97E40E21B4DFB268920B7415AC12 +:100C30002376B033B61F3018605D3237A5625CCFC3 +:100C40002BFC1C73494BA3315545174BF839D81968 +:100C5000D99B12AFFABE3296F19733FBCA7F8171EE +:100C60001D7F34919111F4D085B14CFE6E337AA77B +:100C70006F867AC70D78DF68EFFE5FEF877793970F +:100C80001C738C03BFE09458B60FDA0EBE520F717E +:100C9000C16D1F82D4A2726663B168A0FDBE451CFF +:100CA000CCAF7798FDBDD6903F94B812609E37C503 +:100CB00032BEFDD60183E6DCEC2DFEBEEFF5B18C35 +:100CC0000FA5C632BFDAD603B9090B70FFB947C406 +:100CD000821FF064473D6C45C50FA8E86F930F6F06 +:100CE0009D3E86FE737297C10ECBED38FC8208F3F1 +:100CF000759C21244E203DF4390A6FAC1ADE5B5DF1 +:100D00000C1E1DC76ED8AF0AFEA904FE7106CDBF2A +:100D1000D52EC5433C98827F651E4AFF8E16E2DAC7 +:100D200060C1ADE4DAFA15FE68E5EF314CB013E5C9 +:100D3000EF33205D6EB7B96E89C5726F0AE4CFECF0 +:100D4000637AD2362E4F4972F170C09FB24EF3795A +:100D5000AA8CA7B7FEEFE7E354D2AF4BD7AFC80ECC +:100D60002FD2CD76164FEEF006CCE91077D6968EC0 +:100D70007F9F4A15977B3F8EFF8CF6FDC2B60E8390 +:100D800001EE8F55EF10E250DDEDA7BE1DA233A995 +:100D900005E9AFED18C17D5CDEFC5DE68FA4729FB6 +:100DA000BFEB86E7EBB07FF839FB2081A693FD1BF4 +:100DB000560E41FC066CB0AFC278A2FB06D2DA46F2 +:100DC00023D0EB92652C2DE5E7D54B9ADCB83F4B51 +:100DD000D6B378C465B1A94C3E737A2586E8C1F8CC +:100DE000DEBA4D7B8FF01F5C7E9E6D7D6A0FF44BEB +:100DF000E9EBFB808F9BDA9E5807C355E8F5EC467C +:100E000019E194456BCFF33DB1CCCFB8FD30A3F7DA +:100E1000C91BE55C784F6CB297D8C1BFFDD6C64DF3 +:100E200022F0EFB7809E53D93E07797B66DF6331AE +:100E3000DF07F9D66920E047DF6624655B54FB6273 +:100E4000EF863734FBB7BCB96E3AFAEB3BE205E00C +:100E5000F3CABE55F0BECDE8BC0DF7FF9DBAFD9FAD +:100E6000CFDAB7C2BAD07A4FF1FDFFD434BAFFE976 +:100E7000A7B88D7102C0D9668CFCCEDC4BDF90FE2A +:100E8000427CB5A3075F7D2996F91F6CE9B4FFEAA0 +:100E90003B2EA1FF21343E4E374FE52B74932A00A1 +:100EA000FE1BE90A8E007C51BC023D533D7AFECC0C +:100EB0000CDC9507243CFFE1E74B3C2E0477946A59 +:100EC000BF86F999B26FDD6FC038B2F26B57829E60 +:100ED0009F50E845FA3C2BB887C753797616F671D0 +:100EE000047EB08EE3E38AECEEEB7DFFC140CF657C +:100EF000D46284F990F5821DD6452977AC67EFBDA1 +:100F00001EE6F094EF87BF2DBE833DDE213DCCF081 +:100F10001D34425CEB281F936344C8C5FD400CB7E9 +:100F20000F867DB684CAAFFB55F2EBACDC8874AAA1 +:100F3000E0E123CEB7AEC4B1793FCEC7E9071F5D6C +:100F4000A20AFF8224096C3F8B02DBE722C03FBB71 +:100F5000EFA6DB90DEEF884CEF76B0B7E2E1EF472B +:100F60006D40FA8C9B66C77B2F4F49CEA8388D7E8B +:100F7000E4C374EFA667D0CE03FA85FDDE1BFD97B0 +:100F800001FD930874EFA374AF5A3F850E285DFCF2 +:100F90001DF0A57CD7D385720EA9E0659BEE1C736E +:100FA000AA9DE1E9FF00528D6EB5008000000000AF +:100FB0001F8B08000000000000FFBD7D097C54D598 +:100FC000D5F87DF366C93233994C76B230490CA01E +:100FD0002C0E4980B0D84E08204A88C352D7A0931F +:100FE00000094B36109556948120068B18152DB6A6 +:100FF000208385EF431B6D10A858832610112D62A6 +:10100000DCB17FA54190454122A81FED87F53BE764 +:10101000DC7B33336F26026AFFE1C7EFE6DE77DF62 +:101020005DCE7ECF39F7C56ED3313684310763AEDE +:10103000E6018C7D8F3FBFF4978C2DA1E77337CFEE +:101040005E712482D1CFF7F0BFBA795E50BD76C70A +:10105000AF571CE9E7AFCFC55F52E0FF71A66789C4 +:101060008C55F147AC4CEF89B525C0FB119DD66C72 +:1010700098B466E2196384039F781983F66F631C42 +:10108000543EAA6FDED32B1FCA31CCE985A6399B0B +:1010900033158F99B105361BAD67F927D393DDB0B2 +:1010A000DE46C6C6E3BA9BC57C72DDD93685C699D5 +:1010B000E029738F898367664F9E7BA0FFF90766DF +:1010C0004F966D88BF3EA170BEEA18404B8CC47E1F +:1010D0006355980CE69FBFC9E4336532B6059FC4DB +:1010E000C32ADBA37C9B32FDEFD9F4CCA5B73396A2 +:1010F0006BCBA475C1EA5AB1EE58686497C1BCDFE6 +:101100006696B59BE1D1D51DDEE281B08F2D46EF0D +:10111000D489993898F31A1CFF9A629DED01586A98 +:10112000ACCBA63807D092695EB68FCF9397EDEC23 +:10113000CFB2A1EE70E6B92D8C8D12F862AD30C938 +:10114000703F1C42F1C6E1D9135E17207C86501710 +:101150007A7EE2D5A81B7D66FFF34401BF2F63783A +:10116000F9ADC1D3DB660E1D27603E554966CCCA7A +:101170003C4B555CFF2866DBE4F03F778C622E1C0D +:101180007F9A1857B6CBFA8FA6AFAE10FA9A867828 +:10119000AD8EE822BAEA53D06974C0BC4C19DD8B1D +:1011A000C1FA98EEDA5EAC80BAEA71BD0048552902 +:1011B000E0EBC7F6848D33D7239ED90113CBC90C3E +:1011C000DD67B5CDC0E1B6D130FA66E897E065B825 +:1011D00003C08B83E38535DE8AF86BDC686288D7D1 +:1011E0006F6339DCAC53D96803F4B7427F24F7C688 +:1011F000A99E035741BD31D9E850609E13862EC287 +:10120000FB89ABA08DE8C3AD20BE4FBC3AE29ADFAC +:1012100040BB77A28EE5C08B5B8DB005A4C3BFA792 +:10122000F9362948A72DC427F3C7B2C12678DEBEF8 +:101230006918D1D5ACE22C05E976CEE658059FDBDE +:10124000C7D8742AF3EF63D84295E813F8A0DE16E6 +:10125000808F61DE3A15E1D53BCE936C8865EC1149 +:10126000DB35E323D281CE3259241BCCD843505FE7 +:1012700009706BB4BB14164BF506730AF121632396 +:1012800008AEAD0CF0D418D55D774560FF2C5E7FBD +:10129000A4F1EA868634C69E897135229E3E30BB13 +:1012A0001FC1F98726D5A944E782AE7F80CE7E1282 +:1012B000BDD42E2C6287F3E0F70E660EA41B904778 +:1012C000B76E06F895E83D9B705D35BD8E3E8EC3CA +:1012D000D5B67C65F484A17BB98E782117D8C78CEC +:1012E000F011EFAE53CBCD7EB9B3C566174CED52BE +:1012F000265BFCFC8672EB7933973B59509A229817 +:10130000D762C77E3EA223ACC7E4FAE5D1CA62DD4C +:10131000785F183E7E0D89EB6794CFACE57FFFF2D6 +:101320009BA1D01F7F57899F5EE3FCC4E5F5A3C551 +:101330009F26223C9093F0BDDBC51CEB973ADFEA79 +:101340008B74B95F659BA03ED864F42A31B86DE612 +:10135000B0258AF1900D5B9456CB20A8FF4B612EEF +:10136000C0C3E97FA954AEBFD73D3E13DEAFD9A1BC +:10137000732E857E352D0AF183B337F345001D3773 +:101380004759073118AF70B7D96580F6D34A04C9F9 +:10139000659C00D76190EB2FE8CA6882E7F52DC005 +:1013A0007F503D5D08A8C6F5EA9D316C801FBE8365 +:1013B000DE7CB41FEC00DA1B9DC8674F45F2F19F3D +:1013C0008ACCF081108352BEE788014A6159826E4F +:1013D000F47AC662004F5078B11CB530DBA5073CEB +:1013E0002B7AE63500BE4675B5AA089FAC2E878ECF +:1013F00099FDF3E9BB18ED3B4BEFD03903F4D5D69B +:10140000BDCFAB7A80EBD0318DF52A9489319E6FB8 +:1014100010DE2346D5D5637B5CB157F540FF7CA534 +:101420006EB705E9EC1AE644B92AF924AE93B5C1C2 +:101430007259EC814E9715DA471C77B50D80FDC7C0 +:10144000B89982E349FD0D7CC662910EE35DCA4402 +:101450001867E83F18C1478EB375EF6805F93EBEBF +:10146000638CE218104AE76B98E3B738AE779FCEEB +:1014700089F8753433D70694137FBA620CC24BF6E1 +:10148000EF1DCBF5CA488FA7084415EE2706E71DC8 +:101490007EA36FB701D6336C9677B7D111B09FD9C1 +:1014A0008CC64BEDF4D23E520E780AB1CCB6C6D201 +:1014B00038238EB7B60D807E4975B01F684FEF7820 +:1014C0004F41B8A6D7752888CFAD7B77D17AD33A6C +:1014D000DA7929F8EB79611774DB03561DED23DB0C +:1014E000CAF5CDF2535C6F66C77AB2AD09FE7D2CAA +:1014F0002FF424D7C1F86BF66675EF17E5EE952843 +:10150000E403E4526EAC91C6B9CBEAE98FFBABBD04 +:10151000B1730FD2E0F37BDFB1127FB4C4137E133B +:10152000F77D4AF8485C48BA98ADD9375F4179B140 +:10153000A61470A684C259CA8D35B87EA21F5BF46A +:1015400024A0CF27ED9E82D8407BA5CC1E9D1520E0 +:1015500097E47B8F2F66EE19B09061EDE55B59162D +:10156000C9F77EB101F27DC2C0FB22919E9A2C2E5A +:1015700017B69F56D88D38CF335842FB33065E9747 +:10158000F07A40E0333B7652B6750887930DE8F861 +:101590009948DE4F2B8FEE8DD509BB83D30BEBE043 +:1015A000F482FB08B4BF66C6723C8C74798AF49CE2 +:1015B0004EA6E2FE8617F87623DD0E1BEFDD8DF4D6 +:1015C0009FCE049D8CE774A2A5F7DB63B97C1D71E7 +:1015D000BC8B21DCF315E60E67EF54C672BB29BE47 +:1015E0006334D10FF04319CE3734B54E35A0DC66E5 +:1015F000B609A87F7E13EBA07E7905AEDD486F3675 +:10160000979BF879BED9C6E92693D307BC3F271C20 +:101610003F6D433E1AE0E7A378A44773283DDE26DA +:10162000E0F41B01DFD0F13D77E1F8F11D3A9702BC +:10163000830C3B60F631E83A6C01E849E45306F468 +:101640000F0BB4CFB215229FA5563915C4EB02B3C8 +:10165000FB1EDCD772948DF948CF3A5F3DBC976C86 +:101660007311FE7EB49E6867116C68909DF5402CE6 +:10167000B7E35795A1BC7EFA5B23CA5387E4BFBD8D +:10168000B9D1E501F4F1C7507C3F120EDF5A39A7FA +:10169000C5B75F2E04CB3980D75A8E0F6EE7C77758 +:1016A0002C50B97C08966B3DE123443E083CFCC1BC +:1016B000ECDA84EBCCC64540E91DCDFA617B4FFAEC +:1016C000F8C558F34FB3672FAC8F5F8C4D08D5C763 +:1016D000BA88AED7158047758BEA50610BF58BEC55 +:1016E0002EC4FFFA66C58976E1EE1695E861FDF233 +:1016F00028D29B72BD5F6E8F19C4AE8452F03F6BCF +:101700008F257D5A1B2BE65F06BFC0FCA76DBCBAB8 +:10171000DDE6793D500EAD6FF92612E1DC3F5971DF +:101720001D41BB4AAB8F81851478DF84BF2908D760 +:10173000C10D2A32D6F59EAD2695F0F62E8E378C49 +:1017400075BE330AD6F5A7A6D1BA407BEBEC8EAFB7 +:101750006FDD05EBAF8DE6FAB9369AEBE7D3BBCE7A +:10176000F7417ABB76E174927BC3F49E8F03E5DC8C +:101770001BFD0E7339CC4A6D47FBE3D42EE5FB68A5 +:1017800000A135A29F1EED0A35CAA906DB15441C2F +:10179000F539001F845F5B14C1AF3E07F82E93D666 +:1017A0007902D7D96E31B214683F0BFC88FDE4BAD8 +:1017B0007FC47ACF845F6F9AED68B4A00BD5BFBEAB +:1017C0006EBC201E607CD5A2A77D9C66514EC4676E +:1017D000B3D1C510FFDE83C23E1078AB113477BAA7 +:1017E00065C8010FEC6FFD813427BE7F7AC7D948E9 +:1017F0009D19ED478F6A877DA9E95D56D487BB5B4C +:10180000CE5EDE3980E49BC10EEB3BBBEFB0DD3337 +:10181000E047EDCF6ABF88FDD5EACD0D817622AADB +:101820005952941A3A525ADAFEA90C22FE63280F32 +:10183000BD19CC570FFB5E3E50D0D354E640BED707 +:10184000E27BBBCD9D610FE0DBCD36B703D785F3DF +:10185000A4E6D23EB3B03EE8CDE979061DEE6F0CAA +:1018600043BD29ED3DB94FB4C72373FDFB93F65E2D +:10187000F7FE73CE0FDAC768DF83EC740E742CC5E5 +:10188000735A2D2885073203F7DF4A78A916FBAC77 +:101890008E30B7AAB02FB6CD70B253CA83ACD07D0C +:1018A000009E86F37D380F7810CF7F373BEB114ECB +:1018B000FA0E1BDAAFB0AF91B80F5650968C70F895 +:1018C000C0EC9A8CF2FE99258CE8FAF4B3CCF714AC +:1018D0006C7A4BBB8EE86603BB82E8FF0ADD995B3E +:1018E000DD66E2EBB1F87E7E47A30EE56F8ECFA1F9 +:1018F00043B97A7947B34E47F4E0192FE074560F95 +:10190000EBEBDF54A7FE48BA98149E2E42F0F6ABDC +:1019100040BC49B88D12F4300AE18632B94B7FB22F +:1019200033C20F37C00B4BB5878EC7586706C2A9A5 +:10193000EDC5637D3A61BC9A978FDD8A70A9F9ABDA +:10194000898861CC5F2F8F41BAFFB230BC5D737262 +:10195000719D5B0FC478AB3D8BE47B15EB30A2BD72 +:101960000072DDAD0F90EBD28EDB67E828C6F1F791 +:101970000D51D91280F359E7B02416465FC8723F63 +:10198000DA6D39007FF455E1F9E4C5FC186E47DAE9 +:1019900083FC5AB2DCB778967B8CA1E7F1F60D8E0A +:1019A000247F4EB1C61E7AC8CEED8DA7ED5CCF81E7 +:1019B0006076E13A4FFDC5E2F342D3A9DCF7AD0C06 +:1019C000E0746ADBBB795EA0A353ACE3F69790DFCB +:1019D000BE36D3B9AE78F0FB794B2C7EFEBC8AFBC9 +:1019E00052D8552FBC697540FFE22DBBE3BD01F015 +:1019F000BB8AE9BFEEA6EB4C9C97EF8FE93BFB203F +:101A00003ED84B27121D5016BFF86A3CA703383743 +:101A10000D45FF14E78F3F635380DD5DBCB0C63DCD +:101A2000262FC01F732E92F902EBFA0E231E89ABEC +:101A3000CF99A9FD76BB259EE44D2FD60BE54D8FA2 +:101A4000F0BA48786ADB253CF70D3E9181F6C597E0 +:101A50003DD8C507ECC17EAF37167BDC6372FCF561 +:101A6000BF7DA7DEE60EF35E8B18FFAC737812DA4B +:101A70007DC5C6D6CBC2F9E1E439530BA737CE57A3 +:101A800046E3B87F39671A1F6E5DDBEDBA9FE63F0C +:101A9000D807AB0AB00B4BF49E37EDDC5FB06A326F +:101AA000D46B2E3F3B8ECED9925E84DCBB8A79DB31 +:101AB000907FB5F421F1FDBEC45B2A4B45BC3D6966 +:101AC0007770BA11FC20F9430B476D39C1C83CE16E +:101AD000CE03CF75C3359279411EDEBEC1407AFE7A +:101AE000CDF31F4ECD037A3FB6D6605B0A53CE5A74 +:101AF000B73BED51F4A70D36D914A81F73B45E8619 +:101B00007C5FB94E75233D1C5B7B7BE27428BF0074 +:101B1000FEAD8275546E3050FBAC0D7750FB09C1A1 +:101B2000D795EB12FAA3BC7CB3FD8144C4E3ACEFC0 +:101B3000EEBF1EF1B2C568EB3F18CAAA26C53D2606 +:101B400000DE73364606D5B7E8D82CDC87C42B53A5 +:101B50003CDDCF1DB01E63DC4FC4636B881FD518FE +:101B6000C7EDCC9229B0EF9A2167C9BEDFBD278AA5 +:101B7000F4C92B6695ECC8D6C1FFF3B72BA15EF470 +:101B80009DDE49369EC0F358816786CE40A08F8A7D +:101B9000085E2F7A514F766891452578B7825C1D93 +:101BA000434ADE651E0BFD7E21DF5347AD1E0EFD51 +:101BB000C6C61818EAA15FB4CE2966A0277F794E61 +:101BC000FF6967C07E4633971EEDE24266086A5F92 +:101BD00011657D0AED5A184C8FFAB02822F8F9D811 +:101BE000CBAE3D81F6C4585B70BBA4BF9C38A0BF90 +:101BF000FE7EB9B17BCFE78F4C807D56EC53C99EFA +:101C0000BE905CDE8FFBCA417CBF51DA04EFBD2978 +:101C1000A0F3E6F963CB5290BE0A14867EAE63E76A +:101C2000C3F3E55C419F8C019EFBF9F13CD139BBCC +:101C3000BB8E6C7F5DC1BCEE3AAEFFE2E5D90FCB47 +:101C4000AB4E3BF76F68F587967FFE53FAA378F0AB +:101C5000AB195E0B95FF85E5C92D5CFE6AE58556DF +:101C60005FC87569D75B7D4E0DD213CF0979E2D776 +:101C700017467AFE339E8F6BE286849E8FC19E212B +:101C8000787987EAE95C0E76D7EDD86F80D911575D +:101C9000084B5A66CB8A46B9D664F1DC1917E0972F +:101CA000EADFD4A843F9D1EDAF3104FB6DE4F9F5D7 +:101CB0009E38BEFFF2385E87F32B9DFB3744799246 +:101CC000F5386F2FA333307E25CBFB85FC9076AFA4 +:101CD000B477A59D2BED597D03B767B363DD417ED6 +:101CE00033D6AF5F903F18ED74E473EFAE28DAE7B8 +:101CF000678A7B10F26915733D1417A007EB0D7C02 +:101D0000FDDAF5BC1627EC13E6263B41B6CF1C1DC9 +:101D10005E9E6F8DD353FFC2C76FCA403BEEB3B612 +:101D20009B3350CE7EA6F1FFF6C40F0F0B7E7D5085 +:101D3000E89358E1277808F908EAC0EDAE2DF0FEE7 +:101D40008AC56EE2ABDF2EBE91CA47172FA4E78F7C +:101D5000C565D2FCB6C277DCD900A7232B55D217B4 +:101D6000338DEE3EB1F0DE91081DF91B0ED799C7F9 +:101D70006F33633BA3F3E5CCC7276CF206F8011F72 +:101D8000C37D0CE9799FAF09BC5E2A9D56B34E2BEB +:101D9000EAAD6E7A3D10A2B7DB112FA7596722F684 +:101DA000AB553AFA3429A1F33FC85CAF61BF662353 +:101DB000EB8F7CD31CC5F592B6DF9B027FABD09E28 +:101DC00085F233D45F61E4CC3B825E7B5B5DEFC424 +:101DD00091BC3393DD4EEB56294EF43ECE07E7B46B +:101DE0000FF139C689D05F976DB575C755F879C7BA +:101DF000FD715C187F5C4FFE1FED3AEE89E770D5F0 +:101E0000FA856429FD42C7C47E16C5D982FC44E820 +:101E10000F0FE70FBA3ADE48FBDB10D5E9C5B8A8CB +:101E2000F7667E3E4F1AE555D0DF955ADC5888FE9E +:101E3000B07FC6713FA67DBC2719CFF1BD928D4EF4 +:101E4000F4E35C2C3F0E6876F138814747EB58D3BA +:101E5000E18DEC03EB4AECF0141AA134C426D2F85D +:101E600049AC6E09E20DFA1130F2DBA37C8A3C74B6 +:101E700043973C214761A591C877DBAD1E533CBC1D +:101E80003774465D3DFAED53AB783CE284E2E96D90 +:101E9000CF0E8D1BCB32395EF0AF88BBE66F34D0EE +:101EA000BAF2373E46F1D1FC8D57EB950039941FBD +:101EB0006FA0FE275E9DD39BFC181F858FBF0E88E9 +:101EC000E7F462461FE1108A8786A5BF7EF13F31A5 +:101ED000AEDC09F650B03CEF173F24206FA1FA0C9E +:101EE000C9737D3CD7237FC07C0558D31F66C87C4F +:101EF000850DE48FDD6A6CBE06E351DE1A1D43BC1E +:101F0000B7EFF92BC56B67CD7050BCB6FBFD7DCF2D +:101F10002CC7F63FCC628311FE29BE8715F4CF7C17 +:101F20001BC9E3C9DF6E32B125B0A5D96F37533C69 +:101F3000784D958EA17CD1EE1B6632E8785CDBA0F3 +:101F40002BE0F8473928F10E0464447C48BC21FC9E +:101F5000B698316EFC02AD5FAECB807EF004DCC77C +:101F6000966B904E7A55D915F417C8755D489F4CFD +:101F70008AFF69FAE467D4C3B7C55F9C1E9E81746B +:101F8000AED5C35AFDDB64715562BF0BE9E1134264 +:101F9000FE4D89D7C443307E16066FC7841C0CF0F3 +:101FA0008FDF19FF23FCE31FA11C09E31F7FC6C8B5 +:101FB000E56FA39DDD36290CBFBC27E6D7ADEE3219 +:101FC000A2FE8C6F51C2CAB36CAB51C61357E0FA74 +:101FD00064FC442B8FC3C0B711FB5FDED4BA0B7B0C +:101FE000E5C65E168DE6DB15DFC3B937CC3C6B0466 +:101FF0009F3B16308AA33AEA18C92BA8FBB893B0C6 +:1020000095F223001F4FE0B8178A639DB615921D05 +:1020100024E35686D8E0F3F89E78D9CFF547C46F0D +:102020007A0F7AE24F625DB0FF67B05FFC02161470 +:102030009F917199F83AAF62CC4775C4C8DFDA3B1B +:10204000CEB304F33FBA8633E753508F29B515A2B8 +:102050003CB5CF72B661FC66F929EE9F5F3E8FF901 +:10206000962A0179059E2CCA0342BC05FA07760A16 +:10207000F9B653AC1BF4E45FE3F9BA5AE203F4A4F3 +:10208000C4876E75AB4A78ED0AAFA702F0DAFE435B +:1020900078FD19F9F29D8BE4CB0F2F856EFE7191BF +:1020A00074F34B8C6F0C093BDF678857ED7C4067FE +:1020B0004783F8BE073ADB7889F1D2F9E69FA8A7F3 +:1020C00042E1FA5D7C42285C5716EBFA91BC6651FE +:1020D000CE707AD59660FE4FE791D812865C7A1E54 +:1020E000C9FA7B3B8D8867190791EBD5E68FC8F657 +:1020F0009A16250FCF9F85BBCFD339E074DBBFE89D +:102100001C109A07C2E79D0FE48DFC39561DD0DCE8 +:102110000AFC77A6C948277595397E370AFDF77BF3 +:102120000DCCE7A0FE11D8FF0AC6FB5FD1B4BC03FB +:10213000FD575730BD579C4795EFB91D15837C7CE3 +:10214000C55E95F2BFD866FEBC8E452C41FF744C2F +:10215000818E3902E019EB8A628E0078C68DB7074E +:10216000D5E53979AE9837C1DD2BE8FDA41BB382E4 +:10217000FAA778AE087A9E3A2B37A89E5E3722A837 +:102180007FEF85A383EA99DE6B83FA67374C0EAA4B +:10219000E734DE1CD4FF18AB7B7C14ECB33FFA5B56 +:1021A000003FCCEBEAB80CD63B43ACB7EF9AF2A0B9 +:1021B000F781FD5A311E385390C917CF8DDFAB0020 +:1021C0001C6708FFCEE5BE3941E3CF55AB887E677B +:1021D000361A8E04FA69F4AC6B4F2AC0B9C6A73818 +:1021E0005BA15EB926F8F9EC1D1BE8BDD9BEE0F68F +:1021F000B99B83EB83DE9CD29FE701B929BF72466E +:1022000042B0DF8785D08999E4F499B5DCFFA57ADF +:10221000FB6AE824185FEC27D28D43D08D293998CA +:102220006E221DC17453F9FAD6A108072DFCA3FB39 +:1022300069E8C90BFF7E00FE1667307D69E14EFB41 +:10224000837556EC50D8EF9550B8CF6A7978792AD3 +:102250000B853B633E23D71FC1ED8F68E0FD81D91D +:10226000F318CA89B33B16A8188763E3793CFFECDF +:102270008EAF07ED7384892FE584C497D62504F8C3 +:102280007F647CE934C619AF64171167DCFD4F84A5 +:1022900007C8008F01F3110B9C11DD71C5487F3C0D +:1022A000492B3F6509FAE3B904D22BFE786C3DBC9B +:1022B0003D34E60337AE53C6E564BE8ECC2B0A939D +:1022C0009FFC978404CC0FB447E3F9754BFB7C3A31 +:1022D00077C9BC2226F202C3D8FFA44F9AF1D714C3 +:1022E000B20B762670BDFE0A8ED76D1788BC2FA95B +:1022F000D77B1A47C6DF7A2A955D2AC513BB942877 +:10230000E75361F4CA47093F51BF85E68F7F14A8A0 +:10231000476AEE38BB07F50BC0FD636CB758406FDA +:102320002B7EBDFDBB682BD16BD7EBAAAF2F349CA6 +:102330008970C4D8018E2D22DFAF45E4FBC9F5D6E4 +:1023400045A4BAF479D81E9CFF27E38ADAFD8DC232 +:10235000FE71FE3ABC1764972CCFE576DB690187E6 +:102360000D166E271813B99D50AB391FD53670FB6B +:102370000CA4D7AC9680718C8916EADFDF5C684CC0 +:10238000C47184DF6579A64276C57245217BE47706 +:10239000B6D1F4FCCF09858644E8FF6F31AF1160F8 +:1023A000886563165F8F439317FE92E8FF52C268F9 +:1023B0002A8D8936E17FB65D81F4916A7619A95D2F +:1023C0000D1FA78A4EE4FB1A29F264B47180714292 +:1023D0006EA2DFDFC4EDD2E2B18941FEFEF78CF1DF +:1023E000C2DFAFD0EB2E9453BF1478EFC9FFEFEAF2 +:1023F000676B47F1ADF5FFAF8CE4FE7F191F08F165 +:10240000FF3BC785F5FF231EA2ED7EFEE993D82D85 +:102410009FD2503EED307AEAF1FCD5B51DEC7868DC +:10242000EEE7EBA4B8C0C07DD94E3C672DCF64BBAE +:102430002C486F4B18433B7F47A76E69243C5FE9EC +:1024400065367C3E7C2D3FBF55AE7138719B520E78 +:102450005C9DC8FD8706381F5B72F1BDC96D1827EA +:10246000583995D9510D35B2C6222BDA456B59D85A +:10247000F3E368414F130A7751FE764217CFB70F47 +:10248000EDA793767E21E2735897E72C8FCF717971 +:10249000422211CFA9ED3A5FB8737DB2ADE86AA4CC +:1024A000AF81BEF0E78891C24FE632BB27E2F80366 +:1024B000B7F17CD84A297F67E8981EF03E45E07561 +:1024C000CA5A9ED7C1CE7FFFBD2AED4546E333945D +:1024D0002B95532D3EF41355B6647A695D6EC599FC +:1024E00083F2A2E56D37D62BF3F36DE89770FD9D6F +:1024F0002947FB91A9C9B8FCD2B3A3529E901E8F65 +:10250000A738D464416F23F1B09C40727E6534C01B +:10251000BB72ED925D98D7F3FE1F19C59B0EA85DA7 +:102520004371B05F017016E662A967A5E4B748A6DB +:1025300071A68A71BCFF827923FCF3FEAAE575DAE5 +:10254000CF0103F346001D9DDE798303EDEEE5091F +:1025500011E4CF9371DA83AAE73E5242FAAE1A5CD5 +:10256000DA4D2DD136F4839CDEF9613AC64D3EB981 +:10257000E7AC05EDD87FE8BB2C982F7C7CD1BB164F +:1025800017C0F193452AE59DDD2AF48684FB7D89F9 +:102590001CEE1F27BA1721DC6F5BFCDDD0C03C2A84 +:1025A000B63081E879B64FA5905CB79CDD1C8D16DE +:1025B0004A77BDBA392EA82EF540B589D5853BBFDF +:1025C000BC24E86976D30663AA03E7F7AC42FA387D +:1025D000AEE774747C9BC5E7CDF4AFA7BC69B011BE +:1025E000ED837FB498582BEA337D8781E749BB8A16 +:1025F00015A00B8FC0BF769D7B5E8EA6F1663EC692 +:10260000E54719CCB510E0EB69994D7241BB8F9944 +:102610009F38C625015C67AE5018FAE3B0FF22C0B0 +:102620009F67E1FD5FA1FDA5DD679937580E48F969 +:102630005529F03CBD21F87965CB6F699C19CC43D5 +:1026400079206027699E5F730CF50AD84741ED67D2 +:10265000F6669B518F6F4914F1EDA16CD8F7F0FE2F +:10266000AE88EC184F187E92E5C9C53622D6CF1732 +:102670004750797C31A3725122A7E3AA96B7EF4461 +:102680007BA966C716238E73C9F1819613D69B99D1 +:102690005FEF96E83DAF211ED92C25284E50B3E1BF +:1026A000AC91EC32019F52D15E8AF0003CDCC21C3E +:1026B000ABF13C505A65F0C7E9E0FF5B72BFC36005 +:1026C000BF80DAD1913917B55FB94FB96FF9BC5AEC +:1026D000057A0CF3BEE48345421FCDD83869792FC3 +:1026E0000051FDCE63199DFCBC49F67891C06B5139 +:1026F000C4FD648F1785D8E3EC3DDCB7A4C74AE678 +:10270000243DA2A53B4907CC6CA0F72384BDDE4D38 +:102710006F2D0F125C243DCC5C5D68E4E69BC7C85E +:10272000ED4A6FB2F0D726A3BF16E830C83E06BA0E +:102730000BAA6BEDF12F0D9D19281FB476B8CCE7CD +:10274000D4C2E76022CF5F9AE1708DB30DC0738071 +:102750007B39F985F146CA10E4DBC63D7723DF6E8D +:10276000E47CF30F410FB3923C1149F0DCB3F49ACF +:102770001AC47FE7125306F2B367698A1A0FFD3D48 +:10278000AB1492C3A397A61811CED3970D1E877CC6 +:102790009DCB5C34FEB43816D66E189CC4E54779E0 +:1027A0009D811963082946F40B9F6A50C82F8C9AA3 +:1027B0006422E06B96C057F58AB7ADA4AF1CF06FEA +:1027C000285E1FE03FB3EA2A091F70EE08CBC7520C +:1027D000AF54B166630A8C3B67651BD1319C47825D +:1027E000FAD7B29584AFEA664D7BDDD5843FD8B980 +:1027F00011CF89B53B829FF74F127682933991BEF4 +:102800003D775A2230AF71B4804FD94AC586726B7A +:10281000FAB2B6841BA03E7DAFEA84ED74C387850F +:10282000FA23281FEDCCDE1CF2579C713892B09F22 +:10283000C7CAED5245EF1986EDD3E23CC3D0CFD8DD +:10284000F59185617EDFA1732A73E411950FA2FCD7 +:102850002A1B1B3429C0BE2F33D812311EE965F361 +:1028600093C53DB88840F8D446AC247EA8457E8800 +:10287000F0F3C3348C7BA1DDF3A24279846C473042 +:10288000BD9F703426C29190B9EF33909C2E6F8A11 +:10289000A5F371F9B22223EAD5F26DB1641FC1F933 +:1028A000F4BDCB86FAF1796859DE9E6418B7BC395D +:1028B000D3A906E331F4DC19B0CE390D8724FE8E9E +:1028C000F480BF23E1F007780B6A2F4F127249E0C2 +:1028D0008D2D8A23BD5A3AEFD59C0858D799BA480E +:1028E000CA93ECE97CC4668CA0FC03E9BF1ADFAB99 +:1028F000DBCF44793E67570E21FC69F136FEDFD30A +:1029000087A1BDCBFE6E6168674DCB66B74D86F67D +:10291000DB14CE6FD3EAAF198F76C4DD495C9EBD60 +:102920000572D0D597B1B7410EBA400EBE0BF21169 +:10293000EBEF2F4EA6FA878B1D547EB4B81F954738 +:1029400084BF5FF21D1002D1ED92242E179724C987 +:10295000F8FA82643469C6FFFBDD213A1BDE676C3E +:102960009B30369DB1EB5CC1FAF7C6A9C1FAB5D36D +:10297000601B978CE7DB150AD9A3E5EE9141FDE1D9 +:10298000DC64C47B2BAC5F9EBF9DF486C33819E822 +:10299000F1A6E2B8A0FED737A406D59F4872D0FAB8 +:1029A000268DCF0E6ABFB9B47F50BDEC9C9131A487 +:1029B000774701F1CF0291670407778E171BEFFB72 +:1029C00075DDB0A4BB60BD5FEF33D0732D3E245ED8 +:1029D00067AC519907C69BBE06E41F2CF148E3740F +:1029E000E2AF2F0E58E85CB2BC296F7F01D40F35DF +:1029F00019280FE8D0B2B85568AF1D6A4AB032281E +:102A00003DCB5561D7D88C2C40DE152D5B42F9A605 +:102A1000653E9393EC9776EF93B2EEC0F32A2E12B5 +:102A2000F9E43DD5D7AA10FE5C04DF6722E95EE138 +:102A300071B027F12AE1F44EBEAEE30A5B86F513CE +:102A4000911FF7B90BD6716A6263850EFD15EABE58 +:102A500004929FCFAB0CE9B6749E81F20C66BFAFB7 +:102A60006EC03A53725339BE55CAA366CF98687C7C +:102A7000D6051402FD163C6D7AEA01AEFF787DFBA7 +:102A800040DF03823E918E8EC732572C2D56A1F522 +:102A90007EFE76C2067CEE87A76F10EE7BBDC1FD81 +:102AA0006612E0EFF30ADF20926F8B1288AFB470EA +:102AB0003F62E4F2CB8B7CA0F8E5A69FCF96927E96 +:102AC000986E70263A496EE5A7A0DC3AB2D24076FD +:102AD00030D3BBAC93488F3E4F742CE739A2778C30 +:102AE000C3F51D69C864985F51BE52A5F30AD21F91 +:102AF000EFEFE3E7D487550FD824CCDBA07858520A +:102B000028DDDC3E6F18E55D6AED6D597E09BCEA93 +:102B100009B04BE6ECE479812CBF533F7560E03E91 +:102B200096F1F93C0541F94A5559AF1D34EBC82ED1 +:102B30008CC173C289F754A2B313598D4393019F7B +:102B40002775BB86DE05F52F267A8FEAA13E22DAAD +:102B5000F32F84EB5CDDCA0C250BF3FA0FAF1A09D7 +:102B6000EF7DFEACC1496C2EECFC39CFCCEEFD43C1 +:102B7000F615D81BBDB8DDE14AC1FBCF731DCD1AD8 +:102B80007B80C3C78149200017DB6A056D377678E3 +:102B900088E5013C574FD7314FE079E0B0C8E3B149 +:102BA00024F373A8B41BA6247339335DC7E99BBD16 +:102BB000AC707A03FB2A500F48B93D17F3AA55BFF2 +:102BC0001E9072BB8A3552FE8A2399DB2FB3151FE4 +:102BD000D9DD35988902FD2B6C3C6856B5D9E4F3F4 +:102BE00065D298B640FB607A329727738CCF3E8EC1 +:102BF000E45BC93AF83E35FD3E37F82A3A3243F5F0 +:102C00004F856DC3323B8D6F70A29FB752F06B75CD +:102C1000A3E26B253B85EB51E9579D29F4A8563F6C +:102C200085E8258D3E9AA9D1BBAC3158CFC27AE94F +:102C3000DEB25CAF769DEE680BC1610EAC0BF56F3A +:102C400085C7B7A784D6AD3801A321EBA964EE31BF +:102C5000B1B80F78DEEA085D9F765F21EB15FBD4F3 +:102C6000AEBBC2F9552BE6BB543529042FED3E24EB +:102C70003EB4769CC44B8597C3B7A245217C7ED6D3 +:102C80006D1F32F26F4BBA61CDF02FE07D4947B036 +:102C9000AF12946F95AB411E6786D2D31CD66C459C +:102CA000BAA961ADCB5390DF5A9BAF1F8E7E86B51C +:102CB0006FD3F9A9D4DE9AA38B05507A73578EBFD0 +:102CC000CA4FE7178A27FC5CF0C3DDE9A59F1EE029 +:102CD0003573A3EA8A1C14D44FE43F7A098EB3BC3F +:102CE0005E23FA6367093FE585D659ABE7F75F2EA8 +:102CF000B85E01CF9F7BDD0F27F76477853F17769E +:102D0000DB5B1A3DFFB181FB5BA57CFE5AEF22FF26 +:102D10002EB40B3BACCEC6E37D1AB99E9E4F72BD5E +:102D200042E87939CFD1355B295E3013ED8080F6EA +:102D3000CF566FA578A5F1D99956B4CB8FAE99BE71 +:102D40000AF3528F364D27BD5FF97BA9F73DC64088 +:102D50007BA2684DD9FA7B908E3747525CB1A2DDD9 +:102D600023CE452067A19F630D97AB6C3597B39534 +:102D7000A81F07907EEC8BFDEEACF0F4457E086852 +:102D800027BD79E774CF9F77C2B877FE29DAE925A6 +:102D900050D85A7564CFDB5A513F56CFFFF020DE32 +:102DA000D3017BE0FD5F4B7B00AA45064F5B32EA17 +:102DB00021610754AB1B326C683708BDF11F807F5F +:102DC0004478F8E712FCCB11FE01F1DB4F1B389C75 +:102DD000A76BE07F7825C7CBF2A66C2B9E2F3F6DAB +:102DE000C826BBEBD3A61C82FF8C0700FEDC5F1F4E +:102DF0006C773500FCF17C81F087F596B73B04FCDD +:102E00009D1CFE0D1CEE6C252F6784C0D94BF95715 +:102E100077FED1E4443BE278642BD957C7B7A8AC1E +:102E20003EC02E9376D137ACF149B4DF24FC67F76E +:102E3000E91884F2A7F4E1D7AC8887D95B785031E0 +:102E400004FECC9544F1C7EEF9BBEDA86F115FDD30 +:102E500076D445E2A986B919E9C796D70EE039427A +:102E60007171BF458DBC6FB623F8BE19E69295DA35 +:102E7000D1C5E28C88C0F5A469EFD37918C6BDBE70 +:102E8000CDF9EAD6F9C4E75D4179B925ACD580FE24 +:102E900036D6ACD03DEDEA0585D6428671B53A5AB4 +:102EA00087334509CACBAE5675644F5619457C44E5 +:102EB000E45524897E4929DC2F909C62A3F2742476 +:102EC000237D70DA62F4E17D2A385F25E3FCDE9D24 +:102ED00026C2DB415C13C05F350A3F33A842A4B76A +:102EE0005B18A7D35BCC7B29AE07279775A81FA7D4 +:102EF0002D3439C9CE8D8FA1F8D2CD42DEDD625E90 +:102F0000EE463D31CD6C746109E37A31F9D7301A60 +:102F1000A687F90DBD8C74EFB034A2F3593C12DFD3 +:102F2000967CF88E0858EA95608EA31F187EDDF611 +:102F30007D5C285EFCF809F64BD74685F78B0C17AD +:102F400070505C2EF23F9B60EC2858C7A814076FA6 +:102F500077D8B83F7A2DE0C9E2C7AFB69D7979FC42 +:102F6000B20AF3B1F9F758BC241F545D50BDCAC86A +:102F70009F4F796243F1EA34C6DE618E8188B72AB9 +:102F8000942178EE2F8BF1617CEF3AF487DBB1D49A +:102F900013BD4CD633AF8E970D663B0EC7FDE325B0 +:102FA000029EBF2A60AD3100F7D6D783FDF337B458 +:102FB000EA5AFB027CAFD3B7B6217DEA221C061B7E +:102FC000CCE31EAFE4E239A56AE9C5ADB7E289A654 +:102FD000E2D5A3A0AEE3F9AC5DBFE6FE895B805904 +:102FE000116EB7EA59BB9ACBE900E1526B7778A929 +:102FF000DF3C85E237322E20F13F18860FC4E32DE7 +:10300000627D304E8315DF3786C7D77C812FCC8C0D +:1030100046B8CF157C3757F25B5330BF3D827804FA +:103020003E55D02E06B8DD22CA9EF8E2A1146E47A6 +:103030003F94C2CFEFF75CE27CCCDC95417979829A +:103040005FAA4D7C7C39FF75A27C30C54EE3CBF581 +:1030500000BD7E8AE3E8400220BD1E69AC27FB6804 +:10306000160B88C365FAFB49BA0EAD77CB11DDF7B5 +:10307000581ABB6620E8955F443A518EDE626CCEEA +:10308000A93387F69371E652D661A0EF03493F99C1 +:10309000D03F635533E535952AFC1EF4E9428B5742 +:1030A0000776E2C722BE7B06EC469CA73456A1FCFD +:1030B000AF69317796205F975A8D7A2C3F16F1DFF2 +:1030C0005B59178DFF892D2BE60686DF4D5031E6C3 +:1030D000070BF8A4D805FBAD47F9C3EB2B5D69E4FA +:1030E0008D12F54FF7615C66EA79A003AA1F2E7670 +:1030F000C1BCA75F15CFD991627C7EFA3E41CFDE7D +:10310000E334DEE9C7E4F353FCF90AF9FC2B5E7FF4 +:10311000508E2FEA0F6B9E2FD13C7F82D75B9FF89A +:10312000AAD88BF6EB684EDAA523149257462137BE +:103130004A97B6129C4B75BB78399AB5EAF22FDCE8 +:10314000EF648ADB989280F7CE8F58500FFF33D50B +:10315000654C817E9F2679FE86E59C498AD78872D8 +:10316000F73D1FE985921EF2278D42AE9FEAE5A644 +:10317000F7A51E8371DEC3F12F759CBB43C7F9E42D +:10318000C78C734D6AC838477FCCBEFE9CCAE12409 +:10319000C791765171BA4BE985FC3A666490BF706D +:1031A000EEBDCE18F44B31CC7703D0CF5DDA9C91D5 +:1031B00007E3CF7DEEC58C0AB49B84BEAF39A7323E +:1031C00017C8A3DA730A955FB47D64C47BB335DB9B +:1031D000DA8CE3A05F2D944501EBAA12EB047DA7E6 +:1031E0009F1CA0A78DBD74426E3CCCF3329E3BA1C8 +:1031F000477CCED5351FFD3DEAEF114AD8F8F2974E +:10320000627F077BB81F61EEC5E551616F5734EEF1 +:10321000F314063960FCA2FAF0F902BF12EB28158C +:10322000FA6FFA504B8403E03CE43D1E5FAF589BBD +:10323000998BFE6263F2E804825B8F7ED62EEE6786 +:103240006DE17ED6527BC702FC4E99BB57EC83F8EA +:10325000DDB209BF937C062C0BEF8E37C97ABF898C +:103260006346713F18D6F37E9FF920F2CDDE286EBB +:10327000CF4E1B36300AE5436766B4CE06FCAC4F32 +:103280002A73F74AC0F6ABC6617BA1C9D2A78CE00E +:10329000CB882EF449EEFEB84EEC8FFE118FB1357F +:1032A000E106D887E70D95EE037806457BC2C5CBCE +:1032B0002FEFC5E5B9BB978DE0B15707EBCCF5AF64 +:1032C00043CE0F76FD820E18EFC8D294C10F38306E +:1032D0001E53785DAF04FFFCB3923CA302E73FA20C +:1032E000637DF06871B1EB182EF0711DC2064AF7CC +:1032F00028A0B780F3DEE431D141F5A9C571CC1522 +:10330000E8BF9D9A1A54BFB1343BA8FFCD33FA07EA +:103310003D9F68EAC8AF0BB0677BB697BC049F5A65 +:103320008B250AEDBA4F5ABEF9E016B40337AA4E00 +:10333000B45967EFDCF4C148E87506F01B477E49D5 +:1033400007F9D13E9779747A973E307E748A75502A +:10335000BEA23CD75E6CDC68AEAD9DF2097FAE7854 +:10336000D1BC5EE2FC9BCB72513F9EA97B9FFC7956 +:103370003566BECF532F1EE2DF2D44BD02747F356C +:10338000BE88F6E23910FCC0FF453B0E519CCD864D +:10339000C14DB4F7D3E6E9F1FE642D94A85FC68170 +:1033A000DC8A01BAE9686303B761DE48A685DBE51C +:1033B000E7A690BF7C6F14F7FBEC4D8CA5EF48CCD3 +:1033C0006DB886DA6BCE45D3F86FA91DE3282FFAC6 +:1033D0000585E2131353A72DC5FDEC8DF20EB81D24 +:1033E000E69DF8E7ABC723DC6AB6F17B0213D5771D +:1033F000F2E74159D5780DBD3F51657B15B01F628D +:10340000CEDD42E34E441B00EAEA50CB03A89755B9 +:10341000636B9F3FA0BC315A48DED49E8BA4F72635 +:103420001471FDFD7B214F0C9D7C5D63CF4DA2E7A8 +:10343000922E7CBDB282F2F70D091BF5F8BD214337 +:10344000A742FDAF3DD79F4AB9DF37FAFD91BE2FA6 +:103450006048F87A1CE68DBE11AFD8C82CD1C8E3FD +:10346000B375C362581879D53DCF399E6F6C3AC792 +:10347000F38FFF3BCDF517E4C392459D7A8C17314E +:1034800073840DE1555230D85111C067EAAE9B8C60 +:10349000881FC3EAB78DA8AF4D5016053CAF16F98B +:1034A000585A79DD22E483FC8E9BD43F2C7906D1D7 +:1034B000E7AD3641A0828F9E167C2CDFEFA0330E45 +:1034C000E0713BF7F3B7A679DE4239D151C86E7C83 +:1034D0009EE4674706C6697EAEF5039E2314B21BC1 +:1034E0003B29AFBEA4C0A1C3F8C07BDD7A87F3F34C +:1034F00085F6D126F6FD96CA16E2B86FFDF2971D45 +:103500002E18AFEDEEBC3CD40B72DECF7AF17B0B04 +:10351000CCD6751ECF87B52F473B90EF27E2E10C45 +:10352000E3A23B4D746E81768A77D4BE6C7A0AEF43 +:10353000BBD55AE1FC0AF317BD12D98A74DCF64AEE +:10354000A41EF5C71DBD3D9F217C8A5EE93B06CFC9 +:103550008BAE16939E91FDE33A4AF2B687F55E482C +:103560007E69E94CF2A7A781F34B99A0D372C17F82 +:103570001EC14767EB92880FCF2E8245633C759141 +:1035800032701BDA0B0E0B7D974EF2E5443C1F4167 +:10359000FBC4FEB1748FA1EA5C6C101F569FCB1464 +:1035A000FC1D47ED92DFCA059F98847D3143D0B55D +:1035B000B45B243FB2744F622AEC63623DF0BD9568 +:1035C000E2FEF9C84F7EBA31DA90BE806E922B02CD +:1035D000F8A7BEED2686768A29DE4D743303CA40ED +:1035E0003B6566B79D621B9708EB2F5996A9C37B75 +:1035F0009BF2796AEAA5D17F44AAC82730B7E6A032 +:103600005D6BA88B74E27D9A33F13C1E347F058795 +:10361000E37C83BB08ED8CF94F28E43F43FB03E5D3 +:10362000D2D00375C640BFCA4DE706513C7DCAB92A +:10363000CBA834267B2E4738949DBB5EE06BD08FA1 +:103640008A3F0E7171BF92C167726EC844BF9247C4 +:10365000453C1F4F67B64703E37D6B54F28FC9B8F3 +:10366000A4F43399F0DE4F803EFD46DF9841DFA39E +:10367000D1FA9D0AB9FE3FB9D140FABFAAED9DA18A +:103680003A78FE79A62B09F5C97A83A708F733673C +:10369000B2EF3903D4E73EB8D53ADCE18767B3BE71 +:1036A0003507F56933C011FD5FCD2BD5F13E6EF7BF +:1036B00044F3381AA76F49CF5A3A9F732E9BE07391 +:1036C000B6CE447AE82CD02D0BD04352EF48392F98 +:1036D000F58FA4EB6A3D975FD5E618CA23F3EB9DFF +:1036E00049EE42A4BB7E3C1FD0AF779E5A3502F90B +:1036F000E0743CE55D4BBD21F9E085C5C9944724E4 +:10370000F592E40329CFA57C97742FF5D6E83FFD09 +:10371000EFD6BFC3AF93D23C77A5027D5DABE7FA8E +:10372000EB5ABD85E8676CFC243DD2CDC5CBD143B7 +:10373000428E1E0A92A3353DE88145A9527E5E1C49 +:103740001FCC117C33DEC4ED4894F381E3B5A68D24 +:103750007E08F7B13A95EBD99F6BDD3DC9FFD5A93E +:103760009726FF97A45E9CFCFFEF54FE9D0AADBC1C +:10377000C70F71A3BC3FBDF3721FEA83830CF40330 +:10378000EAC19668C726A10F485F44C5F87E481F66 +:1037900014F69EFEDFA9E1F5C1666CFFB1FA40D2D6 +:1037A00097E41BC927922FB47C24F962C26FE1BC55 +:1037B00088787A8BDF8FAAD67B9B280EE9881E8CAF +:1037C000FCD96DC76D5388DF42F484E01F3FBF040E +:1037D000EB0DC91F925F24FF540BFE9829F843F2AA +:1037E000C56EB5F9D111980A90E6F908E588E49319 +:1037F000AAE7B5FAA147BA424F239B195FC790AE1B +:10380000AAA10CA42B530FFC70F012F5C2BE8BA41E +:10381000A7AFFEF3F4F4550FF474E6A7D053A81D38 +:10382000FB61BE03D673361FE46DA69FDE26FC8DBA +:1038300071FB219B9F07F646F17DEE35A693FF674E +:10384000C2F73CCF57DA033385BF41D2691ED80196 +:103850006943FCF8C7F3C0BC8B937B8467537C87B8 +:1038600011CF2733A10CB4037AB27F53D32E4DEE80 +:10387000458AFE17C2F380B49FDD6E1C90161EAF02 +:1038800003D37E025E2762A22AF92BB24B5CA3000F +:103890003F0F89BAB74F09C2F1FA02F9FCB2552EAF +:1038A0003DCA07D6FDDD75F477BCA5CA7ACEFE31D8 +:1038B000B09E098F32BF1F1D9E8F1D15D3ED1F5166 +:1038C00098BF7F715AD6FE95A4E71B45DE4AA79E96 +:1038D000C783443D1FEA96807A81A6BE96F7B7EA71 +:1038E0003B59603E09D28D92CBF1EC0EB01F60FACD +:1038F000F6B3A82F6C0A43FF466DFC8657CFA25C37 +:10390000DBA1506CAA1B0EDE810407FA3E38D507F6 +:10391000EF775DC6D8CDDB78FDF6B54356792F132A +:10392000E306DC1B32342B2ECA4728507C5999A160 +:10393000F0BE3D4DCA13B91E46F71402DE6798AFBC +:103940007729EF77E74D67D1FBADA64B98FF8651FE +:10395000E1EF6FAC10FDC6E4C7847DFE709ACAE14A +:103960002FFC06343F344D690E7F9FFF09C12F1D88 +:10397000183F21784E5A85FEED0EA384B77B15C201 +:103980007B2C63417E34989FEA1BD7BA4B1AF47C98 +:10399000BB2E0DBC7E68BF77A505DB03F49B065FDD +:1039A000A61F80F7DD61DE7704BFDFFA43F85A1205 +:1039B000F2BEA0DB59928E5D41F41EA377137DC643 +:1039C000C42B36B4A36BDC912BF1BCE0E7CFD21251 +:1039D000829B8C1384F0DFB4923103C84E12CF6FF8 +:1039E0005B85FCEBD675F7E7FC28E91AAF36015C7E +:1039F000C9F507EFBF9C76EB2AF44F025DD073AA9E +:103A0000EB03D6ADE5C7664D7D94867F05FF91FC3F +:103A1000407D0070CA41F9167FC8E808A0934F04A2 +:103A20009C4E897CF28ED1DC9EECC8E2E577693C45 +:103A30002EF599A0CB53929EA202E09016443FF43B +:103A4000F72102F64D70BA295EF2F3BD25C5C0BF5D +:103A50001D76FEFC7FD6FE669537CD5FD78EF7CFFD +:103A6000B5F796205CBAC7F72EDA8F76C44D026E92 +:103A7000DFADBD67BF7780C073A2FFBBAB401FF453 +:103A80003D9E6AA40F25943E5E0DA52FAFE67DFAFC +:103A90003B043DBDFFB75079E0D2BCCFF07B10179F +:103AA000FFBEC05BB106AFE335781DA3A997CABAC4 +:103AB0002F48FE4AB95CBEE3E1FB12E3D1AFA9D0C7 +:103AC00075243F3D3F48F43CD726E97715C1D54FD3 +:103AD000CF0FED47FA9DDC2CE9B591F4CF2494C3C8 +:103AE00023FCF5292887A8FE7009C6C5FCFAEA91CF +:103AF0005528B76F6890FD1FA5FE372F93E3ADA63D +:103B0000E7128F8C3D46FAEEA67CA9AF1E27B93F7F +:103B1000A785BFEF4CFFDDFE1FE487460D5CD66A2C +:103B2000EA5E4DFFD517D06FCB34EF2FD23C5FA9A3 +:103B3000A9AFD1D41B82DF2F9BA1101F9615F0389F +:103B4000A5962FB5F4E14AEFB673BAF5B96226FB34 +:103B50002E88AF26D4F3FAB5E91B4B1ACC01F575C4 +:103B60009B4A385FC06C01F79F41E67A55A0074336 +:103B70000F72B320BD07B9D94FABEFF9F37FE0AFB8 +:103B80002914370AB24B76ABC1F53655ACDBBB75A1 +:103B9000FF820181F1D5E74BF05CDD631CC7DB5C84 +:103BA0003226D02E62CD25AE807DCAFEE3BEFB5EFE +:103BB000C5F93CEBFE5CB2D18C714F11DFB4F3124E +:103BC000F4A58AFABA56F86FC6611E2FC693A25A98 +:103BD00073E60F08D8276BEE83FB6CBB5BE5DFB7A2 +:103BE000AB07FC009CCA9883F250A73317E5A5B633 +:103BF000C5C42CFC2F786FF7DDEA42D4D30717C673 +:103C0000515ED32BE9FC7CB13BA677E24CA8B745CB +:103C1000DF46F2B6EDFEB154EE525DCBBB6C8C2D9F +:103C20005EF74A89F9727C1E4370BA3BFDA5922566 +:103C300040EFF7A63BE87D8FDD96B803EDED070C6E +:103C40001437040E7892E8E741D3603C6F972DE972 +:103C50004F71B1F2C7268DC37BA4E5F719285ED258 +:103C6000A9B3919FC8F3C058CA939AB14C94DEABE4 +:103C7000A97CE5DF7FACC77BA65DEB14FA4ECD5582 +:103C80005F37FF6D10D42B1BB2E97EC6CBE774946F +:103C900017FEE99ABE3ECC533E1C5947F9A5D09F6A +:103CA000EEBB569E77EC2FC9C7FEAA0D53388E4245 +:103CB0003BDACF4757A84FE13DCE32AB250AF3BBE5 +:103CC0008F7EC7C8AF73F43E137DEFE653B3E7D6DC +:103CD00035F1748F092D7D765471581580C3DAF44F +:103CE000FD25C929D86E12F8DC6F2D033E2FD37540 +:103CF000D30FE9938A585E5FBBEECD924DB08FA390 +:103D00004FF4A57CB1840CD7BA7480D7E10CD7935B +:103D1000548AFBD9AFFC9BC7255F3A599E88F4B5FE +:103D200059D0F5CBE7CA1303FF6E41C5293DD1C178 +:103D30002B46C702FAEE6954BA82E76CA08338F4C6 +:103D40009BCF10E716A0E7855BC3D8574BD3B93D8F +:103D5000D6F6DB84518E20BAFE98E4299D37A0FE6A +:103D600062FA47A4E78E9816622E75773E24DB1D13 +:103D70004970323445FA2233D17FEA1AE7A2F34F71 +:103D8000739FC996003E14FD3FF1F2FCDF4FA03F48 +:103D90009EFB3EF1FE3F4B603C43F6AFB45ABC681D +:103DA0005C1CB358F4888F83FAC547313FAD629DE0 +:103DB00081F440C5BA84455D287F806ED0BFA6DD02 +:103DC0009729C3C0FD183DC6573F2F199316785E3B +:103DD0003941F2BB27BE7C37FD44C9C6013DF365BE +:103DE000A58DCBA771EBF8F7752B8758F474BF7BC3 +:103DF000DDAB9BE81EF0BCC85CBC5751B9CE44F8A3 +:103E0000EAB458BCB62BF1BE81451F0BE5A174AED8 +:103E10004FF5190EC24791CAF411B954D23D0A198F +:103E20003F3CB1F0D1C7311DF373E6BB7E18C0EF44 +:103E30008C8BD3E9996D2AF91FB5F1C4EAD7B71A6B +:103E40000BD98F8827F61047AC629DE2BBE2E1E315 +:103E500089DA38E2BFD2C5BDB3EE38A281BE875140 +:103E600029E288456B155A7FE542FEBD92A238EEE5 +:103E70003F3EB218E8A02FEDDF6BCBC53C69AE7FAB +:103E80002A99E28B805FAF5E3B8FFC9975E91C5EDF +:103E900065E23BB087239D1978DEAF58174970AEB5 +:103EA0007C72F6074FE4E37DC089F181E76B9BA04C +:103EB0000F189FE13D6839CEB125F7D077678BD6D3 +:103EC000C33919F3B463D973376522DE523230DE59 +:103ED00029FB552EBDBB0FEF07E76CD877D90A95A4 +:103EE0007F0F6BBB89F421F07C320BB82F3E63D976 +:103EF000EB4623D7672C79A8B0B31DFEFB6C9FC29D +:103F000073FC0441ADB8B726E127EF5B95E9F8F7FC +:103F1000364B750ADDC3028946F7977E91C1FDA332 +:103F20007919DCCE2DCB70D23D9EEA5526E7D24CD6 +:103F30003E4EF7BD7538E755EB3A2A28AEF9171310 +:103F4000F9576A9745BA22AD3C1FE3F9019477AD62 +:103F500037023CAA1C5C6EFC42D063AD63D2D594A0 +:103F60009FAE6707F0EF07565BB89CAC8E05B89B19 +:103F70003901E986E2F73919E553E2B8298302E607 +:103F800057443B8CE3B0FAC7DDAB630DE8A7C1FE35 +:103F9000970F4238C65D7F23AEEF5995F81A80B46B +:103FA000AA00EDBF67D53C3C7797ADD83D0EE5F054 +:103FB000DC2D83F146052B7BEE5DD2237305FE3BA2 +:103FC000453E5A39D4F1BB81376470B9E951B9DF44 +:103FD000E806012F4907F279F50A03F7E383BC47A6 +:103FE0000153BDE4431AB7DAD2918872B87ABB8123 +:103FF000EE87DF8CEB0638972F491F7500E8AADCA7 +:104000001043DF51ADF24E3462BDAA51A1BAFFBDDB +:10401000840CA4D32F96BD6045FA391CD99A83FA33 +:10402000A96B5EA493EE29DAB8DFEE8B653974AF25 +:104030006986ADC382DF6599B120DB8E72FCA0ADCD +:10404000D588CF0F3667EAB0EEB2D94661DDA5BF9D +:1040500092EA5F887C17FA41BA52389EAB9A761B77 +:10406000F1EF2FDD2BE8E2D4B3EFF6413F50754678 +:10407000471FD42F40077D5211CECF28A49F6B9AA3 +:10408000781EBCA4831AA403E0BB39820E6AB6BDB5 +:104090007017F2430DE23F37948E809EDBA9FDF945 +:1040A0000DE3187FBF1DE944EA33A82F33A03FCEAC +:1040B000C8EB8B05FEA17D0C6FF70EE0F975DDF9FD +:1040C00008417CD0137ED766E8043E4C2477D78A1B +:1040D000FD76AED86E45FC9D7A76F71E8CB7543FC0 +:1040E0000FDADA11861F043C6A71FF565A3FD9195C +:1040F000B5B85FAB7FFFDD742FF8B096F1FDC9FD59 +:10410000D6EAC5FEE573F1FE3AB1CF2A26E0B5AD99 +:104110002FE73BC167C8C7F4DD21B13F8F3DF8BB36 +:10412000BABBC5FE9A44C96CCD56840FE217E50FA1 +:10413000D08FCB28E5097439B56503E5F74B7CC909 +:10414000F5BFEFD72B2EFC9354128F9D3D7CF7B615 +:1041500045F0C9A1FB92327600FCBED84C9F0D24DD +:104160007AD507CC27E946CE57F4A749D7E2BE61F6 +:10417000FC561C5FCE7BD01BADC7710E32CE1F72BA +:10418000FD922F8BEAA75D3BD88AFD4E59B2D15ED6 +:1041900011787C3FC346EFBBD06E80F75D3B14F2D5 +:1041A0005F1F12E7FD43F7BD602D1FE0A7F777C53E +:1041B000BA259DE10FFAC9E47AF7DAB93F58BB6E28 +:1041C0002987E4BA8BEEBFE15A6C97EBC7F8512010 +:1041D0009D4A384A7A95F7FAB4744B3427F5AADA2F +:1041E000337DD7A61DA2FC9D9076ED78C23E3A2C79 +:1041F000F2CDBB9E56F97DE765C9ED41F78E1833C8 +:1042000007EA9F25F3AEB615623CB749A17B1E5263 +:10421000AFC0CF4A7D803E92F6C1F0DE3C7FA5362E +:10422000DE7502F15975BC631C7E9244DAA5577D98 +:10423000DDAAC6A0FF6A1BCF8393745375B29DF8A5 +:10424000A15ADC932A5BF1EEC46148F74F1B28CEDC +:104250005376DF5823DAFBB3374D1F8AE0C07B1259 +:1042600028DF4F6C1C9247E061B6C4EBF1BEC4C6B8 +:1042700047AFC7BF5F3A63874ADFA1C171908FCB59 +:10428000EEC8237FEBE1C8CE8923D0AEFFB56A43E9 +:10429000BB7EE4A6218BB0FF484BEF58FA78D0C61E +:1042A00038AABBF431A427A41D2CF303EBC5BD90A1 +:1042B000ECDE9CAF7A75978AC80BACEF83F1F9AE50 +:1042C0000D91F4DDA852A3A3B915E7DB9944E78E5D +:1042D0005A382625DBE99E2BD969B38C2C222597E9 +:1042E000DA233045F97543C71DA84F5EBFC33218A6 +:1042F000BF8BCBD4F343CBB97DCDE39071C1DF61EC +:1043000092EBC8EACDE9573B9E7C7F2F9E2BEC7445 +:104310009F91DE3FB1ECE9EB511F9ED89C63C77DB6 +:104320001FDB1949F70B8E1982BFE778A9F7C2B4D2 +:10433000F7A9E43DD7FCDEC1F69CA4FB0BDECBB9AC +:10434000ECD2F2984E2E66744FFC5C06E3FEE4E875 +:10435000EFB6627E6145A3C986F7648E20FD637C5B +:104360006BBB4ADF01A2BBDF80AF23DBF3E83E700B +:10437000C5C7BC5ED1ACF8F0FE72FBC3F753FEC2FA +:104380004CB037F16A79B73DBDFAE1EB910DCE380B +:104390003DCBF13B006736F37C8B90EF3ABCBE75AA +:1043A0004F8AE3FFBFFD2CFD13D37B07DF4793F05C +:1043B00096E7AA57802E0A72FDF0FB72F12CB29F8D +:1043C0004F2EF650795A39B46A24D2B32586EE15A9 +:1043D000BCB4E35115BF7353BD6DF0793C1F8F30F2 +:1043E000C7D0F79FBE5CBC90829A2717D7893F8AB7 +:1043F000B654F8157C545EB5AD8DDEFB72475E0B8E +:10440000DEEB7DD91CC3C59AAB20E83B9912BF3DBA +:10441000DD5796FBFAFCD71CCF72DD9F6F9E6EC5F1 +:104420007DB5FD21AE6538E2373AC6867660A5C80F +:104430002F39BA86DBD9C72362FEAB18F07C7CED3E +:104440009444FC0ED1CCB6A9D7637BC54EC586E794 +:1044500003E7CE49563CCF7DA6EFB4E23DAACFD6C6 +:10446000C8FB573EFABB7B23C6B329D87F44AB9E1B +:10447000393229844CF432FCA49EEECB7E01EDE46B +:104480003F391F45FE13F889C37C92992F72BF4BA9 +:10449000F7F9579CFF468A7DB7F7B6CBF806B517F4 +:1044A00015F0F6636BB796D0DF4FDE68B0E1BABFA8 +:1044B000DC68A0F1E7C0B94D07EB3DBE999F83B022 +:1044C0008EE7E8139BF979674E333FEF54CF33B84B +:1044D000F8FDD260BA2C0AE847DF2DEBE1BB23736D +:1044E0005C7C7F73407FE27E2F44BFB1AC99EE9F2E +:1044F0005D6A3EA9967EFFAA9117DD74DB13BD08A5 +:10450000B822FF23DD4ABA98B386C7F5EDCD830BF9 +:1045100091FE249D68BF03586F64FC3BB2BA28FA31 +:10452000EEF724B3C380FA624A7CE718044F5F07B2 +:1045300097AF6A91CE85F7E458BD29EC77C4DE15B4 +:10454000F2781ABC4BF7BB7ADBF8F7CFC47D315950 +:1045500082BE4A477D3E29DAFE8D03BA74AEFFF271 +:104560003A3DD0F5A491F63BB29D80D7F55FF37A42 +:104570009E7D7B16D43FEF7DF63A3DEC6FD295F6EB +:104580002106A82F59F2CD7563E0B9C9E13AD83BAD +:10459000609E139B92D2717FD07E08DBA7277A8E14 +:1045A00060592BEE8F9D56BA062DCCF4F77F7BA772 +:1045B000E5E04B0E7FBDD3C0E8BB3BA77BCBF587C7 +:1045C0002F9D0ED7A9DE09A1EDE58CDD47F97C5EB4 +:1045D0007E6F077EDC118978AF8AD35DB9BCC7D303 +:1045E000A0B9C7E3E4F7D5E4FD2A797FEA72FFFDBD +:1045F000B3B59772FFECFF0069F3B24F0080000083 +:10460000000000001F8B08000000000000FFE57D97 +:104610000B74545596E8B955B73E492A4925845438 +:1046200025A984AA7C2B90C0257C0C3148E5030485 +:104630008858286AD4A005A2808214011D74F455FC +:1046400061307C9AE98E9F1722462D10957178DD96 +:10465000D1B16D868F532032FC9A0EB463EB8CD3AC +:104660001DD0D168631B3138F40C366FEF7DCE4D11 +:10467000EA562A80BEE77B6FAD975EF6619F73EEC8 +:10468000F9ECB3FF67DF5B5F192CEBA564C6240F61 +:1046900063AB53A1745A596319947BFFE9CFD26875 +:1046A000C69A83AC3B2E8FC15FA3F5D35150CF7C0C +:1046B000BA4B502E4B481ACDC660991362D06F99F1 +:1046C00089B1AE12E8263B6DCCC2D81209FE9D011D +:1046D000FFF9CA194B676C9515FEED44B84287F097 +:1046E0008366467F9F05983FDFC0D81F4F742539EA +:1046F000F58C9D9D1D2E0CBB18FB65BCCFE69C0068 +:10470000ED1DCD8EA634C6BE7CC3A4D443FF9ED07F +:10471000DF27F960FCA57AE6EF84926D1FCED824DE +:10472000282FEAC353A0DF6157F1B68DF0BCCBA9A7 +:10473000630C9E3FEB0AE7FCF578C6822E93F232BB +:10474000A37E773280EB1E9F3E1CFB9D7D7D5DFE30 +:104750003DB06E93CC5812EC7B068C590E7830002D +:10476000AC2FC30742340EB40793A0BEC5F5740E38 +:10477000237C302F9BC8D80D8CEFEB0639BC1FF182 +:10478000C5946419F7379B6F0FDB83328CA33333E7 +:1047900003AEBB9875583F4D0098B18E4BC3607FF8 +:1047A00066C063329680C724C6A6EAA113ACAFE9FF +:1047B00097FA9009D6D784781470D085237A2CD7AD +:1047C000C3F88BC5BCCB8EBC6BC4C15810FE07EBC5 +:1047D0005922E65DDC71773D9ECB9290E14CB7C0EB +:1047E000F525FA7F0F9DC772D1EFFEF2AD469CE230 +:1047F000FE1DDA7ECBD9A6AFF5F0FC52D66DC4FD16 +:104800002EEB8C6AEFA8F90CD7BB7C97B6BEDE996D +:10481000988674C2C6B2B197F4544DE7BD48F49976 +:10482000AA6F74CAB89FE166C50413373D9F47F469 +:10483000C2DE0CB0C87EAC6318D14F8B4B4FE7B1D2 +:104840006497C49CE318BB7E5716734253FDAE6158 +:1048500054265DC8A0FACF5F3936DE5732705ED776 +:10486000BF6AABC6F55DFF6A1195EA3A9A041D4E20 +:10487000D5977486611DE72CB00E809B8EC0628137 +:104880007E9A6ED68718E19999B1BF572CC76B599C +:10489000DFA54F42580E8AFD4A97243A84643C1F94 +:1048A000EF613D437A621E03B53B9979CDA55CA0CB +:1048B0001BBB8E3963E0DF24CE2FCE19CF9CEE8157 +:1048C000763958FCB34A588761AE4109417B735C25 +:1048D000D236E43316F474E5C3730DE2B9AE384E44 +:1048E0003709EE54CDF32A1DDC2AFAAD4B9A76181F +:1048F000E9B2C1B388E82151C9D4ACC7A45F6A400A +:10490000FAB9D567F8A43B621CA25F58C70D5E29AF +:1049100084FC787383B6DD50F975AD4425D4478E99 +:10492000E7D5F6FB29D203D03B107E71243D0C9CC9 +:1049300083C5A3C373F02412BDCBCCB9B912E05B1D +:104940000E1B18EEDF14CFF7790E319786FD800F1E +:1049500060E2758817A84F2ED7E237C5A3C5E7B028 +:104960003A2D7E867BB5FBB735E46ADA337C233596 +:10497000ED598BCB3470B6BF42D37FC4EA6A0DECDD +:104980000ACED4F4CF5B7FA3062E68BD5DD3BFA84B +:104990007D81A6BD38749FA67DD48E260D5CDAF984 +:1049A00088A6FF985D8F6BDAC786376ADAC71D7EE7 +:1049B0004A034FE8DAA2E97FCD07DB34ED93BA5F13 +:1049C000D3B45FDBF386069EDCBB5BD37FCA850373 +:1049D0001AB88A1DD3F4AF31FF56034FB5FEABA60C +:1049E000FF74FBC79AF619CE3F6ADA67B9BFD1D216 +:1049F0006B3C9793D72BFFA579EE5993EFDF505F70 +:104A0000344B95DD4186F4EB243EBA354DA7840145 +:104A1000FE832A97041D9E1C612539C1F2598EB769 +:104A200014E9B0328C7C7C6E9744F2E0AB28BD2850 +:104A3000FFD1EB91A09DFD4A525E7622DD415DC41F +:104A4000FC291E339323D639ACCEAA81877BED9AFD +:104A5000FEB606A7A63DC3E7D6B4672D563470B69A +:104A6000BF5CD37FC46A8F067605EB34FDF3D67B3B +:104A70003570416B83A67F51BB4FD35E1C5AAC6926 +:104A80001FB5C3AF814B3B576BFA8FD915D4B48F89 +:104A90000DAFD7B48F3BDCAA812774B56BFA5FF3F7 +:104AA0004148D33EA97B87A6FDDA9E4E0D3CB977DF +:104AB00097A6FF940B610D5CC58E68FAD7984F6A74 +:104AC000E0A9D60F35FDA7DB4F6BDA67383FD7B4C7 +:104AD000AB76D02CF7D7DA7A61175DAFFC59F37C4F +:104AE000B0DAC3903E826F484AB313D6EB02E13F7F +:104AF0009CE47C779C1EED282F18148C0129AD4175 +:104B0000FD920C420CE90A488C35A6E22840AC2004 +:104B1000B74955C1F3C9684F0090AA73B9FCA01FEB +:104B200013D85AEBA766B21B1C9740DF5DC2BF29A2 +:104B3000834B94A09FAAEB85F966A14E023A6F724F +:104B4000F93C2E58CF7D9DAF4FCB626827045B7038 +:104B50001DA00793BB416F9E886377794B068F3703 +:104B6000C30C788998EF485CABA3CC32F4FC33CC0F +:104B700067A97FFFB8063EAE04FB6B8A18FFA7A0AB +:104B8000EE65B0FB5A03C037058C3D15B012FC4CE6 +:104B9000C04E705BC049657BC04DE5968042ED1DFF +:104BA0008172825F0878080E05EAA8DC16F052FDD3 +:104BB000F64003C1AF047C54EE082CA6F2B5809FEA +:104BC000DA77065613FCF34090CACEC07AAA7F2348 +:104BD000D04AF09B817682DF0A84A8DC15D841E5B3 +:104BE000EE4027B5EF0DEC22F8ED4098E070E03094 +:104BF000C107025D041F0C7C40F0A140379587037C +:104C00003D541E0DF452FBF1C0058207CE4B6B578D +:104C10003361572E1274C0D2B83D792F3F52F685BA +:104C20008E2D46BB7791A04343359887407786CC3D +:104C3000C26DCD2E3C6AA01337D1C971B42FAF9687 +:104C40004ED070407A0D563337D29B5AB654E9C9CC +:104C5000FE0CAE90422F73BB88EB6F3353F537B524 +:104C6000373E2885D09E9B0776B211F8E623619FD8 +:104C70007C14C7E5F539BFC18D765FA314AFC0665C +:104C800001FE77B23BE02F8CA47FD75ED356B49F52 +:104C9000D4F535C2383A18E7BFEC2E5A57233B6C8F +:104CA000C0F540BD470FFC72C6E6DBE202BABE2F7C +:104CB0005B17342213594285DE44C68C76DFF348F5 +:104CC000E7E7FCF71CC2C1175995429CE77A537875 +:104CD000F8AD307FEF11BDB2CD39345E96B7CE005E +:104CE000E17D99F6B73F77A01D5FF717BD0FCFE1C4 +:104CF0008421B1210474DDE99288CF3A5D3A4DD91F +:104D000066F7FD02D7F96DA2FF4E1DA0F2DBEB5650 +:104D1000BCB212B6D4B8A22019ED55F00F0C685FE2 +:104D2000CF614E03CA879B98E75D1CEA66E623F8CD +:104D30005616A452B6F976E1BE6E6321827D15A6A1 +:104D40009C58FB8A5ED73B38D8702C759AF290DD60 +:104D50007700C7FB36D143EB3A31697A21EE4B5DE0 +:104D60009739C349FD66B3DE17707DDFEEFBFA535A +:104D7000296F309DFC88F4618169B03F33C2793777 +:104D800003EFE038CD0F4B21A473953E1AC14CA719 +:104D9000F11F857A29925E804ED07F4BEBCD99939F +:104DA00048F4D24DF26F923E68047BFA842E542868 +:104DB000E9894E8C12AC73511AD049EED0F4F0C090 +:104DC0007A2823E420D0D91738DE9FFEE11A37E293 +:104DD0006DF9DB939C88B7661D9C07D073F0A89E85 +:104DE000EC042644BBFEDAD210F907B2A2CC29C5E6 +:104DF00073E37271BF9EAD7E3D86DC4DC8E5F474F1 +:104E0000C26EA80BD1B89CEFD5767D2E3F477D2E84 +:104E10003FDFA6159F2DD5C3FA4F1CF8DCE82C8D7B +:104E2000B18FD53F79283F82AE97EF3A3DCD837E53 +:104E300017EB2EB93171A0BE50CCABD291DE98E801 +:104E4000DB6A895C573F5DC7E7225DA7005DE7111C +:104E50005D7F8A76F96C9333F95628BB013561285A +:104E60007D2F5AC97F5CC0142A17322F958B800C76 +:104E7000908EBDC1278D88F7FB5827D53F507E7790 +:104E80003AD2F5BD3A1FF9D94B5917D52F67BDB5A1 +:104E900078B437AF5FF3AE1D567D53EB9353914417 +:104EA0006F0CCD7F17CB39DBA54F834EE293EC5CC3 +:104EB000C047B7E47F2213E6BF7D67D51359503F43 +:104EC0005BCFCF851DE3E7A2CA91E87D035F14E0C5 +:104ED000F3DFA678685FFAA43A0D5F343ECE3C1249 +:104EE0008CD3BBCF14DAE68AE093F2FBFF9085F215 +:104EF0004CEEBD13CF7BF9DBA6543CEFFB18D7FB80 +:104F000092478DAFA8FA9E11BDDFCFE215ECF78571 +:104F1000A0EF2FB219D1F71712388A65037628CB84 +:104F2000F1D9CBF206F4F672DDCED18827D0EB951D +:104F3000780EF77DDCD932D685FA2094837688E125 +:104F40003593D2ECD2E817762901858D9F213E7FDB +:104F50008AE38E19BC2EA9FCD09FD1EE301959D00E +:104F60005C467CCE26227F671A89BF9A11B57938B4 +:104F70008FD7E9B70C1EFF8458EFE1EFB83F1D84CF +:104F8000FDBC2CC59A87EB2F53FCC03C2447D2199B +:104F9000CD73472EE763753E66E976A09D7E34C1EA +:104FA000773B9E8F1A4752FDC8C3AECFF2F17C66A5 +:104FB000576C50E5338DC7AEE372E984C11944F8EC +:104FC00044954B0109D62F6F6F28FFA70F701D372F +:104FD000982D618C77B04AC3D97EFF3577401FDFAB +:104FE000A0EAE3CAA8F88E1AF7618A01D757CC3E27 +:104FF00052F141F11D554E0ED2BFB0B12EC49F8863 +:1050000097F5C779FEB93FCEA3C3798D428E32E6BC +:10501000777B23F8D4D600AE8BC67F30B37C8DFF70 +:1050200060D5C0D97EBBA6FF88D54E4DBB2BE8D638 +:10503000B4E7AD573470416BB9A67F51BB47031736 +:1050400087EA34FD47EDF06AE0D2CE064DFF31BB72 +:105050007C9AF6B1E1C59AF67187FD1A7842D76A53 +:105060004DFF6B3E086ADA2775AFD7B45FDBD3AA72 +:105070008127F7B66BFA4FB910D2B457B1BFD5B488 +:10508000D7985FD7C02FC6F178E754EB3F689E9B57 +:105090006EDFAF815F88E7F19A19CE23DAE7C5F9B1 +:1050A000066F8B277E98E53EA969DFFFC8C8CD8DC6 +:1050B000C02FA14774E47FB6D5713DC51AAA391D2A +:1050C000C4F1BED72B1F6AE6CBD1F7BA908E9D7A7A +:1050D0006B26F2757EF99C034076ACD0B3A21AC55C +:1050E0009DBBEEC903588EF4BE5E8D6C53D270F238 +:1050F0000096A37D5F570319336571CA3B5896F933 +:10510000C7D6D87089ABE7BC83E5C4E08A1A94B3EC +:1051100060267EB108D67D3E38926D84752565AADD +:10512000715E0FD1EDAA0C1DF1F9AADB2C14374BDF +:10513000BFD622A33EDF1CE81A7910ECDCF4A7D31B +:10514000D762DC693DD8F9A122B017C0EEC7F25989 +:10515000B0EB43E01C6D04BB1FCB4D60F763FD73E8 +:1051600060F7239CFE74D97A7C6ED5C97BEA7261A4 +:10517000FC110FCA563453D739752B0EC07AEC0F79 +:105180001AAD284B8CAE67E29CB08EEC65B08E0AEF +:10519000428B0751FDEC52301C32391C07FDEC2BC1 +:1051A000741AB81DFF45B02E588BCF973EE9DEAE7E +:1051B00030F6F9B6B337198A619F795DB76D4D0145 +:1051C000389779E602BED3F12C60FC93798FCD0934 +:1051D000960C8697147AFF487249EE2C463EB51617 +:1051E0007D9481EBDA50FD85A2B3E23C8FCC390887 +:1051F000EB7E7E78BC58E72373AAF2AF665CCF796A +:1052000094EF50EFEF8C2147FE53E8FF93795C2F2A +:10521000C39F15E5938D9308B3819D940CF276F3AB +:10522000A4D5A7D1A790AD4109E523BB08CF4F1462 +:1052300028C823784AFC441EB247795354E433E724 +:10524000C178361FD84E91F1B1C55A78339CE71911 +:10525000C3C07A0C77E98232ECC1F0925751609E5C +:105260008E79B05F80371BB5FE65918E917D719F01 +:10527000BAEE8B372968A7DD97C7F5F09680BBECAF +:105280001303FA7F4AD9274047998BFD920FE4AB6D +:10529000ADD1AB04A19FE1D2DFEF372261DFC53A88 +:1052A000519F63FD9A08BB27478C6BB8A427BC1994 +:1052B0009ABD4A6AC4FC06BDE4EF8C617795E6C9E5 +:1052C000FCB96646ED86771E969C305F666348BAE9 +:1052D00087C6F14B0AD4DBC2BC3EABB1535A08F0CF +:1052E0001D794E3A07759CACC5B0FE083CD9E5A0C7 +:1052F0006485E7ED8F0625C483DDEA555822E2DA9E +:105300004BFCBD52F0B47DF5C4B24F86E1BABD8A04 +:1053100017E79BA5F29BDFCA703D1F2BBFA942BDBB +:10532000F61B3DC3FB8C6F9C4A725A8C7DA8A5A9C5 +:105330005BCF3C97F16792721EF1939EBCDDE22C2D +:1053400000FE7DF1364BC3D6187476471EA7B375A1 +:1053500099AADEE2EB49D7733CA9FAEA1B2BA71FF7 +:10536000556EAD4CE1B03ACECAECF12437865A8F77 +:10537000AD3D8EF922D6BB19E6B1E2FDCC772BAC60 +:105380008837F021BC349FCCE5E9D6E7DDE4374629 +:10539000D3CF203E00D19B5C8674D91D6A06BA31FA +:1053A000CD332A682FDAFE5B8B84722493B54A28AA +:1053B000476DD9B58765D4E7B2AFD81BC38EBE128F +:1053C0003FA8E7A9DA2583CFCFF9BB2AB2430D0C5A +:1053D000E9B6C9E5B4E1F9A974DA746478AA2FE2F0 +:1053E0003CD70B3A2E67AD7AE4D30AD6496525EB54 +:1053F000A2F23AD64BA58759652CAB9942652DF39D +:1054000052398DF9A9AC63AD54CE649D54D6B32EF8 +:105410002AC1BFA3D2CBACE487DE08760C96739981 +:1054200097CA5B989FCA2D48DF13F0FEA195E0DB79 +:10543000592795BB80FF9D45181F3153B917E43993 +:10544000966F833CC7320CF2DC69C2F8889BCA8332 +:105450000185CA4381722A0F073CD4EF68A08ECA27 +:10546000E3012F9527020D5476057CD4EF5460316B +:1054700095EF05FC54BE1F584DE507812095FF129E +:10548000584F659111E40AE2DBDD3D16FD9A9C8FD1 +:105490008D1E27E8A34FF384FFEBD1FDF7E2F178EF +:1054A0008E3ABA83B1D5AE94901E6D6E9D2704E5F9 +:1054B000467793743794EB4E703BD6644B243BD9BC +:1054C000D6BE4A72C2B8BBA46E7D029CEDDEBC0F94 +:1054D000E798414F54ED656B1314847FFFA419E8DE +:1054E00070ABC1DFBB15DA7FF5D2BFCE3183CEAE54 +:1054F000483CF5C7D7384CED930EB2662BC007F287 +:105500004E3F9926F175A0103EFED2C773D6E4E354 +:105510003AB91C79D5058E36FA190F5BC8CF18DB5E +:105520007E66AC0EE049AB2D65E81F47F4A3B8F5E5 +:1055300050FDA2DBD5E73A56A437231ED67D0AEEEE +:105540008913E565F7588CCF458EABBBBAF999FE48 +:1055500032F347F6932E335E5191E754DEFF037426 +:105560001E4DDF864B1FBFAEA3F8983515F5FAF632 +:10557000142E777AB3E343DB60DDDB5305BC219F58 +:10558000F6B50E61D8D7BA8DB964C76F8FF3361DE3 +:10559000C1F6BFD129DBA0697BBC6F6331C1F914AF +:1055A000AF5997EA77A35ECA49E0FAB1CDF1489CBA +:1055B0003382FFFF22E4EEE6CABEAEADE84FADD7C0 +:1055C000B102786EDBFA051BDC30CE4B9BC02E029D +:1055D0003879F2C20D05D09EBB4137512F641EAE03 +:1055E000E3A54D0B5FD928E1B823530B61DC3C21C7 +:1055F0003F7386758F5D0974DE66D4C615FAF56350 +:105600003EE7978530CC19D0BF39225EB1D5C01A9C +:1056100022F566413E97B73545BC344CE1F13CD3A9 +:1056200088F8D0E3B0FFAA113CFE93BED64CF19FA0 +:1056300074C77F9E9C0EEDE91D3A054D5AD9B6748C +:105640008D01FD9EDB5827F2E356893F1FCCE6769D +:1056500032182CB97322FC1EB037CAF223E2A7F627 +:1056600086A084718CAA114B258C37A73BEE933012 +:10567000FE91DEE0937C89E827F9A9FDAE229F2BFD +:105680001FD6676F84E735F7B1BE0C3C5798B781DA +:10569000F20964561639DFEC228E872764203DB468 +:1056A000DFD71A695DD1F89AE5AE1E993F7CE01C00 +:1056B000A3DBBFCCE7E7B8FD719802F960128F1F3A +:1056C0009C783993ECE5D96DF11EF4234F3C39B247 +:1056D00096E0A72A3C68FF9E78B9621A96B39F9A13 +:1056E00049FD4E48EC30C605663F75BB8CF53979EF +:1056F000B02E1CEFB491E871F653F789E71FA9C5E6 +:10570000F6725DF0EFD09F2E6F7E2D01E3051589B7 +:105710006F64617942D7BD6A3FCC7F8395FD1AD50E +:10572000B57743DADFD4C13FE63C996BC0788C375C +:105730003F97CEF326E631F07C072FF9B7953BBAB9 +:10574000DE018B8E5DD7D95B83D7BA9E5DD6835839 +:1057500056871534A359ED61EF412CA775F96BD12C +:10576000BCA9FBA0F52096DD237D5EC4FFABFFED59 +:1057700096375E0578C463ABAC6887E63FDE3D6371 +:105780001BC52F0D0CF9A16092BF558F046CF6A6B6 +:10579000A27C78F6195987FADDE46A8D43D8744FF4 +:1057A000AE0EE34CDB535A17D3BE0BE219E2F128DD +:1057B000E821A48B82146F2AF213F0259DC39D82E9 +:1057C0003E4D297E6B0AD68B7B8EFE7EF11C5ED809 +:1057D000DFAF354EA27952A5A0C4CD08B423EC4268 +:1057E0009FB7337F06E2C396E8DF8AF1AD822ACE07 +:1057F000FF2C91D305766F99488F50103EBDD53F51 +:105800000BCFC1E6EBCF1BE074076AB0DF3EC925C2 +:1058100098EE7F364B1C063943EBC23F8CE7A45B06 +:10582000D2C9CE51D76F6B80F122EC0EDCC78D96BA +:1058300081E754BADB20F6F584280BE6F3F1D4F5C2 +:105840006ECCE77A1DD6EDD4E17AF4623DB00F5DFF +:10585000C47A22FAD1FEFAD7CD143BD205637E89F1 +:1058600097CC2947EE7FA1CE13371AD7FFD65F61B9 +:105870005C2909E508ACF367FB2799914FA3F7F181 +:1058800042BE88FB80BD8CFEC34C1FE7DFE646BFEF +:1058900084FE940D61DCBF43F6605CD46669920CB3 +:1058A00011FBB539B89E9ED9E8DF8F7265667982A3 +:1058B00082F43D8B75AEB572FE3E980FEB2B62FD08 +:1058C0007F163671C04E7CFE99F74EE2913A5867CA +:1058D0005531EACFC7EEA5BC89CD8FCC3C8CEBCF40 +:1058E000743FB93F1506F47E2DCE7D3E8F6F6577F0 +:1058F000C89ABC872CBFACC98BC858AC6D077AD08E +:10590000C02A5DD9A5D529A86F7409253367A09D44 +:1059100092A423F90E724A9A1BD31E8DA22B817F6B +:10592000F57CDECDCFA773B359F839B05EC57C7373 +:10593000A2D8AC7A4E306F33B07932D07D73AD3EA1 +:1059400024A11F8FFDF132B2970DF7260E3EA7ADB1 +:1059500006E7CC1928A71FD45929AF2A0AAFA06798 +:10596000FE99FC9407D3A81DEA6533C53D23D6AB49 +:105970008F056BCFE34AFD3B5878CE0CD7E0FA4C4D +:10598000C7DC99A8673397323AFFE8F6A247B5E734 +:105990004A7EEF788CA3B150F8079CE74CC7F65AC3 +:1059A000B4EFA3CF55A5BB9C61B1F5C223055C2F15 +:1059B000E42428A7EAC8AE90C94EF066CBC323FD05 +:1059C000A4EFF2B91F30E55716D243EC6373081FFA +:1059D00055C25D3F298673A8EED3A1FBC2DE3D7E92 +:1059E000E0E999504EFDF57B4DC7A0DFD4EF2CE3E5 +:1059F000B07E37EB9E8181A0E06103F98D6BBE7CA8 +:105A0000A5150344CD8D4C41BDABCEE328E0FA6E25 +:105A10008F21E425F95A2CB36D2407D9C54B11F415 +:105A200002909EE887B7316F632BF991B6FC12861E +:105A3000793CCDACF30ED297678D0CE3AF37363897 +:105A40000D55B0FF1B1B9D86F9789F21B33AB423F7 +:105A50006E6A50A8FEA64685D79B79FDDC060FD559 +:105A6000CF6DF4F07A0BD45B300F29D41580716FB1 +:105A7000B6A43A75781FD0E8E5ED174CD47E1CFC2F +:105A800001CC278C8F0B91BC6FEDD1F17B237F7CF8 +:105A90004882B59A12CB0E3B117FF7E8145017CC11 +:105AA000942D332BC0CF3678437A687F8E853210A1 +:105AB00091BB1736790BA17EB743B6E2FE76837BA6 +:105AC0008BF947C1A532E19DFE00DEBDD841F73A12 +:105AD0005B45FC3EB8C44CF166B07528DECC9664DC +:105AE0000A3B86B7772CB086D01E033948E7D87BAF +:105AF0008F4C7600C8C3A36EB48B76E62B189FCA72 +:105B00005CAAE5B7F4850BAA68BC4666453FBDBEF6 +:105B1000918FD7BC5317D2A15D65B97126D241F3DD +:105B20000EA6A03FFBECC253B5C310EE50142E3F9F +:105B3000B472A179E153479CB81FBFCE5A40FD799A +:105B40001CAFD95FBD5D2F0DF0339DB773407E0C48 +:105B50009637CA611C27635EB582F1C174D827C627 +:105B6000F33B8CBC3E78A74CF72DE90BE5B075F400 +:105B7000007F670B14A6231F26917CD1F0D7C89D08 +:105B80005AF879C1A7C0EF32EE2BB89D513E67D1CC +:105B9000766D3F90933A9457D9EDDAFA5B8BFAE33E +:105BA000021A3C44E3D9E6E7722F7A9F03FB0AC747 +:105BB00015D1BE747C5F28D7A0BED87280EA8B1B3B +:105BC00065C5E94479D7790AF75FB453666180EB1C +:105BD0001796CD447AAADFA4A3F0C8F5AC8BE4C233 +:105BE00095F6ADC63BA2F719BDBFEFF2F55C8EA8E6 +:105BF000F6E01366B207DB1EB6E8F09E15ECAD7852 +:105C00008C2BDC55541D2C407B40C81DC3253D9773 +:105C100027CD16A25383ED517764FCA16554F5138B +:105C200005D46FD88D753C6E41FB8E96633F17E3AC +:105C30004DEAD6E6E35DDB131F953FA6CDC79B7209 +:105C400021332A7F2C2F2A7F6C94A67DAA755C5461 +:105C5000FED8B551F963351A78967B96A6FFF5CA3A +:105C60004D1AF886F23B34FDE778EED6B4DF547770 +:105C7000BFA6FD66EF4A0D7C6BC35F6BFADFE66B78 +:105C8000D6B4DFB1F8279AF668FF492D771570F979 +:105C9000BED9EE3F49016CD0F791F73D6A99DE28F5 +:105CA000F7469E7B5202B7A7A2FBFDB980D3FB8BC0 +:105CB000129F8F05ED9A781CF3D835F1BA7045859F +:105CC000B91BC6711A95DF21DD62E20EBFBFB66B4C +:105CD000EED9F63F0EFD60BCA6C45C1BEA3B8CFF10 +:105CE000FA40B9378774745F615BBF4A223DB86977 +:105CF000158FAB5C30523CAF7F1DAC8EC6FB46DCD3 +:105D00006BA9EBEC1071A42D18474285E49941FD75 +:105D100056C6F17E3F4D57E38E3E1A37A3DC18A4DA +:105D2000FCBC857E09E3C0CD3E66C57B9374CB0287 +:105D30009AFF9B0625995D262EDA16B0330FCC67A5 +:105D40005F155C6384BD7D52D0F7D4B3F0BCDDCF6A +:105D5000281ED35BF0ED53188FE943E108749D21B1 +:105D6000733C3FF7C0EECF5F81F9DAE6A597A15CFF +:105D70008D6ECF5ABEF7EB4397697F6ED95B1FDEFE +:105D80007BB9E71FD875BA25A27DC838694326F3C9 +:105D900044D001E02CE6FD805CC8F5F9F20A23C589 +:105DA000B1AE01FC1502BEBFAAF8CF893BE0B93FF6 +:105DB00039FBEE443B1DEA65AC877E84D73FE59F07 +:105DC000A3FC929C5160DFA3FD1D179B6EC715724B +:105DD000BA956D8DBD18076A4A343AD1CFCF32BB20 +:105DE000CA3E1907746DE07E75B4FFFE5CBFBFDD6F +:105DF00049FE779118274B947A2B7F9E99834C4EBE +:105E000017F71431F0A14F6A97505E652E943F8DBD +:105E1000E48BFD89468A23A45B44DCC1B258131786 +:105E200050E306FB13EF9590EED3C34B289E8FF102 +:105E3000021C6F5CA193D6111D2FC832E7D3BA861E +:105E40001E9FF5D7274831E6895A871A9F889E27D3 +:105E500084F604EA9965F1644F44EF7B4961557912 +:105E6000E170E4D7DE93D3517E9F32903E1C8A5E70 +:105E700030CF3C1431FEB442EEDF63FE78643DE681 +:105E8000878722E3D9CC41EF2B100C2A6684B17BA3 +:105E90004311CE7794CF77C2A0D8C91E04B587FE30 +:105EA0005F7D21D703D330976D38F219F7CBDB81B3 +:105EB000AFB1DC12B0927DD601FC87F00B012795C3 +:105EC000A1809BCA6D0185DAB707CA097E25E0214A +:105ED0007847A08ECAD7025EAADF196820F8E701CA +:105EE0001F959D81C554FF46C04FF09B81D504BFCF +:105EF00085F66001C6A9D753B93BD04AED7B03EDC7 +:105F000004BF1D0851190EECA0FA03814E820F0642 +:105F100076117C281026F870E0309547035D547F99 +:105F20003CF001C137E33EC9AE58DF15C078854F5C +:105F300076A27DF7AC6FA115ED6BFB7C9D15C57945 +:105F4000BB4FB704E31C1D8DFC1E13EF23310E0461 +:105F5000766808ED39FBFC678E4CA5F6B9D4BE19FE +:105F60008704A7C4B682DBAF6C9991FAD930210AB5 +:105F70009EEB58DA18D203DC5A184FEDB61532F9F9 +:105F80006DCFE9FC2985DCEE22F96D3370FB41A56C +:105F90008335855CDEAE29E4F75C1F16F1734ACACF +:105FA0008BAD479E2D54EDA6F587717FF679B03FF6 +:105FB0005CEFBC5566BC97B5DDA3B3727B93DFCBBA +:105FC0003A60BFB87E580FC585D97C6E2FDBE6AD31 +:105FD000A57539E6DF48EDD6A24753D04F6FF7AF2E +:105FE0009A43EB6D9429AED9EE3B9082F76CCF8942 +:105FF0007C27DBF0786FA864F07A9E8D5A7F07E3E8 +:106000007E8303ECA5D763EC03D36E49CF3011C771 +:106010007BD41C338ED729E8D72171FE630FCAC405 +:106020007F2F30B0FBE0B92D60DF05510E54BFB6B5 +:1060300002E355BD85BE9D28379F778E3F20039C88 +:106040005AC7C7CF5D25BF8276349CF7E72D50BF76 +:10605000E1BE4D5E5CEAB04DCE35C86EEDF3DFCAF1 +:10606000C0F89743D29E8F5ABE2DF6F982878FB71C +:1060700065954CF164DB8A375D07F9BCBB91FF3352 +:106080008B3E8AC3304CDE5CA70E4586639EFC3592 +:10609000CE1777FFA63A42CD268F3ADF589CEF6A9B +:1060A000F134E2B15A9B2FC6BA869227579223BF8A +:1060B0002914EF8164B12C9423CF19B8DC0A9EE433 +:1060C000F62425054D1A3C8F9A2FA0E60F44E70BC6 +:1060D000FC5EE029CBC462DEE77ED64FBF413AD7F3 +:1060E000173C1BBD9467E3923149873519D8127A62 +:1060F000EFA72ADEBA26063DA8E55328C700C11F30 +:106100001632712E9BEAF8383A3ECE64B682E02A07 +:106110008B3518435EABE533629C7F2BE4749B7533 +:10612000DFCE0D87F07C8F1A28376A8B2EB401FDE5 +:1061300084E0093DC9D74C7DE7D65722D6F51741F3 +:106140009F5B8CA162BC876E87F14A50AE22BF94E0 +:1061500050FC82D547E05D7DEE3F841DF0FCC575A7 +:106160002974FF3C6F6D1CDA47EDCC4CF46033F8BA +:1061700053C646D0830DE932067D388B8C340EFC35 +:1061800059AA26E2BD0CD7CB35289760DDFB162631 +:10619000913EAC99FFDEAC310057F6C994CFB265A1 +:1061A00029CFD39CF4EF3ACA1379FB31EEF75DF7B0 +:1061B000502DBD9F9421CA67D1CF83B2723D53C287 +:1061C000702E950B2D14BF997C413E13E9A75148C1 +:1061D0007A3CFA173C5E736DAFAC790F6D528FB697 +:1061E0003F60548F764646B7B6DE3EEFCDD353615F +:1061F0009EF6A5FCE1F68BBF3B827070958EE22483 +:10620000EAFB64509341F14D399881F99B1BCC8C8A +:10621000E4B96DBED98AF2607F7A3CC9BFF6DB2C47 +:106220006487AECB6F8A433BD9346F550A96238C73 +:10623000C1AD183BBDE6D52D37D92791BC55F355D7 +:1062400082AC1CEC81BB8DDCC8093EF7F45419E527 +:1062500025CF6799F4EA96A783F9D8AD95D6E1D40E +:10626000B14CBEF97EF876BAB796B8BE701AA11DC9 +:10627000E079A37CD715417B465A703F366DB69CBA +:1062800069A47C6B4C3282F90D0BFDCC88F58D65D1 +:10629000E6483E57F9E4FBF27F3CC687875F590E1C +:1062A0005C69DC2BF17B413EE79BA1FC69D310F2DA +:1062B00054F58F1F29E0FC8B6C4B7AF58C31A67D51 +:1062C000F5AB22CE67E5469EA732BB615A1DDDC302 +:1062D00004BB65CCE77B51DC0BB5A727D23D717BB6 +:1062E0002E0BE3BD4170818EC77BD2F87FED8DB957 +:1062F000141F6A93FC29C13CCC97F0B9F0FCDA0179 +:106300004789307F5B0E97EB2CE4B7E27D358CB389 +:106310003872FDE0EF05B574CCC81EA6F8859E78EE +:10632000CF698C88B7635C1CE317D1CF4DEED5C223 +:10633000532E68E12A66D0C035662D3CD5AA853734 +:1063400015713B7DBA5D5B3FC3A9851DD907E37419 +:106350003CCFDFC222E249F0F75E7E441C68DD6874 +:10636000FE3E5F76F7528ACBB6E5F0788F639536BE +:10637000CE91C54212E22F7369543CD6BD663F866A +:1063800097ED0BA3E341FC5E02F0A1A947318A7CA3 +:10639000F0EA689E87DE3DD2B7BD08CEB3600C5FE1 +:1063A000C7AB1D4D743FC5DAD388AF5C225F69B0BF +:1063B000BE7C8AE8401D0FF92218B17FE48748F8B7 +:1063C000A151BE37701EE48B60A4FE2CE936D0FBD1 +:1063D000AB62BEA1F843E5CF72718FA2E6DDF4890E +:1063E000B1D4BC9B55225F705754BE4E9FA3361943 +:1063F000FDE7BEAE95F1B1F810F92E68E27C88E5B4 +:1064000006917F837C182CE27C88F5A6EF56786392 +:10641000D98B0B055DDCBF63C9864F22F6B7AC7321 +:1064200085065EBEEBE10D91F951F7E33F3008BF01 +:106430009E517EED52B19D2F4FFFCB2BCD0CCD4801 +:10644000DF0728CF96159C31F27BA75E239EEB4297 +:1064500061FF99CCB3F2D12FDB11E2F26C9D88374A +:10646000345B1533C681993B5513C750E3114D4B2F +:106470005CB654D847727F7CC16BA57CDCE1F91413 +:10648000DF48AAF1DCCEC632D653649C6B0662DDCF +:106490008EC156C0E9F957D93341C7C0BE4D17F870 +:1064A0007BC9FDB0EC67248F2EE468EADB449CA333 +:1064B0009FBF2D0BAA703E8BDB49FBB031FF1A1E2C +:1064C00017D4C6D14CE23DE7C1E33B34F56D227EE3 +:1064D00072E5F1B57139D385BC21C62F8C1ADF1A4C +:1064E00073FC8171B5F1BDABB8374F714F183A2EBF +:1064F00036D2CDE9699DDDDF85713183E07F6606A7 +:106500003A9988F280FFE9E3797EAEC1A18D8F19B7 +:1065100030AF0BFA3F97B898E48AFA3EB5FD99057B +:1065200012CACB27F0FDE8A4C1F2245A8ED844DE6B +:106530007CB41C81F93470D3C35CCF364B8A0FE531 +:1065400073F47EFE7FF1877589E3BBC8AECE8E778C +:106550009A2E630FB7058263F1B975F1FEC578070E +:106560007EF78E91694F94E37BEB8CF86CC58E2996 +:1065700073310FB64DF0EB13693AA2A7F4DBD3B732 +:10658000EA23E829DDE873A13D9CAE13F95FF887A3 +:1065900071B427D2B76D8C31BF6AD7A9B0AD01D61F +:1065A00011718E6DC29EEE9FEF8ECCADFA8871D2C6 +:1065B0004DBEB1345F7FFEA398AFE587CDB759C418 +:1065C000C3D4F96C776AF76733FA697F36A187D449 +:1065D000F936E3FE62F0D515E713FE75FF7C7769A7 +:1065E000F76733F9697F36F53B1BEA7C2D3F6C3E3C +:1065F000BBE0CF76F1DE973D9E7F3764A8F7239A04 +:10660000FBF3CCBD66942FED6ABC50E8BB7351FA26 +:10661000AE49E83BF5F97369B914FF3D77F8267385 +:106620002C3D87FA8D093B93093B93093B13E1D934 +:1066300035A7570D077AFCBB1D37CF9541AFCFBEAD +:10664000FFF4F81C80DFD9F18BB932E8A9D9AF9EED +:106650007E330B1E29FEDBFB38FCF4E93E07B45BFE +:1066600082CFCCAD05386918D7CFEABAD57977B9DA +:10667000B95DB97C751E8F6F829C453DD69CE367E2 +:10668000187FFCCAD19B341FFA2FCFEE4D5F100349 +:106690002F6AB97C75217F1EADC08998CFC648AFDF +:1066A000DDA8BEC752A77D8F25296923D987712C04 +:1066B0006445399660F6D0FB97D71673BD70335397 +:1066C0001AB85FE12C10791CF4DECB4DE5625C6BEF +:1066D000E52FB1FD669DE709F477FF79D2BCE1684B +:1066E0003EAB7973A306DE3BDDFE7DDE4F9EFDB142 +:1066F000C46DE5641E8F9936CAC9DF7B8B882BA2D7 +:106700005D3C143E3F7573FF7E009F1E8ECF540F7D +:10671000C7A7B537690D9CFFF294DEF4C7894FC354 +:1067200031F13508AF51F8FB939BA97EA01EED888F +:106730002BE15BC5AB9A5FD82C390BC85E67199A01 +:10674000FC60C61467AC7B1EA4CF483D6BB47B19BC +:10675000DAA38634C58DF9EFCD7FD1C7CCDB7315B5 +:106760008BF85E523CE57D362719C91FDF9F3493B5 +:1067700061FC59B64C23BCD426D5513EA67E18EBFD +:10678000447F353A0F5D9F7C3BE509E96DE8614048 +:10679000D99FC7EC31235FE93F56925D4800579976 +:1067A000872E5F290F3D7526CF434F323A315ED891 +:1067B0009E688C9987FEAD9BFB5DFB717F69B81F5E +:1067C00023FF6E88D8976CE5F7EE589F00F546AB2F +:1067D0008F51FC5DECFF5B6107A9FD4D563F43F90E +:1067E000A0372A4EB45FF4A95C7FE0775BDC31E22E +:1067F000285FBB0DF4FCFDA3AC5CCF99B9DD3EFB7B +:1068000037B1DF27282B9644BC2436DD0D453737BA +:10681000EA78DE9DCA97732D46CA079C6BB1D3F701 +:106820006CE60221F6A446F4BFEE56FE3EB5ACD8A7 +:10683000919E7E7BED945FFE96E1B50097DBA766A7 +:1068400018E8BDC25312F328A983F35DBDDE94A9F5 +:10685000B8CC1BEA4FAF45762C18C3C84E7A75C129 +:1068600043AD954EF28FEA8A919E7D73A6A20F7773 +:1068700063C3D877B1FFF2042ECFD5FBA5E509FCA1 +:106880007DDE6B64DF6CECFF55C51749D5485F7240 +:106890006F0EAE2BA23FDD3345F49F5B3C81FACFF8 +:1068A000E6AFDDF5D27739CEA59DF9C8C7E87CEC17 +:1068B000B1EC29F4B758E4BD86901FE87745D6A31C +:1068C000BFC522CE535A506EEB8E214FD432C33EF9 +:1068D0006EE442A0D78C8CB154AAF5CF7AF475A19E +:1068E00018E7FC9038E71FECF7B4C36A270EF83DB1 +:1068F000E0EF3C84F8F872E1A9F4F1B0A5076ABFB3 +:1069000026BFC76EECFFCE16F97103B0F6BEB32DED +:10691000D05B8CDF196088878911F98B62BFF625FF +:106920006B52D0EF81B3F420DD7604BC236B0D03F2 +:10693000CFBF2CE4080B16D2F306B12E475AEB0C4E +:106940008CBB382C3ACA7360CCAA9167736A53A681 +:10695000A6A10BBB9C291627FAF75DE41764E0FBA0 +:106960000D189F7CE73686F75F59699D12DA75FD31 +:10697000F388F7C657897BE13E5F2DED27C3D6EF3D +:106980009731F25FD38273506EF53DC35794F19205 +:10699000B6DD91C6F31FEE5D181F7202BD672DEDC7 +:1069A000C24F4FB00C70F830A69F71A9D9D5827232 +:1069B000E657091477D6B7E7B320C8FBB0ECFB1B4A +:1069C000C277C8F9902E4F6C169E5BB6289EECB924 +:1069D00076A97506F931F7E858AC78D1CE62EEA702 +:1069E000FC8F622BBFCFB54FE4F4631F3F72E1B859 +:1069F000ABE7FF77849EF949B293DE7F52EDA34D5A +:106A000043F8478E913A215F845E11F833339F1922 +:106A1000F9452F7979B074C76BAFBD96CEE8535B5B +:106A200048471B84FDA38E139F1FA2C678C543F25F +:106A300052B27AB8BEB0FAED4138AF75DFE963CE35 +:106A4000FF85A0FB35D90FD9B17FADD3E7C632FAA8 +:106A50003D98969C7BDD783E2D33FBE995ECBA960C +:106A600033CEDF613E56F028CF37D89F5D68C3EF45 +:106A700041590E1B64D365E2F146D027CECBD8191D +:106A80004691AFDE7280E799B658CABA30AFA1C559 +:106A90009256466AD8C2F356D5FE16CB21D20716B7 +:106AA00085DFDF5A507F48B84CC04709AEEB10E194 +:106AB00043ED7750C85D8B1266F85E5A9CD24AFD52 +:106AC000CCB2D78379CAE63446F744662BF017E296 +:106AD000355FC7CC31F4C9BE62AE4F5A4ACABAAAB2 +:106AE000697D327EB98EB5D8CBECA4E711EFF07C8E +:106AF000738696CFBF137857C76916F9B477AE4E31 +:106B000009D68EC33893F71BA4E716CB027310F592 +:106B10005AE2F8CB8E671A39D478FBD78AF1BE4394 +:106B200079AE4F2CB3E27806C6F7158DF7E1629C7B +:106B3000FFD5FB7BC02CBD474D301D58D81EEB7DCB +:106B4000ACFEF313F7F2D1CFFD6079BC561B870280 +:106B500079EC1E09FB5A5672E65035D5F0F8D30B86 +:106B6000C29F51FD927431F60B127FBF3F28C52B97 +:106B7000F45D0CE1A7A4C769F130F03E2D3F876FAB +:106B80001A781EDE37694C7C874ECBD7DF1CFF3866 +:106B900045939F057CEC31713FC623DEA7F588380D +:106BA0001DC2186FA0179D04FFF7C7891B9C3FC328 +:106BB000EFAC99408EEB605CC9E127FA3639BA5DDB +:106BC000C8EF39E2FB0FD178FEC9482EAFA5477A4E +:106BD0005C78AF519BD69B118BDF5F7CF84206EE51 +:106BE000E7C519FD793B74DFF4E269E7E602C4CB3F +:106BF00011EDFB6FEAF84D47CEA7F822FDA5C0E5E1 +:106C0000DF2F4B3AB37125D98D0BB8DDF87FFA7DB4 +:106C1000B317E6733B7597A495CF4F08B91C14FCC6 +:106C200060BB20D3F743EE2AF2AD403A6A93AC0B37 +:106C3000502EE73CCCF3F29A1E5BD5B328067FB406 +:106C40008CF2FDD5C808BFBA7CBD91E45EB3253790 +:106C5000F972F728439FBB9FE4947ADE558F9879A9 +:106C6000BE8A8FDBD1E9BE7B290F263A3F65A87E1D +:106C7000D5239D440F6A7F138E8FF2C57223C515ED +:106C8000CEA18F81713B2BB733A2D75989C898C049 +:106C9000F163067D997460491C8E6B10FEDC0B6AF3 +:106CA0005CA4A1CCEC8978DE705B99B93A824E9AEB +:106CB00019CF0F8E1EFF372355FB22ACB1630CA8F2 +:106CC0007F31C694269FED973B6478F2FCB4950320 +:106CD0007CCCE30E43E7A3C571BE2D237BAC0DF343 +:106CE000D2C00E5ED3B06004E2B74DF6BD68033C7F +:106CF000F47E68A23CEADF0B3EED167C3AD4F9053F +:106D0000D90130D2187B9C1DC497E2804EC6272340 +:106D10005F34E7EBEA4231F6795CECF332F67878EF +:106D2000E4F7B3C70F89FE1A7B1CED6D4FD4FD4607 +:106D3000248C76B627863D7E4212F105912774C2D7 +:106D4000E0DCD50D7839313999BE975690C0EF5DAA +:106D50004EA07F52067EC8ABA7F3D17E992DF57F5A +:106D60001749F8438C60F047FE05F9620EF3BFB691 +:106D700048223EE2F735781B9F7EE573DE3692D1DE +:106D8000BA36C0F9E1FD46DBC5F93362DD67A48E92 +:106D900052FD37506511EF13333C9D88FBAC41F732 +:106DA0007451F772786DD39F77AC1FDCFF8672ED5C +:106DB000BDD9868B3C2E625AC2428F4B9897AA6DE2 +:106DC000BFA9CE107D2FA8B94FBBD96B885E0F7DB0 +:106DD00017D421D69BDD711FDDBF4FCDE6F944A648 +:106DE000658CE204D1F76DA6B15D1E3DDACF0D8C46 +:106DF000ECFDE83839E6A952FCB081B12D12E579F5 +:106E00006BDF7379A6FE73FE7D94D63A9CC70E762F +:106E100010DAD3D1EF49A8F75AEAF751553CABDF66 +:106E20008F4ABF4D47EB63C129D4AEC6FDF17BB895 +:106E300055E911F9E42B587F7F7A7F2B187BDF9B74 +:106E4000DBEA29CF2073BC7F6C189AB2144678C84D +:106E50005AC8C86F003C68F2094CD9DB699FE71635 +:106E600033364C223C68DA3340D3D3FDC0426D7ECA +:106E700001EC530347FBAB57F2534DD9F99795F308 +:106E8000578A639AC4BDE49451E2FB97A5AC14ED14 +:106E9000A2F4DB9EA1F33807E781715F749C62DD89 +:106EA0003B6E82F1D18FFC77C12FCDE26E5BFDAEE0 +:106EB0000FF3C8F41E9B54CED72C0DF3F27BE912CE +:106EC000467C6E8A6766CC8F972A4C1EC4BBC90469 +:106ED000306C5932327306D4EB453C7B8DC46484EC +:106EE000995531F3F8A3FA5DA1107D5768A879D4BC +:106EF000EF2BB2207F4E9D67D077F52EF33CF97BC8 +:106F0000D6E8E76B299EA9CE3F14FE87FA8EDEBF36 +:106F1000D5BC3781C7531D44AF8D03F44AF07C4183 +:106F20008FF83CCA85BBD5667B5729FA0F671E4C84 +:106F300050364A11FB08CED2F3EF037EBFF1FAD7E9 +:106F4000617792BCEFDF9718EFFBEE8BFE22E4DA5D +:106F50003A7C5909F35E1A19E531A4FBAA3F972937 +:106F6000FF00F6A0911311DF4980F1D63DCEEF1F4F +:106F700036E3773EF0FEE7C040FEED13166CF7D126 +:106F80007736D4BC5CCCA35D5B32F03E72F47D837B +:106F9000BD11C689986FB2990513409FA4F43105BD +:106FA000BFF3ECB96854A6037E6C7DA05001BF937B +:106FB0009989EEA52AAD7E33FF0EE10A166967EFC7 +:106FC000976EA5EFBD86BF6494BF143ECF88EEC315 +:106FD0009FC3C4702EFFF8DDFB7AE4CBA97D5D7AF8 +:106FE000D4F393FBFCA47FF6D94F3DEDE2E7629921 +:106FF00011911F751D5B54CFE98A9F972CEA275F7B +:10700000306AF8FDDA5EA3461EC8175BBE46FD6512 +:10701000EA89AA67D33FE3E3F928DE2DDBB5ED5318 +:10702000443ED0DB2ADF5FC3AEA173BC981633CFDA +:107030006EE0DCD5736EE27174C6C7796E94F79F0B +:10704000464D40FFC04771E864C42FD8172995DD2D +:10705000CC8E7958E54C998E72BDB2F31DA487E4AD +:10706000B33C0F3C7AFCFD5FBE95857EC39EC99DF7 +:1070700059682FEDF9F2153D8E57D5D3CBB03E1997 +:107080004A1EA4584C78AA10B43350CFE34491F56B +:10709000B49E4AE765E5E4CF504E1A876EDF33D9D8 +:1070A000C2C2E4877526A03DC77C7CFE64B3CA5784 +:1070B000EC2F97705E84819FF654EA526A619F7B41 +:1070C0009E91156CDCD3F34602CEBFE7EC39CD7A46 +:1070D00098FE22F345ACFB5A71EE532B7BC9FE7E22 +:1070E0004AAC2BF96C2FC5A15395DE30EADBD4C333 +:1070F0007AFAFE37B3F0BCC8614CA1389ABA5EFC8C +:107100006E2A3ED78272DE88FBB3325628EC7E2888 +:10711000332A8355988F9ACC764A486B532B7D41FE +:10712000A4E7E4A59C9E93ADFEC318BF4F5EAFA33A +:107130003845F259DF06F4CB92CB6505C9E44AF82D +:10714000EC10F3B78AF9D4F9D5F58CA8F44BE87EA6 +:1071500024B3E362FEAE2A138EBF5ACCEF14EB5970 +:10716000C5E83B2CC967AD55E82F27839D41DF3328 +:10717000B8E2799A35F345B7274FD99945E7E0B199 +:107180001ED90AE3A5645B365441B9CEA123FF3270 +:10719000A987513C3DA9279DE47D524FA128278A0C +:1071A000FA69420F703993D4F3502DAF6FA1D2A476 +:1071B000CA17873F8CFB98DACBB87C717849BE98A8 +:1071C000D2B87C51E9B856952BCC5A321FEAF70F4A +:1071D000FFACB5069E7BF773FEFEE5BBD95CBEBC7B +:1071E000FB25F7FB4D69BFD3A35CAA42C305FA4D4B +:1071F000BBC0ED33951FABBA25361148639A83E7C0 +:10720000871FBAC89F3B84D9D500AF6312C929959F +:107210006E6B05DDAEB3EA8349D8FE8189DE773433 +:1072200039CEE598C11EFE83AEF7417CEFF8F73307 +:107230007AEF5D41F5827E434B492E9A846C39E4A6 +:107240005860413E847948AE1E7218E9BC0E083A77 +:107250003E67AFE908C33F5BCCDFFC693ED4FFC1AA +:107260009EEB40934C3D971E412F5F88F33B2BE8EC +:10727000A629DD7B53C904FCFE621ECD7BCEFE0D2C +:10728000BD7FB2DCF61F9FC6FA2EA73A8EFA7C4F5E +:1072900068A519CFF5D09B1F9F40B4ABE35F237B5C +:1072A000EFE4E37E339AF8D0123BCF7890FCF3AD55 +:1072B00088967F8B4A860FC8BF7A6691791E12E73F +:1072C000EB59421E4D55B8DD5E6FE5E7555FB25F85 +:1072D000A6FE8A8BF655AFD28DF2E45AE47F9BF27C +:1072E00024D14B7D3EA797BD829E0F0A7CCEEC63D6 +:1072F0009DE897ED2F986E190BF83EE2D213FF1C14 +:1073000019BBC65206CF1D2995F04B026C7AC9D61F +:10731000B5A900CF5224A2A7FA92AD1D4DD07F96F9 +:107320003541A903F8E8F9B31634AF0E05BC8497CC +:10733000E972F8E354179E1BC7D3CCCAB08CFE4F3A +:10734000BD63BF8CFAF66DC4AB11E32E1EC1677529 +:10735000041F576A2CB88F23A526212F3DE3515EC9 +:10736000CECA37D58FA1757C7D6C4C1ABE776F5015 +:10737000F8953CA7FFC9827EEACC276B53A0DFCCEF +:10738000926619D77BD42C91FC3CDAD744F993C789 +:107390003B39ACD22D3D077479BC6F5B7312B66F6D +:1073A00097483ED52B2F1DE2EA8FD3A73A7E0F0BCD +:1073B000B6E17730CF29AFB7603EF5B1BE05CFCC8F +:1073C000013C1C7F533FC4B84D1FADC071DF4C243E +:1073D0003A9E6D3569F4B18C4E69845EAD1E6FD3F3 +:1073E000C0F54A0DC5D3CF2992E50678DEF35DAD31 +:1073F0007B3991D152DA77BDE87B4CE17C79CCA125 +:1074000023BE3CD6F7B89C8AF05946FB919976DEAC +:10741000FA921AB2AFCE295BF54467820FD5F154C8 +:107420003A3E8A4F231EED9CFF8FF66DB320BD1DA3 +:1074300075BF23E3395D67891A57D0A1AADFF05DD4 +:1074400071A49FDA51FBF37E86EB5138FE6B94D723 +:107450008F237DD53B64A2A7A3CAFE9A1486BF27BB +:1074600062D2ECFFFE1DC99AF19775DA3470B45DF3 +:10747000B5CFFDDBA7CBC40E66A447D847F9C23E03 +:10748000D21F77E0FAAE681729EBE8F74906D9452D +:10749000F9DC2E8AB68754BE6ED689B8AC8EC76525 +:1074A000A3F9DF58FAC3EEF1D82A498EBCBF5BC6F8 +:1074B000BA7390BEE6A31286F11ED075A723FC1501 +:1074C000EB6D8B07397CADCC7669BFBFCABF373F48 +:1074D000BED4771EE59574364CDF6165AB18E507C1 +:1074E000E86B789E115E66AD88D48B25FDF12D8DFD +:1074F0005DA44BD89B8578AC386BE4F18F9EE8385F +:1075000097EA1F8525F22BAE522EEA93F9B87BE657 +:10751000F078677F79338F931509FCE5941A695DDC +:107520008A80F7DC16FB9EB5A454FA41F9A2DF0766 +:10753000DF2980EFAF90E6619E3D55B1D79152CAE9 +:10754000E3B5779778F24AA12C2AF11596225E3D91 +:10755000605FD377C53D649FA9E3BC33CAE316FDE2 +:107560004661C9BCDC0E8FEE07ED63689C86D8E3EC +:1075700040FB387A7E6EECF643B839FC7D23FB3055 +:10758000D243060C64A6F2522AE3E516FAAE468808 +:10759000FBE70D1ED2F34691AF88371091FCC7F47C +:1075A000F534BE1C9E41F7582DD82583FBF9917602 +:1075B00094AC846A22E3AD6AB9A894DF73CE28152F +:1075C000EFF34C6013C8AFA8BCFC3CEAF343CDC357 +:1075D000EC6557C87B5EF363D349FAC3E4275FA524 +:1075E0007D600E4A91DF391F6ABF894A941C8AC2A6 +:1075F000D350F35CED79DC22E8F66AD75D657ACC8E +:107600004EF9D12ECE076B057DF5DBD53F1E3FBE73 +:107610003F1F86FECAD9FBFE93F87E4A4268A53713 +:10762000C67E5E14FBF931E5C1D370CE1B8CA1FB85 +:10763000D1DE9907A76302D27BC7F2F1F005B09EB5 +:1076400037C5FC2D9695EB6F85475B1CBA98F91EE4 +:107650006FFE787AA20D3FD9FF95E3DCFB6D20A782 +:107660005B1E7DD0ACB08175306BD915CEF947E388 +:1076700013755D6D5B305E624DBDAAF7145A5CAF49 +:1076800024E07D69EDE74D76FC0E46B43DA0C6438F +:1076900054BDA5C64D54BBA4C2C1E31F33EDFC7B52 +:1076A0003D15F669A4DF0FB2AE1AF2AF303B6D2282 +:1076B000B10AFD19DD5AFBE43ABF57463B2ADA9E70 +:1076C000A84D3345D907BD7A94DF1517B5FD54FE93 +:1076D000F8AC54C45154791765479ACF9F4940BBC1 +:1076E000EBED0B67282E148D9FEB2E5CDE9FBDAE5D +:1076F0005D4FF783D171ADB72FE4D2FDA011AF1B61 +:10770000C1D4CACC3FC48C80974C7B6B9511EC18CC +:10771000A38329F8DD36FC5833C60D8D17789C7C81 +:10772000849DFBD7898BC12F85513395A07DC1786E +:107730007CCE48EFD3995DEF91BDBD09EA86219ECD +:10774000C79E19A68B110753CF638AC0EF6EE6B7A9 +:10775000E3EF814DB18BF7F72E46DB59FC3C2DA2B0 +:107760007FE2622D3E2DE23C27835B43DF79ECD341 +:107770003E6F11E76B591AFB1CECA3639F43A27A7F +:107780000E13B6C5E1396C59BC4D8A750E998B2F15 +:107790007F0E5B845FA9D2EFB4AC04B2AFF7A6E86A +:1077A000E8FB417B13C359CB31FEFDB299DECFAC70 +:1077B000107136B4A4109F6BB797BF8471DB71A3AF +:1077C000F5748E7B25D1FFBC8EFFFE60CF78EA1F5B +:1077D00027B383F8BB8007FBAAE9BB1BD1FCBBD353 +:1077E0007A00DD33B6CEB93D6B019C8325FB8099D1 +:1077F000FB9B83CF07EF3F4A05BE4B7BF8B954A6EE +:107800009DD4A3BD5EF266ECF351E38F7BA49D3A59 +:10781000202B36AAAF8BFC98913BA3ECE9B32D64E7 +:10782000675BC647D5F7C039D1BD8E9FEC16D9A18D +:107830003DAFEB8738A74A1187307F7D8AE265FB31 +:10784000FA4E717EE9D1C62527F75DFE9C5E13E7EF +:10785000B453C4A17E2EE2009DC27F7E23E0A4F239 +:10786000CD809BEADF0A2804EF0A940B61C1CF7731 +:10787000563ECB4717AFAA84FBED47CF73BF7D7F42 +:1078800062A883BEEF74DE42DF17A4BD4D14BFDBD8 +:10789000077C722CCE49BF1F7834DB4CF1B3A3A513 +:1078A000BFFB7B8ABB7C6BD1F1B80BC7B37A4EEBC5 +:1078B000704E186F5D858BEEA536E04714A1FFEE84 +:1078C0003289BEFF341B0E04EF45543A37F569F197 +:1078D000590FFF6595F1DF1DC8427F618C8BE8A4CD +:1078E00042EF73223E37BA4F915F1E57D8EE1B8787 +:1078F0007180F17A26BEFB143445AC3B0E6F42E03A +:1079000079538944DF731A0ABFD1E58654AE2FA399 +:10791000EBFF7534D7831BDDDBE83C773BBAB25015 +:10792000AFEF13F910B3642948BF5F2877DDB11CAE +:10793000F65B91651FBB11C02DA35368FDFB4A4F39 +:10794000531CF8D88557C621FD1DB3765A30CE7921 +:10795000CCC9DF53871395F97BB79DF22D31F2A483 +:10796000D5F258E922FAFD957FFC7CEFDAD17CDF75 +:107970004C52F50A8C5B81FB4D42F9DEB202F9C331 +:1079800098B983FCCCE873AA705FB388DEF364FC1B +:107990007B4FBFB6862C783F1CED67027D6C42FFA3 +:1079A00078F7043D7DAFAD5EE6E782E788E7A41F88 +:1079B000A3137E99767C66653E63FAC079601DDE0E +:1079C000D7D03AF13EAAEFADBF9262F8B583D6C9DF +:1079D000FC9E58F9B0D1CFCD76B2209A86B3151659 +:1079E00076A19F70309FC6996DE5E3CC12717C9BA8 +:1079F000A0FF59177594DF81F4D680CF95CC2779F5 +:107A000072CCF550571DACB71ECEC641FE469356FC +:107A10000E09395B5F5245F7BDC7DC07C6A3BEBF81 +:107A2000BE74E5E13227C29FD45441B729A52FD5B2 +:107A3000205D5A942E8A2F4C76CB745D787DB936B2 +:107A40004ED1AF17A3F44BB4BEA88F923B11F7549D +:107A50004E43C4F9CF729F4B88A483ABC7CB1C2F76 +:107A60007EAF7BD6051EA71D8C97F7E973A503781B +:107A7000893EEFD878893EA7013CADEAAACB1D8CA0 +:107A80005F156FBF2E79C91A99E71B8DB71F8AAF93 +:107A9000E6D15641AF5C9E5708BE7D3B3B4471B773 +:107AA000B74BF9EF4B1D73FF96E2BFB358A8630DB8 +:107AB000CA45E0CB3942F9E823E44C341E06F8F419 +:107AC0003F282EBFFBF3B7282EAACA2113F225EABE +:107AD00013C11FEAB999901F916F2FF0EF875E2DA8 +:107AE0007FA87C45EB213F38A48FCC1FFCDFC55F0E +:107AF0007B71CD18177616523CB8CAD1A5C77BAC9E +:107B0000C950D23D92887FD23A9C91F53C6E1C5967 +:107B10004F712FA1F7D4B8A6DABE3EBB2B41185542 +:107B2000A4474DC2DE51FDC47D8E53647FAAFA5432 +:107B300016F7FE57AB4FF7087D3A54FBDE73BB795F +:107B4000DCE7CB433D0F801C9F9C6FA4EFB84C0E2D +:107B50003FCCDFA3708449FE6F7437911F0CFB6923 +:107B600046A304E67544E6F3A9E5BEF36D0AD6EF35 +:107B700095BBF40AF507FF16E0038656FA9D860DBD +:107B80008F737D1357F451D6E5DE83BAB34F99E670 +:107B90004AC2EF616F5F83DF010B2A8CBEEB98B5A1 +:107BA000B48B45EEF7A531DCAF9D9CFFD61D076871 +:107BB000DD1FEA69DD6857039D4F969D0E05E7CFEF +:107BC000F6DB23FDEC7DD9F7DA9D00B77C696C0804 +:107BD000D17AC3A37E01F3EC33578D074B8DED7340 +:107BE0001F18F50BC0C74673D504CCA3ACB6DFDBBA +:107BF0003E1FE5DAD95B2660FC1BECBC56D4B7838C +:107C0000F6DFB7CD8CBF3B5DED789FD631A2AFAB31 +:107C100006BFBF5AEDE0F748BED1BE87C64C407BD9 +:107C200039ECC1734F349F0C22DD4C16EB65172FD6 +:107C300051FC41BD97D9739ED347FFF8400FB88FD1 +:107C40006BBF5C45F722B97DBAF926A0D5757D3C9E +:107C50007F0CDBF17BE058BF28861D00F35CE74B0F +:107C6000C6F3EBCABA3786DECDEDFB36E083E7F626 +:107C70006470BC44B76F1EC3ED82B8AFDECF7292A2 +:107C80003DC0F57FB0C012F33B55B7A9FAD21A3BFD +:107C90000F452D5579A5DA23805FB32102BF9BC61E +:107CA00070FFFD7CA9A703F1F77DE77F0A710BE563 +:107CB000F152CFF631C391AE045FAD9763C601EECA +:107CC0001CF3A3C52B6E4113EFABBE73E96FE986BE +:107CD000A6DB41746550E9F821A2E3FF8BF47BE257 +:107CE000FBD0EF207974FE14DDC347D3B14ABF0344 +:107CF00074C8E69B9206E87928BAC17E8B9206E8A2 +:107D00007AA87EFBCEBF1F93DE07C6E9BD2CDDAB94 +:107D1000F4B759D0917A0F5429CE79FDD78CECFE67 +:107D2000A33D46F577C6357E11E83FCAA3AEB072D3 +:107D3000B97FB43797FB193D66BA9F9AE95E29BEB1 +:107D4000BB0D5D23C6AD11F27EA6DB755939AFEAD6 +:107D50000B55DFFD4F7C774398008000000000004A +:107D60001F8B08000000000000FFED7D0B7454C75E +:107D70009560BDEED73FA9919E3E881692A085C022 +:107D8000164640EBFF053D7D10321FA7C1180B9032 +:107D90004C8BE0041B49DD60E2903D9EA131321224 +:107DA0009FCD621FCC7866BD390D038C9DB177C025 +:107DB000561C610BDCE237384BECC671189C4C3C0E +:107DC000C243086C6CD318C743B24ABCF7DE7A0FC3 +:107DD000F56B750BDB43EBCC6457E740A95EBDAA9E +:107DE000BA75EBFE6FD5D37A3363CCCED817F85380 +:107DF0003DBCAC081A19CB65F4F305FCDBE2F2EBF1 +:107E0000252B63DFB9EECBB443F9932CDF0A671E51 +:107E100063AF5F35CAAC88B1AEA9E3F6EAB387FABF +:107E20008F75088C15437B12748676EF54C17700EA +:107E30001E31D1272E9D1E7DDE9F4CFDAECD958738 +:107E4000B3FA329D63687AAF3E8DB159F89B0ECA82 +:107E500020932D33A0CCED5AC712A0CC2CF9369626 +:107E60004C622EB1843193F29EE9CA6BDF15F03972 +:107E7000931983FEEB95F556307F5D0DC031CFCC65 +:107E8000BCF189387AD3C9C9D05ECD970AE369D7E6 +:107E90001DDE9FFEA529F3E430362E57A0F5CDFB5D +:107EA0008CF94CF06B756EEB023603E78771CCD121 +:107EB000C7A9601E99E9011DE55EDB2AE83F6BAAB0 +:107EC000C9E1E5AF4BF8DE6CC6DF1B3ECE7AC64A91 +:107ED00086C6D9E209C8FA54C68E494CE92F5B6FB1 +:107EE000C167E7F8C37A85B23E536ECD55C4CBEB7C +:107EF00092C7E10778670F868D6F1DCB583A63559F +:107F00009F699F8B0E6D7D385C30FB58FAE54F5FA3 +:107F1000C07C4633C78F395D47F8795D32FA903EB1 +:107F20002AAED4EE6293184B96EC87FCF0DC2A99CB +:107F30001D3E053633F6537EAFB8020404ED9FC2F2 +:107F4000BF1480739B6EEF5A27D0DD166C4C1FA2B6 +:107F500097250B4C1A38962E49D4D49B9AC769EAB8 +:107F6000CB574FD4EC6F73DBDD9AFA431B666AEA9A +:107F7000AE274A35F5559DD59AF156EF9CAB69FF72 +:107F8000D6EE6F68EA6B9E7F50537F74FFCA11E98B +:107F9000221A5F88B691E98979053BD2BF884D3AAC +:107FA000FCCFC59CD3A3F7F7217FC27EBD6EAFB7D0 +:107FB000AD82FED5573F8DE7FDB4F4C5BC7200F924 +:107FC000A356D91798C72B407B8D52AD95BE45F46B +:107FD0005E633645E41B95EEB60A5611C7AF66DA06 +:107FE000FDAAB06DBDAE477E2E1AD0EB61BE5937EB +:107FF000B5FC572135FC06C767CCAFC7F584CBA5C8 +:10800000FFEE18937A399E60B57F01FCC4ACC98C31 +:108010009547C7A34AA7B75D37635F6FDDCAFCEA20 +:108020007A2B58A00EE93EDABA673BFC7A926B5184 +:10803000D61DBE5E15FEEF6F865F81EF5FFF23F3F7 +:10804000ED1310DBB288FCE6DF5DEBCFB52B400211 +:10805000BC27157AA8918227128B900E980365830E +:108060007190F9510ED433C16F8452961C04AF380D +:1080700068EF34302AEB717E711086A6D245EB355D +:108080000ECA8D286F452CA9EE9CC7EB8E065E8725 +:10809000F7A82ED5F2BAE73E5E8792EA5E27AF4395 +:1080A0003FAAEF5A8CF5CEB8C0894401EBBE2558E3 +:1080B000370E1E5ACA4BFF05814A99E49638E85D8F +:1080C000A7A77EEC22AF073771FAD0F283315EF6B4 +:1080D000F9B3195F3D3C3F81BF4DC2FD5CD76F00D6 +:1080E0003CD48A82C30EEFD50C32873F15F7D5E416 +:1080F00090D997E033A033316D88CF8C2C98B14A5A +:10810000203E790FF1ADCAEDE1E368E9AB1EF55A07 +:1081100001EC3BFCBE3119E530A7A7FAB2E0122C06 +:10812000F1F913D03E7B32FC4B1E4E1F2A5CA2326B +:108130005FA5B55F8FAAB6321826B75917D15985F2 +:10814000799D2CD987CB6D7150E52F2E2FC2E1562A +:10815000E5AD391FF86C1AFB3A7C96B90A6AB3AEE2 +:10816000BEABF0D9BA303E93ADF79684F019103219 +:10817000D3F0D9B7899E6E275F4E09837526184FB5 +:10818000F60CE823CA9954C04342243E9BFB1BB221 +:108190001FA2C89737F01758676E7E989C51F45C01 +:1081A000B5AAE7FEA8B3A2DDE2677A11CB707CC85E +:1081B0002C3B31D273B53CBE0906BA6BA80EF890C1 +:1081C0000F81BE631F15DC06CF9BC9CE62B85A80F3 +:1081D000C7AAE2318C6EAD712F9D90ECBC05F5EC19 +:1081E00018856E4E66A711DFC376BDC742E49DB504 +:1081F000E8CBF101CD3709C7736622BFD540DBC696 +:1082000082E1FD33B10FF09935C87C3E78CFEA08A2 +:108210000858AF46FD9E8DF4CFEA51FE575F09E83E +:1082200025EAA5E5975B7400BF3F01A4578B7C51FD +:10823000309C2E64E6D3E37E7CD5FDAFB61F349030 +:10824000BC0EDBFF9A41B0CF004E39D5E420FA1ABC +:108250006464CFC84EC1C748BEAC21BCA8F6E3AD2C +:10826000F6266817E8912E627BB340F6D0A76CB370 +:1082700081F305F3FA557A86E7CBAF303911ED3447 +:10828000CBF3D47E6C1323FAA8B6973C556747B856 +:108290000676CC44B824BD0A973F15C7BD60E2708E +:1082A000F9DA087FD50AFEE4411D3343BBBF4F69AD +:1082B0000FA35FFF20B7D3FC4FC42B70DDC8F04382 +:1082C000BF07D04E069368E5DD03FF4384F7DC6902 +:1082D000773FDF015DAE28F0FC6F856E3FDA2451F9 +:1082E000B93ECDF5FD7CA0C77F916E7CE266C80FDC +:1082F0003944F7D5F6CF27901E52F1D93786F410BE +:10830000C24DF8E8B34483DBAA107538BC0ABFE558 +:108310008CC8572A9C2A7C577C7AAB0BC67BB3E768 +:108320005F131CF621F84B45E77E84FBCDC14F67F8 +:10833000B888EF9235766634F96652FC88A44C967C +:108340002BA6A23E8873CC85758CCB74D1BA4C36E3 +:10835000A31DFD024B2793F360487382CF8CF0F787 +:10836000A737ECD243FBD6A92233C1FB5BB3BC36A3 +:108370005AA7FE0986EB9993E96103D6E8F377657E +:108380003E29119C835047BFC7C6F1A29F68F4F8ED +:10839000E0B95FC7D61C0AC1CBC102EE8F9DCDE705 +:1083A000E5DA171ED97629843FDA0FADD3D4DDBDC7 +:1083B000DFDB762954DE6E1044DC9736858EDBD900 +:1083C000C004F45F5A453BE1A143379086F56B2C1E +:1083D000787E0AAE0FE78F00FF3FE75B623DFFD27A +:1083E000A950F68FE1FE69FF241FF90DEAFC1F2B4F +:1083F000EBFF385F177338A6011EBAB3BFC5709F75 +:108400006A6C7C3F4D50727AE67243F577869E73B4 +:108410007951A53E0F3ADE73121DE91CA8764C99DE +:10842000F611E97D27D2BB71A8BEB548D7E88BF01D +:10843000FE730522C17BC016B93D5BA1979D135CFD +:10844000DDD9E8DF3FAB736C8625CECBDC3A1EE589 +:10845000FD56DB7AA253E6E2EB58C038BFCECBF430 +:108460007819E8D179FEB782422AD68DCCC286F837 +:1084700057F50BE7893ED101FDBBF2D79971DD5D60 +:10848000B6F5661CCF84D6826E383CEABA0FECE6AD +:10849000F3CECBF489E0E9B2B9B97BC501A83FA31B +:1084A000AC7B5EEE3A6AAF6AF49F14097FE06743E3 +:1084B000DDE868F5E23C2687BD46C23A736CC6B279 +:1084C0004F7889EC1355BF0DE94FAD9D72FABA9103 +:1084D000E463D7159DCF44F2535E3007DE9FAFBCF7 +:1084E0006D0D727BBE6BBFA35FC4F71C02F9E3F393 +:1084F00073BF4D769D35772EB7E7B3567991549873 +:108500004FF0A13F314FC55B9E565F191D17B7A0B5 +:10851000FA30DED4EAD1592CC090BE2AC2FCF370E6 +:108520007D3BBB40B1D7725931DA2B2D26DF63C8B2 +:108530000F960D423AC2A1E27545818EE820867CF5 +:10854000B06726945DD965B4AFFACCD31704985FB1 +:1085500017DF6643BED0DB8C7EC41BB38A1F0DA819 +:10856000F34DC2FF3325B2B7B08E842F7D3979FC2D +:108570006E96C786EBEC32B0A648F2A7B680F3FD44 +:1085800007597E920FD1DA8D1B04D27BAA7C376605 +:1085900032D937C278DB8C5CCE805FD22B40BF3EB5 +:1085A000A417A0FF175AB3F7E905A27B19E5F1ADAF +:1085B00052B1EF120BB91FFE668189CA93CA7E546D +:1085C0007F7136C33582FCAFAAF23084DF94CAC70C +:1085D0003365F2F14C222F7395713F2EE27CDC5C07 +:1085E000147BB95F9A337AFB1C4B7A8D87522890A3 +:1085F000E879DD9887492EC5126F39A38837A35DC6 +:10860000A13F07A713B5FD7345DEFFAA20E674B2AC +:10861000B47214E5412CE9A4E2CF83DECF97FF7951 +:10862000EC47DA68AEE3A399F2D442E093BF9C2E04 +:10863000DF83E596D723DBBBF3632F77D31E8072EE +:10864000F104DF3723E9B37985B197FB4BD1BE48FD +:10865000E1F645F8FCCB153D144B79D20465B31116 +:10866000D61F01FF8F8EC2FCCB7350EF727B81E56A +:108670009EB9A40FB1DFE167B22EC43E067B141C85 +:1086800041B443053992DDED8DFD7E2D7D483F647B +:10869000AFCC615C1FA8F32F2CE1F87A7A14E0B01C +:1086A00000DEEA256EAF9BC2E050CBBF2D8CBD7DB6 +:1086B0002AE943E04805BB1FCB0542447BAFA7D066 +:1086C00018737E1A0B78D9E2608D91E4C9C9D8EF8E +:1086D0004B9A0DCAAAE9CED328D7964B87E7605CA0 +:1086E000F9FBF81FE61BD279BE61A5C1E545FFAED7 +:1086F0004BB23BBC768C47ACA2FACA7CBB43AF52B0 +:108700003EB6DF947CDB056CD7517DE5EF241FDAA4 +:10871000C3DF17D69DC9C6F136EB1DFB18C69D9564 +:108720007C838DE71BAC369E9F106D3CEF60B529B6 +:1087300079071BCF3B586D4ADEC1C6F30E569B929C +:1087400077B0F1BC83D5A6E41D6C3CEF60B5297908 +:10875000071BCF3B586D6ADEC1D33815E391369EB7 +:1087600077B0DA78DEC16AE379079897E71D6C3C49 +:10877000EF0070F1BC832D72DEC13A947720FFF1D7 +:108780001896A467B85F7F54A9CF067BDD34637861 +:108790005EB56AE7FE2D1817AB0972FC5539785E95 +:1087A000D914B4770A307E4566B0DF04FE65451102 +:1087B000C3F0D5B0F9C3F313DDD9E7BD02FAA3B016 +:1087C0009729BC03E529EA187F3F7CFE6171573B7E +:1087D0008FE7D6657E8BF03BBB2C4878C3E71887C4 +:1087E000AD53F213B556ADFF2A7FE6B2F9715F992A +:1087F000D49908F890456DBB88F92F8CBB5EF1D7F2 +:1088000061DCB76A501B7715331BD4B83CCF4B845F +:10881000C139DFE11C5F046B6A017F2A01E6CFC129 +:10882000A415AE53127C5EA4B7DD1B88BEBC3B45CD +:10883000C71468AA0464609EA512206A86D254C632 +:10884000ACD24CF29B389DFED7D4BDF1D9280F0392 +:108850007A46046C233CA8F9850458BF3483FC2B6A +:10886000F2EF2A33FDBF473A50EB82CCF338825DFA +:1088700062CD802FF96E265C3693ABCE906FEB45C0 +:10888000E635C37341E9379B05294E2D3389F276CE +:10889000B5CC4165D174576911F0A3CEEC75E17A7E +:1088A000AAEC6609F9853DEE3CDB48F1E47AE93251 +:1088B000E04900F6F862DA48768AC82EABF81C4523 +:1088C000BB481F2F7822C9AD8AD8EB61B2832A0A30 +:1088D00019C9C72D2CB2FC7CAC84CBCF374B5DDFE4 +:1088E000443CD7FB16D58F872E8FBED04A799B6D1F +:1088F00061F1C25BFD8A626F4724E7903DB901E9EF +:108900007AF1048F0DE18816C7782AF6F0EC491B3E +:10891000C1AE7B7614EC5AD443B7EC2AFB9993FA98 +:10892000503BCAB10E4FBAD0EFBA929038AADDC30D +:108930003C14678D1CAF796914E22099A8BF13FE1F +:108940000B9D63EA3A02FB87E5FBBC54E1F88E42DB +:1089500087E34B63CF17D3A0D4273E610B8D1B77E2 +:1089600059040E9741D0C0F5B962FFFDA024F678F6 +:108970002A81727DA9FC2EF261D574F96758AA7C10 +:108980003BDFE1BA40FC292DAA4F02F9BC667F7695 +:1089900001EA8906DB5EE32A80F7D552F9FD223A27 +:1089A0006FF41F5B1E6EB11E8F47BCF7B922CBA3BD +:1089B000BB1109C5E44FDE28E2FEE467848728FE88 +:1089C000E4AF8B63BE2F7BEA7386FCC970FE1F5B2E +:1089D000CCE39D6347018E06285746F1EBA68CC277 +:1089E000FC8D5ABF6EBF3E44CE104185E6696CDCFB +:1089F000AF6311FC3D9735BABF377B14D6B110F386 +:108A000071B591F5DA7DC531F7AF967E03CA0733AC +:108A10005BFDA9D0C4BC306FDA50BEB2C9D5AF0F70 +:108A20008D733F38E1E037E508707EB338E672F2C7 +:108A30007C9C1EF975BD19E1E96A067E8DB05F2543 +:108A400025DCFF9B3BE111968876633A43F711E4FE +:108A500009CF3736297E6383A27F762A72D4532CBE +:108A600052E92CE5F5B951E8FAD7CAFB8D4A9CB614 +:108A70005162F22B91F47FECE9E6FC3828E7C671ED +:108A800038EF0DF3CFDF53F4C49ED8D3CF9E0CA0A4 +:108A900093B9B591F17530F674B17402CCBFD4F6C8 +:108AA000F41C90F8B02F9B0D945F9C2EBF580CEFD8 +:108AB0006D8BC2579F2B7869863E3AB0FB5BA03422 +:108AC00042F91090815440FAED55EC6F018E30144C +:108AD0002004DEF1E8E7F43AE41E7CCE5C6DE47F2E +:108AE00084C81BCA9F569939DF74A783FF88FE0E7E +:108AF00033D33993AE20CF9F7665F2FC68383C6A59 +:108B0000FEF46F458F19CF71776516C485F2DDEBE2 +:108B10009B98266FDC7585E785C14F8AD3FA49C9D2 +:108B2000E427858F9F90B9745EA87F24C8DC1F025C +:108B30007F26505C3CE417A9FECF987CF95CF17F5E +:108B400002FD1DCD9F1147490F8B30073EFFDD749D +:108B5000F9DF108F23D0D31FA3D0D39FB0DF7F3492 +:108B60007A62CC11B768CCF071BBB21EB7B58E700B +:108B70003F2021D31991CE54FA027A9B503276E8E5 +:108B80007D21F3B44A6F134B8ABF3EBD5DC0BEF07A +:108B9000EFACE1AFECD649D1FB9DB57ACC280FFA0A +:108BA00032D79BF19EC4D4992E07CE6B11996C00DD +:108BB00038BB5C3E339E7B003B2FBF6484BCC1CD81 +:108BC000222E3F7EADECFFDC099CFF2A960BBE7D7A +:108BD000C07F4D6C9701F74D7DFF5849ECFD887BB8 +:108BE0007248EE35968C20F75E56F8E273055F2BDF +:108BF000DAD629E7995844FB6755ECFD8C342B9461 +:108C00007352D745A4E35B7487E78522AC6714E20F +:108C1000E0E7C7E4E03C4CCD2B6D40FC3E56C4F190 +:108C200017CDFE7D6A14FCB38900D74AF69901FD81 +:108C30006959FFC7AC48E7118E15D9399C069003D6 +:108C400080DF9559BAB731FCD995A4B587D4F767B9 +:108C50002BFEAE6714E467520ECEC3F11A7E0E4CA3 +:108C60002DCFC53E1EB0B488FBB9FF80FC0EFC734F +:108C7000A8A458E3E7FEA864643FF7B57F8FDC1A29 +:108C800050E8A8CB11D99E7D21F6FB40E7E060DDDE +:108C9000EF7C15B9116E6FAAE59ED8DB7B69597A16 +:108CA0009C87C3D1C8B4E7246EF1DF28E02D5D8F27 +:108CB000F368E97725E3FA5F85C3581AF3738CE705 +:108CC00067E831FFC3F9797DA92BBE94EC368F1983 +:108CD000F537D80714675FB939251FCD2AD8676BD8 +:108CE000A996BE934A47A6EFE4D23B40DFAA9CFC7C +:108CF00017614C53A8BC99A8C89B69A5B1DFAF29DF +:108D000018AF488E2CAF2B631FE7DB73774E747957 +:108D1000AC9E37FB47411B4F6EBD258F634E4769A5 +:108D2000A9FA2179ACEA87703C8D865E480CD10B9C +:108D30000D51E4CC68C03136041FB59D02E5AF98F3 +:108D40008DF9A6C0AF9DD839E4DEC7965188134F80 +:108D50000F8D7FC860AF47A0E3DDA5B1CF7FA3BC77 +:108D6000E9377CDB36D2F947A3D5C5283F6273319A +:108D70003BEC9FB1B395F2F6C605AD9487669D02B4 +:108D8000E5FD98F42EF979AB6CDEA7307D365C9E5C +:108D90006C8D395E8B72D897F637C5287ECDEBF88F +:108DA0004A3AF937AFA33C1524EE47B30DCC4EF742 +:108DB000A4AF7CB9FB582F2012302F9AC4E83E761E +:108DC000A7E1C77ACC471B053EFE5CE6E7F94F9763 +:108DD00077FCA3F09EE5A0317F3B547F519A4DFB79 +:108DE000DE69E5CFBBF69BF39F84A59EB6159EC1B9 +:108DF000F3E153A727531CECC5038F6BECEC5ABC73 +:108E0000C7807EDF0B1E867EA229D33571243B9C52 +:108E1000317F92AE8C509AA8947A5EFA059D6DF8D7 +:108E2000FB3BF7F748E867BD78C04C727FEA819E4C +:108E3000F85521E32796713EB6063DFE1900AF3581 +:108E4000D3733209EF1D2BF9739179CED4C22B6302 +:108E5000A4009D0FDF91576B0EA5BB2EA9D64C79B0 +:108E6000E45C9D638A1DEBFC1C43FCF4DAFD82404C +:108E70007EDD2E1150EF9AE1BA867AEC0D89EBC3B4 +:108E8000A9536B49AB752AE71E76E42D3980EFC7ED +:108E90004FAFA7F13B59647BCC58C6E5F08B0699E0 +:108EA000E67DF18048E7C855BCDE697CD6CB300F43 +:108EB000E0A3DEA6A77BD8A78D4E11E5D0E93481CB +:108EC000ED822DDFE97885EE99EC8802EF2F4AB923 +:108ED0009FCA6CA9447FA7F7772E8F747E5FA5BFCA +:108EE000C93364A90CEDC0499E2694FFCCB6E43684 +:108EF0007CF124DFBF4387E6CF03FCCF7DC17F2217 +:108F00000EF7216BCF785CF707A5766ABF450F1F78 +:108F1000BD42F4B0C5C8EFE37875718E03B08E859D +:108F2000D60111CF4F18528394E76D2AE3F2748B68 +:108F3000CA0F63811FE03D7D06BF07C526DAA9CEB3 +:108F400026072784DEA39E55A6AC970532F1F9C209 +:108F5000F87737D81D8C15F6A6378BB0FE8589EFCC +:108F60006EC8867A49EF785ECF78F7B36C89B1B274 +:108F7000DE0C5E9FF6EE6793A05ED19BC9EB953049 +:108F8000D478B09B7AB39ABD7938BEA419BF150FB7 +:108F900072147FFD526FD2458C5F3528EB871F031B +:108FA000CEE3ECFB473AEFE2345BFD782E83C986D3 +:108FB000B0F8193485DC7760A90924FFD4FB0BF3E2 +:108FC000457F3FF6D799FD84DFBB5927D97380AD24 +:108FD000DD5F147E797B2E5CEE6DD9C85C784E8C9B +:108FE000B16609EF33084CD67DC1E3784E9C5F85AE +:108FF000479D7F185CB0B5C89F43703D4FE3A87094 +:109000005DCB377951DE7A6B59AE27044FD784E0B8 +:109010000F186C45DAAC1D0FE13E5D1B139C204020 +:109020003DB97C1BEDDBB5B1C11F088E90BA81EF55 +:10903000635B6F09ED639728B7219D9B8CD66E21EA +:1090400091B1EEB884190CE6D931D6E5C57B6E40F6 +:109050007774EFD89B65741C0038EB8BB4F9A1C70B +:10906000153AFB83220FE6987679CE015DBA7B0430 +:1090700086F770DC83378CA8FF16F65D3462BEA4D9 +:10908000A3E7A211E9BE03EB304EC7F3C688F96F20 +:1090900063B95EBD2F4AE791D64B1C4FA7B2EE7A5B +:1090A0002A15E0E9582DD0BDBCF54792E6607D7DDC +:1090B0002BAE92B1E55587E720B9B438FB9FC27259 +:1090C000251B38950A24B4CCA567F6103DB9624D2E +:1090D0003CB387E8C9164F8AA6BE7217ECCE0C289F +:1090E000376668FA31E5FEEA3236F483E7989A94F7 +:1090F0007D5C66DB19C0B8EE3297C13B1032DEC230 +:10910000BECD6232C2ED111C748DD2CBCF3FADE02B +:109110002B84521C7A1FCFF7F40AC4EF1D6D7ABA64 +:10912000C7D3DCCBEDAEE63582CF2E201EF8BD0DC9 +:1091300077AF40EDEEDEA7EB9311EF1B000F00477A +:10914000DAF8847D2C114793E9DCD54A055677DFA0 +:1091500039038EB3E23B02DD6755BF9BA0C2BFB2AD +:10916000A991CE91017C5EA44F759D4DF647E95CB7 +:10917000D5CA89970DA887617D970634F8D4D65B48 +:109180003CDAFACA8DDAFAD132E59EF234360DF9BC +:10919000E9789920E23924B5FE51D6F9B7F15EE7B6 +:1091A0006ED1790AE9B3CDE89F81FA7EB7E8A2BA19 +:1091B000DA0ECF3B18F19DF8E100F1B140FCB9C5E2 +:1091C000204B35F83D977681E87605B6ABF3670F0F +:1091D000BD4F75FDF0FA4D55EE5A9C1BE8BB30476C +:1091E0000509ED907A511693F3882F229E77F9BDE9 +:1091F000C2076FA3F603B8EE4222857DBAEBFE44A8 +:109200009F17E6BDEBCD563AE7765721D0811DF981 +:109210005E47E7D6E6E3792F28EF03796881F22EDF +:10922000FDA12692EF338D12C977E59C972A2FE492 +:1092300017B5E7B6E6679E213BEBBEE776D279B578 +:10924000C93972C1D3A80F2D7CFE1D4704DF6618F3 +:10925000A723EF34C9CF71323F2FD76153E4682F72 +:10926000C85175FDB0BFE350AE612269411ECD9B70 +:109270006E56A95D263928F86B75E8FF8E53E6DD3A +:109280005F6DA775A73D7A48C0756731EF6601E647 +:10929000BB823A7CEC50F955EDD7B5F80BE85D563A +:1092A000AFB5635B45D7E365305FBB6DC0C8CF2DFD +:1092B000068DA81FEEE0F8DE48E3C3F27574EE50A9 +:1092C000E2FB30473F988076CEFAA339E3D808F620 +:1092D0008DDEACD3C8118314A79137F373B5F26751 +:1092E000A1432B77BE5196A3695F244FD3B4DFDF30 +:1092F00058A8A93FE0ACD4BCFF60539DA66EB2CD88 +:10930000D3BC6FB12FD6D4E373976BDE1FE358A5A0 +:109310006937BDF5A32601ED71B377C00578E8067E +:10932000DE284B1ED223D312E06528E30A2D562CEB +:10933000BBF34D744EB67B3CE89744ECFF1D3A7787 +:10934000694E7CC95C03E5DF0BBE5AFC7E0EA0C9EA +:1093500085F6DB3D4F68E3F0C7AB385FA96543B9DD +:10936000EBC10A28F35EB067F07BE9817B707FCCAC +:10937000718CDB45AF99C92E9A89765388BF71B03D +:10938000BA667E39F67B42BE17F982F532690ABCAD +:10939000B7CF083B8B7AEE3523F5CBEB1DD085E6B6 +:1093A000F77F59CEE5C1B3CEDA7B71FC8E3ED0B2E9 +:1093B000C84FCF7D6844BFAEA3AF3F01F5D90CE7DE +:1093C0008746B4CF879E2B7A4E0CC6619CE31F0E56 +:1093D000E923DE63DD5E6EA4F14F2B72BDE53B7ABF +:1093E0003A4F8BF7376B4A86E473CBE1A01FEF63EC +:1093F000B7B4F37B9B788E36929C06F9FC61A8BCCF +:109400007D361DF4C14C1A4FA30F9697F9E9DE3E45 +:10941000C86FCDFB2B97345CC57C25C871EDF34C30 +:109420007E1E96B10103FA7320D735ED1BCB95FB59 +:109430009CD358DE1720072E3823DFDB7DBB8A9FA5 +:1094400033B8E0AAA37D7816F089E7479F1D863FD1 +:109450008ED7DBE1ED65A48190FD1B66FF5771FFA0 +:10946000EAE52872FBA2B2BFFB8440010A55B7337C +:109470008EE87785B975EDA542DC97CFB7A2BFDE40 +:10948000F22381EEC1FFB2FFAD343BACDF78F8547C +:109490001ADE97761F3A9586F789DB0CF6CD68CFF2 +:1094A000037DD03DE48E5E3FC1DF7EA8B01F9FB735 +:1094B000F70A0E14C9EE9EEB0DB44E36B015FDA39F +:1094C0007D51E03A58CEEDABC3E5762ADD2E9813F8 +:1094D000F57E8FC9E713901E403E215C47C00F8286 +:1094E000FABE6DE6A648F6D46505DF27B71919DE82 +:1094F000FB6D83FEB88ED359A78DF8BD8596C3B09A +:109500002E01D771EE81781C7F8381A19DA1C2F7C6 +:109510007156E0035CFFFBAB0D0CCF2D6F59AD27EF +:109520007CBFBF81DB27FA877FBD3503EACB802E66 +:10953000F13B0F2756DF389D01E3BEBF86DB69751F +:109540000F1B882F97AD136EDD4B0EA56B956EFF2D +:1095500046A1D370FA0DA7DB61F4BAE6EBD1EBDBE1 +:10956000E5B7EC9019A8F761FFE78C433AFA1E7350 +:109570001C407E1A3C611807704FDA2A39C0C36359 +:10958000D3F5BEA7D2506E9CE0EDF96D7B052E7F22 +:10959000ECCB717D19DD4686F7082E2AFB7651D972 +:1095A000373B0B0AF1C8CF626012CAA96C25CEF90D +:1095B0008A81351D46FF52E4F267FA8F6D7BB787CB +:1095C000D0EF7F2BE774ABCAC56946E63A6CC5F7A6 +:1095D0000F8D5F04E3BC6CE0E7352728E34DC90934 +:1095E000362C825257C1E5E46F1538D4FA9F143EE9 +:1095F00060277F43F85C68E6F89FB7D1DF8CEBF813 +:1096000099C975BD1CDE5F30E17C1BEABDEE493FA8 +:10961000C9E3DFB973901DEE56F07FA2FC37CF632C +:10962000EECF32358EF6D772F46909E9D932A568E2 +:10963000DC48F130F7CD6CE64A01BABA9943A55A35 +:109640005F74FCAA7180FC82EB0DC42F37D3E9B99B +:10965000DAEF5305EEE9468E07D6974A7A1BE4B651 +:109660005816926750F1A0FAE39629FB69BF1E5B7A +:10967000C728EECFD8D3848F156DE7845618E741FD +:10968000836CB002BECF2736ADBD3485B19F6C620E +:10969000CC050B3ABBC9CC5C77037D6C92A81ED875 +:1096A00064A3FABB9BEC545EB638C7A2FE79E0A473 +:1096B000670AE2ED44D61E672DCC73EDAC81F04114 +:1096C0003B06F4FD98426B37FAF4CC0CED377A94F4 +:1096D000EFAD28F03F743383B940BEFC02E7838EC0 +:1096E000ED1B7F4672CFB1E67A03FA49F96D17B7E1 +:1096F00062DDBDF1770D685F7C00FA04E90CEC7E59 +:109700006613509E9C33DA810E9A6FA6D0382FEBE9 +:10971000820DC877DE630243FAFCA0F7BA711CD74A +:1097200057742DE1F94D74E69F2DAD4822FCB8FB2E +:10973000F2757C7F8B74A1F729FAEFF94302EE876B +:1097400079A3FD9D4AEC7F46CF90AFB7D70613A40F +:109750000872F8028C8B97A3701D5886B73719BD15 +:1097600053F03C419342C7E1ED8B15FA044C1B9436 +:10977000EF2932218D9F23C19F1658526232F94141 +:10978000FE38E0E796BEBAAB22961E817DA8F5CFE3 +:10979000D88721767C343AFCB2257E43E6C3294340 +:1097A00075F42343EF7FA01F19E9FB82A6ACC9E340 +:1097B000468A77B907C0BE83FDEA00C3C99E82F41A +:1097C0003E8DCA4F8E74D9917FCC71C13DA82FD8E0 +:1097D0005D3AF23BDABD5A7BA841E18706C51E7AA5 +:1097E000B442EB3F819FD45EC1FDA484E34CE33FD0 +:1097F000853F27FFC98C7C05F34E83FD7925D2FE7A +:1098000054D5AEC77E13D82EA27306748EF415BE3F +:10981000CEBFA8E07A54E5EB65C8D748BFBD9CAF82 +:10982000C3C76DA9AAF90B1C775B947B10F757F19E +:10983000F1DA9F13085FEEE752084F1FB3E79CB5BC +:1098400040971F031CFB802EAF399DF149D0FF9A32 +:10985000CB199F6C1D92031DCFC553BF6D9317A7E6 +:10986000B442FD19A47B18EF93DE3A8A6F3EF41CD4 +:10987000E73F75BE0FFCCB52909F8A0D41A303DAE0 +:1098800033FB2E26A01D587CE4FE14E4C368706EE2 +:10989000AD54E0DCF8D8DA4B299C1EF01CEE5A459A +:1098A000BFB99FF41B11FF6B3732A2DFFED77ED901 +:1098B000817CFC495FBC84FAF0E3A3F15E94FFD79E +:1098C0008E997C3A81FC106F22C8B58F0D03F791F9 +:1098D000BD79442FA1FFE83EF6DB3DC88FEED74CA3 +:1098E00068F9B1B57D5DD751EFB5F5DD7B55C4F2B3 +:1098F000A5D1E587F68D8FD37AD5FA6F3799ED2804 +:10990000473F11B99C58DBFB2AD9BF6B076FCCC00E +:1099100038EAC747FF4F09CA35F79B374A509EB907 +:10992000DFB85182EDEE1FC77B22D92D71B3F484CD +:1099300057555F66BF276AE2451B14FAC8EEDCD5AF +:109940003809F0577C6E8903F3B66A7BF1149D13D6 +:10995000DF2FFE797DCAC321FD3A0322E58D8ACE31 +:10996000D5C7AF0EA1CB47AA0C9AEF947DD5380F7F +:10997000B6E2F72D6FC575023AFA0EECB680C8BF95 +:109980002FBB46F0A1BF01F64B783FB2A7AE3D9288 +:1099900042F71099E89C3FBD08EB531CDBED2856BD +:1099A000CCA72687D84BCB023ABF09E8A8A9CFE4B9 +:1099B000277B3F205EA4BA62473D74FD3763B285C2 +:1099C00008719ADC77E7A01C0F8FD7C0CF18845B93 +:1099D000B5AFCEA7F3F851A647D22D04B89A3B995C +:1099E00084781D16D7699A4BF1A2F0F88E3DB0DB52 +:1099F0008CFDEC937512C2ABDAA5B88F3D11E4C0B3 +:109A00005F567279A6F2576780E7F53A03B5E6C963 +:109A1000507E5769EF9174CC0B78E9ECBBFF00C620 +:109A2000173A071F8C9F0EF374BEB798619EE79A92 +:109A3000546B9E82FD06E79A1FC81BA29BF0F91A81 +:109A40002AB95D34642F44D67FA50A5F8F961E2CF9 +:109A5000ACFCF3D083E09F575472FF7C058F9F705E +:109A6000FF3C5C7FA872591D77AD82EFE172F92A45 +:109A7000D939E047935C5E5B69A7F732FB16A59086 +:109A80007FFDDE9214BB75F8F839A243979C377CB2 +:109A90007CD59E737BE55366F47B643DF1A77B899F +:109AA000E0C3FC976AFFB99D02D9E5EE66830FDF3C +:109AB00053E10A2CE1F1D8076483CF220CD989AA9B +:109AC0001D79ABDD2150BB6A57AAF663C0C9E3BB61 +:109AD0004B8A78FB658B6B55E5585CA7859E17977D +:109AE000F3E78C394FA15FF5E05281911C50EC4AAD +:109AF000954EC3EDCE4FFB7212478A433DAFD0A7C0 +:109B0000CA6713C2F843D563CF54707EEB403D5E05 +:109B1000887AFCF71AFB3C7C5CD0E38F57523F46B7 +:109B2000FD8B7E2E3A23F9EB6665FCADEAFE054E11 +:109B3000D620BC592CB019FDCC68FAF57B8A9D1350 +:109B4000ADFD19C57EBC1D3F1F56E4C868F1F3CBBF +:109B500095B7F270FFA9F9F9967D688C62BF57D569 +:109B6000BC86FB1FA7F7046A90FFFE9781E2EEE137 +:109B7000EF3DA5FA9F22D3ECCFA92CA30EFD23F72E +:109B80001A1E3FE84EB2BF437ECC5B7A86E3AC053B +:109B90007F10EDB8476F2651D986F632942B5E3888 +:109BA00047F988156BB4F077634C17FBAFCBA6F37E +:109BB000032DAC9EE24C2D7D49D216500ADD630F79 +:109BC0009D46BEF21ED0DB0F84BEFF88FABE99C749 +:109BD000E136A6FB28F71A660FB478C2ED7EAD7D9C +:109BE00050A9C48DA2D9096FF45BB85C39A3273E94 +:109BF000EFC078D34CC68C7D5C2EB837F23849471D +:109C0000DFE604FC086ABBD27E450C501C8AF26B6E +:109C1000F0EAD5BEA7D3E83E97ACCD27B5EFFF3924 +:109C2000C9CBF0BC52720F974BEE36BD92472AA1BA +:109C3000EF97B7833F390EED4BBBFD1B8877808BC9 +:109C4000F948DEC89AB8CB3E25AFF4E9997F253FA5 +:109C500074C5912879A4EE793C8FA47C2777781E6F +:109C6000E9F4A90CFBEDF3481DBDE7E81ECBEDF2CE +:109C700049A6AA5B711C8A3B4E14797C77629F20AF +:109C800061BC6A621F5F77E9B638B2AF1B7EB53A36 +:109C900005E581BA4F9F2CE2F8FDE4FDCF6AB05F85 +:109CA000C9AF44C902EB7AE3FD0D3FCBE075BBD9E8 +:109CB0008EFD36C4A33FF3C9AFD6C7237EDF801223 +:109CC000F7E7C717C4C8F1C9A178756615C59D9592 +:109CD00078B508FA70CC505C27BCDF8B555C6E748D +:109CE00083BB4271CD233CEFDF9DEE9A47F5BF9ECB +:109CF000C4F8DF2990291EFD2AD035C68DA6C16281 +:109D0000312FFD3FE35827E691BAC7BA7E427CF473 +:109D1000D73A3BF211F4A7FC93F7B09DF423866A7F +:109D200031CF33033F5B40F7315229DF738FB28F5E +:109D3000E9E0CFA25F09D02CC13CF43425DF332306 +:109D40008E8938FE0E836BFB54CC2FF58B8ECDC4E1 +:109D5000048E143C6F199E7712649E2F57F34F6A3E +:109D6000DE3C5AFE49C07994EF56F0F396B280F982 +:109D70007435CFC4963A29F9B5A5CC43F7427C8017 +:109D8000B3AF73DE6B84FCCFC31511F23FEB2B989E +:109D9000629F69F38DDB735F213AFDAA79C6C378B0 +:109DA000AEE28EE6C5ECDC0F0D83BB28E9D334F2BE +:109DB000BBFEF86F09A467FB6E903EBC1634B10081 +:109DC000C51F0778DCBDCF4071866BE0BF8D0DD11C +:109DD000B3EF54F0718FF7D511FDF704EAE3F1FD0D +:109DE000DF2BCFB7BDB7E47EB4F7BD01FE1D0BC6B8 +:109DF000B83FD613108BD16EB983FBF2646584F53E +:109E000099E3B87E0AE7A35285FF4AAB389EEBDEA2 +:109E1000E77E987B03CFAF488A5C707B785EFD74E9 +:109E2000569AA0C6D3C745CABF1C0992DE687944BA +:109E3000A0EFC97CD9FCCB33E991F3F12B7A2F4603 +:109E4000CEBF343690FC8C16CF0E8F63FF9D2AFF59 +:109E5000A6F338767A9544EB4EF6E4D78C6343EB61 +:109E6000BF83FBB07456847DB883E36F9C1DDBF128 +:109E7000EBCA633BFE13311E7F7B8CC7FF61796C9D +:109E8000F3EBBA8AD8C2FFDB18C3DF1F09FEFF5706 +:109E9000CF0784E7FFC3CF0B849F0330BDF5B01716 +:109EA000DBBA849D413FC3EF8DBFD624801C149341 +:109EB000F6D37DCE05E53C1FB6ADDEECDB2B0C9D6D +:109EC0001B50F1F56835F723A5BCEB5EFC5ED404AE +:109ED00039509F82F1B272FE7743AE59785E8C8919 +:109EE000523AE6C9E0CDF4C56097745B22E7595356 +:109EF00095F1A2E99183D5358B6715E31F3D8A7CE7 +:109F00000EFF874A1C52EAE5F7E999684F5F4CF368 +:109F1000DAD3D11E4A3CC99F27F899BC97E0B267B3 +:109F20002FE67FDC201BE17B46C9FF26CFBB2B1B26 +:109F3000E3D2C96017625EF069CC0F923F2BD17BF0 +:109F4000EA7C9766713FEA190313309FEB9DCACFF5 +:109F500039B19EDF91FDA6E6F5CE1AFC975A05CAE7 +:109F6000EBB523FC3FD5F9F3F6652B440CF8CDEBAC +:109F70009128DFF876F9DFE5BA681E9EE77B4CE2B0 +:109F8000AF9C40BF19E078EC6821D1EF8AE3E5FF90 +:109F9000D48CFEC76491F03CCCAF54E205179478A2 +:109FA000871A2F50F35BFFACC4493EC0F80B9403F3 +:109FB000180F8172FB2CDD9DD64FDB6745E0FF67F4 +:109FC000041E1FF2FE94C7870A8D8E9CD0F3947FE7 +:109FD000358BEF63AB9FE72FD478CF0F95F5147EC9 +:109FE0004FEFC7EFA1156E9D6E443D5FB8352B0E48 +:109FF000CB19B24F9706F85EB6FAB04EDDBF487483 +:10A00000B45759E7B63341CAEFBD1A96F7BF348B40 +:10A010009F6768A9E6FB7B09FFA018D41F9B226EEF +:10A0200041F331B14AD247CA2BB5805F8C70B67606 +:10A0300073B8557CB7F8ED7538CFC553C1AD581618 +:10A04000ACC9AEA3B87BDBF5AD68BFB9076F9CAEFA +:10A05000A67899D18EFEC44303DAB8DB13D53CFE53 +:10A06000FE2A1AE088B77B45F28F0BEF15897E92A6 +:10A070005B2CE4BF261B98DE8AF545DC2E2A684C53 +:10A08000ADC33A5B9244F660C1197BD2C379437188 +:10A09000B0E47B378C453CDD2ECFAAC6D32E5BE4E3 +:10A0A000E3B89F5F35CFDA7EF63D3A6FAAAE4BC577 +:10A0B0008B9A2F8D966755CF3DB81B3FD39CD3709D +:10A0C0008BC1068C3F161EBD6854CE5F4AB6ECA10C +:10A0D0003C6CE191EB947F55F3AD6ECF75B2ABA1C3 +:10A0E0009F11FBF76CE2F9D7D7000E2C7B61DDB234 +:10A0F00009EFA1DBA8EC8375E3F3639B72A9F46F0E +:10A100007250797C531995F899C9F464CCDB5EA739 +:10A11000BCEDD559C3CE4D525E6FB7E8FC08F115C2 +:10A1200092F7A37A78DE4F1FC7E335EE3306FABE07 +:10A13000A1FBAC99E4774D5FEB44F40F3E3FE79A07 +:10A1400088707760DE2D842E3E911D9624F4839DC9 +:10A150000E0BE6DB0AFBAF1AF13C4C871830623C71 +:10A160000C20CFC0238BEE9EEBFCDC6F5F8D05F1E6 +:10A170007BDBFC58EFFFCF8F7D95FC5877353F2771 +:10A18000ADCA9102A74EDE8BE519D9F270889CD832 +:10A19000E6E4F9946D9327111FEE764E4A5A1D326C +:10A1A0005E67238F5F24DF3BD912FAFC97D53C1FF3 +:10A1B000962C306724795633FBEBDDC71B416ED7F5 +:10A1C00044B2FB3FF929D0E54CA08B23DF9E3890A9 +:10A1D000C7193F341EB7AD71F5C431289F2E98D8EA +:10A1E000141EAFD3C4E358585E2E5A5C6E45A34E7E +:10A1F000B6D079A1E004D4DBE1F13326062770BDA7 +:10A200002E67E0BD1498318395B161F9B95F30DFF5 +:10A21000CF27C3FBCB1A75A42FD43C5D41A3C8360E +:10A22000017D166C34F8283FD7285EA476C56FEC04 +:10A23000940A3290CE3F386B9430AE161E1F7334A2 +:10A24000EEEF9E04FD1D6D02DD0BBA5D1E4F3D0756 +:10A25000DED2DB3F07E36DF96C57773DF4CF9FAC5F +:10A2600093F0FCF4F07C1E3FFF5DA0D839E171361D +:10A27000A433B44BC2E3F01B153AD8389BEBADD7EF +:10A28000147F531D47ED174E3F3F9DCDF56DB4B87C +:10A29000FE5165BCCEC6826D93717F17E818EA93B4 +:10A2A000CEC65AF3E490F176CCE6E7DB9EC1FC60C3 +:10A2B0006A687E90E701C3F382AA9C2BECFF7D03C2 +:10A2C000E27B37C86BD4636E1BCF1F141EAB398380 +:10A2D0007263084EAEB777C39E07C8BE732431BE03 +:10A2E0002EFA7B45DEA302C5E70A167C763C1EEA01 +:10A2F000CC9944F7B0DC67276FB1A23C5A2016E333 +:10A30000BD1EB753B89567C27CD2FDEFACA1EFBCC0 +:10A31000163E907F0EF7E58166039D0F54F5DEFD36 +:10A32000EF3435F0F6BD4FC6617BAEE0B0D8F179C1 +:10A33000237D3F76FE4B7EFABB580B113A90E781A6 +:10A34000B39744E49BCB16D7DF231F152E52F24C54 +:10A35000CD5C4F3FD0B7C8C0C8CED3EACD13599F0C +:10A36000533CE8465F21E58F52F0FC43DE90BE2966 +:10A370003C0A7A6CCC9DD3633F9D2D113E67821EB3 +:10A3800043789217F13C7DF8FEEF50F63F9A5E8AD3 +:10A39000268751FFF0FB63DE0CC1365C8FDB31EEAC +:10A3A000538AF63A94E3A2D3DF1F6671BA4E8A62EB +:10A3B000CFFD49A1DFA8E7A77A4727CFF487D97F48 +:10A3C0001E7963D5FF52F34DAABFF6A0620FAB65AD +:10A3D0009352FEBBEF37A0728D78BF2139F2FD8614 +:10A3E000870E0968A7A8F71B4E1959CDE1543C4FB9 +:10A3F000ABDC77F22D223BE9D4DFFC62EB8BA97852 +:10A40000DF4990501DB51F3A477ABE1DEC23B2A715 +:10A41000FA7ECBE3AD87F8F9F0F6DEC8DFDDDBAD21 +:10A42000D8DFF53223B9D1AE9CB76DE851F244B70D +:10A43000E2968F8BA1714BB73D30563DC7EB237F22 +:10A440004F1BC78C16B7EC60413AB7DBB14670A022 +:10A450007EB8DD39DC5DCA79DDA8714C79E473B969 +:10A46000E1714CB95A9BC7B96F96C4F7DB250868F0 +:10A47000EF9A75CE363AB77F4C90229DF35E5ACD57 +:10A48000E5F47C250F72D0C8E9E3608540F76FF0F2 +:10A490001E1EEEFBC163FC1ECEC1027E0F47CD7BAC +:10A4A000A8F76BA60EE53DE8FE9D7A2F47BD67C372 +:10A4B000988FE05AF45C1C7DC76B87E1908DDBBD03 +:10A4C0005E7E3F1A6510E6434DCC13895F6BAB6B24 +:10A4D000C46A7AEF8EDB4F8F5447F07B7D8A1FE989 +:10A4E000AE8EEA2FACAFD6FA0B540FF717EE54DE50 +:10A4F000E38BD9EC4EFBFB87631C8F9E323BB6F19E +:10A50000C4EC48FBB6C5A2FD1EAF5A5E56E4DFB0F0 +:10A51000EFC50DBB2FC9F57AB760FFA74ACAA71BC5 +:10A52000289FAECAD5EE317CFC1F29E3A9654029DE +:10A53000BBA37CD7F9974ABCAC4B947B10EE692F38 +:10A5400068E397D30F69E397337B9335F57CFF7806 +:10A55000CDFB85672669DA8B03F768DA4B2F146821 +:10A56000EAE503159AF72BAFD46AEAB382DAF86505 +:10A57000F5CDC561F7387DB4BE1AA0DCD07E75E696 +:10A580006F6ADECB58A35D579647BBAE891BB5EB10 +:10A5900052C7CDF66AD797D3AD5D5F32E6E3F2BE20 +:10A5A0007E3E2E7FB65DC9C7E558B0DF338D932D53 +:10A5B00068B7A9F7A9D5F7FE2F376658DF407F00A7 +:10A5C00000000000000000001F8B080000000000D9 +:10A5D00000FFB3E46660F8510FC17BB918186E72C2 +:10A5E00021F84301CF6786D06A2C0C0C1A40CCC6E8 +:10A5F000C4C0C0CE44BC7E714E047B1D0703C34C57 +:10A6000020DEC831F0FE1A487C9D877E76A9F34291 +:10A610006859C181F73708570A3130B40A3330C45A +:10A620008840F80CA2A8F2554208B6A924657639EC +:10A6300002F5030024CC7134800300000000000008 +:10A6400000000000000000001F8B08000000000058 +:10A6500000FFE57D0B7854D5B5F03E731E3393793A +:10A6600064F2200F02F18400A242180284870827B6 +:10A6700021C4A8018380BC54263C43483211A8BFA2 +:10A680006DBD77260411ADB551691BBCE81D1014D2 +:10A690001575A0D1061CE84014B1DADBA8F8A8D5DE +:10A6A0007650444048C2CB8B2DD57FAFB5CF49E61D +:10A6B0009C4C48D4F6BFFFFFFDF1F3DBECB3CFD9E0 +:10A6C0007BEDF5DA6BADBDF61EC1329A244E22E465 +:10A6D0005BF8A365842784F4E92CDB0ADA8F9164A4 +:10A6E00042FC2F8BF2368E10EE778EF0A45184BC94 +:10A6F000B5990B98693DBCCF4608AD9FDE343D60EF +:10A70000CE2264FF08B302EF9FDE9A8FF5C92FBDFA +:10A71000E714687BD54BBC0075D3BE13CE889D1063 +:10A72000AFB9E5A16BE9F3F69778B2850E45FC93D6 +:10A730004D2485906316C2FE2EB2FA522BAB566D95 +:10A74000DE7F07F45BDE642656DA4FD5EE65D3AEC6 +:10A75000A5F565874402AF546DAB95FAD2FAF200C5 +:10A760001784FA9A7D7FC671DA0A48797028212702 +:10A770007D16225F49EBCE969459F47945606711B6 +:10A78000BC5FB183739BE8FB159BF67F0CFD5734D0 +:10A790008A0379DAFF8AED36220F61637F4B601EF0 +:10A7A0004BA601BC556F88C44CEBE5975649047025 +:10A7B00024D44BA50E18FF614976C03887701C0D54 +:10A7C0009F55CFD071E877D52F706E985AB589789C +:10A7D000009ED6DDD6394FDA615EB5D260F87EF7DD +:10A7E0007D12BCB72C50F6B25506F8364B4500E743 +:10A7F000A6CDD2D2A19DFDADD8FEA60EAE630DD9D9 +:10A80000A99EA8766379D247886CEEAC5710A20453 +:10A81000ED0077409A3EACF3F9792E8190D1D03F8C +:10A820004F644B67FF9430C807FEF7E83F810FF68F +:10A830003A02DBB23AE9B5D245FF2D77D2EBAC4B09 +:10A84000A59FD09E17DDBF563E0474A0F0D4FB5CDC +:10A85000583EE24BC372834F46BCFDCA3704CB0659 +:10A860009F1B9F3FE61B8BE5269F82E513BE622C54 +:10A8700003BE527C6F8B6F0E965B7D1E7CFE94AF89 +:10A880001CCBEDBE1A7CFEACEF6E2C77F8FCF8FC0E +:10A8900005DF7A2C83BE7A2C77F91AB06CF405F0B8 +:10A8A000BD977DDBB16CF205F1F91E5F1396215F58 +:10A8B00018CB7D405F5A867D2D581EF07D88E5AB14 +:10A8C000BE087E77D0771CCB0755BC3B27907C8198 +:10A8D000E2CDA9101715179258A2E48BB49E58CA5E +:10A8E000EA29B7F9F3255A4FF1D03AC563DFCA70A8 +:10A8F000BE99D6FBD6B0F6CC7B488185D633FDAC6D +:10A900007DC0834A8195D607D4B3F6C19BFC0571FF +:10A91000B43E38C0DAAFDE112EB0D1FAD541D69EA2 +:10A92000132293EDB49E1366F5DCB794C90E5ACF8B +:10A930006D61F5BC8FFD939DB49E1761DF8F3F1550 +:10A940009E1C4FEBE3DB59FBC44BA4D045EB130932 +:10A9500087F5027B7E6102AD17B858BDA85F9920CC +:10A96000C7E0BF7D626411A1BCB0DD7FB322A4D378 +:10A97000BA145945DC149FFE39580F8B6431B4BFAB +:10A98000E52F538471B42E91D5D0FE177F05B61FE5 +:10A9900010656C6FF7AFC2F603928CEDA6DA7BB050 +:10A9A000FEAAA8607B72EDBDF8FEAB9282ED836BD0 +:10A9B0001FC2FA41D183ED636B7F8DEF1F943CD8AA +:10A9C000FEC8DA805248EBFFC179B6005FD7719EAE +:10A9D00072920DFC1A4C2BA5FCBA8E2373403E1EBE +:10A9E00000A6A6F2B02E5D5240BFEDFB47DE933CC1 +:10A9F000A7F27632D4973EF54016F6F31CF623D232 +:10AA00007EF89EFB99F8CD585D3F13BF29D7FA69B0 +:10AA100084F7EAACBDEB67DF37E3F5F07C53A1F5D3 +:10AA2000B317FB71F46E5E13BF9DA087E7DB4AADE1 +:10AA30009F83D84F42EFE0098B6374FD84C5655A4C +:10AA40003F7FC47EFAF40E1E451AA7EB4791966B22 +:10AA5000FD7C88FDA4F7AE9FB074AD1E1E6985D63F +:10AA6000CF11ECA77FEFE6A598AFD3C363AED2FAC0 +:10AA7000398974CFEA5D3F071C7AFC1C7074E0E7EB +:10AA80001CC233A877F32A70EAF153E0ECC0CF255B +:10AA9000ECE7AADEF573C0A9C7CF0167077E440EB5 +:10AAA000E635AC77F32A88D7E3A720BE033F4E0EE6 +:10AAB000E019D13B785EEDA3C7CFAB7D3AF0938A26 +:10AAC000F08CEE1D3C85297AFC14A674E04746788C +:10AAD000C6F5AE9F5753F4F87935A5033F57613F4C +:10AAE000D7F56E5E85A97AFC14A676E02717FBC918 +:10AAF000F76C477808EDC7D17D3F07FBEBF173B0EA +:10AB00007F077EAEC57EA6D07EB27BEEA728538F90 +:10AB10009FA2CC0EFC14229E6FE85D3F0733F5F830 +:10AB20003998D9819FA9D8CFD4DECDABE80A3D7E34 +:10AB30008AAE60F899248CC07586AE9D6E9E7E723A +:10AB40007DBF7C85A3EFF32E56E75D6E02760FAFD7 +:10AB5000D933A445E1E9FBF61D09B90F9068BBA6FE +:10AB6000E076C08F835A79D1764DFCD8389D1D95FB +:10AB7000A024EAEA49C57D75EFF7291DA06B4F9D1A +:10AB800073B5AE3DDD93ABAB67948FD7BDDFBFA68A +:10AB90004057BFE2EE1B75EF67F96FD1D5B3D7CF42 +:10ABA000D3BD3FA87EA1AEFDCA860A5DFB55819547 +:10ABB000BAFA35DB7FA27B7F58708DAE7D78D303E8 +:10ABC000BAF611E14774F591871ED3BD3FBA658B84 +:10ABD000AE7DCC87CFEADAC74576E9EAD71EDFA398 +:10ABE0007BFFBAF603BAFAA48BBFD7BD9F4FDED561 +:10ABF000DBDB963FEBDE9FE2FA4CD77E7DDA9706F1 +:10AC00003BD5EE3A768D5AE741AE08FA25FE740937 +:10AC1000EDD5B043C2BAD4D7CEFC14C752F928E55B +:10AC20001FE9C0223919F992FE51BB21BF6FF99576 +:10AC300011FAFCAEF19E2B5DF4F95D9267B82B869C +:10AC40007D43F98D236950CA26288DEDF7898CDF65 +:10AC50000B322E0D3E42BFF79ADA0727D0FA703E2C +:10AC60003F08F2F1326742BB3A8E2735F05E9C997D +:10AC7000A0DF745F56DE93FE287958DF9FDA195CF7 +:10AC800067BFEB454F1ADA51B59FF8C1CE59D79F30 +:10AC9000CEAB2F21AF709F84FD03E9F7FD97A67916 +:10ACA000687F6689FA19D1E34B74FCA1387E18E4F9 +:10ACB000E1208C3FBAEBF8E6016375E35B32CB75BC +:10ACC000E35B243ABE8B90DFD77EAE8E4F89309EF9 +:10ACD0009037B9CF717C7366398E7F9F44FDAEE8A3 +:10ACE000F1E33AC66F81F9BFDFDDFC078CD7CF3FB8 +:10ACF000B3423F7F89CDFFA3DAD3EAF87138FF3F33 +:10AD000073A7D9FC332BD8FCCDACDF8EF19D1DF899 +:10AD10008FC0F8C7BA19DF9C3D413FFF2B2AF5F3DE +:10AD200037B3F14FD65E50C7B7E3F85F7217D8FC60 +:10AD3000AFA8C4F125B3C70DFC2365C4D504E8F85A +:10AD4000A41F557CA9C02E741C28872452A12164FD +:10AD50001B3700E1B82B8EF1DB577194DF509FF960 +:10AD6000F1390950CD9947FD4695D757ECC8974022 +:10AD7000EF613BF5B796A8A02E6EE291BFC90673AE +:10AD8000601085B7B589F7437DF186EB02A05FBD02 +:10AD900066B2A014BE1348189E7FFECB615BA2E78B +:10ADA000652C97D48BC72251F2D6E1071690213536 +:10ADB00014BE29C004A33BEB9F523F0E1CE38FA996 +:10ADC000DF43A8FFF399C8C6FB0BF5F7A01EA1FE51 +:10ADD0001E3ACEA416BFA3DD1D4EA3F097AAF07FA6 +:10ADE0002A3079FDF4362EE0A7F2F9D58F47A07FFF +:10ADF000BDE06E1B457A271C65FE245D9DCECB0F02 +:10AE0000746ADF6D0E6CE110BF32E06B3A8A262166 +:10AE10008BD667505C77BEFFC1BEA907392721B723 +:10AE200012454CA5EFDFBE9AEBEFA2E3CE52CCB9B0 +:10AE30006C1D52324C28D724C33496905B1A478835 +:10AE4000B407325D113F8D448D3BA3585F9F55AAD7 +:10AE5000AFB78A8A68A270B54EE7C866DAEFEC39F8 +:10AE6000FA766D9C81A644466775BC528A9374FA43 +:10AE7000683694B9F0D885749EE362DF6AF078177B +:10AE800089248C7EBCBF0F01BAFA93F1BD792E36AE +:10AE90006F23BC73448B524AE739A78C0F007F1B8A +:10AEA000E1FF689F4D31E5D072FDA32231759D8F82 +:10AEB00011FEB91EE37C8222ACF3F3CB8DCF19DFF8 +:10AEC0001C53E9FF29F0072DBF00FEA0F01F55F924 +:10AED000A353AF32FEF09A3DD3801FDA37F204E974 +:10AEE000AAF2CBAD2ABF2CA9D7F305211E11E8B8D1 +:10AEF0006C0E97FB40141FCC56F96059839E6F6E01 +:10AF0000277E313D065DE66ED87C6F9ADC757E9FAC +:10AF1000A87C33FFC1FD889FAEF36474BA43A5D308 +:10AF2000ED35FAF65B55BADEAED2754EC3C3AF51FE +:10AF3000F541E6C90111E4DDFB538D9E111D3D3D38 +:10AF40002A3D8D70DEA1D2F38E1F337A1AE18DA8CF +:10AF5000F48C349C13C980AEF01AE15B707797F9DA +:10AF6000605CABCC1F9B9EDEA6FC5547A39E57059D +:10AF70006F5875344ACE566C9FAEAB2F0FCCD5BDF3 +:10AF8000BFACA14CD7BEA47EB9AE7DD1FA3B75F55E +:10AF900032FF8F75EF2FB8BB56D77E7BCDFDBAF64B +:10AFA000F9E50FEBEA733D1B75EFCF9EB359D73E22 +:10AFB000ABF4195DFB8CE29DBAFA7465B7EE7DD3F4 +:10AFC000BEAB6E06FE7CEB3D9E803D71C1FD05C6AD +:10AFD000332FB84537BC73D427235F1FF30DC1F25D +:10AFE000B8CF8D7C7FD23716CBD6A6663BAC137418 +:10AFF0005D5C4A12086932CDAB5DDF0FD66982EB2A +:10B0000069C8E4A9F5D37AB34946792869904878A4 +:10B0100024211C2C362A1CED7C547BA487F606AA1E +:10B02000F893BAB69744623FF73E527605F06577DB +:10B03000EB03FDCB00BBA74DB5EB8DED951C298D2A +:10B040007E4EC81A84C36A627647A5C4E4BF7257AD +:10B050007A0171423D3CB8E672E3052993A7029F4D +:10B0600064EBE47859C3353AFD4E209ADC07F86D5D +:10B07000A4EEF98AEDD7EABE3BB59F47B8AB41577E +:10B080008C8365B1F43313E8E17073E68C6100A73B +:10B090007214EB4D7DD02E3CE52B5E757410D0AF55 +:10B0A00014CBE3BE39581EF379B03CEA2BC7F253F8 +:10B0B0005F0D9611DFDD58FEC5E7C7F263DF7A2C1E +:10B0C0003FF2D563F9A1AF01CBF77D012C0FFBB6A1 +:10B0D00063F98E2F88658BAF09CB569F82A52677A3 +:10B0E0003DF1DD71751D3E09FC1783CFA43A7FED5C +:10B0F000FA099D7C16C7DF877CA6E1B9A4C1ACF232 +:10B10000438A8E1F12C097433EEBA1BD4154F9B054 +:10B11000BBEF63B77BB7FC6BF86DEA0FE4B74E7E0D +:10B12000CA30F053764FFC348C8FE2A7A92617B3B0 +:10B130007B547EFA19CC23865F310F8C903E51F6FA +:10B140009A926F82756CA5BA0F421F60FDAC3A7679 +:10B150001D7DB705EDBAC0105837CE0EF9DB60D8AB +:10B160004738FB21257E56F7F333F249F77857D05D +:10B17000BF591AA0444FEADA6E8D6378B59A483108 +:10B18000A1EBDAFD839E722F1C8A758124C2F70120 +:10B19000F774478C7EA9AD0CF8ED09AF758EAF72D0 +:10B1A000A0BF638FFD3D0FCAA926662FC735F36880 +:10B1B000B793F0936EC06FC7BA6476A741BCBD7DEC +:10B1C00090E442BB814CD6E3CF5FA0C3DFFD1447C0 +:10B1D0002DB8EED6A721FE067E3538BD17F8EB490F +:10B1E000BFF784CF8530EF7F013E7BD28F3DE945AD +:10B1F000A2C82F34D1F9B7ED1B96FB800CE35E1E7D +:10B20000DFDAFE9A119E5F7E473E6E4BD1F8B8257D +:10B2100093801FA4CACBD9C62BE3812E1DFDF44019 +:10B220004FEE779F6482FF7E3A4BDFDF7DC6FEE202 +:10B2300025C20DA7E33A2489C453BF92F76CE3D12A +:10B240009F7147FC1037D86773D7C9E0379EFCAFB2 +:10B25000B00C3DEBE30B670F3DE9043F6C651A5FF3 +:10B260007334061DB5B22A9855638FF6579AF4F5D4 +:10B27000B3F55C7110E725C7CF1C06EB8CABE6A8D5 +:10B28000087A3F0D4BAD9F9569128E73727B763CA9 +:10B29000F3FF024C9FEC48407D73D267C1F7FFD9A2 +:10B2A000F074D78F060F218DE4330BE873DA96DD47 +:10B2B000FDFBDDCA83705E82F82909895F81BF6961 +:10B2C000A5FF7F3B00FA15B0AEF5EB0DF27EF370F3 +:10B2D00078BE43371EFD4ED6F68CE1BBEEE54E2020 +:10B2E000C734BEA7F4FBABBABFBD62BBB5466FC7E0 +:10B2F00026E8EADEA6F41A9D5D0BFF00C3BD8613A7 +:10B300006009AB54D9B04DB0AF077EDA03C149F044 +:10B310005F38F65E9525227964149716E0D385632D +:10B3200035FE9767FF99EAA9136F8A04E48C5CA243 +:10B3300050E5A9AE20F29B8998687D91FAF6C2C6C5 +:10B340001525B06E9D78F926F44316935227F8C759 +:10B35000E5A43E0FE2B5A789A918E4F33479C7390B +:10B36000324A1EAD82849D2E5AAFB7E3A97FAFABA0 +:10B370002F6BD0D797925B5260DF7EE9069104383D +:10B38000D01BFAF6AF7917F6BB8CD4AC8375FB579C +:10B390006ABC6BA18B0819546F55FDF6F1BC320ADB +:10B3A000874B6071166D1F7A7922F37F2A66062417 +:10B3B00085BEFF59E3C85BA906A2DF07D6C17EBCE4 +:10B3C0007F3A716F235DE9F75DE137C2ABD9035D69 +:10B3D000F6C3553892B7734A20861ECB14382667B9 +:10B3E000AABE2B105CBAB8C73443FD7BF35332D1ED +:10B3F000F1D31EDE93278C66FC03FCC009ED92E7B7 +:10B4000087F49FD6A5FF827F6AFFFD68FF79BAFEA9 +:10B41000A7FD53FB1FD805FE79B1FAAFFAEDF32F64 +:10B42000FBA93EA978F1974E42D7C913427D8A9B6A +:10B43000D2B572DBBD4E8596C705BF13F8F54480C3 +:10B440002F8E45EF87054E1542C5CE41DC0DFE49D6 +:10B45000FB3FF9ECCF301EF1D536D185F1B4EDE6E6 +:10B46000B099CA6175E3F2129283F523AC7EDF19BD +:10B470001EEA4D7AFEAB78FA9729901F4239458D26 +:10B480002F85D19EADDEFA7911AC4F5ED28E7264FB +:10B49000FC0EC6BF9888FAAF4C8AEFDA4EE1C4388A +:10B4A0008157C58BB7F16767782794377C01FA829B +:10B4B0007A22E8C71BBF2B57EDD4358223F9988D2C +:10B4C000FE7B0C19037A51C30B09303BB5EE995F33 +:10B4D000E71CA1709DDAFAA6938BC297264F67836B +:10B4E0008BFE738FDCBDDE6DA5F2166D0F69EB96DA +:10B4F000DCA4DAD72156568A6127E4F3546E16DDB0 +:10B500007EFAB8F2F9279F7A0CE2997F32BB07D115 +:10B51000FE573CFFDAFBE3697DC54E31B9844DC36C +:10B52000CEA574D2C74BFFBF3BB7931E15BF794D55 +:10B530009287B1E7F72476D265C5CEFD1219D615EC +:10B540001F9383FBA5883D067D82478AC05EA87B4A +:10B55000E6BF2588339ED8C791D4AC18F8DCFC1A16 +:10B56000DA038027A4A74AAF0EFA19DEF752BA8091 +:10B57000DE36D2CBF8DE2255BF40BF906741F9FBE3 +:10B58000853D9007F591D90D78287F619513E6F3F5 +:10B590008550C3F8FCF17B53409F958BFE141796A2 +:10B5A000EC79F9133F42FE5BF6F68F5230BE4494BD +:10B5B0007413AE45FE7498E7924DB3709E4B8907A5 +:10B5C000F9B0FC71BE3440CB0B0229DE19434EACFE +:10B5D0002293932FB650E2D2797E01FE24E8EF77D2 +:10B5E000F8C036B4BBEF24A00F7EA4CE855A0C5809 +:10B5F000BF6061F4FAABBA2E10B03EA3F977EB7DD1 +:10B600002D40A793FD9554D877F112C1AFE283FB8B +:10B6100096F6CBBF3D2595D189C8429EFA1D5DF7B0 +:10B6200027C37378BF4554AC39BAEFC8B7599DE307 +:10B63000AF56C7A770C7C17AFD454A6CFB354FD4DA +:10B64000F4005DB7A3F82C4ADE99FC6FBD9FC9BB1F +:10B6500026FF81E9C5D07EFE309323F80ED6430A3B +:10B66000573815DBF7CFE4503F503F3A969C6F15A3 +:10B670005539D7B71BF985C22F70F1517C03E324EC +:10B68000221D70DF65E906FA7D941EF5C2B8CEAEC4 +:10B69000FD6A72BC4CF35B45BD3E209B981EE8DE04 +:10B6A000AEF2239E2AC5C0538F81FC5279F5CB2080 +:10B6B000BF6229CCFFCB1DCDEFCFA372FB655093AA +:10B6C0005BBD5E35CA6DF9AED12496DC7E69779399 +:10B6D00098724B9FC7945B7B04F9F9FFB45ED5F079 +:10B6E000380CF0784D271E353DD91D3E8D7AF290ED +:10B6F00020235E8D7A92FE1D26795DF951E3438DFC +:10B70000FF2A9EABBA02F451079F6A7CD8C1A71AE0 +:10B710001F7689EFEAF0686CBF00FB3414AEF9962F +:10B720008DD38E5257D2D24E70DF267F268FFBAA42 +:10B7300096F384E5811011F3433F30D58C063B75B9 +:10B74000E2DF6F3D7D1785773EF18B2C2FA05E44A5 +:10B75000BBFFD2B7DF4EA0F399A7E2793E45FB5479 +:10B760004A973902178EA370CE15883F3E11E2B773 +:10B770001CF9340A8EF9E5FA3AFC4D4CE9ECA7A71E +:10B78000F7BFAB9FF27DCBB7295D3F1D44C8BB50CF +:10B790008A38BC10CD57D381AE147FDE515C600077 +:10B7A000EAA988501AE577BD2032FBF3EDC219A350 +:10B7B000C1BEC99F3D2C9EF1FB60F47BBDAA3E3B00 +:10B7C000EB97E341CF9F0D65A37F7BF6D02247AC7B +:10B7D000BCD06695CF5E53F75DDAEC5C3D4FF9BFA8 +:10B7E0008DB4A37DE3B75BC9B618FB821B454D5FE3 +:10B7F000AB74A37F3C1D7F8ECA8773E9A7F1B95153 +:10B80000749B39F584E0EC4A07F8FB34CA0FFBA1BE +:10B81000F805BE06FC365B2345A531E279CFA9F8D1 +:10B820009B78E06BCCCF2D0CE50B80C7423BAF8BF8 +:10B83000833CA9C9EB503214E09A7860F9CF4753A2 +:10B840003EF61EE2DD908FEB0D9D913C31FC6123B5 +:10B850003EA17FB0338F882EC4D77B62E912C0EB44 +:10B860007BB3AC04F635DF95DC55B1E02C33B3F592 +:10B87000662E29BD308AFBBF0FBFF9B31DE1028AD6 +:10B880008FB37696F7DD95FF98DC9F7571815A0E20 +:10B89000F89067F5642E0071B422E2F9F9040EE520 +:10B8A0007D52B4FECA6F9AFE3CE4F55487389789FE +:10B8B000B6570B1109F8D8DBB45300FBFD269928C5 +:10B8C000188F106A86CD8C8A7B1D1105C457F3DF53 +:10B8D000E6DD0EF83D37D34C002E65E81927D80178 +:10B8E000E74223510EBA9BD71F7C645AA108FD1072 +:10B8F000E40F233F1425DB74F55993493F37A5DB4B +:10B90000447364953B06FDEA24C667BDD66F96FF77 +:10B91000CFF4DB04AADF185F8BD1FAED2689F17D25 +:10B92000947E4B8DA5DF56D6CAA9C0172BF766A704 +:10B93000025D57BEB1A44F2CFDF6BA8FF9F76FA880 +:10B9400079E66DFDA87E1B1EA5DFFA51FD1623AE1C +:10B950003B5AEAA57EB3FCCFC8DFEBA0DF62CCB7D1 +:10B9600058C59FA6DF8A43B5A8DF8AFBF1BA7CA938 +:10B9700049524FFAADEC97B3B02EBA6D31F807F0DB +:10B980000AFAED0D55CFC138A0E7FE5D727D273D67 +:10B9900057D55B3DF73F84674DCFADECCFA13DD38D +:10B9A000950F999E5B99C5F4DCCABD4CCFAD1CC404 +:10B9B000F49C51BF1574D16FECFBEA21F47BF423A6 +:10B9C000B37E7D1B6D2F9923BA2DF4FD12593B9F39 +:10B9D00051333A5ADFFDBBD48DBE739FC1732E3DE8 +:10B9E000E9BB3F82BE1B847A6C20C891913F6E1CDC +:10B9F00068D3E5D3BDF7F5B1E75E0479F9038FFEAF +:10BA0000F70726E627EDFBFAD84890BBF7001EAAF9 +:10BA1000EF9E51F9AFD5E7477D3A792893F7AA7B96 +:10BA200018FEAA1B3936DFD57C408675E06F17D12A +:10BA30008FBE7D2FF3A3679B5BFAD8C0CFFF5F2239 +:10BA4000CA25FD2B298BE28739172B30EEB92BCE77 +:10BA5000B905FCCC3902B1801DBBE0D08D27C07E7A +:10BA60005D70713DDABD0BE07922E9C8FB98DBA17E +:10BA700027F5F6EBBCA69DAF6590AEF91013CD8C03 +:10BA80002E13577181CD595DF323A85D86F92DC61C +:10BA90003C89DFABF39FCD47105FE48F7CCCF8E5AA +:10BAA000EF8D787233BC54ADE6F578AAE162E28995 +:10BAB00052BAA42CA5132FB7BF14599701EDCB3957 +:10BAC000F4B78CF3D6F0669CBF8647CDBF59A0BEB5 +:10BAD0003F3F7424669E8886E72EF9221ADE0DF811 +:10BAE000784BD333D7906120971F983C3F1F0D7C34 +:10BAF000F47B8A170AE7AD7307E9CE2BBDA3E26595 +:10BB0000AAE748618A0C782435C067F3CA77BE96E5 +:10BB100042E777B392950B21F5597F933C108F68DC +:10BB2000B6B6A31ED4F8709499C98559D52BEFF5F4 +:10BB30007515E27AD3C4B950BEC2063DA7E699791D +:10BB4000EF61F2D7CCFDF7BA8C518867582E489137 +:10BB5000B65E015DE83FA786185DBC4017FACF6965 +:10BB6000A4FD20E0BD3A997387E1FDA69DF7023F51 +:10BB7000BD6EA5CF41CECB39F716860E7B7ACA654E +:10BB8000F95888C5C718CCC8EB5C3F17C07B895DE6 +:10BB9000ED9389E696F7008E89546E36C3C300FD97 +:10BBA0002F8AFE46FBC5C8073DE50375C7EFB92AD6 +:10BBB0009E5F073AD801DFED12D843DE305B7FB4D9 +:10BBC00076AF201722DE343A34D1F56514A38329E9 +:10BBD000069E6FD6EA2A9EBD214E84EF6FA0FE6FAF +:10BBE0001207BB7E5F1FD4F8DD2C77C513C415D2B6 +:10BBF000A3F406E8B7E87DCDEAA6B7115F37AEA695 +:10BC0000E699DC155F1A7D400F5E0E6FDDCA4FD3DB +:10BC100091987961DF557E4699F5F2B3CFDAFEE669 +:10BC20007088ABEDE550AF9050822E7E30D3CCECD7 +:10BC30009666AB07F9BCFD0DD1BD45EEAA7FA6A85F +:10BC400074017F25FA7CE2649808E84D97957CA6FC +:10BC5000CD7B00E3B7E8F5E075AB07E9D75DFF33CF +:10BC6000CCCCFEEDCE1ED3EAD7C37890D728EBC755 +:10BC700033AE475A5CA9A77979D471BFEFBCB471D0 +:10BC8000BEEBBE8497B4603C4EDB9FD8C37B768905 +:10BC9000603F1673BA7D100A39EE6FFE13FABF5972 +:10BCA0001ADD7DFF103F0A533CBFBEE3498C639F02 +:10BCB0007EF6C834909F15AFF0C442E5AF75878318 +:10BCC00084599E8804764245238FFB5D4408E7CD66 +:10BCD00088B233A827C3F0F1A203F55EC52E73A086 +:10BCE000847E5FF1F26739107F6B5DC3F49FFF596B +:10BCF000951FFD911CC807A810D8FEBC913E8FA8C7 +:10BD0000FC796AB76D0EE86F6E3B3BC75B119C2DEB +:10BD10009AA3E20CF79B4516E7DE6DC33C6CFF333C +:10BD20001CE631037CD1E748B5FCD053CF30BD5C75 +:10BD3000D12406E03C70C5F69DAD1017AFF8D08C4D +:10BD4000F6AB77FB1909ECD3C92F3ECFCE1B37F1E9 +:10BD5000BA78689738E4763E6C86F8596315EA013C +:10BD60005A3F82F5A01AF7FB8E71B2152FEE7DD9DE +:10BD70004F51B8E2374F3BF15C70CB3627C623B743 +:10BD80005F7E5FA04BDC3178BF1A779CFA05C1F566 +:10BD90002176DCF1A4CA2721B33EEE48B627613CE8 +:10BDA00092C299571A237ED1C1FFCF5F7802F6CD98 +:10BDB0004EEDFAF20980BBF29B734FFC94E2932A9A +:10BDC0002017ACDBDE67DFC37D06EDBBF7557DD208 +:10BDD000FACCD3B84FD3FA27B31B7A6BDDFB4526D9 +:10BDE000EC53B4EEFC3A05E2B8ABF74E417F6DF58B +:10BDF0004B9353490C7F402B817F03BDD82732D210 +:10BE0000ADB9B13913E03C4DE90EEB77473C3958F9 +:10BE1000C5E2F4B21A47DE117B5FAE4BDCB871C6E7 +:10BE2000CDD7C13ADE28BA65D28BF8F1614ACFE1AD +:10BE3000BDA0E30E759F2038F5B2F1E3D3F00F4AB1 +:10BE4000AF0B667D1CFE42E392FF7C0CDA1A93BABC +:10BE50008D1F877B813F6DDF6FBF59211690A35DDA +:10BE6000CF61DC1EE8477D0FD2FAFC854C88BB1CF5 +:10BE700017DBEFC0FCEBBD66CCA3AAD8FB01CA530D +:10BE8000EB4B6FE3BE1A51F7DF5A49C71FDB27514F +:10BE90007D3AEF56078B3BAB7480B8B4ECC4E76ACD +:10BEA000FC99F1B51697EE2E1E3DD63280EDBFAB54 +:10BEB000FB91555BFF2C1143BC9F1B0BF43A72D9CD +:10BEC0007D540D0F2EC0C398E8FD96D8F1FF8EFD6E +:10BED0001603DD809E608F75ECA7D07A3F88AB0794 +:10BEE000B80F62EDDFB56E66FB34AD62ECBC456D3C +:10BEF000FF65A4C5B0EF12E8DDBE4B4FF3F8AE7896 +:10BF0000CA0627B44F577C9DBA145BBFDF6AE1D4E1 +:10BF10007B03BEE7BE7E2567CC1B98057C59D57890 +:10BF200044027B4A5BDFB4F99E52FDE753CFF278BF +:10BF30004E645DB019F5BB517F5413163734C25BA4 +:10BF40006E617AABBA89AD1FA776390276DACFA9CE +:10BF500003BB91AFAB771C91FCB4BF83DB7F234560 +:10BF6000A2F2AC60FD0844C17FEA85FD396C7F898F +:10BF7000F9EBC671EE52C7F186628FE3DD71463789 +:10BF8000CE0A7F5062E77E2E3FDE4941990DFD9D2E +:10BF90006C1109E4FD9F0CF2C58118E3CFB5885AF6 +:10BFA0003C8BC90F5D47F11CA6839DBBE41325B4F0 +:10BFB000BB573BC67E08E7FD573B2419E21775B512 +:10BFC0002C2FB5EEDFDC6940EFBA845B713FAEDE4B +:10BFD000805F57B22B1FE21AAEC2D251C0AE46BD2F +:10BFE00093A09874F0AF7614A7CA14CEB5AA9D4654 +:10BFF00004379E0BE59D45C5301FDE65725963EC25 +:10C000003B88F652E289C28BE8D29FE3249746CA66 +:10C01000D08F967F53696939888D2E05538C85B1F1 +:10C02000ECDDFC992E9C77DB0ED57F5088EC4A61C5 +:10C030007964B08EB4ED8ACF21C3F143A2507EB4AF +:10C04000A9CFB91DFBF7835E5AEB244A0295338AC8 +:10C050005599CF86F3AC232C5C36F0E999FF7A85AD +:10C06000F66B0DF1E857B4D9B57C522501E4CC4606 +:10C070001EC4BC4160E56F933AE134E613127825A3 +:10C08000EA3E8D29BC1DFDA1B39B587C802757FF3C +:10C090007A028BCF9100C0AFAE2F2B5438CF12E273 +:10C0A0000EC3FB3B1C180F58F6C622941FA0433446 +:10C0B000BE928AF5E75E1BACCE1CF067365A55BFC0 +:10C0C000C6AFB4C0399BC56ABF7D4AF5E762A918FF +:10C0D000FA415E97A8F2FAE5D2A243988FE6598A10 +:10C0E0007A3E758EFEDCAC314F4B20AA9F1C60FE61 +:10C0F0007397BCADA6CD08B7317F6BC5767D5DC3A8 +:10C10000E327A037AF027412FBE5E2803DE237324D +:10C11000F8D713467D77FC9AD3F4F8B5CA7AFCDADF +:10C120008618F1A7C7AFC3ADC797E6977687DFF844 +:10C13000B1FA73C8FF2AFC8A56D58E54F14AFF4AD9 +:10C140002D294C6503DCE94218E5C2284719F63071 +:10C1500007FFEE9F1CA8C5AFDC0ED4EF69EA7CB8E0 +:10C16000C5EC3B1BC8110FF0BA518EE02420E879D2 +:10C170001BF9D875CC0AC4FA8C7C7B4DF7F45C357E +:10C18000FDD5230BE9579B807F87233FB0F3BE8902 +:10C190002450970572EA76C1FA1DF459DC8B45B834 +:10C1A000F785B8170F82FB5E5C583EA4E6ABB40D72 +:10C1B00025786E30183E9F02FAE9A1DCF669A0F7F7 +:10C1C000BC4B4829E8C11FC5B1F3030FA865BF38B0 +:10C1D00049D5AB856F4C82EF43A20CE7D5DB42DB40 +:10C1E0002C83A0DEC4E33D2ADE84FAAB60FCD6904B +:10C1F000C8E05A6C090C8238C85E11C76D5D3C01FD +:10C20000CF6576D86F21962FD216FACCB9284A9FDF +:10C21000B7363D7A15C4B9369A62E7A94CB19A7E11 +:10C22000D8FA1BEC92B737C5CAF2EA1E1A40E7519A +:10C230003DFDACBA0E3379B856A5F3AB4B6FC4F9DC +:10C24000BF14E26458478AF8DB6E1A46E739EE3DC0 +:10C25000418DCFB078E528F5FD3AD02FA85FEBDF10 +:10C26000E5E9C3DD470502E7F446D52C457FEB152C +:10C2700027E573CA17794A7024F06D612801EFCD64 +:10C28000F17E4CD0AE1FDD22E8F8334F5D57F3222C +:10C29000545EC044F950DF3E2E2218ECA0000FFC83 +:10C2A00075ED71FDF38556D5EE729214E0F30D979E +:10C2B000780EF25EDBDA897B0D85BB6D715F84A33E +:10C2C000ED3C9CFAA5E525BE38D67ABFCACAF8620D +:10C2D000A344709DD9B8D48EF1C5034B2BAE80F525 +:10C2E000FDAB1F7BAE88758E3C4A3FC5B37C2C25C9 +:10C2F0009E8C05FE5ECB31BCD7A797C6C8F7D7F892 +:10C3000059E36F8DAFD397C67962E5357E63657665 +:10C310005AC1D2219C04FEDA3E0E8FE3B6AEF15C28 +:10C32000F6DC8D9FACC90078BC4DE7D0EEB6843802 +:10C330002596BDB1C1EAC4FE5BD7F86B218FEF2E05 +:10C340002A9CA027BBEF7703FA5B3F81A02C7C6778 +:10C35000A92FC373BC4B2C640BC4BB85FAF45B1CC4 +:10C36000C0FF936F5847E17DACD484EBEB46D18D91 +:10C37000F0FBAB08C1F8831ACFED378D6C8E3ECF42 +:10C38000FC8435FF592BA5C7B35617D225C9E3E660 +:10C39000007EF73FFEDB09F2DD76D18C74ECABFA60 +:10C3A00043DA77AF5999DD36334ED90ADF93F26419 +:10C3B0009413B7C7E95E3C12EE4DA0788F92A34E5E +:10C3C000FAF9F1BB440FD571149E44BB09F99228C8 +:10C3D0008AECD2C529FD28479A5C903047208F4DC2 +:10C3E000D3AB5C880B3BA81C8CB2D8C3E0772496F7 +:10C3F000D3795310ACC4C2FA6B114E759CCBC63CBA +:10C4000079CA977970388A6048141271A17F4DDF1C +:10C410006A7A7A6D02417959FBB010A8A3FD6C12BB +:10C42000225688AF64297201A41A250A329E17EF9A +:10C430005F4E30FFD296FD784287DD42857EC4375D +:10C44000FC8258FB797C9C862FCF1F406FE41C6ACE +:10C450003F00E68DDBCAC673BF66413BBD437FA884 +:10C46000F65891BAFE8EFBDCC4F209C29348F43E42 +:10C470009B517F68F6C9B8EB226B60BF68DC9F18E0 +:10C480009CB45B05BE1BADCEB7439FA8EBE69810EE +:10C49000D527F4FBDCD0C866B8072BF76326C75D49 +:10C4A000F4C9213F0FF8FBBE7AC4C81723C2542E2B +:10C4B000D5F6A132DCA7E1EAA843FB1983DE499E49 +:10C4C0003E2A15ED5C95DF8C78D6E4DB28F7B9774A +:10C4D000BB9BCD0C2EE6471AC6215C271C7236E8A2 +:10C4E000A5B778B0F7DBF2291E285CBF02F9A3F4E8 +:10C4F0004B381FB801E6BF2174BD15E4E47BAF27BC +:10C5000021FA75549EF6D3BC273EAE0FAE274EC01F +:10C5100043F5FEF3EA7A12467A77C8019593E878F4 +:10C5200089C6FF467ED7E4A30E2EDEC8C673760406 +:10C53000D6599E0BE2653066B2C90578D5ECED3A66 +:10C54000D5BE25FE74B4FF56BB88BA1E6506804F63 +:10C55000EA44CD5E775BA2E353AB1D05A997DB4FA1 +:10C56000F55EA4FE59D4391BAFD08EFE9BF7A28492 +:10C57000CFBF37FE9A2814793AFC8D891BDD157FD1 +:10C58000F17184B0FBC2FE9F9FDF0C237FDC277715 +:10C59000CEEF5AE2792542F547DEAAF57536193F06 +:10C5A000399C96D7552F68FB9FDDE901A3BC8FA965 +:10C5B000AC6FC6704B0FF2EEB5A9F8256406E8B370 +:10C5C000F1616AB7647595FFF3EAFCBC3686F7B68D +:10C5D0005BDB07833CADE73D3571682F464C26B0E9 +:10C5E0002B7613B47BDCFB8F3A51DE5B9274EB4FFE +:10C5F00057BBC08FF2A9D9A79A5D6A7CAFC32E55ED +:10C60000D71B2D3ECA355179A1F03C19E7F1031C27 +:10C61000752EE6BFC20157D0634F583D75C05F36D7 +:10C620003A9738D82F1912CE62F196B04E3EBB938E +:10C63000479B41DE82143FB0FEF9E9FA3788EB1ED2 +:10C640009EB171090C5EAA85C0BEE99747D860D536 +:10C6500004F3C7FBE5B0FB6BFAE5B2FB3237C73139 +:10C66000FB658BA17CC25AFA18CC4B1488DF9CFB6B +:10C67000FDE10650210EF9649CD200F8B0142B386D +:10C680008F0C17717394DE19429083BC89C44A9948 +:10C6900063F147D2B9FF48FBCB2891F3813F3206C3 +:10C6A000123C379A118A7D9EE89538F187D9EB8D37 +:10C6B0005DCEC1BCA2CACF4189CE37A9849D83E992 +:10C6C00088FB50F001BFAD8E5B71B2AD17D83EABA9 +:10C6D0003F81E1D9E8BF01C1605E825ABF57228223 +:10C6E0003511FD2B3FF0AFDF6441FFCA46DC41D07E +:10C6F000B71FC4B1F8EC3ACEBD1EEABF10DA2D70F8 +:10C70000CF8F26379A3C3C34E116B7405F755E7791 +:10C7100036077C5F2A17EF009E5B279C1DBC1667BF +:10C72000D29EC9F84EE175F9F61AFD9A441DFDAC8A +:10C73000105789D6F30E6908D8EDAD5C9C1BFCAA96 +:10C74000D6E51C8397B3A8E71104DD3CD36CCC1F5E +:10C750006953F5E7DFE3B2901FB5F584CE6F3DC6B0 +:10C760007F0DF3E838876A38776A3C979A96DD112F +:10C77000074AC77CDC5209EE3223674336B4E3BC78 +:10C78000CEF64C12E3BC646AC41AF35CB05652BCD9 +:10C790007D0D784B156B12401FA7DECEF488111F5C +:10C7A0006D9C7FC441D847FB8318331F452BD3D2E0 +:10C7B0006E4A584CDF4F4BBF014BED79835D8819B2 +:10C7C000574CB2713FECDC6403B118FCCD241BED77 +:10C7D000EFB4E79DF71514FF768CBB37C431BC3737 +:10C7E000C431BC37481A3EE57890BFCEBA5B97F7A4 +:10C7F000B4C1674910200FD19F8EF2B9C4C5E8DDDE +:10C80000F9BE82F64D1FA2DC301794C406916C432A +:10C81000BE67F121ED7CC8AF7CCF2440BE94DB968F +:10C82000A5FAFB1646DF0406F7F90D5370DC14B2C7 +:10C83000C63A98E27969A9C90D71A3D30B3F72C2B8 +:10C8400091E985192D79200FA7798F1BE6974A98D2 +:10C850005FB86C8E1408D32E931BA8C26274BA0101 +:10C86000F73BCB4C31F3AEC7D8D8FEE9D138179699 +:10C870006969D3904E9DF59204F04B8C7C4AE53566 +:10C880007DF1A8CE73CC946F145B0C796B134913B4 +:10C8900087EB5B18F195ACB1B3AAB7357949063986 +:10C8A000847DAB52AA47353A0F505F4DC1B828FE80 +:10C8B00071A1D7BF067FC3795D01EA454D8EC810CF +:10C8C000A6E7ADA077A3E2A16D7B3FE80FFB8E9FAB +:10C8D000FCDB3907EC3BFD556877809E3D7ECFBB86 +:10C8E0000E38C7F4C93D2C2E7287C14F5B6463FAC2 +:10C8F0007F8FAD741EE07781EF1F799E287E2577AC +:10C90000B3FD93E501DE70DE5D7F6F505530C97079 +:10C910008F901FF15AA5DE1F66A4C7461B8BB72C4C +:10C92000DFB159CA90617C4F258C7F5CF5438F370E +:10C930003AD0DFD1E059B8638404BED95F4366754D +:10C94000FFBD4564EB875202FB671E156F46380F2B +:10C95000AAF76A2FF925CB8F29A363DD4DF5B02700 +:10C96000C4CE7B18E7B1E413B92895126FC9FD1C3A +:10C97000FADDF0FE3D743DF3DC7D1FEEB319E7D91F +:10C98000F55E1F05FDB3652ABD8DE76D9785D83E21 +:10C99000F862E241F9EC72FE36C4CEC518E38D6749 +:10C9A0000F65DB000FBFB0A9F1C43C3206CE6DEFBE +:10C9B0003A3420FE72F7569F52EF8B827BBBA13C2C +:10C9C000EE2358CE032390E2BF32F4F65DC05FD56C +:10C9D0004D3BF13EB4EFAA8FAA42279C904BADE9A4 +:10C9E000256A876E03F9208B399D7D5ABDF99CC459 +:10C9F000FC6A869FDBD4E7B7013E7220DF5BFED97D +:10CA0000044AEFDB2AC5F3D1F7A53D6FD3EFC3F797 +:10CA100076BEDA3CB5796BED556A5E9CF13B4D0E06 +:10CA2000E6A97CB978EBF4757D298AEAF67E91A9AE +:10CA30009E93C3F3421A9F2D23A545E931F849A3DC +:10CA40006F07DF847E8EF3D3E8BAB8BE4CC5833F50 +:10CA50004DDD4F4C837895918F7A3AA7DD2A463287 +:10CA600041BE8D7CD2DACD7D28211BB32F16CB4A57 +:10CA700011C4CFA8F9BBCE1565DF1C17EA0FFE1451 +:10CA8000E46E2BE3FB0E3D084E31E8F737455CFFC3 +:10CA9000573AE454B8FF0FE9370EF213CC7E784FC3 +:10CAA0001BE7984F51068A80FF622C4FFA4A958106 +:10CAB000833ADB976E3CE704FBBB6D08C1B851AB12 +:10CAC000430FEF691B8F7AE3B44A8F4AA1E59B3F7E +:10CAD00083CEDADA827917C72EA971A74BE6E2581E +:10CAE000F3B4D839DDBD7877A872A8F9350B54FABC +:10CAF000DD1162FBE90B374D477A74C9BF54FDA1C4 +:10CB0000B2460EF58E913E4BDCD7633EDAA2403E34 +:10CB10007EDF855EE441A4BB916E77DA5DEC1E3763 +:10CB2000A146827BED8E6DE270FF7185107BFF73F5 +:10CB3000B6DDF49DE6639C4777F02FDB5ABBAE2F42 +:10CB400081F98F9080CF8DF06BF35F4214A6A7D44C +:10CB5000F976372F1299C4F234D4757F399C5B81F2 +:10CB6000FD93077996CFADC6A134F835788DF328BB +:10CB7000E22BF17C415B038F79D977F8D97D067779 +:10CB8000ACE570FDED8E4E9A5ED1F67BAA9BCA3065 +:10CB90006FCB43FB013BB6ED63C2F629D67378CF6A +:10CBA0005BB7F40CB17CA5EEE84908A3DB624A3719 +:10CBB000F03FBBDE9F90AF0C8CDE270ADCA00C8C14 +:10CBC000DEB72241CC5759B17DBAEEF98D76358E5C +:10CBD000A5EAF59EE48FD424C48C6F69F2A6C99FA0 +:10CBE000268F77DA65666F0A81831959809F87D10E +:10CBF000BFA1FA7A9E9DF93D0FCDA5AF546F3CA71A +:10CC0000DBA7583296D16B095F82CFBBD3BB140F21 +:10CC10003ABDBDD8AECFC3F8A1F3D1E6A1C98936DC +:10CC20003FA39C18BF37D2438BEF19E962A407C01A +:10CC3000097EC65B7B6D813514CEB73806B77FAFF2 +:10CC400015E16E4D9BACC0B9CDEAF4F958FE013E3A +:10CC50004C07FBB0B4CE8E76AEEA878DEA5D5C22DF +:10CC600057B5CB5EB22A23D9B9A7D224E09389B5B0 +:10CC700091191617218F3E585C04F7A44E7C383268 +:10CC80000342F1BF7EF04656DF1679D7E286FBFC01 +:10CC90004B8A0A69FD71D02FA02FFA95DBE0FB6E5D +:10CCA000EBC473F9BACCDE1F652E9DCFEEB166EDF5 +:10CCB00095D43EB3D0F5AEF2F0E057417E2B5B4AFF +:10CCC0008A212E54091178BADE5529CEB02D87ADB0 +:10CCD000FBE3E97B1FD93C4FD921EE76712DAE8B5A +:10CCE000958705942F7288C567053A572BFD6E6DA1 +:10CCF0001CB593297ED7265ADCE017D3E77EF09740 +:10CD0000D7262AB21CF55CA31F7C0770AC35B17C1A +:10CD100082FD6F0C8E8F5CC62ED8EF2325E0CF34BA +:10CD2000FB2C581ADBF325179EE7C837B17889B179 +:10CD3000FD6DBB76AE49CE00BEA83E24A1FCC31F4C +:10CD4000D89F5584C9493561E7D0AA0E133C775363 +:10CD50007DA808CFDDC0B9844F757AE05F73EEA679 +:10CD600093AF189E0A04AE44881AB7D06ED5D5F991 +:10CD700054D310980FE1E3DC706E84CF30D5ECA271 +:10CD8000F3E7AFA025C587E072F370FF4CFDE4899F +:10CD90003CDC9F5527AA792D26763EBE63DD57E5FC +:10CDA0004F2BFB394A8F02DD4FFFB125CFC6F6531B +:10CDB000D0AFD6E65BC72984037FED3582E71972D1 +:10CDC000934933E0CF4694B1C06F1647A2CA976C1F +:10CDD0003F9BFE6540E9369B7E23537EFFFAC19F51 +:10CDE00022FFBBE34DABB2689D73F8593DC3742E6F +:10CDF0008BB230EFA865F56B4CE706D0BAE858C3A4 +:10CE0000EAB0F14A173EB3A3AEC83F14C67131BAB7 +:10CE1000EE50AE01FE164C2CAE231C90707F47CB1B +:10CE200057594B7906F8D1E2607A745D6DC173365B +:10CE3000889B172832E44FEC51EF41FABEA5865784 +:10CE4000DE66427F094AC07FBC83E153A30B69546D +:10CE5000AE813C5E1254AE817DBD7E0E4FA2837EBC +:10CE60003FF2AD9689A0CF1BDFF9280FEF73BF8289 +:10CE7000F533F22DEA43D2F99CFE6DFFCDD1FBE4F0 +:10CE8000FD1CF9A9F01D2503DAAF9CEC22B751393E +:10CE9000AC53882C65839FADF72F1B09D34F1FD947 +:10CEA0004AAF70A03E09E33AF613BB6700D48D7E0B +:10CEB000336949EC55DE9D947337EE172566347D52 +:10CEC000B810D685DFB17B4A3845C1FCD3173BEE9D +:10CED0006B231897B2913837C48D899BA4F953D42A +:10CEE000F89A89F155725E94FFACCE877E5F08791F +:10CEF000F2636C2CBF81CE8F07FD3A82C8588E84B6 +:10CF0000385936A0D883F53D24F8E14F69FF8F5892 +:10CF1000597CCAB29DE8E28F650E16B779C0C9E2A6 +:10CF20008F7162F016B02BE2CE1017D8156D8F4BB3 +:10CF300002EECF0BAE9B70DFEEA009E3DC4F8B015E +:10CF400017EC17B55F25C85B48677F6D2ADDB57E96 +:10CF50001F91E4AB20EEF70B27AB3F9D4F308FBB0B +:10CF6000FD841480FDDCC40C4B4D743C699E83D958 +:10CF7000BBBF7315CC043A04F7C611187FCCBE387A +:10CF800013D0E3B91DB956E08B170147140F89661A +:10CF9000D79DD05FE2390A6F163E67F9FD823C22C9 +:10CFA0009EE277FC8D7619EED17ADA1ABC11F3562F +:10CFB0009F37E1BDC12F4AEEE9507FF1ACEC023D55 +:10CFC000FC7456300EE7F3BC09E7F3625CFBD52B2B +:10CFD00029DC0F0C61F12EC14604D0CF82A940BEDE +:10CFE000933E5FAEF2B1A6AF37811CD1FA231CC1CC +:10CFF000730C82291FE548CB276A6B27984FD467AB +:10D00000660B0FFC1C375D8B3B857988174D2825F7 +:10D0100068CF4DB08B78CE05F299E1BCDB44550F5B +:10D020004FFCB8B284E507BB0FC3BD9ECD76F57E3D +:10D0300030759F7392CA27D791086FA1EDD75D24F1 +:10D040006E88274DBAA8DF8F78CA605F4E51FB57B4 +:10D05000DA5D85F0389FE8EDBF290D4527603D2C4E +:10D06000208A00FC34D96268073BD209F7F0EB9FB5 +:10D070003FE050FDDC4C92199DC7A6ED434DE18782 +:10D080006E44FBB55872035E76DA950F203FC0DF21 +:10D090002292CBC5259FF2B17CC321176D04AE2C23 +:10D0A000A4FC6987F95CDD50EFB7D2795F3D90F55C +:10D0B0000F7C08FAE5CAC7939340DF8F57E9A5951F +:10D0C0001ADF017FB9E2197FB98677CAE7D38E2CC0 +:10D0D0007C4F9337E03BE8678F18981F6BBF9BF23C +:10D0E000EBD3C0AF3BED04FDB89FA55BE6809C6928 +:10D0F000E3B4AA7C6D2CD7D5AEDC0FBFFBE4BFC078 +:10D10000D68DC2BE17A5E875BF4F0283D72BD7CFE8 +:10D11000980679687611F3CC52D47351D1FC921EE3 +:10D12000C52F1ADFB5DA599C48E39FC9BBDFE5E19B +:10D13000F9E40B84B8B24887BFA2F1CF447F18F757 +:10D14000812712E69F18F9675737FC937F5E1640D8 +:10D150006F75E19F438C7FBAE31BDA0FDE6B61E4EE +:10D160009F771CAABDDD2DFF5CC2F3FCABF74EBE62 +:10D17000EC7E65934F9F9F6A2CC7D962E72FBB5403 +:10D18000BCEF96EA6FCA01BD31D5C4CEEF0924E3E6 +:10D19000160AEFEE38EDDEFC9A6CA8EF14981EDA52 +:10D1A0001932A31EDA69F778307E9B6661E757056E +:10D1B0004F04CE23B8FB5AE4E8DF21D9EE6076585D +:10D1C000500C8FFB02ECF137181F8C9D9ACB432A31 +:10D1D0005AFA62A617461D9736C3EFCF3DEACCBF79 +:10D1E000007C9606B8A3DF798F4A78CF52F55109B3 +:10D1F000F5E36FF7BD5D04F1512DCF79CC9EB78B70 +:10D200000A86C2FB8CDFFEA1EA65AD8E4740405F17 +:10D210001AEEDD1FD7711E4B7F6F7E29F0514E67CE +:10D22000BBF13EF9601CDB3F994D6411869871B4E7 +:10D23000F45EB8DECC78AFFCEC303BFF36F3B027C1 +:10D24000F6BDF22A7F18EF37A7F6778A13ECEFE7DF +:10D250005AF6416884C86CDD0E4A35D7303FA326A4 +:10D260001BF8499343FCA3F80B7E3244F7BB06B787 +:10D27000A9F37FD02DB0FBA92212EE4BFE9CB0EF9C +:10D2800082EA3A36CAC9F440EEEA17E6039C23CB99 +:10D290009566A0CBB32E16D7F905095BB2816E6EE9 +:10D2A00001F75382A23CF90BAEF33D22940EB1D3A9 +:10D2B000F63D7DE246C2F88F3A3D639C609F09EDE2 +:10D2C00087E0BB31E37347821EB78F589B04EB9A0C +:10D2D000063785AB789BBD130E0DAE814EC6978F7A +:10D2E0003ACBC6001EE03BD04B4D478E59E07B8DBC +:10D2F0001F827BCF303E88E20BE0834EBEE01640BB +:10D300005DC383A2AECFB7FD8BF8428B6BF4C81719 +:10D3100010B7707E2FBE980B7835F205B5E73CCE7E +:10D3200018F65C50627993C6E73FB1E7E3FB6E897C +:10D3300060DE13D96765BF6BE849C07D90DFB8D860 +:10D34000986D9F1CCBA4A62859E56476BDF63B2AB0 +:10D3500023C21CDA9F23A8A2B80DEDBC7EA827DD4E +:10D360002AFEC8318E83FB4631373E03ECD0701263 +:10D37000D86B23CC256190875DB68919603FE6DACA +:10D380002664C3FC5F1EB2FA4D58D25EEE5BFE9B74 +:10D39000AD72A77DA5E9C366B55B6DFC352A7F4CF0 +:10D3A00052D87927D0EBD17068EB039009E0E0C246 +:10D3B000B34DDFDA508F8722146F93000E8A87FDFA +:10D3C0001C6904FB21DFA4244F063BB04F580038F2 +:10D3D000DBF67E9D09F1CE92D0EB1F02BC25DA3E32 +:10D3E000AC5BBF0F6BB4B7357B48F33F347B49F37D +:10D3F0007BC1AE82F632D51F7199D9BED884B005F3 +:10D40000EF5378E4AC7C95A2CAB340E751A2CEE3D7 +:10D4100066D2827069F7A94C53F1517288FAAB3920 +:10D42000D04EC8548A87A9EA7D2A53DDFAFB226EC2 +:10D430001E1BFB3E15AD9F9EDE37AE1BD71AF6A313 +:10D440007E6879C8C7EE4FF9BD8FF9C3E307F07E58 +:10D4500001D6DFB159ECFE0917C3C32129F63A768C +:10D460005195EBF1A6480E9CC7DEBFE7EFB86E1EE4 +:10D47000D8F3F7F7C18E1C77422090973BFEC4A8E3 +:10D4800078CC0F182B235F69FD7A3F6FB411F69C9F +:10D4900044FFDECC410A8F7225C067C1F295538FDD +:10D4A0003C0AFD9D3F2A90E8731F45926720C4E522 +:10D4B0008BD4DF1D3AC8317B4A6B3FA8FEDEC71113 +:10D4C000956F212143BB67C51C45E7A9EAFD1F1ADB +:10D4D0005DA71E2F3E21E474A50FFCFD33E2105A18 +:10D4E000FCE19CAA0F49F39FF07CCEF58D770A6092 +:10D4F000BF5F9FC613256ADC1B64EAE947C5214E5E +:10D500003A0DF66FF3338F4E83BCE5B7784C81F458 +:10D510008676BE9903F5163EE6BD2A46FC5E1FBA26 +:10D5200013EF55991BCFE4A3A7F1C75F4DF96438FA +:10D53000D09D303B308FDD4B62A4EF813DFF9114D5 +:10D5400019DA3DBEBBA3BF910EAF9C2AC07DAC9E35 +:10D55000E861E4DB7D749EFE2BE177532DC48FBF21 +:10D560009BEAC2FAABBE34AC6BFCEADDFB6412D8BA +:10D57000791A9F4E49627C336EF7A349C4DE492F66 +:10D5800023DE86C533FE7FC9AAD925EE59D3E8A389 +:10D5900077E93A848CEA272D903756AAC23AFB7075 +:10D5A00011DA25443DCF625CDF66F3B74D0175DAD1 +:10D5B000D3EFFECC94CB7AF57B39C56FD50BB00E8B +:10D5C0001609AB991E53ED780D1E239DDF23A50888 +:10D5D0007F77F019F9C008E74B1DF9F60AAE07DAB4 +:10D5E000EFE0CC18982526C69887868F9984AEC719 +:10D5F000D9BD5F8F6F8CD7DBEFE78E17FE11D0DAC6 +:10D600009DBC19E9666CD7F447110C908BA51FECF3 +:10D6100093B9F12948DFA28B1251E83A43FAE9CFD6 +:10D62000F593922B91DF56B9D8B3EEF8ADFA224FAD +:10D630003C233BF94E6C7AD8067CB75BA8B7411CFB +:10D64000F53AFBF43A10BDC2CF0B66E2FD1511139B +:10D6500081D0DA94D099668833783F2478BEA120AF +:10D66000B47F32F0E9AB420BFA596DE7097938CA59 +:10D67000EE6C0AD5D9C02E6B4A66E7F30E26105D14 +:10D68000FEF4C578A66F9A8E9E9DA6C4681FEE62B2 +:10D69000FC3C8328C939F49F45EB297F801FDCC7F8 +:10D6A00081719242CEFD5A32D82D7339F423DAF6C5 +:10D6B0008E792D99C2DB7A7B02EA99294DF7DDE953 +:10D6C000A28408FE63243E6F2FE3F0FE8422D98DEE +:10D6D000F5A2C559E8F78DF926694609B4DF20A2FD +:10D6E000DF3385AF14205E753A8DC3AB3CF6709185 +:10D6F0005AF83D62FF74360E71F993C03F7DA7243E +:10D700006904FE669EACD507E1EF2E1283FFB6FAE0 +:10D71000A573FBCDB47DF52C0EF38DA7B832883FF1 +:10D720008A7F8AD64B38AF5B42A905C0D7338AF5CA +:10D73000E71EC3AA3D39ABD44602D1FBF99C0BE5E9 +:10D74000FAA0B5FD56FC1DF1BD2281F969727EA3D8 +:10D75000CAEFB3E724E9BE9B4E98DDA9C9D54DAA0F +:10D76000FCDDA8FACD733D19BAF14B09B387FE4031 +:10D77000DA0B8164F7B8D87EF4B4F696C3F3E125EA +:10D78000BEDF68D087370D31F8BD7CE55AE48B34B5 +:10D79000CE8DF7C8B8F5ED378FD5D78DF26BD40F96 +:10D7A000B3208B8FEFAA27347D306B2F2F423C683C +:10D7B000563EC533DAC57ABBBD277D3126AE1B7D0B +:10D7C0007149BE17CC902EFAE2E3E2EFA52F7E4B13 +:10D7D000DD96B154AEDF8E57D7CDFEA43FE88D293C +:10D7E000FC8E47818FDAE8BA698EC147DABAA3C5E1 +:10D7F000018AA81CA31E38C5F663A65C4C27FE91BF +:10D800009D71800E3D42ED12770C7BA9353E1BE5E4 +:10D81000AB43EF687A25CA2E11F37EB85D3285DA04 +:10D82000A3522EC0D70FE12B52EF252982842B88DB +:10D830001FA69DC1389057A0FE2CAECF4F227F81EE +:10D84000FEE3123BE5C368AF6871E80A97664FE9EB +:10D85000F9A5231E3993DDC3AAF14911E013E47F32 +:10D86000268FFB04FF1BD47F03B300800000000061 +:10D870001F8B08000000000000FFC57C097854558C +:10D8800096F079F55E2D495592AA6C148BF012B67C +:10D890008424588480EC165958A314A080CB688146 +:10D8A0000B6B129A719CEE69FFA642024343B78349 +:10D8B000D2DACEE8F457D83A831AB40801039DD0DF +:10D8C00015504C5834082EF8D91A6D1AD10E4984C7 +:10D8D000D646BBBFCFFF9C73EF4BAA2A854DFFFFF7 +:10D8E0003FDF9FB47DB9EFDE77EFB9673FE79E97E3 +:10D8F000DB9B55B3AD08E0F6998A071400D0F177A9 +:10D9000022C042E07FC3ACAD16F08EC7BED7FC6923 +:10D91000870DF8E73BFC2F9C90FC2CA450CF0B907C +:10D9200009B054CE5FFC577D333D5E3C277AFE52F2 +:10D9300098FDB9920C701BF8CD301CF7F3C58EFF23 +:10D94000EC4B15C7972E8B7E9EE94C4ABF9087FF04 +:10D95000180123BE5301CAD4BA9DB722BCDD275596 +:10D960008F554C33D1FE0F39C5FE0F35970C807C97 +:10D9700080DF7416A7F8B13DB611211C0DD0BAD1C5 +:10D98000C6ED71EC07F1C5EFE8E7663C9F05FC21A9 +:10D9900007B6B45221B701480518EDC4452760FF0A +:10D9A0002A9E3F0DC78624C0EF73245CD900AFE7E1 +:10D9B00098E704F1BDC3B85E00D70DE3FA015CF748 +:10D9C000C84627F75FDBE8E6FE0D2E446A06C0FA7C +:10D9D0001427AF372FF776871FDF5BE3CCE6E750DE +:10D9E0003EDA44F836E02F7B6A080410DFAF77ACEC +:10D9F000D09474802AB7E2B166F5D1014FE3588E16 +:10DA0000F3CB25BE2BB72A10C4E7E51FAE2B07C406 +:10DA10005F5733EE87F8A92A558336FC6749D363ED +:10DA20003B45DF0CD608FADE228E0233B516CD86D2 +:10DA3000FB2CF0281E15F7F13689F76FF52A411DEA +:10DA4000FF798B279A1E8763E8BE58AEB380FE0F1E +:10DA5000DF5B30470986719D0593A2DF5B7C75D63D +:10DA6000E7CAD8FE7CB498E83EB63FBFDC4E74B738 +:10DA7000E33F86C130A2FB958BA56F8D853EBAC56D +:10DA8000B6B1748E1DBF169DEF273A675C9BCEC65C +:10DA9000FB7F8BCE0F114E90BE70F41B8B9E04301B +:10DAA000BBE9071AD179F6558DD7AD32CE3314863E +:10DAB000D279FED459F86FB742DFFCAAA62F2DFE0B +:10DAC000826B9FE76FEDBF2245E7FD695F6F7EDFE9 +:10DAD000BEF33480C178CEF939D1F88DA56B2CBD59 +:10DAE00016CAF762E9B535E61C065DA013996860B1 +:10DAF0001CBC5F55198E6BD1AD972E16FF084F7E5B +:10DB0000FF71805FF3B9FAD693748276CD5720E027 +:10DB10003247C803F2752005E95BDE0AE14404ECF4 +:10DB2000968B733ED7A8F528F069C439E8E753838C +:10DB3000CE6ADFFA655707B2FC19FB966910B0147C +:10DB4000D2732197B1F055D23A23697E80F968CB20 +:10DB50002ED3B2109E63BA05EEF5519B28DA034E20 +:10DB6000A1071A9D265EB7FB2B9B096E0478E5F092 +:10DB7000806240F83C56E709D28B2133F0FB45C95F +:10DB80003ACFDF9C048104DC1FB4769B0FF9442B51 +:10DB900006C84139D306598235B8649D16F691DC22 +:10DBA000757B34A846B9BBD178EF48E02E40926C23 +:10DBB000FE7494A9268BDE0FB74FC57937156AFA24 +:10DBC000369CE2B2EA3FA0F1AE66AB93DEEB3EF8E4 +:10DBD000CF2D665AE72BF02084F05A3332158E4F42 +:10DBE000739883A437CAD493AA09FBDD3D00A48FA0 +:10DBF000A62D0B9700D26D3AB4D738B19D42748CE4 +:10DC000043BFBFD0793384DE1A88749A21E9344344 +:10DC1000EAAB926695F54649921A84AC3EFD74B320 +:10DC2000A4D18C407B490AEE3B43533C35D8BFF925 +:10DC3000AA16C58F2F933EBAB14F1F95C9F5BD3DAA +:10DC4000BA869601664234FF96350A3D54628B7956 +:10DC50002EED0FBEC97C55E68C1E9F42BA13F9FB10 +:10DC6000628C5E8218FB53A6FE35B903F1F08AC5BB +:10DC7000FBDE5484BBE7B4199EC5E770113B93FBF0 +:10DC8000E3A731C61EC5B6070F277A7584EB15E2E8 +:10DC90002307F50779F5B1D79E3FB6A3A7988EF174 +:10DCA0004ADD220DB2992DCFBA33FBF0DE0FBF92C1 +:10DCB0000EB178AD977ADEDBE87C8D8EDB0F8FAD11 +:10DCC000B3D89E97FC49D748F5FDBDF834E4E595F7 +:10DCD0000B895EE2FF572E0CF2B2FD4AD2593E0C80 +:10DCE000793878FE7222E951C4A7AE219FF4B86C4E +:10DCF0009E67999F851C84068E0A6EC3FE8524C18B +:10DD0000F7AF24F61CCF23BCDF62F23C4BDB68EBA1 +:10DD1000872F2A20FDB975D1793380E205E5872860 +:10DD20004F8AEE84BBB10DA03C11FF055221487211 +:10DD3000628610D0BE355E789ADA19D3F414C2FB2D +:10DD4000655CB3DD41EBE929C4F7F0D72B137D0502 +:10DD5000FDF15FBF117C1AEED3B0D1E6D3502F1C7A +:10DD6000D8E8E47EE34637B78736EADC6E3A91FCC2 +:10DD700043F21FAABC169F16A157E6A50AFD300361 +:10DD8000F50EC13503946000796FC623C0F2887226 +:10DD900010DCA410BDF03C397DF844FA5CEE88E854 +:10DDA00043AD563B2193A582E95E9867E2F7D1091E +:10DDB000083E9FD57F3ED23FAABF8CFC1684C3EF9E +:10DDC000F296B9B00D397CB35D88DF7A65E9D14B45 +:10DDD000C0FDB9F4BC5EB943BD84EB8F0FCF841F87 +:10DDE000A2BD188F8421BCE2CF5D04FF84160B1006 +:10DDF0007DD0B0B27C161AF2F9B5A25CC0FD4884A1 +:10DE0000BE1B8CEF59CBC3C44F07A0238DF05E64BB +:10DE1000F3D9497E97B9043F7895DBDD0AAE3739EF +:10DE2000C3E25109B4E1BEF1EB117F2D19B821CE47 +:10DE30006F69C91CA2E713B7BDF13EC9B7D7E608A1 +:10DE4000AB6C98CC9D1D11F67C003CE3247F927452 +:10DE5000DC7768475A3F4E0EB09EBB6A09925E6BF4 +:10DE60003D93EC09E33ED3AFDAD8BFACA717516EB0 +:10DE70000F27268F653D13420D43F26313E7986D1C +:10DE8000F6AF233CA0653E7A0ADFFBED6500D2AF1A +:10DE9000D3DB3F54C90F2D31E50EE840388F2AA35C +:10DEA00053A87DF2E3E47C6ECF2477127E0E9BECC8 +:10DEB0003AEDFBCE46BD7404F2CBA98D503A02F97F +:10DEC000E3AD8D366E4F6F74727B66A39BDBA33818 +:10DED0004EFCF33A8E137FBD81E3D46FC3716A4F5A +:10DEE000E03AD47ADF7298487E67BCE5D0A82DBCB2 +:10DEF0002B89DBFA3B932C748EC3C95067EC4FFC23 +:10DF0000144E0C378007E52ED5FD53DB0D683FAD71 +:10DF1000FE02651CC0D454F75C6D3AAE3B7BE88FC3 +:10DF2000BEC2F119A9C37E6A43786F3BE3683889A2 +:10DF3000FDD2C7F59F3A883F4F24A292243C64B794 +:10DF4000795136C793D218C468F7C224ECA719FDDB +:10DF5000ECB9A5C80A4B4A3AF2C005B0F3B1E17377 +:10DF60006D88DF2576FF3F51DF12689B533A9DFA9B +:10DF7000107092BC2BE620CBFB10257D11DABFADD3 +:10DF80000EFFC4D4087FC0ABFC218DF4C344AF02A4 +:10DF9000AE74A67770A4D2F7DC98B7D55136311598 +:10DFA000F9F7D72E95F969C234C51B74F4975F63EE +:10DFB000DE84F37A29D16FE2C559B5D42E98E3E215 +:10DFC000BE6FD94DB524FFA58E6BBD5FC2EF875CD8 +:10DFD00066D647C51ACE8B63178D79E391C9C8FF02 +:10DFE000EE694B0C3E4B7C7DD65F9384FD327756B9 +:10DFF000A12A753470DFB56B1B8D97BFDEC072E54B +:10E0000049F2E859C48AEDA569383ED3A178C22403 +:10E010002AD33EA94DA371A7E221B4CDF48E3B557E +:10E0200044E32354CF4CEA9FD54B9DD89ED1664EF6 +:10E03000BD84F366E7A4786CF8DE99F08FAE10FF2C +:10E04000CECC49F224E81417049FAEA4BEC7EAA9B7 +:10E05000D6E91C8F9524D33ABAE23161BFFED6923D +:10E06000FF457014FB52405168DCA5911FFBE4C7CB +:10E070003F2975E2BCFAA10A90FC9C09E7FE91E0F9 +:10E080009FD99AA8272040F5166729BD576F519C44 +:10E090009BB8EF2BA1F9815166FD795CF7E49D7681 +:10E0A000B607E56FE5B35F74F2CEC16C17CADF9AAD +:10E0B000564CED4993F0DBCBDF2A9FC3E326089350 +:10E0C0005229BFEB1FF8BD1D253F294DC7F54F0C49 +:10E0D00073B16E413A956A117A0DE78342EFDF55CD +:10E0E000C1F35B94013F3A8FF3AFE4A7145A71FF79 +:10E0F00059E90951F3E70C7145F5E78D1858AA4520 +:10E10000D8B1F2FCACA8FEAD454AE98888F9BE69F1 +:10E110000951FD45A5AED21111F36F2B1F18D55F24 +:10E12000725B56547FA669B2D01F1BA1BC54C87D38 +:10E130007929FB9BD9AC870A9D62EE1B387E3F8E06 +:10E1400017B6097FAAD085FE14D2A5B4AD88FD808C +:10E15000367C8FC68BEC528F05A0DD3D91EC80FCA8 +:10E1600009E22FF68B6577663BFA056389AE68B7DF +:10E1700023E02F7544DBF1FA44E127CC017FAD0B9E +:10E18000E939A7751EFB5765E9D54561207C46BF77 +:10E190001F0B372AD19D77131FB66AAC37E70C895E +:10E1A000D9AFADD4C17E8CF4EFE6C8B78C7D21E049 +:10E1B0006D27FFC63887B1FFB5CE33479DC67EE1D8 +:10E1C000DF3AD7AC9C85A5A971E15FCFFE4C2C9CB2 +:10E1D00079A9324F81FE15FB85ADA9EC2FE24F7A6C +:10E1E0003C3FC1F07FCA51CFB922F59C43495F58EB +:10E1F000706D3D67AC7B2DFFCF58D7781FEA54DE9A +:10E20000DF78BFF7B9AEC47FBE1BE727C5799EAEE6 +:10E21000C47FFE5CF4FC199A5EE340793E0E8A27C7 +:10E2200040783FA96BE49A959CF5D6525BF6A15FC6 +:10E2300023B770F6F9402DB5533B8327AD78FEB96F +:10E2400039AA4EF907C32FEA1767A50A7FE4F855E4 +:10E25000DDAEE3787D40B753DC51FF886EA7F8AAA6 +:10E26000DE0B73288EF40E37ADA738C49B872DF6CE +:10E27000EF4D15FA7E857CDF680FA9FE15047F85BA +:10E28000ADE351F2492ABFE9B1105F1C277F2FBFD0 +:10E29000BFBF775C0B3A68BFE38F041DBE087D7E6D +:10E2A000BDFEDE2262A60CE253C517A94F4A6C09D7 +:10E2B000BE48FD51E67445F5C793FF83EFCD760F59 +:10E2C0008C7A6FAE9E15350FFDD81CF2876A2C90A4 +:10E2D000A3913E35257AC8CF8BC5E3EFE5F93D0E16 +:10E2E00027B951604ED7557F1CFBE42911F88B7D6F +:10E2F000BE3D55C47383C89EE33A2752756E6B5575 +:10E300009F70E6D07F267E88ED63ACBA8CD6C3952D +:10E31000DDC4771EBBE90ABAE0F0D2E3F3E76A682E +:10E32000FF3DE34DFF381CFBC71E5F21FA534DFB39 +:10E33000B2B1DFFAF87DA27FA369BCD983EC19B82A +:10E340007F6E29F90BE9BE7F27FA759B1D5B15D4FB +:10E35000039509A8D7B0D54C0A14A6F7C5C7DB2D7D +:10E36000685F91C0C86C5E17D2C06E15F17465C24B +:10E37000D020D913ADD8AB13DE2A130C7A77649270 +:10E380009D87DA0951719DDD82EFE1FB6536FF0B58 +:10E39000826FC2C93AEAA5870E960D20FE3891EA2F +:10E3A000643CE4ED9BEA267D85F0ED21FBFEFF0158 +:10E3B000BEE678F0D59AC53E9DF57925648FF38643 +:10E3C0002179943EFA156A3A3F4F0821EFB0BFEE2B +:10E3D0007553FEB1C665F190FF7E42F2EFF5B6359A +:10E3E000328FA1DA051FA929A6F57BB17D5BF2CF9B +:10E3F00019B92F6ABEA10B913FC0D933745181E87E +:10E40000137FA86A610FF9E13DFF90E4A1F8F98359 +:10E4100044813F18D2F3D18FF1F97B77E779B6F1D8 +:10E420007381A765C1EC9A0EEC8FB3066FA0FCE375 +:10E43000A134FF4784873BADC191CC878EF549B4A9 +:10E440008FE2058E538CF80FE33CDD32BC7F5C70AD +:10E45000EDFDC1467665E9648177637FC4B18DE8DF +:10E46000F1DE24F1DC8007E1E8263E30E0EA8507B2 +:10E470008638398F0022FFD425E38B2E5A8FECA7E4 +:10E48000EA1079DC3F9838FF5245C28AFD7DE74D9E +:10E490001C0F1A79E02210FB4D3EB54965E003F8E8 +:10E4A0003B51A2965E695CCBF1FD84762D26FEF68B +:10E4B000B23D9D2ADFBFA9D55FE2A0F6FDE8795302 +:10E4C000651C3F09822AC559933B62C61BE77F46FC +:10E4D000EB4FBD18FD3C294DDAC3413028324FB215 +:10E4E00041C64D974F66A7101F6B182BA8480F8B7E +:10E4F000AEC2A4D43E3DD3B011E759499FDAB82D3E +:10E5000038EBBC8FF669DC880C3F9AF4AA9B5B431E +:10E51000EE0ACEC2BD3036621F2917061E2FBF2F4E +:10E52000F038AE23E797D3B06F6E354350EFC3C3D7 +:10E5300014892F0CDF38FEBB7CD1C1F66B62DB6225 +:10E5400095E4D9EA36811E71BE043D11F4087D6C54 +:10E55000CF498DEAAB929EB509D17ECA78B94F9268 +:10E560006750D47A86BF62D0F350EAAC56F263C6E5 +:10E570003B56B1DF9232293B6AFDA293D1F82E04BB +:10E580009F97E263CF87C071C0C4B35A947F32298A +:10E59000BC83F963D287D1CFA79C8FEE97A6C9FC25 +:10E5A000562CDDAE854F18FBCB69E97F3F3E5DDE23 +:10E5B000687CA6CD89C667862F1A9F039645E36BB4 +:10E5C000A03F1A1F83578D891ABF617D61547FD880 +:10E5D0000FA744CDCF428319D91FBE755ED4FC91DD +:10E5E0003B1645F5473F7567D4FCDCE08AA8F1BCD3 +:10E5F000DD6BFE2EFA17843644CD27349BBE87FE92 +:10E600003736FE4BD47EFF53F4AF8DA1FF56D2E7D1 +:10E6100013885EA8370BFBEC19B925A43F5D4D6F3D +:10E620007C43799B40B1CEF9AAC03CF0D4E0D82F0E +:10E63000549F427A6E30A2DA847AA3D604ABC81E05 +:10E640003C6A32711ED390F317D3843FF2629AC8AA +:10E650007B19787B1AED22D94155EA4373FA8E244F +:10E66000F253549309DAC9FE691ED61FE71C10BE87 +:10E6700019F7550701E7C54A92272D9888FCA8BECF +:10E68000A972FCA90EF2838EF6A4E6E4CE53849F11 +:10E690002B0E9B4E7CABA6FA0364DFF09CA1E7A196 +:10E6A000BF9FF3DE465849F196D15FE65EBF99E61B +:10E6B0002FBB7BE6488A7F7B9FDFADAC2C8DA043D0 +:10E6C000E43917C5F1AB0EA409FB67D813C37EDC90 +:10E6D00069D56B3AD03E8C53857D40BB71200DF1DE +:10E6E000F181F28859F86901339D1FED2ADF27B8BF +:10E6F000D021DF806D4A9FDDD2BF43E6FA203BDAAE +:10E700006F7D9300A33844F7F03DE31D86FE5D95D1 +:10E71000CBF8BBEC889E7FF9FEE102AFF720F690C4 +:10E720000EE72CE23C06FC17A55EFE42EAE54ED25F +:10E73000C711F9EB55BB7626917F7E2E47F8E3C6CD +:10E74000F3DF493AFF2E4DE5F3AFDD9DB0FE7C04CB +:10E75000DE2A42AEA87E55E3C0F591F9CDB5C639A3 +:10E76000FC8A46E75827E5A8A2B523F94E607FFE4C +:10E77000C3345CB772D7957B0ED0FBA69E4C616705 +:10E7800003BCDFD2F780E382A57F8128BFB633CDFB +:10E79000CC7075A689386109364EE4BB25E803B80C +:10E7A000A87D63DA2CE23F7C1E56B0BFA015CCA436 +:10E7B000BF16FAB3CC84F433E079673F1EEDCF691E +:10E7C0003AEF731BF8F87EFBDD7B2A92D80F34D624 +:10E7D00033D64181203FEF3D57C09C49799FE90ADC +:10E7E000FB17B89F8D9EFBEE1EBC99ECB0B1DFBB52 +:10E7F000E0BFF40EF2C522F0F0BAC6FA40D73411E9 +:10E800007AF9034B2F1DED44BF0D6DA630E585361B +:10E810009CB3F2BD4A7775CFCB0F239C1FAFF9662F +:10E82000BF82707FB4BCE7BF0EE0F33B9E5241470E +:10E83000BEF1D9FD5A7A44BC79EEFE2B2C6FE8AFBD +:10E840003CFF2429A597AC1E92930FD6BC342A32E4 +:10E850005E484E9F99904EF73B93D2E2DE6FC4C65E +:10E86000A56B883F597E75F64B0DBE5C2DF972C3C2 +:10E870000BA3F9F986A4DEF388FEF32AE7C1363448 +:10E880005B39AFF18EE487352F7E333132CF578F2E +:10E890007CA95BA975724BF7A63AFA09FB4E5E1E7E +:10E8A000CB71ABEACFA2731EBEFA6932F5F7BDF9A0 +:10E8B0002D9F076EBB3EF8BB11799178AE4AEA797D +:10E8C00097F44AC501AB4EF9AC9203B927EEC27E6C +:10E8D000652BEA1F3CCF2557C7B1A7291E3BA800CF +:10E8E000E5B72AC309ACE42B1B9420E5C3D634EE6C +:10E8F000DD3218FB6BEA161611BB56250B7D5659F7 +:10E90000AF0437B11F3E87E95C2865A3E450EEBF32 +:10E91000E5E378D771B1FE858DB0F63CC69D5DF517 +:10E920005F5E2038D6355A39CF7621296C198CFB99 +:10E930005EDAAB84027A9FDC76B9441CB62AF4987E +:10E9400085F65DF5DCC211E436761D386D213DB9E2 +:10E95000AAE1B159F2799130FF41968BB5BB9595FB +:10E960009179ACD5E80E42A4FD42F80213FBEA40CF +:10E970004E49FA2C6B1A5E43E842BDB6FF6985F535 +:10E98000DA42E2970F0EEFF9DD6F68DF83FF3D9209 +:10E99000F15F747DF8075F80FD8B4AB90F5C3C63C3 +:10E9A000A1F8B2B2C17C21DEFD5263BAEF1EDACF0C +:10E9B000888F63FDEE2D1610F73FD9107C9EEC82F8 +:10E9C000A3C7B21CE1F9579A80F068CE1ECB0AECBF +:10E9D000DB48CEC85EB81DC17871F5BE748DF18478 +:10E9E000B1C4FA78F7A021395EA27758289F57E979 +:10E9F000EEB4105F57863F17F7FF8D9FCCF2C689A4 +:10EA0000B75F4E57A4333F274ADE37648C61B93075 +:10EA1000F7DAC3908DE5BE60450FD9A90D07913B8C +:10EA200014A2B7BF87E00EEC4FD0E97C25073E9FCC +:10EA3000D811B1CF1FA57CF4E6595EF964AC99F00A +:10EA4000B9EF93B15A52DFF3AE4CC7AA78799997D0 +:10EA5000D385DDDE9CECBB182D07099E30EE5BD91B +:10EA600064E77B1494832D2D45917270C7AA5DC411 +:10EA7000E74DAA0725022A1B17FAAB797E9287C8B1 +:10EA8000A336CE0C101FAA4E1FF327FC15F79B28A8 +:10EA9000EF8F50FFCD4DF73F4D72AC396065641E6E +:10EAA000A4D2D4F1AB1685E8BAC36BA2FD0A81F5F6 +:10EAB00096EAF075703C5594A953DC7B74C22C2007 +:10EAC0003CFDBC59E1BCAF39D5BF358BE87B5CE57B +:10EAD000F996A32F04E8BEBB6B1C14117CC6797F8A +:10EAE0003E2E0C2AAEB3B9003CB4EDE6834BDDC438 +:10EAF000BF3FCF38C67E86DD1302D22B35E83F50AC +:10EB0000DEC79E1F0AD33A0939BE2215F75993EE84 +:10EB100064BEB458FD1ECA273D20FB36CDB78AE03F +:10EB2000B3A5278AF87BC8F5E5F9BA48FECD746F1E +:10EB3000E9E77C4B9759F069D70DC07122D7FC4C9F +:10EB4000A6212FE3CD063BB8AD6A54D646DAD744AA +:10EB5000F0DBE879D7C1A51E82DF9C2DF93D33910A +:10EB6000E52276FF8F889FA9CEC0B4626B16E1992B +:10EB7000F0A6F79FF7A1E47B031FA0F973485E118D +:10EB8000546FBCFC923FBDF82CD17573AA2FC7956A +:10EB9000CFD7BCC2297627C6953B9CFF01C9B731A8 +:10EBA000BF95F089EF6FD1FC36C2EF51895FB3C5D5 +:10EBB000A73B59FE7D3AEDDF7BBE41F1CFF78D3C9F +:10EBC000DF966CFFF79EEFCFF27CE654E4375A2FC6 +:10EBD00019789E39391820FEAB4D82A24DF8F8A85D +:10EBE0006B969BE46ECB916F8692BCD72679DC4006 +:10EBF00079B1E69B9691DC6F197427F3FF172FE428 +:10EC000016AA11FB24A7177F45E73B2FCFB1C5E21A +:10EC1000CFA1737C2CCF699C6B49BAEF2FE911F916 +:10EC20002618927E5DFCB3D7B8D794719E47DA61FF +:10EC30008CF3388FD80D895C7FB657FAE11AF898B3 +:10EC40007FECE0D1D9BFF2C209AA2BA96931C13644 +:10EC50003A3E25B522EEFD925593110C7A6D18B20D +:10EC6000D335348D3B9FD839AF16E13E080155F8B6 +:10EC700069D1F90CF02A5E25328FF1DA9AEBCB6379 +:10EC80003CE3AF21798DCD634C0E9B965B52AE2356 +:10EC90009FF1DABCB8F98CD119D171514186CEC03F +:10ECA0008572047F86C28941913783F194BFEA2639 +:10ECB0005B85E39FE39959DE95AE1C9B0BEDE0135A +:10ECC0004F6CDB3A0DE57084C003F56B88C9F5F134 +:10ECD000EC07F5E6475E1BC37E38EA3D95F3024E2E +:10ECE000094B0C1D8BD07F1341A5272ABF123EF67E +:10ECF0006D32F1DB9E54FD2DA24F4F9BCA75280942 +:10ED00005A87C51547EE0E907F8076E09F33843E8C +:10ED1000B7358A7B4B9BEE653D99E0748E5323E4B7 +:10ED2000242F43D8A58A631F0CB5A02C5D329D4CBF +:10ED3000CEC7F5D7EDAF4FA634DEDA736F4FA4D24E +:10ED40009F3B35FF820C3CFF17CAAE5136F25BB7D2 +:10ED500006C7127E42E16CAECF2CD020A015F687FC +:10ED6000A7EA293C14BA04954FA5715BD0347E25DF +:10ED7000F15F55589C97F630A38ACC6D54B8DFD517 +:10ED800058934AEB55FDB67910E9AF9732849FF35B +:10ED9000E2D53CF1BE061ACDBF3FC325992A68A231 +:10EDA0007CE34B324FD97555E579C6FE058D335559 +:10EDB00027F2417E78C711CE8B365975A26FC27388 +:10EDC00020F0D194C07E68D5E1D94076AFDB051E36 +:10EDD00005C7F724F67C44FCD0D36CD5E93E37C197 +:10EDE000B9035271FD3DB21E2C1719B6DED1F7DC06 +:10EDF000D82FA1E997944324BEE07BE5046D074C2E +:10EE00007744E23B49D859C9577B12C326BA67E910 +:10EE100041DFEF5986AB0F4EE07D0D3873D90EEC14 +:10EE2000B1F45CF8713AC3E5243EC8050127348D7E +:10EE3000D649AF2638BD7C8E04A7EE0928FDE1AA8D +:10EE40001A8B8E20CACFA3A4CCA6F4C97755625FD3 +:10EE5000DF86B2B0271BA4FCB76E2B9D16D9478561 +:10EE600033A9EFFDFF78E2F8B6DA219CFF0BA84842 +:10EE70007F3BB649A9744E21572812DE8C42810788 +:10EE8000AA0BB4DBC478EF7CE473472ADB7F9EE7F0 +:10EE9000B13AEDF3B2585EF87ED1F00F1F52C217AF +:10EEA0006E46D2763EE64BC9C773759A8E3C5C8738 +:10EEB000F3FEB83C342A8CFD16ABFF79E2CF573F06 +:10EEC0005CB1BD80F4EF1EB3A79CF44F47E071F630 +:10EED000CB5F34EBDB22E40E86F46472DD61CC3E62 +:10EEE00055E7363D4EFE76F74145A7FBF46E73CFEE +:10EEF0005082BBB2E9330BD563561DFC84FDEBB2E7 +:10EF00004CFF5EDA6F526335D7CF4D861D5C3F876D +:10EF10007A91EB20436EA14F2E9F1DF56C75041D59 +:10EF2000DE93F2063DFE6164BF9AA4BC1EA6381CA7 +:10EF3000DBFD2D770CA7F5F7CBFC80F15E351C19B6 +:10EF40004C78DF04AF716B3CEF0E6A5CBF9CF7AE90 +:10EF5000ED5E6FC4FCD352FE4FCBFD5667FADF2047 +:10EF600078D7B67C6AA1D2C2AAF3A1A114F78634DD +:10EF70003DC519478FF4CA6F8C3C55693D169A5FA1 +:10EF8000751158AF20BD6B53907E2FBDDB386639AD +:10EF90003EDF8F3449213B8BF12AD9E3FD66DF60E8 +:10EFA0009A5FFDCED763498F1D2420F07F5F37AF76 +:10EFB0001D467843FE2F4E2439DB0BACD70C39CDE0 +:10EFC0002739C5F7F389FF8BA89FCB7A798FA57D69 +:10EFD0001ECBE57E13905C22FFB33C20FF3BC9DFD4 +:10EFE000CB77A23CF0FBA359CEF7B49BBCEC37A384 +:10EFF0005E1FC9FDE2C5D4DFD35EEA6439A73A8457 +:10F000004292D7F0115E270440D7F2450AF822FD5C +:10F01000FFBC8C64712F24F1393943D883508E9E04 +:10F02000E2C173D855354A3E22ECA5E84B7B5A9A8B +:10F03000F9976DBF98465226ED8453DA49FF78D68A +:10F04000FBFF286DD586D7A72CA8C3736E38A5F211 +:10F05000F86119F785259F1C91F91AB21B7A9AA8B5 +:10F060001FA6E713B04FF5E513BDEB4BC81C4D9A37 +:10F07000B3E328B5537CA11272DBA62D6B3F6A1651 +:10F08000629E47FCD770646E1ED5E3759FB3420243 +:10F0900082D8F06DCF472F221E1E3E8CF88F63A7BB +:10F0A000F038CC7FE87F0D0677FFF16E45EA91409E +:10F0B000D27CE2C7AE06B5AF8F8054226353DFFD2A +:10F0C000A47D7B006DE77F677A0767223ECF0CF057 +:10F0D00073DB7DFADB4C12CBFD67455CDF60F1E64C +:10F0E00011FF346463A81B874FAD9922EF536485E9 +:10F0F000B8F79C37670A39181580ED0AC7EBAA33B1 +:10F100008874BFD4A07A2DE82F5D84C092A9A46F23 +:10F11000645EF701903F5EFC45FA3C28BB0F90DF30 +:10F120008276EBC15FC4D61178D96F31F25800EB0B +:10F130004DC45F2B9B14F80FC4C5AA67A2E7AF9319 +:10F1400075F2AB1B771D1B8C745DF35CCC38F92D0D +:10F150007CFF11E278785D5D743DC3CD99D27F1953 +:10F160000EC3C97F41BE623D61D6A0D58A7CAC602A +:10F17000144322F69249E00BF52BCB67BE616F8AF0 +:10F18000855EEAB9045CA794BB3B7494EA81A6D47B +:10F190006579688F299A189FD29825EEA7B4A04A5E +:10F1A000750C93BCFE59EC7707BC67A9DE6495D457 +:10F1B00097E0C45FCAFBC8D3AF92FEDDEA606C9DE6 +:10F1C000A8C053959C37198235B4EFCADDA2DE6919 +:10F1D000EDEEE8F955124FEB9E3A7D8CD28515A1E4 +:10F1E000987189A7AAC6983A16B138DC9F29EFAD65 +:10F1F000647DFBF5D65BFCD12CFC8DB7E53AC6F8F7 +:10F20000E64C91EFADC463107DD705D520F1D12A2E +:10F2100025902CFC5E702CC7F3DD67B081ACCFBDB0 +:10F220005FE2E93EC93F7C7E7CBFE219F17DC5FD0E +:10F230003F8B867F0DF82C83F1F9830D3FB050DEB4 +:10F240003196DF56D599D9FF5D23F113CB5F6B7AE9 +:10F25000F9678785EC5B2C7F55FA956BC02FFCF620 +:10F26000FF5BF80D3AAF91CBAC3587393FB5F60966 +:10F27000C543F9AB6B9DABF73CF27C7FEFB99E3594 +:10F28000E83D06C630BDE7A45D17BD63FDEDBD9644 +:10F29000DEBC26E7052FB766733EDDE0ABD87566AA +:10F2A00049BF7DF653C27FBDD4586227FFA3FBA49C +:10F2B000C9A3E89CAF4C2EC0F38F6F5681FC91EE32 +:10F2C000A6E13B03087FE1A9A2C5945F1F7F0AED79 +:10F2D00013DD07B716FD5702DF077BD248EE67B68E +:10F2E0008D48FBBD83D761FBDE7DB2706739E9E9EC +:10F2F00093A545B4AE82E3549F5E28ED54F5C94210 +:10F300007B4784BDFA4DA6C8CF6F71FFFE518A1BA3 +:10F3100066EF357B283F32DBECDF9480F015BEA032 +:10F3200078AA71B763ED479EA47551BE28CD8AF3C4 +:10F33000FEE9088D57ED5118FEEEA6B2BC3D643FC4 +:10F3400083AA87EC6277D37DF90F921FD4FC40FE2D +:10F350007D11FB1D4B15FA66F60D66B6D79D83EC45 +:10F36000BF2EA7BCA87717EB8DCE43FB2CFC7DC32B +:10F370001E05DC78CE63EEA32F131E3A0F9CB65009 +:10F380001050D270DAD211477F1BED250CF3C29CCE +:10F39000AFDD61E1FACDFD7FB0D0792B9FFB84F327 +:10F3A0006F6B287E203FEF1995BF773ADAFCAA856C +:10F3B000F8B4B24E81015991E3661E27FD4AFDCF94 +:10F3C000EA849E36F87F85E47783FF0D795821F52E +:10F3D000DA7D5BE3F3BBA1FF1E04EF9641B8DE03C9 +:10F3E00075CBB90EE9811DD1F35752FC7A23CD17A5 +:10F3F000FCBEF2A9E8F1D5BD7C1E60FD1FAB47BF86 +:10F4000033F47F2EE4129F5F0EAF18A6A13C7D7DE2 +:10F410007ACD308893AF3C29FD06C36E5F0E9BD832 +:10F42000EEC5CEEB6ABC62217B5BD5FA27F673672B +:10F43000357DC9F4286F6AE17AD95BC0BF8EF07957 +:10F440004B93DD49FE767987D003F39AACC1A04295 +:10F45000E3A15AA273F761F1BD49E090C2FE1648DC +:10F46000BDB852E275A5C4E34A8CE306537D8C8C8B +:10F47000E32B65BCBE3A67D7312A29A994E3EBDABE +:10F480008E26131EE781D05BF342426F19F431ECF4 +:10F4900050ACBE400B770FD1776D9395EBD6E74B11 +:10F4A000BD35BF0EF596D25F7F740FB48BFCF17E35 +:10F4B0000177ACDDAD6C889EEF1A20FCD8CBD27FF3 +:10F4C0002E1C104D97F21EB0537E7F9EAE7A82FCAA +:10F4D00056BB46FBB78E457EC3F55BF5E129F1EAE5 +:10F4E000B58CF64D191718FD059467C3F921E70E81 +:10F4F0004764DCFF9F03847FB366B21A20BA46C418 +:10F50000490B0AB3E2C6497309F43786DCF7B371D5 +:10F5100091719277D728E2B77F75EF2CA7BAA6AA88 +:10F520003AA12FBA26E1BA29E4F703FBD15575D6E3 +:10F5300020C53355C82FFC7D1AF109C96393524683 +:10F540007C8271C6EDB4FE42BAEAC4F32F6C44FB70 +:10F550008ECB2F2CFD92F9AB6D843837E26D40BC19 +:10F56000B8C388372AAF0ABFD6785EA97570DC5158 +:10F57000D924EAB51B8E7C33340BE1ED6EFEF3D05B +:10F58000E5544F3E40D8E786E2D0A75457F4F51E25 +:10F590005B5CFFB557FF2BB52C0F95E68E4CF66BD9 +:10F5A0000EA21F7913EAD1B7BFE038A5E148C2BD6A +:10F5B00094CFEB5AE11FE6FC1E3A55C326F683377B +:10F5C000412DB7E41F45FA8D2B9DA24EE941693FBD +:10F5D000A9FF08F2F583387746617FF937F449854A +:10F5E000E4EBD510D83255E9AF072AA4DCACCDDF67 +:10F5F000B585AEF663FDA70A294F1831B0BD8CF56D +:10F600009FFE33865FABDF4E64FFB8BB4D7552AED5 +:10F6100019F1FBAB41E427625C901D275FFB85E499 +:10F62000CF4E797F5C3D4965FC99268BD6F0B710AB +:10F630008FCC37DDA71D41B26F79875FCD263E584D +:10F64000BB3BFADE89E8E8E7BAB1A0C84785EC7CA5 +:10F6500017658CBF74F8D531C46FD56F7F3B4AD026 +:10F66000E79B5196F46BC367B48A22E2669322E269 +:10F67000E6FD5A4732C56B5507555F643DBF41EF04 +:10F6800097A53C8126F203F50374E6ABEA26C11F79 +:10F69000A666D1E2FE4B447EC8CCFBF71B2F46BECC +:10F6A000F91E7B060417F24095B987F9AFEAB489D1 +:10F6B000E1A93A7D397344C47B015A7700E9BFEA76 +:10F6C00075C0FAC40EA46FE7D3F791D89FFF7E02EE +:10F6D000FB61C7B2B7978BFB2F15487F3DFCF69AAD +:10F6E000D191F660E200712F0E840737793FBF1089 +:10F6F000FB4B3C6C824532BF20F879AF8C9B302E9F +:10F700007B73409CB8EC7AFDE9EA662B50FEB9EABF +:10F71000032BD7197DDDBC92E37EB8EA1F4DFA06B4 +:10F72000FCFE1BA97DF8F0CAD1F4FCEBC3AB6FE47F +:10F730007CA9B2292ACF1120F8DCE45F7DF5EE5DCB +:10F74000E47FB669EC9F14B69D7D97EE69F7359816 +:10F75000F9DBD18AFD13760692C8AF2A9C4FDF11E0 +:10F76000ED6BD598FFD0DF32FC2B3BFB57A78AD837 +:10F77000BFC2757C416E8B4E94D3BAA78A8B689AB0 +:10F7800082E3A4D7C6937FE5E8F3B70C783E93F8FD +:10F79000EC6E49E0BC8B02D982CF604414DCEB1ADA +:10F7A0005E67FF645DA31AF5FD88F1DE5F06887B66 +:10F7B00087EF0C3E0B295EE6A3BDA25DD7B82F9361 +:10F7C000CEB1D61C623EA9AE338BF13DA205BA077D +:10F7D0009AC01F4107083F27E811D2659E2538844B +:10F7E000FCFABDBDF78AB22E2428EAF56A5A87F3DF +:10F7F000774C975BF7A5C7B34327E99E071DBEE388 +:10F8000059221E8A1DFFAD5BE4418E9F13FAF1F869 +:10F810004CFFE8787A3200C5225FA048FA3588EFBD +:10F82000ED63E735D37A78FEDD4302C7898F3BF776 +:10F8300026F0FD63A74BE4754BEADB34FA1E666DD8 +:10F84000833281ECD2DA9CF7F87B19EC17919E5C3D +:10F850001B3EC8F7AF15757B6779E3C0B1DD2DECB2 +:10F86000C33CF99D72ECF87C397E063C19329EDB74 +:10F870004EF73E67CACD4EF1DD9BF8EEF556A9D79F +:10F8800017DF62663FEA0CE866717F22EE391648A0 +:10F89000BD7DABD4F7B1DF631BFAFD76B9CEC2678D +:10F8A0006033DD73C47E9F7DBBF40F178197D7EF64 +:10F8B000F75DBDF41363FFFE42895BEAF551308AC0 +:10F8C000F47A08ED0DD75BE426B0DD9E5F3032AEF2 +:10F8D000DF41DFA9EBF23B756A0DFA57E7BEC7F6C9 +:10F8E000F078CBB997F9FB867309901DE79EADCFF1 +:10F8F0001E1A7AE436417779EF51E114301AF4BFD9 +:10F9000084115A647ECDA0FF83920EFFC7754539DE +:10F91000A045E6630EA9FE07DD195447DDC9FE3890 +:10F920009E80ED219E6BA83CD7506B849DBB3470AC +:10F93000795C3EEE3B5F6A40D893746E5B72ADECCF +:10F9400037568414FEEEB0220CA27F9BC2F9CA5136 +:10F950000D2D5CBFB1A454F178855A3C4BF0197C55 +:10F96000B4C026FC03835F7AF125F988C6C95FB865 +:10F9700055FA0BB1FC341ADA67D1FA4BBD8A87EA23 +:10F9800036AFC947CBC6BD4EE1EEB5F808F9D24C4B +:10F990007A31969F5E73FB1F25FC75B75F5E5280C0 +:10F9A000EB1FCFFD6C28F14FE535E4E84549BFDD9D +:10F9B0008EC071AE63A9977504F5B98D1D849756F5 +:10F9C00060BFB2D3D5BE6583F0B7B98EA0229CC00C +:10F9D000F5A5154D76FE6EADA2A13A710CE9E326B0 +:10F9E000D563C77E79C3E952CA239417893A972A07 +:10F9F000BBA8BBABB28BBABBB9E9FEE7DC13F8EF2F +:10FA00000344D711583A7EB5E17BF83E56DF359373 +:10FA10000F37E17F4E0F354BFC6C68BB923986C4C3 +:10FA200034DD7F88E0EE7EFD450B7D8A5135E6D5DD +:10FA3000595482D6ECD679DE2D752DB5945636E024 +:10FA4000B7BB9D42EF9A8343D86FCDBFBE7A9BEA86 +:10FA5000836F8C25FBD5D5D236D612C1EF9D1B50B6 +:10FA60006FC7A1633598A41C6BDC2ACA22E9470939 +:10FA7000B9AE6A3E9A49F98B4E92E77C6ADF491E1D +:10FA8000816DC5DE33C923C99FD92F5A63BD4B4D44 +:10FA90002ACF03AD63D4ED4991F06D66F82E85C48D +:10FAA0003A001DA31617448ED7FCBFD60717853E14 +:10FAB000E888D207069E4216E0EF880387AD5CA770 +:10FAC00040F73FAE083A6A0305FD6EC2608AE476ED +:10FAD00032DD7B0F27974F83BBA9AF41584BA5FB66 +:10FAE000E9B02AEAFB86B0BE9F28F7BF490BB750A2 +:10FAF0003DF064795F3A05DA79DE0CE8E1D60B4E29 +:10FB0000FE0EBA183CDC4EB285E7535A2B3F14E286 +:10FB1000EF7BC2999AEB824D7E6F1D87DE7D78D395 +:10FB2000E082810F95EED5443D53EC796E1828FCA8 +:10FB3000BC9BBC420F914B41F5C09320C4F7F9D355 +:10FB4000A143DEEBC73FC7548C0BE91E6F3ABA31B5 +:10FB5000898C8F20CF9F46E751E39DA7633E931981 +:10FB60004A9D049F12CE347D67BFFE7374533528BF +:10FB7000E5BDEFEBE9FA7151DF3DA8A7E98DF7A9E3 +:10FB80007E59F17AB9BED943DF8D53FC13D63A7B47 +:10FB9000F55936C098812B72064EE8FB6E04FCC006 +:10FBA0007524B1DF8D447C27021723FE2E9251E786 +:10FBB000BB3BB848A73A9165E936FE7B3B85B6A1C9 +:10FBC000E329AF7928CD9F333083EA7DEB46F2629B +:10FBD0005A7002FBB992BFECE09D447850BCC6F766 +:10FBE0002BC07CD3FBF70B3281BF27B25BC5773EBE +:10FBF000DB911F6DA92C053AD55FC323253AF9D3B4 +:10FC00005B5C360F7D476C25B8ED7D70D7D8441D01 +:10FC1000488D4DD47918F572B178ADB119794E8F00 +:10FC20008DFDF198EF907E62F3DF42787A28A998F3 +:10FC3000FF0E53DE2BD3DC5C0F25BF7FAA4930F0CB +:10FC4000506CE3E77DF594EC67D6523D37C259938B +:10FC5000015CFF783469540AD565D5B4897AEE9A87 +:10FC60008C00EB77B35F617D5FD35AD24AF6E2B284 +:10FC7000C3C275DD352E51071FC880D0F37A343DDD +:10FC8000A619F4A0FB4B598F64D0655C3A94D07BE5 +:10FC9000E3C2DE91849342DBCB37D0FDC2B87074EF +:10FCA0007D19D26935D1A9F73B1ECDC9F51E067D58 +:10FCB000907198D99D92EE06BD9CC6DF23F06A51E3 +:10FCC0007F8FC0A0E3F644412F3355E00CE77775F2 +:10FCD0005A37964EFF1BE114C1BAB04B000000002A +:10FCE00000000000000000001F8B08000000000062 +:10FCF00000FFCB936560F8518FC0F9D20C0CDEBCCD +:10FD0000A862B4C40C5C0C0C41405C0EC41A407B6D +:10FD10006F01E9DB401CCECDC01001C4FB81F81F90 +:10FD200010FF07620D20D604E25F407945A81B5BF7 +:10FD3000981818DA80B80388BB805887918141975A +:10FD40009178FB93841918DE8923F87A120C0CCD74 +:10FD500052F4F3FF60C33156F4B5EF29D03E4E178D +:10FD6000043FC71998245C50D570BBE03783074D1A +:10FD70009E178DCF87477F9E212ABF5C0B953F4DF5 +:10FD80008781E123929A0A2DFC6E41C78A460C0CAA +:10FD90004A46C4ABDF608CCA0F3081D000F9ADB1E8 +:10FDA00009A803000000000000000000000000009F +:10FDB0001F8B08000000000000FFE57D097C54D582 +:10FDC000F5F07DF3969949662693900D0871028AA5 +:10FDD000A88013086940B4C322A2228E5BC50D26F9 +:10FDE00002D93710FDF0AFFD3210362DD6D0824645 +:10FDF0008B74C0A0C182040D1824E0002EF82FD50A +:10FE0000D8BF7B5B0C4AC31692801B7EB5E57FCEC4 +:10FE1000B9F725EF4D26806DBF5FFBFDBF69F1E6A9 +:10FE2000BC7BDF5DCE76CF3DF7DCFB14DB2896F89C +:10FE300063C6CEE00FD2AB2C8CB151DDE96CDBA0F8 +:10FE4000A187FA74E7FF5965D3EA87421EABD06EEB +:10FE50001ED6FD9CB185547E408C6B38BB1CD3F400 +:10FE6000101B0E8F6DC91696CCD87D6E46BF01094A +:10FE7000BE742991B1CE1556F7BA0C78AE7A5C08EB +:10FE8000DFF7C8207750C2F73CC95216E43FA2BA48 +:10FE9000D701CCBE3F23B36CC666DAE06F0FFCC35C +:10FEA0007AA0BE7CAC6C1063EA699905A07FEA7702 +:10FEB00012A5033436C3EF0078F92D6CDCD0EEFECA +:10FEC000B913FDEC7380B7E8F9897E5BC0907F09B8 +:10FED00093A8FFECFB4AAA5F6F6FF1F25B6C3E07E1 +:10FEE0003616948DCF3B967FE9C2E78B9B6EA17A45 +:10FEF00018532CD8CF72B7C84FFC5C6396EEFABB90 +:10FF0000F114A27674D8D304EDFE8831E9B5BFB6FA +:10FF100032C043D556D56305BC4CD8AA867F0C7039 +:10FF2000E95A2984B065979D31C04BFB6A0E879DC5 +:10FF30009A0FCB9FA80518AA28B736FFFC0AC4DB86 +:10FF40005699ADA366FC84F7561BC73B6BE4709EC5 +:10FF50009D83A56B774FC7F70B1AADCC0EF5956E49 +:10FF6000CF9F7A05C0F9FB5486454AD72FD0FA01B6 +:10FF70005C1892EA11EE18CFA8FDE03639B41ECA1B +:10FF800077B89A936F83F11FABB431CFC5D06F6749 +:10FF900073F2AD8087A2D09649F85ED146C98B2C0A +:10FFA0003461EBFA37FBC27BA51B24AF15F0525C22 +:10FFB00017CB3C43781FCEC0BFD60639FC63C89F21 +:10FFC0000BE3641948D7EA494CC6F657681E6737F1 +:10FFD0009E8E550E611E6B375CBA01DA81F7CA5EE0 +:10FFE00094BC38C4320B0B205FB66FB74F7BD68101 +:10FFF000E35BA00D76E2B8966A582E3F94BBCDEE37 +:020000022000DC +:10000000C1FEADD526417ED1EAB55A9E81FEC575A9 +:1000100097318FCDD0AF9A412946FE884C8F019BF6 +:1000200018FB53C498AF1EF94409693719E4A29F1D +:10003000144FF42EAE934DF50326194B82FF7E002C +:100040007F02BE823B9D84579D6E73051FE9743B02 +:1000500025E487299DD9C6FAF5F4E74807E84F75E6 +:10006000A59BD25F54A652BAB2D243F47902F107EB +:10007000E972D16FD758364E81765D3EE646314BF8 +:1000800098E21BA7029CE0E770F2DD01C97396F1CC +:10009000EBE9136A20176572159BE453FA02AC056D +:1000A000E6302FB4AFDCE89B389AB1D759E0711C29 +:1000B000FF222950807465AC3ED50F745922811EF1 +:1000C000017C2DC541021E96F4057E063A3D714F16 +:1000D000F6B3B224C69A8870DE738F66503D3554ED +:1000E0008F0AF50C3A773DC9D3734CF5244F2FD0C6 +:1000F000EB594BF5D8CFAF9E27A68F31F7677A9192 +:100100005ECF0B586E91F3FCC6953C63ACB93F33A0 +:100110004AA89E94BBBD2C00E5659D7F58B34F86D1 +:100120007CC7C6F8118F32231F8DDF86F53941AAAF +:100130008C7C1497136392A7785F8209EE33B99F82 +:10014000A97C927FA0293F65DAA5117CE970B75E92 +:100150002660E854385EA3FE6AFD34D23BE3FAD948 +:10016000087EA09F83F4CE03630217BBA1DFD8579C +:1001700006F47F400B5CEE8EC237302E89A562EA12 +:10018000B1601A99BF54E5781BDFFFFBC107E1FDA1 +:10019000724BE7E07880FF4B1AF7218EFB8FA84C5B +:1001A000816E3132ABC072315646FA6F6946F6B392 +:1001B00041035E970D007E91BAEB5DA60652911F3A +:1001C0005B821541E4CF253041B07E8C1D6415E182 +:1001D000E085F0FE80BC54C4BF5503FD616C5F83B5 +:1001E000F68752FBADD87E5B2FED5B07E698DAB75A +:1001F000A51798DAB769D03EC8476770BE681FF088 +:100200003786B1936C3EB56F4D2FA0F6976AACC0A0 +:10021000D47E4C57FBDF60BBDF63FB4951C63F70A8 +:100220008C79FCE945E6F16B7CFC6C4150B41F43D2 +:10023000E397A4201F7F7A111FBF95D7DBD5BEABF4 +:100240000BFF9A04ED3AA45EC63F68AC79FC1794A4 +:1002500098C76FE5EDBB172C13ED3BA8FD78691926 +:100260001FFF0525D4BE660D78918FB4FE31152190 +:100270009C4FD34080524807FA281D92C018E8933B +:10028000DFB2818487076238DF7D1303FCE6E8D69E +:10029000A72C041208F37099E0E9E28DE3343E3FA5 +:1002A00007695E9F2DBA3AAB51A6F98CADB4862E84 +:1002B00082FEB637CA418467ADBC3224D37C0A764D +:1002C00002BEA7B0303EFFF3AA61EB8CE38A4C6715 +:1002D00057ABAD2D06B9EAD2EFE3D9900AE85F0536 +:1002E00032C1A86EB815F434033DFC39E8634C0FF5 +:1002F000ABDC2E39047A9C5D6C949B05DC2E09B234 +:10030000F78740FF7F22FADFAA707CB7CE9342883E +:10031000FF6F56CCD1509FCDAE8E05A477F7A35C6E +:10032000D0A973BB3544F6144C07889FDB491419D8 +:10033000FBD3AE1BDE945C303FD6F431BD77370B78 +:100340002D4E85F23397E70E70C3F8EF9A661D21A4 +:10035000E3FCC47CFD2D24C7ACBF2587B1690D2B00 +:10036000D4FE00DC3E4DFDBCC5F0FE1D01337C57C4 +:1003700081196E5743AA05ED994289AD857AEFA997 +:1003800030E7EBED4C9612385D457B3F011CF48560 +:1003900047F7603A021FBB89AED3DDFC5DBD3FE588 +:1003A0000FA92C4CF3714B1223FA2751B9809B8F64 +:1003B0003BB2BFD3559BCF0FFD99FEA04CF88CEC00 +:1003C0007FCBAE589F05ECD9969A2F5564C1C8F1E2 +:1003D00044F67FC6FCC8F1B8359C1F728391CF39B3 +:1003E0009F44F25379E3B85F1E32F05369FDB5BF05 +:1003F0003C6478AFB8EE26135C18BAC3543EBF26EF +:10040000D7943FBBBAD0943F73D91C139C1B7CD0AC +:10041000547EC6FC05A6FC7B2A1E31E5DF55B0C222 +:1004200004DF1178CA54FEF6696B4DF9965D97DCCE +:10043000887254F581CC70DEF8DAD1FA73B437BF24 +:1004400076285EA4C711B057500E8E81BD82697B9D +:10045000E348B2AB410FE63130A1564BFB83CBC62C +:10046000A25E66A43F43D2EF83C134C69E973C840C +:100470003FB94663616061892574F171A76CC86FEB +:1004800039477E0D08FAC89EF9724BF4E7E5EB7226 +:100490002F40BDD39B3E805F7F9CE73A843D1099FF +:1004A0005F2231BFF1B9BE7EBA5CE27ABE44AC5382 +:1004B0004A5EEA3B9EB9100E0FAE385B7BF5805466 +:1004C000D49368FD27213F801418E8515C37C82475 +:1004D000DF6DBB65EA5719EA04D0AB99CCBF574230 +:1004E0003D13DE9B7ECB30EC87EF75D4FBAC3189BE +:1004F000E6F5B6CAC9BF3CA4227DFC941EA99C4661 +:10050000696B6580D2439505947E5E5941694BE5E0 +:100510007C4A0F540629FD63E5324A3FADACA6F490 +:10052000E3CA1A4A3FAC0C51DA5EE9A35497872E0E +:10053000FDEB17F6B058B7C0036E0F8BB12C82B22B +:10054000CD24E7DE5494F3538E6F06A3BD7FEA6398 +:1005500060A28CDEF115C96FBDD3D147F64A5E08A3 +:1005600098A74FCF7C7B0CA793DDC22633D0478F53 +:100570005CF49CF7DEA1042BC832C0A9DE9B9C5121 +:10058000EA85B90FE9752E3A315FE7705C67B73ECF +:10059000FD976CACF77269209F87F7CA340FB3F0F0 +:1005A000B35EA4D70FC59BF4DA9FD25BA0DC892E83 +:1005B000FC35A73348E7486EAAFF5483952988C7BE +:1005C000A6D8102E8D4FED7BD685F2383755AE3E2E +:1005D00034B2777C95D667543B0CE3296F34C3A7BC +:1005E000AAA5C9DC7FE089BB7518F295BBFAD04596 +:1005F00048FF544AF57AE6A66AD4CEB1BA41717C76 +:10060000FE0EF17970633CF12BAC3BA9FC3FBB3F84 +:10061000BDD5A3F787B106F6850DF501E40D3AF7D0 +:10062000FAA807DD95AF343FD2AB49FD06ED85183A +:10063000F8776620D6AB10ACD75B5E2F07AD97E39B +:10064000F38DA6F6E03D8FBEA6C7F77AE75B85B5CA +:10065000EAE3047D75A5F0E714D7D9ABCDF34ABC26 +:10066000092E6FEC5B6D9A67F00F907F562129C8B9 +:100670003F25829B3A14C73209FA976AF150BDE5CB +:10068000122F576A6BD1021E62C766B433EECDD10A +:10069000F9CF73FB1F40DF1FFDADCA1EC57CE1D73C +:1006A00051F56CB06F2DE8E711D0BD0DC55350EF7B +:1006B0001DDD763DD927B398DF858BA402569D8D2D +:1006C00076CE0966998CFC7F82FDDE35D2B0DEC81D +:1006D000B768D49F99CBCCF32CD8672638BFC60C0B +:1006E000E7B19B9391DFF356AA30B7A05C9AF36F02 +:1006F000B7B849BEF259C5125AEF083FD8BD6EA629 +:10070000F407B92F7DE599ECDCA1E887E0FA5BF707 +:100710000F1426703BA52831A4F920FF8B86913F4A +:10072000B982E1FBA125A8A7824EE65DCF7AD2EF80 +:1007300087F63FB2BFFA7CD2C34F21FA21D749BE18 +:10074000509475DAC31649D85B414A978B71EB76A2 +:100750006B4D045C1B01D747C07F37BF253213BFE9 +:10076000A55A02359624CE5F682F484AA716F84747 +:10077000EA4FED517FED3FB5FE34A83FDB547FFDDE +:100780003FB5FE0B7BF4BF295AFDA5AF6CDA16040A +:100790007D53B479958BC13C7454A94EF602DD4B60 +:1007A000D62F76211F1C51822EE4E7A321797234C3 +:1007B0007EF8D222FCA2CCE790705D857F42FDC717 +:1007C0005EF8D954B4E7BE59AFBA69BD54670D5B42 +:1007D000414ECB1A0AA7A0DF17E0831C5E7A52466F +:1007E000B8D1CC9F45CFAF4A46FF1E708A584F8480 +:1007F000C95E2AABFDF3249C87CA5927C959E47BFB +:10080000D8FEE904D28FB95A5CCF7CE827D9F9E544 +:10081000022FE50D3F3B29BB30BDF630EA13B04C4B +:10082000C80E8F7CAF40D841872CCEC4565842B1F9 +:100830001FB11FA1DED4F1C242DC0EAADAF0E4F04F +:1008400083D0AFB6DADFBA2403BE74793B553FF3E9 +:10085000D7AF7A7AD7CBED62BDD7FD5E88DEF334B1 +:100860000AFBAD89A7256AD885F671C95AD51B84BC +:10087000C7259B9E7DEE695CAF7E62F55E04F51731 +:100880006F7AE3C33100176F5113A7F06138A4E406 +:100890006EFA94C3BFF923BAE951F4F21B9A6718B0 +:1008A0007FFE7042375D8AB7ECD6D8B09EF898507C +:1008B000BF5B6B7144A14FFDC1496867556DF85628 +:1008C000C375E5D15D124BC98882CFB56F90BD80ED +:1008D00078227A0A7A75D12FA27C39D005F57A244C +:1008E000BD22CBBD81FA6514AF17FD93C0DF2FBECB +:1008F0008A7EEC4FAD5EC443C18BF7B9703C8795DF +:100900000ACEE7CF2C4E463F7D811A4C7653CA9FC4 +:1009100017ACB99FF82FFFBDFB93F9FAD0D7D74298 +:100920007355B02F8E73F6EADB689C792C407C58A7 +:10093000F08CEC0F41FAB5C2266F892227C5329799 +:1009400093C3EB80B830CEC3B84E41BFEEEFE5D0D5 +:100950007AF28FCC61A80FEED7FDF16C2EC15F8BC0 +:10096000FD8471B2455FE7DA4CFC5BBBB419E974F6 +:100970006C802F05FD6AE54C090A7C4867A05EF98A +:10098000BDAB53389D9847C916EF815D30019F6319 +:10099000F966D5671F6E7A8F9DC9E86E7F9E681FC6 +:1009A000FA1D83F3F9E16456501F657C35B2AE073A +:1009B000605E37F09941DEB9FCD73EC2E55D97FF36 +:1009C000D04D9331FFABF7B91CE17B385F42BFC21A +:1009D0002994BFFB5689F4839585A3C979AD2AE490 +:1009E000DC9C1FC92FD07F458A33F00DB69340742D +:1009F00020BF5ADE4A78DFA857B15D57CF7A7539E4 +:100A0000CE17FA204F067D7059B73E60ABB91EE88D +:100A1000DDEE0AF2F59B1A7AEE69945F90D7A00793 +:100A2000E557F5E3F88F6FDCFBE19D20B7C7EB7569 +:100A3000B935EBD548B92D7869BD847C1A29B7C77B +:100A40000BC04A8926B7F03CAADC16B4FC4BF4AACA +:100A50008EC7C765B35ED5F5646FF88CD49397CA1B +:100A60009EA87A127EEFB3EC9EFCA8F3A1CE7F4540 +:100A7000BF29BD80FC093A9FEA7CD8C5A73A1FF67A +:100A8000F0CF98F018997F3BF2040CC1BF5D257F31 +:100A9000624913DF8F83F7DEEC9F45F8F2D134C74C +:100AA000AADFEC9F68844311707D44795F04EC8F6A +:100AB000281F88802B4CE54B1AF76A8CF8206C2A8B +:100AC000679DFF2BF6459475AC3E0F95379CD482FD +:100AD000C81F699D1AEA3F752198A8E83FDC299351 +:100AE000FFB00370BC04DAE9D898110A821E596C71 +:100AF000E7EBCD0E77A72B01D2C5F11CEE4CD296B9 +:100B0000A01ED49F77DAB91FA4C3DFE98A37F83172 +:100B10000E36C9A4C75B426C72343F09CC3484DF03 +:100B200016D65B3EF78F76E0BE33B687FBCE40CF5E +:100B3000AB6547FA7C5CBF56CB5E6023366BC1ED7C +:100B40002E74A177340DBA711A3C9FFDB6CCB76DE7 +:100B5000823EA5AF61DD7184059F182BE17EDE72B8 +:100B6000E29F994D7C1D326B7974792812EFE5393B +:100B7000E669A87761FDF0B9D10FACD753B03AE27E +:100B800079D3F5426EAA693D58546BCE0F88F5D4DF +:100B900037BAFEC96499A47F70A184EB7AA1B7AF7C +:100BA0009687DE380DE8D3B14F66B8BF7AAA4926DA +:100BB000FA9CDAC8F753593089E4AF8C7592BED4E9 +:100BC000F1D686F27571EF7AAC6DEB9FB21F423EA3 +:100BD000DAF687E1BF82B46DDB27837720FCCA4752 +:100BE000E97F603DCB4FD865273F73C72E27F17F44 +:100BF000C7CEDFA53F84F0762BF9F73A767D3B1C14 +:100C0000F9B163A1B500F560C700BE7EAADAF9EDBF +:100C1000F0169A7F17111D33148DE87DAAE92F076E +:100C2000302EE054138C0AED8B5DB1245FE5AFDA12 +:100C3000C91FD1B1F3DBEC80E39F379E32B1FFD304 +:100C4000E164D35EC2FEC573BF79F98ED1CF2EC0E9 +:100C5000FDF186DDDA4CC89FF0DA5F87A37EED7880 +:100C600089DB4DED6ACB1ADCDF18BA485EA802BDFD +:100C7000DA51C8FA31B66FD1C4F128473DF1F257C5 +:100C8000F2B39C2F3E26287C3DFBEF8F0FC9C7F5A2 +:100C90009F33649370DCDF1DF803EA895D56E24BF5 +:100CA0007DBCC7EB17903D73AE71DFFB3F6EDC522E +:100CB000F87CC6BDE0DF9CFFAD8A87FA1729073DA7 +:100CC000F97CE703046F727AA9BFE7C9EF6BFFA74E +:100CD000D1FD25A0BBEBDCE30EFF3F4BF7B7A70B25 +:100CE000BABB313EA0FCB5BF52FF7EA89E6BF93760 +:100CF000A77B6FE3D7EDFDB72C9EF733A1FC6456BD +:100D0000ED40C3E2DAD23D6F6742EE5B697BE3B14F +:100D1000BFE323F67BF4345EE5FEB6F1B8EF03EDF6 +:100D2000B27849AC17F93AABBFB02FFACFCB233B1F +:100D3000A47FDA63644F30C5B312F72BDF4A9FE913 +:100D4000A5D80B36E2E300C2EE2B056C5E6FFE4ABF +:100D5000623EDC4AED9F7EFD3EB473D3D264B28323 +:100D60002125FBF775D764FEBC4433AD87AEF598FB +:100D7000D7479312CDEBA889A2BEAB19EFFFD50ED2 +:100D80002914023C8C1FF0CB44F4A78EBF48651297 +:100D9000C093586011AE3B263ACCF59DC07D6C8364 +:100DA000BFF1EFC5E3C42E3C0E5CE9473C0E90C991 +:100DB000AF7A4E3C62BF096F99218CC7618A97E375 +:100DC00031A1D44B7E6AB11EC76EA21DA3389634E2 +:100DD000A33C2BB89EE678A075B8BE9EEE0DDF4C06 +:100DE000ACCF15D1A48E7F254DF6D9CDF5D1FA5CC7 +:100DF000A7CB0FA5874EC77F942EC9AA992E698EBF +:100E0000390ACAEB645C3F8CC4F2991C4E0B2AB4BD +:100E1000DF24D60FD778E628418027A4652A48AF7B +:100E20007CDBF6228C1FB57925EAC7C56D169A1FA3 +:100E30006C5912E17D488D42F07B16F728A4F7D457 +:100E40002B5E39FE20433FBB4FE306BA9FEF977CF2 +:100E50007FE6CCD86CF4C7F01FC67FDE00EBB75935 +:100E6000AB593806F0345B61C1B804F4934BEC73B2 +:100E7000939FDC0CE3EFAAE4EE7ACE55BE37BDF2C9 +:100E8000CF4E5F013DF6F9458C6DC7946F8A28C639 +:100E9000F5F68F9A38BECAF7B3D0401E8721FB0DF6 +:100EA000FB8A2FABDC3FF3CA1F5F1A89EBDC711D95 +:100EB00043E3B87ECDE271A962BD708A79E2BC0ECF +:100EC000D4AF83E268BF749FEC8C16E7B841ACBF27 +:100ED0007F83F1289076D4B26A19D757AC93FCBEC1 +:100EE000C15A1B5B1F251E668D6A117E224137F891 +:100EF000C9D9B87FC3DB9F0DAFC619E9D636E5A8BF +:100F000032BC271DF0F7B961FFEA1FC52FAEF711FC +:100F1000BF1BEC2D93FC51F447BDC0DFD43DDF91E6 +:100F20009FF4D2A6B516E4DF4B6B2DA6FDD83A553B +:100F3000F83146B011D8AFA97BECCE2CA4CB3ED96A +:100F40008BF1A5E54D27B540947DC4487C62FDE852 +:100F50007F6F55DDD4EE0EB57E26E275C7091BC343 +:100F600075F576ADBA385A3FEFB4F27ECE66F5F736 +:100F70000DCFF8F7C3EFB80E47783CAE3F6B99F052 +:100F80008344F21F233E3E55C74238BFE27A15F52F +:100F9000C2A98D8CE67740C963B8FE0679FFB1D14E +:100FA000AF7371E396DFA05D50D624B9714BA24CAC +:100FB00069D1D08F5BDE182FE33C9CE9D1E36FDD74 +:100FC000C36E35C845ABAA10BEF68ED97117B6FBF5 +:100FD000659BC6D04EF1BDDEE9C279FCCBA691245B +:100FE00007BD8DEBE54A563411E31C843E8CE48743 +:100FF000A11B634CF01572A01FCAD7546BCB3C6F7A +:1010000014FA2DD324B18F789EFA2DF4FF997E7BAC +:101010005FD76F01D96F9023BFC09B41BFA544D359 +:101020006F73254F0AE27DEECE412948D7B96FABE9 +:1010300049D1F4DBA64ABE2FBA59C44D7734807E1D +:10104000BBDCA0DF1A40BF45891F19A3E97EFA73F4 +:10105000E8B7D0BF46FE36A17E8B32DE1B04FE749D +:10106000FD36BCE920E9B7E10D16533CF0444DF8DC +:101070009B7AD56F52D2AD681FEF53BDB151F8675F +:1010800093B0C7378B38466C07F55C95F6C3F45CB4 +:10109000DEF9EAB97F119E753D37772BA3B8E89E3C +:1010A0007CC8F5DCDCEDA0E724E447AEE7E6EE64BF +:1010B000DC2F17A1DF86F4D06F8CCA9785F9FBE58A +:1010C0008D194FDE0DF58DF0A95E1B941FD1ADEF8C +:1010D0004619F55D95D68BBEDB777EFA6EABD07781 +:1010E000A0C706A27E8DE40F6F9339DE7CC7E8C3EC +:1010F0001B5F4679F99D4CFB92EF59F8FED13BA35B +:101100000F67217F7D2AFAF3A2C6E9D95E19A4FAF6 +:1011100027BCCEC757BA91FBCBCB1AB87D58562BFC +:10112000873CF0E7A431DF69D8FFC29D124B01F87C +:10113000266BF5130EB4EB9F5799581F4DC934F029 +:10114000C3AC9C62F2FB57D95DEBF0FCD12C85D986 +:10115000D0BF5FEC987414EDE0E21CBE1F502C9ED3 +:10116000EB71B0B3BBF464443C48E39C37FBB39EE3 +:10117000711653AD9CAE539F954218B7DA33EE22E9 +:10118000447AA1B8CEFCFC5D217F37C92D842FF6AF +:10119000AE1C35EE432FD785A77D024F8017139ED7 +:1011A0004252543C01A5A7642677E3A5F0772D4B66 +:1011B000705FA0F02989F69123C7ADE32D72FC3A48 +:1011C0001E753F77B1A82FBF692D9D6B8AC48B8E8A +:1011D000E7487C74E13D021FEF695D7EED9118D711 +:1011E000047C437A26F89F801768C73FEE22D3F924 +:1011F0009B8F045E46568F9B80E10F37611C3AE45B +:10120000E7D5CC79B32FE063D4C79E11389D5E310A +:10121000C61AC07DDA0DF64ED2833A1F0EB3723E67 +:10122000D4845ED9D1AF623CADF31B2537DA21E51A +:10123000613BE1B51CF8D10E45F63EF5CD24815752 +:10124000379DAF6A14F313D0C182EB267DBE0AF13D +:10125000F358239B385DCAEB385DB25827EDC7942D +:10126000D548DE308CA7AC710EC5A1EBFA197E0E05 +:10127000239DA2F0AF128D7F193A9BB3BBE7CD62DD +:10128000516EAAB5FA43DCE7990AF2B196D810FE7E +:101290007716FE3E57FC5024BD2E1378DB847875FC +:1012A00020FE3AB9FD15FE8ECE69E9F9E54AD084F3 +:1012B000D7094F9FE6FCB753F2A05FAC0B6FC8CFC6 +:1012C000903F4AC71BF233D2A1295746380FF0DDB1 +:1012D00027A3E77871BFD428F7853B0FF2FA9F91D7 +:1012E000BC2CCAB87F307FFF40BEEE4DDE8759C5AB +:1012F0003A41F0F73BF6CEFD2391BF774ADC2FD180 +:10130000146FDAF7BCC1CAD74D1BEC2007B8DFF663 +:10131000B6EA5DE7E9A91FAEB27239C0F584C7E04D +:10132000F7BA040782F1A675368A17A47E0CE4F694 +:10133000AA515F6FB2B3A45BB37AAF7F8AA8BF37FD +:101340007B498787617BA8471BA1BD21DDED45CE89 +:1013500017BAFFE05CE3BA43F0CFDF3B2EBD9D1F21 +:101360001A4F55CE9A695F4C8FAB4AB5045E51D186 +:10137000BE9B2C99E2B7A0E782CEFF70FDB76AA3AF +:101380007AAF9FA5DAC88ED0CFCB5E2D3B5810F038 +:10139000F6A54F2579012BE383B1387F8C8779102F +:1013A000922FF78FFAE86ECA97699FEDC6DFF5298D +:1013B000C57DC81B790C1DBB315322FBE13DAC6CD4 +:1013C00034DAE136E6B38A26213FE747F1213CD7FC +:1013D00092595B3DC103723DA22E5485A9774267A5 +:1013E000E23B48AF7132437A35FBFA4CC0F9F7BEA5 +:1013F0003FB34CDC8A073B81EA19B18F2561B931D3 +:10140000BE245ACE8C6EF8EAFD5BA07FA3F7CB5EBC +:101410000F94BB69AFC381723664B585050C78192A +:10142000C34255E8771A7DC8770BEA8302B07BF098 +:101430007C4941D3DA2A17C2AB257ABF3C1898E41D +:1014400082FE6DAA3939E932D40B500EAB295FCD3B +:10145000CB95D74A5E0C71CE6B5A41F14879B512E3 +:101460001D60DC1492988DD71BB241BD9B56C3FB07 +:1014700059387FC1FB586FEDC9F76F41BD03FDA41B +:10148000F737F2FDFA3C78CF8372523B87EA2B5C48 +:101490002D313C0753B091CF4F05FB552FE637EC6C +:1014A0007E8AE6DD29D05EDF0C9C8FC213E93CD139 +:1014B00048C94DE7381FBE80F456070E185FF0A5E7 +:1014C000F3F80949C062FDA3DB7FFD6DFC5C539E10 +:1014D0007781D607EA79272729C342FC7492F6E17F +:1014E0000F01BE03569C37793CCBDE9C2FB416C34C +:1014F000FC98631B44EFCF6A1C47711EB3999FE2AF +:101500003CA68EE676E7BB57DA43E8EF7B57ED4C17 +:10151000C3E77BAFB4D2F3F64D5C0FB70F6821BFC2 +:10152000FBE1D52AC3F32F55AB65D2138737AA74D5 +:101530006E577E86C737E46FE276C8DED5BCDEC361 +:1015400075DC7E9BF0CC6D93701ECE5FCFCFF9EA39 +:101550007A5A5F87E6B90B4DF35BA49ED5F570A967 +:10156000C04741F55ADA4F8FD4BBA5FA7C18A16F5A +:101570004B719F9DF6D3C32447A5F591F1658E6EFF +:10158000BF0DF243F83BE2EFB2FD2AC3758DF4457F +:10159000DB248A67C3F91EF24737493E8C7B28F863 +:1015A000D81A227B3C943BE33F709EF9C4CAF0C832 +:1015B000482BD203F4548EB5F38FBF84E747DFB3D3 +:1015C00061E410F04F2EE15F8F13CE5ACFE37EB26D +:1015D000DE5B998CE78DD9C43EA407F26B641630AC +:1015E000E88DA392EF963BF9FCE046FB47A76B968C +:1015F000569D87F36C918DEB47CF7A95CE8BC70BB9 +:1016000018D60B3EB4770AB7AF48D60CFC50B87367 +:101610004532A80EB644C4CB548973E6851A6FA729 +:101620007097E45E6B6847AF47AF57DBCEDF1BB404 +:1016300093A7BDD55F88FDA3717EADA1DE88ACA761 +:1016400047FBBDD493F35FA757E2B9FF9C77650AC8 +:1016500076CFF962CA20E33E8F9EEA7EE6ECF72D54 +:10166000CC67C05FCE1F6398CF40EF865120FF400C +:10167000BF1B1AB93DD730EAA0569A45B01BE5BD4D +:101680004CF8A3CB26F2FDBB86CCF716A1FC4FC9C4 +:1016900092881F5830A0F54924FBCD83FB00F959EF +:1016A000FCFD7C781FE5B2E1292EA7A02F3CA84FB6 +:1016B000CA56AF9844E56B250FD6DFB03697EC924B +:1016C000821C99517EED41B2930A1A0F26A23C83E7 +:1016D000FCAE447BA06CACD58DEA58974B5DCEDF59 +:1016E00015E76199CD3D0CCF77E0765834F996F740 +:1016F0003361B772B92CCFE172FBEE261547783E05 +:10170000724E72ADCBB18C729CD52DC77B574FD02A +:1017100050AE0F87248AA399807A00E57C831EE768 +:10172000C4EDD8F395F373D999A520BF385FEA7259 +:10173000AECB75A43C372B2DB7623FEEBBD24EE348 +:101740009870D5F60FEFE3FA8AF65F275CF5603202 +:10175000EAC73C85C779E9782D55785C608F7EAD06 +:101760005CA0F53D9FFE45F4E333ABD95F126F8B70 +:10177000E7F1EFB52AF1FDB9E4B3879C9DA77C9E04 +:10178000AF5C9D4B3EF5F6E59DE67AE2916947F543 +:10179000ACAF1DF018063CBEB5F1598A0F3EF1C240 +:1017A000C1A94887E21DC0E7C85F1B9D2C8C7A4EFB +:1017B00009D1BC55D420D33903A684B36F711AE57F +:1017C00098C775156F76123F15BD640D4D81F78B67 +:1017D000B67D319CE26A167652DC5AF005612F071D +:1017E0005B86A31C14293CBE2C522FFCDAC6EDE705 +:1017F000B6EDB1D3707C521DBFDFA2A8FE76D56ACC +:10180000D8A778C2A652BB508EF67983C0C778FE9F +:1018100017FB67BC57418F2B6BDBC0F54451A31AF4 +:10182000C27B328AEAB6B463BC71D1C756F27F95E7 +:10183000D79DA4F31413366F22FF4A79A36CDA8F75 +:10184000EB11DF592787AD1897D8504AFB90001F3E +:1018500024B85EC453FEC0F8C3E2CD3BB705018592 +:10186000C52F3FEF42FD72AC79BD0BF10EF59E35F1 +:10187000DEBA473C67FD23229EF386C3746F4B2F6D +:10188000F19CC7F00F1094B76DE6784E56D787ECF1 +:101890004BE867B63FCAFE47977DBEE9EB35781E39 +:1018A000A1EDA5E36BB0DF257FFB720DC689B15DAD +:1018B000769AF7CA5FF880E2B7F5F7BEB0097FC83D +:1018C00086E729FEBDFD13AB176B6BDF79381DE38F +:1018D00006DBB77C978CFECC793BAF267FEFBCADA7 +:1018E0001352589479434F917F43E7117F1F49B7B3 +:1018F000BD0D7B299EED04D01DF560579C6E7D29A2 +:101900008F7FF688F8DC8DD1CF3BF488C76DB8E5C2 +:10191000C62B51FF37707BF29C71B9EF033D2F3F0F +:101920000F3A6E14F1D7F5379C352EF704FE01F40B +:10193000B2D8CD74FCBA61F6AF9FC6BC863EBDC6B8 +:10194000E586CF037FFA798A776C3EA71DE5E8A587 +:10195000DF503C34D26F8A07E7A3AFD3F13CCA1102 +:10196000B5733ACE3F9D3BAD74DF4FD1CE8F489ECD +:10197000DAB7BE477E6A26CE35B4B3AE1F8F3F9727 +:10198000C4786B9D3C9E57D001E37D3D2E7A2EE2BC +:101990007A395FEBF1BEBDC5F95E6D1F28EE0FE031 +:1019A000F1C8A5B57F10F1B3DD749372905E07CFD7 +:1019B0001A47ADE3C12DF472771C7BF4B8EAAE3858 +:1019C000F608BA213D719EEA8A5307386D04F94939 +:1019D0003E8A762EA27D2D8F7F6F57A39F37D6E349 +:1019E000DA7D11F4D6C7DB9BBCE8727BAE71FC508C +:1019F0003CD16642524F7CB57D1F5DBFCFB44B7F5B +:101A0000D7FABEEBBC548914791EEB5EE4CBD286C8 +:101A100083E4CFEC5A7F8BF1B609FF7BDB0B32C539 +:101A2000392FA9DF4BFA3D527F94E1BD2D51FA7B4E +:101A3000BF5DD8E78D7CFE687BC91972403D6D7B28 +:101A4000B6135F976D3C4871D66FD6BDACB518E242 +:101A50002770FE0819C6D3F6E2EEE1A4CFC5FD302B +:101A600091ED548976CA9BA2B753BEF1A4A99DE219 +:101A700060BDE6769CBBBD638AEF76ACEF5833B7AA +:101A8000138FD5CB9343D1F669ECAAD8EFAFE629F3 +:101A9000CCA3740F8E93DF7B23BB62C8EE9CE7CC94 +:101AA000F9382E11538DE2BAAA168838B09F7A53AE +:101AB00091DE55CEEB18F67731E2D7E0FF51DD012C +:101AC00086F6AA9AEACF42BF43A4DED1122D2C6437 +:101AD000A0F73CE7E4140FED8B84D3909E07320F00 +:101AE000AB58EF6711FEABCF14B62405FAF7595087 +:101AF000F22E807AD9F75F0CF03B7BD6AFC381879B +:101B00006593BFA9CCDA7900D72BEC353BED47C8FC +:101B1000BBEC747F48F91A3B8D77EFD66F9F23BBE0 +:101B2000FBD756C6F787605583F796B9791D87B7F7 +:101B30007EBBE62F6857E3CBD07EFE1A288FEB8959 +:101B40008DB1B4FEE978298EEE51CB7FEDA1A9A825 +:101B5000D7F263393FE66F4E0955417DAD491C6EA2 +:101B6000DD3480EEAB287EC949F1A57BB7BE528635 +:101B7000F354FBE6580C3360EDAF09FBFF37E27E10 +:101B8000AD1AD5638C332F648AC7782EA818615399 +:101B90005C13233F06C911FAB11AE3E83C11D8C51A +:101BA000A67A4EA89D0F78898F83FDF839AA703FD9 +:101BB000D40791E5F4FCFD767E8EBDDC0AEF39BAE0 +:101BC000CB976B9D791CAEEEC7F5493395FF44E783 +:101BD0007391DFB35E5EFE23BDDEAE7AF8FB65E295 +:101BE0007E9B48FE3DD4A557FE7A71B4FB5BA2F400 +:101BF0009F9EDF2FB1A005ED962D76BAB70BEF674C +:101C0000C0730EDB34BEFF55E20AD3FD393B843E80 +:101C10002E8909D37D3EFD443FB03CC2CCD6F22292 +:101C2000D2BDF4153BC3F8B3D2D79C3EA477E9B636 +:101C30006F5B7F9585F18BB1E4D72B7DED7F111F15 +:101C4000945AC3D3E9FEBC2D5686F7E7B56D793BB0 +:101C50001DE5B54D0DA7279C655FAFB4DE6ABE5785 +:101C6000408CE35865E842BC77413FAF5BD48B9E24 +:101C7000B93286DBD7F6189F3586E4DD7C4FD4B1C8 +:101C8000CAC641C6F3FB459EE87AB17F8CFA8F9DA8 +:101C90004377F438F7DA3F2609ED99E66474409605 +:101CA000813D8EFABCA8EEE430F41F7C16A3DF6FF2 +:101CB000E089C3F9E833AD7318EABFCFD23B871987 +:101CC000E7992395368FA2925F87D28EB527F3FAD4 +:101CD000318C37B54F8BA6F786C5C412FE8A1E8E8F +:101CE0008D7A8E7A4C0CE7AB34681F536C17E54342 +:101CF0006FF7332D447AB831C6C3EB490B69F8BC92 +:101D0000B86EFB20231E0A956A2A07724AF82C64D3 +:101D10002BB52C83FED6DB2B9CEFF028743F81F291 +:101D20007FBAF855EEA6333991318E51E014665CD6 +:101D3000F233EBE74814D56F43FC69CCEF5664648B +:101D4000956A92F718564FA903CC2E7E5F5A054329 +:101D50003D7944ECEFA31F0CD36E7C3D487A3F38AD +:101D600080B18B32F0BE094F9CDB80BF6B70B33EFD +:101D700009E3692B18D71753DC688F48C1003B0370 +:101D8000FC5455593788DF03C27C182F49262CF4A0 +:101D9000CFE57EF33BB483804FF93D8457B15015B6 +:101DA000A018C386C9EF3A9EF1FBF3967DCC8CEB6D +:101DB0008F12410716DC4D7ACCC1BA7F9D00A35A21 +:101DC000457D5B15F7B71CDC9F73B85918EDC358F8 +:101DD000070BC742EA18AA1C33CABF2B0B60035F6C +:101DE000BAC79AF323E502F45A44BBF5843FA8F737 +:101DF000AB887ABF8AA8F7ABB3D5ABE3A9DC3628AA +:101E000003EFA5585C592FF0C6DBB309BC017E86F1 +:101E1000E03D7FCC12E315FBE684D718D11B2B964F +:101E200007BA6E8EC9207EFA59DCAE4E8C97668951 +:101E3000350CD7C38B24FDBE4FE67718DE636E1BCF +:101E4000C9E123A29DCD02CF8B74BF558FF276B22C +:101E5000BF7A94B7F7563E267A79676FFD898DDE93 +:101E60009FF85EEAAF8E8D5AFF0FD54B65AF7DF4BC +:101E70000EEEEF76E92737A0DE6C676E46FD541A4A +:101E8000DFFAB7167AC2ED4C5B9A99DE31C8DFC033 +:101E90006F31179A9F47F24914FE72F48571DF295A +:101EA000DABBF3617E5E4DE7835C31BE89B57C9F12 +:101EB000FCEE79DC8F07CB461FE6DF25F2EFAEE1C3 +:101EC000F6E3DD0FCBB40F1B79BFD5C1FFCDEFE13A +:101ED000B8071F80BCDD335F0A8533A2DDDBC5DEBA +:101EE0008F877A6788FE44DE8315609E49CBE4685D +:101EF000F76071BED4CFE145DE7F318BF9C5FD6659 +:101F0000E6E759316EE2DB2225A4550FED9EC7822C +:101F10002B80EFD1FE04BEC7FD2F599CC7662E8DC6 +:101F2000C7D7DF9A60D27FA78678E270BE66AF8B94 +:101F3000E76EFE7CEEB59E14E37945E574ACE91ED0 +:101F4000A02AD59B8AFA4D3D7D3DF3801C6AA707E8 +:101F5000318F211FEC56127E0CF3243D95AA84503C +:101F60002F2A6E3FCB47BB379EF3B35E5E4BBCAEB2 +:101F7000CBCE7C17FE1D46E681FFCF5DE1A1F3DFEE +:101F80005739FCA771FE955D39DE80A3273F04B762 +:101F9000F27157E1B8337A8EA74AF37AC9DEBE0EE2 +:101FA000E645F2CB796DD83FD9EAF9C883FDFBADA0 +:101FB000CAD00FD3133FDE2321C83F15EA4F712447 +:101FC00072DC94C1D8FE72BC6F14F4FF3271BFE8AA +:101FD000A24A26521E57B708EF1FA53447A43E91C8 +:101FE0004EA6728F8A7B4A97547A29D5F16BF356A5 +:101FF000D33D98B60B79FB36B7A05FA245E02F40E2 +:10200000F6972DB582F61DEDEE8A30DE27C7D26039 +:10201000DEC161B9AB09BF9A9B91BF13CA136C456E +:102020001852B5660AD1497157B07CC84F7504067D +:10203000C7A27DE331DF87694D1D71D6FB31BBF847 +:102040006D13C7FB6312E7B748BC3FA6367B306E03 +:10205000E2B16BBBEEAB22BCC37288E3FD3FF97EFD +:102060006E4FBC374F9B69C0BB337B32E1FD6702CB +:10207000CF4B055EAB041DAA043EABC4BDAF55E219 +:10208000DEDC2A81DF2AC43BA48F887B7B17233DBB +:10209000209511EFC0BFD6A14126437B7C0F0F5284 +:1020A00087E05BB785FCA4B2C3EF43BC5B1339DEAA +:1020B0006D0EA003F135E0DD83F941C2A7EAE078B7 +:1020C00086F29C0E025610EF23F139A707E0FDB609 +:1020D000D824D487634C78D612C79F1FDE9FE2F3C3 +:1020E0005BA290F348FC256AFC5E605DBE7BB38F0B +:1020F000AB445C7695B89711F18876CD2AC00FBBBA +:1021000098E3933F1F22602FA54962FD5F0574C0CD +:10211000FC27853D8478C674672C5FB7245A2A76DD +:10212000AB88A7047EDF0F4B0CB2B46CC64380F1C2 +:10213000971A641E84F5FDE15A33FFC86E25E27ECE +:1021400049CF93C86F2BDF562DB87F2FCFBFDE74DA +:10215000AE5B9EE68BF710FE0312DA353F1372B8C2 +:1021600002F985FAC7D7C38B051F2C15F7063F2246 +:10217000F8E73121CF8FEB7CE3E5E748964FE6F1B6 +:102180008E89991671BF629819E309E3BDF54C83F6 +:102190007ED1DAC64329DD9FC93EB692DCC60E6504 +:1021A0003EE4AFF88F1F0CF1FB70FD7DD11E8AD786 +:1021B000EFBF1DEB89BF830EB4871571CFA4CCD7B9 +:1021C00093CD51EF8DADF2EEB1A15FA6B7FEECBE9F +:1021D000691BF173DEE5441ED627E0BF6336C08E6F +:1021E0001A5857C12FD61BC85E8C7AA5C649FCEB7E +:1021F00080FEE71BF824B617FFCE54C7B51B505F0F +:10220000BC80062430C12F6A06D911CF80730FFA23 +:10221000B156A9FEBE382FAC8A8FEE8FFB652CDF3E +:102220008770655D6AF22BAC547DF49E7BAC59EFF0 +:10223000AC14F344C244B39CE8F3C24F457D573914 +:10224000023BB15FC9A727923C27DE1C7D9EA852A6 +:10225000B520DEF751358CCB773057E3F6730FFDA1 +:10226000C3689FE45460F03AF483E97CB690717DD2 +:102270001764DCAED4C7F504F2BD15E70337F13FB0 +:10228000CE0708CB176AFCDEE3BB2DE4875822E4B7 +:10229000ED512167CB857CFD1CE5CB8AF7587B2966 +:1022A000FD8590AB952887901E8FCDE0F6BCB83F9A +:1022B0004C5FCF2CB48DA0FB22AB1C169A17944F09 +:1022C000AC2107AE0F768F76A3FF477666B9034E33 +:1022D000CCCFA2FBDCA5F82C37F2CD37CE59179C1A +:1022E0002D1E16C84FF7162B2AF74BEAF7C8578949 +:1022F000FB0854F7CD0CFDD54F2656D829DE359670 +:10230000C787D7E46613DE811E9DB186755ACAB4AD +:10231000EBBAEEFBC3EA9FECE55E83EF85DE606916 +:102320004176A1414FD488FB249927C88618F4C56B +:10233000C28B2631F4EFF5D413BDE8CDF55C6F2EDA +:1023400092A2EB4DDD8ED7F566A47ED1D3C5174C96 +:10235000369DBF541D5E467A6748743F42B2C3CA79 +:10236000F72F99D79B9BD1331FF095EC30E00BED05 +:1023700021DD6FF1E328E389D49347AED3E7D7009B +:10238000DD3B344BF33C39FAACF3AB795EC83FFD2F +:1023900008CD4F79A747535A50732DD9230C77692D +:1023A0000CF72E1C5E7DBF0BE97BB846EC9FAF5649 +:1023B0004318BF74B8667119C1D5760FD266DC2F89 +:1023C0001E74E13D4DB3D6C8B49F7E2426984EF1CD +:1023D0009FDF9F39231BE26316AC5D9A8EFC386B3E +:1023E000DD523A377B24C137D86F80599687EC7914 +:1023F000FDFEC6BC67AD3EB4C77BE3DBBCD5D1FDFB +:102400003D55F827AE53987708AE4376BBC6748621 +:10241000810F8EFCC24EEB822A2DD88E70D5BA5811 +:102420007C83552544BF0F28D571B50FE994EAF098 +:102430005D8B297324D07E4FEF72C4DB6F455F3B09 +:10244000EEBB3E2DEE45023ADD64F2BBF27DD7567F +:10245000E14763B65EF26344BEA7977C178F936231 +:10246000EEE8F97FB7FF69688FF55D318EBFB4E69E +:10247000F8924FE889791FA150C48BCF5A171B5A85 +:102480001845CE6689F3C7B3C47E99CE8F85D7EB46 +:10249000F639E7E3483E975EB884F8FACB7D2ACD5B +:1024A0006B65C0AFA8EFA51746D37D500B9EBBE26E +:1024B000718C0BFC6ABF4CF925A7EDC4C7ED3FF545 +:1024C000D23982CEDFA9F49D88AFF65D4DE701DAFF +:1024D000C5FDD33A9ED29C7C3DBCC6C1F550DEE919 +:1024E0009F913C74F15768A686729E77FAE75C5E0E +:1024F000F0FED93138ECEBDE1C77A1E06B80D72CF5 +:102500009F346921D49BDFC2E58A8D0D96911F7B94 +:102510006DACF7D128F2BFC6E131F9B5F25B96F3A5 +:10252000F7C0AE4C34C499CC12DF7BC83FCDEF6509 +:1025300065EE204B457912FAB05B0ECCF772B7DB33 +:10254000CDE3D4D317BBC6798569FDD63DCEABE8C4 +:10255000799EB053F25B4613DC3D9E5F8D8E369EB6 +:10256000EE718CA5F2EDF1D1DBFF50B4DF5A59C00A +:102570007CA04F8BC4FDBF79A1FB34D41F79ABE3A2 +:102580001324C3B8F26B8A4DF14F7935B974DF5F0C +:10259000FEEA5CED5E83BC76D185CD36D1E543475E +:1025A00080E832D5E1DFE340B97CA1F0814F3D58AE +:1025B0002FA7D3112D38BC82F4DB7DAE68E7A73E90 +:1025C0008CA4538DA013AC1FB20C74D2E913F97E06 +:1025D000EBFAD2073EC5FD8BA7F8ED45BDEBB10880 +:1025E000FA6544C75FA783F36B2BD80F81F3C2DF73 +:1025F00065A6F8BB5EF127E8ADE3477F0EF6DF5135 +:1026000094FB4E94CD51581FE78773E1ADBB7DC15C +:102610000FE3A28F27C5A9F3C37C1604013EAA715C +:10262000FBA3F7F13CC482B6F3184F979C2E36F10A +:10263000438A7301975341FFA37B1E21BE6E0DC5D4 +:102640007AED19BD8F27C5D90B1F5C186443B3FF02 +:10265000EFF1C111CD37F8299C4760DEC279BDF09A +:10266000F9C7861BFB97EA1897E6C479A9FAFCF626 +:10267000B783E3BDFB701D1E5C277BAB6048258ED6 +:10268000C0607CBFC8F5F437E8DF5B14FFC4F068B6 +:1026900076F4E2CA7D97A0DFB5AAB2995255D8C5A3 +:1026A0000CEDE20CFE5D8F68F7055E2BF4EBE2CAE1 +:1026B00066EEB7B50599DB70CF003B3292FCD88A45 +:1026C000C36CCF696AC08D7E734DDC83A02A81659F +:1026D0001959E8674ACC0C1AF0778D93EFD72C4F35 +:1026E000DDE3C6FD102BD48FFE335B9A72CAE4770C +:1026F0007B5D99E5043AE9D744C7B07A9F24911FDE +:10270000F254841FF294A91F89CDA67D8A48BC2863 +:1027100036FE1D288509FFB3C087FE9DA4A56E3E29 +:10272000CE95C28FFD04FAAF2F023B36D645F6C1D7 +:10273000920B2C7C7D6853E8BE2B6B3C2FAFC5F110 +:1027400071D871FF43C6F559986027DE1026D3D59E +:102750008B12C2F1CC2321DC878597E07AA3635CDE +:10276000CB03F8FC797B20D70978FFA66FF301092A +:10277000F733FC818B11CF357230D303E57F2D7792 +:102780006662B974C8FA3881A717E0398780619FFB +:1027900094DFD7DC0DCB3DE10BE62B11FB86DF5F31 +:1027A0006CCCB7C7F82AB01F91DFCB4AFC42A2FD20 +:1027B00041FC4C079FFFFD343F2F77F27505F10771 +:1027C000F2D73E6E3F9D523C71B8EF87D879DDB4A9 +:1027D000EF63F3BC6E684F11EBD85AE057C5B04FAA +:1027E00077A1E2B3203F5D540DCF8DFD8D62272789 +:1027F00038E8DAF2A876BDDE3F3CAF83F8944F4F5D +:10280000227B24922F7674ED27F0EF69DDA1339EB1 +:10281000B288C3F14CFFD1FAEE93AEFDAA451C7607 +:1028200073A8FC5EBE3FFE696E1CC599EAFDB8A3A5 +:10283000696933DAC57734F59D89F8BCA3E0E23FD6 +:1028400063BA43EDDC138BFAE27E89CE97DDF9C1E2 +:10285000EB6A2CA45BDF5F47F71F3C2FE4713AEB78 +:102860005491FE01E6D6F87E5788DF47C5BC02AE1C +:1028700057D15F71773874DB0D00DDF37AE80634E9 +:10288000F7A6EFEB7C03D543A0DE3D89F694F4F781 +:102890001ABD6F7298BFD7357EC546E3E91EAF8D6E +:1028A000C6AF8F0F7A4AF8EFC28FB8F74DC7C7F897 +:1028B000997CDC77C4DE751D3BCB3AE00EDBB03F84 +:1028C000F3783EDE9F48FC7C8559A01F5F74FAF6C2 +:1028D000203F3EE3F4ED45BD5762EB4C570692BCFA +:1028E000BC85CFCBE4C005C930FE130302172721F6 +:1028F0001E9AFB9C97BD7FC0CEF9FB809DF3F781AC +:102900000C9DAF5B9CC8D7EC74228D53FF7EC792A1 +:10291000AD871FBB1DF8FBC4DBFC3EBB52D973E384 +:1029200043E4979699312E3E323D20FC0C2D5D7C80 +:10293000C8C73B43E1F232A32196CEC1CC982F9B6E +:10294000EEDB9F319FC7C332A579F8ADA675C222D1 +:1029500011D7D2B31EF48344D63373FE04BA17657D +:102960009BE61E477E91359CCF664EF4C9788E60FB +:10297000CC3289F6F1471FF234B6003C3314EF45F0 +:10298000319DF9E07F0DC2FB51CA9AB97F34459E53 +:1029900093F9534857EDE1F33DC273104F0E9FC7B3 +:1029A00061D8CF69532B32DDC8CFF7387CA80772C6 +:1029B0006FF57D8274D5FD22FABCFB0AD801181789 +:1029C0009A7BB72707F924B7DEEEA3D4C69418D0B4 +:1029D0006BB90AB3619AA231C58E690CB3619ABD15 +:1029E00050D84F353791FDE0CAF16B78BF796ED37F +:1029F000F35FE3FBF94A78B764E0ABDCA6B7BFA3AB +:102A000073763E3FC5FD5E56A799D69FC3EACDF0CB +:102A1000E58D6638336C8647EE33C36538366867B4 +:102A20008CF81EE19E9D5686DF2B2BDE6CA538F4BC +:102A30005771AEA0785E3BE9C509C54DD91827711D +:102A4000FC45A705FD953BFEFA32C559746E8A65B3 +:102A50001867B8FBD318168371BC9BEDEB30BF1819 +:102A60006887FED9E2CDF6B5184FB3ED529D4F43BE +:102A7000140FB5ED6FFCBC4BE7066B08E32E8E6FB1 +:102A80007FFE45E4CBE31BFA931DF6AA14B4607DE8 +:102A9000C14738DDC708BD3E46E8F5E23AF37AFCA7 +:102AA0000A976EAFBA87E2FC372681E3BBB5B22F37 +:102AB00087C5772574FB6D8CB067DD40CFCF8776F7 +:102AC000D37988D0CF79A17B351FD16B410CEAB384 +:102AD0008EA3DA0CF44B5D5C63C6A3CEDF9784CC87 +:102AE000CF27BA24A1E70CCF33305EC5B32415E756 +:102AF000EF67A3DF537FBD8BDB192FBCA0E9F2206A +:102B00008B7B2A99C770AEB25BEFB379FD319E081B +:102B1000E935B0FB797144BB7AFDB12E2ECF5FDA77 +:102B2000F879824481876395FBC86EE8B2232B7DD8 +:102B3000BE890638AF6677722EE16F77F2BD86F9EF +:102B4000AA64C3DEE4BB304EAE4E418F362BB9E3F0 +:102B5000B99F8F49C4E7723DF613F3118F6DF56F7E +:102B6000B8B01CD8D9238C7167F93557FB261AE405 +:102B7000FE87F2B94EB71237C7CB2B39CD93F09CF5 +:102B800048710DFF8E6171FD6DB7DC80F85ECDCFB1 +:102B9000D3672BCC2F833C966CB9EDFA61F0BCFC6B +:102BA00099515EEC0F54712B3E2FDE7892CE153D7D +:102BB0006AE1FE8E48FA04059F3DFA134701EA399F +:102BC000A8EF75CB087A7F9F05EC9B23E383EFDCAE +:102BD00005458EB3FA0F6FA0F830339F02DF4B68C4 +:102BE000BF75AE97BCEBE8E9C2EC9BD154F72DA0C2 +:102BF0007879C88FBA7E290C99EB89A4EF6AC16FE6 +:102C0000F01B62E493C8727DA604E9DC74C97CD031 +:102C10009306FF43C9A16A8ACF8D6C07235898C1D8 +:102C20000EDA81E17528979B789C16FC245BB688A8 +:102C3000631FC461BAC715F91118A2F85236D183BF +:102C400078BD994DC654D7376D39F5C3B1FCAB5239 +:102C5000CB73BFA2FA9C24E76DEE30DD6FDB4F9C97 +:102C6000476FF37058FFEE8F9E5FD464A7B8AEE352 +:102C70002734D2BF0B309E14CBBF68B758C0683D15 +:102C8000BEA5CF788C536EABE7F7A51FABEF335ED5 +:102C90003BCBBC1EA94FF4F9F620FE391AFD7ABED3 +:102CA0002617CE838B781C774A9F8ACC8A2874D2C9 +:102CB000DF4BD42A3271FDD3798FC3BB8EF014CC95 +:102CC00050C8EF9F4A7E9A5CE19F3AE8F6BFED025A +:102CD000BA39A1AC0FFE25EC93D7A1DFF30BD9FBDA +:102CE000807B50F73EFDACAC009DDFA30FF440FBB2 +:102CF0003315165680DF66E23C359C609A4F67AE0E +:102D000096289E71D672F378F0BE6EE3FC5AC0AA84 +:102D1000A9DE22564F69C16A737E21CE472E3C2719 +:102D2000C7E3768A6ACDF9FAB9C0928D67ACD1F063 +:102D3000F635D3C7E7FB02C727DD6CA3FEDDB72A54 +:102D40008EEF7769CC87F36DE72A27E9FF6216A03B +:102D50007EDC29E6FDF207737DB320ED983FD33783 +:102D6000AB0F9ECBE7F3232D19499EF9BD7EC5130A +:102D7000597800BFCF87E1BC5BDC248587216C03D9 +:102D8000511DC19FE3BD26387EE379367DFC386E48 +:102D9000E373F63EA76F119E9B92F9B88DF9250259 +:102DA0001F251BAD267FD1988D52D079399EAF6AF1 +:102DB000A1F7CA1ACE584DF58A791DEC016607BAFB +:102DC0008D29582BE3605675E9F1D025D1CECB1C67 +:102DD00010785C755B5E5F94DBC7D1BEED27109DFC +:102DE000437A4AF8A358D806EDC58CEC82293F7B7C +:102DF000218793E21EBDA6268DBE2F4AFB61336557 +:102E0000FF9B780EB3323ED0370EDA9969F1A52BCD +:102E100024BFBEC1E46F9DCFF1F0E4888A4B2AA2A3 +:102E2000ACB7753A3F21D5539C40703B9FA79D5945 +:102E30009D6AC0201723E3B8BE8CDBD342E78F3AEC +:102E4000B74A74FEF929E9209D0F7EEA5A0F43FF25 +:102E5000402AD009F5EF53125B84F7FC6535DC346A +:102E6000E70DA473568C17E30F4A1BC6C9A50E1AAB +:102E70003FB7E3622BD6E2BE54CA8C212390DF61B8 +:102E8000DC336E86E7A3E33CD45E5F07A77BEAC230 +:102E900060C6DCA1D8BE7FCE1B288FC362E8BC7C95 +:102EA0000AE0CA9940E932B4CF5259E66EB43353BE +:102EB000A77846A04F7F958BB793649167DC84F623 +:102EC000E3080E273C2CF9D61113AEA07652ACFCC9 +:102ED000937AF81CED4D1BFA271C067A4FA8C8C43C +:102EE000F65306F134510BA7613DFBBBE81EA075FC +:102EF000C83C37237D3DEFBB7129B82EDCDF060BC4 +:102F000075D063FBD3F4FD97B083ECFB0B87F0F235 +:102F1000C24E9997C9CFE724A6EBF6152FD7A1FA91 +:102F2000E246A25E7D8FDBF95F397CE407BF42EBAE +:102F3000E53C80A053F9E9581632CC0BE5D3BE210D +:102F4000FBB3FCB4CBF41CEF0935C6959714ECA188 +:102F5000EF3B94B2663A9F505A6F8E83BF22267A17 +:102F6000BB3A9F979F9659306ABB9AF9F9E93E2C74 +:102F7000D8275AB964F3F3D392196EFC569453E8E8 +:102F800039CB6971E1FA710ACE47A8674296A07AF7 +:102F900079375DDADD2DA679A8DDC3E10EB1BFA8D2 +:102FA000E7EBF5B74FD3C4393D7ECF7B5B252820B7 +:102FB000C0CFD34D27C9DF5DD2B49BF0A3F3453713 +:102FC0009E6259D080A7E4AAE6B00564FCE9B8FD8A +:102FD0004B875E0224D9A3CBF33B4B7D63211FBFFC +:102FE0006B6190EFD8AC2E792775B3CA220BFDF038 +:102FF000EED289638D302FDFFD7EF3351381B7B2BA +:1030000086F2F76BE3DE7B6B21C606759D3BE84CD1 +:10301000F73B0DB02D0276003CCC00BB23F213230E +:10302000F25323E0345EBECD194E97BD8C6D8EFBFE +:10303000E01A05F45C5BDFF074BC796479D547D79E +:10304000E0F78E4BB3F8F77BCB9A24AF64D0A3653F +:103050005E1E87E4F0B6683387221E9ADF447D50F7 +:10306000D228B971FDE0A8DF122618DFF318DEAB15 +:10307000E7EBD392FA83F45EAFF50FB1903C3F3AA1 +:10308000E4732A77AEFD2D36C5FC3DAFDEF6BB52AC +:103090002D81B750DFEAF7C7B76DF9A8FB7BAA20EF +:1030A0007FED7D7D7B499F469C5B2FC7FE38BAE54F +:1030B00045C7E3A3434ED17DBA7F18D6F4019A07E2 +:1030C000B1F34E2EC0AB75FF547A7814DA5F7827CF +:1030D0002FCE1F4F48A14B705E7A9A052EC176EF16 +:1030E00029BD68377E6AEC80DAF20C5E09F34DDCAC +:1030F00049C2FF0167CB00FC64DDE9C7FFC2E1A460 +:1031000016BA09E6B6EAEFAFC1EFCD1E18D032C04D +:1031100002F0F78F5F3A99E08B5A9E41F8C2EA04B9 +:103120000E0F6B1920C3FB03837D2623FDD6BBA3A3 +:10313000CBFD09A16FF4FEC50EF61D8943FBAA84E1 +:10314000CF3B782CDA067A757AD1B14DEB011FD3DB +:10315000FF2396F4DDFAB65BAEF3131E827E8C6F0E +:103160004C11F8A67991F4BB42F6445F9C0B13BA5C +:10317000E9E94C6FF6D0BC7169C516B41F52A60FB1 +:10318000A579E35597EF27EE51DDE9E9249EFEC4CA +:10319000EDE6FA5BB650BC46CA434EB2AB1E17DF33 +:1031A0006700B923FE7008BA58DC7C3CFF0D197328 +:1031B000D11B0080000000001F8B080000000000F1 +:1031C00000FFDD7D0D7894C5B5F0BCBBEFFEEF26AA +:1031D000BB9B4DB209F979F343081071139318A9F9 +:1031E000D64D881831B50B22626B7149F84930C948 +:1031F00046AD162DBD5948548208D146040AB8E19F +:1032000002622BFD82458C1AE88288F62BBDDF72A4 +:10321000EBAD3FBDD71B7E8A884256B45CEA6DEBAE +:103220009D736626D977935CA87A7B9FE78B8FBEC8 +:10323000CE3BF3CE9C3973FEE69C33B31ABB86902B +:1032400064428E25DC30C74E9FDF31E6159D4C224F +:10325000A4BB33F49C494BC87B1221C44548F009F8 +:1032600053687B0E21DFEDD1047589B4DEE14D7327 +:1032700016D1B2447CBD45C3E5BD7FD5DEE5B3D2F2 +:1032800072312DD3E7AB12998BF533BD690E5AFE1F +:1032900002FEAEA7E51E569FAE25AD589FC3BE7F6A +:1032A000AA84DCE5A3CFD4763A6E297DAE9DB8B56D +:1032B0009D8E6B918917CA0BE7166C5D4E616A7320 +:1032C000CC427889D79B2651F84E36E66A56D1769D +:1032D000BFA7AFC835845C51E0CDB097D1F940FFAE +:1032E000741CD2442795363CFE1C9837ADAFD77A74 +:1032F000B3643ACFDB1DFE39D0BE5EE39D42B4D04D +:1033000089B7C07705B423889F39763BB627F2404A +:1033100019BCFFFF084F95B8EE5F114F77EF34757A +:103320009D2C24F8F705FDB7B9D7A12A07FAD2BA20 +:103330004E1A87CB77C3FFD07148AD2493143A2C33 +:10334000AB226E8DFF36E8BF79E9077AA28137514B +:103350003DF42FF0BE4E0AEB52E9FC82FB24CF76FF +:10336000C2DECFB2119295E8BF13E621E09EF7C30B +:10337000E6347FD1F07C2C3F78A9E6765A9CB7E4FE +:10338000CCAEEDF4FB790F59085186DBD31E719D4D +:10339000DF7FCFB89A5C499FFADEB086E2EBFD1979 +:1033A000C4B39CB67B5F431A00FFEF73BC953F74B8 +:1033B000F7113285905FD9B5F89D49D083E4DBBD24 +:1033C00088E2B753224123D0C34C3DD2C36088D298 +:1033D000C395B0FE747DE8FBEE07278782747D06F7 +:1033E000C90091613E15C4BE5D89A9BFA300EB2948 +:1033F0009D044DB43EDA680E6D95805E28A0A55000 +:103400003F09EB5F95D8FA07EF30E238DD33191D3D +:1034100076373A43C11C00B68B00DEC6A2A3947671 +:1034200082744864EF9499B6617C6CE372C1523A3D +:10343000F0E2DBB43FB2DAE4194F1FB0843294BB40 +:1034400052713C4A0FAB91BE640647FD8FD342AB2D +:10345000705C4F39ACCBA336EF7C781FFD914501F2 +:10346000F83799C84A63097D4AA4C3E8A4EBC0E1D0 +:10347000215D4F13A083BB60008A877F6F386F5335 +:10348000E8FB9FD825840308CD584E481D61F5758B +:10349000CB2CC7A429F0D4860D09F4DDCA1BBC03CC +:1034A00082BE72D9D348FBF373BA22EBA336C08332 +:1034B0001FBE4B80FE3FB7295628D3EFA7C0F2D3DB +:1034C000EF0B87BFFF39F07D19C0C7E0276D166588 +:1034D000BB348C1FF1FCB980AFEB696FEC78629C58 +:1034E000F87E8FD9BDFF07F045F11E4E74015EB422 +:1034F000B8AEF1F0BAF4D1C74DB47E5E9BD6B182BE +:10350000E2D3BFD486F315F0DE951ABD8EE48DECC0 +:10351000FF94A5A55C86F92F65744F961928E26281 +:10352000F1A21F2E53D25D48A28735D228EFE5F0D5 +:1035300001807F5177CCF7F8DFBF1A62DB09BE212B +:103540008A14073FA72B459261DDFC125B37BD3E15 +:103550003A0FE4563CDC029FFFC6E58DA08B787CD9 +:10356000FF1BE0BB6C24BE5DFA814CE8D7BFD48062 +:10357000788AEF9F90107EF7B489044D94EED64B75 +:1035800012D2EBFA072D21909B83A6E80EC067604C +:10359000FF8DB8DEE71ACD0AA14D36EA19BF05F74F +:1035A000DB181F170C1480DC3B47E7ECA5EB73EE30 +:1035B00037DA9EA0248020A4E537DAAD40FFE75E2D +:1035C000BE89F5B3DCA2105A0E0086E9B881E07F0F +:1035D000B6118A57699611C73FB1570A19A0BE8F15 +:1035E000E239465E9EA3FF36940CCB8D41A800388D +:1035F000FA2C08079D69238EF75D335945C76FD1B3 +:10360000485E0DAD6F593229D4CEE031C6CAD51609 +:103610000DE9904A86F9BF4573BCE0DE225627A724 +:103620007079AC60BB431285B3C9B83AA205FA05FC +:103630003EA0F54BA03E67781D5A567FF417984779 +:10364000CB1E357D343DAF9EC79258BACA19A61716 +:103650004B29C317A926A1F1145E1B2F5B6A2221F7 +:103660002DE063E93472E22ADAF4E0C074A0235B4F +:10367000692FA9A3CFC069E20D51B8A7F6F7BC36F0 +:103680008EB677D4443261BA81A5BFCD3B79D5F0EF +:103690003A0B38AFE97F424BAC381E7E4741F1EE22 +:1036A000B662BB89B3AE887DAEC0EF92354C2F0FAA +:1036B000C02BE01F99E9CD755C6F52FD8AF27A61EB +:1036C000D704D4AFA0FF40CE3D95C0F431C83D90A3 +:1036D000336D8EAAAB1C749E6667D51447191BC741 +:1036E0006783E927A1FE88A7EB783D24DAA5E6B534 +:1036F00016B75AC76E47F90CF116DD90C8E4882C4E +:103700006179D1AF753DAB103E19E9E6DECD3928C0 +:10371000971B48971EE8BC8984F440C78B8C24987B +:1037200040E962116D96489F8BD71B8812B37E8D3E +:103730002175B989CB85BB4904BFBF7B675C7D35EB +:1037400009DB687DB391842DF0EC55D7B7507D8EA1 +:103750007CD6F78521F63DE966F3BD8BAFBBA33A76 +:10376000A4F5D3796F3051DDEA84065DB83E5397F6 +:10377000F5E07A269678731E06BDF22B9D672BA581 +:10378000DB3FF0F512F83966AFAA00BC9BB51A9C76 +:103790007FF46103E2E724D5E3B0FE6B1DE4AE598C +:1037A000F479AE8D78F37580267BD62CDB483CAF60 +:1037B0007AC5D40074D3E0D0A8E82AD3A1C372F9A3 +:1037C0000A8EFFE596D0D61C44F714A0A7F25CA1A0 +:1037D00057C99499B47C4C47ED3B5A6E9963F543B5 +:1037E0007F03604FD0F2FD0E26CFEE77E8713D45A6 +:1037F00059CC57D00D1D07FB335FC59E028E654324 +:10380000ED9F6074C3F5F0BA46730FEAE121FAD573 +:1038100010A4DF229F1EF0FA0A972BF3C16EA1F8C5 +:103820007E851214C88F602FB35F293EE62DA5E573 +:10383000574E1779562940674CDEBCF21D3359416B +:10384000877CF3CC4F1FFB275A7FFEB45E31D0FA42 +:1038500005406B74FD5E918817C60BBE680881BE7B +:103860006CD2337BB469FF15CC9ED1FB372C8471AD +:103870005ED079C0DE694A083DB703EBD33C94A221 +:10388000C9AB3A86CFE0CB16F6BD39F4B39FBBA0E7 +:103890003ED513A4EDA326FF4658D7748392887AA9 +:1038A000F9D75AC2C6091738285E8F8798DD7D9CE4 +:1038B0005649304EBF0DFBA17C9AB690F673A233E9 +:1038C00015E743E52FDA5927D618B682FC5D373461 +:1038D000AE84ED8FEB7CD3D368F9F88BC59EE5B44D +:1038E0006AD0A70FEB293D07D632BBAF5EA36C01B0 +:1038F000FC90FD169C87588FC09AC5B5501F58B2D2 +:10390000EC16908F63F139C87B122337CF9168167C +:10391000F0D3C686DCDE30E895FE891E54AFC44D78 +:10392000179FD28D9DB53DA963F88DEED3213D5FE4 +:103930006EFF40177239D343304E80CA6522F80FAC +:10394000E5724C593B5A99AD63E095546EDFA9EB93 +:103950005312FC47605D5A9EFC8FF7972A305E1425 +:10396000E522E94A46BE3CA9F3CE03BA755487F571 +:1039700075317AFDA483D999F5066E0792B03E960B +:103980000F457D79959AEEC5F304A77F5B84C9F74F +:1039900091F51ACE1FB71A408F4D6520936CD02336 +:1039A00056E85FC1FEA79E0EEBEB69397B5958BF05 +:1039B000883F814F28BEC3463AEF931B6C8CBF29CA +:1039C0001AA09F451504F5E5222DB5634BE0BDD245 +:1039D0003740D7E5D48B0EA42FF2678A158AEFF90A +:1039E00084B73350BB97CAB1973AA430EC0BE6AF1B +:1039F000376C35E5005F7BB53658CFCD12CAB1F9CB +:103A00001D95051B6879C99E2B70FD132A185D2E24 +:103A10000939502F4EE5F2B1DE10D2A31DFE3389D5 +:103A2000C03E88F68FF67413FD28AD64241E40AEA8 +:103A3000ABE8211453A6F6D1D45E26570995E724A6 +:103A4000C66E12F21EE43889B303D5F41114FA8855 +:103A5000C93DA2A482DC1372F998DD97E8443B3E8D +:103A60003F15D697AE27939BBB25C46B3369457D25 +:103A700022F4C0D0B85C8F9CD20699BE323C81CF74 +:103A80007C670EAEEB12D28BFA44E895B1E820DFEA +:103A9000A9E1FB88D1E960BC53C1FE9A4E93F07551 +:103AA00074BCA66524DC3C853D6D53503F323D69B6 +:103AB000647A129EE6CBD097F1FA315E1FC6EBC155 +:103AC000543DD377629D853D933A8DD901539785B7 +:103AD000B4A408FC35DEEA94E461BB26F08ED1A8DC +:103AE0005C09651FC905F99E50F9622AAD0FC8C46B +:103AF0000B7C65A178E9A1EF3773FBB72795CDD78C +:103B0000AD67F4AB937DA4D80AEB12C17D6F3499F5 +:103B1000D8811E053E37DBE87725F01DE3B7A1EF1E +:103B20008DA4C31CF37DD52B26D43F175EB6850C20 +:103B3000688FF8B31DB4BF94DF1BD04E3DF78A0DDC +:103B4000F5E939AE0F5DC2EF401E617E16BEAE4193 +:103B500052358E00ED4B33C6810814F659B383D924 +:103B60005923ED215E9F1399C3E8CA80FBCD0B8ECC +:103B70008107A04CE121A07F6E71327E0FEC995637 +:103B8000FC43FA3EE0B37A18F6FDC540AF06EDF708 +:103B9000E718297D4DD72E8B3E48E7D19C69B58328 +:103BA0007EABCEFED7DFDD41CB1FEED11103ACF3F0 +:103BB000F6697349EED8F2B731A43B3E10C32F77B4 +:103BC000EF54979B7BD5E5409FBA7CBFD3E63A651F +:103BD00041D9E1F982D2B5C1D07ABA87C26B78D522 +:103BE00080FA6886D3FF9013E4AD267A18F06CC88B +:103BF000FE780AF83B02FD9F48F03450368A1431B3 +:103C0000FC035F5F30CDCFB68F82B761FC11A30696 +:103C1000F14CAD75F6443917E07CE2D27B3F3C4075 +:103C2000E7BF6896D9BE02DF786BCBCAC19E441845 +:103C30004960FD4D1FC2BE8BB66B84F53F3593B610 +:103C4000A37035AC67FAB0894412806F5BA8DD6958 +:103C5000A44BFC1BCE6F777744CBC3F47FBB9D3561 +:103C600013014EF92FB20FE8E351E837C64EDEEAF2 +:103C70006472FC4BFB993246F899B602FE9A8D03AA +:103C8000FA4A3AFEF57FF90CE5FDE2A5AFE13E8286 +:103C9000CE633EB3AB4D0AC8A7C50F1EC0F762DFA7 +:103CA000762AD38AFBB6D7361858D9A1C7F2A9CD40 +:103CB0006C5FB9B8570AC13CA55917932A412F6CBC +:103CC000D6D90D64245EE3F1F8C1A6B713C0EFF5B1 +:103CD00001221DF67B12B3C7ECAD09B87F505A1311 +:103CE000C0BE0CACBFF143908F8B376B3D602F9003 +:103CF0007D36F4CF2CDE7CC3C48556E8E7D3A44AD6 +:103D0000F0136DB9013C54D0CE17627E9EC8F5F415 +:103D1000BDBCE56A05F8F1D06606FF62877107D081 +:103D2000D1F57FD1227FC91AE2073BB95BEF9D082D +:103D30007CAD6CDA3E1DD6E78399E91A6CBF4B2245 +:103D400076C08B63690ABC5F2CC93EE0E386F58DC3 +:103D5000B5B1764F9D93F9C72AB397A50C5891AF8B +:103D6000E6803E6DDE4CF908C69FF5DEEFEE700D85 +:103D7000F395346BFD2D53A1FF67751EE0BB217BCE +:103D800066D3B790BEE02F4CF1B598E3EBABF29958 +:103D9000C122F8A4B500E4EAE215AD05F651EC8CB9 +:103DA000213ED944F9723221A79D12F902FC9319E0 +:103DB0004ED5BE63AC7D9AB550837AC6E821DEED60 +:103DC000F4994AB7C9B01FB725C9586F4BD2237DA4 +:103DD000CB7FBA77E76FE8BC9E74FA2F80BECC2603 +:103DE000DE62D06B4AD45E45CD5A4035DA61641349 +:103DF000B3AF89CCFC85EB92C98E5531FB7353125E +:103E0000DB4F5039F105F473EEDD3F1F06FCB6645D +:103E10007D3C05EC85C0C5CFF4E05FB3F64B28DFF1 +:103E2000AD1E1F01BA09F4CF240B8A86E572C0C308 +:103E3000F446FCBCE624E9981C7545B19F4A97827C +:103E4000E56E07417ADAB8D48CF6FE4657C80440CE +:103E5000FFAD7C2BECA746EE0F346EFB85570B7441 +:103E60001E92ECE3A1AC30FE186C9817D2D2713ED2 +:103E7000DC9617C4F29E4A8F96D659B7FDE3CA5C0A +:103E8000C0539FCE03EDAD9E810498DF87DB4E24A7 +:103E9000C0FC1AB66971DE0DA14F5216160DCB0982 +:103EA0009DC65F900476825DB2C2F8425E7CB8ED3A +:103EB000D3940556E63F407D5A3A3A5ECCCECAC905 +:103EC000F0FDF5DF64EB726697210472F08C89F9DE +:103ED000F745BB3336A6FFAE4B12FECDDE2CD03FEE +:103EE000436579A206E4C4F7ED6CFE2E7D6F16F0F3 +:103EF000E54792BA9F252BB52444E552E34A8984CD +:103F0000A8CC3FF3DC4B5920FF3FDCFE52565D0C42 +:103F10007CF1DF89E78D496A7F9AF0AFBAF4E10C52 +:103F200018AFCE63607ECC31FCABA23D59CFFCA470 +:103F300083946B810EC577830D662FD8BB83C4181D +:103F400002975B5D3FF7D77ABDF92ED8D788EFE3AC +:103F5000FA5F0DF444E192FA24F427588AA2289FCC +:103F6000BFB4FC77D1F58C91FF749D8DB04ECDC65A +:103F7000E8E17104E9430F78D3B75865D05729EDCC +:103F80008CBEA2F76B709FE532274C81B8803EDD76 +:103F90006D05F9767D81B9439308EFB342D03E3386 +:103FA000BD10BF0B5631FA0FA610F4C3A5915609E8 +:103FB000FDB476E6E7CFA820F655B4F8B32466E75B +:103FC000B88967BD360FD75FC23807C78BD00F409F +:103FD00047202FCF4846A423A95F427B54ABE99DDD +:103FE00007FD8E45572BC5BA72BA1A2AFF9DE8EA1B +:103FF0004941C723E8CAAF205DB98DA3D315F72384 +:104000005F767B12F4C1BE3695E36B2D973FD1FBF3 +:104010008DC2AF2EC17C6B797FB5466B580B7AC4CD +:10402000A3FB38D63FBC89DAC5B07F4A03BB9E3EAE +:10403000C7B5CF5770DD486400FC0896AB8DA82F3C +:104040001FD34472C08E499DD4BA1BE823755E51BC +:10405000493BEE0B331CA01740D7A27F74E9341FF5 +:10406000B323581C283A538FFB9C96072B7DCC8E8C +:10407000A8417E09AC3629A007A7F5E72C07FA0866 +:104080002C231E03D271CF8645E0CF9D6DF580AC09 +:1040900013F125B252CD779D128B53056F22180F65 +:1040A0001B8E330D6CF921E8FFC622F49B0CF98FAF +:1040B000F309EA8DCB8D43D6AD3621DE45FC68D0C1 +:1040C00046117425FA91B13F9268647A68A47C40E5 +:1040D000FF734A05117FEBA19C2ECA3CDE23F85FDB +:1040E000C4A36C45BE1CB0C82B9C39BF32439C0492 +:1040F000FC776CB31684FD00FA8D5919DDCA4F693F +:104100002820E950FB9FABAA3362CABCFDD0F7C19F +:104110005537575F8BFA77A81EC0A67A5994BD26EB +:1041200005E255C3F532B5838D7D12FFBEE2E61B75 +:10413000A8AA1E94C4F87FEEF4821FD14454E3C5AC +:10414000C227C7F5AFA3FD5B15DE3E38EE26E8EFCC +:10415000A912517EA0D34BE15BAB53F78728E5DF73 +:1041600043418CF77F530EAF5A9D316C1F507BE15A +:10417000CF4965C376C2A3EFD5765D49C7B2D83FB4 +:10418000D583FE15FA3EE092D00E89E7D70497F466 +:10419000D5EC6B65847D9DE062F6F5746049BA2FBD +:1041A00041F91D58E62360DF52BBC4E942BBE4E39A +:1041B000530768FDB9599F1F1EA740BB7BE6C1BED0 +:1041C0002A705146F91BD8A90D49946F8CFDCCAECD +:1041D000A6FA1CE305827E96D839FD388204FC9746 +:1041E000DDFBA432A077425AB36EA36BF903973775 +:1041F00013C7E1FBCDF87997BB985F205058B5A164 +:1042000000FADF2611B01756151E4F5980FBA9631F +:10421000290B63BE6BEC7B0AF1D9B853372A1ECB4E +:10422000A9E104786C79F9452FC88D3321096542DD +:10423000831CEA04BBB6A141031621290DCDBF039F +:10424000E31F73F5643C9D5F06D777819DB706A792 +:10425000C2BCE9BF127DB5D1B708E5C4C6B9462BCB +:10426000C6910AEBEE413CD8CD5EC0C3AAC2AA34C7 +:1042700018A765E6743BC64DA83D07F52D0F7E07D0 +:10428000FD4502AE557DBA1AB077CAA95DF70B0A93 +:1042900077A673468D87F2F538EDEEE2FBAC10574A +:1042A0001F5D8EFFBF6446171D922FF8ED52F48FED +:1042B00092587F67761FB31F6F71E955FEF15B5C03 +:1042C000CCAEBD36189906E4B25F1EB0805D1D20ED +:1042D000DE4F605F4D7C56653BAE13935FAE360597 +:1042E000FD6646D7C0635742FDB532EE67883CF0A5 +:1042F0006318F75CA7CBB38A703E80F283452190A8 +:10430000C7FB5CFEEFC2FA96737BF5DCCB371683F6 +:104310007F51D85F9DCF99506F76DA94276B404ECE +:10432000FE49667903C668641AED67C9E74E1CB793 +:10433000D314EA84F50FF668B1BEC9EA5F04F4DB72 +:1043400078EBFA299887600D15801ED5B9BA08D088 +:1043500031DDBEA01FC5E8F21188234F0BCE972593 +:10436000D0177176CD34F063E1BEC5857EDC2ACEF0 +:104370001FE329159C32222B747C91346CE7BCF925 +:10438000E7D932BC14F68FC6C8FCEED573CD04EC69 +:104390005CF248F4B006FCF8AE08017BB8B957C22D +:1043A000719A0B5FD0C3FEE5EE5EC6DF01BEDFA0F3 +:1043B000F8CBC27894CBC2ED810E46672472781C8C +:1043C000E0F979B69E84D076317E5742963379C033 +:1043D000FBD3F3F84333F737514D88F5AB5CC2CECE +:1043E00058A18E5BF071D74911AF16F05A2CA9FC79 +:1043F000E4E2D9C3BF4F3C189D0EFC1BA5F4057E1B +:10440000A70DD2CC7B5EA7F3DB5036C903A6989BE1 +:104410009293B604DE5352A4782FEDFB643AD00D8C +:10442000A921C8AF2D7D95DA662B8BEB605E8CA53C +:10443000B507EA53EF2A44FD0C719359F4FDB31C00 +:10444000AF6956E6C773AF08E6401C34F1A0EF9E93 +:10445000D761FC2BCCE8874DA56B6373E27325F81D +:10446000BDDCA4F800E86777AD5202F088781FC47D +:104470000B67160DE7E3383D92772B7DEE76399882 +:10448000DFCE406A005E781FB20EC71FC19F07E3F0 +:10449000427C0F9EE7D2C232FAFFC9C096EDB8EF58 +:1044A00037603E486DDF1BEF80FEAD35925E8CC7F6 +:1044B000C6D92DD589B7BE02F43F78F6D4968701C8 +:1044C000AEDBF67A30EF25CE1EB9FE9BCC3E3FB375 +:1044D000DDA2003F6CE5729BDA8FC827C15D6C3F9F +:1044E000196F471E75A9F72743E5AFDD8E64F00508 +:1044F000B7B33C0B21DF037CFF37D8703E01F4D704 +:10450000BF0DC113970FB28DE783F48F9E0FF2E6B4 +:104510000E4B10E8E17CAF09FD92328F7B9DB545D3 +:104520001F002475380ECF01791B5872E6E71ACAAE +:104530007F720F8B23C9128F33FD4A4B585CCC6BB3 +:1045400007FF8B805B764C777B8B403EB27937716F +:10455000BF5193B34061F12E9637D494102E007B57 +:10456000EA55AE879ACC2C5E35E8D087615DA326EC +:10457000FF1F5D18D762DF935F1A94D8B8564F8833 +:10458000D975270A35613D9D670FD807B06EAB59C5 +:104590007C6B289F60BFA1C7C0E290581EECCC4145 +:1045A00039592FE256FB993FAE9EC7A74ECC5AF41D +:1045B0000CA45C7448AD35B03FBBB0AA12FDE80F47 +:1045C0003C39139FF52BD57EFF45E0A7CF1B8E23EB +:1045D0000BFF7B1DF1E899BD3CEC47D450FB4559DE +:1045E000295781BECC21F61520FF95205DADABE9A2 +:1045F000B3833EC168973412D83972A7CB0CEBFB5A +:10460000688706F554B043E3857602CF39C9CC8F6D +:10461000744D32F36BD0A50AC138E2D9A1E371071A +:10462000DEDF72A209C35323B1E7A376B966347DF6 +:104630002DFAEBD0B51AC14F17CDD4A0DFFB82DE27 +:104640003B17FDC6CE020279541DB6D69535AC1E79 +:1046500079E78229EAC3FAEB64664812C509F233A6 +:104660003599E7CBC5E16D6197BA1C1F8F690CA91D +:10467000CBF5C43F212D8FC50F62DFA72633F97517 +:1046800061550EC7B707F3E3C4FC976730BC6932C6 +:10469000D93337B36A2ED0412EC49773E0C9FCAB2F +:1046A0007426087FEE752E09E9230EDE0E30DA80BF +:1046B000BE3A593CF46F853F1EEECAE414AE1FBCEF +:1046C0006E885FD6DBF5188FBE5C3F495DB25A0E2F +:1046D0000D95BFFEFD2CDB27756A799E8D1DE5507B +:1046E0009D9DCDE584E4D91186F7566A2FC03C3AEA +:1046F000B525603F4CBBD58AF368D96F423F70F354 +:10470000B2812CD0E32D55030510B789C72F402B5C +:104710000BF945DBD5B9E8FE03EC84D8763C5F4B5A +:104720001D67F5FE20B90CF6392776BF01FA6AB786 +:1047300009F515FDBF0306F0B3BC9C83F6CC8736A4 +:104740007F1BB40B98C35B9ECD01BB85D94DCDFDBE +:10475000861EB00BEB3A62E27CF09FD5EAB81F5997 +:10476000E944FF3BE956BF6FD814F7DD883860177E +:10477000AEF33ABD7F22F03BD53B987F70B65183B4 +:104780007903F55ACF2290B7674D6A7BFCAC8DADAB +:10479000D796A175F6A0BDB565CC75F614C03AD70D +:1047A0006B883FB69F665867BABE4D7C9DCFBE787A +:1047B0007501ACF3C7BBAF2E80755EA7EBF202DFCD +:1047C000B439FC5B9369BF276FF0A13D25F2582FE8 +:1047D000971EF724ABFD2B43E5FF21FFCA58FA30A3 +:1047E0003C04875A1FBAF44A06C8833AA3E1BFD5EE +:1047F0008BF037AA1FCF68407FC7FE3F7FBA66079E +:10480000C8817E2DDA23A2BFFDB23F0FECA1FDEFE0 +:10481000B83D4169ECFE1BB95FD86D2441F0AB880F +:104820007D80B027E3E5F15B7C3E1F257B6F00BBFD +:10483000E6CBFA8D1BF83B63E85366E76E933CCCFE +:104840006FDC8B7EE4967DF3EDE0273E1D627EE318 +:1048500096178BD16FDC187A2D0C7965A45FB2C3E3 +:10486000FEA371DBB104C80710FB5CBAAF3D938CAB +:10487000F4A8DEEF9E0E9D4880FC010A7725E871C2 +:104880008B2BAA07BA6FA1FB3DC8236C91A387A10C +:10489000DF1617C13C97D23EF5FE4FC47937FAF4C4 +:1048A000287737F64B2190D7297A7F4E06E8359244 +:1048B00061C77820E7B38BC9DED494B2D8F8BAF7D1 +:1048C000F3E4E4E17CB0810D8948BF033AE2B583AB +:1048D0003CDB60E3F24C46F9F6C74D8E10CB0F631C +:1048E000EDFF18627642A3C80B934958A6EBB56852 +:1048F000B6F75D586F90F7E138791F5B1671FBBB17 +:104900004918F552331918CA0F8B6D171FD78778BE +:10491000B8AA1FD25AAC801FEC4EAB07E081F8B8A2 +:10492000BA3EC8F6EB941F96960CD3AF580741BF1A +:104930002DDC0F1D6838FE08D06FA04FB2837DD7E5 +:10494000E461F4DB44F75B90471BCFEFA4579D373E +:104950003A16FF97A6A8F5D150F9EFE45FBD3E45A2 +:10496000CDF762FEC26F3F34CF7E89F165DCBCE2D9 +:10497000F7A9F1FE76B1CFBC5C793827452D0F87BA +:10498000CA7F67795837B42EF1F2501DCFF89BE5F6 +:10499000E1FF705CE3997D4F27C0BE03EC78D8A798 +:1049A000ACDCAE63F91314FDB1F1E2E95AAB97C583 +:1049B0004FB5A25E1D8757A6F3383CE3EBD75ED414 +:1049C000E2BA35F33871F33E9B079A365817639C69 +:1049D000363E7EBA84EC9E0E4B151F476D027ECE8E +:1049E000BB743C75750A8B8F525872206F213E6FD5 +:1049F000EB35EBA749FE9875AF2AA21B8251E8DB85 +:104A000028078933E6FDC6146657BFC6F38BDC7AE8 +:104A1000768E60ADCDE285FD8C5BC3F29F7EE0F2C9 +:104A20006D82BC18A3C2F1FAF2ED4443F1F28CAEF0 +:104A300017E54AB0D9EA013928FC37A2FF8B3C5E62 +:104A400071D9FA3F8EDEF7FC0FD37B3C7EF68BF1FB +:104A5000FED6B8DD7A8A1B155F10A4E323105FCA67 +:104A60001949BF63F533161D1F4DF11D496176FECF +:104A700014CC57B84C3963298D9E003F11D963502F +:104A8000C0AF097E12D48FABD3783EAAA77C26E6AE +:104A900069B37325E21CCE5876E40743EBC3ECC838 +:104AA0000FC65C9F2F6747DEEEF07D087476B2D2AA +:104AB0008BE7011EB551F8617FF89C61D4732EE23B +:104AC0003CC6A5FC2D5FC4D1D517FF4B72D4923ADA +:104AD000965DF975CBD1CF13C07F3A763F419EFFEB +:104AE0001941BC45F749646B8C5F3B1061F97B1938 +:104AF0001C5EF1FE3FF8BEA121D59B994ADF7FFCE9 +:104B0000AED14812A99E2E6572B1C567C5B8424B99 +:104B10002FCB7F695946508EB780DFB408FC8933AC +:104B200009D87D4F3AFD13208FEED1F7AC416D22AD +:104B3000F8DB6711B0F3CEBDCBCA339CFEC99867D2 +:104B4000B76C00E318DDB3CE601E56F9179F3E52D6 +:104B5000538AF0A23FC165509F67B93D95C933F1B3 +:104B60009C3D846F2FFAF33F6E60F9DA0197D70E00 +:104B70007E09E10FB728118C2BB4EC61C65BB996A6 +:104B8000CD87FC3003E9A9654F6531F84D49AFA9E0 +:104B900018ECDDF2DF5B71DFF7F183E99827B1CF25 +:104BA000E5AF027CD84A4337817D9A4DC701BBF7F8 +:104BB000E3DD371503DC42FEAD03BF391D7F9D4D9C +:104BC000ED1727469677BF644726EE339BACFE5A17 +:104BD00098FF3A138323B89D9F4FE1FEF278FE17AA +:104BE0007C9FAAD5E038A9DF35629C5CC885753A00 +:104BF000E237E60DCB93129E671870F13CC7FE9921 +:104C00002C4F8597AD2E75BEE747C93794003C25DC +:104C1000A9F2578B675947E40B94A4B27896EA5CE3 +:104C2000A2E522B3A773ED7AA427DB4AC2E254942B +:104C30009EC0AEBF361A9906E7BCF2BBC3D7029E30 +:104C4000F75FD4209EE49947303E9328B1F1F256A5 +:104C50000F744E007F8CFDADEB6049952E7B15A047 +:104C6000F449A7EF8154E4FFD64218AFEA5F742CF1 +:104C7000BF729F05FD0CDD594D985F79EE3D83EACB +:104C80007C4EFC334856603E656EDF6F314E60DB14 +:104C9000238D9A27FB44AA15F9A62518998E393633 +:104CA000D7BA50CECAFB7E1F04BB43EE944102919B +:104CB0000E9D5703E7D382CB09FAF5C777DB35B0F2 +:104CC0005ED93C3F6670FF7F4EF1E3BE45C40542AE +:104CD0002CBF4937F008ECC7E4E503DF0CC27AECDF +:104CE00071685AC07FAA8BB6A0DF659F05FDACD95D +:104CF0007D792BBE41CBD92BED18071B7CE5EE6CE3 +:104D0000CCE7A7F31C3FCA3C1F4A65F948F23E8B2B +:104D100006F499FC04F1C0A8B223A50AE17E8A96A4 +:104D2000693FDF077A4A1E8E9B823F0AF45443AAEA +:104D30007F07D0CDD0B9A4A566762E899FA7B52DC3 +:104D40007D6F179CF7D9C2FDB907F74F9E85FEBF4F +:104D50004E598275B8E060F9952FA4B278E248FC0C +:104D60001FC43CD6DC7DBF657A8DE202FA97758C54 +:104D70005EE44E570FF8195F49F063DEEE751D6172 +:104D80002DC6CDEC277F5CA3C4EC77D6333DD3B2E0 +:104D900093EDCFE3F73797D22FBF1E92334CBF0C62 +:104DA00095FF4E76CBEFE2F4CADFBC6F21EAFD5EE1 +:104DB000BCFD12BFBF1B618FC7F537961D23F25094 +:104DC000AA86C761F6B44DD84941559E4E95959F28 +:104DD0003B34AAFB5F9F64477A10793B29EDCA7286 +:104DE000C8DB8FFE88A0DF4EE415893CA26015CB9E +:104DF000F7096A8C782ED14DBA307F681C094B12A6 +:104E0000FAD706F0FC6D2AE411D1EF4FA4E662FF59 +:104E10009B8967A516E5A62201FC26C83F4902B872 +:104E2000431B16C178B759713C13E49F24E13E033C +:104E3000F939DDC7F256A735B0B8433AD5CF504E51 +:104E4000CF6774699AABC73C56915722F24F045E04 +:104E5000AA38BED3272CCA01B928F254D6993DE509 +:104E60006017C1396838BF1C6C34F3BC13D66F7738 +:104E7000632E9E4FFEB27929F17816F929FA447F04 +:104E8000A6BB6CE43967413731EB89706DDCC7EC48 +:104E9000FCAA063DCE63B07106FA2B071B3504EC65 +:104EA00081AA7E03A3C3B8F136CED59330F42B8705 +:104EB0004C204F053D5CCACEA5EB5B08FEE0836D40 +:104EC0003BF34E52DE3FD4D68BCF4193D4ABBD12D1 +:104ED000CFA1CE03C9F58DB4FC5AF91AC8B78966BB +:104EE0004994846AD3AFFA964CF5C46072F47D2875 +:104EF000DFBEE17BAC3C3EBA45A2ED9BD33E62ED0A +:104F00008136D3A9D85EFFEFB541EB57D07F7F261E +:104F1000F1F91C35EE64F4EB3C12413F12D77FA54A +:104F20004C3EBAAD7AB49FDC3C1F9554F3FC5488D8 +:104F3000F8D0727B5A31C6EFAD44D91381FA0C0315 +:104F4000B32708E387F6F1CC6F6DE4F4403284BFF9 +:104F50006A2008F2AE3DC781DF0FC9E73D8610F336 +:104F60009BB1F18FBE78059E4B1279B684D833671A +:104F70005F81F936AAF25A133FA729DB33E1BC7BE4 +:104F8000BB8EDBC1BC7CC4E65F88F304BEA4F6DD47 +:104F9000D11B7E5004FC7476EF0FF341CEDDA8A741 +:104FA000FB8451E45A593A936B833AEB4A897EB7B2 +:104FB000C6E66F013A7CC7326F3A1C319A9B54A9FE +:104FC0007700BCC1E7B480D7644E278ED90C3E472A +:104FD000B54F823CD476131B37D92F7BF15C847F8D +:104FE000B6741B85BB5D62F29B7E94887655A19258 +:104FF0000871C8267EEE55CBE58896CB917F6E1B57 +:10500000C897A9C1784DEF135AB0E77FCBE3E2BF51 +:10501000CD519F9FE87133B8C5739656B902E8CF5A +:10502000A5AB3A524BE940ABF78470FD326D1837AF +:105030003E602B770FD0EFA5EC1F95423E777BE6C5 +:105040008F4A21BEA7757ADCBE98728F9BD17F35BF +:10505000B403BC595A4BC1EFFBB5F59748FB2BFA8B +:10506000F2FD0DF56360703519A359706EFE59930A +:105070007F3BACFF85F9C7302EFC40FAD1F721AF5A +:10508000E3A88ED15D3093E7E393EE690994EE0EC9 +:10509000E739785E0A8BBF1E9EC0FCA8547EB1FC27 +:1050A000D18912E621D6CE66E7626F26918E01FA8B +:1050B0003D3A5968FDF48A1CB47F6B799EC8F47739 +:1050C0007C09B07ED36F8FCA20F7C7B2E76E74EB4E +:1050D0009481183EBE4951976F2E5497BFE5519762 +:1050E000BF5DF19709B16593D97B10E8F55589DF6C +:1050F00047710DB1237FBAA420D85D935F4AE7E7DB +:1051000089593EE54FF97EF1A50A82F5293B8D5B71 +:105110008D50CFFDEF5A5E3FD94D8CD94EC407EA72 +:10512000E9A8C4F3325D1893227BEFB1333F346DAD +:10513000ABA7FDEC9DAF201FA75835E49BC0EBA5A6 +:1051400046B4C3045FB49B287D533C968F339A8149 +:10515000DEDB759EF5D097D66C50402F572618B1E0 +:105160006FED3FC8A8D7969B0CC44ECB071F376383 +:10517000B95C263EC823A120CE86E7519D27D40ADC +:10518000F3A5ED60BEED0E1657D796EB51CFD37E4B +:10519000715D0F3EA109119C7FA58CF9A61C66C10B +:1051A0007774247CFF34E76BAD8684518EA5B37B86 +:1051B000390ED1FEA1DF83BFD2F6A0DFAE50B91306 +:1051C000EACF1B27E0B9A8C0D0792F5903C015DA60 +:1051D000B97CE867E7F2043F0BF942A55EBE2B8578 +:1051E000309014F80F053B05EC0482FB0011B7CC9E +:1051F000348A7AD90BFDA60DB567E7E05278995647 +:1052000085352560A7BCF127A0C3B1E445611A9399 +:1052100013E229E4C516C3C3476AAF196D3D0AEF0F +:10522000C7F20C9B9DADC7840CE04BAD794206E8FC +:10523000CD768747F1C5940BE9766AAE13F045DB6E +:10524000D1F2AD35C7F2E518FD5498C6E4006DE71C +:105250004DA2F01E342919C0BFA38CDBCCC6B57C8F +:10526000BDE3BAE9B8B4DD411B1D97B6DB663284F5 +:105270003509A38D5FA1C078971A97A21D913F832E +:10528000AF03A59320F8C10EDA3448AF3378BEF2ED +:10529000C164361E2954E7FFE49BE9F8985FA6CE67 +:1052A000F7B951DAD4017AFA6953C256A0CF373828 +:1052B000DD1CB6FC433ED8696FCC2B388472267156 +:1052C000790710D10CD28BF246C8C10B69C7CAA1AD +:1052D0004CE5E18D6974DE0FE41E9D079D1F723C55 +:1052E0009D8FF6A5D95B935636127E419F026EA024 +:1052F00053E08B213A8D835FD01BB9A51713253757 +:10530000533B179EC2EE25A495E5C52B99C3F3A385 +:10531000443EDDD8CAE6D11844B86F74FC18F3E6F1 +:10532000EE18E7FF1EC035F7CA4FF0BE22E29E3FDF +:1053300001F67714DE7969C9FF7BF0C6DBF997CAFD +:105340000F1F8BCFC5F8D2AC9D981F1E986DC57CE2 +:10535000F1693C3F36D0A0C1B800DD0FE23EA28526 +:1053600018432097A772BB5C9C5B784562FED6E031 +:105370008B06457D3F517CDEB88279E9C1652CBF43 +:105380007CC87E6F56D07E1FD273FC9C44773193CD +:10539000EDDDF728EAFB89E613F5FD440BED2171FD +:1053A0006F8A94329CBFDFDD4390FEBB6DB9589F7E +:1053B000AE65FA887C83E9A3EE1CA2BA1F699D3909 +:1053C0003411F394785EC146C83FF86FF20B7E9AB1 +:1053D00026A9FCC243E5AFC92FDCE6F0EF023A5B39 +:1053E00058E4CD92283DD6EB997F98D2EBA6088160 +:1053F00074C5D67CD8A7DD445ADFD2E421BDFE02B5 +:10540000E97532A5D73C15BDEE61FC1544212DE8A8 +:1054100075884E0BE3F300FDFB60DC6E47EFEF5B3E +:10542000605FD36FF0B03C6896D7192F1F62E059C8 +:105430002033785C5A2DC2F33AF4130FCFE5F04DC8 +:105440002C9DA612C61F63F14FAA4C82B69261FE34 +:105450003199FD6FC1B8437CF408DBCF8E805B6B64 +:10546000457A9A73078B7F052CCC2E8038581A1DED +:105470007F261F7F4EA7AFDA01ED664A0C0F61FA57 +:105480000F857F16AF9FD9DF8C7970B3AA75C7637C +:10549000ED20212F45DC6D2E6F7FAB7DA60EF2D265 +:1054A00067D7AAE35D73EF64F1B639B3D5FDCC25B8 +:1054B000AB3FC17C4DD2AA03FCCDBD535DFF49DAA1 +:1054C000509C6C02C4C90E713FD020E513E0A3D7F5 +:1054D00093176FBA87D2F9849F149580DFF0869472 +:1054E000C66D4FD0F2B31B2761F9F594EF7EFF280C +:1054F000D46F29C072355CE204FB56E043CA67856D +:10550000E577CCC849007DC2FBBD87E07BB7D9DF1A +:105510003D93B6734FC9C53CD66AEED7185CC8EA4E +:105520006FBED2C65295EF52D05F5C6D66F7351DE7 +:10553000297EBB04F2AAAB7379B9E4D549503E2465 +:105540007D82F73A9C6BB6CAB00E2DE9CCCF3EB93E +:10555000500A4FA478A976F2FE9BD9BC6A4B9E4BA9 +:10556000073EA9AE62FD4CF65476E6413BCD792C60 +:105570009F4B372600FE05BFE5F07D95B02B7D5C87 +:105580004EBCE43DD69144FBF519250F4CD1577123 +:105590008CDD4B6665E7037DDE1C19FCF4D3BC2C67 +:1055A000EFB6CAB83C0DE4E12D7E7D29CCCB6E2C44 +:1055B0003E0479118915956598A76D24B8BE94FEAF +:1055C000C7A7033F5EFD495602109D554DFF82BEA1 +:1055D000660ABAAF56D337E5DBC9E9659796DF2A85 +:1055E000FA360DD3F758F63E85AB02E1FA865AAF8C +:1055F0000D8D13C79FF1E38E2537E02F56FE0EC3A6 +:10560000D78B7C9801D98D79C0A75D824F6F023806 +:10561000F49A089E8FCA963C93F0807185C7887A69 +:105620002F8E5F057C99E0332F190917FCC9C26ED4 +:10563000657F2EF0A364F07AFA9D973887E1A2E3A4 +:10564000DF910E7AFC1106CF66A995C919BE2F11FC +:10565000FE971631DF3EF57CCBCDEC1E0337F8CB41 +:105660003076523C6908EECB5807319F00D7E7B33C +:105670008D3E9B9ECEED36473DD2CFED54A33A28CA +:105680005EC274FF0F701ED404F7C17E6F21F162F9 +:10569000FC9CD247203DC66E12F0C6E3A9650CB94A +:1056A0001A3F9F78FC0CAF5B240D9EE2FCE1D07C9E +:1056B0002F739EF1F68A4BAFF65B3AB97FD139EC86 +:1056C0004F2C84FA5A62F6A03FD123E17EAF96DADE +:1056D0001F20A76B6B08FA719C560DFA13851D32BB +:1056E000169F5CFF4D26B76A9B083FF7C8E6174F29 +:1056F0008FA964E07E78D61A950D0B80FF1BACAAAB +:105700007306B556168F784EC8113250067A7FA8A8 +:105710003C42EF0F94811C8ABF7FAEF622F37B3BA5 +:105720002F4AF8ACF51C2B03BDEFAC1928037956B2 +:1057300067F7FE14D655DC13198FCFBDE91A919780 +:105740007259741ACF47220E7AC4E67F393DC63F9C +:1057500075568AA09F75B5CBCEE7E7CF017A76D88C +:10576000732AC1EF34DBD8AA03BB38D1E13F90CE16 +:10577000E4E8175FC0E6179A523CDE56ED7F5866A4 +:10578000C3221EEEE578B881EBD9F39BB4B80FA91C +:10579000F6163E0DA1A0C09B3A1242BEF5A27E14A1 +:1057A000F7C69DA7065518DA3F6F437DBBF857F53E +:1057B00018279BB05E4394187D39316456DD7F32E3 +:1057C00079A75355BEA2375DD5FECABE5C557D7123 +:1057D0007892AAFEAA374B54E5B2C85455FBABDF0A +:1057E000A95295AF1998A16ABF03F43DC5E3374E9E +:1057F000CF52BDFF68E3F437213E7D5DF43BAAEF55 +:105800004F703F04097A238574FE0B04BD5EAC53D0 +:105810007D4FCD9AB0540E7CCFFE16AC6679F795CD +:105820001463B1FD2DEC52DB13379028E62BB684C0 +:10583000244F9840DE9DBABEB1AF07F17AA97B0F25 +:1058400026B8E66BC05497C6513B632220825C0D9C +:10585000798363F1FBA5D6BF80E47FA9F537B8D57E +:10586000EB6F52D4EB6F2954AFBFCDA35EFFC40AD8 +:10587000F5FA3BBCEAF54FAA51AF7FB24FBDFEA986 +:1058800073D5EB9FE657AFFFB806F5BA67B6AAD750 +:105890003B7BA97A5D73824B54F5F17420E849C8CB +:1058A000CFBC95F7AADB53A46862E842D0D9025F67 +:1058B00003E6638DEF7A48355E3C7D4C203C8FF4E7 +:1058C0002BD247E5386E7F72BAA07AA96A5C32DAC9 +:1058D0001937C073EE046EFFFB46B73384FC8AD5DC +:1058E000EBB1FBE6B1E4DA087DC5F7D163EA2BD86A +:1058F000479B86F7D163D1EFBB84EA591C7C35FA0C +:10590000CFEEB033380E9A993DFF29545D43DBD179 +:10591000361514DE77613E74FC77CD93D10FF21DFE +:10592000D2AB8371EF24117CCE23517CFA895D7553 +:10593000BE6501F1E9B95F6409E0A9C938500E7A82 +:10594000FFC2FCA3EF637CEE48D265DD07721CE268 +:105950003FE30939C5E5C9498803D1F23913F7276F +:105960007A89E28AC1E729EEF7AC9B26A19E255AE7 +:1059700033E6B1D5DD2EA19EAAFB0FF66C1FC7F44E +:10598000DA88E75281D72E6E1F303BA10F0EDD6201 +:10599000FC90F8AD688F7AECB0DEB43F1687F9471B +:1059A000767FB1DBC8E0DC2511B9C289C70671DD9D +:1059B00061FDE17C9BDBC8E0DBA52346C0EF64E230 +:1059C00047FBF031998A3CD6EF24D6EFD15CF01733 +:1059D0009ACD6F7EAB1AF2A9E5E072F4DF7F8FA853 +:1059E000FDF777B64AE8BFFF1E859B3EDD768F1B2D +:1059F000F4B228EF02B8211E00EDE8FB5477AB04A7 +:105A0000FEB1AFADBF3D0FB1765FB2BFA17E0883DF +:105A10000BFE603D857F3683D2B781D2CBB6EF11C6 +:105A2000F41FC6FB6BC769A90681FC311DBB97C07B +:105A30002DAF67FBE2C31EBBCACF44740E38477A52 +:105A4000297B0EF2BE4FC59CD3A07434EAFDBA1F69 +:105A500065B07CA4F6B6C844884B9EE371D787DB5B +:105A6000DEC4B256F6605E26DCF7E588F95EEFA28A +:105A7000F531724EB6D2EF63E48DCEEAC3CB6B1E26 +:105A8000698B60BC53C7EF257B34E35EBB3FC6BF69 +:105A9000F2CE386E271983C49E42B8694FFF4E4F2D +:105AA00023403F5ABB7C2A761F6D70D3FE62F5EE11 +:105AB000C564121B7F58D9F60EC2FD88E4F7436710 +:105AC000867C1236517C1B6438034DDF6FB811E5BC +:105AD000AFDE76AF07EEA11A0B7F06B77C21567EAC +:105AE0007E388EDFCFC5E5E7936DD1C9304E7BDBC5 +:105AF000800A6F5D6D17F1FD9A3652C4EA3FC47A91 +:105B00004D8D82F4738AD24204E27AF2800DFCC198 +:105B1000D43E26107FD6B98D186F30B818BCE4A2D9 +:105B20000BE9639E9DC1003EBF4C4A1FEF2FD5E19C +:105B3000FEFABE4C2BB6BFEF37E30F7829DFEA2918 +:105B40001AB47FC37C86C761F8D373F94964BF0F69 +:105B5000E4803E5DC63885D33E0BD7F1CBF627F007 +:105B6000AE3711CC47D6675AD15EB85C38DD196ABA +:105B7000BCC7E38FE209E5FF7D1C4FF73DC8FC93EE +:105B8000F7DD4FF03C05594AFFCA87E96A1C978741 +:105B9000A9C487CFAE362A080DB05E46E29F40ED1D +:105BA00011D28B8D4DE0A7827AAFEC80D48827AAE2 +:105BB0005D33E1B9A6E26417B0E3DA6B3F8BC01343 +:105BC0006211802F7B0309C155BC98AB40C777F8A1 +:105BD000593981D727CC65E5445E9FE863E54CEFF2 +:105BE0000B523500161747CBB43A6FCA0779BC8001 +:105BF000B073F1FC7E8DCD84CB0BAB736635D4DFF7 +:105C000049F09C8BA8FF09AF4FB31E5F99077A63D9 +:105C1000B6FAFB0D1C0FA9D6E35DD330DEA6AE1796 +:105C2000F1AC64EBF937F1FB2275FD53FC7B9BF57E +:105C30007C641AD4E7ABC77F9CD75BAC2CEF8DCAD2 +:105C40007E767F03AF7F8CD79BA01EC62F64F55A4C +:105C500071DF096FD7C9E118E2331E430C2633BF49 +:105C6000F2963623F2573CBFDD07F773950DF39B91 +:105C70007D2919F5DE86FB3298DC495006BCDE51E1 +:105C8000E4A2A877DA65CC37D0BAF5484F062B974F +:105C9000279C1F87E489D4EA6144C6E4F4A5E89A06 +:105CA00012F005906B59F40FE83AE3FB1AE28F917A +:105CB00073E94D66E28FE583054E5539E5CE74559F +:105CC0007BD7EC5C55BDB57492AA9ECC76229FDC46 +:105CD000CBE9CB5C54A2AA17F765906DBC9D9DB52E +:105CE000D3E54F55B53B5FA824028D9FBA49DCA38D +:105CF000E631827CB8D7969B0AFCF8B3B60A444ECC +:105D00003BE527F6B4F3A71B8C59FA5478B910CBAE +:105D1000CF3B587E7F7B9B879573089EAF6F6FABA1 +:105D2000C1F22ECA9FF0FC699B179FDB6959A1CF76 +:105D30007FA4FD2BB49F1EDA3F949FA1FDC3733354 +:105D4000ED1F9E3FA1FD43FD06DA2F949FA670C173 +:105D5000F329DA0FBCFF31ED1FCA4FB4F9B0BCB65E +:105D60006D2E961F6FF3E3F3B1B6067CDFD9D68AAA +:105D7000E547DB96E2F3E1B6203EDBDB56627D2FA2 +:105D8000A793E7F979DCE72BD9BD03F1EBDF9F217E +:105D900061BB2F9D9F534A157AB92A3FA73F03FC49 +:105DA00002BDEAFC54C01FC26162788C87E36806BA +:105DB000B30F2791C8720B931F18071FDFE75961B4 +:105DC000A1FC35AE95AD7B4E5F14EBD31AD8784766 +:105DD000B99D405C419251CE8E9B43BB7352A4CA85 +:105DE000C2F207D00F43DC143FE5EC5A7246E621BD +:105DF0000DC02557503D1E33AF217C39189C80B70C +:105E0000D1E0FD578E376D692FBB5FA7A62B0C6CB9 +:105E100066F6B6E2FD3AC6B9BEB04C9F2E9F1FEFA4 +:105E2000E99874713ADD2452F976F19B44A1CF8C44 +:105E300026F5FE317D41896A7FA6BDB8862857D1F7 +:105E40007E8BD4FB3C73FEBDAAEF8C190FA9EAF53B +:105E5000AE15AAFABABB731E71033EC7B1B89961F9 +:105E6000F5720221E485DD4F205CE64C368F73929B +:105E7000C27E5F6037FF3D13BE7F79D6CEF1655C91 +:105E80008DFBF2090E562C480C6A400F7DFC8B44AA +:105E9000947F3B9ED1A09F7E22096940DE4CA6E6FE +:105EA00024D45F01378C6BF1AA262D948B89A285AF +:105EB000F255248AFB3ABA7FD164D2F56BD1FA9FAE +:105EC00031D1F2D94CFFB32CBF308CFABA80AF6716 +:105ED00081D8C7AD97E3FDDCC64CF437A9CF257652 +:105EE000F0FD4B8789F90D973BCA53C10E3E3746EB +:105EF0003EA8CD7DE28D0514DFB6B463F814EF1F24 +:105F00005734A39ED7CFCB94BE5A5EF77AAA4FD40C +:105F10007C9307F3385BFACF29E0766BC98F22FFB9 +:105F200074E8843C5312419E0D973D8924661E3BC4 +:105F3000DADEC9935121FA116F325F37315FF94FC1 +:105F40009576C84B2CE079D13BDBD2F2ABC70F7F03 +:105F5000EFE37450482235A05F0B8B349E1074E041 +:105F6000B5ABFC31A6FC2E2F9C0B934B8807C4F2DB +:105F700044D285F729C87FD5623E9A7CF01AA25098 +:105F8000FBD86A0D9360D170BF84FB75BECFE5FC72 +:105F900067F66A9C8F9C25EC260FE874F299D51B56 +:105FA000013AFCAC5BC7D8F4B8BABED04A50EF2D6A +:105FB0002AD4871409EECBEBC27B40E52D12C9C869 +:105FC0000138A6B9E7837EDF6B413AB6AC2FC79F95 +:105FD00030B859E3AF40FC0E287B35C2E8A2ED9AF9 +:105FE00027EBB7823D3901F06205BCDC915F0D43C0 +:105FF000E717221E17F2792FE4F3E8C81CC23F838B +:106000008778BC701FEFA26EE18F52CFF3F1D2AA56 +:106010006FC3BDA2ED112DFF9922353E57E92253E2 +:10602000E64BC37051381766825C01B8AF820FD857 +:10603000FC9A9F91C8C61C946B35686F9469303F79 +:106040003D9E2E9B3299DC8F66D8D97DE4EE534875 +:10605000CFC3E5936F2C48C2FD33B35B6C32CB8F5B +:10606000F47A9558BFF72AE15FE4E772CC1CDEA111 +:106070007B0527B1BC602B89AC87BCB4B1F6F52B8E +:10608000327370DCE17D3DB55D203FA5CC88795C45 +:10609000AB443EA172549969634F385765E474FA72 +:1060A000A84D9DF7B39DCF6F3B5F8F41A3C87BF297 +:1060B000D616C79CF3A9EBAF473F9688D30E72FF65 +:1060C000E1A0591D576DE4A43078A8ABCA0CF1C10A +:1060D0002E16A76DECBF99DD6BBBEFC7782F30EDA7 +:1060E00053017AA8E7EDEB57AAFD580B77FA915FB9 +:1060F000E3FD64F17E318A393DEC1FE3FD625B33E1 +:10610000F97EC2438A210E7B6275DE6133EC7772C1 +:10611000089E0F1FA77D01EFDDA6BB812EB84F970C +:1061200014B1FBA3E2D7FF54961EF1B253ACEF7843 +:106130002BDAA53BCB981CD879E0FC2DE3693F2BEB +:106140007324D5F98095393A5CA7B7297DC3B397F5 +:10615000909AD1EE293B94A9F96A72EF5AF5EFC1F2 +:1061600034F70D1CB62828FF5E03BA1F3CFC7942A9 +:1061700011F251147FBFC408C23099C10DE7B37644 +:106180006B3E99174B0F6F67CA58FF36A78B2F0DC1 +:1061900057B51AAEB3456FA5CC6070FD0EE4C6B915 +:1061A000F0F194587B46C0B57B8CDF03F8F0ABE28E +:1061B000A942AD1F62F074FABFC3D36EFDE8F0FCD4 +:1061C00095C3F3B343EC5E9B91F55F519F75ABE1D3 +:1061D0003DFB7C640E88490AEF5F117FEE9329181E +:1061E00013E6F8EB2DE5F459CAE58F07CF5091C0BF +:1061F0007B57631E66AF4C926AA15CBE007FF72C92 +:1062000093EFC3021A3F9EBF21EF1946957FD764D3 +:1062100031BADE9D2E8D8A87D22C36CF0347EAB263 +:10622000C1BFF1D83B0602726133CFBF7ECCDE6BBB +:10623000847BA6051EA15C429F017D741128BCC70A +:106240004A3F332AD651C6D3B0F1D6C6F18D184F86 +:106250003CA76415327B553AA48573386BAF7D0B30 +:10626000EF7F5B5B2AA3ECFDD2F85F1D87FFF05B3D +:1062700029B7307A999245E16B91FE90F06D5A0EF4 +:1062800048D17F2A827C15BD1FE71FA078EC91467C +:10629000E2292D8BD18B989F98BF80DB76DD025C45 +:1062A00007DBBB06541AA5BCBDD017895CFFC1BC77 +:1062B000505F5C2BB3734C6532AEFBDA8AA978EE83 +:1062C0006C37CF17895EA31FF577441670BC3D76F7 +:1062D000F1B711B84739D8AFC3FB3F883CE0BE15D2 +:1062E000EE1FFF8D8CF789537AAA81FBCC0E1C39E7 +:1062F0009F00FBEBF9593A847B3E97878317B535AE +:10630000781EECC867766D0CFDD76569B97D12897A +:10631000C039AF3525EC3C8B95DB03D623271B001A +:106320007E6BC543062986DE66651910AE35FA68B0 +:106330008A87F617D8A72561E6FFC17B1987CEB3F8 +:10634000DA191E5A4A0FA1BD60ED67F735D66529E7 +:106350004CCE52B8F7D2F7E6899FD9EBA1BE948E06 +:10636000973BFCBDCDCED6D35CC6EE4B5A7BED3F02 +:10637000DBE13EC844F81D47D8EFF2790AB89272C3 +:1063800035BCDF482417F8CB2E63BE5A6FF85E2366 +:10639000D8FB822FDECAD562BB47F93989472B0A61 +:1063A0004370AE4CD0B135DBFF4016CC8FF2C50B3D +:1063B00068EF447CD3103FF662C833DF2545E632F0 +:1063C0003B446F073E2CD46854FC16E1EB269E54E8 +:1063D000FDA3DD733FA75DA1F73B424602E74DFEFB +:1063E00078716622D8A71D19C2DEF31A015F9B25BA +:1063F0005F620E8CF32F5ADC0F1E3872BC01C6EDA3 +:10640000A0F302BE7DF875EB6AB0533AEC5EE4533C +:1064100031BEECD0F0F560FDECD67BDF047F64D4B8 +:10642000C1EECD3A38758611E89FB6D3403F7FA0C4 +:10643000FBF7F004E8A71AFD060BEDB3A6C3778BB4 +:1064400088FF11B06F17756B55F7833CCCE5C5C25B +:106450008B16128ED92F2CACF80E9E6B5C78310106 +:10646000DF3FCCCFED3FCCCFBDEDE2F878993F5F79 +:10647000CFFA8AFB6F4F9CDE4AFEDD8E3AC6F7BB31 +:1064800060FD9AA5013DA8FA35533FC7F3647F68C4 +:10649000B393B02106DE11F34C22E1987187DA5DE7 +:1064A00034917052ECFA32FA1D9EAF15EBFFD0E634 +:1064B000463C8EDDFF38151E87FBCF53E17164FF2C +:1064C0000558FF87B6C24BF43F798CFE7354F00F2A +:1064D000F79B8FEFCF1DAC7BD642F9EE6078C5C637 +:1064E000574BE1F7F70CF87B1BA4AFB70ACFB9EE17 +:1064F00022780EFA81FD7F7A1FF2521FD8AAF7C0C8 +:106500001883BAE83CCF287A269FD88370EF9C780E +:10651000BE9D9587EB1CFFDE2887EC90676A2C9464 +:10652000EDA0E78C24125A01FB975223CA3911DFE0 +:1065300012FDFE3453AB92B3E27EA1469E7FD86833 +:1065400061F1AF26ABFF2CACFF124D57CBCF681FCC +:10655000A70B3BF07C3B210EDCD788F88E0CFBC5EB +:106560003C707DF9089C0B9B97E3FF0CBEFB091563 +:106570002B10EFD15EB1CD0FF9798FF37DE4E3A657 +:1065800088DB13233F75D9F257B31BBAE2E8B7ECA7 +:10659000773BC28C7E75D940BFDAC8CFEB72E07C06 +:1065A000E300BF674E41FBB9AEF430DE475927FC2C +:1065B000022BE3F356321D604F8B785402E41782AE +:1065C000DDB086DD53586F61E5FA5F27E1B917BA90 +:1065D0001FB214819CD9AD65FE221E073BCF611E00 +:1065E00034AEC902FC0EF27C97F3FDAFE1BDA7E724 +:1065F000578E473AA8FFE50FF11EC3DDE94C9F0D0A +:10660000EEB3A13EAB3778CAE15ECDDDE9CC6EEDED +:1066100095C309253176ECA3195528A73F5E395E4D +:10662000131B27199FCDE4C21AE1FF94A3E570CE96 +:10663000EAE3D2F03FA13EDD63C2DF1BD3ECFD53A2 +:1066400039DEBFBAC680BF6351B577E2BAB9B05F71 +:106650004C90311F5BB3D784F09C5DC5EE83836F94 +:1066600041EE35EF1D87BFCB566F8962DE64B3D92B +:106670005300F1C1FABDDFC0DF9F38F1F8C42C90A0 +:1066800083C793952CBC6FFB718A743AEFE3FB26AA +:10669000B0F79D57E3B96ADB1A8B7F34FF88D04B84 +:1066A000F1F7CDED4E2F3ED707F89968F4801C5EC8 +:1066B00038E45F67F707D6BF199DA524A0FF06F34E +:1066C00017EAEDA7F0F71DEBBB8FDD49303EE9423D +:1066D000FA15FBBCF871EBB9FEDAAD8FCE83DFD5CE +:1066E000AB6FE7F8E7BFF759AF29C6DF9B14F85F38 +:1066F00013771FF3F738DEC5F3C41119EFB9A47689 +:106700004516F88F4EEC3720BD9D583319EF5710C2 +:10671000E3D55358ED944F8F3B9529B0BE0BB2157E +:1067200036FF76B67F15EFE9F811F8BDCEE83E2DBD +:10673000E6AF0DDAA30910C714ED4479683EFD5A9F +:10674000FCBDB7DDE90770DD295D11A02BCD2F6DF4 +:10675000A8B703BF64BF1BF7712909829F34F88E65 +:1067600001F77B07F719D09E1E7C979DCF1F71EF15 +:106770009F359A05F7DC067E390EE5DA6066740B04 +:10678000B3BF4D78CFE4E051FFD53C5E9CC6EFD15E +:106790004C03BBEFC23E5318EC3EFAC4B843906CB6 +:1067A00073E3FBFD16BC2F883ED9F924698F1B7F4C +:1067B000378974F1EF23F8FD0359FE0920A71FC89C +:1067C000A3FD5BE1FB93D8EE42AEFF4A8C591192D8 +:1067D000CEC74BC77E33FDD9F85EFACCCD7E0FA86D +:1067E0008BD747B03E60F05F8DF3F8BD8DF48C32EF +:1067F000CFAF7A5FE47DD949B88E026E8A67B42341 +:10680000E3F1D293CDF69F021FF17439B49E9780C5 +:106810000FFC3278BFC03EB68EAB26EA993CE99CAD +:106820008CF632DE30149327B87CDF074897833A22 +:10683000EFD3A097A2477584DDC3482D03F05754CA +:10684000B076F516E6F710709CE1E7071A3B591E83 +:10685000E199E73EC89A6F85F3F31FA8CECF0BFFEF +:1068600021ED2401FC33568F925057C4EC762DC293 +:10687000C57E8F6E8D4EC1DF0B0C3E3E11FD122783 +:10688000F4CA5EBC0776D5151AA0276D3197BF4FA5 +:10689000B07989FBDDC43D6DF17819C866FAB2990B +:1068A000F8EF823BFE8F132585074BF1BE4A74FF3C +:1068B0006B20CD52F69A587E3BEA8591F742EA2F3B +:1068C000F17B82FFBBE553B05665809F6002E8D53F +:1068D000D376B67FC45B2240BF6BD93C3BE003B8A4 +:1068E000FF82F84E835EC45B25281E4E4BAC3E9E55 +:1068F000CE84BC1B810FA01BE817BEA37D7F9E9D8D +:10690000C3F63F76273F9417D4435EAAD057014978 +:10691000D6C07D0F271D4A02D0E5C9CE3CE772C81C +:10692000F7712829B1F676E010C17B0E1438FF7399 +:1069300035FC2E92770AF805773BD5FE8878785E8D +:10694000A81C40FDF35F98C6C553008000000000FE +:106950001F8B08000000000000FFB57D0B7854D5A8 +:10696000B5FF3E73662633794E1E8484409824E436 +:10697000018430090F4141074810156878092885BE +:10698000930710421E88B6175BDB0C24205AB441D3 +:1069900051D18B76404154B4414141037700A55811 +:1069A0005163D5566DCB0D88BC1F31A897FFADAD97 +:1069B000FFF55BFB9C64CE90A8B5B7F93ED8D967CC +:1069C000BFD75A7BEDF5DA3BDF7C433FD7096175D2 +:1069D0002B42F41022CE6D11629810A3DC82F34298 +:1069E000D885C811FCF38DCA89DB3A5C8885F88D9F +:1069F000AAAAF9DAB59EC82BEB2D5C1FE375467782 +:106A0000F1BDF1B5FF50F228B3214C0887FE3D5D82 +:106A1000880F311E8D7BEA90DDA70C461A2EAC093B +:106A20004254AC75FA451AA56F4ECCBA53E685426E +:106A300075C76C5C99D84AE3966F2ACA1291B21F47 +:106A400041F3AAD0E7559EEACD52870AD1F6A8EACB +:106A5000DA84F6EB559E8F6AF3B81EA5EF27D6DBD6 +:106A60005CCBA99F0A7D3E277A6BD1C5B994B70A42 +:106A7000ABBD80F2562DDA45FD2E78542DF677B158 +:106A80003EAAF781B5A00BF8604D893A7C32A81E6A +:106A9000D66994E3BFF7687257D1FCC2E977CC633B +:106AA000A3E2F7D1FC4EF4D1E6217FFC9330B18212 +:106AB000F2EADA45D1EEDC2BE17DC2A1457B720121 +:106AC0005FB91E039EA1E318F0BC0878C620BDBACA +:106AD000C54BF0AB7D48F5A0CEBEE64BD180DF982C +:106AE0003D4547AEC1F7B561228CDAEC3B9CFECE4A +:106AF000AD348F8BAB55413D8AD23D198982C6DBBF +:106B00006EF97C2EE073BF4DCC7A91D2D2B7A747F5 +:106B10005B28FD46A71FF5210927356A7AF47CAE6C +:106B2000DF3EB998F2C7DC9EC482A07A3FD6E92C3A +:106B3000145F656BFF168D712AD6D8785D065E2EC0 +:106B4000621D34BF8B8D11FEE504978BBDDBB85FF2 +:106B5000034F46BF15C083414F546FA5DBA58FE39C +:106B6000B31747115CD3B4E19E2EE864C183342E81 +:106B7000FA5B1FE575E67DFF710D7874E09B962545 +:106B80000CFC038F4FA46DBC97BE59DEB30AD193A2 +:106B9000E0D0787DAA42DFCBF6840985FA2B53DA60 +:106BA0008E28099C77FB14AC7FF13C8C57F67198CA +:106BB00005E5C7F75E9FC7F30AC12BC129B52B7A3C +:106BC000BF98D696EA0982DFC53E6D7379BE067D11 +:106BD00074CE9BE751BB374C605F5C4C237C4676A0 +:106BE000C2B101F819C6F55D76A66F6F1EE0D7B188 +:106BF0005E57C87A5D21EBFD40307D0B8FC6EB29D7 +:106C0000FF24CC82EFE50FDC94E5A6718EDF3B8E8E +:106C1000D7753CCE9B87FD753C95FACFBD729DE53F +:106C20000FD03A73BF659D8D4EC657B7EB8C6B7B0B +:106C3000427CCB3A37EA7468ACF333AB3BDA8AFA7E +:106C4000BB55B19C8A6AFB14DF7F8DCCBB56D0D07C +:106C5000B536490FB56B23FCC0D78566DB047F6E64 +:106C6000271FA0F1BE273D58981E8E8F753F3C020E +:106C7000F4759FEAF2B9019721EFFC9CF2C7EF5738 +:106C80005D02F9B1127EC40F2CE00FC7538B27733E +:106C90007EAFCDB582FAF9B4F16F7F04FD5CDC63A1 +:106CA000730B5E5FF1FDB390A7F982AF115C6EC606 +:106CB000B854CEEB57EF19D68872F1E86057A6BBEF +:106CC0000BBE1402E78A35AA691FD201C1E3D53E83 +:106CD00090E2C63A0C381387CD9A3AA8131EC84FD3 +:106CE0001FD409975ABBD09AF8FB12FB944141FC80 +:106CF0000CF04997E744FF3CC9C7D2A283F673C89A +:106D0000FC42F98F51CF48FFD2C157CCFC7851706B +:106D10009EE05019925F1CC237AA42CAAB43CAB761 +:106D2000F7FA9CF940E8F813D3E4BE31E058AAC35F +:106D300071BB45917CE43EC5BF897E2DB5BAED4B54 +:106D400069FE2F8E11F3D04F995538AEE57DD9CE1F +:106D5000EB2BB58A86B0027CF7703D63DDD45F43D0 +:106D6000581CE5C3251FA27A13EC417983DF1AF37F +:106D7000094F93F030D2C55B9D8DC783E059DD1478 +:106D80006BCAD7EE4A6E3CEEE8CC2FC62FC9F46F23 +:106D900022AD7E38E0227FAA77B51E8C20FA49B258 +:106DA00068E169D4EFC583FF1B9DEB66BC0F2F26FE +:106DB000FC16A8E92F1DA6F5B6ED563D9BD0EF9B1E +:106DC000F2FC115F5F7A781B7DAFD99B21EE75775E +:106DD000AE3F148E17775D8A4EA7EF170ED9C30505 +:106DE000C901A5CDF163EDD1BCBFBA84BB5B87BB44 +:106DF000D1DF056B6BF494A07A17446BF4D4207A3E +:106E000029DD75A94EE431FC7C6A101FFF744F8F99 +:106E1000B12A7D2FFB7DAFB1164AC7E9FDDE6F7346 +:106E20003FB986E6EDDB1DE6D94CF3BEF0E62C0B50 +:106E3000DA5F78B3424F7FEAE5F4B34F53317EB463 +:106E400045D2BB31DE8834294F95598E3E311AFC2C +:106E5000FFD59E69F5699DE56596822CE0799BAD2D +:106E60006D2EE67D4111AB95B8CE7EC6A5B9B9FDB4 +:106E700085DD279F007FF8F4FE3E05602B177667BF +:106E8000E769547EE1E321592EEAF7C27DC91EF07D +:106E9000856D36F74F99DEEE89F260DF1BFD619C50 +:106EA00025E87FF755C335A41FCBF9523E4F93E336 +:106EB000FA9482CE7EA32DEE5F8F02BFF8BDCDB3D4 +:106EC0009992A57FCFE8198BF5613F778187B2D57D +:106ED00061C26DE2272B78DEA5C263871C84721124 +:106EE000445FE5A298BFCF6F347F5F407C02DF171D +:106EF000AE377FAF108DAB5A697D8BFCE6EF82F623 +:106F00008F2F11FBDAF869E2F37EF1D66FC24CF5F0 +:106F1000844FE70F0EE6C7A5B41FC1C79E57FCFEFE +:106F200015C0EF3D2AAF33745DCBD3D2781D8F44AB +:106F3000FC636E6B105E8F59843589E07ACC2E1C11 +:106F40004905E847089CABBE3D61FECDD4E4DEFEBA +:106F50005FA59632DF4BB2E03CB8C305CE47FDEDEE +:106F600039998A7ECA5617795B83E677D1E67DE444 +:106F7000E79057DF237E4DF58E8DF5378EA5791D71 +:106F8000BB57F5D47731AF33249FF9E3091EF728B7 +:106F9000C23F84F2CF9C4C2D21BC9CDE7C32B534A8 +:106FA00098FE15312B981E8D9466C2EB82AC89F445 +:106FB00018AD05EB09ADD7895FF37C0D783A55B173 +:106FC000A42B7A7814744FE5397F5705E4CE9A3DA7 +:106FD000363FE83362E3170FDF0AFA6CB6B940DADE +:106FE000B57B542FE474B15BF567E21C6BFE34BAD9 +:106FF00012E7CCEE212E3568DD740E17E37CB9B0B4 +:10700000EB5262592EF73319F244ED9E873CA0DF14 +:10701000EEE6F15C9AFAAFF13FAF99FF9DCFFD200C +:10702000F146F0818D27B2C0DF890F3E9786FD992A +:10703000F5B51D79215A8783FE687E2CBF5FF47FEA +:10704000C5F2A5A359F5FABBC0C39E343BC3FF07E5 +:10705000CF6F02CD2FB1737E349F3DE0CBC63C6B2A +:10706000DC6D769CB3171DD179E0A7B4A089F989AE +:10707000FAF9E4067F2D9B2888BF16EE9EBFC20951 +:1070800079A151F1400F286F56F9DC2ADFA0FADD13 +:107090008497C2ECBBF63B219F3E44E5D474BC3AD6 +:1070A000EA8FB3A8FEC2FB54CEEFDBF8D33FDA8001 +:1070B000D70D3611063C86476FD2C7637968913E7B +:1070C000BF45CD379D56A0B7EC513D01B4DF1CE55F +:1070D000C1F7B2D5B663C1F4351FBF507FF3D72BCC +:1070E000FE401AF884B9FCC2309FCE2742BE6F5CC6 +:1070F00035757F02522BEB898BFCE672FCBC4EF39C +:10710000A9D57FDF9AB9A617F073C129440BF6AB56 +:10711000B595F51D11684D051E2FECFE2C1578ACAC +:107120007DF57FB24417F8EBD84FCD510927228463 +:10713000384BE7C63716D0FDA5C9C55DD47FB18FE2 +:10714000DC175B6DBE5E9063F76FFC8AF9C1C5DD2D +:107150005A5F5717F4DBB95F7D4E4B12D280532034 +:107160001DDAE4BA11FB84E4C17B411F9B564DDD5F +:107170004479E76B364842A2363392F70BF6C7FCE8 +:10718000A07E8D7DB2157C01E930C91F5EEC23E540 +:1071900084D5BABCB0755FFBE4CC2EE6B33ACD26FD +:1071A000CFDB3E926FCC4D2B0E4F879C61F1450398 +:1071B0001FC2EB7527107C159DBEEA972D51F03D3F +:1071C000493472DA5B3471FAB8105A24EA0B8F0B27 +:1071D0007016A24F2CE0C77B9ED7AB31DFFC898EA7 +:1071E0003BF06AD0832F56F837D3EFEA46875063D7 +:1071F00020EDB546A351D4A0A9BFEE4BE5B60F5480 +:10720000D69FD43E063E3D2EE0F7CBC8E931C1F80B +:10721000DB77B87402FAABDE497A2EF5777E874DBC +:1072200004A0575969BF503DDBE12FEC69E04BCD1D +:107230008A80BC5C4B797CAF1D65F5FA83E0929740 +:107240002EE1919A9EC570BB60F51E9A08FA73955F +:10725000DA21D7DB0E974FC079634B2AB5635EFB0B +:107260000E8F75A4016FB156DE37AB9A8D715B5CE2 +:10727000E83F2AF6039E6F43AE454453BB868FC258 +:10728000FC0C4C87E443613A5C1B02850E7717F8CF +:10729000F189C2143182CA77A81330CFF3AE5217E6 +:1072A000F0688B957687309B7702F49AB0D8B878DF +:1072B000CC6F447A06CFFFABD8253CCFAF48BC801B +:1072C000BE41F27A31F20DBDCB55867DE323BC8FF2 +:1072D0006B1D72FCA83D2A9FA362A443E7DBEFBBB2 +:1072E000CA689CC8BEDA24D083319FA861AF0BF076 +:1072F000E71C8B85E5B3863722D7802F18E51BD294 +:1073000025BD19F858996075817F3CAED3E74A577F +:10731000B1A320689DB61E161D5EC50EC069BBBD1B +:10732000F810CE9736FA8E73737FD25407F414AAEE +:1073300067413F27EA68C764A3DFE90EC07741428F +:10734000E978B45B2896ACC27E5BB85E1581203EBE +:10735000DB6093E32EB81C2102433AC75D40F8E39B +:10736000F697A3F97B8353D66B8892FBE7CE7429FB +:107370002FAED4D3B57AFA83F9BAC7CCD7CFC7FE2C +:10738000714BA9E4EF77A653BFD54AEB788826ABBB +:1073900092DAED80EF893A97088405CDF78A75C6B1 +:1073A0008B40D0381DF52E3B45203E181F6EC6473A +:1073B000E77A23B9FC445D12C3B1FBFE534C70EC79 +:1073C000EC3FC304C72BFBCFE2F2137539DFD1FFCB +:1073D000C06EFA4F33CDBFB3DF7EFC5DECD2FA82D4 +:1073E000BFDCED227EC074D3CA7626BBA2FD067632 +:1073F0002FF1719880DCF79553CB7605F1876DE915 +:10740000765D9F0BA480DFFAC43A4E6B775D1A8FCE +:10741000F66EE20B6CE7D0CB6B451BCF13FC02FA88 +:10742000BD48B6BAB97C97960DBDC89847873CF35E +:10743000BB489F85F641D89EBF47631F5FB4B64DDA +:10744000867DAAA9598D08DED707F4FD31B6CF177E +:1074500079B0D7D5A01DF1BD9FEE5D9C0DF8D48409 +:10746000B5E561DEFBF7FE2D0FE7C8577B16F7C5C4 +:10747000F7AD549FE50F7B5B8D27A8BF7EC2E5B3B8 +:107480008CE84C9BF5FD1FFA7DEB9EFA5E98C736A3 +:10749000D83D482EAC59F656C6F178B021EF83E0BE +:1074A0005F82F816EB43BBA6A96320DF7D48320F4D +:1074B000E587EE9672C3D03EC26F4983DCF7E12CBC +:1074C000F0899A61761754E1F0FC1696B7C38739B4 +:1074D0005C389F9FED93C1EBB3434EC840FBA2784D +:1074E000A6E754F1AFC96D1B42F64FE00F35DB68DC +:1074F000BC6AB575F23885F7D131F0A99AB7BF7873 +:1075000047D75F13819F5A8C4BF0785FEF27214359 +:107510003B897A9AA3F5BEABA8DE8C9B9353A11F3F +:1075200095E8FA9998484019C9FC6810EC20579ED4 +:10753000DB520F7A4DD134C0C197ECF0E0FC1A98C1 +:10754000221CC971D8D0FEF4A934EE57E916C32E17 +:10755000AA60DE03F4353DDFAB69692C9F93FE38EA +:10756000D0D13F3BAE25C3FB77F00BA3FE8737DFBF +:107570003A48EBE2DC30E479BBBDE936CCB3AD3A56 +:1075800092F54798F3D0EEC99BC3022AEC8AB6C89D +:10759000D5D0E73F8A987BB007C1E3FE282D228330 +:1075A000DACD9A79C32AE495FDF1EEA5A0E792D64B +:1075B000E1C0E7D34E2D2683C6AF72687D1369897B +:1075C000E7FB68D93138E48BE3259E44F1A0E22E35 +:1075D000E72FE753A2C8F10F476949E8A7C4D2F2E1 +:1075E000C455F8666D617B8368E8C1FD9CB78B8AE2 +:1075F000AEE47F030E47F475ECB3896B2FD3FAF634 +:10760000AD8DF1D4D37CCBEF9E39B796D2F996E20B +:10761000C4806A9A7716D655E52BE99B4CF2F3792C +:107620009B3EEF65FABCADAEACE0FD1C3AEF7A4391 +:107630005EF985C2FA20FF50FE155FACFF5ECA8777 +:10764000592E7D300DE7D6200BDB493684D3DE2260 +:107650003DF25D7D9E8FD3BE73C4F1F7D5F89E14C5 +:107660002EDB273D6CF1C37E503C7637E3E9C99AA7 +:10767000488F4A639508B71D725099F0B25CFCD9E7 +:1076800098BFED69A575156668D7016EF3E22DA95F +:107690001FF03CB48153206F8D92EBF8167993D78D +:1076A0003155B86C2C94893516C81F535D7229F377 +:1076B00015B93FA609AF0DE3CD101AD7FBC305BB23 +:1076C00017FAC41FA00BD1BC670A1F7F9F2DFC9C1B +:1076D000DE2A025CFFC7A295F306BC893EE6254878 +:1076E000FA38D95365F8DF8C79BF1791D76719AD90 +:1076F00063CA23D999AC5FADEBC1F0F9AE794FD134 +:10770000E986F6EF3CF483FD3B9DFA997A63C8FE67 +:107710002DEC61E033F3DBF6514B7B87FE14994C83 +:1077200070B85E47E9F5DEC5AC3F15A991C247F8D0 +:107730006919A5FA21771CF22E4F48A075DCFDB916 +:10774000D4837EB75CBC3D84CA7F374615F5DCD256 +:10775000CBF2D464BD9FC9BDC79F869DF5B00824F8 +:107760000CA5B9175DD65E8FA1F94E56B735C45238 +:10777000F984DEA4C704F1BD1B12B65BA1D7DDD826 +:10778000CFFC7D62AE59DF99241A55C079F250734F +:10779000BD7D800FD1D78A0CA9B788016280EEDF4A +:1077A00063B9FB477A1FED132FD9E10B793543BB42 +:1077B00007705C3AE9B3B9185758E57A6ADE51D9CF +:1077C0009E778CE42C2F9DDFC7EBE8840893F208AA +:1077D000F2A7486E407AA6CECDE9393AE7517EA1AC +:1077E000CE23EB67143F807D56BAFA732BF072B745 +:1077F00053C2F96E67AA1F76B58AA6C6F1985EE5F0 +:10780000AEA68348CB03C5E371CC2E38B4E420D2B6 +:10781000BB3BF4B6250EDD5FC0F3BF5DA7D3DBA392 +:10782000A6DE3488F6C9EDBBA5DFEBF63E53A74DC7 +:107830004A40DEC6F9EEE8A8FAB22234DA22CFA82E +:10784000DECD58B7B7F9E8C1785AE7C9BA113CFF9D +:10785000D3755E9EFFD9BA099CFE3DA3F839AE27C9 +:107860003E67796CD2B6A3D614AA5FE455BCD8B7EC +:10787000D77A85DF4F74B1DE26CF81F5740E601F95 +:107880008F1934F5F13B30E90C6D27DACFB871511F +:1078900011C6993CA2C48A7A33BF16223EAD934EDC +:1078A000BF8BEE8DF557EBF83BBF5761789EDF1B22 +:1078B000CBF06CDF911103F960E9CE8C9E48896FA3 +:1078C0001A7A6F04E0D77ED9C2F36DFF289CF58E3B +:1078D000D0F64B770EEC897A6709DF2248DE3CFB55 +:1078E000FC7FB883CF95B3714D5F7D02FEF657C91B +:1078F000DF48B239F118F85FEF5E1ED0CB055DCEE0 +:10790000263D2302E75F8D6E57047F42FE6CB8B4BC +:10791000E70E7F21652CF617C673139CC31C19B99B +:10792000C787707F477E46FDBDFC589207FAEFB9C6 +:10793000ED8FA463FCAD4DF33F798CFA3FEFB7F8C0 +:107940006C744E9D174D175E051F7E2A92ED7B7756 +:107950002B342F9CC39B7B713E47B1862FC3392CA0 +:10796000FCBCCF7314B77519F1ADAA171FED057ADA +:107970007C8D603082CA5F5B1BC17CED359BE7C8A4 +:1079800032F4F7B8ECEFE9FBEF3CB60BE97DD50537 +:107990007752FA65461CE3A1FC814503D09ECE795F +:1079A000914CFD3DF78A1280BF6AD0BA7D2B926957 +:1079B0007E83371CB5F4A234FF29A51EE9C03E37EB +:1079C0001E82FDF96F196E6E3F645B9A9A826DD9C3 +:1079D000CBFFC9757CFE9BE582DC759F8FED253A58 +:1079E000E583014AD3998D34D7B0D48F0A348663A6 +:1079F00023AF6767F3B4F76F155807491E98778967 +:107A0000DDC3E791DFB711783EAFE57858BF2BF6BD +:107A10003D0A7A3BAF257A703EBD4CFAFCD5A87F73 +:107A2000C4CAEB7CE5A9F7A261DF89213DD909BF72 +:107A3000487EDB78D4AFEEE316F087F579E2FA09F9 +:107A4000804FCD8E9D1BB99F2A8707FA6EC5CE4BFE +:107A50000753202FDE203C99A0C71D32FFAB42AF59 +:107A600047A5A5566CFC52E65B8A395F4CDA27FCC9 +:107A7000FEA24CCA498FE8E7A068CD637EC924EE18 +:107A8000EEC4D7AFA818E5EBD37CC9B06F1BE727CE +:107A90009D7BA9FDB065ECB27DCBD85B53192EDF81 +:107AA000F3DCB3EBE797D1DF2376E173523F30DFAE +:107AB000C09EBEC12ECFEBCDC467402FC6794DE32B +:107AC000E6F593EDBDE0AF29AA326807C123E59141 +:107AD000309637BEEFF8B36256F1F96DC85BB5E189 +:107AE000922FF2D941ED5F88D2AEEE370C76327923 +:107AF000DE0BAB3B17F2C8E351DE6BFAB1BCD59697 +:107B00008A35D0397A1DE653A392FC9511247F451E +:107B1000C67DAF733410E52D42FBEF5B7F6C04CD67 +:107B2000330629F1EF68A486DE455A4897FC397D73 +:107B30005B13F8F34361923F470D61BE64AC33744D +:107B40009C03C40734E23B6FD039A3113F181739A7 +:107B5000C6CA787DDD527590CEE522390208DA1A60 +:107B60003B94F3DE28826361A42AB42EF4472325D4 +:107B7000BCCDC73AC7274498EA1525C4DAB18FBFF0 +:107B8000EFFA551D4F6AB83CBFD47083BFBA137467 +:107B9000BF7DC8FAE57A6F770E63BE3A56F97EEB81 +:107BA0002EB215DF093C8F8BCCE773735CE4942312 +:107BB0009AE075D4E17BE87A43D7251CDF4F8EFA33 +:107BC00089227C16ECC7CFED6C776BB6B53EF75BC0 +:107BD000826BF3A25C0FEC472FD3BE70809F4EB533 +:107BE000B39CDB0CD992EA37F770715CCB6BBADFD0 +:107BF000DC375B6FEF147CBE34CFEEC57EF45E6184 +:107C00003410EC48F5D26FD26C5BF216CEEBE6E5A1 +:107C1000291E9A8150C1EF69CB7CE497FCBC5E09B8 +:107C2000DC0A7F81EF73BB40FD75B1FED5E9945F3F +:107C3000F78B0C9ECF47A48FD762BC8A70E65BEBB4 +:107C400062BDC971049F97FFA1F279B22E9FF29194 +:107C5000CCD7D96EB36E8A37197EAD041D6FEB3663 +:107C6000CAF25EB093A23C4DB6FFC426EBDFA2D7AA +:107C70004BD0F1FBB14EA7B4FF993F689323ACA062 +:107C8000FF77FB95BEC6FB467893E1177AAC3C9331 +:107C90006D98B754DE90C6F4A4DBD366E9FCDCE84B +:107CA000170D1CC3214FCB9FD9F3373B41DF332A3C +:107CB0009C47211F7E54B1220A7AFD0C4D0D842170 +:107CC000BE6A7A91B743AE4BC7B85E396EB9A11F91 +:107CD00006CA00DFBD6D0E712FCBFF8121C1FA9660 +:107CE00081E745FABEAD6E1AF360B07E5D6927FE8E +:107CF0003318E5723F57456ABF077DD5EEBAE1C13B +:107D000060BDFB54F94379BCEFF471CFD5791F3CCA +:107D10009E09396F02A7C6B81DFA11F049FDF6D5C4 +:107D2000CF73DAEF3E0BF0DAE494FA92B5EDE38527 +:107D300094AF9F3580CFF709531D5ED8F5DA77846D +:107D4000F961AFAD9F15EEC5BAEAF744F9615798EE +:107D5000A7EF1BD2BBF8BB6FBB8DE9ADCAEE7F6648 +:107D60000BB5ABDADB9FE989E895ED96BE57236446 +:107D700079B4376DE55094F764FA79CDE68EE1F287 +:107D80003755C1E5E181AC5882779B533B8575132C +:107D9000BDB2FDBCCA2EBF1FD1E912FA25FBFF966A +:107DA0004471BF42CF6B3F8F677D4F58BDC9F39180 +:107DB000BF7D20AF47B3CB7D216AA47E78C425E781 +:107DC00075A4399EF785418F478AB7DC939580EF7C +:107DD00024AFD2FCFEB24C0DC01F6ED09F32F5F224 +:107DE000DB5751BB4F5F55D96F33E7D78B0FE3FBA1 +:107DF0009C15D51339ADBC6B329FCBF51FA7EEA2F6 +:107E0000F284A9A7D8BF6BE07F4E95D99F9A98E9D5 +:107E1000553381DF5CFFF68354FFE1D9271600AFAD +:107E2000C333354726ECDBF6D697FF4CF36D5DFE8A +:107E300027D6A336446B11F87E71F7D35CBF66C5B5 +:107E4000FF2C807E50639574639CDBB53A3DBF91F7 +:107E5000A9C5A2FFAA15BF633D2222B745F2D7BB31 +:107E6000BE1F3F3AD3BCF96585DA2D0E6FAEE154E3 +:107E7000F5E7E1FC3BAB04A2950C862BEB75E75CC8 +:107E80008168E047B348B972F1D610BF315092A86B +:107E9000DB8BA8DDE226558F57F4DB41A7A1F51750 +:107EA000D377AEF73DBF578A26F93D76D7FDD73059 +:107EB000FE4500FEAE33CF646E023D9CDFF9745682 +:107EC000B09F3634BD72BE72FDE7F47D738EBED8AE +:107ED000406FDBC24CF6850BCF24EBF426E9E9C2F8 +:107EE00033D9ECE74ED4F7D905C5670947BB5F081E +:107EF0008E67109EA6E11C97E36D1A0EB9FB619D7B +:107F00002F2E8E6F1A0EBE67F041E168CA63BB4127 +:107F10004E531EF464837F8AE2A62CFEEE6FCA42A3 +:107F2000FB972DD20E63CCA7F2B9148E7BA2B5F0CD +:107F3000FEAE7C6EE026E48D71EA9D92EFD43B2587 +:107F40007F095DB79629EDE8A44FE61EA7B3A43ECE +:107F500096F4825CE49365DE29F30B3794D8E16FE5 +:107F6000AFB7C9BC6B7D89FD18E6F73569B5C44F5D +:107F70007374BFC5027FA9DD0BFBFEFAE5E11C3F70 +:107F800031DB3ECF4B69F67ABB695C030FFDFDE642 +:107F9000EF8BF4F9F40D890BEAA5B6ED0BC339F6B6 +:107FA000A4E8328E6049A6B4E33EFB6C477C91AAFC +:107FB000EBDBC26DD0A15BEA1B8CD78FED065EEFC9 +:107FC00048A1F92FD6E3A55EB648B8FA9E957CE3A2 +:107FD000E57C2D05E7D505C01DE75C2CE57321EF99 +:107FE00049BC1979035FA1F05DF1F18214D8959F26 +:107FF000C894F6C7507C2C8F1ADE13E5065CCFD4EC +:108000001DCA00DC8D759DA8F37AE968EBB4BFAF9B +:10801000CF77688C8F7C47307DD76F1D7288242086 +:10802000716EABD58325D45BFDF743BFA8DFAA36BD +:10803000F904973B80977391FBDF41BD051B620BF1 +:10804000A00F18ED17AE2FF29607CD7BE056335EEA +:10805000063599F3837799F35B71060DFBE7DBE552 +:1080600007CCF92187CCF9931FDC7133B64F85EA31 +:10807000BB5F85BEF3E7F187704E9F7AF99568E0A4 +:108080006BF15FCB0F428F0B8D67213C2AD0737C45 +:108090005B14A6972BE25ABAE14346DC06766230BF +:1080A000DD540ADF416BDA95F5CF8AA69BBD4467A4 +:1080B00055CBDECF907AB3EC7764D35A3BE4CED085 +:1080C00071BBE33B22D2EBC63E2A1921CBAE5E3612 +:1080D0004E7C8AFED6BC371EF458F22B85E59B9267 +:1080E00097B25F07DD1CDD3EFB464E6F9EC0F03051 +:1080F000EC920B9B954014E55D2344877F1FF18B29 +:10810000A50D21F19F6B42E282D699CB17EEDAF7EB +:10811000FF104750E17882E32EAE8C67F41F805E3B +:1081200059794AB07DAAF2A96FC2CCE5725DF3F528 +:108130007518E7ADF05DCBF17B57CBAAE238FEA313 +:1081400073E9A84B3B8573CB3877AF5EB75195F297 +:10815000BCB784FDC891768E8BAC76884004CDEB9D +:108160005094DDEBA2EF97D647B1BCB280E45CE857 +:108170008B940A27C74D7A62D0EEC4BB2ACB65D553 +:10818000F1121ED5BF51FCB01D57C3A88BFC933212 +:10819000BF4804D8BE0B3AF206AD03F80BCE8B46AF +:1081A000A95F565903FB009F8E7368ABB95E15AD8E +:1081B000F3A338C87BE6EF35A28DEBD7EEFA262C79 +:1081C000F87B903D9AF55E43FF5675F94AFD653898 +:1081D000CB4F74208483BE6CBADCBEEE1E92236843 +:1081E0007D2B0D7BF85A29DFDDB2519E63249F67FA +:1081F000014EEBD6927C86EFA46F20CE442C0AF77A +:108200004BF95EEA0BEB6667B15CF4F23F5E0A4045 +:108210001F697B4861BBD2BA7CD9EFBAFBFA7339CC +:10822000F8A7C2E384B11CB66E8A51DE87F5914F80 +:1082300030C564C8F9FAF71E6EFEDE4BF566C13E26 +:10824000221E74B27DC490FB0DB9BE2E56CBC91A46 +:10825000D6B9FE75B16D51F0BB898AF8EF25B76CC0 +:10826000D6CFE3365A3FFC2AC795E283F08F19F543 +:108270004666C97365F858EF16BD1EFB5FCA2D53DD +:10828000EEBD8EE655FEB0C50D7BA18107E1F5661A +:10829000010EC7D73A0B4077C3C74A7BD9917CC937 +:1082A000E723860A8E371AABF73B36CB624A93C276 +:1082B000891EA99FE345D21E1F35B498ED9624135D +:1082C000CCEB2A6E65B2DE4FB9BDF8F7A3BB984F71 +:1082D000075D144AF9FBF86DCA26392F2FC7270E00 +:1082E0007FC0C9F6CEE3FA3964E081E86818CB0FA5 +:1082F0003A5F8B0DA19BB5A0079C87A00725986EC0 +:10830000CC74718B22E12BEE93F2F7BA589937E8CF +:1083100082F43FF1BFA09B22C1F0EF4E0F34D6DBB9 +:108320009D1E4874B00874D0512F840E84D53FEC44 +:10833000DBFC42A52362872B848214ABF021CE178D +:108340006724C3EB1EAB1FB178BDAD122F7DAC927D +:10835000EEE8B4F18517707D2FE27D4B1E5C28BCE2 +:1083600054BF2445B07DAD1FC9553171DC4E204549 +:10837000588E0ABB13A5685F1223FB2FE92938FE2C +:108380008EFAF35AE274E6361CFE5EC17205DA47D5 +:1083900017707B9F45B6F75A29ED9B21F598B69546 +:1083A000611CBF5C72779F2CD0C9C4B1663A39A2F8 +:1083B000D39591DE94EDD68D759E24F083D286FE02 +:1083C0007CDED43B8BAB77029FCF47B0FC59B2EA3F +:1083D000C79386617E2FC47B80C23393B7B33FA817 +:1083E000B461F64F3E84BEB4D5C9DF2BB2B5F559A2 +:1083F00090FF15F7DC9DF4A174C6017B12B5D79AE6 +:10840000A69C7F95D2C9BEEDEF409E983C5DE5FAF3 +:108410009385B43F8B0639CE24DFE7D624EA6FD2AA +:108420002885C3698E3A5DA9B7C10FA4E3F7A92CCB +:1084300045977FE43D8192557DB2D273E13F21C9DA +:10844000B80B39FD53A3FE186503E4A5BEE3E4FEB3 +:1084500033EAA31FF47B3A4BCA55BFD5E162E40966 +:10846000AE5CBF7C75D8D18C68A4B64036A5E9FD5A +:10847000C7BE84754E4C17E3D703EE77AA6213CFBD +:10848000B7AD84F94254961BF4AB9142CDFAE3D6D2 +:10849000FECC278F8E693B7A37E58F6E1E24ED8CDC +:1084A000BA7D61BE4BB07C70748CE4776D9B239871 +:1084B000FE8FB85AA3E2A43D8EED0D653A497CB615 +:1084C000ACFE7EF8B9CB22ED47717ECC7F681AC72F +:1084D0002794AD530361B807B0C66C6FA88AD4DE89 +:1084E000C67E08B51B84DA074033A0A3F2350AD351 +:1084F00061DF7A8F3D99F99CE2C2FACA2303FD70CD +:108500000E947B9C1CC77C85FDE06B82FB70D8B908 +:10851000050789B5676B9F004E258D25ACEF46E4B6 +:108520006ACCBFFAAA0417EC179DFE26C25E0BBEEA +:10853000646D4DC6BEFC55969BF13031CE9515C984 +:1085400074EDE4FB11476DAE2CCCEFE84AA705E7CC +:10855000EDC41592BE69DF39708FE11EAB08073F8D +:10856000D89A25FB9DB3DC5ABC91F2BD1DC21A15E9 +:1085700007FACA67FA5ED85FFB2DE675EA17620450 +:10858000E489B2356BE5BC74FA10D696C2781AE766 +:10859000D4E6B402D8013AE4DBFE63DB01C70EBACD +:1085A00098AE303DD07A0EC18E9CDEBFF432CAE95F +:1085B000FB3ED0CBC4B1817E881B2F52AB38BEB6F8 +:1085C0003D4978E0776C176D2C8FB4933C02BE6701 +:1085D000F019839F105D781D899DF8DE5247532264 +:1085E0001EBEB5CEC1E9B3752E6125786FAB4BE2E7 +:1085F000FC0B756E4E9BEA72F8FB8B751ECEEFA8D6 +:108600001BC1F997EBBC9CDF553781D357EB8AF937 +:10861000BBC1AF083ECC970CBE63F02783BE0C3EB7 +:10862000154A577309CCB81741ED991F1A7C10EB06 +:10863000B01474F22703CFE94AB12F09FC50B4CE2D +:1086400006FF2852CF3DFF0AC1B9BD2292ED22EDAF +:1086500042F2C1F648079F07A976B10BF689FADB0B +:10866000BC47EF0E3A876FAD508435888E7FBCC40F +:1086700029AC41743C6F59AC293F67D9FB6FF4A416 +:10868000FEDF8DD172B3691E477E79E2F13FD1F7EB +:10869000DFFCF24C26F04EF3D8FC08C6BD2B5C9FE5 +:1086A00047AB9CD75D769697FA864B7DAB6FB8D477 +:1086B000B7F0E3088ACF3DA2E3A3242DF69DA7B12E +:1086C0006FECAE9B47C04EB452DE4BFA04F8A3F2F7 +:1086D000BFE8F82B5D16C6702D6DD0F76B70DC36D9 +:1086E000C1F558B260F94EF10A01BFD7B15FD803A6 +:1086F000242B88638AC3AF407622E56B0EEC98ABDF +:108700007FF711E47665D92196B3354724C77F08F2 +:108710009FED5C707FCAB2835C4FB4F636C56F467E +:108720000CF5DAC13740E3C05F69CE7E81FD2E1AB9 +:1087300015BE7F54AE7F2F5FAD98E2A26764ABF2A7 +:10874000DE459695D3F359423F471AF9BC32E89675 +:10875000F808C7619637E6DB1704F1E752FD7B594D +:108760008EC514A7797F969DFB398FCD49FDDE9B81 +:10877000936E9FCFFCCFCDF7058CFAA53905AB6082 +:108780004F2E5D83A8A6CEF625D9567D5E2EA97FF5 +:1087900039E85C8BE2F8A22ECF07439E39855F470C +:1087A000F2FC59EFAA7CE1B917E08FACFC73189F7B +:1087B00053958375FB4AAE7FF8349683BC91CA709B +:1087C000C8E112FF85CFFD351A715DB53BA4BD9799 +:1087D000D2A3486BEEAA60FB5E8D87F6491CF8AD0C +:1087E000D9EFFFFA0B7FE6FB9D84B0143D6E98E352 +:1087F000D46A767CCAF16BB0C7F986727F1C5F1DA4 +:10880000DABE56F99AF557422CC3A768CF97893C30 +:108810008F9D9712C1E76AF7AC4CEC2A8E28B41FE3 +:1088200023CEC1B0FFD58A359FC3CF597BD7849360 +:1088300092DE65FFA1ED1ECA8E4A38315020C6EE89 +:108840002AB6935805C79F2CD5ED38EDFE4CF6633C +:10885000772777D7AEA7462492B55BDD3188B3BEC4 +:1088600028C484AEF0F449B6946BCFD33E823FFB6C +:10887000E23695E5CA8BDBA2783FD46C7BF020E230 +:10888000046B9E52D8ED582D5A38CEAF66872A1CFD +:10889000C1E71DEC47F1DDCF73F173514B405F8BA6 +:1088A0009A14EF669A4FBBC31DD323683EAF80BEB8 +:1088B00088341787350D47FFC6FC9F077F0B92371B +:1088C00017353FC8F18D54EF02CB37BF8DE0383CF0 +:1088D0003AC9DEC13CCF6E18C2FEF5454DDB6B5880 +:1088E0003ED816E182E9E98CCD7C0FE4803EDE8142 +:1088F0006C298F9CD5EDD1675F50591FC23CB12FB9 +:10890000CFE871B846BB37F5766F664BF9A7265BA3 +:10891000EE4FA3FEA2A6A3D1FDA8FEC95DEF73FA98 +:10892000BEBE6F1645B6F03DCF933B22F89EE0C920 +:108930001DFF39FE351AEF7CD3980425689F9DC82A +:10894000B6C97DBA41C62FF32517D6139A783D676D +:10895000B7A528AC2F03DEA4B79FDDF112DF4336A5 +:10896000E4EB1F1C2F384BB186DCA3183D08728D39 +:10897000A355BFD7D1A6DB63FE6FFAAFD1BF27598E +:108980008AF571E43D0D61C46FB864BD2235B72727 +:10899000F6DDDCC1EE99B8972DDE927197A2B7FB98 +:1089A00011E87F73DF8D67BBCB529BBB27F25F1C47 +:1089B000268595E0337788CE57925A87C1BE7B349F +:1089C0004DCA15863FAD6AB522BC04BF5E44673E02 +:1089D000E4FDAAD06007C949677C3D5661F1DA71B0 +:1089E0003E46D9992EEAB73B37C1BE75C42E7CEC02 +:1089F0007F7BD129FD27E9D20FF218F617A5557113 +:108A000081AC78D8F174BAA99A4AE541F453B529F2 +:108A1000900539EA9C5DDA2B510EFDA9AA40D6AB30 +:108A2000D7E914FDA0DFA369AE0B2CF7EE8C12D0B2 +:108A30003F2CAF4449BBC8D3CE4D6141E776BF1C44 +:108A40008B1177C7FE4ADF66393FCC0BF2FC227BE5 +:108A50006316E45D63DC45D18D3CDE397DBC45E1C8 +:108A60008DD29FA3C711A23E8F6F13EC776A7B262E +:108A70008CE5E633C92D2F63FC33CFF4E7B887A329 +:108A800069FE05BBB8DCC9F1E795CF860530DFD3B9 +:108A9000CF44B15DEBB44DCA63A7A312591E3B147A +:108AA000F5F05CF6633D15A6C02E745A11F62494B9 +:108AB0006FEEC1F24065DD32F6D754127B811C4B5C +:108AC000E904C87FA737F7677BD1E93755BE5C411A +:108AD000DF57E3BB261AE7FE8CF58008B6239E79A4 +:108AE000F66FFD83FD3B465AF994D93E66D083511B +:108AF0005E9423F960518ED4536EC871715A1DD1A2 +:108B0000F4703AAF53F207C203EB81B41F1361EF65 +:108B10003FD2B43B5189049C0359FF09B86F95FAC1 +:108B2000D6996D36F65355BE12E5653BD4DD57F147 +:108B30007DC94A55CAE3951679DF50F9E556B6FF67 +:108B4000D43FE32C003C08DEACDFB66D56F571E493 +:108B5000B8A7B7F4917E8D809E7F7910FB3526C62D +:108B600089795359CEDA9007B85E7A2A82E3FE6992 +:108B70001C2FE2342A7FF67309CF9805AC27D0C1A9 +:108B8000CDFCB94AE7CFD5775F1383FB10E25D9543 +:108B9000EF795CB27A7A82FF86C2EBD11C9D3FBF2F +:108BA000FC38F3832ADA37880F5BACFB13173FAB33 +:108BB000B05CB978D5358F30DF7DC726702FE25C89 +:108BC000D383D1C1F8A8CF91FCB0B3BD87EB2FA65A +:108BD000FAB2FD5BD13C9F2D360FE6138AC7EFDD5D +:108BE000FE59F507B5AF6C22F922EFCAF55F122DD9 +:108BF0003FFD33F8CB3627FB5109FF7C3FEAACAD94 +:108C00006901D67FF67927F39DB3B172DF9FA4F394 +:108C1000D4978DF9DCF46BB6CBFC619AC039B4D033 +:108C20006FEED798D7EA1C9BA4B7784F0CFC44D5BD +:108C3000840FF447F8F911B77FD7C6ED43D7B34097 +:108C40006FD7B14F9F8F60BA39DB4BE2E5EC0BD9A0 +:108C50007C9E1D8D95F44EF34D85DE743656A6B878 +:108C600099047AA874497A383BA689ED026795ED94 +:108C70009C1EB5C97695CB747F3BD15F12E807B4D3 +:108C800009BBAA634D0BE419F0F9E1059C06704F8E +:108C90003BD48E0E3AC5F9D7AAEF33E31D05F6EBA8 +:108CA000B09FA789EFC76BBA3C59B5ED4A7F25F055 +:108CB00054B54D617FDA7F19FDD0AC130C3F00D164 +:108CC000E5629FC2EF222C6EB86D11FBD396ACBD4E +:108CD00015746FAC63B17E6FFCA8A2F27C8E3A690A +:108CE000FFE45E399E01DFDFE7281DEF75B88CF3E6 +:108CF0008BF6F03B396E4947946DA4FEAA1A943561 +:108D00003C4E9AA1E7CAF5197022B0D861E73BAA98 +:108D1000DFD3EE6EFDC63CBB9BCF319DCF1F4D9385 +:108D2000F793DBDE96F7CC2F7D3D2426EE5BE44106 +:108D3000BE6160F487B863D020F5F322F81CF635E5 +:108D4000ECEB34CFAC0D66FF4ECE53E6FC806DE607 +:108D50007CEE0E733EAFD99CF7BC6ECEFF09E30EDE +:108D6000EB8413F46FC43542FF460AFDDB1D26F584 +:108D70006FE4A17F2385FE8DEFD0BF9187FE8D3CF0 +:108D8000F46FE4A17F2385FE8DEFEEFE124E55BAFF +:108D9000BD1478E0B8BADD4E233E81F7CBC5D98942 +:108DA000CC478555EAA51717E5B2FCD8616F9AE262 +:108DB000607B93118F9518AD85F7471C80D2B22A3E +:108DC000398DDBB11DBAF6556987AE2A7046C2EE01 +:108DD000D1BAF2E42A883DA7A3B418D4BF686BDBEC +:108DE00002F8562F3BC07EFFD6E5EE77AF93F863CF +:108DF000FB8B115F5582730F7C9BF4251977EE7105 +:108E000004DB5343FD44624D501EF2D33A733ED40B +:108E10002F04BEE635EDAB46C6C76F6C6DC9E0FBEF +:108E20009F3EE3E0FB699FEAF63B31CBC1F298211C +:108E3000CF23CE1B70597A9FB209E795A77F1CC339 +:108E4000B9FD50A6E97E61685A767908CBF31DF921 +:108E5000358A05E3944F5FBE8FF56ACDCBE7D2ED3F +:108E6000FADCB2D75B4CF3EEEF0F37D1D1C0AD7166 +:108E7000217ECC5EA6FA8377A587F8310798CAA72A +:108E8000AD1962BE8F5F7C8DA9BCAFBD236ECFA133 +:108E9000FBB9E4FC5CB2CEA5C8025E6F68BD54C5E8 +:108EA000F327F86FC5DB524E2DA773C61BAFBF2B40 +:108EB00052007F9D7732E057D1648B859DAD4C3F4A +:108EC00087C432F3B95C61153E575C27DD55B88421 +:108ED0003796DA7F696D4C653AFAE547A92A8168C9 +:108EE000D180963CE8AF8BDE7C7238E8AA5ADD98D8 +:108EF000EAA2F23B14FF165C203F13B73D712495A4 +:108F000027A95A497FC273AA2D70FF1CF0D1ED1911 +:108F100002EFA47CBAE6A5688E1FD4E92FD5E60A35 +:108F2000071D6C6C54594F81FD4C8DEBA4938D8DB6 +:108F3000F1E1D06B2AC6283EC8C7065C0CFA08854A +:108F400007C9EFEFBA69BD970EC9F7948C752E75F6 +:108F5000C9FAA241B637DE0730D67B5CD7472B373C +:108F6000BE91753B7D3FD77F5F9E1B7EDCBA5DBCAB +:108F7000EEC5966D5B92297DC7A1DD85752D7D7B44 +:108F80005CF4481AE7CB6D32AEFDB3754F3EE1237A +:108F90007E7A77E39376E80F9556BF9DDFCD7966AD +:108FA000A31DF10ED76FDDC8DF176C2D617B8071BB +:108FB000CFEE941197ADC3A362ACB2C145EB3CDEDA +:108FC0005FCA8515E1329EA6481DF54602D6B55505 +:108FD000C9C7BAA6176FB7E3FD8187F57AA1FBA6CB +:108FE000FDF0B4A21EB07B35291CC7D4DD3E99111B +:108FF000E8CFFB64DAE5344EA75F1EC87ADE8782CD +:10900000B42F9C23B921FAF56155DAF59A55F94E3A +:10901000983D90300DF2C25EF96E45359D43230AAE +:10902000A0B70B7135A5C5A354139DD7164698F666 +:10903000C12C11B4AFA8BF9B452F537EFAC40C536B +:10904000FD99D30786F89D0B3ACB997F5D6D7A8F9A +:10905000A6FA2E9F5B61BBC758F3774AEF623ABB13 +:10906000D1D4BE5A4C35BD47B3E8A9F718CE4465F4 +:1090700076C4E154E8F758666947F5EFADFC9D16F4 +:1090800062DAAF7D333C7F92E7A58DFD09863D7D99 +:10909000167ECFE8EABC0CEF881745BC30EC1D9A71 +:1090A000591E69613D55483C54EBF6A8EA1C698F8E +:1090B000AAF6B5D8118F4DF0B7A610486A1A15B6A2 +:1090C00037527D474A9CCCDF85EF3BCCF752D0DF4F +:1090D00065941F524BB0BF42CB6B68DD38176A6096 +:1090E00047623BD884936C0733C6D1FB37E834F42E +:1090F0007D80D0FE060C7033FFAEDCBAFD602F829F +:10910000CFB4E2D87CC49D54354DB195E45E496F2F +:1091100006FFBF546161BF7EFBE1034C6FED155646 +:109120008F8C4BFF76B8D478A5DD35940E17D0BA66 +:10913000E07F5EB043F1F815590FF0E905FA0C81B4 +:109140004F4A177033E0D501BF90727E3F6E28E220 +:1091500026E47B0A57C025149EFA380B34C17227C7 +:10916000CDCBCFF30AE9578C08DD8FB7DBD9FFB041 +:1091700041112EE5BBE131F5B2B4E3F4CD90EB6FD4 +:10918000DBA97820BFDF7CD9CADF3BE8A758C6D966 +:109190004F9F68DEAF1DF4542CF7CF8CCB89DCEEEB +:1091A000DF4557DF454F86FF26347EDDB847E61999 +:1091B000A0DFB71A26867DF34FC4E11BF24177E7A3 +:1091C0004CC739E4D2F11099DEE5F9BC342A9DE3AD +:1091D000CC35DDBE68F0694D6F678C5B42E5EE789B +:1091E000D07B6F7E67715543466AF0FB37DA4A1BC6 +:1091F000DB815397C7735AE27425E27C29592EDF2D +:109200006939764FCF44F8298EADB4254CA4AE8F82 +:10921000DD3934550C42BE88D34FD786CD0AB6CF40 +:109220001BE92D03E4F9619CEFE72D87A367613FFC +:10923000AEDC198D90A1C52BDF1FEEA273BED9A2A3 +:109240002D1AC0FEE08D7CCE0BD7C63CD8E70C397A +:10925000A37265514FC80355FF38F004E4016DB99E +:109260002D1172EAE90F5481D01A3AE758BE38E559 +:1092700094F47D6A7304DFAB3CA5082FFC518BD4BA +:109280007D792ED379DB7C33C68F70D2B8C330AEF4 +:109290007F4B12C6F5F8B230AEB63C33A62BBB8B73 +:1092A00091D6AE97F2DF16C3CEACDBA321F7230F26 +:1092B000B95F644BB91F79C8FD4821F7E37B0DFC0A +:1092C0000EF01BD7B7E5436FF58D15394BF81C8EA3 +:1092D000CC815C7FBB12EE013FBA5DF1F4E478848F +:1092E0000F62E5F91B8257231DDD46B25910DD5E82 +:1092F00077D92182E3EBC68858537E9C23D954BF8B +:10930000C895662ABF3EA9BFA9FC0677BE297F5330 +:10931000CE4853FD499E31A6FC8F46DC60AA3FC56E +:109320003BC5949F3661B6A9FE8CE21253F9CC5925 +:109330008B4CE5B3B5DB4CF95B2BEE34D5FFF192EA +:10934000E5A672AF7059710E36431F23B8EF853E04 +:1093500046E9ED6F674606E375D4384B97EF0C3559 +:109360000D90FA5674AEF739D025EE09810EFBE860 +:10937000F780F6E29C1906BF654091FA704B32E81F +:1093800026B45E68F9A888FD97F09465FFE76E9FA4 +:1093900061253E31EAAAFD4332287FFBC0E619561B +:1093A000E22FA3AED9FF523AE57FF1DC37B27CF071 +:1093B000FE4B285772F7CBFC34C122C8AF06CE9BB8 +:1093C000E1A3758CBA2E7D8D47DA53BA8C53355292 +:1093D000C001719D8003D200D127D2FD449F485F18 +:1093E00027FA2CB7097190E813E921D24BF1FDF768 +:1093F000A497223D4C7A29D277482F45DA427A2920 +:10940000D23FD4CDE2F4833A8DDBFDB1AE82D38F6F +:10941000EA96F0F74FEA9671FA973A1F7FFF648059 +:10942000617F08B09DC6F08BD5C01F097BDE2EDBA7 +:10943000B960BFB1E295E7ABE1C7AC5F225A23B098 +:109440004F5BADB1271C9DFEC9EEF9AD559C08924E +:10945000CB9CE1DECF06F0F8BD5DCCB7F5EF47C49D +:10946000B43E0584A74FD3B5B3E007330ACA56C646 +:1094700010FFB8EEEB2536D0CB8796AEEFA3EFD535 +:10948000F9DBA703BD6DE8F75AFD5DA66B1D32AE93 +:10949000F05A6B6B3DDBDBBF146EC403ED33ECEFB6 +:1094A000F758F95EB1F285E0FCE804C1F9FA2F5BE8 +:1094B000380EF15A972789CF1D3D6FC40575F8FD09 +:1094C000F11314EF63F8E18D789FC22F5AC7413E24 +:1094D000181D69778785C40DC0DFBE2FEA8FC6BC13 +:1094E000F87D27C3BFFFD4972280F7F20C3FFEB56B +:1094F0008E9634D81546DFE1F004C73319FE7AE5BD +:109500008B1615E78911AF648C63CC3BCA4AFD15F5 +:1095100074C6235DEB6ACA475C467D7524F7D79312 +:10952000BEE3DD49AAE755B95D533EECC7A3AB22C4 +:109530003D42E98C13E8A9AF9BEAF13A0BBFD03862 +:109540004E62B41E27817E1CB29CDF011C9D104818 +:10955000C6FB9FA397D83DB0833E8EB8B382CEB8EA +:1095600005D48F08DAC79827FAEDF715CD17F2BCA6 +:10957000D7CBF09DE692F429DC7A5E3FAF85632C71 +:10958000DBBB543D5F1CE6FA6B04D1CFAD19DA901A +:1095900081D4DF1F948CCC7CD617327A60DF4F09E0 +:1095A0007947B00BFA1931F0FF847EBC12EFBD058C +:1095B000DBE142E9C8C08F414F06DEBBA32B830E1F +:1095C00082E2D018EF1D71657A7FA1F4D61D9D1936 +:1095D000F475AD43D201F08CF82083AE942F9AF845 +:1095E0001EEBE82A079F7F065D85D2C5957425E9A5 +:1095F000B4FE270EEEEF4ABAEAA407C0E587D355BA +:109600008B8AF3F89FA5A7796D623CEEFF975C7695 +:109610001F44DAAB9FB6177CA64C8C190F12132E81 +:109620007510EC62A1F532BAA9174A7FA1ED6EBCA4 +:10963000A25D466E70BB71FA5919DAAE12ED7A046A +:10964000B71BC271116FE9F708DE721A712D9E996E +:1096500090530EB96DF22D2FE18DCC27BA19A7F3D7 +:10966000F34362099FBF24EEFA404F853A698DCBE0 +:109670005DC8FA426164D7710537EAEDC77F5DDCEA +:1096800080F98C4F30CBE337EAF2FCF5A291FB0F67 +:109690007D47E1C6DCEB59CE0F7D4761F3403DFECF +:1096A000204DA481DF170A8F9C9FFE0E46A1BECFDE +:1096B0005374BAC970AB62541CEE9B6A561C32AF2D +:1096C000E31D8C3C8CEBE3FC0DC2CFE94D22C0FDC9 +:1096D0004CA20309F91F096193EF5FC8FBBA35AAD1 +:1096E000F6DF90578D7BBA4F3BB557B0CF0F444C48 +:1096F0009E83774AC60D19D70FEDF617BA59CEDB00 +:10970000EFC860B913FBD216D7C927DEA473BA5FBE +:10971000A6BC378A14F746FBD179FA3B3AC791BF0A +:109720003167B940BBF16E73BC93D1FE26D7386167 +:109730008DEFFE9CBC296F776FD8CDDE8ACD2E04CD +:109740007EDF8ABDAA10EB7D2BB6A745A661764EBB +:1097500007BDD2AF2BB9D8A0FBCEF1C6F378DDC1DF +:10976000D9806B283C0D38FF00B81EEB0AAE7B0792 +:10977000089637AA23245FAD8E907CD580737558E8 +:10978000C77DDE9EC1F127550E09AFF9CBAE11564C +:1097900012F5172C1BC9F99375C207B89FC69260C2 +:1097A000100FB1F709EB58CE1BEFDC9D7DF8BDE83B +:1097B000249AE72A87F63F98DFB98240164984E267 +:1097C000E4867ABE8F7FFE05D5037DAA4A75AFF188 +:1097D000C0CEFA962AEF717D7D2015FE58F154D740 +:1097E000F1E8550E095F439F1CD2AF98F7ADB15F0A +:1097F00085FEBE80215FF50E93F1DCC63DF7EEE4F9 +:10980000ADE1E192AFF50E93FCD8C0EB06BB7EEE66 +:10981000533FC3898FA6FC3A9CF5AB98586F4C2EEA +:10982000EC8385C2A49F187695F604F97ECAB5220A +:10983000EB9151942F3C64137E2A6F074340799239 +:10984000F4B3B61FBAA482EF174529FC3E86716FA8 +:10985000292CC922DC417CC2E90E37BD4B1B911378 +:1098600067CA47797A99EAC78C483795C77A0798C3 +:10987000CAE3271498F23D8AAF36D5EF396BAC298D +:109880009FACDD68AA9F5231D59437F8588AFC24E2 +:10989000FA2CB9C5D4BEEFB25253FD345FA5A95C12 +:1098A000C53B9B3140ABB7252711CF81CA9F8CD5D3 +:1098B0004B43DEE3B508CBF0CE776BFE335ADECBFD +:1098C0009910B980DFAFC96CFC99799EEA446B2C82 +:1098D000A5D7BBCD7CB128C99C1F17B94F81DF71BB +:1098E0009CCBCC9F5396584DF91FE5EAFC344FE4CE +:1098F000B1DDE3BBF0AF0D30E13F144E440FFC7E11 +:10990000683B9DEF3ECCEBCD327E0F077E93E0753A +:10991000C06F120C07F84D82F3F09B04D787DF2449 +:10992000B81C7E93E0F22187CCF81FD662C6FF55A3 +:109930001F99F16FD06577781AD96AA60FA1299A75 +:10994000F22D78BAE694997E42F1731D895BB109D4 +:10995000C087E209B87F38BE5686E08BF0C3F73780 +:10996000DB7B47317E1ED7D7756D6020DF972E3A9F +:10997000A40ABC6F63ACF371FDDC3F6DD51A73892B +:10998000CFFCCE5D90043E769D907EDBF155164F68 +:1099900080BA7F20649CD929DA43A83F2BFE52AAC3 +:1099A0001D74D226DFCF7B0E7C79D895F1B23E12A2 +:1099B0004FF8BEF6CF54BE2775C4D2A8808FAF8EA5 +:1099C000D19E009F9997BB84D79B248AB72F405C78 +:1099D000D47F85A5223FB7AFBCC72D725BF9FE8946 +:1099E000C127E7A6C8B8A92DB9BA7FDD23E3A79E92 +:1099F000C995727794C7C571DE25B9F27E0DA98B22 +:109A0000A97307013E879DD980CF3A0BBFEBD98A56 +:109A10007BE4099DF7C8210F43FEECA3CB7FF51F24 +:109A20003B1C5847F67A613A7FFBFB1DA6F8E281A2 +:109A30005B5DA6FCA0A62453FDC1BBDCA6F2FC40E6 +:109A40008EA97CC8218F293FAC6584A9FE551F795A +:109A50004DF991AD134CF5AF39556CCAA788B6478F +:109A600001DFBE8AB4531CCD4D97FAB95B70DCE4BC +:109A7000DCBB63E57D5FDD7E61C8FB46DCB9A6D358 +:109A800075A81ED1D72EE5E8FA6421F54687AE1FEA +:109A90000AB33EA1E971E31DF7587CE6B871235E75 +:109AA000BC43EFD0F58A8E7B349DF1E2DEE078F1A5 +:109AB000B9615DBF1F7D5EC77BE8FCFBDAE57AEB31 +:109AC000EFB4F3BD1D635EA1F349C99674BBD9D150 +:109AD000F5BDAABFE54AFB466B66F125D0FD1336FE +:109AE0004F2BFF6D842BC6F3B4225EB7FE1776CFE3 +:109AF0000AF7778F3777B05CCF1C8B65DE945C8E6E +:109B00008B33FDDD84884192BEAD8375FB4AC878F6 +:109B1000736364DC9A88B1BB41BFDD8F27E1996430 +:109B2000170D7CFF4BBF67F1E3354DF7A1688EBD84 +:109B3000517F3FCE6F033D4C1C4BF2593EC9135B26 +:109B40007A3D144972CA13CBAC6C9F8A7BFE57379F +:109B5000FBFA75DE9FE94BFA10E803B20EF4A80792 +:109B6000F25429B70C92EB2B52BFEEB8E7C07E1827 +:109B700021F4F34370BC4F17F4C67468ACE3DF758F +:109B8000EFC1A0DB503819FAAFD0E33BFB19F3D299 +:109B9000E167EC07037EC6FD13F76DB6E24D917CDD +:109BA0008F6502E2E50CFC6DC993F6C6053A3C50A0 +:109BB0000FFCA8BB7A456A6E0CECF7EDC21DE3EA18 +:109BC000820E3BEAFF9BE062C0BFBBFB6DDDF1870D +:109BD00050BEF05DF7DDBAA3D37FF6DE5B109F9039 +:109BE000F14B3A5EFCFD2C1C17707794793F3F32A5 +:109BF00048F2899183F4FDE423FDD6CC2F04FC0FB9 +:109C0000F52B559D5FC8F3BC24AD98DFAFC6F98A2C +:109C1000FB5BF3374AF94788E2C4AB87C28F6FE337 +:109C2000FBCBD77A05DB6D4A1B153FDEF92AF175B0 +:109C3000AD0FB39FCFCD7207BF3BC8264D6A5746C5 +:109C4000EDF6A55DF9CEFAC248F9EE60E8FBEA0B45 +:109C500075BD192F6A60DF86FABDEE19A4FBB13C11 +:109C6000C2C3F29C1ED750A1D7E9A037BF7C6F0EAC +:109C70007A32F631A51C1F67C0CD0D3FD490CE3C83 +:109C8000C1373C07E77983B5CBF8C50EF81A7EAB30 +:109C90000EBFEC61BE27111A8F71CE7720BA2B3F11 +:109CA00098E11FEB6E1F74F8C7BEC3EFD61E69891B +:109CB000C6DFF169DF26DF67E9F45BFD65B8CB221B +:109CC000FD5331F03FB5EAFD898D795DDD0FD59605 +:109CD000EFE43894668BB67310ADEF2CF58F777B7D +:109CE000EF89DC9F88771126EA76A92BD7ADCBCDFB +:109CF000A314E98FF6A98CEFF609F25E3DF15181CC +:109D00007D67C44F4C118104A4861F4A5B3D92E1DC +:109D10006FF8A14A0223799E33EA17DAF0E468EB80 +:109D2000A3771585BB3BFD53AD7D645C54777EAA5C +:109D30006997F3B9BFE997AFE17E3E189426E5B67F +:109D400086FB6E039D0DD82A6C5867ABADEBBF4BFD +:109D500051A8F3AB12E89A3D82E2AD962BBC2F9648 +:109D60002AC288BF623E6FE42F35EAF92299BF7D8F +:109D7000A5CCB7EAEFA76DD1ED20582752AC077AF2 +:109D8000F936DD4E827520C53AF01D7C0D79F0352F +:109D9000E4C1D790075F430ABE86EFA5A2381576C7 +:109DA0005BF8D30A83F607FC6985417213FC69C12D +:109DB00079F8D382EBC39F165C0E7F5A7039FC6929 +:109DC000C179F8D382EBC39F169C873F2DB83EFC28 +:109DD00069C179F8D382EBC39F165C0E7F5A703944 +:109DE000FC69C179F8D382EBC39F165C3E6F996220 +:109DF000F2B7CDD3DF7F285B1FCFF45198511C9B66 +:109E000047F8FDEF887FFCC4960E3C372F02DD2E0D +:109E1000AD0EF7483C374E9078B70889E7B6D98C35 +:109E2000E7BBEC325F24E3B443E9077EAB429BF42B +:109E30005B2185DF0A29FC5648E1B72ACC947E2BAA +:109E4000A4F05BE13BFC5648E1B7420ABF1552F86B +:109E5000AD90C26F85147E2BB483DF0A29FC56F8BF +:109E60000EBF1552F8ADF0FD08CD03FE2B635E90DA +:109E7000F3FB99F452A243935EEA32E521E707D758 +:109E8000879C1F5C0E393FB81C727E701E727E70FC +:109E90007DC8F9C1F94983DCBCBF20EF07B783BC9B +:109EA0001F9C1FD4E87B03B6AB491B2EBC8EB43578 +:109EB0004A7942710931352F7326FC8BAD4E253519 +:109EC000D623846DF980998594D7F438C73CD16640 +:109ED00001BE39AE80F0A60504C7650FFA7FC95CE4 +:109EE0006EF8B3F987F09EBF43B0DE50A3DFAF3505 +:109EF000DA7B844B456AD4EFCC775D2F747CA31E4C +:109F0000F3CBA0799062998F7893FCBB220B70AF52 +:109F1000608B4591F1B82B643C74285DADCA93E722 +:109F2000FB16CBF6FDE1885329513CB8EF9165153E +:109F3000876C0580D392027EF72A2F565FD792ABAB +:109F4000118765CCDBB04B129FE07B86A3DA84BD22 +:109F50009CC619FD85B0E3EF734CB44B7902EDA0BC +:109F60006F0EF429DE4D41F4BD2C4F9E7B9AEFB667 +:109F7000ABCBE9FBC06D4BAEC6FDC589E1B2DDD30D +:109F8000BF8966384E6E50F89ECEA86DC28BFBC955 +:109F9000CB757E3A709BCB5ECEE3BAF8DEA3D16F71 +:109FA000C98654BEA759225A0B710F450C55F83D6E +:109FB0007C036EB4BED7B1BE2CDA2AB02FFFE0FB13 +:109FC0004F242E7E9FFB4FA387C61621AE5034CB65 +:109FD000F742270D2D59D983E6A5F9E57BA1A3BF4B +:109FE00058F206E79F92EF8532F90CE7F9F179987C +:109FF000ED53F8FD95C9BE8D960437EE652FB72554 +:10A00000A2FE36E1815805F508F78A8D75E58A16B6 +:10A010008B5301BD8803F141F4479C633AE825DF87 +:10A0200063E3F759A6585D36F01B43CE2971C9B1D9 +:10A030008BD451317CCF32444EB8D4D083E3627E8E +:10A04000789C4E3BDFE75FBAD3C97285B65E61BECE +:10A05000793E5FC6BB56DDF6E1704B7A679CCE99C0 +:10A0600034FF16BC037B267D7BF40885E588BD792B +:10A0700004D7A30D2FF13DCD92956FF03D944B0D7C +:10A080000F45CBFB6CD2FF52AEC3CDB03BCDD7F169 +:10A0900053AEC7691DAB93EF3AD339CCEFAE5C6AD0 +:10A0A000B0B19C112A2F1AF2A7F11E9110AE3FC237 +:10A0B000CE53D160E33BC00BD794AC4A1257CA9140 +:10A0C0008B75397351838DE3B22AF4F7D442FF6E56 +:10A0D000CF623D1E6BF156F3F74FF242E450E37D41 +:10A0E0004DBD4EC9DB0766B03CB4C4C6FECD39CB0E +:10A0F000A57C24B60B3FEE93CC593ECE82F766E6A4 +:10A10000ECF47A942EE8E95D5D4E9AD8EA64F84F53 +:10A11000B91CC1FC65EAE514CEDF7C3999D3999767 +:10A1200065DC2AEE22816E5A8BE43B07EFEBF2D11D +:10A130000CC4B1C6433EEBC9F4DD4EF48D21F2747C +:10A14000BE35C0AB1C807838D1A6AD449CECC48D24 +:10A1500082EF834D821C45FDCF825C158FFD9156A9 +:10A16000C4F76126287CBF68D2D0DBF4FD40FB43F6 +:10A17000303FE1F757B4C2297EC439CDD2B65B80F7 +:10A180007F635F68BEA3FC5EEA249F62C73B929A2E +:10A19000AE6F1B741FBA3FE646E876B2486907EB1C +:10A1A000B09361B27824C9B76A26E4D3B9B06DF62A +:10A1B000D20981601F952BCB7BFC76D5CC069241D2 +:10A1C000FF55FBC91C8B45DE3F233990EF0B88966A +:10A1D000A29E942F59A314403F32E6F5B967EC389C +:10A1E000CFB04E3A28EDD8A7F21EE5D27B324D7E95 +:10A1F0009BD0B48CE08DFD3437A6F5270A6168F456 +:10A2000060E12D1C81F7EB85F1285400F198B7E847 +:10A21000F9EAC13BFFB43A97E1C4F991BF7D68A662 +:10A220002FF25FE09373146BF0DF1B4BB268570D96 +:10A23000EEC1F750C703BF11B96DFC9E444AB64B3F +:10A24000F2A9107B4BF56089C750BB4B59AE3C77E8 +:10A2500084D59D7A2BFB7BDC6CB734D67DCC66BE77 +:10A26000E76BA4F307EBE75EDDBFE79ECAC316F911 +:10A27000FEC26316FFF657885E2FF7D06660BD8F6B +:10A2800021DE9EE7AFF1FA8CF74C3AF895FE6E8925 +:10A29000414F47965DE2FB2AA59176B71A444FE5F8 +:10A2A000AB15BE0F5ABA4CDEE7D6562BF25D846E64 +:10A2B000EC58BF99FDBFFC9ED56F7E112E0B75F833 +:10A2C000CEB1B7BCE148EB84EF9F973D60937C34FF +:10A2D0009089FB0EB72C71F2BBD99F7B8AAB060F1E +:10A2E000039E3C8CA771D8E5547F4B8CB604DF4BA2 +:10A2F00045CB41D81DE7FEFC6D7E8FBAB6398DDFA8 +:10A30000BF2CD995BF0AEFD97CEED17E82F5974458 +:10A31000BAEC90476A1A62F97C9EDB53BFCF2BDA06 +:10A32000D8CF67E0E7BEC1D28E777DBE1CE7A2AE74 +:10A330005711C06C534CF5BAB6631AF6D1503B4B6B +:10A34000E8BB21DF655781DDC41E645F35EC32B6A2 +:10A350009C63B371AECFB177FDF73EF7EAF337F404 +:10A36000DAF91D7A6DEEF89E90FFD72A2ED8D3CB5E +:10A3700023DD3371BFA1FC900D91B462629C5BBE82 +:10A380001F738F7C3FA6F48E7CE66773809302DC9C +:10A390003B19C9FBB8DC4FE990EEF7FBAD6B0FF44E +:10A3A000D90D7A0A78F91D827297D71E17241F9546 +:10A3B000352AA677248CFC0B8355C99748DD00FC11 +:10A3C0007E7C479A1D6F39CD213109F1997B412758 +:10A3D000C33ADB513D8E3F99982E0ECAF7BD14FE4D +:10A3E000BBE4182FF8EF5B95369ADFC3A0FA2CDF99 +:10A3F000ED1A1CC5FD95B868DD69485D3C4F8203C8 +:10A40000C3A9ED3EEACFCDE3303ECA027E1BEC0786 +:10A410007310F742F95B5C7E1BC6296D90EFD46820 +:10A420006BE438DAEA58FB20C8075697BD4FB05C9A +:10A43000D820DFBD9EA3FFDD119A2FCBCDE50427E9 +:10A44000DCB333EEDD86C2AB449F7F7963AC59CE7B +:10A450006C5C6B037E6677F35EC639DD0E5DDA30C9 +:10A4600086DF3728B77AF9BE8AA6C3FBB3DB9CF731 +:10A47000C25F327BDD23B634CAFF65B0946BCFE98F +:10A48000FB71627A2093DFA9BACDC9F1E3B35D8D88 +:10A49000BCDE0E783F44F081DCE22A6678139DF83A +:10A4A000106F59BECE8CDFCEF944C977FCD795F03A +:10A4B000FE5B60D5ECAEE079ACDF9789F8A1D9B44A +:10A4C000EFF10E9770697C1FF6C44333F9EF056214 +:10A4D0009E1CCFE6718FC7BB5344374CD706FD187F +:10A4E000F7F38DF1AC1EABB4C77BBE6B9F7A0F4206 +:10A4F0004EAF277CC30FD0DD3EB5E302268D6B2F18 +:10A5000097EF075EC1EFF4FDFAFF016A916CD3008B +:10A51000800000001F8B08000000000000FFED7DA0 +:10A520007B5C5565BAF0BBD6DA57D8C0668BB051A4 +:10A53000C00D0262116D10101575A1805B736A6306 +:10A540003729C48DB7500191ACA89FF3B10D6FA905 +:10A5500095262A9675B6A68D957570B2461B9BD921 +:10A560006A9A5D0F3A8DD33953B6CD32BB09D234D6 +:10A570009F7DD399BEE779DEB560AF0DA475A6F9CE +:10A58000CEEFFC3EFCE3F57DD77B7DEECFF35E7630 +:10A5900022634CB23136789883B1818C1918934577 +:10A5A000C83FA177FBED02639571ACBE2D13D22895 +:10A5B00056FF6B0B63DFE3DFF89E74A253642C8FAE +:10A5C000B1DBA05D1B7CAF10D9ABCCD6F33DD3295A +:10A5D000D0F78A1436D31DD41EFBC37EE3D5EF1308 +:10A5E000FC698B337BEAABE356D878BBA9D07E9A63 +:10A5F00005EB8BDDF51BA83ECFB3E92691C53236BE +:10A60000DB04FF87A594487B56C4E632D6B057706A +:10A610001AA1A8E14189B118489F8BF0B164C6BE68 +:10A6200068F8CD3BB740BDCF376FAF64437BE635AD +:10A63000C73F8A39463036F75236730C606CDEA558 +:10A640003194560FF364380706D5DBF85CBA07C6B9 +:10A65000BFAD2DFBDC7F305AB79FE530F6FE73BFF0 +:10A66000FDE368E897319FDE7D4DCF3A66AD3EA1B0 +:10A67000AFB204C38DAF734D4657158379CEB6186C +:10A680001C1214CD5E5EC5649827B333671AE413B9 +:10A6900075CC2B42BF6CFD16D904EBF330FE57B5D9 +:10A6A0005C90A95D63BE4F82F50C867AC61C5EDFA6 +:10A6B0000CF0F7580C678448A8E82D910319BCCD1D +:10A6C000F7293DF81D0CA921A707EF890A1DCC5ECB +:10A6D00057066D7BF0050333960FEB651CAEEAFC65 +:10A6E000A72AF3BF6DBD20FBA0DE0D4E07CF572775 +:10A6F0001BE6C17AE7AC4F36CC86B45CF95E3E47C8 +:10A700005BDE8D2FAB8AAFCC9576584F571BC75762 +:10A71000D73A3DE1AB6B4F2F7C2531A9671E7700FF +:10A72000BED8008E2F3682E30B53C057A5332FA817 +:10A73000DEBF707CCD7EFEED0F5E76D0FAA8FFCE38 +:10A74000078DBE1DD0FFACB6BD84B7F2D51BF4C9D2 +:10A7500050AFCE994C7051DBCFAECFB63280E76DA3 +:10A76000ABB7EB1D16FCEEE893EE219559103F4177 +:10A770009E099067BA40BC3BA2A77E39A47B619C2E +:10A78000258BCD91ECDA9E71B628F43CBB3EDA867F +:10A79000E3CDAEAF7A886571FA7767F6E6BFB36648 +:10A7A000CE17B3A03FE4CFB345CE24E48B0A51D4F7 +:10A7B000F09B9A3E847883793D06E03523FEC3DB27 +:10A7C0009E46380C5E14E66C864FA9A9011F8E8B3D +:10A7D000F48CF33688CC6B827AA935818B388F5410 +:10A7E000A0286C8769848D52160BF91D30ED024844 +:10A7F00053249EEE73F2F5C3773F7E6731813C5C54 +:10A80000BF4ACFA1F46A603B57A700FE0D31CCD9F7 +:10A81000ECE8A14FB51F953E55FAED6F7D7BAE700C +:10A820007D6793393C598633C904E3563E3CCCB925 +:10A8300046B8FC3A0D61000F5BD07A81580B6C7DF5 +:10A84000AC3735905776CD0FADB7A524B68FF586CA +:10A85000AE53E5933926CEC3C02751019877D7FA76 +:10A86000A1510CF12D302FCA9DB38BCD22CE5B5D53 +:10A87000D7534D5019E6B6BBC944E9334DC068C340 +:10A88000003E4D76CA3FDFE4A0B4AD2983CADB9D0C +:10A89000369A3F6381886980A78A3085FFFD3C8FA7 +:10A8A000E56541E5536D9CEE4E5B0311B62039FD25 +:10A8B00071BD790D8B42FA0E3C88FCCC1A87B25DD3 +:10A8C00030D4E9F56723C44CA44F3E3FB5DD127D7B +:10A8D00027C93F166170EC02969BB124FB7423E0FC +:10A8E0006BEEF2382790129BD13894E4C20C6FB40F +:10A8F0009300B07E0B4378CC53E460F892AA952382 +:10A90000B17E6BB2558071E65A9CE75AA9FDD5CE4F +:10A91000FBF17B4B99212593AACA26906377287275 +:10A920006C89C0DCC88777A09C44FE120FA5A2FEEC +:10A93000B9A355F01B29CF560B00D721CDEED27805 +:10A9400094135B05E70E6CBB0DE4A9A9479E760D39 +:10A95000737F817A817D07F407FD5F252002715D99 +:10A960006D721CCAF14D827517C379B90D089F0528 +:10A970000A9D9C6E3913E1C8EC81EBA3F85F10656A +:10A98000CC238B286F1B143D86644079454E0E31D5 +:10A9900070F841CADA113F3AA709E9A0CB9212C573 +:10A9A000FA286F884889C3F239AD12C945959EAA25 +:10A9B000D535287C3317BEA3DE2B912A6291BE5673 +:10A9C000B64CA474CE8692CD5EA0E324C11D3B9A02 +:10A9D000D6A367B89E39B513AF47BC55EF30469B39 +:10A9E000006F497A6F524E103FCED9BE2A8941BBC3 +:10A9F000F3DBCDD351FE175BCB8AA3A1FDBC6DD198 +:10AA0000D952901E49CAE67A6441EDC43806F0ACCA +:10AA1000F9FB9127ACA08FE7429F56E8FF9BB670E9 +:10AA20009F17AAD434ED4F9280E7DE3179E2B3A1CB +:10AA3000FE42F1E02DA3501F08BEA7E2A9BE23CE1F +:10AA4000DA873C50D373C00F0EA0F7DAFFF51EF57E +:10AA5000F395F8D6F5E5D0BEA6F68548EC67E1A6F5 +:10AA60003FE45BA1FCA0E849C3FE3F17B63F654544 +:10AA7000026CDD9E857A7CEEA6B4284F1FF217F992 +:10AA800000F151BD5F20F8AAE5337C510684BBC7B5 +:10AA9000CF0C564CADCC80F47E5E628D680FA8F66C +:10AAA0008C5A3E329BCBADF351EB93904EE63FB5C3 +:10AAB0002509F5CC67113C5FF1D4AD6FA0DCF2EC59 +:10AAC000341A10AF1E1D3338519F7941BF221D55D6 +:10AAD00003FFC693DD61AE047A2ACA0E27B8CE6F93 +:10AAE0001D41FA519D177CA7F2CF74CC85F318D283 +:10AAF000DC998D74FF679D7F2EE2F3CFF566A71773 +:10AB0000F199CDF5DB9FD74BA558EE0586417BE447 +:10AB1000CFEB5F8848B5F4D86F25D2FBB28476D6E8 +:10AB20008B4236EAEDF0CC76C32CB21B18D1599D7E +:10AB300095D359C3017DE9E018B2C7A8A446E73709 +:10AB4000F485AF058ABDD59DDFB7D7807C52B3872A +:10AB5000DB11356D67C88E50ED925A859F17EE391F +:10AB6000437685DAAE6E1F874BED3E5E5E9501C87B +:10AB70001DCDE5800042BA0AF105F9FBFEF5D7D3F9 +:10AB80009769F27B297FDFB5562E0F759D49A8B7CF +:10AB9000D6649C3420FE6B972BFD425E1F34DEBCD6 +:10ABA000EC81042F2C1F6AC1F60E8DFD50BB2F9A2D +:10ABB000DAFB6BC356A3BE97EB2C3A4C9B6B2DA4D0 +:10ABC000FFB7D58B19BA5C9C5C9813EDB983619182 +:10ABD000592847072E3C650648026A3B8F8850BEBD +:10ABE0003ACA732FD2671C03AE90506FF805B45F5A +:10ABF0003B5EF97404F63F6E48E06B0653D70BBF1B +:10AC00009B5E0CF26419982D641F670646201D0F89 +:10AC10003CCCE5F4E37AB61AF51BD3B9D93428F75E +:10AC2000A3DC423C7F1BE6DB05FFFF1DF30FC6FEE6 +:10AC300099C93F14DBBDA4D0A7DB68592DC0BCAEB9 +:10AC40001EEA59834BBE41D05F932D220EA434AC33 +:10AC5000D7A1E7DF557B758222A713C18E40BBC801 +:10AC600030C86E413A6E36F3F509B2CC1A611EF760 +:10AC7000671E9E8D7A7A6DA78919619D133AC3C8A4 +:10AC80007E4D1CE422BDD66C4E22BD2D3874AC0224 +:10AC9000EA1FCE14FD3AACCF4C3EACCF4C2176AE81 +:10ACA0006896B19D70F0B56F51BE0F962E1E8982C9 +:10ACB000F50DBE477036439DCAAE738FFF1BA415BA +:10ACC0009776ECFD5748FF2DCAB313E17ABACB75DE +:10ACD000C603A85B6B6D3339B9DE60C1EB3878EF22 +:10ACE000B79136B1677E1D9DE79EFB4D2EA62627A8 +:10ACF000EA9F090725D21FA1F3E9B0C3C487523DDB +:10AD0000B23B3B2CA24F10B0FE91F7707E134C1655 +:10AD1000BF84F6BA49FF65B07E618EC4E87357936D +:10AD20004A61DF8391108B93477D74D14276EB3873 +:10AD3000850F553A7B2B9BDB8F6F297255853373BB +:10AD4000C82C58AFA8F06CD6ABFA2210CE327BF8E4 +:10AD5000769152AFEB9228931D5E6DF431E8B2EB21 +:10AD6000E050D233FDC9D93FA0DD01F6C4F254F959 +:10AD70005D842753F4EECD0AFC54FD2D29FDDFAC94 +:10AD8000C0F1668BC8E1765308DC147A0AA5971ED9 +:10AD90007A8841DBA31BCFECBEF6A351C984DF6BDD +:10ADA0001EE678FD90F0FAED5B2B80CDD8A0BF4D6C +:10ADB00021FCFE0C78F58BB93F02AFEDA178F59B35 +:10ADC00087215E37896467A01D8876A307E5C0B533 +:10ADD00094E7F66006233951298539D724E3778033 +:10ADE0004316C987A3281F54B930C415B806F5E91E +:10ADF0006970E5717E01B18D97E7A4105D24B0F60E +:10AE0000782C07BCE7A17D279986667E0C72B7E592 +:10AE100001DFDEDF403FCD826FEB3C988FF7668B22 +:10AE200013EDB70E9FE8D5C33C5AA259D67E18BF82 +:10AE300065FE554E2F9633456E4C37F8D07E83EF26 +:10AE4000498DF8BD9C7F7FE9EF671F44FBAC338DD4 +:10AE5000D1BA5AB2593ADA672D6519F4FDB7AADCAE +:10AE6000793082B72FE3F4DD32DFE6433DF4E8A327 +:10AE7000BEE1A8275AB6CBF136480D519EF81C9872 +:10AE8000FF2089D37D4B329443BA597097CFC57E4A +:10AE9000AEE1F30D94873DFF1474654E05D106E5D0 +:10AEA000A71B2376A05C55E974F0302EDF8778CF9E +:10AEB0006C45387927B08C7AE8FF4385DE54F80B6F +:10AEC000C0368D00F798103CA87417A3C05F58CA0D +:10AED000E9CF3B41594F1DF3A1BF910053090738FA +:10AEE000571AC1F0837496D5938DF36F5E0CF89169 +:10AEF000701D1C0FA74556DDD6075F15E628F10D1E +:10AF00001802F9A69271BEA944BA427A6C04BA0A30 +:10AF1000A2471648883E17AED015CA8308F7B81C5A +:10AF200058E757C21FF2B1F0ADFF94A6F735CEA493 +:10AF30001C2E2F1E337B4A7348EF4DD0D89D6F6572 +:10AF40007F9A88FAE5F4BDAF25609A14E59E8CEBF4 +:10AF5000D85CFED75214FF1FC607F4B88E0FCBFF84 +:10AF60004F22DA2D954B5F23FABFD2799699983705 +:10AF70001CE01E5D2C38FD00BF792D46E724F81635 +:10AF8000575C750CE159D66A74189156D8628D1CBD +:10AF90003B2B8F40378A1DDA6A24BA39F74B89F484 +:10AFA000C1B9928BAF0E800FE756084EAC57D63220 +:10AFB0006C2590372B2916A85E9957A07A65A91C95 +:10AFC0005F271A05A23740AF253B28DE31A7F58E53 +:10AFD000A988DF13C55F0FA4F8C17A1847E5632E6F +:10AFE000DE489E9529F5AB561B9147BBBF97B5AC84 +:10AFF000BA88FC3FD31B52DE3AE953ECB7AC515B45 +:10B00000EEC635821D77574E440CCA07E664CEEF74 +:10B010001148F240F20FFA93BB407144CF300FC297 +:10B02000C389BC617AA4EB990857A0DBE8A57CDD55 +:10B0300033A70ABE49B0CE9916CE671F9609BEFB4C +:10B04000053EFF0940EF65501E0B745D16C3E438E2 +:10B0500048DD26E60FC7792E1DF609CADBD338D4A2 +:10B0600028AAEF8FB4A15CF7E81189B7322FA5E5C4 +:10B07000CC47E9EDCC4FF398C13A937490AF93FC71 +:10B080002B318EF32BB36703D2D75F8B4E9C16E028 +:10B09000FBDD3942DE2894438D0368DD975B1F702A +:10B0A000A5807606AA41AC5F96E37E14FBB3CA4C3A +:10B0B0008F71AB74958E5A993715D617BBDEE29B0C +:10B0C00004EB8B6BF51CC2F5A64F373810EF8313DA +:10B0D000F83A1374DC9F3F546E60A3810E363F181C +:10B0E000E6433ADBBC3520DAA1FEE6038001CC97CB +:10B0F000AF14BCF0DDEA614E8CD359751E11EDFE24 +:10B10000A2568F1808E2A7E1B241443991BED32379 +:10B11000A29EB45AD7533D355FACD44F3779065908 +:10B12000C94E9E4EF4335CA11FB59FD456835F0475 +:10B13000B817C94A7D99B757FB618A9E56DB6139BA +:10B14000D2677AABA34F3F454D5B503F838FF808E2 +:10B15000C605D27BCA1F71FDDA84F01B78F3AB36CB +:10B160004C370321F8711C9DC74CE379F83CD3158B +:10B17000DA87BFBF7F8FE3631EF0BBB9F5FE22E421 +:10B18000A3CD001FC4F3E69DB3CCD4CFF4599A7974 +:10B1900031A986F22508074BEF753CA2CC2F3DD58F +:10B1A000235A69BDCE4368E7A5CB8CE2016A3F769E +:10B1B0001D7405F46A777A857ACCCB905A94B84797 +:10B1C0003A8EB34E40FF315DC157496BFD6133F696 +:10B1D000E366145F4CCF85FEA1FE268483A137FC75 +:10B1E00042E7995ECCE77342A9DF8EF194746CE775 +:10B1F00058114374C5E7D7D5EA14621C97B18FA0E4 +:10B20000FDC9907E9EC2B80CA4CF4E7E6D4A2EB46E +:10B210007FFED19776B4D0520E3EB30FE556ABF514 +:10B22000E69B709C83229FFF4D72E25D98DF6D204C +:10B230003D9ABE534EDB44799313FDEBAE56DF557A +:10B240002F42BD2C18C664EB3D8F130A9CDA153AC9 +:10B25000383979CB205CEF5345772C5802ED875F66 +:10B26000F7388D3B7CCAFC9416C80F9BF8CBAB30EB +:10B270007F5F8EC73C02E4FEB0D25FDEB60FE56AA8 +:10B28000E9FC1C8297C57645F2A939DAE3F502BFDD +:10B290003747DC528EFCB8D26670482477EB19FA37 +:10B2A00059CD1177DBB1BFE5D1F9264C0DD6BF36AC +:10B2B000A19C3C6EC931211E9A2D131896EBAC0A45 +:10B2C0009EBE1B4FFA40528872778473BA4C74E565 +:10B2D0006428270C0906ADBCD671792FD91D3EB460 +:10B2E0009FBAACF54881CC600954A07C935479692D +:10B2F000717A713CC9E2B4A3BFB44291372C86AFD6 +:10B30000D36039F79F38AF5EFD632E96504B7F8632 +:10B31000B0CC2841F93FDA9BC6103E575383C5BBDA +:10B3200018F544687F5D2070508EA34F4776337EBA +:10B3300048EEDD5EB21B347AA45B5E7AA2F521F2A0 +:10B34000521E817AA2582079E961EB0CB8FE120CEA +:10B35000B2005C3CDBB85E54F97B26CE05F0E549D3 +:10B3600065915C5EE9E473260EC6EFD1AE5C2A45BA +:10B37000221E025EC9E0E9C39FF778937F501E9DAD +:10B3800041FA87A90790FE21FD44E10F8F8A076FDC +:10B39000D9F5A3505FCB12D90395CB8536B4CFE254 +:10B3A000BCD14769BEC5DC2E6897BFA6F51C2A89AB +:10B3B0004B44797962D999C7EF41BDBE299CF4FF0E +:10B3C000A4A56756603C6EA657701A21EF591A7DE6 +:10B3D000F77B986F343A5D903FABF081FB974591D6 +:10B3E000684F08B8CE8C9E75561632839BE239F1B1 +:10B3F0003396403B4FA3E0343B7AE0A1C77A52EF4B +:10B40000F505BC3746FED0FA3FBCD7A8C859773EF1 +:10B41000CAD9A2C6E4870A705DEBF57C9E8DD1D7B0 +:10B4200053DE27393976B91C9EA9D83F9EA5B3575C +:10B43000C6C3F7C06A41F9CEF156A9C8E540E38812 +:10B4400063183F0D2C17483E79BC52A21FDACD5C21 +:10B450009E4D78EF280A905DD8E53DB4925A2B7244 +:10B46000DEA37436178C58946FA7DFE3FE9F47FE68 +:10B470006325B69BD3A2B5832602FD0C40B8BC67FA +:10B4800026FDE9F196D1BAEFF04569EA55AD8ED3C4 +:10B49000E43DAB8BAEC7B0E7AC7B27523CAF9239F3 +:10B4A0002291DE2A656E37C19F251BE633579D4FDB +:10B4B00031B7C72A8BC17EA2EF5A7BB0C7FE893352 +:10B4C00020DFA87854F1133AEF5E7619E376D0AC1A +:10B4D00075DA7ADD761030168ABACAE5DA76BF32C6 +:10B4E000BB9F45B9E8DE38E01BF2ABAE501E828050 +:10B4F000217F6E26E3711FA6E843D5CE2F597A51DE +:10B500008F726866E3453DC273E6D21FE6A75F38D7 +:10B51000B5F3BEA1204ABB3E394E93BFD13544534B +:10B52000FF66F730CDF75BA75FABF95EEE19A9C9EF +:10B53000DF5E3D5E537F46FD24AD1C7A379AD6A36D +:10B54000E2A7BF79BFA5E8A37742EC12359D3AE2A6 +:10B550003F1391BF3F2C67E4BF7C7833D3F8311D94 +:10B56000232482E7805C3DF931F7E5C8EF8F20BFE7 +:10B57000C94FF4A1C2F34373A1C928A27F62E47E3C +:10B5800079A85F729039505ECED4B1FD42548FFFDE +:10B59000670EF39CC7FEBAE30D4B0FF17843881F8B +:10B5A00073A578FF7006CCBF0F79794D2EF7C316BF +:10B5B000EE36AFFF38088EB56DD19AFCA2FDF1EBE7 +:10B5C0003F0ED63B4B041DAEB346E1935A16A07D09 +:10B5D00052BBE8A0FEEAC4402CE63B58676CB4F4CA +:10B5E0008F838B0A0F808F253728DEA9FAC33F1976 +:10B5F0003E450A9ECBB4701A93CBE3905F8F10291F +:10B60000DD9C23C7E7FE03F11CB49EF4DCBC7FDCA9 +:10B610007A2247C859089F9F1BAFDFE31E0F94177C +:10B620008E900B7F26B84CFE47C2A547CF472FD838 +:10B630000DFAA3729D81FBFDDE335CBF3772FDFE08 +:10B640007CB48FF6879BF344E70E07ED97D23EE973 +:10B65000A17B8D611918DF59A1237D797A99908199 +:10B66000FEC226218CFC360FAB4816C8BEB978C87E +:10B6700048FD31AA07EDFD3A90F351053E6B09E410 +:10B68000DFCCE571B1356E714A8A03F5F61FAC1E49 +:10B690008A8B7AE2111E9EFD30E16B69DF45EE2B4D +:10B6A0007E12D06BE5D112858F5FCCD5D13A1F2E9B +:10B6B00014B99D942ABA701F6315D8A968570696C5 +:10B6C000EB285F91C7E9596DF71F0A9DC794DD14F8 +:10B6D00086F388DA24BA7D7D8CFB512E8F0F3D795D +:10B6E0005718EDB3012A7468EFDBBDD6692E58AF49 +:10B6F000BDD0968DB6DFDADC68EA6F4D469715CF80 +:10B70000A1FC8C7478CA8EFEA0C0FA8C33CD55E6AD +:10B71000ABEE0F5894FE36E941BFA29D2298281E39 +:10B7200061F11AF9F91567B126DECA1C020B6EA782 +:10B73000D6F328F46AC7421BE197F6EFD578B15DDE +:10B74000A117A41BC4BB4ACFA1FD8389EC8DCCE912 +:10B7500089F3D915528E1AE5D98D748FFDEA901FA1 +:10B76000BC5CFE076EBEC4E32CDED7DEC37988E185 +:10B770005F529C0CEC4ACE5F4B43E2BE3F914F02BE +:10B78000660ECF4084561EDEABD0C9DA7F82DE481B +:10B79000BA02BC3E9CCBE58FABC0FD36CA3BC7B2FC +:10B7A000D430A2FB1F0B2796604538515EBA723821 +:10B7B00079F33D1F109E74CC6FB4717F0BF9E17269 +:10B7C0007CA4C23149649EBEF4F2883CE5FB1BCAEE +:10B7D0007EAEB76AC80FD9612877C502C6D22CCC15 +:10B7E00061BCB6FF7A0E9C8F85E86A39D2E5AE96C9 +:10B7F0009430E4CF6465BCCA9BD2A70C77A05F20CD +:10B8000018D00E04BFC3C0E33FDC4E57E57A4FB9F2 +:10B81000D67EC4724F668F1FA6DAF7EA773C97820E +:10B82000E3AAF359A5D861FDCD7755124B72A2DC7E +:10B830005A768F80F0DCB15AD4F87D715E612503B1 +:10B840003F3ECE7FAF13FD8E38B0AFCD28CF75F51C +:10B850008233085E817B810A381387F82BE04FE240 +:10B860003ABD67895E42C757D7B1AB858F1BE75D8D +:10B870002CC8909F54512FA0DFB756997F5C05A329 +:10B88000EF69993E01E3219E16568AE3555633032C +:10B89000C6F52A33995386F2CAC64374DEEDB9025F +:10B8A00039256F20C94F3A4FE32AF0A4E7011D4D17 +:10B8B0004D28437667B84B86F1897F161DA7B54C96 +:10B8C000F0A2EF59D4E23C84FE01D011C57D3C2D9D +:10B8D000011A5FE7E571725D8BC1E98075488D657E +:10B8E000B4FF21551B9C32D43BB629DF8FF1952D37 +:10B8F0008DDCDF0DF59374D6FAD7C3D15FAB109909 +:10B9000044010A792AFA5956852E5630773BEEF7CC +:10B910003319FE41BB48A5DC5A3D6F2A6622E5D0AB +:10B920007883DC139F409E6BDC40B2D394AA8D6772 +:10B93000482D2BC9AF33627DA8AC0F897748D5A5B8 +:10B94000141797ACDAF25BF32262088E593C1E9E04 +:10B9500073EF888DB7C27C727F79E31F303D8741DA +:10B9600033805BFEB23B074C87FF16ACD87823A62A +:10B970004FBCCEE89CC18FE057668CFAF1FCFAE828 +:10B9800095F2ABB2260FD0B9C2AF7DD2BF1A4F0924 +:10B99000E54F95FE43F94E4DD75E867FD7260512BB +:10B9A000910F4FDF3B3203DB5736DE73C8C7885F2A +:10B9B0000507D077A577711123BA605697D05B5EE3 +:10B9C00084370B49ECBF371F3F867C3BFEEFE71304 +:10B9D0007F08DF95098CCE6381FD49F69C9AAADF2A +:10B9E00023F2B93EBD906724BC4E46C10AAC3B056C +:10B9F000DAE0BEC778604E2BA47F2EF03C8BE34D7F +:10BA0000813C9EEF7BFD406B0CAE374BC7F58EA79C +:10BA1000DB8EE67648B7FFA8D80F59063605EDDC71 +:10BA2000C02611776E59E0C0E73BD6E2BE6BB9C9BC +:10BA30009906EBCABADF48F484048AF6519668A7DF +:10BA4000B8E5AEB68FCB699FB1D1C0D2286EE00EFB +:10BA5000C3736400CFB0AA4CB257C3AC68AF7A8549 +:10BA6000A4AA881E7B08F5220AB42CEFAD53AC3093 +:10BA7000FEAE42B047337BEC1CD5FE599C9F4CEB8D +:10BA800057ED2068C7B0DD8FE5A74A0B4B22BB19E5 +:10BA9000E683FBF7B64C2690ED1352FFF43223D920 +:10BAA000AF76AF7BCA70B45B97A7E6A0DD0AE39AD6 +:10BAB000246E7FFD3BCA67BB4EF95E28E6E0B949BC +:10BAC000751F800574D1188753EDAAFEE7A563E7BB +:10BAD00054B905957F9B2F9FC17EFF5972DD635539 +:10BAE000E84D4D63F879E0E90ABD8DCF37539A9E52 +:10BAF000FFB3DB73A7AE93FE79EBFE39D7E1FA9F74 +:10BB0000B18ED8FF21F8D83CF97FC63A6E99F24F32 +:10BB10005C87375F6EC8CF4379D646E788EC2E7EC8 +:10BB20002E1CE4DE3DBC9CCB398B930964C7FF74AB +:10BB300079D784FD9D411F1CCFA17877083A1867FB +:10BB400088A5A188ECCDA58CF681862CE5FB404329 +:10BB5000963A4D22DA03166E270E52ECCE414BB9BF +:10BB6000DD19A79C2B888B117D32D43FF6CB5BCAA5 +:10BB7000E7C6E0BE9091ECD5E636DDF516D4535E0F +:10BB800089CE8F86DA89D2D2954A9C5F6B9FAAF6BE +:10BB9000681AE379FDB2B3B44FA7DAA34394F2B4C1 +:10BBA000A57C3F60488BD61E8DABD6DA8FFA82100B +:10BBB0003B73A9BA7FD049EBD32DD7E9F1FC7FA81D +:10BBC000DD897BB0A81407AB7A06B4FE4DD730F6FA +:10BBD000747EF7F98C1CDC1F9AB95AD0E83955CF1E +:10BBE0000224287EA4E2E343D473883FF734B55F90 +:10BBF000D26F3EAF48704C2E4FD79C5362EC7E1EE6 +:10BC00002F71733AFAF5EA116BD1AEDDB7EEC63794 +:10BC1000317D69FD9DE1E504AFF5546F7FCBC6EB47 +:10BC200030FF5076BB3D12E6F5D0A853EF09D0EFB8 +:10BC30006A3CE385EBB378298FB6149E8BD0B37A38 +:10BC4000DADFDBA40F4C9F0DE52B12451C91BE23C0 +:10BC50001D9832189D9F3059787EF5358CEEE33073 +:10BC6000E55C9F1A87093DD7B7CAC3C75905F0C419 +:10BC7000733596187E1FA939E1FEE908EF668781C2 +:10BC8000E139398B72EE4F62D5AE2AA877DC7EBFE0 +:10BC90007D16EE0B6718887EA498CE26C493D99E95 +:10BCA00063AFC27142E235CD29E9372059BCB5FBFB +:10BCB000F09E67207D7BCFC92F319D2AB5EFC3F35E +:10BCC000255246889FD26BBF9811DC9B87335F4A11 +:10BCD00032963B6E10914E75EB6F9A86FE54C150B2 +:10BCE000E71A584F5802F31B601E61BDF689797B35 +:10BCF000A9209CCED54896F5150DD8DFA808BA7FA7 +:10BD0000C0BE03AECBA7F34DF457F680A8473A0E5A +:10BD100053F68FC3327BED1FD3FCC2304DE1593B4C +:10BD2000E4C3157A5F637BCA87FB776B13526E108F +:10BD30001D3DF5695F19D6BBF2BB1BAB685FFD26E5 +:10BD40009315CF9F8529FBCAA1E374A53A5B67438E +:10BD50006AB418647316F1550F5F72E0D85383E626 +:10BD600001F5FA9CA73A6E731EC783DA9FD1C264AD +:10BD7000B42343F7AD43FB817970BE56EAA9FD3188 +:10BD8000D646E70174888B517DB5ABA7B90DDFE9C5 +:10BD900024BB1FFF82E382CC1A43FC35AC55DBCEBB +:10BDA0009CCACF0DA8F4182A2FA5D0FDF7D47A6F1E +:10BDB00038E1819F2708AD1F0AD7D0F6F0B7335876 +:10BDC000DEDD60E1FB885DA99DB922AC7BA53D4726 +:10BDD000337F5ABFD0D37FEFFD3C6DBE4C36F6B9F2 +:10BDE0003E94077DCD77824EBB6F596CD1B62F8DB7 +:10BDF000D17E772568F39245E9DF916DA2F31A8E23 +:10BE00007C139EF753F9D818E2EFF78ADF2AFA2E4F +:10BE100091C9741E7593DE790EE5C4E33340D201F7 +:10BE20007D3C2CF8CC582E55B45B510FC6ADD39346 +:10BE30009C7AFCAE5BCEE0BDA016A06B84E571F7EA +:10BE4000479B6EC57CB148F10D9BFB7039D251CB3D +:10BE5000775FBF371BCF9F3A0D74CE5B3DB7B1758F +:10BE6000AC612B1E0B8ACB94CD69F0FDA12AE68430 +:10BE700099B02363632371FC2DD1A215F5DDF3D1B5 +:10BE8000F5FF8E7194E6198CF61942E15737D246C8 +:10BE900072366E75B680F75B1E1E9B5F8972310627 +:10BEA000FC6594AF90CA7DC517C715F0F8C0B6C53C +:10BEB0002FC523BE37580FDB699E15A213A7D85292 +:10BEC000C1E57F8B85D13E7BF3A852371E4DEC72C6 +:10BED000C90E3C8BD8E2DE41F35E592D72D9AC9C81 +:10BEE000970158C851399CBE0C364AFD986E34B340 +:10BEF000F839289792C2E87C507FF681B484CB57FA +:10BF00006C6FCCE9BFDE43118DF1C85CCB67E49F59 +:10BF10009F0BFD6D9DB199F2AA3C8D53E8BBBBDF31 +:10BF2000103DBA1BF04B72361AE42C9EC7638E8705 +:10BF300089B775F5C2B4203AD555807CCDE2E72E9D +:10BF4000307EBBBEA834E387FC4C9D9BCBE51855E7 +:10BF50001EBBEB9761DC05DAFB515F633F78CE0FC8 +:10BF60005219D7B751A83F447EF30C8303EF39E849 +:10BF70002A400E437B5D82564F1C18C9F135FBC128 +:10BF8000BBCC9EA0384D8C721E66A3BEDE9C06EB19 +:10BF9000D93843746E07786CA96810FA8AC7C455FB +:10BFA000707E990DF5D16FDE5291131BBC9E668C8D +:10BFB00073C0D036D70F9FDBD385C8BF5D2379BC54 +:10BFC000BD67DD1CBE71403FA8879A4797AEE66A01 +:10BFD000DA41725567E56D6DAE7A3A07D955C1CF32 +:10BFE0005DAD13F87E82A4C4CB9B8BF249BFF44BAA +:10BFF0002F152B499F84E2579D3FFDE507E91199D5 +:10C00000F1F119879BB4CE4CFAE107DA3B74F94A97 +:10C010007DD40B1E6D7FBA625136E3F8A85F10AF76 +:10C020003AE6C57B93A1FD952AFC163A1FC969E043 +:10C03000EDB19D8DF88BF4DB6901E0C8E982CEA1FA +:10C04000B3F7383CB7243A7C6BF8012ED28774AE34 +:10C050002BA5F7788F098E65B8EFE87D5DA2F3E731 +:10C06000A17A4FCDAB7030B136E79C3EEC4D9C0FC2 +:10C07000EA3569A7D789FA01D0978AED362A4B09A4 +:10C08000BBB3D45CE0E8ADD7BA5C6DABAF82729362 +:10C090008399F6033C4C53997F30C079ED33CF1C24 +:10C0A000BF8AF53D0EAE03F899E0BCE6F94733E6EA +:10C0B000407BF3EDAD26B4B943CFA1F56EEFA47686 +:10C0C000714BAB4CD319C5236554B986080BD9AF56 +:10C0D000CC7486E4B334C9C6EDA7103DB90EF85050 +:10C0E0008FF04A6404AFD03871E8F84905C9FCDE26 +:10C0F000E4E2521A774345A71EE3905DAE7AC54E3F +:10C10000F2F4A9EF42FBB17B3AA723FF77151AC8D7 +:10C110001E7EF8C1499311CFDE6512C5D17AD17B5D +:10C12000C8BA3D23F59CAE1C8BCD287FB7CCB9DBBC +:10C13000ECE8C3FED852318BCE2F5A96703B63A5E4 +:10C14000BD81E488A542B9E7A2D8CB71AABF13A2EA +:10C1500027B7543798F1DE9B7ADE9085D8DB97EDD0 +:10C16000BF1FBDBB61F98BF1A84FEE2A6988C77963 +:10C170006F89F04F7713DFD5939F02F2381EE5F1F8 +:10C18000A2910E922FDDF27FC6393B0E1E18695523 +:10C19000F88ADB435FE27F41BF668D92A714601C83 +:10C1A0002DB5448E7660BC74DFBBD300AE93BD7AF0 +:10C1B000F2638DFB81F4C12F322638495F9E1E68E1 +:10C1C000B0229DAC6AFC468FF76BCEE2E955E87F62 +:10C1D0005502B78756C51898DF42F3A1454F752E13 +:10C1E00066A8A7F509DC3701BFC58F79162310FDB6 +:10C1F0004C8EF1BAAD00872931BEBB30AD4AACD709 +:10C20000D9609C1247B480F09DA263C5061EAF9D05 +:10C2100085F35C11F311C55927A7C5D17D54A3C57A +:10C22000ADC3FBC97A67D5F6B58CCE8B51BC15B0C2 +:10C230004AF7E18C18C7BDB6278EABEE13A9F1DC27 +:10C24000750529042F21C1FF2DE223CB1A10F11E01 +:10C250007E983E40F6F8AA4613F941CD093BDA91A3 +:10C260003D3223F83EA47A3E17E063B1027C560CBF +:10C27000BC9BD6959414BB17E7A5FA91F120AF505B +:10C28000DE6525CC9B8AEB4B7AC3ED4A867AC60CD9 +:10C290005D366016E0EAB9A278AC1EC6213C58D8DB +:10C2A000384CFBABBF22D140F1D8D0F2270B785CE1 +:10C2B000320B0521AEEB5E13DDCF5D75E0BEF7AA54 +:10C2C000507E1E3039C967678114BCFFDE1D77665A +:10C2D0007CFFDDAE9CBFB5DB0D743FA63BBECCF84A +:10C2E000BEBC1AE7881AE5D98C78F231C721F4C7A9 +:10C2F000FEAB718F1B46CA4F607FAC6DC015C56326 +:10C30000C2C6EA689F2729857982F7055629EB5F1F +:10C31000D50D877A3BEAF575289407F60F878D3798 +:10C32000E7BB2622DD46EC8847FDDA47BC431317FE +:10C33000C17B2879B10462FA93AA799C2466EA3C0D +:10C340008A774853F93ED90A1660FCDCA0C0847C89 +:10C35000BAEA4BFD0D7087E8D7CC7A929391AE90F4 +:10C36000B8482F7F45E6766588DCDBA2F0F9F1025C +:10C3700025EE91CFF2BFE79325BB2852D9F7891854 +:10C38000954272E811570AD943C41C41F0BE9C9DE6 +:10C390007350B1877EA79C8FF72BE7830F2BE78322 +:10C3A0005FC5770BC0903F86EF16407ABCC949E560 +:10C3B0006F341528CA99E36F45EE9248B21F94F97D +:10C3C000E994F9ADB04E7325037E566DD3D37958F9 +:10C3D00063C284E968CF32AFDC9E11DB73EF8775EF +:10C3E000C2BFFC9E73A75D091E3A4F3AC7CAF73F0A +:10C3F000557C2D54EAAF12B619905FC7766AE136C4 +:10C40000FE52A4C6AE2C62DAF397134D4334F54BBB +:10C41000ACDAF39793ECD76ABE4F7668CF5F5E973E +:10C42000313E641F564B570B13806E804EAA337DEE +:10C4300034FF85D6528A7BCD0DB9C77447AB363FE2 +:10C44000DFA7CD2FDCADCDABE7C9C34629F43092D1 +:10C450008DFC31F14EE4F70C85EF0701BF6FB33A65 +:10C460009911DACF1678BFF81EC6001BED4BC976BE +:10C470008C23ACE3F79FB05CC7CBBDC395F67ABE07 +:10C480006FC58EDBE8BE1D4BCCE1ED06F0EF7EFC08 +:10C490008EA4F1720EAF87FE12D61BA2F453C3E531 +:10C4A000939C45FE829BEC33236BB3626A01FEC210 +:10C4B000349A39E99E750CAB27BF7590727F325163 +:10C4C000E8A4BC43B086613E4570A6F0F8858FE4D1 +:10C4D000C35049FE752AF1895B7447F4E6970DB99C +:10C4E000BA07F0AAF8860291E4E2235646EFF9D89B +:10C4F0005CF713BF6EC316B06E336B8F49157AF8B5 +:10C50000E7EDBC61C45F135C0EDA2FB515240B7820 +:10C510002EA588859CCB364569E8A3C41A17425FCF +:10C520004342E84B4B7F7F9DECD5453990CE42E8A6 +:10C53000F02FBEE5512C18AF4C8FFA058FD58976B8 +:10C540004A059ECA02964F75469B31EE678BD173A2 +:10C5500079A5D83FA54A9FABE459EBB2E1FB6B56F6 +:10C56000D149E6F6BA2D3DF12518DF9600F635EAF9 +:10C570006399915C7DB0D31F7635D47F04FCFF6551 +:10C580000CFD1BEB64BCEF65B5E4105F3F624979BD +:10C5900000F35ED0E8587F4331F7AFE5E86C82EFF7 +:10C5A00051A1BE05EFA53DC2F24CA9C1F52DBCFEBF +:10C5B0007A596451909F183182EABF9D6766F8CE20 +:10C5C0008177A0D98771EC63F2AC77DD41EB7F7B9B +:10C5D00014D707AF191CF1A80F1E997C77A687D234 +:10C5E000748D5F684B10E4BECE17858F3672BD9296 +:10C5F0005BE2C7787C74C234579903FD1DB70BE921 +:10C6000042E712F1E85B37FD442B7EA8E406C10F38 +:10C610004B9B745D0E43FFE3110B77351E299ED5AE +:10C620005286F90291EE03D95CE2EBD9B8AE027EF4 +:10C63000FEF04AE571A81E18329ADBBF9386443C8F +:10C640003014FADF50245AB1FF0D7A2BDDE7F14E9A +:10C6500066E45717BBEA97E0BC6D09110CCF6FDA9F +:10C660000A1A78BED8C0CC004F936BBD17F1694A47 +:10C67000F58CC0F647077E7A1CED195B82483A704C +:10C68000A2CBF9AE1BEB1728F19DE279EB703C9B36 +:10C6900045B49A590F1C54B9BE9EC9CBC9FFB20A02 +:10C6A000F4DECC0A6B430DCEE7918470B2F36DAE2D +:10C6B000060BE279C3403DD14149227F576A55C2FA +:10C6C000B40ACCFF62A09171BEF32F1F8AFE815382 +:10C6D000A075355B1A685EC72E8939C1EF96A8A987 +:10C6E000D9A185CFEF46F1F89009E3F1809FB7F526 +:10C6F000CC9C9A8BF4A3A778537F7C6B735DCE7E22 +:10C70000FB61FE2A94030B11BE8597C2984F40FA35 +:10C710003D2961FE777F015B80D6D960C1FE416E05 +:10C72000BBFAA2BF88D19C7E9B0B0E4BF84E82D7E2 +:10C7300021101F345B4E4E443E7828B58CE8E8A1AA +:10C74000828F9A892F86F3FCDB79F7EE413C7A13CE +:10C75000C3697FE7A1825931C1F4BE609448F432C5 +:10C76000EE6F614E3FE2639481F8FB9108C7568CEF +:10C770004F79F3CC64BF4B8275D96C98E7C46228BB +:10C7800087FEA25D623EF17E75058F0B2B307ED554 +:10C79000653B84F8904A66317EAE4939F71491EFD3 +:10C7A0005C4335B4FA6F952597DECFD892D07042AE +:10C7B000D9B620BB6A9022570694884528DF0659CF +:10C7C000B85D65EB940594BBA1FB47AABED729EDE4 +:10C7D0008C325BA6A3541B37D215707D1B6A7FE990 +:10C7E0002CDC5EC33FBC8FAECF353F89E738743158 +:10C7F000DA7A7F19A59C730AB1AF543ADF60E57A03 +:10C800006243AED18774BDA198DB592A1FABF247B2 +:10C8100085BF2A87D47B7EEF28F695514E5E3687FA +:10C82000E4EA99E5786F07D49E7317C37B8956FABB +:10C83000FEAE721FF194626FBDA7D85BFFA1D85BFB +:10C84000EFA3BD05F986518308BF37142E76DD08A6 +:10C85000F31A902011DF143A4E4CC4EDAF71192732 +:10C860002C7DD96111D1A20EE3058F34F27B4936BC +:10C8700097ED9815F159CF95F92C6B766934BBBCBF +:10C880007CF2E37AD2D13EE4EB7B55B94F794C99F7 +:10C89000FF7165FE6F28F357ED8F4943BE32A1BC8F +:10C8A000DF10AFEF477E29FC29A7D0B9A85079B592 +:10C8B00001C408E9EB2291FC9F2078E76AE4BD25DA +:10C8C00020F7F54E59C9681EBFDB6076572C467CB1 +:10C8D0004E6614A79DE8AA27B96503B94572B3F857 +:10C8E0005CEB6CCA473883E59E518163B1CB5A8EAD +:10C8F00072BE38464F1F5724A4D0BD5BD5FE0E1D17 +:10C90000F772F00C9567A682F55EE2F3FF47726C52 +:10C910002CE3E38EBD243AFD5CDE1C4F2679239187 +:10C920007C0AED5F95376F63CC6420BE4F64A1FB3A +:10C9300000770A614E84E79D287C303F97D17DFFC8 +:10C94000C18A3D6757DED1014EA1B8CED84EB0F5B1 +:10C9500083F87AFC2553F71B6CDC8E8FD6E4279A7C +:10C96000E235F54BACC99AEF93ECC335DF273BB208 +:10C9700035F9EB324669EAFFC259A4C9DF50305994 +:10C9800053BF4C2ED3E46566A577480E36ED1EFAEC +:10C99000B11EFDA7B6A11FA7F5864FA1F1F00B0EA2 +:10C9A00060E1B5A38B67E80046855187EF4C86FCB4 +:10C9B000C6D19367E880EF0A071FFE3A195868D37B +:10C9C000E8293C7FF5E1AF5320BF65F4753C3F8615 +:10C9D00091F0DC3A7AEA0C2FE0591CEA797434D0F1 +:10C9E000F12D97EA8FA23DF8C765D3E6264BF84EA6 +:10C9F00040596206CCE76C8AE761FC7E73ECAC15AB +:10CA0000781176FC77F5748FED37A379BB8E8BFCAC +:10CA10005D8D8E8BFC1D0DBBC8F1F65353F5BECB5F +:10CA2000040E9A7EDF5F11647EAF05FDCD3969DCAF +:10CA3000DFC414FD4D4CD1DFC414FDCD397AEE6F47 +:10CA4000628AFE2696A3BF89E95B4D32A5EF34B911 +:10CA5000286D6F7253DA7DBFE029E76A3D0A38EF2F +:10CA60004F8B5B98C3E417114EA1E74A3AF49D4FF0 +:10CA7000D07ECA45E6C0FB1287224E3970BFAC3962 +:10CA8000CF44742E74B63B4CF0BD3097E79B2FB665 +:10CA90003B507E611EED9E8EE8B66C94BFCDB51600 +:10CAA00027EEBB355FF4C7239F14D61BE8DE4C711D +:10CAB0006727C5E90A2DFCBD844311C78E28E39181 +:10CAC0005CDA7991F9457C27C7DCEEB02AE3603F58 +:10CAD000306E32EAB7C225302EF55BBF98FAA9B0A6 +:10CAE000748F2B848C6BFAE171270A41E3A67631AF +:10CAF0007A1701C77568C6F54B743FFCA25FC27810 +:10CB00006147B4D38E714D355F8CDF21BF45CFDFD8 +:10CB10005F2C74F825D493B8BD89EF5BC681D833F8 +:10CB2000D3790D1FC965A84771B99D5D7C9D179A82 +:10CB3000FC0B909F8A957760C08CA57B9B4C0C73F7 +:10CB4000A2BE2891BE3B363817DF39E3EFA0151B94 +:10CB5000DDDB901FEB745CDEB01833DF57D0B5CF50 +:10CB6000FF15D43B193B98EC9504FB4B2C7504B492 +:10CB70005FE4CA44BBE3245B4F72687594E77F8F20 +:10CB8000067ABE31B35E50F427F5637785EFC0FDBA +:10CB9000888E5786E5211F4D333A5E64C0BF7F1FE4 +:10CBA000DD44FC3C2DCA91872FACFD7DF40A9E8F9D +:10CBB00073BC883783ADAC694671FC8F3F2F45F15C +:10CBC0000D749AA70A3AB47FD4735376D1133606FC +:10CBD000E054EBFACAC0E7D769C07870D41807C12F +:10CBE0006FE06146E7983A2747F876E07EDF80FA03 +:10CBF0006C8C87B24C471ED64BD277D27DF28EEF2B +:10CC0000F8FD27A819795350FCFE898392ABAFF841 +:10CC1000E3C931DC4E5D946A598778A8B39B4C9484 +:10CC20001EBC48E78299CE9D8AF16BD9D0F77BA9CB +:10CC3000AF8EE1FA2179A54131024174C294E53009 +:10CC4000A6E6BD0CF4D0F6BBC3BADF8B037032434B +:10CC50009AC8F3DE1D8F17EB34F565ACDFFD1DE3DD +:10CC6000F4ACA7BDFCDBCD8F2F4F55C6437A99C7D7 +:10CC7000C87F0CD53B6B0B6DEA3B3F84E7C763CCA9 +:10CC8000DBE93D5249798714EA5A314E11CEE83D2D +:10CC9000AEC1BF37FB9A819E769A393DA78A3CDDAB +:10CCA00029F2FAEA3BA5EABB6BCF147A6E2BCCA330 +:10CCB0007EFCD48FB4371BDFCB88676D34BEFA6E31 +:10CCC000945A2F01F420092B5D673AE2AB5012FB16 +:10CCD00084E7E7638AE6201D5C68F2B24F82F4CDF8 +:10CCE00085F0C8C660FCD549DAF75A3F1F3381DAB0 +:10CCF000A9ED6B1B27B24F2878E9273AAA4D156991 +:10CD00001FBD4E62AFE23B9C20590DA897D576A778 +:10CD100040DEE278EF82FCC5F43D90BB9FE8D13E57 +:10CD20009D4EE9FB4D1E2A3FDD544D69A0A99ECAC8 +:10CD30003F6A6AA4F496DB2372917F16ED5FC63ECC +:10CD400009A2F7DA36BD2710943F55D4371DAD51EF +:10CD5000E8E85472DFDF9F1CC3EDBB53E3383E3B72 +:10CD6000C0DEC0F7DA802E975B6DFDDB1D1DCAFDAE +:10CD7000AEA3E3F9FE65473CCF2F1FC3FD6E596498 +:10CD8000ADD8FEE87803EF3F45ACC6EFB28DF77B38 +:10CD90002A5DA477A47E35B1E8FE31583F16CA73E8 +:10CDA0007AF2A7AEE2DFE541BC5C9DAFFAFDB64288 +:10CDB000ABFAEE613A7FCF8FDFF7027AA7FED5FAA2 +:10CDC0006326703E0CADEF4BE5E7C943E1F1A9C224 +:10CDD000B7C4176867231F2407F1459D83F842A550 +:10CDE0004395FED6167238A71A153A0FE7E7EE07F5 +:10CDF000A32E847683E3CCB48F20E3BBCBB09E9D7F +:10CE000082C22FA1FCA0BC63ACF283CA072ABD0F6B +:10CE1000063EE3EF34F3758C95FA795F5859477BFA +:10CE20006CC45D84D7837A2BEAADB1127F2F79B0C1 +:10CE3000D8F5CEEDC89FB1110E8C9196ACB2D4F757 +:10CE400025C73EFEAFC243950BFDC0A3171C0CCAFD +:10CE5000BBC33F120E24E7508E23FDF621B74E8C44 +:10CE6000B1297617A7DFCFC7C86F221D7508661DC9 +:10CE7000DE7BE830F77D5FF0E878BE0E958ED61643 +:10CE8000324A07E33A87F6967BEA7ABAD7790723DC +:10CE9000F9971AC6CB43F1ACAE2B48FE9DC179A9D8 +:10CEA000F0640CEC1FE827A1C642EFE8DD56E8E08D +:10CEB000FC36F0D3CA0DAC67FD358A3E7B4C94F846 +:10CEC0007BC88A7EE92E17A49965991ABD4347CF7E +:10CED0003A5FE1EF8AFB45568DEF72A36F1D1C1779 +:10CEE0001F52C8E543D7F43C11F7132FFCD542F786 +:10CEF0008B2F0CEA3C8DF6CE85563D53DE239B2AC4 +:10CF000080DE9D8B3E130CF9A5F29EF3E7E8F70E49 +:10CF1000837A6D174FA3BDB568ABC44C789E60EBA8 +:10CF200037B7203DCD7B454FE7999A5B371E477A4F +:10CF30003CB74FC0E76FD9857D02C5316B5B227C62 +:10CF400066A85F0A79AC7FC76EC9C7E38B32C53963 +:10CF50006A94F13E31D7A5A05D3E71EB5D3A84FB4A +:10CF6000BCED028B837E8FB4DE790CDF1D39B78D6B +:10CF7000DF2F6B3647EEC0F9974AEB0C83A07CC1DC +:10CF8000765E5E6329FD0CF743173CCD28FEB36047 +:10CF90006F04F98FF35AF41F0582EC8EEA6DDAFC08 +:10CFA0007CD666403A58B0535B5EB307F241F279E3 +:10CFB00050A1122F19CEB2295ED2C2E307AA7CEF8C +:10CFC0006D5F7BB91C6D50DEFF667F89A5F70F5F33 +:10CFD000F926E9230BCF9729F93390FFEA1B8E1727 +:10CFE000152E75CAD85FC5B3DC365867DD2B662BA6 +:10CFF000FAED7507CE46E279B04561017A1799BD21 +:10D000002C59D1DE7B60BFE445F8D61E343F89FB46 +:10D0100098752F9E30603CA174DF62B2572631EFC5 +:10D020004AF49BFDA2C8DA898EDAE97D5F2677CEC5 +:10D03000C37E2E1C305BD10EA87BF94FC76EC7FC98 +:10D040008B02DDA7BC9018203A99B755A27B430C00 +:10D050002DB4FC1E3A9110AF88E7B6287A8FE50E02 +:10D06000C43BE219F0EE48463AE171D0794F4BF4F7 +:10D07000BDB9B5D980F5CFF9387E55BC974A4B0973 +:10D08000CF0B1EE7F89CB875D7E630A483A7F564EC +:10D090008F1F817683783B0D1D185EE1FD5FD8C53B +:10D0A000CF9177D3C10163371DE03C2F4707C0A75D +:10D0B000A4F72F47079DE89792BFFFDDB9C7D00EB1 +:10D0C0008FE0E787D5771BD5771A072E3C7514DFDD +:10D0D000E74AB3BF407677A5ED8BDAC58CDE099DB4 +:10D0E0005388E74B26BFBD02D17772CAB3D9142F3C +:10D0F000D507766DC178437438C5C73A92CBB6E18F +:10D10000FB98C5B66F93F6C23A16FDCE48E711EB11 +:10D11000157EC63F3C07A2BE4B0C78A7F319B50796 +:10D120008DFC5CC63EEDFBE11DF19CCE4B0C9D954C +:10D130008BD14F80FE701C41E6FEE9C283FC1D4589 +:10D14000D59F5CA8BEA7B847FB6E83607D9BEA3D78 +:10D1500050984270181A37D68176797339F3840D56 +:10D16000FD217DC1DFA97C5CF18BFAB527FBD11BCA +:10D17000AA1DC9BC21F7DA15B97547019FE3D1BBD8 +:10D18000DFD0E17B8C1D3BF9EF3BCC3F08F22A0658 +:10D19000F719F51AB953A7D4FF14E90FE076DE5B4F +:10D1A000FF922805CB97F78BB19F9AA7793F7548D7 +:10D1B000571457F56F0E83FEBE6CD333E497054CBE +:10D1C0009137FB23286ED44BBEECDCBE12CDF7505A +:10D1D000BA5A0876262E2294BEEAF669EB3D5DA87F +:10D1E000EC7B0E67D7E0F9FFAF31E090D7235FBA51 +:10D1F000DFE9678E28E4EF6E7D2868EFEF0F6B059F +:10D20000960FEA77B8CFC463A44AFEEADD564DFE16 +:10D210009A36BBA6FEB5FB1D9AEFD9FE0CCDF711D1 +:10D22000C79D9A7C5E7B81A6FEC8F7644D7E54C084 +:10D23000A5A93FE6BC5B93EFCA84F5F461CFA8E9EA +:10D2400024BBA0A93FD961D6F47F5D46B426DF6533 +:10D2500051E0A3D899AAFDFBA7426EFF86A62A7CBF +:10D260007FE1D48EA3FAED371468C72B93B5E35D45 +:10D27000295EF01D419D9EFF7E02A6F8FB09BA348F +:10D28000FEFB0998C7DF4FC0147F3F01CB7FDDE471 +:10D29000A4FCBEA602CABF047E09E6F7839F82E90A +:10D2A000CBE09F60F9E5E0774C19F7B832EE1BCA86 +:10D2B000B83F154E6F29FDBDA3F487EF0DEAF43D8D +:10D2C000DF6B5D79E225E0E322DB67745F596E086E +:10D2D00094621CA3F37589E1F967E6F11D6F8A4139 +:10D2E000FD3680A19DC4DC9D6FE23E6EDD8B43ADBB +:10D2F00078AEEF81FD7F7807BF5FD82751BCE6F09D +:10D30000FEB391D8CF9797C2E9300AE945C8D77CD8 +:10D310002B507E0D7CC7736793F74ACABB676DA419 +:10D32000EFBE4C55F33EBA2FEDDEB3D780785AB836 +:10D330007B2F7D7F1DF85AF37DF776CD772BD6872F +:10D3400074A1CE477185CFF7ABFDF9A97E4D2A7F39 +:10D350003FFEF3DD47568E417DBCB76A00C6B51768 +:10D36000EE39113BFB07F0F1D54BCF66A21EA83D6D +:10D370002029E7D1787FB507F44A9ECFBF26756F85 +:10D38000299E37637B04BAB3F4255B4FE7C416EEDE +:10D39000DF5583727661C6ED7A8A7FB5494ABC83D0 +:10D3A000BFD3506365DCAE6BFB3A12DFA9FF7DDBB8 +:10D3B000D1EBF11E74C7C123F45E4CC73E49E34F65 +:10D3C0008D1DCBF13B762CF7FFBEDC772412CF0905 +:10D3D0003ED07684C35DE7A7F51F56F21D9012BCC0 +:10D3E000F74BB4FEF99724CDEF01B8C071A1FBCD86 +:10D3F000FBD322705D27DBF878D3407D50796AD566 +:10D400001C9CFF1BF6F23CE57D32FADDA18EABAE33 +:10D41000DB857276619BD4E779F739D82FCCEF980A +:10D420009ED3E9EBA92F1C1B04707FC335209B748E +:10D430008452AF622CD79BA5064F2AEA91931647D8 +:10D4400004D2F9FDAEA11188DFC39862B9EB49BAE5 +:10D4500007BE601F1FEFA4B53D12E9EEE4BE1152F6 +:10D46000F0FECB2DCA7ABAE9BB1B6F5EC253B56F13 +:10D47000BB05FBE9C11F2F9F36D64AF5DFF09DB8EB +:10D4800005EDAC9319FCDDC0630646FEF5C23DDC3C +:10D490004E3E7970F0F6E0FB59D3147C7464F07D55 +:10D4A000F50BFBF54ABDDB77314D3D3DC7D74EED62 +:10D4B0007CACBE330FA17D5EF3B844671D6AF4F502 +:10D4C000B1B8FE4FB769E757ADC0B946EF8F8D0DC4 +:10D4D000A2D79A03DD7C63213A3FA0F28983F0A9A9 +:10D4E000E2F16486C4E765E7EFF8D5ECDD4574DD6D +:10D4F0003BBEC4E3B783EF313929BE74197F5AB5F7 +:10D500001B82FC2DFABD23BD6B689E98D2631F9CC5 +:10D510002E941F1A9B877E989BFCCC930CEC5B1877 +:10D52000B316EDEB28FA1D89CD386ED73E3DBDFF11 +:10D530005F6B3AB000DF23EF7202A3C0BCBBB6E959 +:10D54000BBDF67463B779E62E77EEAF0E44BA07F55 +:10D550006B9789B4BE9A3D920FCF175C50E4DE57AB +:10D560007B936F407AAD392E59D13F9AD896FC7093 +:10D57000612EE977B257EBDAB89D5CB75B20BB58F8 +:10D58000B5436A153BE49C62079F5BD6C9EDE35740 +:10D5900004B611EAAD0D037B04E65D9B3985ECDA38 +:10D5A0005A69DDCAC10E3C47A5B51BE61F3C44E7DE +:10D5B000AEC0CED1942FDCADCDD7B669F3AABFF8FB +:10D5C000D2D86E3B6338FA372552611CF2C39B0AEE +:10D5D0005E557FE7CE6B9CF4FB270FE81C53D4B855 +:10D5E00004C26BD12B2FCCC779FB6AC29CE47F3479 +:10D5F000FE96E0DAF117EED774E0DE1BF233E3F0CB +:10D60000EDD8CFE97C915EF0E1EFBA2C425D81FD6F +:10D610009904DF328C3B7BBB22493E29E7081ACABA +:10D62000B9FF2A630C18A6B27E2CF7E743F5EA3857 +:10D630005D408A0E921381B12954AFD8C0CF57DE16 +:10D6400019E124FD36C4C4EDF521266EAF0FD17566 +:10D650002EA3DF851824F07D8EAC9769FF606D9D49 +:10D6600085F617047B950EE1B17650950EE97D881D +:10D67000B52D03FD3A355F8CDF337BEC83528B474E +:10D6800087E3EC8C17947D04AE4FCB74567D749079 +:10D690007E656C99667EEA3DCC9F7D7E56989FA5FF +:10D6A000677E80EF286CFF75AE93EC86A432F5F7A9 +:10D6B0001AEA492EA8F0FC12E8BD187045776C8173 +:10D6C0006E6AB61D22FFB296B5AFC476A5917C1DD9 +:10D6D000A506FEBE5169184F75E3B8FC2A51D2A5C4 +:10D6E000E3B4F6C39171B27E1CA43BC6B94DE3F21C +:10D6F000683F9579617D0D6FF377D643E53E9413CE +:10D700003D7D0D7C88F26F46BD604DD5D8699CBFCC +:10D7100016F1A26E3E5AF8F693C427EA39CC6AC6CF +:10D72000F97B66A3D99A1AC4178B90DFD0DE77C332 +:10D73000BF7C8C13F0BF6AEB7C3A97E9698CB5A289 +:10D740005FB748FA92F6257E2CDF2DDAAFCDFBCD00 +:10D750009CFEFD1102F94919E3BAE30DC48F490A91 +:10D760007F6CF708740E60FB773A1ECFAB10287EF3 +:10D7700077331436DA944962BDEA22BA4F7233E342 +:10D780004763594B8CF2BB3D31B46F7993B2EE9B3A +:10D7900075FE4328578EEADB92319E74B4D6E4C4FA +:10D7A000FECB591BBD6F5AC1DA293D155EF7A29F0A +:10D7B0003AF72622DDFDC963A478D6F6E53B225070 +:10D7C000BE67B1E556DC4F0450ECC6B701FBB3733E +:10D7D00042F71DD5FBC4602FC7217D02FE27211D06 +:10D7E0009C07DCD8737AB75FF8C71723117F5F2CCB +:10D7F00079E1965B19FA5F9DE4472DA85F46F75DD6 +:10D80000819CDA33F27BF0AAE25DC55B375E1DF0E6 +:10D810002F18AFB0A6048493F46519C9A57F91E8C9 +:10D820009CD6E5F0AAC27DBC829F3B0E70F9158A9A +:10D830006F150FB7E2BBF54349EF6E233C3123C9A7 +:10D84000CB507AB81CBE8030E93CD9C41823F9A16A +:10D8500083452E4F07CF13285E793BF3BC1280F42B +:10D8600096F0F7F5FCDE0AC75B8582B73F31DF2F04 +:10D870003292FF71783B32CEDD346E606FBE0DE5C3 +:10D88000D3FEF8B2C6E1FC37555FFA18F263083FE1 +:10D8900087F06B371E9DF02F088F9EC648E2CB6E37 +:10D8A0007C4B7BAE4C2FE27F308EB55FF0F993AFAF +:10D8B000805F0546BFBFF8F838ADDE54F1A6C2A5BB +:10D8C000BFB8E007CC7FD42AD0BE0AE7E3BB8D7493 +:10D8D000FF43DD5751F74F5E19C7F55C68FA01D871 +:10D8E0004BB85FB526E3E440B4334F19D47EF8FE5D +:10D8F000EF07CBDA13F1F7B63E28E2E92903FFDDA3 +:10D900000F352F87F1B8E407F1462FC2E90361F81C +:10D9100004D4331F08F75CCFF3710607E6CBE32688 +:10D92000E03D90537A358E79BF127FF0F179948F74 +:10D930002CA67A02FF5D4A07FEDE1DF62B0836177D +:10D94000CCE783BBD2E87D9DEE7D8D71DC0E7F46FA +:10D95000594777DCFF5E81E2FE335135E1FEC48436 +:10D960002D2E7C87F3F47D43B369DFB4413B3EEA5F +:10D97000FD648A976EE0E7FE2E75EAAB82F45BB732 +:10D98000BE2DBEC8CBE7E4D1EF8CA8BF4727DB860E +:10D9900073FFDCC77FDF50D5675DC75FB004C77317 +:10D9A0003F53E2DFDDF9E10F2605EBC3434FAD4DF9 +:10D9B000C77EAA0DDE2CA7057F87EEB124B45BAA33 +:10D9C0009F5A954EF6F4530FA4A35F54BD636DBAEE +:10D9D0004CF9700FF9653ABEEE2F9E1B45E7F3D464 +:10D9E000FEF6CADCAFA8301D2A41BD3DE5EAAF56C0 +:10D9F000E0FE41DA7D02C5FF66B0F615A8672B335D +:10DA0000385FB11613C97FE88FF66B770DFFC54EEF +:10DA100094076F649CD5CF817A123E203510DFD5F4 +:10DA2000F2ADA3DF095CCD7F27B0A77E22EDFF56C4 +:10DA30002D17E89DAB19F5FC77F3A4F1D104C75974 +:10DA4000ABB38FD1FB574B79F914A36FDF49EC6768 +:10DA50008B81DF3F64EE94E0FB7092B25F38739D80 +:10DA6000F27B71CA38699B63B707AF5352F61D59F1 +:10DA7000EA7724DF6E50F03275E98957EDD0EF5424 +:10DA8000BDC73C1EBEBFB3E95CAA9F611CF4333A1C +:10DA90005F9866F03C3A1FD7BDC34871D2DCACC179 +:10DAA000521CD4CF5952B411D3994BAB1E9D8F72D7 +:10DAB000B8D594CD8F35F2F935084E11E5F491EDD6 +:10DAC000B7CE42B89DDFC47FFFAB61FB30FADDC249 +:10DAD000FEE4DEAF9AF8EFF93DDD64A2F4D9262B1F +:10DAE000C3A3EBCF35D929FFAF4D0E4AD9F43CCDB6 +:10DAF000EFD8F4D7DF884BE1F4BB73B9ABCDF43B7F +:10DB0000880D4639753CC02BEDAADA1D0F28EBC2F3 +:10DB1000F7B8B2BDC913110EB90F2C3E86A6B37566 +:10DB20003CDF977DF3E4EA2414D6772C3DF3C47CE4 +:10DB3000F87EFB78F7350827D3B68B14A7387260C8 +:10DB40005525C2BB7A8791AF4F59F7F94DE9718FCF +:10DB5000627CF9753DC50D166D3BF3C4030C7F87E0 +:10DB600077B12198DEAF74BD578FE77EE6E5F8AA5E +:10DB70003F38FC78BE5A9B44FCB303F82AF3A7F362 +:10DB8000D5A2A5CB087ECBC6BB6F42B89DD77B93F1 +:10DB9000909FCE0F1F4B74EE7D4520F8AB72BCDB1F +:10DBA000AF56E0BF506C5B5798DC23C7BF61B90428 +:10DBB000DF43073E4D47FBF99BFDE53FB8EE97601D +:10DBC000DDFE6118AF33511AFA3DDFE019EA84F542 +:10DBD000E5F7F33EE8D2F16AFC9F9F53C03F213640 +:10DBE000F89D21E68D82F9D41C14FC6159A8CF263A +:10DBF0007DA643BF11FCCF8F34E78C19FB28489FCB +:10DC0000F737DFCBA575D84F5A8FDC1DF99EC8FCBE +:10DC1000417A7B54208CF983C6EDF673A0CC40FB8F +:10DC20004EF12417106F782EECC281E13B30FF9942 +:10DC300081E3F1C24B604FF1781093F27BD6F9D9B2 +:10DC4000812FB250CE86AEB7EEE52F883E6AF6AF92 +:10DC5000BA28D0FA277FA6CBBAFCFA0F3DF54516B5 +:10DC6000E2EF337D201FFDB60B864016E2A1EEB732 +:10DC70005C9EFF5838A8E5F3571BE8F73AEB04130E +:10DC8000D14989F425C51F2E1CE7F187BA034F92AD +:10DC90003CED3AC8E3408BC4F6D2388C9BD49F3914 +:10DCA00086F2ACCBCEFD31E89FDE712B1CAAE84199 +:10DCB0005D6712DEF73BD84D0FDC8F3C8FFC3B0CD1 +:10DCC000FB69A3F3BD2C2B9CA15DF139F2F3307CF1 +:10DCD000BF307925D2F979DFC01C948F6F66FDAD16 +:10DCE0008EE286BF0FA77BB2B56D92E69C79F73ABC +:10DCF0007C123F70C454FB299CC9C1E7B90C8E1B30 +:10DD0000C86E7E83EF132EBA8AF3137B99F353ED1B +:10DD1000F243067B507FBB157E52EDC829BFFF1B27 +:10DD2000F1E5B38532FD04D54FA5C7FF9FFEF74C43 +:10DD3000FF2F4133EC630080000000001F8B0800C0 +:10DD40000000000000FFA55A0D705455963EEFBD2F +:10DD5000FE4927DD4913421208840642881A6203ED +:10DD60008172D6C4E9FC6E2033BB016B2DC4088DD3 +:10DD700022249D7482E8EC6AB96E1A02AC6475368E +:10DD80008C59471D479B9F8028EC769440C0A00D7E +:10DD90000ACBA26B45AA263A555B54ABAC0EE0A663 +:10DDA00023823BD6E2B8E73BEFB5DD1DE24FEDA69F +:10DDB0008ABA7DEECFB9E79E7BCE77CE3D8FB45247 +:10DDC00022CA226ACFCD082A0AFFA66EA245446D58 +:10DDD00029247FF641451FAFD364BC7D40A3C958B9 +:10DDE00093EB08CE9E415447DD269A45B4844265A4 +:10DDF000A471BF29F2CB5B79BCFE0D6D4117936115 +:10DE00001BAD6AB013D5A67A0B3614130DABCAAA94 +:10DE10008662CC0B952E9D4BF40DFE7E4A749B873B +:10DE2000994F222AD3140FF61B9D9C16DCC95D8BDB +:10DE300097FB1B494D98A7EAF3984F53087C82A3A0 +:10DE4000254B1DD868B46499233EEF8E37D2D60790 +:10DE5000314EA1D23B12F6F94B8F856821D117CBF9 +:10DE600017AA0F65F279AEDA037433518D76ED2976 +:10DE700085F7DD70CC4C5605FC67BCAFF239026704 +:10DE800034EA65FA52470A79ACCCCE4B1E0FCF1B51 +:10DE9000993B29D8C5E76F3FA09089E7B51DB1EE42 +:10DEA0004CE1796DE648B69BF7DD36F03B8B87DBBE +:10DEB000F6FEF72CAEB958CF4736439E1415FA6DCF +:10DEC00077F24F17917F60CEFB77313FFF694DF4BA +:10DED000ED37BD6721D6D7059E8FFD5A0EF6D58248 +:10DEE0006EA5F05627DAFD3CAF48BF9B6FF8DFE523 +:10DEF0005C5786B3387EBEF8395DA2A718BDF869B5 +:10DF00003EF702D68B46EB437659EE21967B716E37 +:10DF1000CE8E2E25719DAE5F8F76694B0ECB159DF3 +:10DF2000A9B81566154D0D6C76421F858AB39717F3 +:10DF3000475F7FB9742DF49B122CBD9DCF17B59010 +:10DF4000DCC7E2C7B69BB40479160F6A1EDC433403 +:10DF5000959A0EC9BD7BA7E23EA8BC61A96712D6FF +:10DF60008DBE7B2B6F195579BDFDFA7304CA757987 +:10DF7000CEB0A9C97D1B72D7E7E5ED80FED900C4FC +:10DF80008E4EA9FAFE1E95C7E7C7D7BF689CA74665 +:10DF90002BCE89F0F806C59DE31C679F58BB87F51B +:10DFA000BE86EFE945BE6FB42F753869CD6CA2FD12 +:10DFB0001DB942FF73874BDA504791F4BFD2E11687 +:10DFC000FA60C72D421FEAF0083DD05127EDD18EEF +:10DFD00006E93F0351FF8C70A020ECE2147C6D4AEF +:10DFE0009C1ECE1C434F499E3F9CA924D353149999 +:10DFF000FF70B83C1860FAA532A79C938DCAD1C0B7 +:10E00000FA684E4B2FA10CB4F9414A67BBB17B03B0 +:10E010001EB6FB3FD4EDDA4333C5CF4B30AF3AF3F6 +:10E02000CE46F8DBE52C2B69ACCFC31EEFDF63DEF9 +:10E03000E9D35505DBD13F68735BF9FE8757DC9464 +:10E0400001BD47FF4D238DB7AE285AB0B994E90AF8 +:10E05000BB2276CCFC6E6EC866BBC64FE65335B8A5 +:10E06000BAD4A4E38473B602FDB7AEC13E1B26DB6F +:10E07000165879FC4AB9F757D827A6F7DA29EB0AD8 +:10E08000BCD08BD9F5BECAF302FF6EA65E9EF780A8 +:10E09000C39D64DF47CB2B82B09BC545B336CF070A +:10E0A0007F76BAD9BC3FBBF57EC8E751D3944EC149 +:10E0B000319709B810C4FDF33E952E45EC306C71D4 +:10E0C0009932997F38B5222BC0EB4E19F77DDAB81B +:10E0D000EF33C67DBFC3FDD5DCBECBFD6887B81F5F +:10E0E000ED8A989E4DA385D05FF0A70D2F7944EF60 +:10E0F000A3F9A0A3665A0E3B5C023FD3F127BF8170 +:10E10000E578A25C97E36E037F866E6BE8D3D785D4 +:10E11000844F8B85BCB0FF4B589F609FB175F1F564 +:10E1200024EDB29B2990C2E7A0C3B620F4445389E2 +:10E13000805FCB0EE7082E6929B38ACF4F647A013E +:10E14000099ED2AB567D5EAE6B21FC857524FB8C9F +:10E1500004D58099EDC49F395498C9F28E187E1663 +:10E16000A30FFD4913FCF6CF679ADBD714FD7CFEA5 +:10E1700065438513B05EB1A9B033FF4E7DFCACE1C1 +:10E1800087FE99063FE33C9412CAC77D448F1DCE9B +:10E19000BF87E92E7B78AD1E07C28582DF142E5C17 +:10E1A000069C5442E7C84DD477FC7DAFE927D047A1 +:10E1B000E879D0FDC77FAFD34ADF3967E2F8A450D2 +:10E1C000BEE204FD8141F73D3FC19D409B5F398721 +:10E1D00071CBA6DF7BAB27336E5883A73B6037FF3D +:10E1E000A2DB97ED40FF27D05BCB112BC12E2B0F6D +:10E1F000F47FF60A8FB7F43BDC80FBA86786E8BBA8 +:10E20000F3C8DEC7616F237D66F187AEFDBF7BFE7D +:10E2100011996725985BBD35544ABCCFD1E37FE3A4 +:10E2200035619FB4D015D06F579C1739EA27EAFEA5 +:10E230003D54F1A93700BDF51FF86BC4B5FA0C0ABF +:10E24000C06EE965BE4766E47BF5866A2AE171C760 +:10E25000D04AF06F7BC9EA869DFA5ECDA9841F5F24 +:10E26000F3CC14FB6BBEB13B1F71573DBA6FCF238C +:10E2700059986723C8DB9EC976C47AF5693B16DDD9 +:10E280002FF7B76BCF6F20F73E1BED643ECDCC036D +:10E29000FB35EF991D0CF0D15EFBFAE395B8871AB8 +:10E2A000EDB93DE8BFB2DBA6420F672D9E8C72F838 +:10E2B000E159B3BB17EB0CBA7978A22E4F5AA4568A +:10E2C000EE2FAB3B1F71D737F1E1BF80DCF55AF77A +:10E2D000F3CFE23C7BAD843871611FEB8DD75DE8F5 +:10E2E00035CFC72D8FEC7398602F9794EE95CF8222 +:10E2F0007FAF3EEF92AD5BF419E89D43D88FE711F5 +:10E30000E2F225657B52FF85DEBD255ED6DFC5972F +:10E31000EA8BBD09F61BF317DF6E6B527C14246089 +:10E320005CF219BFC919203BC7DF6683BC78E89946 +:10E33000916729BEFEE27E73D8C23A6AB6D2E694ED +:10E34000CCB83FF8F2FEBC0EE7F3A93B0A91C73404 +:10E350002F88AC845F5CB0514A2ECF7BDB885FBED8 +:10E36000831B972A25DF2D4F4D85EEC75773F53850 +:10E370007675C0160C28DF1D8FFEA3839CEFCC8E14 +:10E38000D377AF677E29717E6F5B42AD6EDEB72DAE +:10E3900053C78F733C7F3FE35895B1CFAA8792E76D +:10E3A000DF529129F6D3668914220EC6F82FAC8865 +:10E3B000E15AA4107835765D3DD213E0C8CB8AE0EF +:10E3C00088EFA0F2A1966EA8343BAE4F5F4A20A81A +:10E3D000958C7F0FB98B8C7B605EEF55E87EE5DB1B +:10E3E0006FF3D8984F4B6A241D7953AB23928E7CE0 +:10E3F00068E4A8463B8DEBCB8AF19F19DFAF494615 +:10E40000B83F64F6D8C6DB8F8F433C6F1D7EB32ABE +:10E410003EA9D0FDA669204DF623676411ECB6E94C +:10E42000B9E47538A733C11F470676657B13E28FC1 +:10E43000CF903BAA7C287E13FDFAA37CD8814FA500 +:10E44000CD0AABF622AFB1650A4D293A1DB0B1E550 +:10E45000FBBEB4A7C27E2E5E6D153F1E5122827395 +:10E46000B927AE0A3E8C982382738ECAFF11FC181E +:10E4700099105909DCCAADB4AF96F1C991952E1E19 +:10E48000FFB2C2A0A791E40385273257034FEAB534 +:10E49000D1B711376997D9093F89E97B9DA127A297 +:10E4A000C7863B78FC0F41B30BF1614EA562E40BCC +:10E4B00096F8F9B5B83F8D90EBC041F86793DDDD74 +:10E4C0002BA3C1FDAF201FBC33DBDDE5BA5E6F328D +:10E4D00087E5CACAFC6A2DEE293BDDFB8F15CCDF30 +:10E4E0005F1CC907CEB1B54B1C6A7BDDBA13FB4775 +:10E4F000CDA37B805F171CDE272B589FAD96A1AD67 +:10E50000A52CD267E6C829A4F84B606F8223BABD58 +:10E510008D14EFB2089F1E562AEB6797710F944B2C +:10E52000B403F6A1E8F7FCE6C0ABEF006F468666E1 +:10E53000094E8FF5A70B034FA603373EE0F81E9850 +:10E5400013EFFF60F55E0BFA97BFB8C312E1F69EBA +:10E55000CDC9E7BB7CEDF60CF80B3D9ED00F7BECF4 +:10E5600049A6C7EA0576194EF28380E8FD9CC729C3 +:10E57000F2B7540EB5410FDFD2CB98D612E8136331 +:10E58000E831F3A941CF1FCE7948F8B64E0B0F43BF +:10E590006F2307CC047CEFE4B826747F5A10EF1A7F +:10E5A000F500C7AD2C3D6E215EB4A40FADC4BD8C8B +:10E5B000F45B9D98BFE9C8A7F9383FDB633ECEDB2B +:10E5C00072E47036C1CE8DF704C7C76C8CB7F41FE8 +:10E5D000C9C6BB24D6DFAA860A211747B812E0476E +:10E5E000ACDFAF850B217F8B325482F128E496F9A2 +:10E5F0004C6BA049CED1AAE87E4F4734C1F9B1F7A0 +:10E60000F651856EAF8C0F25C807371DBD5412B16A +:10E61000C7F1A0D9C09513E82FD6FDDFB9C8C0094E +:10E620005EDA0CBF1F0727BC31DCA3F516C87DAE30 +:10E6300042973BB65EF8CA3B2320E36DAF5D2A9953 +:10E64000598C75C63C4AC0A359717C010EE40A0E70 +:10E650006C3267F3B97CCF2BEE4E5ED2DCB8B1964C +:10E66000A7D33AD3FDB5D06B1305E45D3756AEB1F1 +:10E6700076F470857EBF3E557F8FFBF628C14E969F +:10E68000EB22637DEE7CC19B30F0675DF5C65AF8E6 +:10E69000DF7D597E4BE2BBF987F8AFED49A6D7ADD8 +:10E6A000DF589B338E9FFB1EDA7E6A125DCFAFD997 +:10E6B000BBA336DB757D7F4CEE8BB6989C95E64907 +:10E6C00089FA58BEB17612B7EB52FEAFFAD0CF7DC1 +:10E6D000F188358CB8CBFAB5E0FCB7FD71BD2509E2 +:10E6E000B77F805F33056B9D33BE5BFEB16DAB12B0 +:10E6F0001E56804FEC5FBDE267EC3709FB6DAA1830 +:10E7000053A7685A3D1D793779574F4FAC538C6DDD +:10E710001928A7A8B788BD49CB7EB8D23D8E3E62E6 +:10E72000F36FAED4649F4D861D4FA96F79E6151E19 +:10E730007FB9CC5356C97E55AEA992BF8FDDA7A62F +:10E7400052CF0F86B21DBF803D4507CD4EF849B967 +:10E75000A6EB334FBDFC2EFC312FDBE1EA647E35A6 +:10E760005569FABC633627EA40D1635FE57BE0FF79 +:10E770005BECCBA5CE62B2D3641E3F953B57F03D18 +:10E78000B6CFC7C63E69A57ABED35E64FEFE3A53D5 +:10E79000B1E3DB3A93E41BC569C1D91287BF90F896 +:10E7A000161D5CE8D45CC0F7A01DFED6FEF57F67A1 +:10E7B000230E8F0CFE67BA0BB875EDD374D8CFB6A5 +:10E7C000818FD3810F27066639D09E1D7239D01FE5 +:10E7D000ADFBB816F3BA8C365E67308B9CB136F65B +:10E7E0007E8ED51312DED1CDD06BAF73DB2F4B6194 +:10E7F000EFA9DD8263FC8ECE44FC88D7195C39E337 +:10E80000D56512EB0C05B3F53A035AD4190ACC7A44 +:10E810009D0134EA0C685167403FEA0CA051670043 +:10E820008D3A0368D419D0A2CE80FE2BA86BB1BC60 +:10E83000514EDE50DFAAD1EC82FF0FF46A41E4F5BD +:10E840000F1CD3747A8712C47D7FC6FB230E46AF9C +:10E85000E875B028C75379E71F34CBFB201ADA5E7E +:10E860003713F7D6AFB97155171137D914DBCDA3CC +:10E8700027511F6AEF53DC1B5DE85F2E726C1B5C37 +:10E88000F87E23FA7BCD6ED585FBBA9A8DFA976F09 +:10E89000B057EA58D539C72C72CFFB15CAE1FDEF46 +:10E8A000B0EAEF64BFC6BD2CF7B045953CDA6F1DEA +:10E8B00092F74BCB8B8A734D421EDA7ECBE78213E5 +:10E8C0009DB6F49D90D71FB239D724C5578FE47DEC +:10E8D0007EFC74C18D3C43454CAFD5A790DF5E7B79 +:10E8E000013821F948427EB4D6D9FC33E467A45DEF +:10E8F00033E1FC7E7EE84E64F9D63D6DFE2892B091 +:10E900007F733099F60DF66DCD23C899DC8F4A03DD +:10E91000E2B23F94DC1FAA74647D92C63FE6D13C0C +:10E92000E45B75FFB4E6403FEF77B9DB2AF9CA61D3 +:10E930008FF77025FBF149B347EA2F278FD9E4BD44 +:10E94000757EFB9CA4FA4B8D3655EA1F1BCC8AC4FE +:10E95000F12BE5DE63B0CBAABA7BA5EE5295EB10A6 +:10E960007F8ED9E1D1F28637C077C35C97D4BF6A76 +:10E97000ACF40BE1C77E2FF73C68167FABE95482FD +:10E980002AD3ABC96D817FAD62758A3D99ED8F2920 +:10E99000EC0FAB78AFC604BBDAB05D91BC420A1095 +:10E9A000ACE795863E570DFEEB570AFBCBBD563DB7 +:10E9B0000FCE5355E19FD7C5718BE7DF475E0BFC48 +:10E9C000661DC755B41C675F8F70BF376D6ABE9EEA +:10E9D000E7BB72C07FF51933014F6A727E5EE8951E +:10E9E000785FEDFC84EF5B09DFA57D73D3F7E1A8C9 +:10E9F000893E49C86B4F9A75FC617DCA7BEB14EC6C +:10EA000055EA3E5E69CF743449BBA28CC4FF0B3417 +:10EA10003D6F2FE0BB72664ADDA20FEB6BDAED6E45 +:10EA2000E83F860BBB8DFCBE40E596E7ED4ED55B1F +:10EA30000BD329DC3F8D5BCA147E61E77CD4715C0B +:10EA4000C23F4F3DBBC0057D7C6977431F3539C749 +:10EA5000E6E1DD31CBE0FF7259C355DC97279D021B +:10EA6000D89F8F43DDACDF5A1C48415D3DE4D15057 +:10EA7000273FA638F1AEBF1E4FB76F71C2CF0A1441 +:10EA800027EAB7B5A9DD35D9CCBF76E60C37F09CBF +:10EA9000F155EA6123DCEA76706B5053F4B5A66C4D +:10EAA000D4F30DFF29F7A6544D8AF7D71B7E141D0A +:10EAB000FC221DF1F547D46D77837F806CEE5E8379 +:10EAC0003FECA0FEA66952BF8DD9D1E5FD393B616F +:10EAD0004753ABF4758D8DEF99914F0CDDE6CDC1A9 +:10EAE000FE2BD77CBE255BCE397EBD8C713703B83B +:10EAF0003BB65E16C3F13D46FD1D786B32EABA2681 +:10EB0000A3AE6B32EABA26A3AE6B32EABA26A3AE44 +:10EB10006B32EABA26A3AE6B32EABA26A913AE97D5 +:10EB2000F6DD8E87A41DEA08C87842BCB8B9EAC7EA +:10EB3000D55D17558D5377A5145786C45DF67BBDFB +:10EB4000DE3DA6CECAFEAE26F87BD5E0847B1E4312 +:10EB50005ED26371B338546BF1163C60177CF0548D +:10EB60008D5B6F8DE9CF2EF5D9CB649B8F7BA82C65 +:10EB70009A655251C734EE2356EF84DFE09CF01BB8 +:10EB8000B4F01BD3ECB8DFFCD6C2AE5DAAE7090136 +:10EB9000C9136C72BF5B3732AE307D2F399370E58D +:10EBA000B331B8C20F9A159063EDA095BA743F23A4 +:10EBB000F84F25377F9C3F0ECE84749C99961ADAC5 +:10EBC000877DA6B5A5BA9117B3BF8B9D9DDCA6889E +:10EBD000BFAFA106D9771CBC49479E7CEFC4D17357 +:10EBE000BFE1F9F7FE835DF29DAD93D72EFAFFE00A +:10EBF0004D4D95AE8F5F77847DE75996EA54B643C5 +:10EC00008E57D5162A92BAB89A2AFE50A33DAE580E +:10EC100080A377D33CDC77B5B5E139C899C3FE2E24 +:10EC2000EFDF2CA3BE6B1A6ADECBF4D9EC3C37BE07 +:10EC3000AB4DCD3D44050B804775C5B0ABB3D4ADEE +:10EC400060DD6319DEBF83BFDC5ECCA756E3FE96B2 +:10EC50005397B6B34BEE63CE42DCFB32ABAB1FF542 +:10EC6000862D6F9E907AC2B20CD742D41BB6BC7967 +:10EC70005AA7735CFD8A1BE5B213ABAB7F82F866C3 +:10EC8000EB3E9F1067FDA1094974FBC0E4EEF30958 +:10EC900071AE053FF89D4E3F534CB8AF5643945C60 +:10ECA000D5BB1DF2F9EBFE4B7FCFD3A8C4C9A7AAF1 +:10ECB000745C9C7482C2B0E7D1C50EF9FE973371C3 +:10ECC000FD3CD4DBA8D8B510F338AFFD35ECF8E245 +:10ECD000AD9EA7C127CF38770EF1793558C7900D73 +:10ECE000ED19E3BBE429D5DB88B6363D60927E356D +:10ECF000588AF66D35F420FAD92F76814FED93F3CB +:10ED00006E2C623ACF1A9AB7DE8E78E9D98DFE73EF +:10ED1000659E5EEC37B6EEDF699C8FE5D98779C3D7 +:10ED200085AAE4F9C337EA6DCC2EC2553A0E1D37D9 +:10ED3000FCA8AC93E4FBE758FB395EA51A78F9FD13 +:10ED400072B3BC47204F4C7EEA5E5D0A7958DEA361 +:10ED500086BCAF619CEC99528FF96E7B0DC87EC763 +:10ED60000D3B657C6C39AFE3A3B485A6E004E40DEC +:10ED7000531E0D4E80BC53768CDA5CDCBE1018B589 +:10ED8000217F78E16F476DE87FC14375E3E1BF56AE +:10ED9000AD09DFC2B251593F9DF71A9277C2E8041C +:10EDA000E46F854D6F59026CB7739EE67D93F2B7A1 +:10EDB000228963D30D5B9AFEA84AB087E9CF90E41D +:10EDC000AB549D25E3BE14DDFF7D8F3EA8C28E6E41 +:10EDD00008B2DC09F637E769D3E54812DFB0AC6B5F +:10EDE000317083F3B5A4713F3347BE3CC5C023E403 +:10EDF0008F8D8C37FEA6B7BE42BEC879DC187E8CDC +:10EE00004D311C26C45DEFEB1117FC2079DEDABB17 +:10EE10001ED98AF76D53E3768BBC8FD7F46D45DB33 +:10EE2000DAFA9E258724BF4C9ACFF965127D9D9C06 +:10EE300063E4687BF0F3AD39E3ECCB76702DD10E53 +:10EE40004E9A4337E0BD7AD29FEA0E481C09DD0F87 +:10EE50007CD9D96A7723AEECFA55A5D8D7B7F5A9EE +:10EE6000328FA9FA47D951A7CC0F545211FCE6872B +:10EE7000DA11E0E1EC243C0C48DD72894370AEDD30 +:10EE80007807B6AD714A3E12F3EB3653E8C3AD983E +:10EE900097E590EF110CB745A62C7C6F9AE2EE4AED +:10EEA000C82BCE2E9915049DDD190A83EFE8CF15E6 +:10EEB00037EAC8D5693AAED6A80DAD7B79FC2D35B9 +:10EEC0002CB8F15BE007F36FB7AC977645D94CB13E +:10EED000DB5C0A29FAFF67702DC47B3DF63DAD6708 +:10EEE0005BB0EF20DEFB4AF099B5A88FFE955DE49C +:10EEF0008906D58099CFD3338104B77BEE2C94B8A3 +:10EF000013A586C6FB91FF2C4F953A6ACF04D71301 +:10EF1000F86EDAD37CA3E4F587FEA4C7FBD1A5295C +:10EF20006EE4713DF35C1B71AE9E475D32FE9AA2AA +:10EF3000F30B3CA1EBA767A97ECE9EE64C799FC55B +:10EF4000EEA167876732BEBF5932BCE5D5A803186A +:10EF5000DF1F7B66703FB74F290D77DE073E737565 +:10EF6000795794B9E4DE4EDE79E3137B747D86F144 +:10EF70001DAC7D8923E9FDFEBFFE80CBB3202200BE +:10EF80000000000000000000040835000000000040 +:00000001FF -- cgit v1.2.3 From 94a78b79cb5f14c09a42522738d6694c6a1cdd20 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 27 Apr 2009 03:27:43 -0700 Subject: bnx2x: Separated FW from the source. >From now on FW will be downloaded from the binary file using request_firmware. There will be different files for every supported chip. Currently 57710 (e1) and 57711 (e1h). File names have the following format: bnx2x--.fw. ihex versions of current FW files are submitted in the next patch. Each binary file has a header in the following format: struct bnx2x_fw_file_section { __be32 len; __be32 offset; } struct bnx2x_fw_file_hdr { struct bnx2x_fw_file_section init_ops; struct bnx2x_fw_file_section init_ops_offsets; struct bnx2x_fw_file_section init_data; struct bnx2x_fw_file_section tsem_int_table_data; struct bnx2x_fw_file_section tsem_pram_data; struct bnx2x_fw_file_section usem_int_table_data; struct bnx2x_fw_file_section usem_pram_data; struct bnx2x_fw_file_section csem_int_table_data; struct bnx2x_fw_file_section csem_pram_data; struct bnx2x_fw_file_section xsem_int_table_data; struct bnx2x_fw_file_section xsem_pram_data; struct bnx2x_fw_file_section fw_version; } Each bnx2x_fw_file_section contains the length and the offset of the appropriate section in the binary file. Values are stored in the big endian format. Data types of arrays: init_data __be32 init_ops_offsets __be16 XXsem_pram_data u8 XXsem_int_table_data u8 init_ops struct raw_op { u8 op; __be24 offset; __be32 data; } fw_version u8 >From now boundaries of a specific initialization stage are stored in init_ops_offsets array instead of being defined by separate macroes. The index in init_ops_offsets is calculated by BLOCK_OPS_IDX macro: #define BLOCK_OPS_IDX(block, stage, end) \ (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end)) Security: In addition to sanity check of array boundaries bnx2x will check a FW version. Additional checks might be added in the future. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/bnx2x.h | 15 + drivers/net/bnx2x_fw_file_hdr.h | 37 +++ drivers/net/bnx2x_init.h | 605 +++++----------------------------------- drivers/net/bnx2x_init_ops.h | 442 +++++++++++++++++++++++++++++ drivers/net/bnx2x_main.c | 343 +++++++++++++++++++---- firmware/Makefile | 1 + firmware/WHENCE | 20 ++ 8 files changed, 866 insertions(+), 598 deletions(-) create mode 100644 drivers/net/bnx2x_fw_file_hdr.h create mode 100644 drivers/net/bnx2x_init_ops.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3320e7761576..bc7eef12d955 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2676,6 +2676,7 @@ config TEHUTI config BNX2X tristate "Broadcom NetXtremeII 10Gb support" depends on PCI + select FW_LOADER select ZLIB_INFLATE select LIBCRC32C help diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index a329bee25550..8678457849f9 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -965,6 +965,21 @@ struct bnx2x { int gunzip_outlen; #define FW_BUF_SIZE 0x8000 + struct raw_op *init_ops; + /* Init blocks offsets inside init_ops */ + u16 *init_ops_offsets; + /* Data blob - has 32 bit granularity */ + u32 *init_data; + /* Zipped PRAM blobs - raw data */ + const u8 *tsem_int_table_data; + const u8 *tsem_pram_data; + const u8 *usem_int_table_data; + const u8 *usem_pram_data; + const u8 *xsem_int_table_data; + const u8 *xsem_pram_data; + const u8 *csem_int_table_data; + const u8 *csem_pram_data; + const struct firmware *firmware; }; diff --git a/drivers/net/bnx2x_fw_file_hdr.h b/drivers/net/bnx2x_fw_file_hdr.h new file mode 100644 index 000000000000..3f5ee5d7cc2a --- /dev/null +++ b/drivers/net/bnx2x_fw_file_hdr.h @@ -0,0 +1,37 @@ +/* bnx2x_fw_file_hdr.h: FW binary file header structure. + * + * Copyright (c) 2007-2009 Broadcom Corporation + * + * 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. + * + * Maintained by: Eilon Greenstein + * Written by: Vladislav Zolotarov + * Based on the original idea of John Wright . + */ + +#ifndef BNX2X_INIT_FILE_HDR_H +#define BNX2X_INIT_FILE_HDR_H + +struct bnx2x_fw_file_section { + __be32 len; + __be32 offset; +}; + +struct bnx2x_fw_file_hdr { + struct bnx2x_fw_file_section init_ops; + struct bnx2x_fw_file_section init_ops_offsets; + struct bnx2x_fw_file_section init_data; + struct bnx2x_fw_file_section tsem_int_table_data; + struct bnx2x_fw_file_section tsem_pram_data; + struct bnx2x_fw_file_section usem_int_table_data; + struct bnx2x_fw_file_section usem_pram_data; + struct bnx2x_fw_file_section csem_int_table_data; + struct bnx2x_fw_file_section csem_pram_data; + struct bnx2x_fw_file_section xsem_int_table_data; + struct bnx2x_fw_file_section xsem_pram_data; + struct bnx2x_fw_file_section fw_version; +}; + +#endif /* BNX2X_INIT_FILE_HDR_H */ diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index 39ba2936c0c2..3ba4d888068f 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -1,4 +1,5 @@ /* bnx2x_init.h: Broadcom Everest network driver. + * Structures and macroes needed during the initialization. * * Copyright (c) 2007-2009 Broadcom Corporation * @@ -8,6 +9,7 @@ * * Maintained by: Eilon Greenstein * Written by: Eliezer Tamir + * Modified by: Vladislav Zolotarov */ #ifndef BNX2X_INIT_H @@ -45,33 +47,71 @@ #define OP_WR_64 0x8 /* write 64 bit pattern */ #define OP_WB 0x9 /* copy a string using DMAE */ -/* Operation specific for E1 */ -#define OP_RD_E1 0xa /* read single register */ -#define OP_WR_E1 0xb /* write single register */ -#define OP_IW_E1 0xc /* write single register using mailbox */ -#define OP_SW_E1 0xd /* copy a string to the device */ -#define OP_SI_E1 0xe /* copy a string using mailbox */ -#define OP_ZR_E1 0xf /* clear memory */ -#define OP_ZP_E1 0x10 /* unzip then copy with DMAE */ -#define OP_WR_64_E1 0x11 /* write 64 bit pattern on E1 */ -#define OP_WB_E1 0x12 /* copy a string using DMAE */ - -/* Operation specific for E1H */ -#define OP_RD_E1H 0x13 /* read single register */ -#define OP_WR_E1H 0x14 /* write single register */ -#define OP_IW_E1H 0x15 /* write single register using mailbox */ -#define OP_SW_E1H 0x16 /* copy a string to the device */ -#define OP_SI_E1H 0x17 /* copy a string using mailbox */ -#define OP_ZR_E1H 0x18 /* clear memory */ -#define OP_ZP_E1H 0x19 /* unzip then copy with DMAE */ -#define OP_WR_64_E1H 0x1a /* write 64 bit pattern on E1H */ -#define OP_WB_E1H 0x1b /* copy a string using DMAE */ - /* FPGA and EMUL specific operations */ -#define OP_WR_EMUL_E1H 0x1c /* write single register on E1H Emul */ -#define OP_WR_EMUL 0x1d /* write single register on Emulation */ -#define OP_WR_FPGA 0x1e /* write single register on FPGA */ -#define OP_WR_ASIC 0x1f /* write single register on ASIC */ +#define OP_WR_EMUL 0xa /* write single register on Emulation */ +#define OP_WR_FPGA 0xb /* write single register on FPGA */ +#define OP_WR_ASIC 0xc /* write single register on ASIC */ + +/* Init stages */ +#define COMMON_STAGE 0 +#define PORT0_STAGE 1 +#define PORT1_STAGE 2 +/* Never reorder FUNCx stages !!! */ +#define FUNC0_STAGE 3 +#define FUNC1_STAGE 4 +#define FUNC2_STAGE 5 +#define FUNC3_STAGE 6 +#define FUNC4_STAGE 7 +#define FUNC5_STAGE 8 +#define FUNC6_STAGE 9 +#define FUNC7_STAGE 10 +#define STAGE_IDX_MAX 11 + +#define STAGE_START 0 +#define STAGE_END 1 + + +/* Indices of blocks */ +#define PRS_BLOCK 0 +#define SRCH_BLOCK 1 +#define TSDM_BLOCK 2 +#define TCM_BLOCK 3 +#define BRB1_BLOCK 4 +#define TSEM_BLOCK 5 +#define PXPCS_BLOCK 6 +#define EMAC0_BLOCK 7 +#define EMAC1_BLOCK 8 +#define DBU_BLOCK 9 +#define MISC_BLOCK 10 +#define DBG_BLOCK 11 +#define NIG_BLOCK 12 +#define MCP_BLOCK 13 +#define UPB_BLOCK 14 +#define CSDM_BLOCK 15 +#define USDM_BLOCK 16 +#define CCM_BLOCK 17 +#define UCM_BLOCK 18 +#define USEM_BLOCK 19 +#define CSEM_BLOCK 20 +#define XPB_BLOCK 21 +#define DQ_BLOCK 22 +#define TIMERS_BLOCK 23 +#define XSDM_BLOCK 24 +#define QM_BLOCK 25 +#define PBF_BLOCK 26 +#define XCM_BLOCK 27 +#define XSEM_BLOCK 28 +#define CDU_BLOCK 29 +#define DMAE_BLOCK 30 +#define PXP_BLOCK 31 +#define CFC_BLOCK 32 +#define HC_BLOCK 33 +#define PXP2_BLOCK 34 +#define MISC_AEU_BLOCK 35 + +/* Returns the index of start or end of a specific block stage in ops array*/ +#define BLOCK_OPS_IDX(block, stage, end) \ + (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end)) struct raw_op { @@ -118,292 +158,6 @@ union init_op { struct raw_op raw; }; -#include "bnx2x_init_values.h" - -static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); -static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len); - -static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data, - u32 len) -{ - int i; - - for (i = 0; i < len; i++) { - REG_WR(bp, addr + i*4, data[i]); - if (!(i % 10000)) { - touch_softlockup_watchdog(); - cpu_relax(); - } - } -} - -static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, - u16 len) -{ - int i; - - for (i = 0; i < len; i++) { - REG_WR_IND(bp, addr + i*4, data[i]); - if (!(i % 10000)) { - touch_softlockup_watchdog(); - cpu_relax(); - } - } -} - -static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) -{ - int offset = 0; - - if (bp->dmae_ready) { - while (len > DMAE_LEN32_WR_MAX) { - bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, - addr + offset, DMAE_LEN32_WR_MAX); - offset += DMAE_LEN32_WR_MAX * 4; - len -= DMAE_LEN32_WR_MAX; - } - bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, - addr + offset, len); - } else - bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -} - -static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) -{ - u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4)); - u32 buf_len32 = buf_len / 4; - int i; - - memset(bp->gunzip_buf, fill, buf_len); - - for (i = 0; i < len; i += buf_len32) { - u32 cur_len = min(buf_len32, len - i); - - bnx2x_write_big_buf(bp, addr + i * 4, cur_len); - } -} - -static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data, - u32 len64) -{ - u32 buf_len32 = FW_BUF_SIZE / 4; - u32 len = len64 * 2; - u64 data64 = 0; - int i; - - /* 64 bit value is in a blob: first low DWORD, then high DWORD */ - data64 = HILO_U64((*(data + 1)), (*data)); - len64 = min((u32)(FW_BUF_SIZE/8), len64); - for (i = 0; i < len64; i++) { - u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i; - - *pdata = data64; - } - - for (i = 0; i < len; i += buf_len32) { - u32 cur_len = min(buf_len32, len - i); - - bnx2x_write_big_buf(bp, addr + i * 4, cur_len); - } -} - -/********************************************************* - There are different blobs for each PRAM section. - In addition, each blob write operation is divided into a few operations - in order to decrease the amount of phys. contiguous buffer needed. - Thus, when we select a blob the address may be with some offset - from the beginning of PRAM section. - The same holds for the INT_TABLE sections. -**********************************************************/ -#define IF_IS_INT_TABLE_ADDR(base, addr) \ - if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) - -#define IF_IS_PRAM_ADDR(base, addr) \ - if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) - -static const u32 *bnx2x_sel_blob(u32 addr, const u32 *data, int is_e1) -{ - IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr) - data = is_e1 ? tsem_int_table_data_e1 : - tsem_int_table_data_e1h; - else - IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr) - data = is_e1 ? csem_int_table_data_e1 : - csem_int_table_data_e1h; - else - IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr) - data = is_e1 ? usem_int_table_data_e1 : - usem_int_table_data_e1h; - else - IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr) - data = is_e1 ? xsem_int_table_data_e1 : - xsem_int_table_data_e1h; - else - IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr) - data = is_e1 ? tsem_pram_data_e1 : tsem_pram_data_e1h; - else - IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr) - data = is_e1 ? csem_pram_data_e1 : csem_pram_data_e1h; - else - IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr) - data = is_e1 ? usem_pram_data_e1 : usem_pram_data_e1h; - else - IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr) - data = is_e1 ? xsem_pram_data_e1 : xsem_pram_data_e1h; - - return data; -} - -static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, - u32 len, int gunzip, int is_e1, u32 blob_off) -{ - int offset = 0; - - data = bnx2x_sel_blob(addr, data, is_e1) + blob_off; - - if (gunzip) { - int rc; -#ifdef __BIG_ENDIAN - int i, size; - u32 *temp; - - temp = kmalloc(len, GFP_KERNEL); - size = (len / 4) + ((len % 4) ? 1 : 0); - for (i = 0; i < size; i++) - temp[i] = swab32(data[i]); - data = temp; -#endif - rc = bnx2x_gunzip(bp, (u8 *)data, len); - if (rc) { - BNX2X_ERR("gunzip failed ! rc %d\n", rc); -#ifdef __BIG_ENDIAN - kfree(temp); -#endif - return; - } - len = bp->gunzip_outlen; -#ifdef __BIG_ENDIAN - kfree(temp); - for (i = 0; i < len; i++) - ((u32 *)bp->gunzip_buf)[i] = - swab32(((u32 *)bp->gunzip_buf)[i]); -#endif - } else { - if ((len * 4) > FW_BUF_SIZE) { - BNX2X_ERR("LARGE DMAE OPERATION ! " - "addr 0x%x len 0x%x\n", addr, len*4); - return; - } - memcpy(bp->gunzip_buf, data, len * 4); - } - - if (bp->dmae_ready) { - while (len > DMAE_LEN32_WR_MAX) { - bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, - addr + offset, DMAE_LEN32_WR_MAX); - offset += DMAE_LEN32_WR_MAX * 4; - len -= DMAE_LEN32_WR_MAX; - } - bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, - addr + offset, len); - } else - bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len); -} - -static void bnx2x_init_block(struct bnx2x *bp, u32 op_start, u32 op_end) -{ - int is_e1 = CHIP_IS_E1(bp); - int is_e1h = CHIP_IS_E1H(bp); - int is_emul_e1h = (CHIP_REV_IS_EMUL(bp) && is_e1h); - int hw_wr, i; - union init_op *op; - u32 op_type, addr, len; - const u32 *data, *data_base; - - if (CHIP_REV_IS_FPGA(bp)) - hw_wr = OP_WR_FPGA; - else if (CHIP_REV_IS_EMUL(bp)) - hw_wr = OP_WR_EMUL; - else - hw_wr = OP_WR_ASIC; - - if (is_e1) - data_base = init_data_e1; - else /* CHIP_IS_E1H(bp) */ - data_base = init_data_e1h; - - for (i = op_start; i < op_end; i++) { - - op = (union init_op *)&(init_ops[i]); - - op_type = op->str_wr.op; - addr = op->str_wr.offset; - len = op->str_wr.data_len; - data = data_base + op->str_wr.data_off; - - /* careful! it must be in order */ - if (unlikely(op_type > OP_WB)) { - - /* If E1 only */ - if (op_type <= OP_WB_E1) { - if (is_e1) - op_type -= (OP_RD_E1 - OP_RD); - - /* If E1H only */ - } else if (op_type <= OP_WB_E1H) { - if (is_e1h) - op_type -= (OP_RD_E1H - OP_RD); - } - - /* HW/EMUL specific */ - if (op_type == hw_wr) - op_type = OP_WR; - - /* EMUL on E1H is special */ - if ((op_type == OP_WR_EMUL_E1H) && is_emul_e1h) - op_type = OP_WR; - } - - switch (op_type) { - case OP_RD: - REG_RD(bp, addr); - break; - case OP_WR: - REG_WR(bp, addr, op->write.val); - break; - case OP_SW: - bnx2x_init_str_wr(bp, addr, data, len); - break; - case OP_WB: - bnx2x_init_wr_wb(bp, addr, data, len, 0, is_e1, 0); - break; - case OP_SI: - bnx2x_init_ind_wr(bp, addr, data, len); - break; - case OP_ZR: - bnx2x_init_fill(bp, addr, 0, op->zero.len); - break; - case OP_ZP: - bnx2x_init_wr_wb(bp, addr, data, len, 1, is_e1, - op->str_wr.data_off); - break; - case OP_WR_64: - bnx2x_init_wr_64(bp, addr, data, len); - break; - default: - /* happens whenever an op is of a diff HW */ -#if 0 - DP(NETIF_MSG_HW, "skipping init operation " - "index %d[%d:%d]: type %d addr 0x%x " - "len %d(0x%x)\n", - i, op_start, op_end, op_type, addr, len, len); -#endif - break; - } - } -} - - /**************************************************************************** * PXP ****************************************************************************/ @@ -567,111 +321,6 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = { PXP2_REG_RQ_BW_WR_UBOUND30} }; -static void bnx2x_init_pxp(struct bnx2x *bp) -{ - u16 devctl; - int r_order, w_order; - u32 val, i; - - pci_read_config_word(bp->pdev, - bp->pcie_cap + PCI_EXP_DEVCTL, &devctl); - DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); - w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); - if (bp->mrrs == -1) - r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12); - else { - DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs); - r_order = bp->mrrs; - } - - if (r_order > MAX_RD_ORD) { - DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n", - r_order, MAX_RD_ORD); - r_order = MAX_RD_ORD; - } - if (w_order > MAX_WR_ORD) { - DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n", - w_order, MAX_WR_ORD); - w_order = MAX_WR_ORD; - } - if (CHIP_REV_IS_FPGA(bp)) { - DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n"); - w_order = 0; - } - DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order); - - for (i = 0; i < NUM_RD_Q-1; i++) { - REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l); - REG_WR(bp, read_arb_addr[i].add, - read_arb_data[i][r_order].add); - REG_WR(bp, read_arb_addr[i].ubound, - read_arb_data[i][r_order].ubound); - } - - for (i = 0; i < NUM_WR_Q-1; i++) { - if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || - (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { - - REG_WR(bp, write_arb_addr[i].l, - write_arb_data[i][w_order].l); - - REG_WR(bp, write_arb_addr[i].add, - write_arb_data[i][w_order].add); - - REG_WR(bp, write_arb_addr[i].ubound, - write_arb_data[i][w_order].ubound); - } else { - - val = REG_RD(bp, write_arb_addr[i].l); - REG_WR(bp, write_arb_addr[i].l, - val | (write_arb_data[i][w_order].l << 10)); - - val = REG_RD(bp, write_arb_addr[i].add); - REG_WR(bp, write_arb_addr[i].add, - val | (write_arb_data[i][w_order].add << 10)); - - val = REG_RD(bp, write_arb_addr[i].ubound); - REG_WR(bp, write_arb_addr[i].ubound, - val | (write_arb_data[i][w_order].ubound << 7)); - } - } - - val = write_arb_data[NUM_WR_Q-1][w_order].add; - val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; - val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; - REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val); - - val = read_arb_data[NUM_RD_Q-1][r_order].add; - val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; - val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; - REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val); - - REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order); - REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order); - REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order); - REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order); - - if (r_order == MAX_RD_ORD) - REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); - - REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); - - if (CHIP_IS_E1H(bp)) { - val = ((w_order == 0) ? 2 : 3); - REG_WR(bp, PXP2_REG_WR_HC_MPS, val); - REG_WR(bp, PXP2_REG_WR_USDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val); - REG_WR(bp, PXP2_REG_WR_QM_MPS, val); - REG_WR(bp, PXP2_REG_WR_TM_MPS, val); - REG_WR(bp, PXP2_REG_WR_SRC_MPS, val); - REG_WR(bp, PXP2_REG_WR_DBG_MPS, val); - REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */ - REG_WR(bp, PXP2_REG_WR_CDU_MPS, val); - } -} - /**************************************************************************** * CDU @@ -695,128 +344,12 @@ static void bnx2x_init_pxp(struct bnx2x *bp) (0x80 | ((_type) & 0xf << 3) | (CDU_CRC8(_cid, _region, _type) & 0x7)) #define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val) ((_val) & ~0x80) -/***************************************************************************** - * Description: - * Calculates crc 8 on a word value: polynomial 0-1-2-8 - * Code was translated from Verilog. - ****************************************************************************/ -static u8 calc_crc8(u32 data, u8 crc) -{ - u8 D[32]; - u8 NewCRC[8]; - u8 C[8]; - u8 crc_res; - u8 i; - - /* split the data into 31 bits */ - for (i = 0; i < 32; i++) { - D[i] = data & 1; - data = data >> 1; - } - - /* split the crc into 8 bits */ - for (i = 0; i < 8; i++) { - C[i] = crc & 1; - crc = crc >> 1; - } - - NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^ - D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^ - C[6] ^ C[7]; - NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^ - D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^ - D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6]; - NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^ - D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^ - C[0] ^ C[1] ^ C[4] ^ C[5]; - NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^ - D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^ - C[1] ^ C[2] ^ C[5] ^ C[6]; - NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^ - D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^ - C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7]; - NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^ - D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^ - C[3] ^ C[4] ^ C[7]; - NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^ - D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^ - C[5]; - NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^ - D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^ - C[6]; - - crc_res = 0; - for (i = 0; i < 8; i++) - crc_res |= (NewCRC[i] << i); - - return crc_res; -} /* registers addresses are not in order so these arrays help simplify the code */ -static const int cm_start[E1H_FUNC_MAX][9] = { - {MISC_FUNC0_START, TCM_FUNC0_START, UCM_FUNC0_START, CCM_FUNC0_START, - XCM_FUNC0_START, TSEM_FUNC0_START, USEM_FUNC0_START, CSEM_FUNC0_START, - XSEM_FUNC0_START}, - {MISC_FUNC1_START, TCM_FUNC1_START, UCM_FUNC1_START, CCM_FUNC1_START, - XCM_FUNC1_START, TSEM_FUNC1_START, USEM_FUNC1_START, CSEM_FUNC1_START, - XSEM_FUNC1_START}, - {MISC_FUNC2_START, TCM_FUNC2_START, UCM_FUNC2_START, CCM_FUNC2_START, - XCM_FUNC2_START, TSEM_FUNC2_START, USEM_FUNC2_START, CSEM_FUNC2_START, - XSEM_FUNC2_START}, - {MISC_FUNC3_START, TCM_FUNC3_START, UCM_FUNC3_START, CCM_FUNC3_START, - XCM_FUNC3_START, TSEM_FUNC3_START, USEM_FUNC3_START, CSEM_FUNC3_START, - XSEM_FUNC3_START}, - {MISC_FUNC4_START, TCM_FUNC4_START, UCM_FUNC4_START, CCM_FUNC4_START, - XCM_FUNC4_START, TSEM_FUNC4_START, USEM_FUNC4_START, CSEM_FUNC4_START, - XSEM_FUNC4_START}, - {MISC_FUNC5_START, TCM_FUNC5_START, UCM_FUNC5_START, CCM_FUNC5_START, - XCM_FUNC5_START, TSEM_FUNC5_START, USEM_FUNC5_START, CSEM_FUNC5_START, - XSEM_FUNC5_START}, - {MISC_FUNC6_START, TCM_FUNC6_START, UCM_FUNC6_START, CCM_FUNC6_START, - XCM_FUNC6_START, TSEM_FUNC6_START, USEM_FUNC6_START, CSEM_FUNC6_START, - XSEM_FUNC6_START}, - {MISC_FUNC7_START, TCM_FUNC7_START, UCM_FUNC7_START, CCM_FUNC7_START, - XCM_FUNC7_START, TSEM_FUNC7_START, USEM_FUNC7_START, CSEM_FUNC7_START, - XSEM_FUNC7_START} -}; - -static const int cm_end[E1H_FUNC_MAX][9] = { - {MISC_FUNC0_END, TCM_FUNC0_END, UCM_FUNC0_END, CCM_FUNC0_END, - XCM_FUNC0_END, TSEM_FUNC0_END, USEM_FUNC0_END, CSEM_FUNC0_END, - XSEM_FUNC0_END}, - {MISC_FUNC1_END, TCM_FUNC1_END, UCM_FUNC1_END, CCM_FUNC1_END, - XCM_FUNC1_END, TSEM_FUNC1_END, USEM_FUNC1_END, CSEM_FUNC1_END, - XSEM_FUNC1_END}, - {MISC_FUNC2_END, TCM_FUNC2_END, UCM_FUNC2_END, CCM_FUNC2_END, - XCM_FUNC2_END, TSEM_FUNC2_END, USEM_FUNC2_END, CSEM_FUNC2_END, - XSEM_FUNC2_END}, - {MISC_FUNC3_END, TCM_FUNC3_END, UCM_FUNC3_END, CCM_FUNC3_END, - XCM_FUNC3_END, TSEM_FUNC3_END, USEM_FUNC3_END, CSEM_FUNC3_END, - XSEM_FUNC3_END}, - {MISC_FUNC4_END, TCM_FUNC4_END, UCM_FUNC4_END, CCM_FUNC4_END, - XCM_FUNC4_END, TSEM_FUNC4_END, USEM_FUNC4_END, CSEM_FUNC4_END, - XSEM_FUNC4_END}, - {MISC_FUNC5_END, TCM_FUNC5_END, UCM_FUNC5_END, CCM_FUNC5_END, - XCM_FUNC5_END, TSEM_FUNC5_END, USEM_FUNC5_END, CSEM_FUNC5_END, - XSEM_FUNC5_END}, - {MISC_FUNC6_END, TCM_FUNC6_END, UCM_FUNC6_END, CCM_FUNC6_END, - XCM_FUNC6_END, TSEM_FUNC6_END, USEM_FUNC6_END, CSEM_FUNC6_END, - XSEM_FUNC6_END}, - {MISC_FUNC7_END, TCM_FUNC7_END, UCM_FUNC7_END, CCM_FUNC7_END, - XCM_FUNC7_END, TSEM_FUNC7_END, USEM_FUNC7_END, CSEM_FUNC7_END, - XSEM_FUNC7_END}, -}; - -static const int hc_limits[E1H_FUNC_MAX][2] = { - {HC_FUNC0_START, HC_FUNC0_END}, - {HC_FUNC1_START, HC_FUNC1_END}, - {HC_FUNC2_START, HC_FUNC2_END}, - {HC_FUNC3_START, HC_FUNC3_END}, - {HC_FUNC4_START, HC_FUNC4_END}, - {HC_FUNC5_START, HC_FUNC5_END}, - {HC_FUNC6_START, HC_FUNC6_END}, - {HC_FUNC7_START, HC_FUNC7_END} +static const int cm_blocks[9] = { + MISC_BLOCK, TCM_BLOCK, UCM_BLOCK, CCM_BLOCK, XCM_BLOCK, + TSEM_BLOCK, USEM_BLOCK, CSEM_BLOCK, XSEM_BLOCK }; #endif /* BNX2X_INIT_H */ diff --git a/drivers/net/bnx2x_init_ops.h b/drivers/net/bnx2x_init_ops.h new file mode 100644 index 000000000000..32552b9366cb --- /dev/null +++ b/drivers/net/bnx2x_init_ops.h @@ -0,0 +1,442 @@ +/* bnx2x_init_ops.h: Broadcom Everest network driver. + * Static functions needed during the initialization. + * This file is "included" in bnx2x_main.c. + * + * Copyright (c) 2007-2009 Broadcom Corporation + * + * 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. + * + * Maintained by: Eilon Greenstein + * Written by: Vladislav Zolotarov + */ +#ifndef BNX2X_INIT_OPS_H +#define BNX2X_INIT_OPS_H + +static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val); +static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len); + +static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data, + u32 len) +{ + int i; + + for (i = 0; i < len; i++) { + REG_WR(bp, addr + i*4, data[i]); + if (!(i % 10000)) { + touch_softlockup_watchdog(); + cpu_relax(); + } + } +} + +static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, + u16 len) +{ + int i; + + for (i = 0; i < len; i++) { + REG_WR_IND(bp, addr + i*4, data[i]); + if (!(i % 10000)) { + touch_softlockup_watchdog(); + cpu_relax(); + } + } +} + +static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) +{ + int offset = 0; + + if (bp->dmae_ready) { + while (len > DMAE_LEN32_WR_MAX) { + bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, + addr + offset, DMAE_LEN32_WR_MAX); + offset += DMAE_LEN32_WR_MAX * 4; + len -= DMAE_LEN32_WR_MAX; + } + bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, + addr + offset, len); + } else + bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); +} + +static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) +{ + u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4)); + u32 buf_len32 = buf_len / 4; + int i; + + memset(bp->gunzip_buf, fill, buf_len); + + for (i = 0; i < len; i += buf_len32) { + u32 cur_len = min(buf_len32, len - i); + + bnx2x_write_big_buf(bp, addr + i * 4, cur_len); + } +} + +static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data, + u32 len64) +{ + u32 buf_len32 = FW_BUF_SIZE / 4; + u32 len = len64 * 2; + u64 data64 = 0; + int i; + + /* 64 bit value is in a blob: first low DWORD, then high DWORD */ + data64 = HILO_U64((*(data + 1)), (*data)); + len64 = min((u32)(FW_BUF_SIZE/8), len64); + for (i = 0; i < len64; i++) { + u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i; + + *pdata = data64; + } + + for (i = 0; i < len; i += buf_len32) { + u32 cur_len = min(buf_len32, len - i); + + bnx2x_write_big_buf(bp, addr + i * 4, cur_len); + } +} + +/********************************************************* + There are different blobs for each PRAM section. + In addition, each blob write operation is divided into a few operations + in order to decrease the amount of phys. contiguous buffer needed. + Thus, when we select a blob the address may be with some offset + from the beginning of PRAM section. + The same holds for the INT_TABLE sections. +**********************************************************/ +#define IF_IS_INT_TABLE_ADDR(base, addr) \ + if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) + +#define IF_IS_PRAM_ADDR(base, addr) \ + if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) + +static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data) +{ + IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr) + data = bp->tsem_int_table_data; + else IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr) + data = bp->csem_int_table_data; + else IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr) + data = bp->usem_int_table_data; + else IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr) + data = bp->xsem_int_table_data; + else IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr) + data = bp->tsem_pram_data; + else IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr) + data = bp->csem_pram_data; + else IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr) + data = bp->usem_pram_data; + else IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr) + data = bp->xsem_pram_data; + + return data; +} + +static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len) +{ + int offset = 0; + + if (bp->dmae_ready) { + while (len > DMAE_LEN32_WR_MAX) { + bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, + addr + offset, DMAE_LEN32_WR_MAX); + offset += DMAE_LEN32_WR_MAX * 4; + len -= DMAE_LEN32_WR_MAX; + } + bnx2x_write_dmae(bp, bp->gunzip_mapping + offset, + addr + offset, len); + } else + bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len); +} + +static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, + u32 len) +{ + /* This is needed for NO_ZIP mode, currently supported + in little endian mode only */ + data = (const u32*)bnx2x_sel_blob(bp, addr, (const u8*)data); + + if ((len * 4) > FW_BUF_SIZE) { + BNX2X_ERR("LARGE DMAE OPERATION ! " + "addr 0x%x len 0x%x\n", addr, len*4); + return; + } + memcpy(bp->gunzip_buf, data, len * 4); + + bnx2x_write_big_buf_wb(bp, addr, len); +} + +static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, + u32 len, u32 blob_off) +{ + int rc, i; + const u8 *data = NULL; + + data = bnx2x_sel_blob(bp, addr, data) + 4*blob_off; + + if (data == NULL) { + panic("Blob not found for addr 0x%x\n", addr); + return; + } + + rc = bnx2x_gunzip(bp, data, len); + if (rc) { + BNX2X_ERR("gunzip failed ! addr 0x%x rc %d\n", addr, rc); + BNX2X_ERR("blob_offset=0x%x\n", blob_off); + return; + } + + /* gunzip_outlen is in dwords */ + len = bp->gunzip_outlen; + for (i = 0; i < len; i++) + ((u32 *)bp->gunzip_buf)[i] = + cpu_to_le32(((u32 *)bp->gunzip_buf)[i]); + + bnx2x_write_big_buf_wb(bp, addr, len); +} + +static void bnx2x_init_block(struct bnx2x *bp, u32 block, u32 stage) +{ + int hw_wr, i; + u16 op_start = + bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_START)]; + u16 op_end = + bp->init_ops_offsets[BLOCK_OPS_IDX(block,stage,STAGE_END)]; + union init_op *op; + u32 op_type, addr, len; + const u32 *data, *data_base; + + /* If empty block */ + if (op_start == op_end) + return; + + if (CHIP_REV_IS_FPGA(bp)) + hw_wr = OP_WR_FPGA; + else if (CHIP_REV_IS_EMUL(bp)) + hw_wr = OP_WR_EMUL; + else + hw_wr = OP_WR_ASIC; + + data_base = bp->init_data; + + for (i = op_start; i < op_end; i++) { + + op = (union init_op *)&(bp->init_ops[i]); + + op_type = op->str_wr.op; + addr = op->str_wr.offset; + len = op->str_wr.data_len; + data = data_base + op->str_wr.data_off; + + /* HW/EMUL specific */ + if (unlikely((op_type > OP_WB) && (op_type == hw_wr))) + op_type = OP_WR; + + switch (op_type) { + case OP_RD: + REG_RD(bp, addr); + break; + case OP_WR: + REG_WR(bp, addr, op->write.val); + break; + case OP_SW: + bnx2x_init_str_wr(bp, addr, data, len); + break; + case OP_WB: + bnx2x_init_wr_wb(bp, addr, data, len); + break; + case OP_SI: + bnx2x_init_ind_wr(bp, addr, data, len); + break; + case OP_ZR: + bnx2x_init_fill(bp, addr, 0, op->zero.len); + break; + case OP_ZP: + bnx2x_init_wr_zp(bp, addr, len, + op->str_wr.data_off); + break; + case OP_WR_64: + bnx2x_init_wr_64(bp, addr, data, len); + break; + default: + /* happens whenever an op is of a diff HW */ +#if 0 + DP(NETIF_MSG_HW, "skipping init operation " + "index %d[%d:%d]: type %d addr 0x%x " + "len %d(0x%x)\n", + i, op_start, op_end, op_type, addr, len, len); +#endif + break; + } + } +} + +/* PXP */ +static void bnx2x_init_pxp(struct bnx2x *bp) +{ + u16 devctl; + int r_order, w_order; + u32 val, i; + + pci_read_config_word(bp->pdev, + bp->pcie_cap + PCI_EXP_DEVCTL, &devctl); + DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); + w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + if (bp->mrrs == -1) + r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12); + else { + DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs); + r_order = bp->mrrs; + } + + if (r_order > MAX_RD_ORD) { + DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n", + r_order, MAX_RD_ORD); + r_order = MAX_RD_ORD; + } + if (w_order > MAX_WR_ORD) { + DP(NETIF_MSG_HW, "write order of %d order adjusted to %d\n", + w_order, MAX_WR_ORD); + w_order = MAX_WR_ORD; + } + if (CHIP_REV_IS_FPGA(bp)) { + DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n"); + w_order = 0; + } + DP(NETIF_MSG_HW, "read order %d write order %d\n", r_order, w_order); + + for (i = 0; i < NUM_RD_Q-1; i++) { + REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l); + REG_WR(bp, read_arb_addr[i].add, + read_arb_data[i][r_order].add); + REG_WR(bp, read_arb_addr[i].ubound, + read_arb_data[i][r_order].ubound); + } + + for (i = 0; i < NUM_WR_Q-1; i++) { + if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || + (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { + + REG_WR(bp, write_arb_addr[i].l, + write_arb_data[i][w_order].l); + + REG_WR(bp, write_arb_addr[i].add, + write_arb_data[i][w_order].add); + + REG_WR(bp, write_arb_addr[i].ubound, + write_arb_data[i][w_order].ubound); + } else { + + val = REG_RD(bp, write_arb_addr[i].l); + REG_WR(bp, write_arb_addr[i].l, + val | (write_arb_data[i][w_order].l << 10)); + + val = REG_RD(bp, write_arb_addr[i].add); + REG_WR(bp, write_arb_addr[i].add, + val | (write_arb_data[i][w_order].add << 10)); + + val = REG_RD(bp, write_arb_addr[i].ubound); + REG_WR(bp, write_arb_addr[i].ubound, + val | (write_arb_data[i][w_order].ubound << 7)); + } + } + + val = write_arb_data[NUM_WR_Q-1][w_order].add; + val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; + val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; + REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val); + + val = read_arb_data[NUM_RD_Q-1][r_order].add; + val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; + val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; + REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val); + + REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order); + REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order); + REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order); + REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order); + + if (r_order == MAX_RD_ORD) + REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00); + + REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); + + if (CHIP_IS_E1H(bp)) { + val = ((w_order == 0) ? 2 : 3); + REG_WR(bp, PXP2_REG_WR_HC_MPS, val); + REG_WR(bp, PXP2_REG_WR_USDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val); + REG_WR(bp, PXP2_REG_WR_QM_MPS, val); + REG_WR(bp, PXP2_REG_WR_TM_MPS, val); + REG_WR(bp, PXP2_REG_WR_SRC_MPS, val); + REG_WR(bp, PXP2_REG_WR_DBG_MPS, val); + REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */ + REG_WR(bp, PXP2_REG_WR_CDU_MPS, val); + } +} + +/***************************************************************************** + * Description: + * Calculates crc 8 on a word value: polynomial 0-1-2-8 + * Code was translated from Verilog. + ****************************************************************************/ +static u8 calc_crc8(u32 data, u8 crc) +{ + u8 D[32]; + u8 NewCRC[8]; + u8 C[8]; + u8 crc_res; + u8 i; + + /* split the data into 31 bits */ + for (i = 0; i < 32; i++) { + D[i] = data & 1; + data = data >> 1; + } + + /* split the crc into 8 bits */ + for (i = 0; i < 8; i++) { + C[i] = crc & 1; + crc = crc >> 1; + } + + NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^ + D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^ + C[6] ^ C[7]; + NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^ + D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^ + D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6]; + NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^ + D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^ + C[0] ^ C[1] ^ C[4] ^ C[5]; + NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^ + D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^ + C[1] ^ C[2] ^ C[5] ^ C[6]; + NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^ + D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^ + C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7]; + NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^ + D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^ + C[3] ^ C[4] ^ C[7]; + NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^ + D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^ + C[5]; + NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^ + D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^ + C[6]; + + crc_res = 0; + for (i = 0; i < 8; i++) + crc_res |= (NewCRC[i] << i); + + return crc_res; +} + +#endif /* BNX2X_INIT_OPS_H */ diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ad5ef25add3e..cdc80e0820cd 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -53,12 +53,19 @@ #include "bnx2x.h" #include "bnx2x_init.h" +#include "bnx2x_init_ops.h" #include "bnx2x_dump.h" #define DRV_MODULE_VERSION "1.48.105" #define DRV_MODULE_RELDATE "2009/03/02" #define BNX2X_BC_VER 0x040200 +#include +#include "bnx2x_fw_file_hdr.h" +/* FW files */ +#define FW_FILE_PREFIX_E1 "bnx2x-e1-" +#define FW_FILE_PREFIX_E1H "bnx2x-e1h-" + /* Time in jiffies before concluding the transmitter is hung */ #define TX_TIMEOUT (5*HZ) @@ -5232,13 +5239,15 @@ static void bnx2x_gunzip_end(struct bnx2x *bp) } } -static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len) +static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len) { int n, rc; /* check gzip header */ - if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) + if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) { + BNX2X_ERR("Bad gzip header\n"); return -EINVAL; + } n = 10; @@ -5247,7 +5256,7 @@ static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len) if (zbuf[3] & FNAME) while ((zbuf[n++] != 0) && (n < len)); - bp->strm->next_in = zbuf + n; + bp->strm->next_in = (typeof(bp->strm->next_in))zbuf + n; bp->strm->avail_in = len - n; bp->strm->next_out = bp->gunzip_buf; bp->strm->avail_out = FW_BUF_SIZE; @@ -5369,8 +5378,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03); msleep(50); - bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); - bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); DP(NETIF_MSG_HW, "part2\n"); @@ -5434,8 +5443,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03); msleep(50); - bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); - bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); #ifndef BCM_ISCSI /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); @@ -5510,7 +5519,7 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); - bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END); + bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE); if (CHIP_IS_E1H(bp)) REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp)); @@ -5518,14 +5527,14 @@ static int bnx2x_init_common(struct bnx2x *bp) msleep(30); REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0); - bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END); + bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE); if (CHIP_IS_E1(bp)) { /* enable HW interrupt from PXP on USDM overflow bit 16 on INT_MASK_0 */ REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0); } - bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END); + bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE); bnx2x_init_pxp(bp); #ifdef __BIG_ENDIAN @@ -5571,60 +5580,60 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0); REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0); - bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END); + bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE); /* clean the DMAE memory */ bp->dmae_ready = 1; bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8); - bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END); - bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END); - bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END); - bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END); + bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE); bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3); - bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END); + bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE); /* soft reset pulse */ REG_WR(bp, QM_REG_SOFT_RESET, 1); REG_WR(bp, QM_REG_SOFT_RESET, 0); #ifdef BCM_ISCSI - bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END); + bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE); #endif - bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END); + bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE); REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT); if (!CHIP_REV_IS_SLOW(bp)) { /* enable hw interrupt from doorbell Q */ REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0); } - bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END); - bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE); REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); if (CHIP_IS_E1H(bp)) REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp)); - bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END); - bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END); - bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END); - bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END); + bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE); bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp)); bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp)); bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp)); bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp)); - bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END); - bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END); - bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END); - bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END); + bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE); /* sync semi rtc */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, @@ -5632,16 +5641,16 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x80000000); - bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END); - bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END); - bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END); + bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE); REG_WR(bp, SRC_REG_SOFT_RST, 1); for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) { REG_WR(bp, i, 0xc0cac01a); /* TODO: replace with something meaningful */ } - bnx2x_init_block(bp, SRCH_COMMON_START, SRCH_COMMON_END); + bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE); REG_WR(bp, SRC_REG_SOFT_RST, 0); if (sizeof(union cdu_context) != 1024) @@ -5649,7 +5658,7 @@ static int bnx2x_init_common(struct bnx2x *bp) printk(KERN_ALERT PFX "please adjust the size of" " cdu_context(%ld)\n", (long)sizeof(union cdu_context)); - bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END); + bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE); val = (4 << 24) + (0 << 12) + 1024; REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val); if (CHIP_IS_E1(bp)) { @@ -5658,7 +5667,7 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, CDU_REG_CDU_DEBUG, 0); } - bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END); + bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE); REG_WR(bp, CFC_REG_INIT_REG, 0x7FF); /* enable context validation interrupt from CFC */ REG_WR(bp, CFC_REG_CFC_INT_MASK, 0); @@ -5666,20 +5675,25 @@ static int bnx2x_init_common(struct bnx2x *bp) /* set the thresholds to prevent CFC/CDU race */ REG_WR(bp, CFC_REG_DEBUG0, 0x20020000); - bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END); - bnx2x_init_block(bp, MISC_AEU_COMMON_START, MISC_AEU_COMMON_END); + bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE); + bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE); /* PXPCS COMMON comes here */ + bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE); /* Reset PCIE errors for debug */ REG_WR(bp, 0x2814, 0xffffffff); REG_WR(bp, 0x3820, 0xffffffff); /* EMAC0 COMMON comes here */ + bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE); /* EMAC1 COMMON comes here */ + bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE); /* DBU COMMON comes here */ + bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE); /* DBG COMMON comes here */ + bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE); - bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END); + bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE); if (CHIP_IS_E1H(bp)) { REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp)); REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp)); @@ -5763,6 +5777,7 @@ static int bnx2x_init_common(struct bnx2x *bp) static int bnx2x_init_port(struct bnx2x *bp) { int port = BP_PORT(bp); + int init_stage = port ? PORT1_STAGE : PORT0_STAGE; u32 low, high; u32 val; @@ -5771,7 +5786,9 @@ static int bnx2x_init_port(struct bnx2x *bp) REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0); /* Port PXP comes here */ + bnx2x_init_block(bp, PXP_BLOCK, init_stage); /* Port PXP2 comes here */ + bnx2x_init_block(bp, PXP2_BLOCK, init_stage); #ifdef BCM_ISCSI /* Port0 1 * Port1 385 */ @@ -5798,21 +5815,19 @@ static int bnx2x_init_port(struct bnx2x *bp) REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i)); #endif /* Port CMs come here */ - bnx2x_init_block(bp, (port ? XCM_PORT1_START : XCM_PORT0_START), - (port ? XCM_PORT1_END : XCM_PORT0_END)); + bnx2x_init_block(bp, XCM_BLOCK, init_stage); /* Port QM comes here */ #ifdef BCM_ISCSI REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20); REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31); - bnx2x_init_block(bp, func ? TIMERS_PORT1_START : TIMERS_PORT0_START, - func ? TIMERS_PORT1_END : TIMERS_PORT0_END); + bnx2x_init_block(bp, TIMERS_BLOCK, init_stage); #endif /* Port DQ comes here */ + bnx2x_init_block(bp, DQ_BLOCK, init_stage); - bnx2x_init_block(bp, (port ? BRB1_PORT1_START : BRB1_PORT0_START), - (port ? BRB1_PORT1_END : BRB1_PORT0_END)); + bnx2x_init_block(bp, BRB1_BLOCK, init_stage); if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) { /* no pause for emulation and FPGA */ low = 0; @@ -5837,25 +5852,27 @@ static int bnx2x_init_port(struct bnx2x *bp) /* Port PRS comes here */ + bnx2x_init_block(bp, PRS_BLOCK, init_stage); /* Port TSDM comes here */ + bnx2x_init_block(bp, TSDM_BLOCK, init_stage); /* Port CSDM comes here */ + bnx2x_init_block(bp, CSDM_BLOCK, init_stage); /* Port USDM comes here */ + bnx2x_init_block(bp, USDM_BLOCK, init_stage); /* Port XSDM comes here */ + bnx2x_init_block(bp, XSDM_BLOCK, init_stage); - bnx2x_init_block(bp, port ? TSEM_PORT1_START : TSEM_PORT0_START, - port ? TSEM_PORT1_END : TSEM_PORT0_END); - bnx2x_init_block(bp, port ? USEM_PORT1_START : USEM_PORT0_START, - port ? USEM_PORT1_END : USEM_PORT0_END); - bnx2x_init_block(bp, port ? CSEM_PORT1_START : CSEM_PORT0_START, - port ? CSEM_PORT1_END : CSEM_PORT0_END); - bnx2x_init_block(bp, port ? XSEM_PORT1_START : XSEM_PORT0_START, - port ? XSEM_PORT1_END : XSEM_PORT0_END); + bnx2x_init_block(bp, TSEM_BLOCK, init_stage); + bnx2x_init_block(bp, USEM_BLOCK, init_stage); + bnx2x_init_block(bp, CSEM_BLOCK, init_stage); + bnx2x_init_block(bp, XSEM_BLOCK, init_stage); /* Port UPB comes here */ + bnx2x_init_block(bp, UPB_BLOCK, init_stage); /* Port XPB comes here */ + bnx2x_init_block(bp, XPB_BLOCK, init_stage); - bnx2x_init_block(bp, port ? PBF_PORT1_START : PBF_PORT0_START, - port ? PBF_PORT1_END : PBF_PORT0_END); + bnx2x_init_block(bp, PBF_BLOCK, init_stage); /* configure PBF to work without PAUSE mtu 9000 */ REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0); @@ -5885,18 +5902,17 @@ static int bnx2x_init_port(struct bnx2x *bp) /* Port SRCH comes here */ #endif /* Port CDU comes here */ + bnx2x_init_block(bp, CDU_BLOCK, init_stage); /* Port CFC comes here */ + bnx2x_init_block(bp, CFC_BLOCK, init_stage); if (CHIP_IS_E1(bp)) { REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); } - bnx2x_init_block(bp, port ? HC_PORT1_START : HC_PORT0_START, - port ? HC_PORT1_END : HC_PORT0_END); + bnx2x_init_block(bp, HC_BLOCK, init_stage); - bnx2x_init_block(bp, port ? MISC_AEU_PORT1_START : - MISC_AEU_PORT0_START, - port ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END); + bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage); /* init aeu_mask_attn_func_0/1: * - SF mode: bits 3-7 are masked. only bits 0-2 are in use * - MF mode: bit 3 is masked. bits 0-2 are in use as in SF @@ -5905,13 +5921,17 @@ static int bnx2x_init_port(struct bnx2x *bp) (IS_E1HMF(bp) ? 0xF7 : 0x7)); /* Port PXPCS comes here */ + bnx2x_init_block(bp, PXPCS_BLOCK, init_stage); /* Port EMAC0 comes here */ + bnx2x_init_block(bp, EMAC0_BLOCK, init_stage); /* Port EMAC1 comes here */ + bnx2x_init_block(bp, EMAC1_BLOCK, init_stage); /* Port DBU comes here */ + bnx2x_init_block(bp, DBU_BLOCK, init_stage); /* Port DBG comes here */ + bnx2x_init_block(bp, DBG_BLOCK, init_stage); - bnx2x_init_block(bp, port ? NIG_PORT1_START : NIG_PORT0_START, - port ? NIG_PORT1_END : NIG_PORT0_END); + bnx2x_init_block(bp, NIG_BLOCK, init_stage); REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1); @@ -5931,7 +5951,9 @@ static int bnx2x_init_port(struct bnx2x *bp) } /* Port MCP comes here */ + bnx2x_init_block(bp, MCP_BLOCK, init_stage); /* Port DMAE comes here */ + bnx2x_init_block(bp, DMAE_BLOCK, init_stage); switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: @@ -6036,7 +6058,7 @@ static int bnx2x_init_func(struct bnx2x *bp) if (CHIP_IS_E1H(bp)) { for (i = 0; i < 9; i++) bnx2x_init_block(bp, - cm_start[func][i], cm_end[func][i]); + cm_blocks[i], FUNC0_STAGE + func); REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1); REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov); @@ -6049,7 +6071,7 @@ static int bnx2x_init_func(struct bnx2x *bp) REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0); REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0); } - bnx2x_init_block(bp, hc_limits[func][0], hc_limits[func][1]); + bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func); /* Reset PCIE errors for debug */ REG_WR(bp, 0x2114, 0xffffffff); @@ -11082,6 +11104,190 @@ static int __devinit bnx2x_get_pcie_speed(struct bnx2x *bp) val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT; return val; } +static int __devinit bnx2x_check_firmware(struct bnx2x *bp) +{ + struct bnx2x_fw_file_hdr *fw_hdr; + struct bnx2x_fw_file_section *sections; + u16 *ops_offsets; + u32 offset, len, num_ops; + int i; + const struct firmware *firmware = bp->firmware; + const u8 * fw_ver; + + if (firmware->size < sizeof(struct bnx2x_fw_file_hdr)) + return -EINVAL; + + fw_hdr = (struct bnx2x_fw_file_hdr *)firmware->data; + sections = (struct bnx2x_fw_file_section *)fw_hdr; + + /* Make sure none of the offsets and sizes make us read beyond + * the end of the firmware data */ + for (i = 0; i < sizeof(*fw_hdr) / sizeof(*sections); i++) { + offset = be32_to_cpu(sections[i].offset); + len = be32_to_cpu(sections[i].len); + if (offset + len > firmware->size) { + printk(KERN_ERR PFX "Section %d length is out of bounds\n", i); + return -EINVAL; + } + } + + /* Likewise for the init_ops offsets */ + offset = be32_to_cpu(fw_hdr->init_ops_offsets.offset); + ops_offsets = (u16 *)(firmware->data + offset); + num_ops = be32_to_cpu(fw_hdr->init_ops.len) / sizeof(struct raw_op); + + for (i = 0; i < be32_to_cpu(fw_hdr->init_ops_offsets.len) / 2; i++) { + if (be16_to_cpu(ops_offsets[i]) > num_ops) { + printk(KERN_ERR PFX "Section offset %d is out of bounds\n", i); + return -EINVAL; + } + } + + /* Check FW version */ + offset = be32_to_cpu(fw_hdr->fw_version.offset); + fw_ver = firmware->data + offset; + if ((fw_ver[0] != BCM_5710_FW_MAJOR_VERSION) || + (fw_ver[1] != BCM_5710_FW_MINOR_VERSION) || + (fw_ver[2] != BCM_5710_FW_REVISION_VERSION) || + (fw_ver[3] != BCM_5710_FW_ENGINEERING_VERSION)) { + printk(KERN_ERR PFX "Bad FW version:%d.%d.%d.%d." + " Should be %d.%d.%d.%d\n", + fw_ver[0], fw_ver[1], fw_ver[2], + fw_ver[3], BCM_5710_FW_MAJOR_VERSION, + BCM_5710_FW_MINOR_VERSION, + BCM_5710_FW_REVISION_VERSION, + BCM_5710_FW_ENGINEERING_VERSION); + return -EINVAL; + } + + return 0; +} + +static void inline be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n) +{ + u32 i; + const __be32 *source = (const __be32*)_source; + u32 *target = (u32*)_target; + + for (i = 0; i < n/4; i++) + target[i] = be32_to_cpu(source[i]); +} + +/* + Ops array is stored in the following format: + {op(8bit), offset(24bit, big endian), data(32bit, big endian)} + */ +static void inline bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n) +{ + u32 i, j, tmp; + const __be32 *source = (const __be32*)_source; + struct raw_op *target = (struct raw_op*)_target; + + for (i = 0, j = 0; i < n/8; i++, j+=2) { + tmp = be32_to_cpu(source[j]); + target[i].op = (tmp >> 24) & 0xff; + target[i].offset = tmp & 0xffffff; + target[i].raw_data = be32_to_cpu(source[j+1]); + } +} +static void inline be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n) +{ + u32 i; + u16 *target = (u16*)_target; + const __be16 *source = (const __be16*)_source; + + for (i = 0; i < n/2; i++) + target[i] = be16_to_cpu(source[i]); +} + +#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \ + do { \ + u32 len = be32_to_cpu(fw_hdr->arr.len); \ + bp->arr = kmalloc(len, GFP_KERNEL); \ + if (!bp->arr) { \ + printk(KERN_ERR PFX "Failed to allocate %d bytes for "#arr"\n", len); \ + goto lbl; \ + } \ + func(bp->firmware->data + \ + be32_to_cpu(fw_hdr->arr.offset), \ + (u8*)bp->arr, len); \ + } while (0) + + +static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) +{ + char fw_file_name[40] = {0}; + int rc, offset; + struct bnx2x_fw_file_hdr *fw_hdr; + + /* Create a FW file name */ + if (CHIP_IS_E1(bp)) + offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1); + else + offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H); + + sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw", + BCM_5710_FW_MAJOR_VERSION, + BCM_5710_FW_MINOR_VERSION, + BCM_5710_FW_REVISION_VERSION, + BCM_5710_FW_ENGINEERING_VERSION); + + printk(KERN_INFO PFX "Loading %s\n", fw_file_name); + + rc = request_firmware(&bp->firmware, fw_file_name, dev); + if (rc) { + printk(KERN_ERR PFX "Can't load firmware file %s\n", fw_file_name); + goto request_firmware_exit; + } + + rc = bnx2x_check_firmware(bp); + if (rc) { + printk(KERN_ERR PFX "Corrupt firmware file %s\n", fw_file_name); + goto request_firmware_exit; + } + + fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data; + + /* Initialize the pointers to the init arrays */ + /* Blob */ + BNX2X_ALLOC_AND_SET(init_data, request_firmware_exit, be32_to_cpu_n); + + /* Opcodes */ + BNX2X_ALLOC_AND_SET(init_ops, init_ops_alloc_err, bnx2x_prep_ops); + + /* Offsets */ + BNX2X_ALLOC_AND_SET(init_ops_offsets, init_offsets_alloc_err, be16_to_cpu_n); + + /* STORMs firmware */ + bp->tsem_int_table_data = bp->firmware->data + + be32_to_cpu(fw_hdr->tsem_int_table_data.offset); + bp->tsem_pram_data = bp->firmware->data + + be32_to_cpu(fw_hdr->tsem_pram_data.offset); + bp->usem_int_table_data = bp->firmware->data + + be32_to_cpu(fw_hdr->usem_int_table_data.offset); + bp->usem_pram_data = bp->firmware->data + + be32_to_cpu(fw_hdr->usem_pram_data.offset); + bp->xsem_int_table_data = bp->firmware->data + + be32_to_cpu(fw_hdr->xsem_int_table_data.offset); + bp->xsem_pram_data = bp->firmware->data + + be32_to_cpu(fw_hdr->xsem_pram_data.offset); + bp->csem_int_table_data = bp->firmware->data + + be32_to_cpu(fw_hdr->csem_int_table_data.offset); + bp->csem_pram_data = bp->firmware->data + + be32_to_cpu(fw_hdr->csem_pram_data.offset); + + return 0; +init_offsets_alloc_err: + kfree(bp->init_ops); +init_ops_alloc_err: + kfree(bp->init_data); +request_firmware_exit: + release_firmware(bp->firmware); + + return rc; +} + + static int __devinit bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -11116,6 +11322,13 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, if (rc) goto init_one_exit; + /* Set init arrays */ + rc = bnx2x_init_firmware(bp, &pdev->dev); + if (rc) { + printk(KERN_ERR PFX "Error loading firmware\n"); + goto init_one_exit; + } + rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -11163,6 +11376,11 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) unregister_netdev(dev); + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); + kfree(bp->init_data); + release_firmware(bp->firmware); + if (bp->regview) iounmap(bp->regview); @@ -11431,3 +11649,4 @@ static void __exit bnx2x_cleanup(void) module_init(bnx2x_init); module_exit(bnx2x_cleanup); + diff --git a/firmware/Makefile b/firmware/Makefile index 25200d106ee8..1c670e0c0448 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -32,6 +32,7 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \ adaptec/starfire_tx.bin fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw +fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-4.8.53.0.fw bnx2x-e1h-4.8.53.0.fw fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-4.6.17.fw \ bnx2/bnx2-rv2p-09-4.6.15.fw \ bnx2/bnx2-mips-06-4.6.16.fw \ diff --git a/firmware/WHENCE b/firmware/WHENCE index 4c52984a8319..c1e9c5ab694c 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -614,6 +614,26 @@ File: myricom/lanai.bin Licence: Unknown +Found in hex form in kernel source. + +-------------------------------------------------------------------------- + +Driver: bnx2x: Broadcom Everest + +File: bnx2x-e1-4.8.53.0.fw.ihex +File: bnx2x-e1h-4.8.53.0.fw.ihex + +License: + Copyright (c) 2007-2009 Broadcom Corporation + + This file contains firmware data derived from proprietary unpublished + source code, Copyright (c) 2007-2009 Broadcom Corporation. + + Permission is hereby granted for the distribution of this firmware data + in hexadecimal or equivalent format, provided this copyright notice is + accompanying it. + + Found in hex form in kernel source. -------------------------------------------------------------------------- -- cgit v1.2.3 From 29b35dd868e9442914a44ff8e8be739c3d65cc9d Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 27 Apr 2009 03:28:03 -0700 Subject: bnx2x: Removed blob file Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_init_values.h | 16322 -------------------------------------- 1 file changed, 16322 deletions(-) delete mode 100644 drivers/net/bnx2x_init_values.h diff --git a/drivers/net/bnx2x_init_values.h b/drivers/net/bnx2x_init_values.h deleted file mode 100644 index 1f22c9ab66d4..000000000000 --- a/drivers/net/bnx2x_init_values.h +++ /dev/null @@ -1,16322 +0,0 @@ -#ifndef __BNX2X_INIT_VALUES_H__ -#define __BNX2X_INIT_VALUES_H__ - -/* bnx2x_init_values.h: Broadcom NX2 10G network driver. - * - * Copyright (c) 2007-2009 Broadcom Corporation - * - * 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, except as noted below. - * - * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2007-2009 Broadcom Corporation. - * - * Permission is hereby granted for the distribution of this firmware data - * in hexadecimal or equivalent format, provided this copyright notice is - * accompanying it. - * - * - * This array contains the list of operations needed to initialize the chip. - * - * For each block in the chip there are three init stages: - * common - HW used by both ports, - * port1 and port2 - initialization for a specific Ethernet port. - * When a port is opened or closed, the management CPU tells the driver - * whether to init/disable common HW in addition to the port HW. - * This way the first port going up will first initializes the common HW, - * and the last port going down also resets the common HW - * - * For each init stage/block there is a list of actions needed in a format: - * {operation, register, data} - * where: - * OP_WR - write a value to the chip. - * OP_RD - read a register (usually a clear on read register). - * OP_SW - string write, write a section of consecutive addresses to the chip. - * OP_SI - copy a string using indirect writes. - * OP_ZR - clear a range of memory. - * OP_ZP - unzip and copy using DMAE. - * OP_WB - string copy using DMAE. - * - * The #defines mark the stages. - * - */ - -static const struct raw_op init_ops[] = { -#define PRS_COMMON_START 0 - {OP_WR, PRS_REG_INC_VALUE, 0xf}, - {OP_WR, PRS_REG_EVENT_ID_1, 0x45}, - {OP_WR, PRS_REG_EVENT_ID_2, 0x84}, - {OP_WR, PRS_REG_EVENT_ID_3, 0x6}, - {OP_WR, PRS_REG_NO_MATCH_EVENT_ID, 0x4}, - {OP_WR, PRS_REG_CM_HDR_TYPE_0, 0x0}, - {OP_WR, PRS_REG_CM_HDR_TYPE_1, 0x12170000}, - {OP_WR, PRS_REG_CM_HDR_TYPE_2, 0x22170000}, - {OP_WR, PRS_REG_CM_HDR_TYPE_3, 0x32170000}, - {OP_ZR, PRS_REG_CM_HDR_TYPE_4, 0x5}, - {OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_1, 0x12150000}, - {OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_2, 0x22150000}, - {OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_3, 0x32150000}, - {OP_ZR, PRS_REG_CM_HDR_LOOPBACK_TYPE_4, 0x4}, - {OP_WR, PRS_REG_CM_NO_MATCH_HDR, 0x2100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_0, 0x100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_1, 0x10100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_2, 0x20100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_3, 0x30100000}, - {OP_ZR_E1, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4, 0x4}, - {OP_WR_E1H, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4, 0x40100000}, - {OP_ZR_E1H, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_5, 0x3}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_0, 0x100000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_1, 0x12140000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_2, 0x22140000}, - {OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_3, 0x32140000}, - {OP_ZR_E1, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4, 0x4}, - {OP_WR_E1H, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4, 0x42140000}, - {OP_ZR_E1H, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_5, 0x3}, - {OP_RD, PRS_REG_NUM_OF_PACKETS, 0x0}, - {OP_RD, PRS_REG_NUM_OF_CFC_FLUSH_MESSAGES, 0x0}, - {OP_RD, PRS_REG_NUM_OF_TRANSPARENT_FLUSH_MESSAGES, 0x0}, - {OP_RD, PRS_REG_NUM_OF_DEAD_CYCLES, 0x0}, - {OP_WR_E1H, PRS_REG_FCOE_TYPE, 0x8906}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_0, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_1, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_2, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_3, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_4, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_5, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_6, 0xff}, - {OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_7, 0xff}, - {OP_WR, PRS_REG_PURE_REGIONS, 0x3e}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_0, 0x0}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_1, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_2, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_3, 0x3f}, - {OP_WR_E1, PRS_REG_PACKET_REGIONS_TYPE_4, 0x0}, - {OP_WR_E1H, PRS_REG_PACKET_REGIONS_TYPE_4, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_5, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_6, 0x3f}, - {OP_WR, PRS_REG_PACKET_REGIONS_TYPE_7, 0x3f}, -#define PRS_COMMON_END 52 -#define SRCH_COMMON_START 52 - {OP_WR_E1H, SRC_REG_E1HMF_ENABLE, 0x1}, -#define SRCH_COMMON_END 53 -#define TSDM_COMMON_START 53 - {OP_WR_E1, TSDM_REG_CFC_RSP_START_ADDR, 0x411}, - {OP_WR_E1H, TSDM_REG_CFC_RSP_START_ADDR, 0x211}, - {OP_WR_E1, TSDM_REG_CMP_COUNTER_START_ADDR, 0x400}, - {OP_WR_E1H, TSDM_REG_CMP_COUNTER_START_ADDR, 0x200}, - {OP_WR_E1, TSDM_REG_Q_COUNTER_START_ADDR, 0x404}, - {OP_WR_E1H, TSDM_REG_Q_COUNTER_START_ADDR, 0x204}, - {OP_WR_E1, TSDM_REG_PCK_END_MSG_START_ADDR, 0x419}, - {OP_WR_E1H, TSDM_REG_PCK_END_MSG_START_ADDR, 0x219}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, TSDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_ZR_E1, TSDM_REG_AGG_INT_EVENT_0, 0x2}, - {OP_WR_E1H, TSDM_REG_AGG_INT_EVENT_0, 0x20}, - {OP_WR_E1H, TSDM_REG_AGG_INT_EVENT_1, 0x0}, - {OP_WR, TSDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, TSDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_ZR_E1, TSDM_REG_AGG_INT_EVENT_4, 0x7c}, - {OP_ZR_E1H, TSDM_REG_AGG_INT_EVENT_4, 0x1c}, - {OP_WR_E1H, TSDM_REG_AGG_INT_T_0, 0x1}, - {OP_ZR_E1H, TSDM_REG_AGG_INT_T_1, 0x5f}, - {OP_WR, TSDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, TSDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, TSDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, TSDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, TSDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, TSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, TSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, TSDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, TSDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, TSDM_REG_TIMER_TICK, 0xa}, -#define TSDM_COMMON_END 96 -#define TCM_COMMON_START 96 - {OP_WR, TCM_REG_XX_MAX_LL_SZ, 0x20}, - {OP_WR, TCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, TCM_REG_TQM_TCM_HDR_P, 0x2150020}, - {OP_WR, TCM_REG_TQM_TCM_HDR_S, 0x2150020}, - {OP_WR, TCM_REG_TM_TCM_HDR, 0x30}, - {OP_WR, TCM_REG_ERR_TCM_HDR, 0x8100000}, - {OP_WR, TCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, TCM_REG_EXPR_EVNT_ID, 0x30}, - {OP_WR, TCM_REG_STOP_EVNT_ID, 0x31}, - {OP_WR, TCM_REG_STORM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_PRS_WEIGHT, 0x5}, - {OP_WR, TCM_REG_PBF_WEIGHT, 0x6}, - {OP_WR, TCM_REG_USEM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_CSEM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_CP_WEIGHT, 0x0}, - {OP_WR, TCM_REG_TSDM_WEIGHT, 0x5}, - {OP_WR, TCM_REG_TQM_P_WEIGHT, 0x2}, - {OP_WR, TCM_REG_TQM_S_WEIGHT, 0x2}, - {OP_WR, TCM_REG_TM_WEIGHT, 0x2}, - {OP_WR, TCM_REG_TCM_TQM_USE_Q, 0x1}, - {OP_WR, TCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, TCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, TCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, TCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, TCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, TCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, TCM_REG_TQM_INIT_CRD, 0x20}, - {OP_WR, TCM_REG_XX_INIT_CRD, 0x13}, - {OP_WR, TCM_REG_XX_MSG_NUM, 0x20}, - {OP_ZR, TCM_REG_XX_TABLE, 0xa}, - {OP_SW, TCM_REG_XX_DESCR_TABLE, 0x200000}, - {OP_WR, TCM_REG_N_SM_CTX_LD_0, 0x7}, - {OP_WR, TCM_REG_N_SM_CTX_LD_1, 0x7}, - {OP_WR, TCM_REG_N_SM_CTX_LD_2, 0x8}, - {OP_WR, TCM_REG_N_SM_CTX_LD_3, 0x8}, - {OP_ZR_E1, TCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR_E1H, TCM_REG_N_SM_CTX_LD_4, 0x1}, - {OP_ZR_E1H, TCM_REG_N_SM_CTX_LD_5, 0x3}, - {OP_WR, TCM_REG_TCM_REG0_SZ, 0x6}, - {OP_WR_E1, TCM_REG_PHYS_QNUM0_0, 0xd}, - {OP_WR_E1, TCM_REG_PHYS_QNUM0_1, 0x2d}, - {OP_WR_E1, TCM_REG_PHYS_QNUM1_0, 0x7}, - {OP_WR_E1, TCM_REG_PHYS_QNUM1_1, 0x27}, - {OP_WR_E1, TCM_REG_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1, TCM_REG_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1, TCM_REG_PHYS_QNUM3_0, 0x7}, - {OP_WR_E1, TCM_REG_PHYS_QNUM3_1, 0x27}, - {OP_WR, TCM_REG_TCM_STORM0_IFEN, 0x1}, - {OP_WR, TCM_REG_TCM_STORM1_IFEN, 0x1}, - {OP_WR, TCM_REG_TCM_TQM_IFEN, 0x1}, - {OP_WR, TCM_REG_STORM_TCM_IFEN, 0x1}, - {OP_WR, TCM_REG_TQM_TCM_IFEN, 0x1}, - {OP_WR, TCM_REG_TSDM_IFEN, 0x1}, - {OP_WR, TCM_REG_TM_TCM_IFEN, 0x1}, - {OP_WR, TCM_REG_PRS_IFEN, 0x1}, - {OP_WR, TCM_REG_PBF_IFEN, 0x1}, - {OP_WR, TCM_REG_USEM_IFEN, 0x1}, - {OP_WR, TCM_REG_CSEM_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, TCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, TCM_REG_TCM_CFC_IFEN, 0x1}, -#define TCM_COMMON_END 159 -#define TCM_FUNC0_START 159 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0xd}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x7}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x7}, -#define TCM_FUNC0_END 163 -#define TCM_FUNC1_START 163 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x2d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x27}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x27}, -#define TCM_FUNC1_END 167 -#define TCM_FUNC2_START 167 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x1d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x17}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x17}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x17}, -#define TCM_FUNC2_END 171 -#define TCM_FUNC3_START 171 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x3d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x37}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x37}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x37}, -#define TCM_FUNC3_END 175 -#define TCM_FUNC4_START 175 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x4d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x47}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x47}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x47}, -#define TCM_FUNC4_END 179 -#define TCM_FUNC5_START 179 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x6d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x67}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x67}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x67}, -#define TCM_FUNC5_END 183 -#define TCM_FUNC6_START 183 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x5d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x57}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x57}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x57}, -#define TCM_FUNC6_END 187 -#define TCM_FUNC7_START 187 - {OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x7d}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x77}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x77}, - {OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x77}, -#define TCM_FUNC7_END 191 -#define BRB1_COMMON_START 191 - {OP_SW, BRB1_REG_LL_RAM, 0x2000020}, - {OP_WR, BRB1_REG_SOFT_RESET, 0x1}, - {OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_4, 0x0}, - {OP_SW, BRB1_REG_FREE_LIST_PRS_CRDT, 0x30220}, - {OP_WR, BRB1_REG_SOFT_RESET, 0x0}, -#define BRB1_COMMON_END 196 -#define BRB1_PORT0_START 196 - {OP_WR_E1, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0xb8}, - {OP_WR_E1, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 0x114}, - {OP_RD, BRB1_REG_NUM_OF_PAUSE_CYCLES_0, 0x0}, - {OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_0, 0x0}, -#define BRB1_PORT0_END 200 -#define BRB1_PORT1_START 200 - {OP_WR_E1, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0xb8}, - {OP_WR_E1, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 0x114}, - {OP_RD, BRB1_REG_NUM_OF_PAUSE_CYCLES_1, 0x0}, - {OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_1, 0x0}, -#define BRB1_PORT1_END 204 -#define TSEM_COMMON_START 204 - {OP_RD, TSEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, TSEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, TSEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, TSEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, TSEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, TSEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, TSEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, TSEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, TSEM_REG_TS_0_AS, 0x0}, - {OP_WR, TSEM_REG_TS_1_AS, 0x1}, - {OP_WR, TSEM_REG_TS_2_AS, 0x4}, - {OP_WR, TSEM_REG_TS_3_AS, 0x0}, - {OP_WR, TSEM_REG_TS_4_AS, 0x1}, - {OP_WR, TSEM_REG_TS_5_AS, 0x3}, - {OP_WR, TSEM_REG_TS_6_AS, 0x0}, - {OP_WR, TSEM_REG_TS_7_AS, 0x1}, - {OP_WR, TSEM_REG_TS_8_AS, 0x4}, - {OP_WR, TSEM_REG_TS_9_AS, 0x0}, - {OP_WR, TSEM_REG_TS_10_AS, 0x1}, - {OP_WR, TSEM_REG_TS_11_AS, 0x3}, - {OP_WR, TSEM_REG_TS_12_AS, 0x0}, - {OP_WR, TSEM_REG_TS_13_AS, 0x1}, - {OP_WR, TSEM_REG_TS_14_AS, 0x4}, - {OP_WR, TSEM_REG_TS_15_AS, 0x0}, - {OP_WR, TSEM_REG_TS_16_AS, 0x4}, - {OP_WR, TSEM_REG_TS_17_AS, 0x3}, - {OP_ZR, TSEM_REG_TS_18_AS, 0x2}, - {OP_WR, TSEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, TSEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, TSEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, TSEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, TSEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, TSEM_REG_THREADS_LIST, 0xff}, - {OP_ZR, TSEM_REG_PASSIVE_BUFFER, 0x400}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18000, 0x34}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18040, 0x18}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x18080, 0xc}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x180c0, 0x20}, - {OP_WR_ASIC, TSEM_REG_FAST_MEMORY + 0x18300, 0x7a120}, - {OP_WR_EMUL, TSEM_REG_FAST_MEMORY + 0x18300, 0x138}, - {OP_WR_FPGA, TSEM_REG_FAST_MEMORY + 0x18300, 0x1388}, - {OP_WR, TSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2000, 0xb2}, - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x23c8, 0xc1}, - {OP_WR_EMUL_E1H, TSEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x23c8 + 0x304, 0x10223}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x1000, 0x2b3}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x1000 + 0xacc, 0x10223}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xa020, 0xc8}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1c18, 0x4}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xa000, 0x2}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1c10, 0x2}, - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x1ad0, 0x0}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x800, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x1ad8, 0x4}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x808, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3678, 0x6}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x810, 0x4}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3670, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb0, 0x40224}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5000, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x4cb0, 0x80228}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5008, 0x4}, - {OP_ZP_E1, TSEM_REG_INT_TABLE, 0x930000}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5018, 0x4}, - {OP_WR_64_E1, TSEM_REG_INT_TABLE + 0x360, 0x140230}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5028, 0x4}, - {OP_ZP_E1, TSEM_REG_PRAM, 0x324f0000}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5038, 0x4}, - {OP_ZP_E1, TSEM_REG_PRAM + 0x8000, 0x33250c94}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5048, 0x4}, - {OP_ZP_E1, TSEM_REG_PRAM + 0x10000, 0xe4d195e}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5058, 0x4}, - {OP_WR_64_E1, TSEM_REG_PRAM + 0x11e00, 0x5c400232}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5068, 0x4}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5078, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4000, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4008, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x62c0, 0x200224}, - {OP_ZP_E1H, TSEM_REG_INT_TABLE, 0x9b0000}, - {OP_WR_64_E1H, TSEM_REG_INT_TABLE + 0x398, 0xd0244}, - {OP_ZP_E1H, TSEM_REG_PRAM, 0x325e0000}, - {OP_ZP_E1H, TSEM_REG_PRAM + 0x8000, 0x35960c98}, - {OP_ZP_E1H, TSEM_REG_PRAM + 0x10000, 0x1aea19fe}, - {OP_WR_64_E1H, TSEM_REG_PRAM + 0x143d0, 0x57860246}, -#define TSEM_COMMON_END 297 -#define TSEM_PORT0_START 297 - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x22c8, 0x20}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x2000, 0x16c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x4000, 0x16c}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb000, 0x28}, - {OP_WR_E1, TSEM_REG_FAST_MEMORY + 0x4b60, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb140, 0xc}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1400, 0xa}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x32c0, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1450, 0x6}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3350, 0x64}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1500, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x8108, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1500 + 0x8, 0x50234}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1500 + 0x1c, 0x7}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1570, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x9c0, 0x4c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x800, 0x2}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x820, 0xe}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb0, 0x20239}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2908, 0x2}, -#define TSEM_PORT0_END 317 -#define TSEM_PORT1_START 317 - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2348, 0x20}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x25b0, 0x16c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x45b0, 0x16c}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb0a0, 0x28}, - {OP_WR_E1, TSEM_REG_FAST_MEMORY + 0x4b64, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb170, 0xc}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1428, 0xa}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3308, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1468, 0x6}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x34e0, 0x64}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1538, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x8110, 0x2}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1538 + 0x8, 0x5023b}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1538 + 0x1c, 0x7}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x15b8, 0x12}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0xaf0, 0x4c}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x808, 0x2}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x858, 0xe}, - {OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb8, 0x20240}, - {OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2910, 0x2}, -#define TSEM_PORT1_END 337 -#define TSEM_FUNC0_START 337 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b60, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3000, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3000 + 0x8, 0x50248}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3000 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x31c0, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5000, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5080, 0x12}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4000, 0x2}, -#define TSEM_FUNC0_END 345 -#define TSEM_FUNC1_START 345 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b64, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3038, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3038 + 0x8, 0x5024d}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3038 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x31e0, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5010, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x50c8, 0x12}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4008, 0x2}, -#define TSEM_FUNC1_END 353 -#define TSEM_FUNC2_START 353 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b68, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3070, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3070 + 0x8, 0x50252}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3070 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3200, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5020, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5110, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4010, 0x20257}, -#define TSEM_FUNC2_END 361 -#define TSEM_FUNC3_START 361 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b6c, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30a8, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x30a8 + 0x8, 0x50259}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30a8 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3220, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5030, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5158, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4018, 0x2025e}, -#define TSEM_FUNC3_END 369 -#define TSEM_FUNC4_START 369 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b70, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30e0, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x30e0 + 0x8, 0x50260}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30e0 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3240, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5040, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x51a0, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4020, 0x20265}, -#define TSEM_FUNC4_END 377 -#define TSEM_FUNC5_START 377 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b74, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3118, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3118 + 0x8, 0x50267}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3118 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3260, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5050, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x51e8, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4028, 0x2026c}, -#define TSEM_FUNC5_END 385 -#define TSEM_FUNC6_START 385 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b78, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3150, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3150 + 0x8, 0x5026e}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3150 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3280, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5060, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5230, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4030, 0x20273}, -#define TSEM_FUNC6_END 393 -#define TSEM_FUNC7_START 393 - {OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b7c, 0x0}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3188, 0x2}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3188 + 0x8, 0x50275}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3188 + 0x1c, 0x7}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x32a0, 0x8}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5070, 0x2}, - {OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5278, 0x12}, - {OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4038, 0x2027a}, -#define TSEM_FUNC7_END 401 -#define MISC_COMMON_START 401 - {OP_WR_E1, MISC_REG_GRC_TIMEOUT_EN, 0x1}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_1, 0x71d2911}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_2, 0x0}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_3, 0x9c0424}, - {OP_WR, MISC_REG_PLL_STORM_CTRL_4, 0x0}, - {OP_WR, MISC_REG_LCPLL_CTRL_1, 0x209}, - {OP_WR_E1, MISC_REG_SPIO, 0xff000000}, -#define MISC_COMMON_END 408 -#define MISC_FUNC0_START 408 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC0_END 409 -#define MISC_FUNC1_START 409 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC1_END 410 -#define MISC_FUNC2_START 410 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC2_END 411 -#define MISC_FUNC3_START 411 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC3_END 412 -#define MISC_FUNC4_START 412 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC4_END 413 -#define MISC_FUNC5_START 413 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC5_END 414 -#define MISC_FUNC6_START 414 - {OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0}, -#define MISC_FUNC6_END 415 -#define MISC_FUNC7_START 415 - {OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0}, -#define MISC_FUNC7_END 416 -#define NIG_COMMON_START 416 - {OP_WR, NIG_REG_PBF_LB_IN_EN, 0x1}, - {OP_WR, NIG_REG_PRS_REQ_IN_EN, 0x1}, - {OP_WR, NIG_REG_EGRESS_DEBUG_IN_EN, 0x1}, - {OP_WR, NIG_REG_BRB_LB_OUT_EN, 0x1}, - {OP_WR, NIG_REG_PRS_EOP_OUT_EN, 0x1}, -#define NIG_COMMON_END 421 -#define NIG_PORT0_START 421 - {OP_WR, NIG_REG_LLH0_CM_HEADER, 0x300000}, - {OP_WR, NIG_REG_LLH0_EVENT_ID, 0x28}, - {OP_WR, NIG_REG_LLH0_ERROR_MASK, 0x0}, - {OP_WR, NIG_REG_LLH0_XCM_MASK, 0x4}, - {OP_WR, NIG_REG_LLH0_BRB1_NOT_MCP, 0x1}, - {OP_WR, NIG_REG_STATUS_INTERRUPT_PORT0, 0x0}, - {OP_WR_E1H, NIG_REG_LLH0_CLS_TYPE, 0x1}, - {OP_WR, NIG_REG_LLH0_XCM_INIT_CREDIT, 0x30}, - {OP_WR, NIG_REG_BRB0_PAUSE_IN_EN, 0x1}, - {OP_WR, NIG_REG_EGRESS_PBF0_IN_EN, 0x1}, - {OP_WR, NIG_REG_BRB0_OUT_EN, 0x1}, - {OP_WR, NIG_REG_XCM0_OUT_EN, 0x1}, -#define NIG_PORT0_END 433 -#define NIG_PORT1_START 433 - {OP_WR, NIG_REG_LLH1_CM_HEADER, 0x300000}, - {OP_WR, NIG_REG_LLH1_EVENT_ID, 0x28}, - {OP_WR, NIG_REG_LLH1_ERROR_MASK, 0x0}, - {OP_WR, NIG_REG_LLH1_XCM_MASK, 0x4}, - {OP_WR, NIG_REG_LLH1_BRB1_NOT_MCP, 0x1}, - {OP_WR, NIG_REG_STATUS_INTERRUPT_PORT1, 0x0}, - {OP_WR_E1H, NIG_REG_LLH1_CLS_TYPE, 0x1}, - {OP_WR, NIG_REG_LLH1_XCM_INIT_CREDIT, 0x30}, - {OP_WR, NIG_REG_BRB1_PAUSE_IN_EN, 0x1}, - {OP_WR, NIG_REG_EGRESS_PBF1_IN_EN, 0x1}, - {OP_WR, NIG_REG_BRB1_OUT_EN, 0x1}, - {OP_WR, NIG_REG_XCM1_OUT_EN, 0x1}, -#define NIG_PORT1_END 445 -#define UPB_COMMON_START 445 - {OP_WR, GRCBASE_UPB + PB_REG_CONTROL, 0x20}, -#define UPB_COMMON_END 446 -#define CSDM_COMMON_START 446 - {OP_WR_E1, CSDM_REG_CFC_RSP_START_ADDR, 0xa11}, - {OP_WR_E1H, CSDM_REG_CFC_RSP_START_ADDR, 0x211}, - {OP_WR_E1, CSDM_REG_CMP_COUNTER_START_ADDR, 0xa00}, - {OP_WR_E1H, CSDM_REG_CMP_COUNTER_START_ADDR, 0x200}, - {OP_WR_E1, CSDM_REG_Q_COUNTER_START_ADDR, 0xa04}, - {OP_WR_E1H, CSDM_REG_Q_COUNTER_START_ADDR, 0x204}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, CSDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_0, 0xc6}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_1, 0x0}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, CSDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_ZR, CSDM_REG_AGG_INT_EVENT_4, 0x1c}, - {OP_WR, CSDM_REG_AGG_INT_T_0, 0x1}, - {OP_ZR, CSDM_REG_AGG_INT_T_1, 0x5f}, - {OP_WR, CSDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, CSDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, CSDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, CSDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, CSDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, CSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, CSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, CSDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, CSDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, CSDM_REG_TIMER_TICK, 0xa}, -#define CSDM_COMMON_END 485 -#define USDM_COMMON_START 485 - {OP_WR_E1, USDM_REG_CFC_RSP_START_ADDR, 0xa11}, - {OP_WR_E1H, USDM_REG_CFC_RSP_START_ADDR, 0x411}, - {OP_WR_E1, USDM_REG_CMP_COUNTER_START_ADDR, 0xa00}, - {OP_WR_E1H, USDM_REG_CMP_COUNTER_START_ADDR, 0x400}, - {OP_WR_E1, USDM_REG_Q_COUNTER_START_ADDR, 0xa04}, - {OP_WR_E1H, USDM_REG_Q_COUNTER_START_ADDR, 0x404}, - {OP_WR_E1, USDM_REG_PCK_END_MSG_START_ADDR, 0xa21}, - {OP_WR_E1H, USDM_REG_PCK_END_MSG_START_ADDR, 0x421}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, USDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_WR, USDM_REG_AGG_INT_EVENT_0, 0x46}, - {OP_WR, USDM_REG_AGG_INT_EVENT_1, 0x5}, - {OP_WR, USDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, USDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_ZR_E1, USDM_REG_AGG_INT_EVENT_4, 0x5c}, - {OP_WR_E1H, USDM_REG_AGG_INT_EVENT_4, 0x7}, - {OP_ZR_E1H, USDM_REG_AGG_INT_EVENT_5, 0x5b}, - {OP_WR, USDM_REG_AGG_INT_MODE_0, 0x1}, - {OP_ZR_E1, USDM_REG_AGG_INT_MODE_1, 0x1f}, - {OP_ZR_E1H, USDM_REG_AGG_INT_MODE_1, 0x3}, - {OP_WR_E1H, USDM_REG_AGG_INT_MODE_4, 0x1}, - {OP_ZR_E1H, USDM_REG_AGG_INT_MODE_5, 0x1b}, - {OP_WR, USDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, USDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, USDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, USDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, USDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q2_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, USDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, USDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, USDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, USDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, USDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, USDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, USDM_REG_TIMER_TICK, 0xa}, -#define USDM_COMMON_END 532 -#define CCM_COMMON_START 532 - {OP_WR, CCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, CCM_REG_CQM_CCM_HDR_P, 0x2150020}, - {OP_WR, CCM_REG_CQM_CCM_HDR_S, 0x2150020}, - {OP_WR, CCM_REG_ERR_CCM_HDR, 0x8100000}, - {OP_WR, CCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, CCM_REG_STORM_WEIGHT, 0x2}, - {OP_WR, CCM_REG_TSEM_WEIGHT, 0x0}, - {OP_WR, CCM_REG_XSEM_WEIGHT, 0x5}, - {OP_WR, CCM_REG_USEM_WEIGHT, 0x5}, - {OP_ZR, CCM_REG_PBF_WEIGHT, 0x2}, - {OP_WR, CCM_REG_CSDM_WEIGHT, 0x2}, - {OP_WR, CCM_REG_CQM_P_WEIGHT, 0x3}, - {OP_WR, CCM_REG_CQM_S_WEIGHT, 0x2}, - {OP_WR, CCM_REG_CCM_CQM_USE_Q, 0x1}, - {OP_WR, CCM_REG_CNT_AUX1_Q, 0x2}, - {OP_WR, CCM_REG_CNT_AUX2_Q, 0x2}, - {OP_WR, CCM_REG_INV_DONE_Q, 0x1}, - {OP_WR, CCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, CCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, CCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, CCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, CCM_REG_CQM_INIT_CRD, 0x20}, - {OP_WR, CCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, CCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, CCM_REG_XX_INIT_CRD, 0x3}, - {OP_WR, CCM_REG_XX_MSG_NUM, 0x18}, - {OP_ZR, CCM_REG_XX_TABLE, 0x12}, - {OP_SW_E1, CCM_REG_XX_DESCR_TABLE, 0x240242}, - {OP_SW_E1H, CCM_REG_XX_DESCR_TABLE, 0x24027c}, - {OP_WR, CCM_REG_N_SM_CTX_LD_0, 0x1}, - {OP_WR, CCM_REG_N_SM_CTX_LD_1, 0x2}, - {OP_WR, CCM_REG_N_SM_CTX_LD_2, 0x8}, - {OP_WR, CCM_REG_N_SM_CTX_LD_3, 0x8}, - {OP_ZR, CCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR, CCM_REG_CCM_REG0_SZ, 0x4}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM0_0, 0x9}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM0_1, 0x29}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM1_0, 0xa}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM1_1, 0x2a}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM3_0, 0x7}, - {OP_WR_E1, CCM_REG_QOS_PHYS_QNUM3_1, 0x27}, - {OP_WR_E1, CCM_REG_PHYS_QNUM1_0, 0xc}, - {OP_WR_E1, CCM_REG_PHYS_QNUM1_1, 0x2c}, - {OP_WR_E1, CCM_REG_PHYS_QNUM2_0, 0xc}, - {OP_WR_E1, CCM_REG_PHYS_QNUM2_1, 0x2c}, - {OP_WR_E1, CCM_REG_PHYS_QNUM3_0, 0xc}, - {OP_WR_E1, CCM_REG_PHYS_QNUM3_1, 0x2c}, - {OP_WR, CCM_REG_CCM_STORM0_IFEN, 0x1}, - {OP_WR, CCM_REG_CCM_STORM1_IFEN, 0x1}, - {OP_WR, CCM_REG_CCM_CQM_IFEN, 0x1}, - {OP_WR, CCM_REG_STORM_CCM_IFEN, 0x1}, - {OP_WR, CCM_REG_CQM_CCM_IFEN, 0x1}, - {OP_WR, CCM_REG_CSDM_IFEN, 0x1}, - {OP_WR, CCM_REG_TSEM_IFEN, 0x1}, - {OP_WR, CCM_REG_XSEM_IFEN, 0x1}, - {OP_WR, CCM_REG_USEM_IFEN, 0x1}, - {OP_WR, CCM_REG_PBF_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, CCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, CCM_REG_CCM_CFC_IFEN, 0x1}, -#define CCM_COMMON_END 596 -#define CCM_FUNC0_START 596 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x9}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0xa}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x7}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x7}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0xc}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0xb}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x7}, -#define CCM_FUNC0_END 603 -#define CCM_FUNC1_START 603 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x29}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x2a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x27}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x27}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x2c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x2b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x27}, -#define CCM_FUNC1_END 610 -#define CCM_FUNC2_START 610 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x19}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x1a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x17}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x17}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x1c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x1b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x17}, -#define CCM_FUNC2_END 617 -#define CCM_FUNC3_START 617 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x39}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x3a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x37}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x37}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x3c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x3b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x37}, -#define CCM_FUNC3_END 624 -#define CCM_FUNC4_START 624 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x49}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x4a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x47}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x47}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x4c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x4b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x47}, -#define CCM_FUNC4_END 631 -#define CCM_FUNC5_START 631 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x69}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x6a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x67}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x67}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x6c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x6b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x67}, -#define CCM_FUNC5_END 638 -#define CCM_FUNC6_START 638 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x59}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x5a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x57}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x57}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x5c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x5b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x57}, -#define CCM_FUNC6_END 645 -#define CCM_FUNC7_START 645 - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x79}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x7a}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x77}, - {OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x77}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x7c}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x7b}, - {OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x77}, -#define CCM_FUNC7_END 652 -#define UCM_COMMON_START 652 - {OP_WR, UCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, UCM_REG_UQM_UCM_HDR_P, 0x2150020}, - {OP_WR, UCM_REG_UQM_UCM_HDR_S, 0x2150020}, - {OP_WR, UCM_REG_TM_UCM_HDR, 0x30}, - {OP_WR, UCM_REG_ERR_UCM_HDR, 0x8100000}, - {OP_WR, UCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, UCM_REG_EXPR_EVNT_ID, 0x30}, - {OP_WR, UCM_REG_STOP_EVNT_ID, 0x31}, - {OP_WR, UCM_REG_STORM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_TSEM_WEIGHT, 0x4}, - {OP_WR, UCM_REG_CSEM_WEIGHT, 0x0}, - {OP_WR, UCM_REG_XSEM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_DORQ_WEIGHT, 0x2}, - {OP_WR, UCM_REG_CP_WEIGHT, 0x0}, - {OP_WR, UCM_REG_USDM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_UQM_P_WEIGHT, 0x7}, - {OP_WR, UCM_REG_UQM_S_WEIGHT, 0x2}, - {OP_WR, UCM_REG_TM_WEIGHT, 0x2}, - {OP_WR, UCM_REG_UCM_UQM_USE_Q, 0x1}, - {OP_WR, UCM_REG_INV_CFLG_Q, 0x1}, - {OP_WR, UCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, UCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, UCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, UCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, UCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, UCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, UCM_REG_TM_INIT_CRD, 0x4}, - {OP_WR, UCM_REG_UQM_INIT_CRD, 0x20}, - {OP_WR, UCM_REG_XX_INIT_CRD, 0xe}, - {OP_WR, UCM_REG_XX_MSG_NUM, 0x1b}, - {OP_ZR, UCM_REG_XX_TABLE, 0x12}, - {OP_SW_E1, UCM_REG_XX_DESCR_TABLE, 0x1b0266}, - {OP_SW_E1H, UCM_REG_XX_DESCR_TABLE, 0x1b02a0}, - {OP_WR, UCM_REG_N_SM_CTX_LD_0, 0x10}, - {OP_WR, UCM_REG_N_SM_CTX_LD_1, 0x7}, - {OP_WR, UCM_REG_N_SM_CTX_LD_2, 0xf}, - {OP_WR, UCM_REG_N_SM_CTX_LD_3, 0x10}, - {OP_ZR_E1, UCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR_E1H, UCM_REG_N_SM_CTX_LD_4, 0xb}, - {OP_ZR_E1H, UCM_REG_N_SM_CTX_LD_5, 0x3}, - {OP_WR, UCM_REG_UCM_REG0_SZ, 0x3}, - {OP_WR_E1, UCM_REG_PHYS_QNUM0_0, 0xf}, - {OP_WR_E1, UCM_REG_PHYS_QNUM0_1, 0x2f}, - {OP_WR_E1, UCM_REG_PHYS_QNUM1_0, 0xe}, - {OP_WR_E1, UCM_REG_PHYS_QNUM1_1, 0x2e}, - {OP_WR, UCM_REG_UCM_STORM0_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_STORM1_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_UQM_IFEN, 0x1}, - {OP_WR, UCM_REG_STORM_UCM_IFEN, 0x1}, - {OP_WR, UCM_REG_UQM_UCM_IFEN, 0x1}, - {OP_WR, UCM_REG_USDM_IFEN, 0x1}, - {OP_WR, UCM_REG_TM_UCM_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_TM_IFEN, 0x1}, - {OP_WR, UCM_REG_TSEM_IFEN, 0x1}, - {OP_WR, UCM_REG_CSEM_IFEN, 0x1}, - {OP_WR, UCM_REG_XSEM_IFEN, 0x1}, - {OP_WR, UCM_REG_DORQ_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, UCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, UCM_REG_UCM_CFC_IFEN, 0x1}, -#define UCM_COMMON_END 714 -#define UCM_FUNC0_START 714 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0xf}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0xe}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC0_END 718 -#define UCM_FUNC1_START 718 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x2f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x2e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC1_END 722 -#define UCM_FUNC2_START 722 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x1f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x1e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC2_END 726 -#define UCM_FUNC3_START 726 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x3f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x3e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC3_END 730 -#define UCM_FUNC4_START 730 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x4f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x4e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC4_END 734 -#define UCM_FUNC5_START 734 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x6f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x6e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC5_END 738 -#define UCM_FUNC6_START 738 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x5f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x5e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0}, -#define UCM_FUNC6_END 742 -#define UCM_FUNC7_START 742 - {OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x7f}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x7e}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0}, - {OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0}, -#define UCM_FUNC7_END 746 -#define USEM_COMMON_START 746 - {OP_RD, USEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, USEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, USEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, USEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, USEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, USEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, USEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, USEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, USEM_REG_TS_0_AS, 0x0}, - {OP_WR, USEM_REG_TS_1_AS, 0x1}, - {OP_WR, USEM_REG_TS_2_AS, 0x4}, - {OP_WR, USEM_REG_TS_3_AS, 0x0}, - {OP_WR, USEM_REG_TS_4_AS, 0x1}, - {OP_WR, USEM_REG_TS_5_AS, 0x3}, - {OP_WR, USEM_REG_TS_6_AS, 0x0}, - {OP_WR, USEM_REG_TS_7_AS, 0x1}, - {OP_WR, USEM_REG_TS_8_AS, 0x4}, - {OP_WR, USEM_REG_TS_9_AS, 0x0}, - {OP_WR, USEM_REG_TS_10_AS, 0x1}, - {OP_WR, USEM_REG_TS_11_AS, 0x3}, - {OP_WR, USEM_REG_TS_12_AS, 0x0}, - {OP_WR, USEM_REG_TS_13_AS, 0x1}, - {OP_WR, USEM_REG_TS_14_AS, 0x4}, - {OP_WR, USEM_REG_TS_15_AS, 0x0}, - {OP_WR, USEM_REG_TS_16_AS, 0x4}, - {OP_WR, USEM_REG_TS_17_AS, 0x3}, - {OP_ZR, USEM_REG_TS_18_AS, 0x2}, - {OP_WR, USEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, USEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, USEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, USEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, USEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, USEM_REG_THREADS_LIST, 0xffff}, - {OP_ZR, USEM_REG_PASSIVE_BUFFER, 0x800}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18000, 0x1a}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18040, 0x4e}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x18080, 0x10}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x180c0, 0x20}, - {OP_WR_ASIC, USEM_REG_FAST_MEMORY + 0x18300, 0x7a120}, - {OP_WR_EMUL, USEM_REG_FAST_MEMORY + 0x18300, 0x138}, - {OP_WR_FPGA, USEM_REG_FAST_MEMORY + 0x18300, 0x1388}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_WR_ASIC, USEM_REG_FAST_MEMORY + 0x18380, 0x1dcd6500}, - {OP_WR_EMUL, USEM_REG_FAST_MEMORY + 0x18380, 0x4c4b4}, - {OP_WR_FPGA, USEM_REG_FAST_MEMORY + 0x18380, 0x4c4b40}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5000, 0xc2}, - {OP_WR_EMUL_E1H, USEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2000, 0x102}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4640, 0x40}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8980, 0xc8}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x57f0, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8960, 0x2}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x57d8, 0x5}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3228, 0x4}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x57d8 + 0x14, 0x10281}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3200, 0x9}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1c60, 0x20}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x3200 + 0x24, 0x102bb}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x2830, 0x20282}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3180, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x400}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000, 0x2}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0x8, 0x102bc}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0xc, 0x3}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b68, 0x2}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x6b68 + 0x8, 0x202bd}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b10, 0x2}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x74c0, 0x202bf}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x1000000}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c00, 0x100284}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c00, 0x1002c1}, - {OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x0}, - {OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c40, 0x100294}, - {OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c40, 0x1002d1}, - {OP_ZP_E1, USEM_REG_INT_TABLE, 0xc30000}, - {OP_ZP_E1H, USEM_REG_INT_TABLE, 0xd20000}, - {OP_WR_64_E1, USEM_REG_INT_TABLE + 0x368, 0x1302a4}, - {OP_WR_64_E1H, USEM_REG_INT_TABLE + 0x3a8, 0xb02e1}, - {OP_ZP_E1, USEM_REG_PRAM, 0x314c0000}, - {OP_ZP_E1H, USEM_REG_PRAM, 0x31b60000}, - {OP_ZP_E1, USEM_REG_PRAM + 0x8000, 0x35ef0c53}, - {OP_ZP_E1H, USEM_REG_PRAM + 0x8000, 0x36500c6e}, - {OP_ZP_E1, USEM_REG_PRAM + 0x10000, 0x361319cf}, - {OP_ZP_E1H, USEM_REG_PRAM + 0x10000, 0x37591a02}, - {OP_ZP_E1, USEM_REG_PRAM + 0x18000, 0x7112754}, - {OP_ZP_E1H, USEM_REG_PRAM + 0x18000, 0x286127d9}, - {OP_WR_64_E1, USEM_REG_PRAM + 0x18ee0, 0x4e2402a6}, - {OP_WR_64_E1H, USEM_REG_PRAM + 0x1ff40, 0x401802e3}, -#define USEM_COMMON_END 842 -#define USEM_PORT0_START 842 - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1400, 0xa0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9000, 0xa0}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1900, 0x10}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9500, 0x40}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1980, 0x30}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9700, 0x3c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4740, 0xb4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2450, 0xb4}, - {OP_WR_E1, USEM_REG_FAST_MEMORY + 0x1d90, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2ad0, 0x2}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b40, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3080, 0x20}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b60, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8000, 0x12c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5318, 0x98}, - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x3238, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5100, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5200, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5300, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5400, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5500, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5600, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5700, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5800, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5900, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f00, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b78, 0x52}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e08, 0xc}, -#define USEM_PORT0_END 876 -#define USEM_PORT1_START 876 - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1680, 0xa0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9280, 0xa0}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1940, 0x10}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9600, 0x40}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1a40, 0x30}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x97f0, 0x3c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4a10, 0xb4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2720, 0xb4}, - {OP_WR_E1, USEM_REG_FAST_MEMORY + 0x1d94, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2ad8, 0x2}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b50, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3100, 0x20}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1be0, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x84b0, 0x12c}, - {OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5578, 0x98}, - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x323c, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5080, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5180, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5280, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5380, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5480, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5580, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5680, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5780, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5880, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5980, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f80, 0x20}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6cc0, 0x52}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e38, 0xc}, -#define USEM_PORT1_END 910 -#define USEM_FUNC0_START 910 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a30, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3000, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4018, 0x2}, -#define USEM_FUNC0_END 913 -#define USEM_FUNC1_START 913 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a34, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3010, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4028, 0x2}, -#define USEM_FUNC1_END 916 -#define USEM_FUNC2_START 916 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a38, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3020, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4038, 0x2}, -#define USEM_FUNC2_END 919 -#define USEM_FUNC3_START 919 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a3c, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3030, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4048, 0x2}, -#define USEM_FUNC3_END 922 -#define USEM_FUNC4_START 922 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a40, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3040, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4058, 0x2}, -#define USEM_FUNC4_END 925 -#define USEM_FUNC5_START 925 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a44, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3050, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4068, 0x2}, -#define USEM_FUNC5_END 928 -#define USEM_FUNC6_START 928 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a48, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3060, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4078, 0x2}, -#define USEM_FUNC6_END 931 -#define USEM_FUNC7_START 931 - {OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a4c, 0x0}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3070, 0x4}, - {OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4088, 0x2}, -#define USEM_FUNC7_END 934 -#define CSEM_COMMON_START 934 - {OP_RD, CSEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, CSEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, CSEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, CSEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, CSEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, CSEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, CSEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, CSEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, CSEM_REG_TS_0_AS, 0x0}, - {OP_WR, CSEM_REG_TS_1_AS, 0x1}, - {OP_WR, CSEM_REG_TS_2_AS, 0x4}, - {OP_WR, CSEM_REG_TS_3_AS, 0x0}, - {OP_WR, CSEM_REG_TS_4_AS, 0x1}, - {OP_WR, CSEM_REG_TS_5_AS, 0x3}, - {OP_WR, CSEM_REG_TS_6_AS, 0x0}, - {OP_WR, CSEM_REG_TS_7_AS, 0x1}, - {OP_WR, CSEM_REG_TS_8_AS, 0x4}, - {OP_WR, CSEM_REG_TS_9_AS, 0x0}, - {OP_WR, CSEM_REG_TS_10_AS, 0x1}, - {OP_WR, CSEM_REG_TS_11_AS, 0x3}, - {OP_WR, CSEM_REG_TS_12_AS, 0x0}, - {OP_WR, CSEM_REG_TS_13_AS, 0x1}, - {OP_WR, CSEM_REG_TS_14_AS, 0x4}, - {OP_WR, CSEM_REG_TS_15_AS, 0x0}, - {OP_WR, CSEM_REG_TS_16_AS, 0x4}, - {OP_WR, CSEM_REG_TS_17_AS, 0x3}, - {OP_ZR, CSEM_REG_TS_18_AS, 0x2}, - {OP_WR, CSEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, CSEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, CSEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, CSEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, CSEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, CSEM_REG_THREADS_LIST, 0xffff}, - {OP_ZR, CSEM_REG_PASSIVE_BUFFER, 0x800}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18000, 0x10}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18040, 0x12}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x18080, 0x30}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x180c0, 0xe}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x5000, 0x42}, - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_WR_EMUL_E1H, CSEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x1000, 0x42}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2000, 0xc0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x7020, 0xc8}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3070, 0x80}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x7000, 0x2}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x4280, 0x4}, - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11e8, 0x0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x25c0, 0x240}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3000, 0xc0}, - {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x2ec8, 0x802a8}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4070, 0x80}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x5280, 0x4}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6700, 0x100}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x9000, 0x400}, - {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x6b08, 0x2002e5}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x13fffff}, - {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c00, 0x1002b0}, - {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c00, 0x100305}, - {OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x0}, - {OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c40, 0x1002c0}, - {OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c40, 0x100315}, - {OP_ZP_E1, CSEM_REG_INT_TABLE, 0x710000}, - {OP_ZP_E1H, CSEM_REG_INT_TABLE, 0x740000}, - {OP_WR_64_E1, CSEM_REG_INT_TABLE + 0x380, 0x1002d0}, - {OP_WR_64_E1H, CSEM_REG_INT_TABLE + 0x380, 0x100325}, - {OP_ZP_E1, CSEM_REG_PRAM, 0x32290000}, - {OP_ZP_E1H, CSEM_REG_PRAM, 0x32260000}, - {OP_ZP_E1, CSEM_REG_PRAM + 0x8000, 0x23630c8b}, - {OP_ZP_E1H, CSEM_REG_PRAM + 0x8000, 0x246e0c8a}, - {OP_WR_64_E1, CSEM_REG_PRAM + 0xc930, 0x654002d2}, - {OP_WR_64_E1H, CSEM_REG_PRAM + 0xcbb0, 0x64f00327}, -#define CSEM_COMMON_END 1014 -#define CSEM_PORT0_START 1014 - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1400, 0xa0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8000, 0xa0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1900, 0x10}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8500, 0x40}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1980, 0x30}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8700, 0x3c}, - {OP_WR_E1, CSEM_REG_FAST_MEMORY + 0x5118, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4040, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2300, 0xe}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3040, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2410, 0x30}, -#define CSEM_PORT0_END 1025 -#define CSEM_PORT1_START 1025 - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1680, 0xa0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8280, 0xa0}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1940, 0x10}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8600, 0x40}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1a40, 0x30}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x87f0, 0x3c}, - {OP_WR_E1, CSEM_REG_FAST_MEMORY + 0x511c, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4058, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2338, 0xe}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3058, 0x6}, - {OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x24d0, 0x30}, -#define CSEM_PORT1_END 1036 -#define CSEM_FUNC0_START 1036 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1148, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3300, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6040, 0x30}, -#define CSEM_FUNC0_END 1039 -#define CSEM_FUNC1_START 1039 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x114c, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3308, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6100, 0x30}, -#define CSEM_FUNC1_END 1042 -#define CSEM_FUNC2_START 1042 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1150, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3310, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x61c0, 0x30}, -#define CSEM_FUNC2_END 1045 -#define CSEM_FUNC3_START 1045 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1154, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3318, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6280, 0x30}, -#define CSEM_FUNC3_END 1048 -#define CSEM_FUNC4_START 1048 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1158, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3320, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6340, 0x30}, -#define CSEM_FUNC4_END 1051 -#define CSEM_FUNC5_START 1051 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x115c, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3328, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6400, 0x30}, -#define CSEM_FUNC5_END 1054 -#define CSEM_FUNC6_START 1054 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1160, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3330, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x64c0, 0x30}, -#define CSEM_FUNC6_END 1057 -#define CSEM_FUNC7_START 1057 - {OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1164, 0x0}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3338, 0x2}, - {OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6580, 0x30}, -#define CSEM_FUNC7_END 1060 -#define XPB_COMMON_START 1060 - {OP_WR, GRCBASE_XPB + PB_REG_CONTROL, 0x20}, -#define XPB_COMMON_END 1061 -#define DQ_COMMON_START 1061 - {OP_WR, DORQ_REG_MODE_ACT, 0x2}, - {OP_WR, DORQ_REG_NORM_CID_OFST, 0x3}, - {OP_WR, DORQ_REG_OUTST_REQ, 0x4}, - {OP_WR, DORQ_REG_DPM_CID_ADDR, 0x8}, - {OP_WR, DORQ_REG_RSP_INIT_CRD, 0x2}, - {OP_WR, DORQ_REG_NORM_CMHEAD_TX, 0x90}, - {OP_WR, DORQ_REG_CMHEAD_RX, 0x90}, - {OP_WR, DORQ_REG_SHRT_CMHEAD, 0x800090}, - {OP_WR, DORQ_REG_ERR_CMHEAD, 0x8140000}, - {OP_WR, DORQ_REG_AGG_CMD0, 0x8a}, - {OP_WR, DORQ_REG_AGG_CMD1, 0x80}, - {OP_WR, DORQ_REG_AGG_CMD2, 0x90}, - {OP_WR, DORQ_REG_AGG_CMD3, 0x80}, - {OP_WR, DORQ_REG_SHRT_ACT_CNT, 0x6}, - {OP_WR, DORQ_REG_DQ_FIFO_FULL_TH, 0x7d0}, - {OP_WR, DORQ_REG_DQ_FIFO_AFULL_TH, 0x76c}, - {OP_WR, DORQ_REG_REGN, 0x7c1004}, - {OP_WR, DORQ_REG_IF_EN, 0xf}, -#define DQ_COMMON_END 1079 -#define TIMERS_COMMON_START 1079 - {OP_ZR, TM_REG_CLIN_PRIOR0_CLIENT, 0x2}, - {OP_WR, TM_REG_LIN_SETCLR_FIFO_ALFULL_THR, 0x1c}, - {OP_WR, TM_REG_CFC_AC_CRDCNT_VAL, 0x1}, - {OP_WR, TM_REG_CFC_CLD_CRDCNT_VAL, 0x1}, - {OP_WR, TM_REG_CLOUT_CRDCNT0_VAL, 0x1}, - {OP_WR, TM_REG_CLOUT_CRDCNT1_VAL, 0x1}, - {OP_WR, TM_REG_CLOUT_CRDCNT2_VAL, 0x1}, - {OP_WR, TM_REG_EXP_CRDCNT_VAL, 0x1}, - {OP_WR_E1, TM_REG_PCIARB_CRDCNT_VAL, 0x1}, - {OP_WR_E1H, TM_REG_PCIARB_CRDCNT_VAL, 0x2}, - {OP_WR_ASIC, TM_REG_TIMER_TICK_SIZE, 0x3d090}, - {OP_WR_EMUL, TM_REG_TIMER_TICK_SIZE, 0x9c}, - {OP_WR_FPGA, TM_REG_TIMER_TICK_SIZE, 0x9c4}, - {OP_WR, TM_REG_CL0_CONT_REGION, 0x8}, - {OP_WR, TM_REG_CL1_CONT_REGION, 0xc}, - {OP_WR, TM_REG_CL2_CONT_REGION, 0x10}, - {OP_WR, TM_REG_TM_CONTEXT_REGION, 0x20}, - {OP_WR, TM_REG_EN_TIMERS, 0x1}, - {OP_WR, TM_REG_EN_REAL_TIME_CNT, 0x1}, - {OP_WR, TM_REG_EN_CL0_INPUT, 0x1}, - {OP_WR, TM_REG_EN_CL1_INPUT, 0x1}, - {OP_WR, TM_REG_EN_CL2_INPUT, 0x1}, -#define TIMERS_COMMON_END 1101 -#define TIMERS_PORT0_START 1101 - {OP_WR, TM_REG_LIN0_LOGIC_ADDR, 0x0}, - {OP_WR, TM_REG_LIN0_PHY_ADDR_VALID, 0x0}, - {OP_ZR, TM_REG_LIN0_PHY_ADDR, 0x2}, -#define TIMERS_PORT0_END 1104 -#define TIMERS_PORT1_START 1104 - {OP_WR, TM_REG_LIN1_LOGIC_ADDR, 0x0}, - {OP_WR, TM_REG_LIN1_PHY_ADDR_VALID, 0x0}, - {OP_ZR, TM_REG_LIN1_PHY_ADDR, 0x2}, -#define TIMERS_PORT1_END 1107 -#define XSDM_COMMON_START 1107 - {OP_WR_E1, XSDM_REG_CFC_RSP_START_ADDR, 0x614}, - {OP_WR_E1H, XSDM_REG_CFC_RSP_START_ADDR, 0x424}, - {OP_WR_E1, XSDM_REG_CMP_COUNTER_START_ADDR, 0x600}, - {OP_WR_E1H, XSDM_REG_CMP_COUNTER_START_ADDR, 0x410}, - {OP_WR_E1, XSDM_REG_Q_COUNTER_START_ADDR, 0x604}, - {OP_WR_E1H, XSDM_REG_Q_COUNTER_START_ADDR, 0x414}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX0, 0xffff}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX1, 0xffff}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX2, 0xffff}, - {OP_WR, XSDM_REG_CMP_COUNTER_MAX3, 0xffff}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_0, 0x20}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_1, 0x20}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_2, 0x34}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_3, 0x35}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_4, 0x23}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_5, 0x24}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_6, 0x25}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_7, 0x26}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_8, 0x27}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_9, 0x29}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_10, 0x2a}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_11, 0x2b}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_12, 0x2c}, - {OP_WR, XSDM_REG_AGG_INT_EVENT_13, 0x2d}, - {OP_ZR, XSDM_REG_AGG_INT_EVENT_14, 0x52}, - {OP_WR, XSDM_REG_AGG_INT_MODE_0, 0x1}, - {OP_ZR, XSDM_REG_AGG_INT_MODE_1, 0x1f}, - {OP_WR, XSDM_REG_ENABLE_IN1, 0x7ffffff}, - {OP_WR, XSDM_REG_ENABLE_IN2, 0x3f}, - {OP_WR, XSDM_REG_ENABLE_OUT1, 0x7ffffff}, - {OP_WR, XSDM_REG_ENABLE_OUT2, 0xf}, - {OP_RD, XSDM_REG_NUM_OF_Q0_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q1_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q3_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q4_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q5_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q6_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q7_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q8_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q9_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q10_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_Q11_CMD, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_PKT_END_MSG, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0}, - {OP_RD, XSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0}, - {OP_WR_E1, XSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1}, - {OP_WR_ASIC, XSDM_REG_TIMER_TICK, 0x3e8}, - {OP_WR_EMUL, XSDM_REG_TIMER_TICK, 0x1}, - {OP_WR_FPGA, XSDM_REG_TIMER_TICK, 0xa}, -#define XSDM_COMMON_END 1156 -#define QM_COMMON_START 1156 - {OP_WR, QM_REG_ACTCTRINITVAL_0, 0x6}, - {OP_WR, QM_REG_ACTCTRINITVAL_1, 0x5}, - {OP_WR, QM_REG_ACTCTRINITVAL_2, 0xa}, - {OP_WR, QM_REG_ACTCTRINITVAL_3, 0x5}, - {OP_WR, QM_REG_PCIREQAT, 0x2}, - {OP_WR, QM_REG_CMINITCRD_0, 0x4}, - {OP_WR, QM_REG_CMINITCRD_1, 0x4}, - {OP_WR, QM_REG_CMINITCRD_2, 0x4}, - {OP_WR, QM_REG_CMINITCRD_3, 0x4}, - {OP_WR, QM_REG_CMINITCRD_4, 0x4}, - {OP_WR, QM_REG_CMINITCRD_5, 0x4}, - {OP_WR, QM_REG_CMINITCRD_6, 0x4}, - {OP_WR, QM_REG_CMINITCRD_7, 0x4}, - {OP_WR, QM_REG_OUTLDREQ, 0x4}, - {OP_WR, QM_REG_CTXREG_0, 0x7c}, - {OP_WR, QM_REG_CTXREG_1, 0x3d}, - {OP_WR, QM_REG_CTXREG_2, 0x3f}, - {OP_WR, QM_REG_CTXREG_3, 0x9c}, - {OP_WR, QM_REG_ENSEC, 0x7}, - {OP_ZR, QM_REG_QVOQIDX_0, 0x5}, - {OP_WR, QM_REG_WRRWEIGHTS_0, 0x1010101}, - {OP_WR, QM_REG_QVOQIDX_5, 0x0}, - {OP_WR, QM_REG_QVOQIDX_6, 0x4}, - {OP_WR, QM_REG_QVOQIDX_7, 0x4}, - {OP_WR, QM_REG_QVOQIDX_8, 0x2}, - {OP_WR, QM_REG_WRRWEIGHTS_1, 0x8012004}, - {OP_WR, QM_REG_QVOQIDX_9, 0x5}, - {OP_WR, QM_REG_QVOQIDX_10, 0x5}, - {OP_WR, QM_REG_QVOQIDX_11, 0x5}, - {OP_WR, QM_REG_QVOQIDX_12, 0x5}, - {OP_WR, QM_REG_WRRWEIGHTS_2, 0x20081001}, - {OP_WR, QM_REG_QVOQIDX_13, 0x8}, - {OP_WR, QM_REG_QVOQIDX_14, 0x6}, - {OP_WR, QM_REG_QVOQIDX_15, 0x7}, - {OP_WR, QM_REG_QVOQIDX_16, 0x0}, - {OP_WR, QM_REG_WRRWEIGHTS_3, 0x1010120}, - {OP_ZR, QM_REG_QVOQIDX_17, 0x4}, - {OP_WR, QM_REG_WRRWEIGHTS_4, 0x1010101}, - {OP_ZR_E1, QM_REG_QVOQIDX_21, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_21, 0x0}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_5, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_22, 0x4}, - {OP_ZR_E1, QM_REG_QVOQIDX_25, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_23, 0x4}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_6, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_24, 0x2}, - {OP_ZR_E1, QM_REG_QVOQIDX_29, 0x3}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_5, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_25, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_26, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_27, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_28, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_6, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_29, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_30, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_31, 0x7}, - {OP_WR, QM_REG_QVOQIDX_32, 0x1}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_7, 0x1010101}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_7, 0x1010120}, - {OP_WR, QM_REG_QVOQIDX_33, 0x1}, - {OP_WR, QM_REG_QVOQIDX_34, 0x1}, - {OP_WR, QM_REG_QVOQIDX_35, 0x1}, - {OP_WR, QM_REG_QVOQIDX_36, 0x1}, - {OP_WR, QM_REG_WRRWEIGHTS_8, 0x1010101}, - {OP_WR, QM_REG_QVOQIDX_37, 0x1}, - {OP_WR, QM_REG_QVOQIDX_38, 0x4}, - {OP_WR, QM_REG_QVOQIDX_39, 0x4}, - {OP_WR, QM_REG_QVOQIDX_40, 0x2}, - {OP_WR, QM_REG_WRRWEIGHTS_9, 0x8012004}, - {OP_WR, QM_REG_QVOQIDX_41, 0x5}, - {OP_WR, QM_REG_QVOQIDX_42, 0x5}, - {OP_WR, QM_REG_QVOQIDX_43, 0x5}, - {OP_WR, QM_REG_QVOQIDX_44, 0x5}, - {OP_WR, QM_REG_WRRWEIGHTS_10, 0x20081001}, - {OP_WR, QM_REG_QVOQIDX_45, 0x8}, - {OP_WR, QM_REG_QVOQIDX_46, 0x6}, - {OP_WR, QM_REG_QVOQIDX_47, 0x7}, - {OP_WR, QM_REG_QVOQIDX_48, 0x1}, - {OP_WR, QM_REG_WRRWEIGHTS_11, 0x1010120}, - {OP_WR, QM_REG_QVOQIDX_49, 0x1}, - {OP_WR, QM_REG_QVOQIDX_50, 0x1}, - {OP_WR, QM_REG_QVOQIDX_51, 0x1}, - {OP_WR, QM_REG_QVOQIDX_52, 0x1}, - {OP_WR, QM_REG_WRRWEIGHTS_12, 0x1010101}, - {OP_WR, QM_REG_QVOQIDX_53, 0x1}, - {OP_WR_E1, QM_REG_QVOQIDX_54, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_54, 0x4}, - {OP_WR_E1, QM_REG_QVOQIDX_55, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_55, 0x4}, - {OP_WR_E1, QM_REG_QVOQIDX_56, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_56, 0x2}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_13, 0x1010101}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_13, 0x8012004}, - {OP_WR_E1, QM_REG_QVOQIDX_57, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_57, 0x5}, - {OP_WR_E1, QM_REG_QVOQIDX_58, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_58, 0x5}, - {OP_WR_E1, QM_REG_QVOQIDX_59, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_59, 0x5}, - {OP_WR_E1, QM_REG_QVOQIDX_60, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_60, 0x5}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_14, 0x1010101}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_14, 0x20081001}, - {OP_WR_E1, QM_REG_QVOQIDX_61, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_61, 0x8}, - {OP_WR_E1, QM_REG_QVOQIDX_62, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_62, 0x6}, - {OP_WR_E1, QM_REG_QVOQIDX_63, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_63, 0x7}, - {OP_WR_E1, QM_REG_WRRWEIGHTS_15, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_64, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_0_LSB, 0xffff003f}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_15, 0x1010120}, - {OP_ZR_E1, QM_REG_VOQQMASK_0_MSB, 0x2}, - {OP_ZR_E1H, QM_REG_QVOQIDX_65, 0x4}, - {OP_WR_E1, QM_REG_VOQQMASK_1_MSB, 0xffff003f}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_16, 0x1010101}, - {OP_WR_E1, QM_REG_VOQQMASK_2_LSB, 0x100}, - {OP_WR_E1H, QM_REG_QVOQIDX_69, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_2_MSB, 0x100}, - {OP_WR_E1H, QM_REG_QVOQIDX_70, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_71, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_72, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_17, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_73, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_74, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_75, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_76, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_18, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_77, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_78, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_79, 0x7}, - {OP_WR_E1H, QM_REG_QVOQIDX_80, 0x0}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_19, 0x1010120}, - {OP_ZR_E1H, QM_REG_QVOQIDX_81, 0x4}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_20, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_85, 0x0}, - {OP_WR_E1H, QM_REG_QVOQIDX_86, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_87, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_88, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_21, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_89, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_90, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_91, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_92, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_22, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_93, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_94, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_95, 0x7}, - {OP_WR_E1H, QM_REG_QVOQIDX_96, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_23, 0x1010120}, - {OP_WR_E1H, QM_REG_QVOQIDX_97, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_98, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_99, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_100, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_24, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_101, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_102, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_103, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_104, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_25, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_105, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_106, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_107, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_108, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_26, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_109, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_110, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_111, 0x7}, - {OP_WR_E1H, QM_REG_QVOQIDX_112, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_27, 0x1010120}, - {OP_WR_E1H, QM_REG_QVOQIDX_113, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_114, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_115, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_116, 0x1}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_28, 0x1010101}, - {OP_WR_E1H, QM_REG_QVOQIDX_117, 0x1}, - {OP_WR_E1H, QM_REG_QVOQIDX_118, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_119, 0x4}, - {OP_WR_E1H, QM_REG_QVOQIDX_120, 0x2}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_29, 0x8012004}, - {OP_WR_E1H, QM_REG_QVOQIDX_121, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_122, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_123, 0x5}, - {OP_WR_E1H, QM_REG_QVOQIDX_124, 0x5}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_30, 0x20081001}, - {OP_WR_E1H, QM_REG_QVOQIDX_125, 0x8}, - {OP_WR_E1H, QM_REG_QVOQIDX_126, 0x6}, - {OP_WR_E1H, QM_REG_QVOQIDX_127, 0x7}, - {OP_WR_E1H, QM_REG_WRRWEIGHTS_31, 0x1010120}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_LSB, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_MSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_LSB_EXT_A, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_0_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_LSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_MSB, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_1_MSB_EXT_A, 0x3f003f}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_LSB, 0x1000100}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_MSB, 0x1000100}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_LSB_EXT_A, 0x1000100}, - {OP_WR_E1H, QM_REG_VOQQMASK_2_MSB_EXT_A, 0x1000100}, - {OP_ZR, QM_REG_VOQQMASK_3_LSB, 0x2}, - {OP_WR_E1, QM_REG_VOQQMASK_4_LSB, 0xc0}, - {OP_WR_E1H, QM_REG_VOQQMASK_3_LSB_EXT_A, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_4_MSB, 0xc0}, - {OP_WR_E1H, QM_REG_VOQQMASK_3_MSB_EXT_A, 0x0}, - {OP_WR_E1, QM_REG_VOQQMASK_5_LSB, 0x1e00}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_LSB, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_5_MSB, 0x1e00}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_MSB, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_6_LSB, 0x4000}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_LSB_EXT_A, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_6_MSB, 0x4000}, - {OP_WR_E1H, QM_REG_VOQQMASK_4_MSB_EXT_A, 0xc000c0}, - {OP_WR_E1, QM_REG_VOQQMASK_7_LSB, 0x8000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_LSB, 0x1e001e00}, - {OP_WR_E1, QM_REG_VOQQMASK_7_MSB, 0x8000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_MSB, 0x1e001e00}, - {OP_WR_E1, QM_REG_VOQQMASK_8_LSB, 0x2000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_LSB_EXT_A, 0x1e001e00}, - {OP_WR_E1, QM_REG_VOQQMASK_8_MSB, 0x2000}, - {OP_WR_E1H, QM_REG_VOQQMASK_5_MSB_EXT_A, 0x1e001e00}, - {OP_ZR_E1, QM_REG_VOQQMASK_9_LSB, 0x7}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_LSB, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_MSB, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_LSB_EXT_A, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_6_MSB_EXT_A, 0x40004000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_LSB, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_MSB, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_LSB_EXT_A, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_7_MSB_EXT_A, 0x80008000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_LSB, 0x20002000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_MSB, 0x20002000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_LSB_EXT_A, 0x20002000}, - {OP_WR_E1H, QM_REG_VOQQMASK_8_MSB_EXT_A, 0x20002000}, - {OP_ZR_E1H, QM_REG_VOQQMASK_9_LSB, 0x2}, - {OP_WR_E1H, QM_REG_VOQQMASK_9_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_9_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_LSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_MSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_10_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_LSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_MSB, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_LSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQQMASK_11_MSB_EXT_A, 0x0}, - {OP_WR_E1H, QM_REG_VOQPORT_0, 0x0}, - {OP_WR, QM_REG_VOQPORT_1, 0x1}, - {OP_ZR, QM_REG_VOQPORT_2, 0xa}, - {OP_WR, QM_REG_CMINTVOQMASK_0, 0xc08}, - {OP_WR, QM_REG_CMINTVOQMASK_1, 0x40}, - {OP_WR, QM_REG_CMINTVOQMASK_2, 0x100}, - {OP_WR, QM_REG_CMINTVOQMASK_3, 0x20}, - {OP_WR, QM_REG_CMINTVOQMASK_4, 0x17}, - {OP_WR, QM_REG_CMINTVOQMASK_5, 0x80}, - {OP_WR, QM_REG_CMINTVOQMASK_6, 0x200}, - {OP_WR, QM_REG_CMINTVOQMASK_7, 0x0}, - {OP_WR_E1, QM_REG_HWAEMPTYMASK_LSB, 0xffff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_LSB, 0x1ff01ff}, - {OP_WR_E1, QM_REG_HWAEMPTYMASK_MSB, 0xffff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_MSB, 0x1ff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_LSB_EXT_A, 0x1ff01ff}, - {OP_WR_E1H, QM_REG_HWAEMPTYMASK_MSB_EXT_A, 0x1ff01ff}, - {OP_WR, QM_REG_ENBYPVOQMASK, 0x13}, - {OP_WR, QM_REG_VOQCREDITAFULLTHR, 0x13f}, - {OP_WR, QM_REG_VOQINITCREDIT_0, 0x140}, - {OP_WR, QM_REG_VOQINITCREDIT_1, 0x140}, - {OP_ZR, QM_REG_VOQINITCREDIT_2, 0x2}, - {OP_WR, QM_REG_VOQINITCREDIT_4, 0xc0}, - {OP_ZR, QM_REG_VOQINITCREDIT_5, 0x7}, - {OP_WR, QM_REG_TASKCRDCOST_0, 0x48}, - {OP_WR, QM_REG_TASKCRDCOST_1, 0x48}, - {OP_ZR, QM_REG_TASKCRDCOST_2, 0x2}, - {OP_WR, QM_REG_TASKCRDCOST_4, 0x48}, - {OP_ZR, QM_REG_TASKCRDCOST_5, 0x7}, - {OP_WR, QM_REG_BYTECRDINITVAL, 0x8000}, - {OP_WR, QM_REG_BYTECRDCOST, 0x25e4}, - {OP_WR, QM_REG_BYTECREDITAFULLTHR, 0x7fff}, - {OP_WR_E1, QM_REG_ENBYTECRD_LSB, 0x7}, - {OP_WR_E1H, QM_REG_ENBYTECRD_LSB, 0x70007}, - {OP_WR_E1, QM_REG_ENBYTECRD_MSB, 0x7}, - {OP_WR_E1H, QM_REG_ENBYTECRD_MSB, 0x70007}, - {OP_WR_E1H, QM_REG_ENBYTECRD_LSB_EXT_A, 0x70007}, - {OP_WR_E1H, QM_REG_ENBYTECRD_MSB_EXT_A, 0x70007}, - {OP_WR, QM_REG_BYTECRDPORT_LSB, 0x0}, - {OP_WR, QM_REG_BYTECRDPORT_MSB, 0xffffffff}, - {OP_WR_E1, QM_REG_FUNCNUMSEL_LSB, 0x0}, - {OP_WR_E1H, QM_REG_BYTECRDPORT_LSB_EXT_A, 0x0}, - {OP_WR_E1, QM_REG_FUNCNUMSEL_MSB, 0xffffffff}, - {OP_WR_E1H, QM_REG_BYTECRDPORT_MSB_EXT_A, 0xffffffff}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_0, 0x0}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_1, 0x2}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_2, 0x1}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_3, 0x3}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_4, 0x4}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_5, 0x6}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_6, 0x5}, - {OP_WR_E1H, QM_REG_PQ2PCIFUNC_7, 0x7}, - {OP_WR, QM_REG_CMINTEN, 0xff}, -#define QM_COMMON_END 1456 -#define PBF_COMMON_START 1456 - {OP_WR, PBF_REG_INIT, 0x1}, - {OP_WR, PBF_REG_INIT_P4, 0x1}, - {OP_WR, PBF_REG_MAC_LB_ENABLE, 0x1}, - {OP_WR, PBF_REG_IF_ENABLE_REG, 0x7fff}, - {OP_WR, PBF_REG_INIT_P4, 0x0}, - {OP_WR, PBF_REG_INIT, 0x0}, - {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P4, 0x0}, -#define PBF_COMMON_END 1463 -#define PBF_PORT0_START 1463 - {OP_WR, PBF_REG_INIT_P0, 0x1}, - {OP_WR, PBF_REG_MAC_IF0_ENABLE, 0x1}, - {OP_WR, PBF_REG_INIT_P0, 0x0}, - {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P0, 0x0}, -#define PBF_PORT0_END 1467 -#define PBF_PORT1_START 1467 - {OP_WR, PBF_REG_INIT_P1, 0x1}, - {OP_WR, PBF_REG_MAC_IF1_ENABLE, 0x1}, - {OP_WR, PBF_REG_INIT_P1, 0x0}, - {OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P1, 0x0}, -#define PBF_PORT1_END 1471 -#define XCM_COMMON_START 1471 - {OP_WR, XCM_REG_XX_OVFL_EVNT_ID, 0x32}, - {OP_WR, XCM_REG_XQM_XCM_HDR_P, 0x3150020}, - {OP_WR, XCM_REG_XQM_XCM_HDR_S, 0x3150020}, - {OP_WR, XCM_REG_TM_XCM_HDR, 0x1000030}, - {OP_WR, XCM_REG_ERR_XCM_HDR, 0x8100000}, - {OP_WR, XCM_REG_ERR_EVNT_ID, 0x33}, - {OP_WR, XCM_REG_EXPR_EVNT_ID, 0x30}, - {OP_WR, XCM_REG_STOP_EVNT_ID, 0x31}, - {OP_WR, XCM_REG_STORM_WEIGHT, 0x3}, - {OP_WR, XCM_REG_TSEM_WEIGHT, 0x6}, - {OP_WR, XCM_REG_CSEM_WEIGHT, 0x3}, - {OP_WR, XCM_REG_USEM_WEIGHT, 0x3}, - {OP_WR, XCM_REG_DORQ_WEIGHT, 0x2}, - {OP_WR, XCM_REG_PBF_WEIGHT, 0x0}, - {OP_WR, XCM_REG_NIG0_WEIGHT, 0x2}, - {OP_WR, XCM_REG_CP_WEIGHT, 0x0}, - {OP_WR, XCM_REG_XSDM_WEIGHT, 0x6}, - {OP_WR, XCM_REG_XQM_P_WEIGHT, 0x4}, - {OP_WR, XCM_REG_XQM_S_WEIGHT, 0x2}, - {OP_WR, XCM_REG_TM_WEIGHT, 0x2}, - {OP_WR, XCM_REG_XCM_XQM_USE_Q, 0x1}, - {OP_WR, XCM_REG_XQM_BYP_ACT_UPD, 0x6}, - {OP_WR, XCM_REG_UNA_GT_NXT_Q, 0x0}, - {OP_WR, XCM_REG_AUX1_Q, 0x2}, - {OP_WR, XCM_REG_AUX_CNT_FLG_Q_19, 0x1}, - {OP_WR, XCM_REG_GR_ARB_TYPE, 0x1}, - {OP_WR, XCM_REG_GR_LD0_PR, 0x1}, - {OP_WR, XCM_REG_GR_LD1_PR, 0x2}, - {OP_WR, XCM_REG_CFC_INIT_CRD, 0x1}, - {OP_WR, XCM_REG_FIC0_INIT_CRD, 0x40}, - {OP_WR, XCM_REG_FIC1_INIT_CRD, 0x40}, - {OP_WR, XCM_REG_TM_INIT_CRD, 0x4}, - {OP_WR, XCM_REG_XQM_INIT_CRD, 0x20}, - {OP_WR, XCM_REG_XX_INIT_CRD, 0x2}, - {OP_WR_E1, XCM_REG_XX_MSG_NUM, 0x1f}, - {OP_WR_E1H, XCM_REG_XX_MSG_NUM, 0x20}, - {OP_ZR, XCM_REG_XX_TABLE, 0x12}, - {OP_SW_E1, XCM_REG_XX_DESCR_TABLE, 0x1f02d4}, - {OP_SW_E1H, XCM_REG_XX_DESCR_TABLE, 0x1f0329}, - {OP_WR, XCM_REG_N_SM_CTX_LD_0, 0xf}, - {OP_WR, XCM_REG_N_SM_CTX_LD_1, 0x7}, - {OP_WR, XCM_REG_N_SM_CTX_LD_2, 0xb}, - {OP_WR, XCM_REG_N_SM_CTX_LD_3, 0xe}, - {OP_ZR_E1, XCM_REG_N_SM_CTX_LD_4, 0x4}, - {OP_WR_E1H, XCM_REG_N_SM_CTX_LD_4, 0xe}, - {OP_ZR_E1H, XCM_REG_N_SM_CTX_LD_5, 0x3}, - {OP_WR, XCM_REG_XCM_REG0_SZ, 0x4}, - {OP_WR, XCM_REG_XCM_STORM0_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_STORM1_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_XQM_IFEN, 0x1}, - {OP_WR, XCM_REG_STORM_XCM_IFEN, 0x1}, - {OP_WR, XCM_REG_XQM_XCM_IFEN, 0x1}, - {OP_WR, XCM_REG_XSDM_IFEN, 0x1}, - {OP_WR, XCM_REG_TM_XCM_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_TM_IFEN, 0x1}, - {OP_WR, XCM_REG_TSEM_IFEN, 0x1}, - {OP_WR, XCM_REG_CSEM_IFEN, 0x1}, - {OP_WR, XCM_REG_USEM_IFEN, 0x1}, - {OP_WR, XCM_REG_DORQ_IFEN, 0x1}, - {OP_WR, XCM_REG_PBF_IFEN, 0x1}, - {OP_WR, XCM_REG_NIG0_IFEN, 0x1}, - {OP_WR, XCM_REG_NIG1_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_AG_WR_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_AG_RD_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_SM_WR_IFEN, 0x1}, - {OP_WR, XCM_REG_CDU_SM_RD_IFEN, 0x1}, - {OP_WR, XCM_REG_XCM_CFC_IFEN, 0x1}, -#define XCM_COMMON_END 1538 -#define XCM_PORT0_START 1538 - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, -#define XCM_PORT0_END 1546 -#define XCM_PORT1_START 1546 - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, -#define XCM_PORT1_END 1554 -#define XCM_FUNC0_START 1554 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC0_END 1563 -#define XCM_FUNC1_START 1563 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC1_END 1572 -#define XCM_FUNC2_START 1572 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC2_END 1581 -#define XCM_FUNC3_START 1581 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC3_END 1590 -#define XCM_FUNC4_START 1590 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC4_END 1599 -#define XCM_FUNC5_START 1599 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC5_END 1608 -#define XCM_FUNC6_START 1608 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0}, -#define XCM_FUNC6_END 1617 -#define XCM_FUNC7_START 1617 - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8}, - {OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff}, - {OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff}, - {OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0}, -#define XCM_FUNC7_END 1626 -#define XSEM_COMMON_START 1626 - {OP_RD, XSEM_REG_MSG_NUM_FIC0, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FIC1, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC0, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC1, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC2, 0x0}, - {OP_RD, XSEM_REG_MSG_NUM_FOC3, 0x0}, - {OP_WR, XSEM_REG_ARB_ELEMENT0, 0x1}, - {OP_WR, XSEM_REG_ARB_ELEMENT1, 0x2}, - {OP_WR, XSEM_REG_ARB_ELEMENT2, 0x3}, - {OP_WR, XSEM_REG_ARB_ELEMENT3, 0x0}, - {OP_WR, XSEM_REG_ARB_ELEMENT4, 0x4}, - {OP_WR, XSEM_REG_ARB_CYCLE_SIZE, 0x1}, - {OP_WR, XSEM_REG_TS_0_AS, 0x0}, - {OP_WR, XSEM_REG_TS_1_AS, 0x1}, - {OP_WR, XSEM_REG_TS_2_AS, 0x4}, - {OP_WR, XSEM_REG_TS_3_AS, 0x0}, - {OP_WR, XSEM_REG_TS_4_AS, 0x1}, - {OP_WR, XSEM_REG_TS_5_AS, 0x3}, - {OP_WR, XSEM_REG_TS_6_AS, 0x0}, - {OP_WR, XSEM_REG_TS_7_AS, 0x1}, - {OP_WR, XSEM_REG_TS_8_AS, 0x4}, - {OP_WR, XSEM_REG_TS_9_AS, 0x0}, - {OP_WR, XSEM_REG_TS_10_AS, 0x1}, - {OP_WR, XSEM_REG_TS_11_AS, 0x3}, - {OP_WR, XSEM_REG_TS_12_AS, 0x0}, - {OP_WR, XSEM_REG_TS_13_AS, 0x1}, - {OP_WR, XSEM_REG_TS_14_AS, 0x4}, - {OP_WR, XSEM_REG_TS_15_AS, 0x0}, - {OP_WR, XSEM_REG_TS_16_AS, 0x4}, - {OP_WR, XSEM_REG_TS_17_AS, 0x3}, - {OP_ZR, XSEM_REG_TS_18_AS, 0x2}, - {OP_WR, XSEM_REG_ENABLE_IN, 0x3fff}, - {OP_WR, XSEM_REG_ENABLE_OUT, 0x3ff}, - {OP_WR, XSEM_REG_FIC0_DISABLE, 0x0}, - {OP_WR, XSEM_REG_FIC1_DISABLE, 0x0}, - {OP_WR, XSEM_REG_PAS_DISABLE, 0x0}, - {OP_WR, XSEM_REG_THREADS_LIST, 0xffff}, - {OP_ZR, XSEM_REG_PASSIVE_BUFFER, 0x800}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18bc0, 0x1}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18000, 0x0}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18040, 0x18}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x18080, 0xc}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x180c0, 0x66}, - {OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18300, 0x7a120}, - {OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18300, 0x138}, - {OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18300, 0x1388}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4}, - {OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18340, 0x1f4}, - {OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18340, 0x0}, - {OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18340, 0x5}, - {OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18380, 0x4c4b4}, - {OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18380, 0x1dcd6500}, - {OP_WR_EMUL_E1H, XSEM_REG_FAST_MEMORY + 0x11480, 0x0}, - {OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18380, 0x4c4b40}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3d60, 0x4}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x11480, 0x1}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d60 + 0x10, 0x202f3}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x29c8, 0x4}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3000, 0x48}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29c8 + 0x10, 0x20348}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1020, 0xc8}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2080, 0x48}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1000, 0x2}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9020, 0xc8}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3128, 0x8e}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9000, 0x2}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3368, 0x0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x21a8, 0x86}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3370, 0x202f5}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2000, 0x20}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3b90, 0x402f7}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x23c8, 0x0}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3e20, 0x202fb}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x23d0, 0x2034a}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1518, 0x1}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2498, 0x4034c}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1830, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2c20, 0x0}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1838, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2c10, 0x0}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1820, 0x202fd}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2c08, 0x20350}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4ac0, 0x2}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3010, 0x1}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b00, 0x4}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x4040, 0x10}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1f48, 0x202ff}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x4000, 0x100352}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6ac0, 0x2}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b00, 0x4}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x8408, 0x20362}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x0}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100301}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100364}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x1000000}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80311}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80374}, - {OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x2000000}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c60, 0x80319}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c60, 0x8037c}, - {OP_ZP_E1, XSEM_REG_INT_TABLE, 0xb50000}, - {OP_ZP_E1H, XSEM_REG_INT_TABLE, 0xbd0000}, - {OP_WR_64_E1, XSEM_REG_INT_TABLE + 0x368, 0x130321}, - {OP_WR_64_E1H, XSEM_REG_INT_TABLE + 0x3a8, 0xb0384}, - {OP_ZP_E1, XSEM_REG_PRAM, 0x33660000}, - {OP_ZP_E1H, XSEM_REG_PRAM, 0x34060000}, - {OP_ZP_E1, XSEM_REG_PRAM + 0x8000, 0x38b30cda}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x8000, 0x37960d02}, - {OP_ZP_E1, XSEM_REG_PRAM + 0x10000, 0x3bb11b07}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x10000, 0x3bc31ae8}, - {OP_ZP_E1, XSEM_REG_PRAM + 0x18000, 0x2a2629f4}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x18000, 0x382629d9}, - {OP_WR_64_E1, XSEM_REG_PRAM + 0x1d6c0, 0x45280323}, - {OP_ZP_E1H, XSEM_REG_PRAM + 0x20000, 0x124537e3}, - {OP_WR_64_E1H, XSEM_REG_PRAM + 0x22220, 0x3bbc0386}, -#define XSEM_COMMON_END 1741 -#define XSEM_PORT0_START 1741 - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3ba0, 0x14}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc000, 0xfc}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3c40, 0x24}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x24a8, 0x14}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1400, 0xa}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2548, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1450, 0x6}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2668, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3378, 0xfc}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2788, 0x24}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b58, 0x0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x28a8, 0x24}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d78, 0x20325}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa000, 0x28}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d88, 0x100327}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa140, 0xc}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1500, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29e0, 0x20388}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1508, 0x1}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3000, 0x1}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5020, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5030, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5000, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5010, 0x2}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x5040, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x5208, 0x1}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x5048, 0xe}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ac8, 0x2038a}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50b8, 0x1}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b10, 0x42}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ac8, 0x20337}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d20, 0x4}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b10, 0x42}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d20, 0x4}, -#define XSEM_PORT0_END 1775 -#define XSEM_PORT1_START 1775 - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3bf0, 0x14}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc3f0, 0xfc}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3cd0, 0x24}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x24f8, 0x14}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1428, 0xa}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x25d8, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1468, 0x6}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x26f8, 0x24}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3768, 0xfc}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2818, 0x24}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b5c, 0x0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2938, 0x24}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d80, 0x20339}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa0a0, 0x28}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3dc8, 0x10033b}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa170, 0xc}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1504, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29e8, 0x2038c}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x150c, 0x1}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3004, 0x1}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5028, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5038, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5008, 0x2}, - {OP_ZR, XSEM_REG_FAST_MEMORY + 0x5018, 0x2}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x5044, 0x0}, - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x520c, 0x1}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x5080, 0xe}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ad0, 0x2038e}, - {OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50bc, 0x1}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6c18, 0x42}, - {OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ad0, 0x2034b}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d30, 0x4}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4c18, 0x42}, - {OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d30, 0x4}, -#define XSEM_PORT1_END 1809 -#define XSEM_FUNC0_START 1809 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e0, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29f0, 0x100390}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5048, 0xe}, -#define XSEM_FUNC0_END 1812 -#define XSEM_FUNC1_START 1812 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e4, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a30, 0x1003a0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5080, 0xe}, -#define XSEM_FUNC1_END 1815 -#define XSEM_FUNC2_START 1815 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e8, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a70, 0x1003b0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50b8, 0xe}, -#define XSEM_FUNC2_END 1818 -#define XSEM_FUNC3_START 1818 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7ec, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2ab0, 0x1003c0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50f0, 0xe}, -#define XSEM_FUNC3_END 1821 -#define XSEM_FUNC4_START 1821 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f0, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2af0, 0x1003d0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5128, 0xe}, -#define XSEM_FUNC4_END 1824 -#define XSEM_FUNC5_START 1824 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f4, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2b30, 0x1003e0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5160, 0xe}, -#define XSEM_FUNC5_END 1827 -#define XSEM_FUNC6_START 1827 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f8, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2b70, 0x1003f0}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5198, 0xe}, -#define XSEM_FUNC6_END 1830 -#define XSEM_FUNC7_START 1830 - {OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7fc, 0x0}, - {OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2bb0, 0x100400}, - {OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x51d0, 0xe}, -#define XSEM_FUNC7_END 1833 -#define CDU_COMMON_START 1833 - {OP_WR, CDU_REG_CDU_CONTROL0, 0x1}, - {OP_WR_E1H, CDU_REG_MF_MODE, 0x1}, - {OP_WR, CDU_REG_CDU_CHK_MASK0, 0x3d000}, - {OP_WR, CDU_REG_CDU_CHK_MASK1, 0x3d}, - {OP_WB_E1, CDU_REG_L1TT, 0x200034d}, - {OP_WB_E1H, CDU_REG_L1TT, 0x2000410}, - {OP_WB_E1, CDU_REG_MATT, 0x20054d}, - {OP_WB_E1H, CDU_REG_MATT, 0x280610}, - {OP_ZR_E1, CDU_REG_MATT + 0x80, 0x2}, - {OP_WB_E1, CDU_REG_MATT + 0x88, 0x6056d}, - {OP_ZR, CDU_REG_MATT + 0xa0, 0x18}, -#define CDU_COMMON_END 1844 -#define DMAE_COMMON_START 1844 - {OP_ZR, DMAE_REG_CMD_MEM, 0xe0}, - {OP_WR, DMAE_REG_CRC16C_INIT, 0x0}, - {OP_WR, DMAE_REG_CRC16T10_INIT, 0x1}, - {OP_WR_E1, DMAE_REG_PXP_REQ_INIT_CRD, 0x1}, - {OP_WR_E1H, DMAE_REG_PXP_REQ_INIT_CRD, 0x2}, - {OP_WR, DMAE_REG_PCI_IFEN, 0x1}, - {OP_WR, DMAE_REG_GRC_IFEN, 0x1}, -#define DMAE_COMMON_END 1851 -#define PXP_COMMON_START 1851 - {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x400, 0x50573}, - {OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x400, 0x50638}, - {OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x420, 0x50578}, - {OP_WB_E1H, PXP_REG_HST_INBOUND_INT, 0x5063d}, - {OP_WB_E1, PXP_REG_HST_INBOUND_INT, 0x5057d}, - {OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x20, 0x50642}, -#define PXP_COMMON_END 1857 -#define CFC_COMMON_START 1857 - {OP_ZR_E1H, CFC_REG_LINK_LIST, 0x100}, - {OP_WR, CFC_REG_CONTROL0, 0x10}, - {OP_WR, CFC_REG_DISABLE_ON_ERROR, 0x3fff}, - {OP_WR, CFC_REG_INTERFACES, 0x280000}, - {OP_WR, CFC_REG_LCREQ_WEIGHTS, 0x84924a}, - {OP_WR, CFC_REG_INTERFACES, 0x0}, -#define CFC_COMMON_END 1863 -#define HC_COMMON_START 1863 - {OP_ZR_E1, HC_REG_USTORM_ADDR_FOR_COALESCE, 0x4}, -#define HC_COMMON_END 1864 -#define HC_PORT0_START 1864 - {OP_WR_E1, HC_REG_CONFIG_0, 0x1080}, - {OP_ZR_E1, HC_REG_UC_RAM_ADDR_0, 0x2}, - {OP_WR_E1, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1, HC_REG_LEADING_EDGE_0, 0xffff}, - {OP_WR_E1, HC_REG_TRAILING_EDGE_0, 0xffff}, - {OP_WR_E1, HC_REG_AGG_INT_0, 0x0}, - {OP_WR_E1, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_PORT0_END 1882 -#define HC_PORT1_START 1882 - {OP_WR_E1, HC_REG_CONFIG_1, 0x1080}, - {OP_ZR_E1, HC_REG_UC_RAM_ADDR_1, 0x2}, - {OP_WR_E1, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1, HC_REG_LEADING_EDGE_1, 0xffff}, - {OP_WR_E1, HC_REG_TRAILING_EDGE_1, 0xffff}, - {OP_WR_E1, HC_REG_AGG_INT_1, 0x0}, - {OP_WR_E1, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_PORT1_END 1900 -#define HC_FUNC0_START 1900 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x0}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC0_END 1915 -#define HC_FUNC1_START 1915 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x1}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC1_END 1930 -#define HC_FUNC2_START 1930 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x2}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC2_END 1945 -#define HC_FUNC3_START 1945 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x3}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC3_END 1960 -#define HC_FUNC4_START 1960 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x4}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC4_END 1975 -#define HC_FUNC5_START 1975 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x5}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC5_END 1990 -#define HC_FUNC6_START 1990 - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x6}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2}, - {OP_WR_E1H, HC_REG_VQID_0, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0}, - {OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a}, -#define HC_FUNC6_END 2005 -#define HC_FUNC7_START 2005 - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1080}, - {OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x7}, - {OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10}, - {OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0}, - {OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_VQID_1, 0x2b5}, - {OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0}, - {OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a}, - {OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff}, - {OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2}, - {OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a}, - {OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a}, -#define HC_FUNC7_END 2020 -#define PXP2_COMMON_START 2020 - {OP_WR_E1H, PXP2_REG_RQ_DRAM_ALIGN, 0x1}, - {OP_WR, PXP2_REG_PGL_CONTROL0, 0xe38340}, - {OP_WR, PXP2_REG_PGL_CONTROL1, 0x3c10}, - {OP_WR_E1H, PXP2_REG_RQ_ELT_DISABLE, 0x1}, - {OP_WR_E1H, PXP2_REG_WR_REV_MODE, 0x0}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_0, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_TSDM_7, 0xffffffff}, - {OP_WR_E1, PXP2_REG_PGL_INT_USDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_USDM_7, 0xffffffff}, - {OP_WR_E1H, PXP2_REG_PGL_INT_XSDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_XSDM_7, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_0, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_1, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_2, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_3, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_4, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_5, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_6, 0xffffffff}, - {OP_WR, PXP2_REG_PGL_INT_CSDM_7, 0xffffffff}, - {OP_WR_E1, PXP2_REG_PGL_INT_XSDM_0, 0xffff3330}, - {OP_WR_E1H, PXP2_REG_PGL_INT_XSDM_0, 0xff802000}, - {OP_WR_E1, PXP2_REG_PGL_INT_XSDM_1, 0xffff3340}, - {OP_WR_E1H, PXP2_REG_PGL_INT_USDM_0, 0xf0005000}, - {OP_WR_E1, PXP2_REG_PGL_INT_USDM_0, 0xf0003000}, - {OP_WR_E1H, PXP2_REG_PGL_INT_USDM_1, 0xf0008000}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ6, 0x8}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ9, 0x8}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ10, 0x8}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ11, 0x2}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ17, 0x4}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ18, 0x5}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ19, 0x4}, - {OP_WR, PXP2_REG_RD_MAX_BLKS_VQ22, 0x0}, - {OP_WR, PXP2_REG_RD_START_INIT, 0x1}, - {OP_WR, PXP2_REG_WR_DMAE_TH, 0x3f}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD0, 0x40}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD1, 0x1808}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD2, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD3, 0x803}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD4, 0x40}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD5, 0x3}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD6, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD7, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD8, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD9, 0x10003}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD10, 0x803}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD11, 0x803}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD12, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD13, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD14, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD15, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD16, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD17, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD18, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD19, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD20, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD22, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD23, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD24, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD25, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD26, 0x3}, - {OP_WR, PXP2_REG_RQ_BW_RD_ADD27, 0x3}, - {OP_WR, PXP2_REG_PSWRQ_BW_ADD28, 0x2403}, - {OP_WR, PXP2_REG_RQ_BW_WR_ADD29, 0x2f}, - {OP_WR, PXP2_REG_RQ_BW_WR_ADD30, 0x9}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND0, 0x19}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB1, 0x184}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB2, 0x183}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB3, 0x306}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND4, 0x19}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND5, 0x6}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB6, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB7, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB8, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB9, 0xc86}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB10, 0x306}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB11, 0x306}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND12, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND13, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND14, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND15, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND16, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND17, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND18, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND19, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND20, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND22, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND23, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND24, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND25, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND26, 0x6}, - {OP_WR, PXP2_REG_RQ_BW_RD_UBOUND27, 0x6}, - {OP_WR, PXP2_REG_PSWRQ_BW_UB28, 0x306}, - {OP_WR, PXP2_REG_RQ_BW_WR_UBOUND29, 0x13}, - {OP_WR, PXP2_REG_RQ_BW_WR_UBOUND30, 0x6}, - {OP_WR, PXP2_REG_PSWRQ_BW_L1, 0x1004}, - {OP_WR, PXP2_REG_PSWRQ_BW_L2, 0x1004}, - {OP_WR, PXP2_REG_PSWRQ_BW_RD, 0x106440}, - {OP_WR, PXP2_REG_PSWRQ_BW_WR, 0x106440}, - {OP_WR_E1H, PXP2_REG_RQ_ILT_MODE, 0x1}, - {OP_WR, PXP2_REG_RQ_RBC_DONE, 0x1}, -#define PXP2_COMMON_END 2137 -#define MISC_AEU_COMMON_START 2137 - {OP_ZR, MISC_REG_AEU_GENERAL_ATTN_0, 0x16}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_NIG_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_NIG_0, 0xf0000000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_PXP_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_PXP_0, 0x55555555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_PXP_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_0, 0xf0000000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_1, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_1, 0x55555555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_NIG_1, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_NIG_1, 0xf0000000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_PXP_1, 0x0}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_PXP_1, 0x10000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE3_PXP_1, 0x5014}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_1, 0x0}, - {OP_WR_E1H, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0xc00}, - {OP_WR_E1H, MISC_REG_AEU_GENERAL_MASK, 0x3}, -#define MISC_AEU_COMMON_END 2156 -#define MISC_AEU_PORT0_START 2156 - {OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xbf5c0000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xff5c0000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff51fef}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff55fff}, - {OP_WR, MISC_REG_AEU_ENABLE3_FUNC_0_OUT_0, 0xffff}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 0x500003e0}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 0xf00003e0}, - {OP_WR, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1, 0x0}, - {OP_WR, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_1, 0xa000}, - {OP_ZR, MISC_REG_AEU_ENABLE3_FUNC_0_OUT_1, 0x5}, - {OP_WR, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_2, 0xfe00000}, - {OP_ZR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3, 0x14}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3, 0x7}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_4, 0x400}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_5, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_NIG_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_5, 0x1000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_NIG_0, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_6, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_PXP_0, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_6, 0x4000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_PXP_0, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_7, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_PXP_0, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_7, 0x10000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_PXP_0, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x4}, - {OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x0}, - {OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_0, 0x3}, - {OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_0, 0x7}, -#define MISC_AEU_PORT0_END 2188 -#define MISC_AEU_PORT1_START 2188 - {OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xbf5c0000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xff5c0000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff51fef}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff55fff}, - {OP_WR, MISC_REG_AEU_ENABLE3_FUNC_1_OUT_0, 0xffff}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 0x500003e0}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 0xf00003e0}, - {OP_WR, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1, 0x0}, - {OP_WR, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_1, 0xa000}, - {OP_ZR, MISC_REG_AEU_ENABLE3_FUNC_1_OUT_1, 0x5}, - {OP_WR, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_2, 0xfe00000}, - {OP_ZR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3, 0x14}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3, 0x7}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_NIG_1, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_4, 0x800}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_NIG_1, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_5, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_NIG_1, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_5, 0x2000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_NIG_1, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_6, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE1_PXP_1, 0x55540000}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_6, 0x8000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE2_PXP_1, 0x55555555}, - {OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_7, 0x3}, - {OP_WR_E1, MISC_REG_AEU_ENABLE3_PXP_1, 0x5555}, - {OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_7, 0x20000}, - {OP_WR_E1, MISC_REG_AEU_ENABLE4_PXP_1, 0x0}, - {OP_ZR_E1H, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x4}, - {OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x0}, - {OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_1, 0x3}, - {OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_1, 0x7}, -#define MISC_AEU_PORT1_END 2220 - -}; - -static const u32 init_data_e1[] = { - 0x00010000, 0x000204c0, 0x00030980, 0x00040e40, 0x00051300, 0x000617c0, - 0x00071c80, 0x00082140, 0x00092600, 0x000a2ac0, 0x000b2f80, 0x000c3440, - 0x000d3900, 0x000e3dc0, 0x000f4280, 0x00104740, 0x00114c00, 0x001250c0, - 0x00135580, 0x00145a40, 0x00155f00, 0x001663c0, 0x00176880, 0x00186d40, - 0x00197200, 0x001a76c0, 0x001b7b80, 0x001c8040, 0x001d8500, 0x001e89c0, - 0x001f8e80, 0x00209340, 0x00002000, 0x00004000, 0x00006000, 0x00008000, - 0x0000a000, 0x0000c000, 0x0000e000, 0x00010000, 0x00012000, 0x00014000, - 0x00016000, 0x00018000, 0x0001a000, 0x0001c000, 0x0001e000, 0x00020000, - 0x00022000, 0x00024000, 0x00026000, 0x00028000, 0x0002a000, 0x0002c000, - 0x0002e000, 0x00030000, 0x00032000, 0x00034000, 0x00036000, 0x00038000, - 0x0003a000, 0x0003c000, 0x0003e000, 0x00040000, 0x00042000, 0x00044000, - 0x00046000, 0x00048000, 0x0004a000, 0x0004c000, 0x0004e000, 0x00050000, - 0x00052000, 0x00054000, 0x00056000, 0x00058000, 0x0005a000, 0x0005c000, - 0x0005e000, 0x00060000, 0x00062000, 0x00064000, 0x00066000, 0x00068000, - 0x0006a000, 0x0006c000, 0x0006e000, 0x00070000, 0x00072000, 0x00074000, - 0x00076000, 0x00078000, 0x0007a000, 0x0007c000, 0x0007e000, 0x00080000, - 0x00082000, 0x00084000, 0x00086000, 0x00088000, 0x0008a000, 0x0008c000, - 0x0008e000, 0x00090000, 0x00092000, 0x00094000, 0x00096000, 0x00098000, - 0x0009a000, 0x0009c000, 0x0009e000, 0x000a0000, 0x000a2000, 0x000a4000, - 0x000a6000, 0x000a8000, 0x000aa000, 0x000ac000, 0x000ae000, 0x000b0000, - 0x000b2000, 0x000b4000, 0x000b6000, 0x000b8000, 0x000ba000, 0x000bc000, - 0x000be000, 0x000c0000, 0x000c2000, 0x000c4000, 0x000c6000, 0x000c8000, - 0x000ca000, 0x000cc000, 0x000ce000, 0x000d0000, 0x000d2000, 0x000d4000, - 0x000d6000, 0x000d8000, 0x000da000, 0x000dc000, 0x000de000, 0x000e0000, - 0x000e2000, 0x000e4000, 0x000e6000, 0x000e8000, 0x000ea000, 0x000ec000, - 0x000ee000, 0x000f0000, 0x000f2000, 0x000f4000, 0x000f6000, 0x000f8000, - 0x000fa000, 0x000fc000, 0x000fe000, 0x00100000, 0x00102000, 0x00104000, - 0x00106000, 0x00108000, 0x0010a000, 0x0010c000, 0x0010e000, 0x00110000, - 0x00112000, 0x00114000, 0x00116000, 0x00118000, 0x0011a000, 0x0011c000, - 0x0011e000, 0x00120000, 0x00122000, 0x00124000, 0x00126000, 0x00128000, - 0x0012a000, 0x0012c000, 0x0012e000, 0x00130000, 0x00132000, 0x00134000, - 0x00136000, 0x00138000, 0x0013a000, 0x0013c000, 0x0013e000, 0x00140000, - 0x00142000, 0x00144000, 0x00146000, 0x00148000, 0x0014a000, 0x0014c000, - 0x0014e000, 0x00150000, 0x00152000, 0x00154000, 0x00156000, 0x00158000, - 0x0015a000, 0x0015c000, 0x0015e000, 0x00160000, 0x00162000, 0x00164000, - 0x00166000, 0x00168000, 0x0016a000, 0x0016c000, 0x0016e000, 0x00170000, - 0x00172000, 0x00174000, 0x00176000, 0x00178000, 0x0017a000, 0x0017c000, - 0x0017e000, 0x00180000, 0x00182000, 0x00184000, 0x00186000, 0x00188000, - 0x0018a000, 0x0018c000, 0x0018e000, 0x00190000, 0x00192000, 0x00194000, - 0x00196000, 0x00198000, 0x0019a000, 0x0019c000, 0x0019e000, 0x001a0000, - 0x001a2000, 0x001a4000, 0x001a6000, 0x001a8000, 0x001aa000, 0x001ac000, - 0x001ae000, 0x001b0000, 0x001b2000, 0x001b4000, 0x001b6000, 0x001b8000, - 0x001ba000, 0x001bc000, 0x001be000, 0x001c0000, 0x001c2000, 0x001c4000, - 0x001c6000, 0x001c8000, 0x001ca000, 0x001cc000, 0x001ce000, 0x001d0000, - 0x001d2000, 0x001d4000, 0x001d6000, 0x001d8000, 0x001da000, 0x001dc000, - 0x001de000, 0x001e0000, 0x001e2000, 0x001e4000, 0x001e6000, 0x001e8000, - 0x001ea000, 0x001ec000, 0x001ee000, 0x001f0000, 0x001f2000, 0x001f4000, - 0x001f6000, 0x001f8000, 0x001fa000, 0x001fc000, 0x001fe000, 0x00200000, - 0x00202000, 0x00204000, 0x00206000, 0x00208000, 0x0020a000, 0x0020c000, - 0x0020e000, 0x00210000, 0x00212000, 0x00214000, 0x00216000, 0x00218000, - 0x0021a000, 0x0021c000, 0x0021e000, 0x00220000, 0x00222000, 0x00224000, - 0x00226000, 0x00228000, 0x0022a000, 0x0022c000, 0x0022e000, 0x00230000, - 0x00232000, 0x00234000, 0x00236000, 0x00238000, 0x0023a000, 0x0023c000, - 0x0023e000, 0x00240000, 0x00242000, 0x00244000, 0x00246000, 0x00248000, - 0x0024a000, 0x0024c000, 0x0024e000, 0x00250000, 0x00252000, 0x00254000, - 0x00256000, 0x00258000, 0x0025a000, 0x0025c000, 0x0025e000, 0x00260000, - 0x00262000, 0x00264000, 0x00266000, 0x00268000, 0x0026a000, 0x0026c000, - 0x0026e000, 0x00270000, 0x00272000, 0x00274000, 0x00276000, 0x00278000, - 0x0027a000, 0x0027c000, 0x0027e000, 0x00280000, 0x00282000, 0x00284000, - 0x00286000, 0x00288000, 0x0028a000, 0x0028c000, 0x0028e000, 0x00290000, - 0x00292000, 0x00294000, 0x00296000, 0x00298000, 0x0029a000, 0x0029c000, - 0x0029e000, 0x002a0000, 0x002a2000, 0x002a4000, 0x002a6000, 0x002a8000, - 0x002aa000, 0x002ac000, 0x002ae000, 0x002b0000, 0x002b2000, 0x002b4000, - 0x002b6000, 0x002b8000, 0x002ba000, 0x002bc000, 0x002be000, 0x002c0000, - 0x002c2000, 0x002c4000, 0x002c6000, 0x002c8000, 0x002ca000, 0x002cc000, - 0x002ce000, 0x002d0000, 0x002d2000, 0x002d4000, 0x002d6000, 0x002d8000, - 0x002da000, 0x002dc000, 0x002de000, 0x002e0000, 0x002e2000, 0x002e4000, - 0x002e6000, 0x002e8000, 0x002ea000, 0x002ec000, 0x002ee000, 0x002f0000, - 0x002f2000, 0x002f4000, 0x002f6000, 0x002f8000, 0x002fa000, 0x002fc000, - 0x002fe000, 0x00300000, 0x00302000, 0x00304000, 0x00306000, 0x00308000, - 0x0030a000, 0x0030c000, 0x0030e000, 0x00310000, 0x00312000, 0x00314000, - 0x00316000, 0x00318000, 0x0031a000, 0x0031c000, 0x0031e000, 0x00320000, - 0x00322000, 0x00324000, 0x00326000, 0x00328000, 0x0032a000, 0x0032c000, - 0x0032e000, 0x00330000, 0x00332000, 0x00334000, 0x00336000, 0x00338000, - 0x0033a000, 0x0033c000, 0x0033e000, 0x00340000, 0x00342000, 0x00344000, - 0x00346000, 0x00348000, 0x0034a000, 0x0034c000, 0x0034e000, 0x00350000, - 0x00352000, 0x00354000, 0x00356000, 0x00358000, 0x0035a000, 0x0035c000, - 0x0035e000, 0x00360000, 0x00362000, 0x00364000, 0x00366000, 0x00368000, - 0x0036a000, 0x0036c000, 0x0036e000, 0x00370000, 0x00372000, 0x00374000, - 0x00376000, 0x00378000, 0x0037a000, 0x0037c000, 0x0037e000, 0x00380000, - 0x00382000, 0x00384000, 0x00386000, 0x00388000, 0x0038a000, 0x0038c000, - 0x0038e000, 0x00390000, 0x00392000, 0x00394000, 0x00396000, 0x00398000, - 0x0039a000, 0x0039c000, 0x0039e000, 0x003a0000, 0x003a2000, 0x003a4000, - 0x003a6000, 0x003a8000, 0x003aa000, 0x003ac000, 0x003ae000, 0x003b0000, - 0x003b2000, 0x003b4000, 0x003b6000, 0x003b8000, 0x003ba000, 0x003bc000, - 0x003be000, 0x003c0000, 0x003c2000, 0x003c4000, 0x003c6000, 0x003c8000, - 0x003ca000, 0x003cc000, 0x003ce000, 0x003d0000, 0x003d2000, 0x003d4000, - 0x003d6000, 0x003d8000, 0x003da000, 0x003dc000, 0x003de000, 0x003e0000, - 0x003e2000, 0x003e4000, 0x003e6000, 0x003e8000, 0x003ea000, 0x003ec000, - 0x003ee000, 0x003f0000, 0x003f2000, 0x003f4000, 0x003f6000, 0x003f8000, - 0x003fa000, 0x003fc000, 0x003fe000, 0x003fe001, 0x00000000, 0x000001ff, - 0x00000200, 0x00000001, 0x00000003, 0x00bebc20, 0x00000003, 0x00bebc20, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x00000000, 0x00007ff8, 0x00000000, 0x00003500, - 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, - 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0x00000003, 0x00bebc20, 0x00002000, 0x000040c0, 0x00006180, 0x00008240, - 0x0000a300, 0x0000c3c0, 0x0000e480, 0x00010540, 0x00012600, 0x000146c0, - 0x00016780, 0x00018840, 0x0001a900, 0x0001c9c0, 0x0001ea80, 0x00020b40, - 0x00022c00, 0x00024cc0, 0x00026d80, 0x00028e40, 0x0002af00, 0x0002cfc0, - 0x0002f080, 0x00031140, 0x00033200, 0x000352c0, 0x00037380, 0x00039440, - 0x0003b500, 0x0003d5c0, 0x0003f680, 0x00041740, 0x00043800, 0x000458c0, - 0x00047980, 0x00049a40, 0x00008000, 0x00010380, 0x00018700, 0x00020a80, - 0x00028e00, 0x00031180, 0x00039500, 0x00041880, 0x00049c00, 0x00051f80, - 0x0005a300, 0x00062680, 0x0006aa00, 0x00072d80, 0x0007b100, 0x00083480, - 0x0008b800, 0x00093b80, 0x0009bf00, 0x000a4280, 0x000ac600, 0x000b4980, - 0x000bcd00, 0x000c5080, 0x000cd400, 0x000d5780, 0x000ddb00, 0x00001900, - 0x00000000, 0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8, - 0x00000000, 0x00001500, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x00000000, 0x00007ff8, 0x00000000, 0x00001500, 0x00001000, 0x00002080, - 0x00003100, 0x00004180, 0x00005200, 0x00006280, 0x00007300, 0x00008380, - 0x00009400, 0x0000a480, 0x0000b500, 0x0000c580, 0x0000d600, 0x0000e680, - 0x0000f700, 0x00010780, 0x00011800, 0x00012880, 0x00013900, 0x00014980, - 0x00015a00, 0x00016a80, 0x00017b00, 0x00018b80, 0x00019c00, 0x0001ac80, - 0x0001bd00, 0x0001cd80, 0x0001de00, 0x0001ee80, 0x0001ff00, 0x10000000, - 0x000028ad, 0x00000000, 0x00010001, 0x00350804, 0xccccccc1, 0xffffffff, - 0xffffffff, 0x7058103c, 0x00000000, 0xcccc0201, 0xcccccccc, 0x00000000, - 0xffffffff, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x00000000, 0x00007ff8, 0x00000000, - 0x00003500, 0x000e01b7, 0x011600d6, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x00100000, 0x00000000, 0x007201bb, 0x012300f3, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, - 0x00000000, 0x0000ffff, 0x00000000, 0x00100000, 0x00000000, 0xfffffff3, - 0x320fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, - 0xcdcdcdcd, 0xfffffff1, 0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, - 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, - 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, - 0x31efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, - 0xcdcdcdcd, 0xfffffff5, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x310fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, - 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, - 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, - 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, - 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, - 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, 0x30efffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, - 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, - 0xcdcdcdcd, 0xfffffff3, 0x31efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, - 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, - 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, - 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, - 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, - 0xcdcdcdcd, 0xffffff97, 0x056fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, - 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x310fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, - 0x320fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, - 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, - 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, - 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffff8a, 0x042fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, - 0x05cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, - 0xcdcdcdcd, 0xfffffff5, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x300fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, - 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, - 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, - 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, - 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, - 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, - 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x040fffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, - 0x300fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, - 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, - 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, - 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, - 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, - 0xcdcdcdcd, 0x00100000, 0x00070100, 0x00028170, 0x000b8198, 0x00020250, - 0x00010270, 0x000f0280, 0x00010370, 0x00080000, 0x00080080, 0x00028100, - 0x000b8128, 0x000201e0, 0x00010200, 0x00070210, 0x00020280, 0x000f0000, - 0x000800f0, 0x00028170, 0x000b8198, 0x00020250, 0x00010270, 0x000b8280, - 0x00080338, 0x00100000, 0x00080100, 0x00028180, 0x000b81a8, 0x00020260, - 0x00018280, 0x000e8298, 0x00080380, 0x00028000, 0x000b8028, 0x000200e0, - 0x00010100, 0x00008110, 0x00000118, 0xcccccccc, 0xcccccccc, 0xcccccccc, - 0xcccccccc, 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, - 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000 -}; - -static const u32 init_data_e1h[] = { - 0x00010000, 0x000204c0, 0x00030980, 0x00040e40, 0x00051300, 0x000617c0, - 0x00071c80, 0x00082140, 0x00092600, 0x000a2ac0, 0x000b2f80, 0x000c3440, - 0x000d3900, 0x000e3dc0, 0x000f4280, 0x00104740, 0x00114c00, 0x001250c0, - 0x00135580, 0x00145a40, 0x00155f00, 0x001663c0, 0x00176880, 0x00186d40, - 0x00197200, 0x001a76c0, 0x001b7b80, 0x001c8040, 0x001d8500, 0x001e89c0, - 0x001f8e80, 0x00209340, 0x00002000, 0x00004000, 0x00006000, 0x00008000, - 0x0000a000, 0x0000c000, 0x0000e000, 0x00010000, 0x00012000, 0x00014000, - 0x00016000, 0x00018000, 0x0001a000, 0x0001c000, 0x0001e000, 0x00020000, - 0x00022000, 0x00024000, 0x00026000, 0x00028000, 0x0002a000, 0x0002c000, - 0x0002e000, 0x00030000, 0x00032000, 0x00034000, 0x00036000, 0x00038000, - 0x0003a000, 0x0003c000, 0x0003e000, 0x00040000, 0x00042000, 0x00044000, - 0x00046000, 0x00048000, 0x0004a000, 0x0004c000, 0x0004e000, 0x00050000, - 0x00052000, 0x00054000, 0x00056000, 0x00058000, 0x0005a000, 0x0005c000, - 0x0005e000, 0x00060000, 0x00062000, 0x00064000, 0x00066000, 0x00068000, - 0x0006a000, 0x0006c000, 0x0006e000, 0x00070000, 0x00072000, 0x00074000, - 0x00076000, 0x00078000, 0x0007a000, 0x0007c000, 0x0007e000, 0x00080000, - 0x00082000, 0x00084000, 0x00086000, 0x00088000, 0x0008a000, 0x0008c000, - 0x0008e000, 0x00090000, 0x00092000, 0x00094000, 0x00096000, 0x00098000, - 0x0009a000, 0x0009c000, 0x0009e000, 0x000a0000, 0x000a2000, 0x000a4000, - 0x000a6000, 0x000a8000, 0x000aa000, 0x000ac000, 0x000ae000, 0x000b0000, - 0x000b2000, 0x000b4000, 0x000b6000, 0x000b8000, 0x000ba000, 0x000bc000, - 0x000be000, 0x000c0000, 0x000c2000, 0x000c4000, 0x000c6000, 0x000c8000, - 0x000ca000, 0x000cc000, 0x000ce000, 0x000d0000, 0x000d2000, 0x000d4000, - 0x000d6000, 0x000d8000, 0x000da000, 0x000dc000, 0x000de000, 0x000e0000, - 0x000e2000, 0x000e4000, 0x000e6000, 0x000e8000, 0x000ea000, 0x000ec000, - 0x000ee000, 0x000f0000, 0x000f2000, 0x000f4000, 0x000f6000, 0x000f8000, - 0x000fa000, 0x000fc000, 0x000fe000, 0x00100000, 0x00102000, 0x00104000, - 0x00106000, 0x00108000, 0x0010a000, 0x0010c000, 0x0010e000, 0x00110000, - 0x00112000, 0x00114000, 0x00116000, 0x00118000, 0x0011a000, 0x0011c000, - 0x0011e000, 0x00120000, 0x00122000, 0x00124000, 0x00126000, 0x00128000, - 0x0012a000, 0x0012c000, 0x0012e000, 0x00130000, 0x00132000, 0x00134000, - 0x00136000, 0x00138000, 0x0013a000, 0x0013c000, 0x0013e000, 0x00140000, - 0x00142000, 0x00144000, 0x00146000, 0x00148000, 0x0014a000, 0x0014c000, - 0x0014e000, 0x00150000, 0x00152000, 0x00154000, 0x00156000, 0x00158000, - 0x0015a000, 0x0015c000, 0x0015e000, 0x00160000, 0x00162000, 0x00164000, - 0x00166000, 0x00168000, 0x0016a000, 0x0016c000, 0x0016e000, 0x00170000, - 0x00172000, 0x00174000, 0x00176000, 0x00178000, 0x0017a000, 0x0017c000, - 0x0017e000, 0x00180000, 0x00182000, 0x00184000, 0x00186000, 0x00188000, - 0x0018a000, 0x0018c000, 0x0018e000, 0x00190000, 0x00192000, 0x00194000, - 0x00196000, 0x00198000, 0x0019a000, 0x0019c000, 0x0019e000, 0x001a0000, - 0x001a2000, 0x001a4000, 0x001a6000, 0x001a8000, 0x001aa000, 0x001ac000, - 0x001ae000, 0x001b0000, 0x001b2000, 0x001b4000, 0x001b6000, 0x001b8000, - 0x001ba000, 0x001bc000, 0x001be000, 0x001c0000, 0x001c2000, 0x001c4000, - 0x001c6000, 0x001c8000, 0x001ca000, 0x001cc000, 0x001ce000, 0x001d0000, - 0x001d2000, 0x001d4000, 0x001d6000, 0x001d8000, 0x001da000, 0x001dc000, - 0x001de000, 0x001e0000, 0x001e2000, 0x001e4000, 0x001e6000, 0x001e8000, - 0x001ea000, 0x001ec000, 0x001ee000, 0x001f0000, 0x001f2000, 0x001f4000, - 0x001f6000, 0x001f8000, 0x001fa000, 0x001fc000, 0x001fe000, 0x00200000, - 0x00202000, 0x00204000, 0x00206000, 0x00208000, 0x0020a000, 0x0020c000, - 0x0020e000, 0x00210000, 0x00212000, 0x00214000, 0x00216000, 0x00218000, - 0x0021a000, 0x0021c000, 0x0021e000, 0x00220000, 0x00222000, 0x00224000, - 0x00226000, 0x00228000, 0x0022a000, 0x0022c000, 0x0022e000, 0x00230000, - 0x00232000, 0x00234000, 0x00236000, 0x00238000, 0x0023a000, 0x0023c000, - 0x0023e000, 0x00240000, 0x00242000, 0x00244000, 0x00246000, 0x00248000, - 0x0024a000, 0x0024c000, 0x0024e000, 0x00250000, 0x00252000, 0x00254000, - 0x00256000, 0x00258000, 0x0025a000, 0x0025c000, 0x0025e000, 0x00260000, - 0x00262000, 0x00264000, 0x00266000, 0x00268000, 0x0026a000, 0x0026c000, - 0x0026e000, 0x00270000, 0x00272000, 0x00274000, 0x00276000, 0x00278000, - 0x0027a000, 0x0027c000, 0x0027e000, 0x00280000, 0x00282000, 0x00284000, - 0x00286000, 0x00288000, 0x0028a000, 0x0028c000, 0x0028e000, 0x00290000, - 0x00292000, 0x00294000, 0x00296000, 0x00298000, 0x0029a000, 0x0029c000, - 0x0029e000, 0x002a0000, 0x002a2000, 0x002a4000, 0x002a6000, 0x002a8000, - 0x002aa000, 0x002ac000, 0x002ae000, 0x002b0000, 0x002b2000, 0x002b4000, - 0x002b6000, 0x002b8000, 0x002ba000, 0x002bc000, 0x002be000, 0x002c0000, - 0x002c2000, 0x002c4000, 0x002c6000, 0x002c8000, 0x002ca000, 0x002cc000, - 0x002ce000, 0x002d0000, 0x002d2000, 0x002d4000, 0x002d6000, 0x002d8000, - 0x002da000, 0x002dc000, 0x002de000, 0x002e0000, 0x002e2000, 0x002e4000, - 0x002e6000, 0x002e8000, 0x002ea000, 0x002ec000, 0x002ee000, 0x002f0000, - 0x002f2000, 0x002f4000, 0x002f6000, 0x002f8000, 0x002fa000, 0x002fc000, - 0x002fe000, 0x00300000, 0x00302000, 0x00304000, 0x00306000, 0x00308000, - 0x0030a000, 0x0030c000, 0x0030e000, 0x00310000, 0x00312000, 0x00314000, - 0x00316000, 0x00318000, 0x0031a000, 0x0031c000, 0x0031e000, 0x00320000, - 0x00322000, 0x00324000, 0x00326000, 0x00328000, 0x0032a000, 0x0032c000, - 0x0032e000, 0x00330000, 0x00332000, 0x00334000, 0x00336000, 0x00338000, - 0x0033a000, 0x0033c000, 0x0033e000, 0x00340000, 0x00342000, 0x00344000, - 0x00346000, 0x00348000, 0x0034a000, 0x0034c000, 0x0034e000, 0x00350000, - 0x00352000, 0x00354000, 0x00356000, 0x00358000, 0x0035a000, 0x0035c000, - 0x0035e000, 0x00360000, 0x00362000, 0x00364000, 0x00366000, 0x00368000, - 0x0036a000, 0x0036c000, 0x0036e000, 0x00370000, 0x00372000, 0x00374000, - 0x00376000, 0x00378000, 0x0037a000, 0x0037c000, 0x0037e000, 0x00380000, - 0x00382000, 0x00384000, 0x00386000, 0x00388000, 0x0038a000, 0x0038c000, - 0x0038e000, 0x00390000, 0x00392000, 0x00394000, 0x00396000, 0x00398000, - 0x0039a000, 0x0039c000, 0x0039e000, 0x003a0000, 0x003a2000, 0x003a4000, - 0x003a6000, 0x003a8000, 0x003aa000, 0x003ac000, 0x003ae000, 0x003b0000, - 0x003b2000, 0x003b4000, 0x003b6000, 0x003b8000, 0x003ba000, 0x003bc000, - 0x003be000, 0x003c0000, 0x003c2000, 0x003c4000, 0x003c6000, 0x003c8000, - 0x003ca000, 0x003cc000, 0x003ce000, 0x003d0000, 0x003d2000, 0x003d4000, - 0x003d6000, 0x003d8000, 0x003da000, 0x003dc000, 0x003de000, 0x003e0000, - 0x003e2000, 0x003e4000, 0x003e6000, 0x003e8000, 0x003ea000, 0x003ec000, - 0x003ee000, 0x003f0000, 0x003f2000, 0x003f4000, 0x003f6000, 0x003f8000, - 0x003fa000, 0x003fc000, 0x003fe000, 0x003fe001, 0x00000000, 0x000001ff, - 0x00000200, 0x00000001, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00007ff8, - 0x00000000, 0x00003500, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, - 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, - 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, - 0x00000003, 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, - 0xffffffff, 0x00000003, 0x00bebc20, 0xffffffff, 0x00000000, 0xffffffff, - 0x00000000, 0xffffffff, 0x00000003, 0x00bebc20, 0xffffffff, 0x00000000, - 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, 0x00bebc20, 0xffffffff, - 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000003, 0x00bebc20, - 0x00002000, 0x000040c0, 0x00006180, 0x00008240, 0x0000a300, 0x0000c3c0, - 0x0000e480, 0x00010540, 0x00012600, 0x000146c0, 0x00016780, 0x00018840, - 0x0001a900, 0x0001c9c0, 0x0001ea80, 0x00020b40, 0x00022c00, 0x00024cc0, - 0x00026d80, 0x00028e40, 0x0002af00, 0x0002cfc0, 0x0002f080, 0x00031140, - 0x00033200, 0x000352c0, 0x00037380, 0x00039440, 0x0003b500, 0x0003d5c0, - 0x0003f680, 0x00041740, 0x00043800, 0x000458c0, 0x00047980, 0x00049a40, - 0x00008000, 0x00010380, 0x00018700, 0x00020a80, 0x00028e00, 0x00031180, - 0x00039500, 0x00041880, 0x00049c00, 0x00051f80, 0x0005a300, 0x00062680, - 0x0006aa00, 0x00072d80, 0x0007b100, 0x00083480, 0x0008b800, 0x00093b80, - 0x0009bf00, 0x000a4280, 0x000ac600, 0x000b4980, 0x000bcd00, 0x000c5080, - 0x000cd400, 0x000d5780, 0x000ddb00, 0x00001900, 0x00000028, 0x00100000, - 0x00000000, 0x00000000, 0xffffffff, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x00000000, - 0x00007ff8, 0x00000000, 0x00001500, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x00000000, 0x00007ff8, 0x00000000, 0x00001500, 0x00001000, - 0x00002080, 0x00003100, 0x00004180, 0x00005200, 0x00006280, 0x00007300, - 0x00008380, 0x00009400, 0x0000a480, 0x0000b500, 0x0000c580, 0x0000d600, - 0x0000e680, 0x0000f700, 0x00010780, 0x00011800, 0x00012880, 0x00013900, - 0x00014980, 0x00015a00, 0x00016a80, 0x00017b00, 0x00018b80, 0x00019c00, - 0x0001ac80, 0x0001bd00, 0x0001cd80, 0x0001de00, 0x0001ee80, 0x0001ff00, - 0x10000000, 0x000028ad, 0x00000000, 0x00010001, 0x00350804, 0xccccccc5, - 0xffffffff, 0xffffffff, 0x7058103c, 0x00000000, 0xcccc0201, 0xcccccccc, - 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, - 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, 0xcccc0201, 0xcccccccc, - 0xcccc0201, 0xcccccccc, 0x00000000, 0xffffffff, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x00000000, 0x00007ff8, 0x00000000, 0x00003500, 0x000e0232, 0x011600d6, - 0x00100000, 0x00000000, 0x00720236, 0x012300f3, 0x00100000, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, 0x00000000, - 0x0000ffff, 0x00000000, 0xfffffff3, 0x320fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x30efffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, - 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, - 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, - 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0010cf3c, 0xcdcdcdcd, 0xfffffff7, 0x31efffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x302fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, - 0xfffffff3, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, - 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, - 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, - 0xfffffff7, 0x30efffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x304fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x31efffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, - 0xfffffff1, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, - 0x0c30c305, 0xc30c30c3, 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, - 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x056fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, - 0xfffffff5, 0x310fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0040cf3c, 0xcdcdcdcd, 0xfffffff3, 0x320fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x310fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, - 0xfffffff6, 0x305fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0002cf3c, 0xcdcdcdcd, 0xfffff406, 0x1cbfffff, 0x0c30c305, 0xc30c30c3, - 0xcf300014, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, - 0xffffff8a, 0x042fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cc000, 0xf3cf3cf3, - 0x0010cf3c, 0xcdcdcdcd, 0xffffff97, 0x05cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cc000, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xfffffff5, 0x310fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, - 0xfffffff3, 0x316fffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0000cf3c, 0xcdcdcdcd, 0xfffffff1, 0x302fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xfffffff6, 0x305fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, - 0xfffffff6, 0x30bfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf314, 0xf3cf3cf3, - 0x0004cf3c, 0xcdcdcdcd, 0xfffffff2, 0x304fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xfffffffa, 0x302fffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, - 0xfffffff7, 0x31cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf300, 0xf3cf3cf3, - 0x0020cf3c, 0xcdcdcdcd, 0xfffffff0, 0x307fffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf300, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0040cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0002cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0010cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0000cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0001cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0002cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0004cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0008cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, - 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, 0x0010cf3c, 0xcdcdcdcd, - 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, 0xcf3cf3cc, 0xf3cf3cf3, - 0x0020cf3c, 0xcdcdcdcd, 0xffffffff, 0x30cfffff, 0x0c30c30c, 0xc30c30c3, - 0xcf3cf3cc, 0xf3cf3cf3, 0x0040cf3c, 0xcdcdcdcd, 0x00100000, 0x00070100, - 0x00028170, 0x000b8198, 0x00020250, 0x00010270, 0x000f0280, 0x00010370, - 0x00080000, 0x00080080, 0x00028100, 0x000b8128, 0x000201e0, 0x00010200, - 0x00070210, 0x00020280, 0x000f0000, 0x000800f0, 0x00028170, 0x000b8198, - 0x00020250, 0x00010270, 0x000b8280, 0x00080338, 0x00100000, 0x00080100, - 0x00028180, 0x000b81a8, 0x00020260, 0x00018280, 0x000e8298, 0x00080380, - 0x000b0000, 0x000100b0, 0x000280c0, 0x000580e8, 0x00020140, 0x00010160, - 0x000e0170, 0x00038250, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, - 0x00002000, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x00002000, - 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0x04002000 -}; - -static const u32 tsem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x19d9458a, 0x1138fc18, - 0x5980a1fc, 0xd8181998, 0x88039880, 0x81b8803d, 0x91a18191, 0xdafd7891, - 0xbf760862, 0x6ec30330, 0x0211e620, 0x1082239a, 0xf354029f, 0x0f5fc806, - 0x6512b315, 0x3a263860, 0x06a77ef0, 0x298d2ade, 0xc1124536, 0x1e4586de, - 0x93476f19, 0xca8922ff, 0xff4041df, 0x65296340, 0x229dbe54, 0x04a65e84, - 0xe4d1a5a1, 0xd7f2a1ed, 0x5192fea1, 0x0dee6ec6, 0xf8003ca8, 0x6065495c, - 0x00606549 -}; - -static const u32 tsem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7dedff00, 0xd554780b, 0x733ef0b5, 0x49999cce, - 0x424e4cce, 0x4c22f212, 0x21a08812, 0x8a80af0c, 0x2201277f, 0x282039f5, - 0x4201d458, 0xd4837908, 0xcdedaf4b, 0x11102484, 0x0547f435, 0x5088768b, - 0x340da2d1, 0x0ec160d2, 0x6d7b1420, 0xc0faf06f, 0x480bf5ea, 0xb12f3141, - 0xcbc57e20, 0xe7dad6bf, 0x264ce664, 0xafdbd880, 0xb4fdffff, 0xece7d9b8, - 0xebdaf7b3, 0x7b5ad7b5, 0x75923ded, 0xc7bf9302, 0x03fc45d8, 0x8c4d4fe5, - 0xf2c109b1, 0x80f66667, 0xc9b18727, 0x473afebd, 0x6d55633c, 0x9da23b19, - 0x99ec258c, 0x50281421, 0x2c23d5fe, 0xbfdf8250, 0xf097c365, 0x4219b6ff, - 0xd0977c3e, 0xc3e611e9, 0x02d5e4fb, 0x933a876b, 0xea0c319c, 0x4b19b98c, - 0x126b2c64, 0x4b223fa3, 0xe0ff828d, 0x8f392573, 0x27fc34b1, 0x61467574, - 0xc678c0ae, 0x5c531e32, 0x38a9d0d4, 0x843f7815, 0xbcd2c67f, 0x0731b725, - 0xbc03cf63, 0xbcf071c9, 0x61de3a5a, 0xc22eefe5, 0x3af3a1df, 0xae58cd6a, - 0x32773e30, 0x416589a7, 0xf3e33ebf, 0x3d6346ac, 0x4fe3d99b, 0xec3fc346, - 0x8c517ecc, 0xb1138f30, 0xcb3c018c, 0x632f0e54, 0x5467b2bd, 0x6a9b1f10, - 0x2c32a258, 0x852f0f58, 0x56338765, 0xed975e03, 0xf8165c16, 0x2f6c39fe, - 0xbed7e631, 0x15ead66b, 0xa362593e, 0xb50404a1, 0x67eff4e4, 0x11bfcb11, - 0x2b30fef1, 0xea4ab2a0, 0xaf805595, 0xfb765aaa, 0x67edfe95, 0x54e88933, - 0x5bf6b929, 0x5adefc61, 0xf1866ae6, 0x02d59997, 0x91fb2fac, 0x7a83e5d3, - 0x21476366, 0x36d0fa83, 0xc1198981, 0x9e00afef, 0x007f91db, 0xa52b2a1e, - 0x740642de, 0xb02bddec, 0x871c0ce6, 0x776cbbf7, 0x0c65f306, 0x6658e70c, - 0x32e73826, 0x74893a41, 0xd2073071, 0xf324bcc1, 0xcea84289, 0xb0f3dc54, - 0x9de29f7f, 0xe7f4ed87, 0x38e60b49, 0xf25700bd, 0x57a06650, 0x9d3ab5b1, - 0xea563265, 0xbe442969, 0x8decb538, 0x9e025855, 0xf7c02413, 0x08a78b7c, - 0x5798a9fb, 0xa780cd9d, 0x8d1859e6, 0xff2db43f, 0x0cf80933, 0xc4c5f3ba, - 0x76313f21, 0xf04f843c, 0x5a11f1cf, 0xde981c5d, 0xb08b2b97, 0x05f1091f, - 0x1f011772, 0x26a0423f, 0x544d28e0, 0x29fc573a, 0xd0a0d86b, 0xc3595bfa, - 0xe50069c6, 0x3f0cbc11, 0x0843ac61, 0x1cbd4be5, 0xb0ff3bba, 0x3c303b94, - 0x04f3d3ff, 0xab7e1274, 0x1fc8b700, 0xbfd97615, 0xca61f812, 0xf7c0e6ab, - 0x362a3f80, 0xd40b7e0b, 0xe8dbaf4d, 0x5e26f77d, 0x3765d80f, 0x16d74ff2, - 0xbdf00ba8, 0x1bf1fda5, 0x155ebf91, 0x3b763359, 0xfa84ca22, 0x3b06a4e5, - 0xc0750f1b, 0x578db147, 0xbbef362b, 0x692fbf1f, 0xf41b30b3, 0xf17bb157, - 0x7d42371d, 0xc33361f1, 0x6b5b1526, 0x2fa814e5, 0x582d0bf1, 0xf0e029ef, - 0xfe8976f9, 0xc7bed0ad, 0x1b389ed1, 0xc6ba73e8, 0x63329cca, 0xc4f6f675, - 0xa567c059, 0xf8851dfe, 0xc176e95d, 0xf29f6885, 0xc943d6ea, 0xb917af38, - 0x8b6d977c, 0x7f1d4e66, 0xab64f7f0, 0xbc1ef818, 0x64f3065f, 0xd662efd0, - 0xb07a8854, 0xd93aeb62, 0xebe20f69, 0xe34a8d74, 0x8bdfc9f4, 0x577c0e30, - 0xc2e08af9, 0x989a5629, 0x7bb0e517, 0xf3ce6db7, 0x56afce0a, 0xbce3b6ce, - 0x6ed8cb56, 0x2efe7fb1, 0xfea5cd54, 0xbc2172cd, 0x59b4dd2f, 0xdb910e2e, - 0x8c836db2, 0x1ac86d70, 0xd7208dec, 0xd7807841, 0x52f583b2, 0x0fa803d4, - 0x233cbf25, 0x852acf84, 0xb2cbe258, 0x1a73226d, 0xddd388f8, 0x13fc2ef7, - 0x6bdbe5f0, 0x74eabc27, 0x1aa7d3eb, 0x1aa8cedd, 0xbcdea51d, 0xf8f81119, - 0xc003a471, 0x827884d3, 0x9f06ad72, 0x97cb3263, 0x9b877fa0, 0x3cbb02a9, - 0xd999365f, 0xf563067c, 0xd2dd07b0, 0xd99750f5, 0xf582e652, 0x7bb1fa50, - 0x0493d42a, 0x9f3867ef, 0xc25bc17a, 0x2496abd7, 0x9579e00f, 0xfce0e6c0, - 0x30d0218f, 0xc0c955af, 0xa6f7809f, 0x8bcf7969, 0x3c7b0682, 0xb17f8bd6, - 0x39fa8326, 0xa198fd43, 0xf7cbac9f, 0x324e16a3, 0x9616a3f4, 0x8dfcfde8, - 0x595db1fa, 0x37854d3f, 0x2c29e118, 0x0491fbd5, 0xbf6f5768, 0x37a979b2, - 0x73c2364f, 0x13f53973, 0xbcc5d53b, 0x1ae7ae0a, 0xb776b03f, 0xed95ef08, - 0xb0d763b1, 0x5028be50, 0x0edb8005, 0x17ca1252, 0x0ca29331, 0x8eeb187c, - 0x27a1d433, 0x4175e4f5, 0x958813fd, 0x45397c69, 0x9f90bd26, 0x43faa562, - 0x85e90a29, 0x5ef06e87, 0x8e20eb83, 0x2ea192cd, 0x11ab477b, 0x14e01af8, - 0x60961258, 0x7ff52417, 0xf1ccdabf, 0x217a9050, 0x5f7c18fb, 0x8ecdea65, - 0xa635fa85, 0x6f116bfc, 0xe5eb812e, 0x63559128, 0x230b28bb, 0x233ab4fd, - 0x085f79ef, 0x00871a9e, 0xbf6085fd, 0x126f668d, 0xdaf8d7f2, 0xc0127c67, - 0xcc086ab7, 0x12ba0527, 0x60f8099e, 0xa43d5a3d, 0x69f10938, 0x43be4191, - 0xfc6197c7, 0x06ff1a1c, 0xc71ba3c4, 0xbe3fe84f, 0x61927325, 0x897a6b7c, - 0x0cab7c61, 0x4fbf03e3, 0xc6d66dad, 0xc0ddfc07, 0x99a134d8, 0x97a4b7c6, - 0x65abf8d0, 0x3f186256, 0x5bfc6faa, 0x819efe70, 0x83799fe6, 0xa5e9fe71, - 0x7ccbf9c6, 0x5f6ab3fe, 0xa28fc6d2, 0x5e16cff9, 0x2f4ff3e2, 0xf0b7f3e5, - 0x77c6fb7e, 0x5effe1f4, 0x8077bf9c, 0x93592df1, 0x5a1ff38d, 0x85bf9c6e, - 0xbb545f8f, 0xa15f1b53, 0x3b0917f1, 0x9687fcf9, 0xc5b2f8d3, 0x923e42eb, - 0xfdaaa353, 0x81a44f68, 0x1d260c40, 0x0472a6e5, 0x1fa00518, 0x04990a86, - 0x9c5143c7, 0x0145ceef, 0x7d4129bf, 0x5120fcc7, 0x352acfa0, 0x9edb2f9e, - 0xa59ea32f, 0x376889f7, 0x6d453ff1, 0x6c37ad22, 0x1c3fc5bd, 0x136eede0, - 0x5a2f587d, 0xa45f937f, 0xe5db8ef5, 0xf005c660, 0x1c9e5ff9, 0xaf3a1cd5, - 0x935172f0, 0x418764f9, 0xbe3c388e, 0x1aa23602, 0x26476be0, 0x9fac1098, - 0xc60a3d04, 0x7a0e3b2f, 0x6653cb14, 0x009c8f6e, 0x50e4cb3d, 0xf6e5a9b9, - 0x93bd8f88, 0x5bbaf303, 0xc4a4ff83, 0xb9727df1, 0x9ffc47e0, 0x4654b75b, - 0x09a8b4fd, 0x7910e98c, 0xd4e8d2af, 0x6fe2dbbb, 0x4e9f0816, 0x243dcfc4, - 0x97fd8c8a, 0xde2fd766, 0xddf0c830, 0x486fe63c, 0xd70bf682, 0xc2a21fce, - 0xc7307ffc, 0x53ed1632, 0x13548490, 0x354b31c9, 0xa7316f81, 0x15399d75, - 0x31ccf72a, 0xb9faec1b, 0x07fd635e, 0xb77ac625, 0xa1366fd9, 0x6044b1bd, - 0xfbdfa19b, 0xf5ef8daa, 0x71093671, 0x78daae9c, 0x78722777, 0x2c72c3ef, - 0xae89563e, 0x5bfcabf7, 0x87aa9e1d, 0xeb402ccd, 0x43024765, 0xc812fa3a, - 0x7caaf35e, 0xdef0e1de, 0x3dbab66f, 0x3ffdcf00, 0xe19f0912, 0x1ebc77f0, - 0x1d8136ed, 0x4be1b1d7, 0xe1b7da33, 0xff8709f3, 0xf3e11581, 0xf7d46551, - 0xcfe17df3, 0xf3849f39, 0xfe5b5553, 0xed2113a0, 0x3fbe5a2a, 0x7f0844e8, - 0x619b6d95, 0xcff12fa8, 0xbc5fb435, 0xfde1be61, 0x8625a6a2, 0x971b0bf7, - 0x7df3ea1a, 0x7fb4323f, 0xe1ad4560, 0x8fd57dfd, 0xa0ffde18, 0x3ea19d64, - 0xd0d1bbd7, 0x9b399efe, 0xaf4def0d, 0xe513bc8f, 0x915deea8, 0x5671bae1, - 0xda38f939, 0xc9156783, 0xb4f8f485, 0xe0e48926, 0xca938d74, 0x5671b6ee, - 0xc583d72f, 0x5e9c4c0c, 0x71af9ce1, 0x4665ea32, 0xc2aff3fa, 0xea0f9f05, - 0x849c137f, 0xcc83713f, 0x02c2c002, 0xe3e3eb8b, 0x7de4315e, 0x6fde65c7, - 0xd71f4100, 0x11d8bdff, 0xf35579f9, 0x046aa1fc, 0xb72821ff, 0xb9d7152c, - 0x0f7d6d1e, 0x302e5f7f, 0xc673e84f, 0xd79c9256, 0xb94ceb69, 0xf941f5cc, - 0xf402e4ce, 0x40e5cbbf, 0xc6a5f576, 0xa2a4016b, 0x3ceb449e, 0xa401f901, - 0x592fc0c0, 0xdceef906, 0x955c1227, 0xaf4013a8, 0xc19e63ae, 0x8133d426, - 0x8d77e903, 0x49dc3842, 0xa04b6f54, 0x66b3bd75, 0x1213a0fa, 0xe543c7d2, - 0xa87335a7, 0xa5e3593c, 0x094d44f2, 0xaa6bc795, 0x59a8eca9, 0x35c7e541, - 0xaa3f2a3e, 0xcff2a469, 0x1e544d35, 0xe540d9ad, 0x2a7e357b, 0x54dc6bbb, - 0xba2bf9f6, 0xecd78dfe, 0x80afcd55, 0x67ea8795, 0x43d4b9b4, 0x739276db, - 0xf9ca1257, 0x365ce519, 0x8e67e3da, 0x31996382, 0xf9c2be30, 0xba3a606d, - 0xf6295ec9, 0xf5c7fd03, 0xe28b6f7f, 0xd899b274, 0xd9a67074, 0xe17fc323, - 0x7543905a, 0x16065909, 0x7b0cd724, 0xed617e84, 0x8e5d7a43, 0x9bddcc4e, - 0x71e8133b, 0xe5bf99f2, 0xda75bf61, 0x407517fa, 0x059875a4, 0xbd21779e, - 0xeb46f042, 0x9aabef5a, 0xfe0cbfbe, 0xd7f0faba, 0xfbfe8e9e, 0xfea54141, - 0x985ab4cf, 0x13dc7884, 0x67e607ed, 0xef3f0e67, 0x965c7940, 0x444f5264, - 0x565e83c0, 0x4aa864b4, 0x66d3fae8, 0x12699fac, 0x7ad0b7a6, 0x35998cec, - 0x554af90a, 0xfa430c4f, 0xf7a95127, 0x56492cb3, 0x9ebc804f, 0xc31596de, - 0x5f3f6fd7, 0x12c7b707, 0x485f82bf, 0xf0deffed, 0x0e8fd40c, 0xecad630f, - 0x03ea2b13, 0xedf59778, 0xfd2672fd, 0x6c57e295, 0xda1cf98f, 0x7bf8160b, - 0x1207e291, 0xab7ef5d5, 0x659f445a, 0x6edf3e34, 0x73be0f18, 0xc5f73eea, - 0xadf14bcc, 0xc4864ec4, 0xf169d611, 0x366db2c6, 0xc4aeb8d5, 0x6d55ea1a, - 0x9d61aac9, 0xfc807fc1, 0x42416ab3, 0xb8d729be, 0x1a5247a8, 0xdcaf8005, - 0xab7ea4e4, 0xc2aede04, 0xe17b21da, 0xa72b5751, 0x9df040db, 0x94ec39ae, - 0xac4bde40, 0x7c0201e0, 0xa7232d25, 0x6aeb9ea2, 0x7b444bad, 0xf33c4cb0, - 0xf7c22790, 0x8d024d3b, 0xee6fc4b7, 0x1aa3ae35, 0x57e8307f, 0x167e4e7f, - 0xd4864e53, 0xcedc4d3b, 0x80f7ef0e, 0xf0e5efd6, 0x48fdb953, 0xfece8de1, - 0xfb6caa78, 0x1c92f642, 0x82f2ffc1, 0x57f1d278, 0x401cf26e, 0xedba5a7d, - 0x9fa3d918, 0x0fd97d9a, 0xf53f425f, 0x44929f9f, 0x5e7d5271, 0x6129303e, - 0x7c5a059c, 0x9ef7f817, 0xfd3d610f, 0x6ccddfec, 0x2ec7c00d, 0x6f782b40, - 0x13335fd6, 0xa17d4133, 0x5ad05b56, 0xcfdd7146, 0x2a8edc4c, 0xd1071e62, - 0xa1e53581, 0x4cc5d91d, 0x5d4f11d3, 0xb8c76dec, 0x329c3a10, 0x1667a4c9, - 0x18ed1a36, 0xf50d7fb0, 0xf58c1bc5, 0x11333662, 0x7af149f5, 0x340bf333, - 0xf7fbc33f, 0x7fe12a4d, 0x855eab31, 0xf9a4aaeb, 0x26540b23, 0x157c02a5, - 0x6f3679bf, 0x4c5fc63e, 0xe3d10fdc, 0x38e24b23, 0x7ef1a5fc, 0x3fef0dd9, - 0xf7771d69, 0x8b06488d, 0x89c6157f, 0x6d730c58, 0xfbf1fd65, 0x870fe16d, - 0xfbaf5f57, 0x383469c5, 0xdb826dc4, 0x2f7f811f, 0xeba67c68, 0xd5445beb, - 0x8ddc17e0, 0x21bf10f5, 0xb2e2d446, 0xee911322, 0x67d5aa5d, 0x14f7a18a, - 0xb4edf7b7, 0xde80eab8, 0x0679373f, 0x4ec81389, 0xed2165c8, 0xd2f26e7e, - 0xade14ef3, 0x995bb462, 0x3b45c814, 0xe218d614, 0x07e35953, 0x8b91ca31, - 0x833b66f1, 0x6fe81475, 0x9fa0f841, 0xdb92f655, 0xbbc62e58, 0xbfa1de41, - 0x87851cc7, 0x94dba805, 0x59fd8656, 0x7cf18c92, 0xaf58d39b, 0x1d207fc2, - 0x3f8a3046, 0xc2908f45, 0xa86018f0, 0xe32eed0f, 0x84e851f3, 0x201fdd91, - 0x8b10763e, 0x02556943, 0x26cf8c22, 0xfe7d9d49, 0x7bfa2656, 0x2f8a7e1c, - 0x2ae5fb40, 0xc5a95f6f, 0x507f97cf, 0x12ee3830, 0x3ceaa8fa, 0x21419068, - 0x7fbe3d75, 0x71fe625e, 0x3a6f41df, 0xd10d5561, 0xde4d739b, 0xd40f4869, - 0x009f0893, 0x760d78e3, 0x2a1a9a60, 0xf8c20be7, 0x88e1aae3, 0x5dfd0667, - 0x2ddef26e, 0xe387f426, 0xea4ffbaa, 0x4882ffd7, 0xfeeabcf3, 0xbfebf587, - 0x15ff5232, 0x977979bf, 0xf4a9f80f, 0x803a4f57, 0x5267d999, 0xe80ba253, - 0xc1b5be5e, 0xa9f97281, 0x5d2073e4, 0xd38bf33f, 0x16e7c923, 0xb74f9751, - 0xff11e422, 0x7e9d1f10, 0xd03bd1e9, 0xd5b73aae, 0x607c52ac, 0x0160259b, - 0x5d6caca6, 0x9b63e5c2, 0xafaf18e5, 0xb3f902fe, 0x2fa8cdaa, 0x32785f4a, - 0x40cde311, 0x0e7fcd49, 0xb9507f90, 0x68852fe5, 0x5eb15577, 0xdfe17bd2, - 0xe3e7f8e1, 0x2f981ec8, 0xaf7ff4c7, 0x6955f3ef, 0x7d6aa978, 0x84910bf4, - 0xcdfc83a5, 0x9a25f6f0, 0x68a4ffbd, 0xdf38a78f, 0xf9113644, 0xf307c74c, - 0xeebf7b73, 0x8f73a7c5, 0x5b9d3c01, 0xe421ddfe, 0xd727f284, 0x165a677b, - 0xe735fcfe, 0x0dd4f2c0, 0xaed4317a, 0x6767d7d6, 0xeca7e69b, 0x39b965e1, - 0xb03f40e0, 0xe5d9b37c, 0xfcbeba43, 0xc19e2ffc, 0x1607ccb8, 0xbfe870d7, - 0xef83e5ec, 0xb2f500dd, 0xdbf8e61d, 0x211434f8, 0x2a974831, 0x6c62bbf8, - 0xbfa50e90, 0x473b283e, 0x8e3fe7f1, 0x6ca3d20b, 0x8d993ec7, 0x298f8fea, - 0x0ee4fb2d, 0x5a5d0225, 0x3fa2158e, 0x57e2f751, 0xcfafea32, 0xe0d8175e, - 0xdcf8088c, 0x62ec907c, 0x51d113c4, 0xdd1f53a3, 0x0157dac2, 0xeabf505d, - 0xff7f0a74, 0xc7fe9a2f, 0xc4399cfe, 0x86bcafcf, 0xb67f28fb, 0x25fe70b8, - 0xc0e83caf, 0xaa929c79, 0xdb3f5f39, 0x7186e890, 0x44becc4b, 0xbcfe4a95, - 0x121fb9e4, 0xf23e2dbf, 0x7f8a44c3, 0x89b27730, 0x325f056c, 0xa6d16fce, - 0x62bf34d9, 0x2bbe25e6, 0xe0f45679, 0x8959e0fe, 0x4111df4d, 0xae24522e, - 0x5b354f8f, 0xa7654d70, 0x7dc0e170, 0xff45b785, 0x2dff8a56, 0x0fcaf8a5, - 0xb620fdf5, 0xad67ea8c, 0x885f4e9c, 0xac1abefa, 0xbafca13c, 0xd23b7565, - 0xf710f4e7, 0x571b8c60, 0xe1a7c931, 0xfd08b843, 0x0da6478a, 0x4e61f4e6, - 0x0efb4f29, 0x7c14fdf4, 0xcddbed8e, 0xe1ae5b6e, 0x2331763b, 0x6d72fe38, - 0x0a3b807c, 0x8953d5ed, 0x9845ff60, 0xafa4a15f, 0x85576037, 0x7c8857f0, - 0xf2df7973, 0x5d6f9708, 0xa633fdde, 0xbebffbe3, 0xbf07e5c3, 0xe0057b43, - 0xf7a60c0a, 0xa40966fb, 0x102c2c0f, 0x98b7ae49, 0xbe36b935, 0xe004f9d7, - 0xeddd7096, 0x3fec17e3, 0x764ff08e, 0xf87af16c, 0x565f442e, 0xfe8e78e1, - 0xbb72e9fd, 0x04ff9358, 0x6cff28c9, 0x81fb9713, 0x8f1f09fd, 0xbffd984b, - 0x15e50678, 0xaff713e4, 0x7b365fcb, 0x6f9fde70, 0xbddef03f, 0xb79fa720, - 0xd46a72e8, 0x5a72e19f, 0x8b0273b2, 0x639fa724, 0x3924421a, 0xe511e785, - 0x3e20e954, 0x4fe947fe, 0x85377f1d, 0x87d74fe1, 0x5c31e103, 0x7459fe1f, - 0xf087d446, 0xd7961de7, 0xbe74ff9f, 0xf4adf9d3, 0x29431597, 0xa5f3a63e, - 0x7c7d77ce, 0xbf5df3a9, 0x7f01a378, 0x182defe1, 0x3cb80183, 0x4714cdbb, - 0xf7c3df28, 0x43bbe17f, 0x4f09e3a9, 0x58c65a6e, 0xf8d4a1d3, 0xac3fbad0, - 0xded612de, 0x84f7561d, 0xd586f7b5, 0xcbed0dab, 0x3cc80edb, 0x686025af, - 0x8678ae27, 0x1228327d, 0x5fb9fabf, 0xec85fada, 0x7a50be43, 0x4af37be9, - 0x3c63b3e6, 0xf148af7c, 0xf1c01e91, 0x67a7182a, 0xf31f867b, 0x3c6c1a24, - 0xf6a3d4ee, 0x6c5ed03a, 0xdef5e588, 0xea157904, 0xaf79fd3d, 0x7af5c78d, - 0xd88ebd3c, 0xd8edfb10, 0x76f4911e, 0x8f4d9f87, 0x8ac267e4, 0xc1d47242, - 0xe3cf7a06, 0x2544d3fd, 0x5fc6057d, 0x8617449a, 0xef6a8a74, 0x419e6071, - 0x3bac9ecf, 0x45f3c0e7, 0x8db48a6f, 0x7b7683d8, 0x2dc7920c, 0x77f88725, - 0x53df329f, 0xbf7e3193, 0x4579fb87, 0x11ecc36b, 0xa9f896b6, 0xa32e5958, - 0xecbf053e, 0x82ff71b8, 0xd6a945cb, 0xe326c95f, 0xdc7bfd7b, 0xbdfb45c1, - 0xbdf18b74, 0x34078b57, 0x863272eb, 0x71fcd18d, 0xf4d28f1e, 0xe73134f2, - 0x8f4039ce, 0xc322c39e, 0x7b33fbfd, 0x99c7a244, 0x9ebf7ced, 0x23d7f6e2, - 0x3e92f77f, 0x89d4f1d4, 0xac0f24f2, 0xfd5f3aaf, 0x9187bcaf, 0x987d766f, - 0x3b2833fb, 0xfd907d77, 0xe6ffac5b, 0x590ff4fd, 0x5e53f6ff, 0x493ed1b7, - 0xe276ebcf, 0x7fbd9ef7, 0xeb187f4c, 0x9f142dbb, 0xabfd79ee, 0x9e9fe45c, - 0xd4129695, 0x80433d77, 0xec1f68fe, 0x83b72afd, 0xa27ad7d6, 0x99251fdb, - 0xfe7b47db, 0x8f10b1f6, 0xed0acc25, 0x49a3d786, 0xb35eaa9e, 0x67ad3c51, - 0xa17957ef, 0x9d77ff76, 0x7fb6a54f, 0x736763d9, 0xb17c2276, 0xeaa7df7c, - 0x5f3fd7b7, 0xad17f98b, 0xf085e4fb, 0xbeefca7e, 0xda3d45c9, 0x43db93b3, - 0xe78ee6dd, 0x68ee7f70, 0x6695dcfd, 0x0a3773c0, 0x9bac0a55, 0xa014cf0d, - 0xcbc7f4dc, 0xbc271437, 0xfcf47c52, 0xc10f835f, 0xdd9df5cd, 0xde70156f, - 0x21fc7f5f, 0x2dd785ea, 0x7cfa97c4, 0x25a96f3f, 0xf372e57b, 0x9c799876, - 0x799dffe4, 0x992b810b, 0x3ff328f7, 0x2d7fbd37, 0xe12e8939, 0xcf9fd072, - 0xf5443ef7, 0x822eed97, 0xfdf90af7, 0xf9f27ff6, 0xefba6b7f, 0x2e3bba04, - 0x7ff2ef3f, 0x4c0f79f2, 0xd7ef37f7, 0x7e62aee8, 0xbeefd54b, 0xadbef821, - 0x4ffb5b9e, 0xcd03ef2e, 0xd7ebb75f, 0x994d5c98, 0xaf439f18, 0xc569d601, - 0xc311b33e, 0xcc466b85, 0x14ced154, 0xf52bf6c3, 0xfb99af72, 0x5bee224d, - 0x086f9c62, 0xcd31f38f, 0x3d2da28f, 0x8a525a18, 0x94958ec9, 0x96bedc55, - 0xc06eed5c, 0x176b9acb, 0x887728b8, 0xc5ea3d8d, 0x1764da7a, 0xfcc3afc5, - 0xb9817ac9, 0xa56fb005, 0x8c396f6b, 0x84798dfe, 0xa5c96029, 0xab9618f2, - 0x59a4b8b5, 0x8f7e0d95, 0xdbac6392, 0x45bac69c, 0x38cacfeb, 0xe624d6fc, - 0x38b4f8c7, 0x798abf72, 0x8918e26d, 0xb1b75009, 0x17fa1f26, 0xf7e32496, - 0x1ec0311b, 0x5abdcf12, 0xe1f6f63c, 0x1bbb6c71, 0x44d238f1, 0x2e4a6b71, - 0xfcb8bc25, 0x8d9e786b, 0x55d788d5, 0x094f88ed, 0x7f6e5ffd, 0x34ccdf91, - 0xbad2597f, 0xdc984690, 0xcd3b6336, 0x9d2cbe4f, 0xcbd25d38, 0x332d3a35, - 0x43a745d0, 0xe818fa04, 0xdbf9e3a2, 0x2e9c27d2, 0x6fdff8e1, 0x07fe1276, - 0x974e97a2, 0x50cdc534, 0xbf9acd5e, 0x49fd1530, 0x1879a7ac, 0xfe6b33ed, - 0x66ef1482, 0xea93a43e, 0xf42f4862, 0xb7e002db, 0xf3fb7efd, 0x7aea2714, - 0x081dd8e9, 0x456fd94f, 0x75fc0566, 0x00b3b76f, 0x65f92f7e, 0x5b4b43f4, - 0x33fb8a45, 0x57779029, 0x6eafbec8, 0xcafd97f7, 0xdd29f34e, 0x06dff169, - 0xfaee97df, 0xb0ec9724, 0xd7e4bd95, 0x38125ef8, 0xb91d7ddd, 0x2a5bafb8, - 0x9c23ff71, 0x9e65625f, 0x3bb9d027, 0x6dc60e7a, 0xdf3c6d84, 0x1ee5b4b6, - 0x7f90c5b3, 0x91dbd666, 0x28bdf05e, 0xc213be50, 0xa9e79a17, 0x2f9d1dfb, - 0x36be1c0a, 0x76f31fb3, 0xe8edb74b, 0xe953f8c6, 0xc30b8b51, 0xbedb55d2, - 0x298dfda0, 0xd1d97abf, 0x68b6fe41, 0xf3f43f88, 0xc489b7fb, 0x15ad951f, - 0x9d4087e4, 0x25b2a2f8, 0x72ebfc72, 0xafd969fe, 0x01f2eef6, 0xfd7ecb0a, - 0x5be30382, 0x3ab7dba7, 0x76dfffc8, 0x3f5bb8e9, 0x91e5bf3f, 0xa7f9fa4b, - 0xbfe01ff1, 0xc58720dc, 0x220db649, 0xcbe0047f, 0xadef948b, 0xcbd95bf3, - 0x38c39f67, 0xcfcee774, 0xcb78439f, 0xe7cbfbff, 0xaf609fd0, 0x88add4db, - 0xa5de9797, 0xddfe9e38, 0x9dc7992c, 0x817c5fbb, 0x1fdd9fe2, 0x7f01df80, - 0x4a9ef7ba, 0x7bb27f47, 0x1889d7c7, 0x77be592f, 0xef9c60da, 0x0ca757f2, - 0x88f41166, 0xfadf225e, 0x1afe20af, 0xad03af4e, 0xe9efc807, 0xdfa37a02, - 0x69b717d9, 0x3071e0a9, 0xd9af16a7, 0xddce391e, 0x7ad33e2f, 0x8d379dd7, - 0x72ecd2c7, 0xd3882bb2, 0x1c7403bc, 0xdbf4057d, 0x7fe688fe, 0x175fa646, - 0xb4e803fe, 0x677e8c2c, 0xfcfd175b, 0x3ad77c19, 0x4d38c068, 0xa6f00ae0, - 0x27bfd1c7, 0xa3227fbb, 0x25fced7c, 0x6e90c5c5, 0xbb44c1b7, 0x8e9b3e5f, - 0x9a9f0ffb, 0xe7e7ef7b, 0xc62a2c32, 0xbef74a1b, 0xfdd3f24f, 0x538a11ea, - 0xdd9e2d33, 0xf0fefacd, 0x5396a3f8, 0xcec5b559, 0xfe1a3be3, 0x74e3fe31, - 0xce2d73d0, 0x8f58f9c3, 0xf7140cff, 0xde799569, 0xafdf1e88, 0x16a1f2d8, - 0x4bd2094f, 0x3a748498, 0x08fdc976, 0xe22a0f1d, 0x1c686261, 0xad7c7233, - 0xd1adde2f, 0xf187e90b, 0x2538becb, 0x6e30d3d4, 0x67de17e5, 0xf741f411, - 0xecff1e66, 0xa3ce4736, 0xbf9ae3d2, 0xff53970a, 0x2f33c595, 0xc5b7ff07, - 0x52765f8f, 0xea78e1bf, 0x8f5910bc, 0x75f32dbf, 0xc5f7aaff, 0xbe4305ca, - 0x7bc9b941, 0xa2b1f904, 0xcfcc98f5, 0x52f3f0a5, 0xb53b7cfa, 0x97ced1bc, - 0xad778a44, 0x7a40396a, 0xe85f5c3c, 0xf0e1a6fb, 0xade0d09e, 0x44ebe36c, - 0x5fbb4ee7, 0xf73a7e81, 0xae7e26ef, 0xe28c7edc, 0xfdb6876d, 0x5908ee5a, - 0xf09d7157, 0xf9dfc087, 0x1e5cbeca, 0xec79e5b7, 0xd19ce3e1, 0x9ed561f4, - 0x6d54e3c8, 0x4e30c2ff, 0xe645af99, 0xc7a5fdeb, 0xefb92d3b, 0xb74efec1, - 0x79e6199b, 0xa7116e9e, 0xf5173a47, 0xea6eb6ae, 0xbd707ee7, 0x23fd7ca4, - 0xf8cc5cfc, 0x1f28a3b7, 0xe991f97e, 0x63c4c61f, 0xfe878409, 0x9f396b5a, - 0x9dc4feb6, 0x3d6ef48a, 0xeb88af72, 0x6fc42ed4, 0xf79f9d88, 0x3b14f54e, - 0x8fbc85e8, 0x5d91e33c, 0xc4cdf5c3, 0xfc0326a3, 0x5c60ce30, 0x1fa1ea07, - 0xf982a73c, 0xe88f086e, 0xf08e9c28, 0xb549aa88, 0x61e7fd09, 0x5e743c56, - 0xacd7ef40, 0xb003cf1a, 0xd89ce30b, 0x1e4cd24f, 0x8bbe4c47, 0x3cfd3e97, - 0xbf94714e, 0xa059e60e, 0xf02cd378, 0x7d7d927d, 0xe78641c6, 0xde5126bf, - 0x78c59676, 0x554bac6e, 0xdfd0267c, 0x596ce4cf, 0xf949d937, 0x4258d707, - 0x20580ff3, 0x6f51f917, 0x587defd7, 0x7e1a427e, 0x1a88fd02, 0x7e5a597c, - 0x21d610c2, 0xc9bd7da0, 0x0e27cfce, 0xf84de255, 0xbd9af3fd, 0xec3f9fa9, - 0xec315e77, 0xcee5e29c, 0xc94fc627, 0x05d43a5f, 0xcf7ab4fc, 0x8f5fcc14, - 0x477f27bf, 0x12798aaa, 0xe7829e7f, 0xc85fe257, 0xf50c931f, 0x9c1fab13, - 0xc8fff54a, 0xf50e931f, 0x8dff1a6f, 0xca04cbd7, 0x3d582d57, 0xebf22a7a, - 0x2cf9cb55, 0xce5188c0, 0x75bc40ef, 0x7bba3e79, 0x1ff31391, 0x5f8e657a, - 0x4376c1e6, 0xa5bc7126, 0x40ed1f29, 0x75350d3c, 0xfe7f22d4, 0xb157ef7c, - 0x4c9c17a8, 0xaca8fc25, 0xc1fa455e, 0x2f1749a3, 0x9e174791, 0x93eba64f, - 0x01f78acd, 0xf991e384, 0xe05ce823, 0xad332533, 0x98cf5f3c, 0x78d4c0c7, - 0x469167a2, 0x1ad3844f, 0x58bf8f92, 0x5cfcc9f4, 0xafa6934c, 0x9e38aaa6, - 0x2f172be0, 0xe1edf75e, 0x4be7507a, 0xc8695ced, 0x1087c679, 0x7de29f5e, - 0xffd092c8, 0x161de33c, 0x9f7c0acf, 0x1d3e7c5c, 0x9f3f5bf9, 0x91ce7e18, - 0x48a6bd49, 0x76b35ff6, 0x782071ce, 0x2aef563d, 0x77f3371c, 0x41879dce, - 0xc91746be, 0x1ccd4c2e, 0x827c62bd, 0x5215cfc4, 0x4695439e, 0x971324bf, - 0xa310f643, 0x8b1ed67d, 0xb9bf46e0, 0xf49541e7, 0x6dd15a77, 0x44f557e4, - 0x3e60b467, 0xfcc3cf50, 0x4c66295c, 0xd90d1ca3, 0xbf401313, 0x5ce0e40f, - 0x339c1c98, 0x71c673ae, 0xdb3a2e7b, 0x553fa83a, 0xb00c0feb, 0xe0b9e0c4, - 0xe5eb911e, 0xc1271a9e, 0xf6f98431, 0xa57efae1, 0x18b56de3, 0xde02fdcf, - 0xe8bc405f, 0xc0e5ff78, 0xa3457bf4, 0xe8912bdf, 0x74fe7e17, 0x6bfbc5be, - 0xf8aa7f6c, 0x15742ad0, 0x869dcfc3, 0x6a4ab5d3, 0x78ae88da, 0x682f9ee2, - 0x36e9d19d, 0x412b857a, 0xe3a0641a, 0xe8efd8eb, 0x10985f3d, 0x4f7e9d5e, - 0xfdef900f, 0xcf5f0b07, 0x9c4bc7c2, 0x8de291d3, 0x1060feb4, 0xcf58212e, - 0xf8d1e6b5, 0xde3c4d83, 0x10bdbfd3, 0x7fd03e71, 0x30f2a5e6, 0x2fde5573, - 0x50fdffe0, 0xf110ffbe, 0xfe22223f, 0x03bc463f, 0xf6c63ffe, 0x4fff8057, - 0xdd7f852e, 0xf4d32fae, 0x2bee1942, 0xc5fcff01, 0x13313339, 0x15142dc6, - 0x5b25ffe2, 0xd21f6d45, 0x62725b7d, 0xb92c8f50, 0x199f7abe, 0xb3c970f8, - 0x9169f102, 0x73fd5e76, 0x784b5ced, 0x1cf15f5e, 0xcbc9e91f, 0x49f9f7e7, - 0x336d950f, 0xe410bf3e, 0xc7ca74db, 0x93f3f1f5, 0xe11726a2, 0x68a33ff8, - 0xd628a2fa, 0x0e9c2ed0, 0x864daa43, 0x29e4f03c, 0x9f90fd7d, 0xbe726497, - 0x3fb5f14f, 0x07c61998, 0xf8fc52dc, 0xbc63e200, 0xcdfb1530, 0xef56e4d7, - 0xe30ae86f, 0x33e19f3a, 0x6acbfb9e, 0x1bfb9e34, 0x686294de, 0x4c86cd7f, - 0xfe91fbc3, 0xafef0d6b, 0x50d636db, 0x8372d51f, 0xb6e8fda1, 0x4c7d4302, - 0xfb4316e0, 0x1a678771, 0xefda13ea, 0x789fb435, 0xfde18174, 0x86a51df5, - 0xba7e37f7, 0xa9bf50cc, 0xed0d5ff7, 0x5eb88b03, 0x94935fdc, 0x740ae786, - 0x2a5fecbc, 0xbe7c549b, 0xe6a4db34, 0x744f3e86, 0xccb1733b, 0x357fa373, - 0xb14cbc90, 0xae85a726, 0x6cccf9cf, 0xac536bd0, 0x55817ac6, 0xe07497e3, - 0xcdfe2017, 0xa55ca356, 0x026bcf56, 0x2ca59bb3, 0xd2f94619, 0x58b75f20, - 0xc5bb7eb9, 0xedfa657a, 0xaa7f6c4e, 0xece74032, 0x444be5c3, 0xd2a2caf9, - 0xcca9fb47, 0x1b96f945, 0x4d3e466d, 0xccaf401a, 0xc3cf1ab3, 0x9b61ea8b, - 0xfd139064, 0xd0a8f9f9, 0xdbe2c2e7, 0xa0676f28, 0x05a4e57e, 0x7d016eb7, - 0xa97b2729, 0x9aaf9fd4, 0x97988a63, 0x3bf590f7, 0xfa1b49fa, 0x210f4fd9, - 0xde92bb7e, 0xccf30a7e, 0x92f5e72a, 0x316c94bf, 0x775825e2, 0x5479e60d, - 0x508e7e4e, 0x54dcffe5, 0xae2b78d3, 0x173cfaf7, 0x1133307d, 0x06d203f3, - 0xd55e9ff0, 0x4d5cf1e6, 0xc345adc9, 0x14d53fb0, 0x7a45bf7a, 0xfd10aaa0, - 0x1e5aa198, 0xc8a653f4, 0xd53f4af9, 0x0a8c19fa, 0x5503ed14, 0xaba0fb21, - 0x048723f8, 0x9377f8f3, 0x17c8a7f7, 0xe7b7460b, 0x6ecb73f1, 0xabb24cd7, - 0xd75f8254, 0xe78ae943, 0xe92bd429, 0x66731249, 0xf06787f4, 0x06636f3c, - 0x338fafbc, 0xf7aa14b9, 0xe59e380a, 0x820d8cc7, 0x5bffeaf1, 0xf7eaf824, - 0x3cf94f5f, 0xe29aa516, 0x993cfaa7, 0xc7afdfb6, 0xcd26cf8b, 0xd63c418a, - 0x6e77db5f, 0xacfd6187, 0x7ec76de2, 0xd337aecf, 0x8205f5b8, 0x6f3ebde1, - 0x741dc369, 0xe15d2b1e, 0x79862ef3, 0x3496dc23, 0x73fd570e, 0xb8234b02, - 0x43d2f7fe, 0x8aecbfe8, 0x0dbc6176, 0xe889b1f0, 0x6738ceed, 0xf30f27d2, - 0x34a418aa, 0x25fb21af, 0x96fa1fb2, 0x4cdbaf95, 0xf688959d, 0x4635f254, - 0x66f5c5b8, 0xc51707f2, 0xe0af942a, 0xd1a159af, 0x55ef38d5, 0x9cef3349, - 0xbdd4f00b, 0xfd4c3223, 0x2d347671, 0x15df043d, 0xfcbb46b7, 0xef78fece, - 0x01387272, 0x6e10b7ee, 0xcd214371, 0xdc21da9b, 0x33d8173f, 0xde77c819, - 0x14ff44e9, 0x977dc313, 0xd3fff870, 0xefc4e3ca, 0x879a5558, 0xeb7c549c, - 0x16584196, 0xb51ddc91, 0x7fceb80e, 0xfcebe568, 0xeb08d687, 0xfdeee5fc, - 0x7ed39f28, 0x6dd14b08, 0xeadaecd2, 0x197b50ec, 0xec49d6f4, 0x318baf57, - 0x7ec5ce3f, 0x3ccbb607, 0x9719d94d, 0x1ed0cbb7, 0xedd3fe43, 0x8d5abfb1, - 0x9e886476, 0xb3d34afd, 0x9ea15d5f, 0x4eed80bd, 0x68881bdd, 0x91c824c7, - 0x1b38dcf5, 0x2a957fc7, 0x1be3ca33, 0x6d9f9e20, 0x0e1f6c8b, 0xce5d0eb4, - 0xd68cc8cf, 0xefd754f9, 0xc560dfdc, 0x9c2fed32, 0x247fe0d9, 0xe329f71b, - 0xedde5187, 0xaea4fd40, 0xf10d83f8, 0x886de3ab, 0xc04f88cd, 0xf9c6d3a3, - 0x648b69c4, 0x1e03960f, 0x0e3c064d, 0xd903f6c7, 0xdfad5783, 0x6ee78c4b, - 0x837c35ba, 0xbc71979e, 0xce3ebbae, 0xe545b8c3, 0xe7a473ec, 0x399c7aaf, - 0xf74475c6, 0x011c61bf, 0xd77ddfe7, 0xb7716b7f, 0xd5178a0e, 0x0c4d7abd, - 0x0a2aa7c6, 0x9586f4fa, 0xa49985db, 0x5976bb07, 0x576708dc, 0xece7cf1c, - 0x10f135da, 0xaf3e39c6, 0x85299c39, 0xaf5d2dd8, 0x4333c91c, 0x8f3b5d7f, - 0x209449e4, 0xd17e27e7, 0xfc5c57df, 0x128f3ccf, 0xc7d0273c, 0x0ebe566f, - 0xf8f1b7ad, 0xc798d3c9, 0xf7b19a36, 0xfaf963a3, 0x1c7a6891, 0xe3bf479f, - 0x7f7ea1f3, 0xc7e57054, 0xdd262b00, 0xab664c55, 0x00a68de5, 0x6e0a8f96, - 0xbe55e311, 0x4d3cfc91, 0x911b1652, 0x4728fd01, 0x8e0803db, 0x8dd7a3a3, - 0xa7ea29db, 0x0b2c3eea, 0xc402ef14, 0x2baf5c7b, 0x37fc7d09, 0xa1b38d87, - 0xe14d215f, 0x7e77b77a, 0x29ef1f94, 0x8fb9344a, 0x6767aa80, 0xc58c2f0e, - 0xe68b7ff7, 0xd258f2f2, 0x8e5c2689, 0x38a03970, 0x5a669bd4, 0x710d96df, - 0xef822f27, 0xe7884d97, 0x9805e97e, 0x9639c87d, 0x0967e3c7, 0x00b90714, - 0x14e78178, 0xb53e02fa, 0x3317cc4b, 0x89b0f416, 0x0bf055b9, 0xee4293ec, - 0x68ffc1d9, 0x4d60fc76, 0x4d38f6ff, 0x45e0333e, 0xd5db1976, 0x5c0cee09, - 0xfc81774f, 0xb4fa030d, 0x7ca958d5, 0x184d46ad, 0xa7b8f206, 0xafea8926, - 0x0ca938d7, 0xe7a08cd4, 0x545c6bfb, 0xa7b5368f, 0x552c7ad3, 0xfe879baf, - 0x0b12fdf5, 0xbc23b7bd, 0x8e567bc4, 0x97f9c887, 0x0093e62e, 0x3d352fae, - 0x38d6fb52, 0xc6a7afe2, 0xfd31d400, 0x8ad9ffbf, 0x054d643f, 0xa3fa983d, - 0x415359c3, 0x78129f8e, 0x181e02fe, 0x552e748e, 0xb7329f2f, 0xf0a9a2c4, - 0x4df31b6b, 0xc8bcc24d, 0x8e153fde, 0xe8f6cc61, 0x1d4ea69f, 0xfdc7f309, - 0xf6c614fe, 0xc7abdeda, 0xfba9d873, 0x818bab3f, 0xfc6dc8f9, 0x82899f3e, - 0x7d4056a7, 0x0bf39b33, 0x98b53c93, 0x3773d9cf, 0xbefee273, 0x1b5ece3e, - 0xdb7613b7, 0x51399db8, 0xe6c1fce0, 0x411e5aca, 0xbae86e6f, 0xef3ede11, - 0x8f74d7c0, 0x2fb78c0f, 0x2f5e30d5, 0xfa0711c5, 0xd7ff752e, 0xe95c8eb4, - 0x491f3d77, 0xc4847cfc, 0xe6ba2bf3, 0xfda66e26, 0xba1f6878, 0x4723da8f, - 0xd2ded7b6, 0xed0681d6, 0x659fb7be, 0xa68372f0, 0xf5c62457, 0x05d16bff, - 0x61b947bf, 0x5fda38de, 0x09e2d3aa, 0xe57a3a93, 0x2f7e76f9, 0x13d43e5c, - 0x3c04784e, 0xd1a5d70f, 0x1e605533, 0x6048ffcc, 0x28028433, 0xdbcf36dd, - 0xc2d24fd8, 0xd197be4d, 0x7165d85e, 0xe3a3d9a2, 0xd903eeab, 0x6121fa8a, - 0x8fda31cf, 0x643a13aa, 0x8f97f7a4, 0xcb714d7c, 0x3275733a, 0x1b176dd5, - 0xbdb4feb0, 0x99d6237a, 0x6fa9ebef, 0xd60c3f00, 0x13e3e1ce, 0x90bb63d4, - 0x3b5829e8, 0x7e06ef57, 0xf5e665d8, 0x4b391f2f, 0x5ccbb1fc, 0xe18d9f3d, - 0xef987af5, 0xaa6f58ae, 0x52905409, 0xe1fd65fb, 0xb7aeb09b, 0x77da92ff, - 0x3f6e54db, 0xa40cde2a, 0x855d5f7f, 0x2ea43dba, 0xf2b33af1, 0xc55f9f52, - 0x7f29af81, 0xe70f72b8, 0xce1bc447, 0xc3cdef13, 0x7a8ce975, 0xa4eb51d4, - 0xd73673b8, 0x9f0301d7, 0xb753e7e9, 0x2a2cbc98, 0x085ecf44, 0xce42ff5b, - 0x84a8b1d9, 0x38b4fe90, 0xbb033a76, 0x6f182b34, 0x2a2e64cd, 0x950f3187, - 0xee96dbd9, 0xbb2db447, 0x7a89d5af, 0xfad73e2b, 0x68e89780, 0xd09e1ff4, - 0xe8fae2f4, 0x01a31bfc, 0x7782f59e, 0xf17a888d, 0xe74ab365, 0xb2243a2f, - 0x35b53b37, 0x5330ad8c, 0xf73b5cbd, 0x5de95e6d, 0xeef51233, 0x19ab9322, - 0x4f0cb3d7, 0x2fbe19be, 0xaae19ddb, 0xe7bcc165, 0xc496d8b2, 0xef304ab1, - 0xaa3faf59, 0xb546d9f1, 0xd2f786c9, 0x9543fbe8, 0x71d2eb6d, 0x7db3fb7f, - 0xbd3c901f, 0x7c41951f, 0x447ad15c, 0xbf69daf6, 0x29f3c64c, 0xd6fad99f, - 0xbef75a3f, 0x0b74196c, 0xeb2ff5ea, 0x79b8744d, 0x06f43d20, 0x38373fe8, - 0xac6a87c8, 0x5dc2fe54, 0xde9a2d7d, 0xd3295105, 0xbfb4606c, 0x9156e990, - 0xb9ade68f, 0x7c0ac1a6, 0x8eac82f4, 0x179b3e44, 0x5b7c4b95, 0xbe722b16, - 0xdd07b964, 0x0dcfb692, 0x6535d4f5, 0x3c53bed3, 0x6f68c8be, 0x88526d54, - 0xc80ec00f, 0xdca83e47, 0x7ee1f260, 0x4edac9a2, 0x45e77de7, 0x368fcd31, - 0xaf5c4f9e, 0x6cdf3be9, 0xdcbddf1e, 0xf392c539, 0x511e7451, 0xe51fbfaf, - 0x9128be24, 0x55ffb47c, 0xe741de72, 0x38fbbf18, 0xc879c356, 0x0428e3fe, - 0x794e3e87, 0x57d21c70, 0x27ec1fe5, 0x6b8df83f, 0x4dd67b75, 0x3be5ac71, - 0x9b05fcb4, 0xf3f6307b, 0x1827a6b4, 0x7780b1fa, 0xeeafa329, 0x1ccf4093, - 0xf933d3ec, 0x90d3530d, 0x6cf7c1be, 0xb90f4192, 0xc1d3a025, 0xfbeead28, - 0x51f6e47e, 0xf533ed61, 0xa986ccfa, 0xf3c3fb93, 0xb7582db4, 0x1be97b42, - 0xe11d5f4b, 0xa1f573a3, 0xe3e9c5fd, 0xe9fd4bdf, 0xb51a97fc, 0xf80fa0f0, - 0x27ac60ef, 0x7a7cf31f, 0xca273367, 0x8d4966e1, 0x21d08572, 0x37af8a35, - 0x35afe725, 0xf7883fe0, 0x4ffd035c, 0xfb0d38d5, 0x968b8b8a, 0x549879d1, - 0xc7cc5e9d, 0xca6d77cf, 0xfe27ec32, 0x16ae387f, 0x7000f70e, 0xc307fd4c, - 0x5e30c231, 0x031c8e10, 0x870b577c, 0x7a6b3b18, 0x8f6bda06, 0x280f2898, - 0x66b3e4d1, 0x6ff65da2, 0x0ca78a26, 0x880f3c67, 0xfb0de329, 0x2c7b99b4, - 0x9efe31f3, 0xd2c3b129, 0xb7279458, 0xa9d716b3, 0x5f64489f, 0x39ab73c1, - 0x726e870e, 0x204ffde3, 0x665fd495, 0x1f82b7b9, 0x82fbe6f2, 0x70d33efa, - 0xbde3e595, 0xe7a39ba0, 0xfb8d18df, 0xaa1e7366, 0xe7983cc2, 0x352ff195, - 0x92bc8330, 0x2c20d21d, 0xabe33b25, 0x701b87a8, 0x147076bf, 0xf6045bb7, - 0xe4e1c370, 0xbcb9ef48, 0xf0f35b9e, 0x341b8c34, 0x8b5e74af, 0xcdb353fe, - 0xf31fb2df, 0xe8531e76, 0x47acd6de, 0x50998dfd, 0x6899d717, 0xfd6314bd, - 0xdf719adb, 0x176cc9fd, 0x68cd11da, 0x47fb60bf, 0x566bf214, 0xf0d338d5, - 0x6d3a927e, 0x76b2d81d, 0xc1798ab2, 0x87148af5, 0x732addeb, 0x773c5cf5, - 0x8dd1ee31, 0x51ebd60d, 0x071ab98f, 0x949ebca9, 0x339aeb8c, 0x7b463ad3, - 0xae68c80f, 0xb1a8a675, 0x6ff0fac1, 0x3d20fac0, 0x9dc1b1b3, 0x2b2efd86, - 0x883bfad5, 0xe2178a71, 0xef68bc34, 0xd2f4fb33, 0xcbcc06c6, 0xf5836b12, - 0xaddf30a9, 0x353d72cf, 0xfb47fa18, 0xc3e3e60b, 0x877b057b, 0xca4e744b, - 0x603b6306, 0x9991b67e, 0x0cd7dfb4, 0x2bef117a, 0xdfc91dee, 0xf234fbeb, - 0xd3ed1370, 0x6f5c7b60, 0xbdbcc96c, 0x57df833c, 0x8a15db20, 0x307ac037, - 0x149ef315, 0xf371ffa6, 0x8fb6a4b8, 0x01f78511, 0x75a3f084, 0xf73a32ed, - 0xdc661d69, 0x8cd3979f, 0x16798975, 0xaa27bfa0, 0x4637e7c6, 0x8341f96b, - 0x6dda0a58, 0x133e4dc3, 0xfcc91bb6, 0x02c75e54, 0x628d8f64, 0x8d1f541d, - 0x1e16635e, 0x41d2725b, 0x2dcc71ab, 0x47aa38f2, 0x71313b44, 0xf2471eae, - 0x74be414e, 0x61766b47, 0x7e3fef0a, 0xf7ca2cc6, 0xcdef69f5, 0x313d8633, - 0x7eb5e60d, 0x50ceddc6, 0x2f5f4efb, 0x48adfb75, 0x68cbf983, 0xa0bda221, - 0x364575db, 0xe5984f5e, 0xc6147a7e, 0x26cddb11, 0x58ad9fbc, 0x6f16638b, - 0xbb444fc8, 0x5cdf68ac, 0x44d787b2, 0xd16cbb73, 0x77b219fa, 0x9af79e14, - 0xfe7f764f, 0x183109ba, 0xb9b06fa7, 0xfe47ae62, 0xdfbf23fd, 0xb1ed4af5, - 0x0a6bc4e6, 0xc19b1e50, 0x8ffbc6af, 0xcadd9a0e, 0x758be418, 0x6ccec8c3, - 0xc7d6f28e, 0xffcdbf42, 0x41d574ea, 0xf73667fd, 0x4e3823f8, 0x8f7f1443, - 0x6f2126f7, 0x3ff7edf6, 0x1e8c5c2f, 0xfdf0fc78, 0x91b183fe, 0x43bdf1ef, - 0xfed05fc3, 0xd9dd90f0, 0xdcc4f660, 0xcbbdf087, 0xead679e7, 0x112f5189, - 0x86b4fb67, 0xd67603e7, 0xe64058b8, 0xbd62d1f7, 0xdd3f68a4, 0x22d25caf, - 0x097cdc50, 0x3a3d226b, 0xeed5894c, 0xc5e631a7, 0x4dbd1696, 0x795b4bed, - 0x42d632fb, 0xe17a75ed, 0x8301b5bd, 0xf0ce3a1d, 0xdcd11dfd, 0x78acdd6f, - 0xfffb431f, 0xc4d91991, 0x1167c04f, 0x07e22df3, 0x31b977d8, 0x371faf9a, - 0xf6c8db62, 0xb863f128, 0xe05cb87d, 0xc207b3e7, 0x9379d553, 0xde0a3d61, - 0x7ad3219f, 0x49f9add4, 0xeb7c9387, 0x7ff9846f, 0x244af59f, 0x23bddaa7, - 0x425f8275, 0x33befaf9, 0x2d1bdeec, 0xa6ba680f, 0xcb43fe25, 0x6b3ef9ef, - 0xfd0dc379, 0xf402cedc, 0x9eed61dd, 0x48a41412, 0xafd01979, 0x3adc1f41, - 0xddbf58c2, 0x39dfac65, 0x7d3df229, 0xb4d46b6b, 0xd6aa7bd0, 0xf38e700e, - 0x575e8d2d, 0x0b12df7f, 0x0b7bebcf, 0xf9815ee9, 0xc17fb494, 0x1b14faf3, - 0xd91ea0f3, 0xfb46cfbf, 0xbc8a5521, 0x55164319, 0xbde2efe0, 0x9f9d8af0, - 0x17ff4037, 0x998a05e3, 0x97de0fb7, 0x1251f7c4, 0x3c5a493c, 0x633495c3, - 0x1b87b7d4, 0x0bca2afd, 0xdc46d896, 0x27e60d77, 0xe8edef1a, 0x0f38fe8a, - 0xcf9863fd, 0xe84f8c6c, 0x3e7d5a71, 0x2c7f28ff, 0x39cfbb5a, 0x346b6e9c, - 0xa30ba8f9, 0x39d23d73, 0xb973df07, 0x87bb52f9, 0x43c129ff, 0x26896879, - 0xb3ac171e, 0x9c528eb9, 0xea0ff344, 0xf306b8b4, 0x56ef5d7d, 0x1095ecc2, - 0xed7d22ff, 0x39f5f5d7, 0x38f377e4, 0x156a2d88, 0x360dc3ae, 0xfaa66ebd, - 0x00a6e6d3, 0x5aaffdf9, 0x831f189c, 0x6718ddef, 0x411dcdf3, 0x065d5d7e, - 0x0e7bc14b, 0xb4cbb0de, 0x6abdd6fe, 0xd8f5c669, 0xdb76f36d, 0xba49f242, - 0xf9d1efec, 0xf9fd08a6, 0xf90dfd0c, 0xf8c1fd76, 0xfd7788ad, 0xa7f61bfd, - 0xceff2202, 0x691bf949, 0xa17b1fed, 0x42cbb89e, 0xf7fd4f71, 0xe7cfca0f, - 0x7a8cfdd1, 0x4e14137f, 0xd51ace87, 0x8e5d8f90, 0xe507377a, 0x67f49da0, - 0x8320cb45, 0x69f5d4de, 0x681bf9c5, 0x57482cbf, 0xb5212e2d, 0x38aa5e93, - 0xbc68bfff, 0x349e903b, 0xf7e9124e, 0x3549c781, 0x38e0e3e8, 0xf7700c93, - 0xc132671f, 0xdac38fa1, 0x9fe70ca2, 0xae3ccceb, 0x33986672, 0x1e823626, - 0x83714bd1, 0x60ff70c9, 0x62b2e49d, 0x4eca75ff, 0x287f3435, 0xef005f7c, - 0xf02164c5, 0x867ac1d5, 0xf30b72c1, 0x3d405e52, 0x072213f6, 0x62a5d9a2, - 0xf8c262bf, 0xc62ef9e9, 0xbdb945fe, 0x33727d10, 0x8bd82df2, 0x7e3b583f, - 0x49ec0f95, 0x4769ecc9, 0x93764aba, 0x6b68f313, 0x45c51315, 0x64ac92eb, - 0xca12adff, 0xbd739455, 0x2243a95f, 0x8f7df438, 0x9f29e681, 0xc33cd077, - 0x9ffb3bef, 0x76a14f1b, 0x3b57eefd, 0x0f93d730, 0x93545bfd, 0x4e5d450b, - 0x2127d853, 0x47ef0ff4, 0xec4520da, 0x8e9dbc27, 0x6ce901ff, 0x3d2070ee, - 0x88a5e3ba, 0x951b1079, 0x310798ef, 0x271f4c2f, 0xe00ecd1c, 0x238742f7, - 0xe5f48323, 0xa5f50546, 0xdc9fccfd, 0xb4cbd24e, 0x7fafadef, 0x56a984e6, - 0xbc6c4f9e, 0xfe206f57, 0x7d62f1d3, 0xf3c641f3, 0x7f94bd53, 0x483c3972, - 0xfb43cb82, 0xe2297600, 0x425836be, 0x4938fc86, 0x354fe631, 0x63e21e48, - 0x56d54df3, 0x5b4927da, 0x927dc569, 0x063392d5, 0x37ded8fd, 0xf983fec1, - 0xbe793a35, 0x6bff786a, 0xb4661ef0, 0xc4531573, 0x06a379fb, 0x34baafb0, - 0x77d9acfa, 0xf501fe69, 0x3775c1e1, 0x71524e2a, 0x399b35dd, 0x4bad03bc, - 0xe103bf7a, 0xfc7dd1eb, 0x392c1bf7, 0xffae3f56, 0x4a35e3e1, 0xbc3e4f1e, - 0x7078046f, 0xcd31acdf, 0x546df84d, 0xd5fd1525, 0xcc5111e8, 0x656fea1a, - 0x67f7a2cc, 0xccf1e3e2, 0x8f8c6b22, 0xe3a3979c, 0x1df2b769, 0x186f1ded, - 0x8f7f0e5f, 0x7c21e8e2, 0xe84ca9d9, 0x91bb97cf, 0xfc381317, 0x5aa6f7a1, - 0xbc458633, 0x7f1fb27f, 0xde4df186, 0xf7e74664, 0x19b94306, 0xeed56efa, - 0xb5c0aa43, 0xf2f4fc0b, 0xc2a6147b, 0xe477e6fa, 0xc939405f, 0xcfcfdf6b, - 0xf026b4d1, 0xefb51e7b, 0x625dc7c3, 0x12c8fee7, 0xcc654abb, 0xf12ff751, - 0xdb5a37f7, 0x5e789ca3, 0xb22e35b1, 0xd763931f, 0xb49a68f3, 0xb41d0873, - 0xcfb7a14f, 0xcddcc79b, 0x1b3dc50a, 0x257fe0ad, 0xa9ffb5f4, 0x82023fb6, - 0xf9dce30b, 0xf99aebdb, 0x7f3e51f9, 0xfb62ab8c, 0x5c8ec4c4, 0x740efc41, - 0xf70cc6db, 0x3b5855db, 0xe7ce51b2, 0x7699bc9a, 0x68eaa718, 0x5bd62247, - 0x4e9d3edf, 0xb71d6f7e, 0x47777b37, 0x3fa0dc53, 0x79f96a7d, 0xcc29f3f2, - 0xdd3fa837, 0xad00a5ca, 0xd3e7e5ab, 0xcd1c6f99, 0x0b8d67db, 0xc2d3bfbe, - 0xc8b1a4d8, 0x884f1c00, 0x30f4489f, 0x7a064ddb, 0x675e3c80, 0x7881e8d7, - 0x76b7a3ea, 0x76a74bef, 0xcd71e0bf, 0xf72a615f, 0xa5fbf5d7, 0xe5f7678e, - 0x5b7dd05b, 0x13f736e5, 0x3b0b4f78, 0xe6be5222, 0xfefc29c2, 0x771685c4, - 0x0b57da0c, 0x6a1453ff, 0xf3937f69, 0x7f0d22fd, 0xf745cc9d, 0xdad6f80e, - 0x984ebef8, 0x54f1967f, 0xc23fb8fe, 0x44da8bf7, 0x305f1bca, 0xbf61f145, - 0xbf05ed79, 0xe2f9fdc4, 0x773a68c6, 0xae7bf0be, 0x2dd76893, 0xc4e6c27c, - 0xfe597bdf, 0x327e6641, 0xc9fcbbf4, 0xdf07d50c, 0x24f0af45, 0x27a05d59, - 0x8853db1f, 0x3083457e, 0x0630be7f, 0x0ec7cafc, 0x98b8c2ac, 0xcf94cdf4, - 0xf47f506d, 0x615677b1, 0x18b7e9bc, 0xf63b26e7, 0x63b442dd, 0xf4d0425f, - 0xc1c03ffd, 0x5a4d874b, 0xa9aac4fd, 0x4daff2a0, 0x2a293568, 0x562765fa, - 0xc4d939e1, 0x1318f738, 0xfd8ef78c, 0x6fec42b3, 0xcea313c1, 0xe7f7806d, - 0xbec817ed, 0xdf693a00, 0x014f370b, 0xb278bbbb, 0x582d975e, 0x86668f8f, - 0x3339be38, 0xd9da3e38, 0x8b7c7aad, 0x718cdd45, 0xd505e3f7, 0x3fe82453, - 0xceaea1c3, 0xc4d8c919, 0x1baaf9f5, 0xc476cfc6, 0x98f18cdd, 0x837dbed6, - 0x1f18d5f8, 0x03de656b, 0xd37f7866, 0xb66e43e3, 0x07e36202, 0x30a8c679, - 0x29d641ff, 0xf4dfa7ab, 0x4463e41d, 0x0d59f3bf, 0x939204f6, 0xf4d28843, - 0xc2defc15, 0xe34ef93e, 0x1f57db7c, 0xc3cfc1d1, 0x5e24f5e8, 0x59195d6f, - 0xc312dc5f, 0x2a35baf9, 0x4d66fbf2, 0x03be003f, 0x8b6d7f14, 0x08cf0ff6, - 0x1f900fea, 0xa79224eb, 0x807f5c75, 0x93b4cd1c, 0xefec46dc, 0xab6bcadb, - 0xab79af76, 0xf8c68ee4, 0x30c7ae82, 0xcce38682, 0xfa0d3bb5, 0x017daf39, - 0x3151d7e9, 0xc9c7872a, 0xc53093f1, 0xb59847a8, 0xdf743b3d, 0x3cda77fe, - 0xe3d3ae33, 0x7439013f, 0x8ef969df, 0x9f9e4bfc, 0x7f38c72d, 0x9c1dbd88, - 0x678a54c7, 0xfa17ebf4, 0xbbfd6a73, 0x5f04ae72, 0x15f065ea, 0xdcbaf84f, - 0x19fd833c, 0xfbfd2fe3, 0xc17db593, 0x223ae326, 0xa4f38647, 0x7f8027ce, - 0x2cfe8853, 0x9ea9f4d6, 0x6bbdd107, 0x064fe524, 0x31e7e5c7, 0xc4bfbe81, - 0x81f25ddf, 0x963d453e, 0xc56fb927, 0x71ed79f6, 0xc0efda2a, 0xbf1af56f, - 0x3a6fc849, 0xaae35b9d, 0xebbe69f3, 0xfa4bb204, 0x3ada41d9, 0xd024d79a, - 0x9e0d99ef, 0x87e715e7, 0x7beba7c0, 0xeb55bfe8, 0xe7e73c7f, 0xf9f8fb67, - 0xcd1f943e, 0x0eae679f, 0x1c3d5fba, 0x732885fe, 0xd5eb2109, 0xeb8a36ab, - 0x5abb78eb, 0x85edd7fe, 0x25d701f2, 0xf8377d07, 0x84e1c068, 0x1e518b76, - 0x7cb55f50, 0xb664f742, 0x7f0c89b6, 0x8de700b2, 0xd74f237a, 0x8795be93, - 0x5bb2240a, 0x49d97a82, 0x37ae8bf6, 0xb06b5603, 0x2bb5b9fd, 0xaf51eb0b, - 0xc7ecf76a, 0xc7c5a08b, 0x7348e106, 0x9277bb70, 0xddfc4597, 0x5dbb1cb8, - 0x8f3423d7, 0xe80a2b8d, 0x6d2a855e, 0xe1d49d3d, 0x345378a3, 0x104271e2, - 0x7d7afa1f, 0x15e3a5a7, 0x8197bced, 0xd83af51f, 0xaca69525, 0x7ef8ff60, - 0xe7df0866, 0x841f3839, 0xeabbe7d3, 0x0f83c027, 0x0d43f0f1, 0xc75009ef, - 0x04982d7b, 0xfde617eb, 0x6b5c50cc, 0x56e04232, 0x104e3eb8, 0x5d8f5c4d, - 0x07e22e46, 0x58f7ed31, 0x41cf24ec, 0xe5bb707c, 0xe7168701, 0x3f29eed5, - 0xa1390268, 0xcf3e367d, 0xd4c95dee, 0xddad6cef, 0x6f2f4bdf, 0x7496f2d6, - 0xb5e2b17b, 0xf846cdd4, 0x1cbb7f79, 0x47792f1c, 0x8ed063dd, 0x5c51ee19, - 0xb5e41fe8, 0xf98fdccf, 0xf07bd924, 0x7c820407, 0xe5c2dd9e, 0xc34bb814, - 0x43db9bcb, 0xd874adfb, 0xbbfb3975, 0x28fb23cc, 0xcba457e7, 0x5a72217d, - 0xbe3850e3, 0xc4167e60, 0xa3d464a7, 0x83f7f97a, 0xcf1fb3c3, 0x3e039525, - 0x78eb6d50, 0xbf996d6b, 0x7c7286d2, 0x8e50b994, 0x9be65bbb, 0x315d2146, - 0xa219cc11, 0x79f3d61f, 0xf02876e8, 0xe5f20b65, 0x1a10c73a, 0x7751f86f, - 0x1fbc0e74, 0xc613768e, 0x7eec5b7d, 0x0efc23f4, 0xe2072eef, 0x14ef5673, - 0x8cad4fdc, 0x85b5aeae, 0xdf6bef3c, 0x8f89ed06, 0x1fee22bd, 0xf8c03f95, - 0x7cdaf1bd, 0x02cfa9a0, 0x20c855e3, 0x0f5459a7, 0x655ade20, 0x3ef7bede, - 0x5611a5fa, 0xf97bf229, 0x95befd60, 0x536df3f8, 0xfd17d21c, 0xcb93b424, - 0xee1a4f45, 0x16c1b27b, 0xe003ae17, 0x1fbf1077, 0x06c931b4, 0x4a1efffd, - 0xc4d3d3d4, 0x6b8e74a5, 0xfb40965a, 0x8f7fba44, 0xa4fd0b7a, 0x4d17bf3b, - 0x3c2ec8fc, 0xd3e30c38, 0x4e9cd109, 0xeb558fd0, 0x1b1d6ac7, 0x48ffbf94, - 0x8efe491f, 0x141dbebe, 0xe0e7ea04, 0xd735d74d, 0xd841f885, 0x83ffea1f, - 0xa5b48cc2, 0x1f9affc8, 0x7c61f647, 0x7b45dd70, 0xce21ac65, 0xebe0d3e6, - 0x0a3e4748, 0x3ed147b5, 0x7d67b3ed, 0x0cdf57f3, 0xf4e2767a, 0x715e0096, - 0x6e8acb5f, 0x6fe817fe, 0x36b3d81a, 0x8d3ec3c0, 0xf8660e2f, 0x3d4fdc44, - 0xfba05c38, 0x79450fdc, 0xe095aa73, 0x5c5a8938, 0x33cb5120, 0xe5e28c4f, - 0x1eb8620f, 0xaf863cfc, 0xbca837d7, 0x1c88e89e, 0xbdad9847, 0xeb89a9ff, - 0x91f935f7, 0x684fd1f3, 0xedaaf5fa, 0xfc211cde, 0x8e13eebe, 0xdd7dda09, - 0xe3c76f94, 0xfe340bfd, 0xe8873b06, 0xf8abb414, 0x876e9d7e, 0x4d9f6d9e, - 0xf78213f5, 0x2c047bbd, 0x9f904f3d, 0xf148aef4, 0x6f58e2a1, 0x55a5e622, - 0xcb8e4544, 0xf4f0d20c, 0x38a30d59, 0xcfdc29ef, 0xb7bfe6cb, 0x1b25f585, - 0x1d7ba49e, 0xe29f994a, 0x1a1b45bd, 0xc8aebf68, 0x80a7302f, 0xc78799fe, - 0x943a3581, 0x710d116e, 0xb552c5e7, 0xe4139b1c, 0xae1dfc5b, 0x9b25f7d0, - 0x57ea19c6, 0x1816976f, 0x7a823bf2, 0xbfec90a7, 0x3e757ef0, 0x8f4fb70f, - 0xf10d38d7, 0x861b05ee, 0x78cdf217, 0x73217ede, 0x36177cd1, 0x11ef1966, - 0xb2b84c6e, 0x1ec1827b, 0x538445f5, 0x3fa8fd26, 0xf7f80e3f, 0x17f7c485, - 0xe08c3a7c, 0x7bc38bf8, 0x8e018c5d, 0xc433e668, 0xdff326cf, 0xf8f1b429, - 0xef8ff023, 0x7e407652, 0x07f577cc, 0x1fc01dae, 0xfa87fdc8, 0xb9937903, - 0x024d65fe, 0x9c4ce0e5, 0x66cfb46a, 0x6e75f0c7, 0xc1b44c76, 0x679a2b3e, - 0x6b57376c, 0x776b5737, 0xa84a38b9, 0xa164265d, 0xe9fde33e, 0x71951fbf, - 0xffca6dfa, 0xedc310dc, 0x6eaa9fd7, 0xbbf40c6f, 0xd0773b56, 0xefdade6f, - 0xf735ad4a, 0x5e5285e5, 0x1e6fe6e0, 0x09dfc3ac, 0xf601dde9, 0xfcc1e83f, - 0x7ba0df67, 0x6eeff4ba, 0xb432d15f, 0xa954f008, 0x8bb973c9, 0x15dcafcf, - 0x3f418790, 0xae1ce529, 0x827d96b4, 0x5a5df214, 0x22b76f09, 0x2ff06cc6, - 0xffd5a27f, 0x6549c635, 0x1840495a, 0x3652ed06, 0xec24116d, 0x0b577f0f, - 0x66a949e0, 0x93dfd0fe, 0xedcf194a, 0x6fc7db9a, 0x04e61616, 0x9a68d0f1, - 0x5c62a391, 0x85da3135, 0xaa47cceb, 0x50f10eb7, 0xce8051fe, 0xa8fc4c49, - 0xbdbb425d, 0x23d7755b, 0x7078eb7f, 0xae0a6a8a, 0x711fd1a3, 0xfcfa9b38, - 0x30bebe62, 0x4766a8f6, 0xe976eb37, 0x42edc661, 0x5712a75a, 0x3efc308e, - 0xb69c6261, 0xef32244e, 0x37da854e, 0xa327a232, 0xccae24f9, 0x2c76e66e, - 0x2cb4f7a7, 0x3e7c16cf, 0xb1c8f06d, 0xd647df78, 0xbf8480da, 0x26dafe3b, - 0x51fbc453, 0xc3fc359a, 0xf9c59e3c, 0x9cb8f3e9, 0x99dbd05e, 0xe84f8807, - 0x3d3d10f2, 0xd8c1dfb2, 0xff3ef4e3, 0xe97bf8d9, 0x997acafe, 0xc74e4f7e, - 0x69eab77f, 0xb4a6bc41, 0x3708166c, 0xdc7a78da, 0x5ca39f0e, 0xe78d971e, - 0xfb94073a, 0x16873b15, 0xbd7dca85, 0x1cd9f44c, 0xdbafe796, 0xe1887ff7, - 0x5890eaeb, 0x4bc43ecf, 0x8a3adb65, 0xc2d92cef, 0x4067f77f, 0xfe215cfc, - 0x07ee1284, 0xfbe1cf94, 0x4acff95e, 0x7ab2ff44, 0xe5acfbfe, 0xb8f077db, - 0x0b998fce, 0xcb7943f5, 0x0728a10e, 0x8773077f, 0x9f0428b0, 0xca7ee5a9, - 0xaec6bf83, 0x5bd71fcb, 0x718efce1, 0x0e53b462, 0xe87eb8d9, 0xb87c57cc, - 0xf669dc1f, 0xcebb6396, 0xe61768e4, 0xfff8e977, 0xe99b8efd, 0xa77db5dc, - 0xa3658025, 0x8ac939a9, 0xcad70efb, 0x6eabe42e, 0xe9127bd5, 0x5a792713, - 0x78d8fbf1, 0xbe16abbb, 0x58d85a75, 0x3c72b955, 0x8fe30c4c, 0x72e63f89, - 0xf43aa493, 0x24b186bc, 0xeb9daa37, 0x67d7132d, 0x1e7ccc87, 0xf787193b, - 0xb3ee3107, 0xe3878724, 0xf294dc68, 0xca1f9d00, 0x70d3bd38, 0x5fc830ce, - 0x1b7dbfee, 0x2c3fff7e, 0x00284ba1, 0x0000284b, 0x00088b1f, 0x00000000, - 0x7dd5ff00, 0xc5547c7b, 0xbddcf8f5, 0x0dd90afb, 0xdc3bf79b, 0x24280c10, - 0x01049e6c, 0x878424d9, 0x28026e20, 0x47796bc8, 0xd2026c92, 0x6dfad0fe, - 0xe5318316, 0x16d46b6b, 0x882ea945, 0x835ab696, 0xb80d06a2, 0x47d62228, - 0x2d8aa523, 0x2220a5da, 0xfb1b6484, 0x6fcb56c0, 0xec9999ce, 0x0f0d9bde, - 0x7cf9fb6b, 0xdcc98fe1, 0xe6739f79, 0x9ce7339c, 0xb5331d99, 0x228ca8cd, - 0x389aa6a4, 0xfd2d34bc, 0x84e90ee9, 0xf00b9085, 0x8321226f, 0xf121326c, - 0xbd3ca484, 0x582c524d, 0x1c5a7fbe, 0x052627d6, 0xaed84bbe, 0xa0af9686, - 0x84225ba9, 0xa0e4258c, 0x31cc7881, 0x2ae8b484, 0xfd68d947, 0x7b488496, - 0x663b2d13, 0x68db4573, 0x9d63967f, 0xeab4ac07, 0xa33e6398, 0xda4bf68b, - 0x4264c7e9, 0x121230de, 0x8c1ddb41, 0x6dd3ed60, 0x42229074, 0x07891b26, - 0x233d1bbf, 0xc1dfda14, 0xbfb083a1, 0xa6eab797, 0xc37b697a, 0x19d8b220, - 0x9b74ef32, 0x6ca5db0e, 0xe8e921dd, 0x5a48b8f7, 0x513f321e, 0x595b01ef, - 0xcc67cc26, 0x43844ed4, 0xae3d56dd, 0x1ce8c2a7, 0xb05466b6, 0x8fe868de, - 0xe6ed7bd6, 0xfa7e8c4f, 0xbd2fc7fd, 0xbf50246f, 0xc1b47255, 0x37df5bfc, - 0xa9a1c9ce, 0x4932e7e7, 0x613a6420, 0xf0bf36ff, 0xdfa151be, 0x70a6efa7, - 0x76eaf5a2, 0xa32fd2ef, 0xc5a95769, 0x24268d23, 0x8b6bccf3, 0xdefd2148, - 0x74112266, 0x5736dd6e, 0xfbce8d91, 0x0e535dcd, 0x58845149, 0x20f9339f, - 0xc421f015, 0x06b4e19f, 0x3a5225e7, 0x722fce30, 0x10b3fd2a, 0x55ef46b2, - 0x95ddf099, 0xb7eb4559, 0xccf830c6, 0x42e0cc1f, 0x157bec2c, 0x0b80975f, - 0x8c0a7f1d, 0xdce5915f, 0x2454fd01, 0x329bd846, 0xaff99e61, 0xebdc2999, - 0x823d92ec, 0x672b8d56, 0x579d0cf0, 0x79b84e65, 0xe2f1c06d, 0x44f8d963, - 0x7180cfef, 0xefb2f109, 0xf9216932, 0x3873f6c1, 0x1f77e9be, 0x3a864efb, - 0xd7f38273, 0x4d836fe2, 0xe861fac2, 0xa3ac116c, 0xc7cf98f6, 0x0f53ace8, - 0xe6799674, 0xd043e230, 0xeab6cfcd, 0xd5fd1531, 0x5fd88cd9, 0x708f4d9d, - 0x1a780cd9, 0x2c03534c, 0xcc1ba69a, 0xc7850f5e, 0x1f26f39b, 0x7e297292, - 0x20fa316e, 0xb4b7437d, 0x48dfca16, 0xe8b7e361, 0xdf216b74, 0x34859772, - 0x6e1d5e21, 0x376bcf98, 0x6a7e2147, 0x26bd1ae7, 0x9f8fcfda, 0x63de5897, - 0x67fa12f1, 0x72f66bad, 0x22e24768, 0xfe024fec, 0x738c075c, 0x4ae9fdac, - 0x51bf6e79, 0xb7a7dfa1, 0xf027fdb1, 0xe8c6db50, 0x0107ec4b, 0xbd3c20d7, - 0xf024fdaa, 0x8db07f31, 0x17a505d1, 0xcecd7780, 0x3349db08, 0x0102eb1b, - 0xe5568cfa, 0x6d93dbeb, 0xf3044727, 0xd007f035, 0x81620ec1, 0x79f2d679, - 0xeeb9d3ce, 0x6755fd83, 0x50341ff6, 0x0d1f16d4, 0x881f7ee0, 0xffd66b7e, - 0x0164fb3a, 0x0e93ab21, 0xadf62a61, 0x7f7aa861, 0x6f78e56f, 0x7bb69482, - 0x4d4dd382, 0xcbee1b61, 0xb80d939a, 0x19532d9f, 0x231cb35f, 0x133c508e, - 0xdebe43f2, 0x457db17b, 0x9964db64, 0x71e2bdc2, 0xfa44d6c9, 0xaba44fcf, - 0xa36ce224, 0xf5b67dfd, 0x0025a8f5, 0xc82eafdf, 0x37ae98a4, 0x3777ad82, - 0x3b5d3be7, 0xde91c029, 0xcc248c1b, 0x3fb72f7a, 0x01223be2, 0xec386b3c, - 0x1f2e9ebb, 0x17a529fb, 0xf6c1cecf, 0xcf92e8ab, 0xf6eb3d3e, 0xbbbce94f, - 0xcbb44c76, 0x4e4d3640, 0x7c409fa4, 0xa53b7d84, 0x4c99389f, 0x37de2895, - 0x351ebdb4, 0xfcfbb68e, 0x81f3a397, 0xf7cdbf6f, 0xe5e799fd, 0xbb9700f5, - 0x75ecf67e, 0x95e35e50, 0xce304d62, 0x95ffc7ce, 0xdea9fb42, 0x26100f51, - 0xd57cbf4d, 0x74f5a7e8, 0xfbec6dde, 0xa836c1ce, 0xf713f9f7, 0x6ef0075f, - 0xf2c26b6a, 0xc36c4f33, 0x7b3f6bfc, 0x683fdf76, 0x94675abd, 0x799dea1d, - 0xa5e23f7e, 0xc077a5d6, 0xeba2077a, 0x33f6bbcd, 0xe126d97e, 0x1973237e, - 0x2d74131f, 0x9ff3f7e8, 0x2a1b1e2d, 0x16f7c437, 0x833b9723, 0xcb391c98, - 0x994d6ff7, 0xb3d205a5, 0x85cc44cf, 0xfe8dbaf5, 0xcf9868ec, 0x1f174628, - 0xb6d47871, 0x2db831ad, 0xf9fb1ed8, 0x487bee80, 0x9e7d2873, 0x6b4ef4a2, - 0x0050b8ed, 0xeb0afde3, 0x11257ad3, 0x2f37be14, 0x7cc12e38, 0x18354722, - 0xbf9e706a, 0xd574e564, 0xebc5e5a1, 0xe96a3d18, 0x059b0be0, 0x907d8beb, - 0x4d32bbb2, 0xb2603e41, 0xd6ce3e33, 0x6aed5297, 0xd7efd2b2, 0x65d973af, - 0x4f97c78a, 0x4a9c9e1f, 0x211b3ff3, 0x65fe2015, 0x8f39c989, 0x5ba9c705, - 0xd04e465f, 0xd9a2eaf9, 0x11b0497e, 0x07c8b5fd, 0xd7ba31b6, 0xf205bd13, - 0x89f200fa, 0x072e16ba, 0x1279b077, 0x96632073, 0xae59db15, 0x83ce098d, - 0x3058b3b6, 0x29b8c81f, 0x678ee407, 0xc51dca2e, 0x233df388, 0xe4f101f8, - 0xee09cc2e, 0x711d04b7, 0x8c13fe01, 0x7e30b534, 0x4ffb4953, 0x8a4d2e8f, - 0x09a60a2e, 0x16b95883, 0xf2f0b74e, 0x923b451f, 0x3b5e01a2, 0x60f25563, - 0xdaf2be20, 0x6e4cddcd, 0xe91c72bf, 0x08740dd0, 0xaa4ebbe3, 0x6472f6e4, - 0xf70e94ae, 0x5c3a471c, 0xabf8cede, 0xb8d4bdbb, 0x259ba68c, 0xefe61732, - 0x7404f4e6, 0x9bf9a764, 0x7d71a3a2, 0xd9fcebee, 0x39baa7c0, 0x61ef75dd, - 0x4e86f6f4, 0xbcf801e7, 0x36e47db1, 0xf95a0790, 0x113b5528, 0x6f8a6edf, - 0xd67a0493, 0x67a0c3ba, 0x3b1355d5, 0x6ef757ec, 0x081a1fbe, 0x7b7707ee, - 0x2fe872e5, 0x5d9a6e35, 0x992f5096, 0xeef34a9c, 0xfb04525a, 0xd96b652d, - 0xd20ba01e, 0x20ab912e, 0x0ddced5f, 0xab8fafed, 0x2099cbb3, 0x9927b6f7, - 0x47ebfd69, 0xcdfb6314, 0xf4294ae9, 0xb620a9e7, 0x706f2127, 0x9cdb3ca1, - 0xf20ed23c, 0x88daedce, 0x0651177a, 0xb89ca1d9, 0xbea16bf4, 0x6c80b3db, - 0xe3ecc292, 0xcb03923d, 0x08de91bd, 0x3b7a7eda, 0xeddc7fd3, 0x139f1f6c, - 0xa1a911f0, 0xd78c1173, 0x788982fd, 0xbd9d20a4, 0x930a67b9, 0x509a2fb3, - 0x746d9ece, 0x34541390, 0x10568c8f, 0x358e02af, 0xa03a99ad, 0x9966425b, - 0xf8cb1e60, 0x4c0d5a3c, 0x3973446e, 0x9b2f7590, 0x1fbe72c7, 0x78eb4796, - 0xaffbe46a, 0x9b05c995, 0xe0e41727, 0x921e3e39, 0x73970245, 0xe5bae874, - 0xb527dc3e, 0xe2feb34f, 0xdbbc8e4c, 0xe855e842, 0x6c7a5a47, 0x6ca6e3e2, - 0x3301203d, 0xa55ad949, 0x57d7e7da, 0x5d3d5f13, 0x755bf5e7, 0xa8b989be, - 0xfc82dd37, 0x6c91837c, 0x77f7fa97, 0x5be3344f, 0x3cceb115, 0xcdd7e409, - 0xfa3fd416, 0x8720e9f6, 0xb8f4022e, 0x84dec97c, 0xea1670ab, 0x09d3bd68, - 0xede03b56, 0x5a8e1c47, 0xbdafab7d, 0xd19c0f46, 0x4325c9ea, 0x4186e969, - 0x549e0173, 0xa198b75f, 0xa7b68d9d, 0x8fb612f5, 0xf213627b, 0xf7ec26ab, - 0xeb1b68f6, 0xd859d627, 0xcb2e2c00, 0x27c98eb9, 0x7adc3dab, 0x9e85a3d2, - 0x074f28bd, 0x82db33f4, 0xafc7e1fb, 0xbd194b48, 0x01284151, 0x41fdb23d, - 0x5278fee8, 0x3d447a41, 0xf4e0ddca, 0xb647a786, 0xaf54dc5f, 0xd29b3d02, - 0x27a65ae3, 0x4fdb085b, 0xa7232e8c, 0x7c007932, 0x159f542b, 0xefbb54fb, - 0xedf6fd05, 0xefdccbfb, 0x1fb606dd, 0x801c29bb, 0xfce8fbde, 0x9be74665, - 0x48fdd036, 0xfdd137cb, 0xffc214d8, 0x981fe7b5, 0x04079c27, 0x73663dbf, - 0x745f0076, 0x19ab7f6f, 0x47f396c9, 0xc83fcbf7, 0x65de98be, 0x5fb4ca86, - 0xa1afdd33, 0xe0a663f4, 0xea63e6b6, 0xb9113901, 0x8947ad5e, 0x266883f4, - 0xdeb1bebf, 0xa3d24238, 0x55f1c3de, 0x007d73ab, 0x46f41e7c, 0x6324114a, - 0x131bd33d, 0xde00e640, 0x417a47b6, 0x20484e3f, 0xccc2e7ae, 0x67df3f67, - 0xfce29f02, 0xeac51090, 0xff7df2f7, 0x4ff7af29, 0x4b9c869e, 0x3a283f70, - 0x0f2271d7, 0x3b448f2c, 0x172c2f3a, 0xd73be9f3, 0x137cd998, 0xbedecaee, - 0xc18f0429, 0x3e75757d, 0x5eeb37e0, 0x25a97e9f, 0x8b908e38, 0xf981ba5a, - 0xf581fc83, 0xb81a8e54, 0x7e7eeb5e, 0x71d0d33e, 0x7b5fdf04, 0xb482b8a8, - 0x2bfbe0d5, 0x5635c7ee, 0x2522fa02, 0x9d2c4707, 0xe1befd57, 0x088d1f6c, - 0xeafb4364, 0x314dd758, 0x9331dfb4, 0xdfa0fef8, 0xa09ce0ab, 0x0c531e27, - 0xf5e0dde0, 0xd3f9e087, 0x8f7fd618, 0xe991ecd5, 0xd623b8fe, 0x3ded0d15, - 0x03eec465, 0xe5077339, 0x896fb027, 0x4df808af, 0x0147f13d, 0x5d58c79c, - 0xbf4031f1, 0xc9366772, 0xf257fca2, 0x63f7c2e7, 0x84b95111, 0xfb71f3f6, - 0x85799f6f, 0xcaf85ab6, 0x03df85b9, 0x22317afa, 0x18e2e803, 0x513b97d5, - 0x830656df, 0x944bddbe, 0xfc30b6c1, 0xcc0ba457, 0x20beb33a, 0x55663f98, - 0x7a442f9f, 0x6fc30c4d, 0xe214f9fd, 0x09fe8589, 0x627bbf9e, 0x1f5df614, - 0x56ea8230, 0x78833e7f, 0xeb1f7f68, 0x985b7548, 0x30c53771, 0xc84ddb7a, - 0xf7e570d4, 0x0f7671f1, 0xb030fb65, 0x7f02f24d, 0xe1bf5eac, 0x07e532cf, - 0x3eacebd5, 0xe831694c, 0x8f36d56f, 0xc7f3474f, 0xd11f8c0c, 0xc5cdb37f, - 0xeb47b941, 0x0e03c7e9, 0x4b20f43c, 0x2e52e0f9, 0xbc3596b7, 0x13d825f9, - 0x3cc4f5aa, 0xdcb3f69e, 0x4a983cec, 0x2cb33e8b, 0xbfb6028f, 0x25b73bf2, - 0x5c4a5c80, 0x32eccad0, 0xf40d9264, 0x4331c95e, 0x317910be, 0xfa8f4b3d, - 0xe29fe231, 0xe7188beb, 0x82f7c04c, 0x80f504c1, 0x7a45b705, 0xd07c213d, - 0xa5a1e1cc, 0x7eb84f9b, 0x767feda5, 0xfe81196c, 0x739ca23a, 0xdc163e81, - 0xcfc54e76, 0x53ff25ba, 0xad5d028f, 0x649fdab1, 0x433865dd, 0x623bfee8, - 0xc43af3bc, 0x675e4f53, 0xa04cfaf6, 0x87c640df, 0x30eacf60, 0x940a3cd9, - 0xa2cf111b, 0x291a9fdd, 0xe60ecbe3, 0x361e9e97, 0x196be819, 0xde0337b1, - 0x1244b597, 0x033f084f, 0xc3e81805, 0x3f609e7d, 0x3cde3b4b, 0xaddcfc0a, - 0x2c9d23f7, 0x8f105b35, 0x9c7af3ee, 0x74316907, 0x8a7b45f9, 0x8e5123fb, - 0x9e7d60db, 0x9f47c67b, 0x263f491a, 0x7eb8efd2, 0xfdf0edd7, 0xe228c8a1, - 0x4b78fa00, 0xf3a70ef6, 0x832b35ef, 0xeabc2863, 0x460e948d, 0x734e3763, - 0xd243fe88, 0x77fc6aac, 0xcc25f5bc, 0x65d9b967, 0xc2be3904, 0x32a7cf41, - 0x6457c9e0, 0xef8a151b, 0x9185f2f1, 0x45ef8f97, 0x6c7fbf7c, 0x661ff4a4, - 0xe1c7dd1f, 0xa5ea23df, 0x71f27db0, 0x0e7ea906, 0x4a686bd2, 0x943c7ddb, - 0x3e79f3e7, 0x604bd79b, 0x9f7c1df9, 0xeacb9c7c, 0xc5f1c769, 0x3b36fe30, - 0xe015b1d6, 0x8cf9db45, 0x22fb1740, 0x16b7a8bc, 0xfc077e52, 0xea3a6d6d, - 0xedaf94ad, 0xc4d97ac0, 0x4cf58d17, 0x03485728, 0xcfb07be5, 0xcf84148b, - 0x274a52a6, 0xd7b03cb4, 0x04aedb64, 0xa9f02af1, 0x8c7b63c5, 0xc3c9eff4, - 0xd43e9251, 0x61e5428e, 0xa3b30c7b, 0xd27f6118, 0x9e991899, 0x85f10c36, - 0x3e5f2274, 0x608c6ebe, 0xf4fba078, 0x7bd418b5, 0xfba1397d, 0x97c704e5, - 0x0f1f67e0, 0x8ab5e352, 0x5e6de1e3, 0x8d8c516f, 0x007b4fc9, 0x31c7ddf7, - 0x165c7eac, 0x0f424393, 0xcb8703ff, 0xc8549a4d, 0xd5533195, 0x1c4dc5fa, - 0x44c5379f, 0x087ebc09, 0x88f215f3, 0x345f17f2, 0x5e0b0fdd, 0x217f2135, - 0xb0d9031b, 0x63bd68ff, 0x2c0a6e58, 0xe472a58a, 0x18dfaa26, 0x22ddb1f3, - 0x3cefdf68, 0x85d04a3f, 0x3e9c8095, 0x1853d625, 0xe54f7e40, 0x296bae1d, - 0xba437ca1, 0xd037fe34, 0xd694c93a, 0xd8560c87, 0x03a64ef9, 0x208fed02, - 0xe147f40a, 0xb850e7fe, 0xc63bc76b, 0x319fe0e9, 0x96f11e92, 0x9f70f247, - 0x7585ffbd, 0x9cf2ed21, 0x51d1eccd, 0xceb8ffbe, 0xe9fa0175, 0xd42dfdba, - 0x7d198fcb, 0x3096add9, 0x63df46e5, 0xf2c1490f, 0x3d973fc5, 0x762fca46, - 0xe4fd7677, 0xa5eeba66, 0x861db29d, 0x5fe77a5c, 0x7a031ddf, 0x0ec1a775, - 0xdf2a46e7, 0xbcc3d5ef, 0x791e981b, 0x83a6a74c, 0x9f55dfb3, 0x1962d273, - 0x83dea8be, 0x3be09cfa, 0x4adf7e42, 0x5c81577c, 0x461c465f, 0x66b4ff48, - 0xe1420cd5, 0x0eb2c2b7, 0x6be7d1f9, 0xbc1ea1a7, 0x7cb07892, 0x4fe18b59, - 0x4561f2a1, 0xeabf3aab, 0x56fe7561, 0x67df3aaf, 0x2f0f2e7f, 0x32c7a7df, - 0xd94b3e3a, 0xb03fe03e, 0x3d05e4c1, 0x98af5b48, 0x3ca4cbd7, 0x24f813b1, - 0x4760fb95, 0x48e11758, 0x6ebebe04, 0xc5e2696f, 0xe7f57cec, 0x10de21af, - 0x37a8237d, 0x6c6f12e4, 0x63cb7eff, 0xf4238415, 0xe071f0ab, 0x2cb671bc, - 0xc6263afc, 0x10653d0a, 0x8bbe27f6, 0x45e3827e, 0xcfea3ce1, 0x8f98079b, - 0x5d9fdb05, 0x1b9c7e19, 0xa9b1c6fa, 0x7db064e4, 0xfc6b931c, 0xa3e82d1c, - 0x7e127cfe, 0x07a17917, 0x31a5db07, 0xd9a48afd, 0xf906454e, 0x8b63b094, - 0x224270fd, 0x3bb464e6, 0xebcfcfdd, 0x5fb05cf6, 0x083d009f, 0x6514e3f6, - 0x714e9f9f, 0x66c6f7d9, 0xf70687eb, 0x941d768b, 0x43f8ceae, 0x58b2eef8, - 0x6b8e1c6b, 0x57187627, 0xdba2fbd0, 0xe8bb062b, 0x6778ff7c, 0x546ba279, - 0x30f53f28, 0xe85189bf, 0x9c95165f, 0xbc391a25, 0xd42dfdac, 0x95bea8bb, - 0xd3e74c0d, 0xbd23b7bd, 0x04ce24af, 0xbd9ef3a0, 0xff5c33c3, 0xf315fc86, - 0x6259e599, 0x9ba79820, 0x2abfee98, 0x1d599f3e, 0x99d3ef4c, 0xc71c061d, - 0x025b1441, 0x7cd9a51e, 0xd3d4f329, 0xf9be84fc, 0x908e9183, 0x12fe7cf1, - 0x9df0a7b4, 0xd4b253c0, 0x36f30495, 0xbc74b8c1, 0x824de208, 0x5dac69b4, - 0xe4a27481, 0x3079b3d4, 0x0d264f3c, 0x675f5069, 0x9d6ccbf6, 0xd0090674, - 0x985e0fbe, 0xc6fcf2b7, 0x568bbdd9, 0x158b77c0, 0xcf9188f9, 0xe52c4763, - 0x2fe46687, 0xc9b75866, 0xfd1cfbe2, 0x94f53c64, 0x3d8fb829, 0x3bda0943, - 0x02369106, 0xe72c5ae3, 0x1b58b03c, 0x8f9049b1, 0xe0faf5b0, 0x66ce70fc, - 0x2346e8f1, 0x0b19dc9f, 0x677a527c, 0xf285e025, 0x19ff6665, 0xc3ef5ca8, - 0x73e0b773, 0x4d7e7c31, 0x1325cf9c, 0xe2588706, 0xb01ef1c0, 0x40419cae, - 0x49d65984, 0xd44b7ed0, 0x25eff454, 0x7969e000, 0x8abd54ec, 0xd53bc56f, - 0xeab9c4f9, 0x9d4bb27c, 0x3f93d337, 0xcf928be8, 0x16217499, 0xc02359cf, - 0xfce062de, 0xebcf99a2, 0x3d74a408, 0xfd3e71ef, 0xbb13f58d, 0x8eeebcfa, - 0xe3b41231, 0xd0cd9825, 0xde57d53f, 0xcafa658b, 0x97281e27, 0xf3cfc803, - 0xc0f9b626, 0x837cd3ae, 0x7e8bbf64, 0x1b2ab66f, 0x3d5494f4, 0xc76624d3, - 0xf54adbd1, 0x865b7cb4, 0xe689becd, 0x1d7ec1eb, 0xd5b7f30b, 0x49f68d3c, - 0x0247ab13, 0xdc8fe0cd, 0x8366c9b6, 0x81e5717a, 0x8bd046c9, 0x76db1057, - 0xbfbe8612, 0xce86fba2, 0x53c809f7, 0x5e9c48bc, 0xf3290f22, 0x7cbc0d71, - 0xc59dfc07, 0xe18b13f2, 0x65feca5c, 0x3a75e475, 0x90e0eec0, 0x77d62e51, - 0xa16ebde4, 0xcecd65e3, 0xb3bc3b43, 0x0973f99c, 0x3463f7df, 0x905c6afb, - 0x8f3cb1ce, 0x707587e7, 0x899c6ebb, 0x746d6bf9, 0x36666288, 0x8c71fac0, - 0xfc44edfe, 0x5af2fb63, 0xfd07fc12, 0x47fb0795, 0x5829343e, 0x7467dc1c, - 0xbdb37ca8, 0x1bd696a9, 0x87edf7a3, 0xa78e3c7d, 0xa37d3c79, 0xbf9406f4, - 0x628b3a9d, 0x6d7db1d4, 0x861302ce, 0x14b80653, 0x04d07edb, 0x7c904cfd, - 0xbd4c6698, 0x5fa609bf, 0xd147edc5, 0x06ef4649, 0x12a68eba, 0x77b4678a, - 0xd820f9fc, 0x4907e5a5, 0x88e9e001, 0x0739c841, 0x7a15d39e, 0x3a1afb1c, - 0xfd406c98, 0x2a932ffc, 0xd5013bf0, 0xd2bbce8c, 0xbe2116c6, 0x755f2c0f, - 0xe36a3f28, 0xb337e464, 0x6abf32a6, 0x57b35cfd, 0x10ce4092, 0xbbd277e6, - 0xb10a6f32, 0xc43f0897, 0x773206fb, 0x44f39857, 0x4fd31c6d, 0x3b3066ab, - 0xa346fd6f, 0x1d537fca, 0x335eecc7, 0x8c8f26e3, 0xfcc47943, 0x5c7179a7, - 0x46411b6f, 0xe10a9f00, 0xaf504523, 0x81edf4ab, 0x9cba8cf8, 0x8e3999f3, - 0xfdea0302, 0xbe08df9c, 0xf6c41cee, 0xd2423cf3, 0x9367ae81, 0x87ffe406, - 0x7e456f4b, 0x18f11373, 0x951f6f00, 0x310278b1, 0xd55359ef, 0xa71cd27a, - 0x5cf37f3a, 0xf0c51ead, 0xe79dc621, 0x09579752, 0x5aaa783d, 0xfff05e0f, - 0xb9468abe, 0xdd54f89a, 0xe7e02185, 0xc000f660, 0xe873f30b, 0x1bdc6e91, - 0xbebc3f99, 0x388def3d, 0x127767d8, 0x4976cfbe, 0xb2ffd1cb, 0x82115a4b, - 0xaf5ad4ff, 0xb8647204, 0x987dd855, 0x7934e4de, 0xc3df83f7, 0x91128359, - 0x49e3cebc, 0x493c400e, 0xadbe907e, 0x57165665, 0x30b51c41, 0xa45b349f, - 0x16fef41d, 0x65da3e5d, 0x2aaca25b, 0x0da6fa3b, 0x13d4054a, 0x44c558f6, - 0x6e9c6df2, 0xd7779dc2, 0xbafe31c5, 0x71766259, 0x9e333ccf, 0x9cb3e32b, - 0xbc413f2a, 0x9d828e4c, 0x229c6470, 0x63fda3ea, 0x5c95c1b3, 0x44af5340, - 0xd2171197, 0xd11b265e, 0x4fe1a8ae, 0xb476b1f1, 0xce0fc7eb, 0x9cfd3b41, - 0x2fb43c8e, 0xfd844b12, 0xffd8292a, 0xf4dbd99c, 0xdf53a710, 0xdcbf4db1, - 0x7bbba412, 0x8d5cb8e2, 0xaf409124, 0xe7ba767d, 0x7ba7684c, 0x5ffce75c, - 0xa35acba0, 0x2171ed0f, 0x07df8af4, 0x38ab8b92, 0x9cca18bd, 0xf9d056f3, - 0xb46bbcf5, 0x1d19f9c3, 0xe7ffb46d, 0x9da344f7, 0x50455f51, 0x652c6d3e, - 0xec07a47c, 0x9f1d745f, 0xf9e35745, 0x8ad4a360, 0x663ba3f2, 0x6af1d232, - 0x073c01cb, 0x74a56f57, 0x569f2218, 0x6be750ef, 0xdf9e2748, 0x47ee9f6b, - 0x0517c8cf, 0x56ef761f, 0xd4c323b7, 0xcb8f377c, 0x7da77c8b, 0x7d4c0556, - 0x9d8b3dae, 0x8641e9c3, 0x1de8a3ae, 0x2eefb723, 0x008a9db0, 0x7494fb56, - 0xc7adfd31, 0xfb665a7a, 0x2283c99f, 0x6e568e3e, 0xedbd7115, 0xe0bfca3a, - 0xb0f42afc, 0x07f2c222, 0x92721d74, 0x42df382e, 0x7fe84ede, 0x7c084e42, - 0x52109695, 0xa743f742, 0xc9434fe0, 0xed37c050, 0x0489f71f, 0xd8314391, - 0x7dce07bf, 0x9478f8e3, 0xb7203c1e, 0x17b33a3d, 0x6a59abe8, 0x06693940, - 0x9ba69f3d, 0x83ca1724, 0x323daa97, 0x692c7bc0, 0xd6833598, 0x8cee6f1b, - 0x3a513804, 0x3f4a1239, 0xb197c44d, 0x11d1524b, 0xbf457796, 0x848e961d, - 0xc47df33c, 0x74e998f4, 0x054fd0c5, 0x7a687e38, 0xc8e76240, 0xeb1f9629, - 0xbadbfda1, 0x53274869, 0xf30f5789, 0xf1a9b0ab, 0x9d49253f, 0xa3f4a69f, - 0x70c38c0f, 0x1f4e7870, 0x08772ea1, 0xfcd4477e, 0x857c932e, 0xc1f9187a, - 0x5d80efc1, 0x193d7221, 0xd50dfa01, 0x6a1f7144, 0xb8ebe0e9, 0xf26fdd6f, - 0xbf185c75, 0x13b70f49, 0x2bfc4b5f, 0xd3fa969f, 0xeb1bf759, 0x7a10a4e5, - 0x65e2fb14, 0x907f8b03, 0xa9fe655e, 0xe5193312, 0x642afa03, 0x3fb14576, - 0x8cfa05ae, 0x315dd209, 0xcf119eff, 0x19086ce9, 0xa1367402, 0x5327c23d, - 0xfef1e4bc, 0xcbba05ae, 0xe223ea0f, 0xd254d15c, 0xa532be8f, 0x705fd42c, - 0xa47d09df, 0xd26b6a40, 0xb91f0267, 0x1be609a7, 0xe3434f42, 0x512f808b, - 0xda7dc27a, 0xcbaace4f, 0xf026f435, 0x52e5f42e, 0x367480d2, 0xea60a75b, - 0xf2855cab, 0x5b32dcb5, 0xacdfed0f, 0x0936f462, 0xea0b31e8, 0xdca5e9ab, - 0xe96bceac, 0x0ba88e91, 0x9f4b571d, 0x10dbd103, 0x5f2137a0, 0x6f4d2f63, - 0x75bfe3d3, 0x7f1e9b7a, 0xd2d37a11, 0xbb5fe099, 0xa0e56c22, 0x4b57d73f, - 0xde0a0f28, 0xf904d61d, 0xa89975e1, 0xb68aef4f, 0xdf5d7ea3, 0x3b0bcac0, - 0xbdc4321d, 0xe5e3ad64, 0xc872ce99, 0xe5a7afd7, 0x23a2ebb4, 0xd8662e2c, - 0xef3cac9d, 0xadd786ae, 0x587867a0, 0x6f3f97fb, 0xb968a396, 0x2fb799b7, - 0x7c872d6d, 0xff6b0b7d, 0x46a9f819, 0xb79a7c43, 0x7d5fbe09, 0x1d9da66f, - 0x3efe99ab, 0x9777af91, 0xd8ebdcf4, 0x5bb595ae, 0x883cd075, 0xe99ff9e0, - 0x75f1d7e5, 0xd6cadc4e, 0xfae27719, 0x8ba50aa9, 0xea0f0115, 0xb574a76f, - 0x06dfc8c5, 0x4a973f38, 0x4e9069ad, 0x5217eca1, 0x22ded987, 0xcc7e650f, - 0x7b8874ed, 0x45fd99e2, 0xce20fff8, 0x9f4432a0, 0xd99e27b8, 0x84bd4563, - 0xa0018a18, 0xa8ac4787, 0xa4ff0b5f, 0x812221ef, 0x723587bc, 0xbfac243d, - 0x03564a72, 0x865311ea, 0x5fa53f08, 0x9b8e94bf, 0xc98be177, 0x3f43ece1, - 0xe69ee3e2, 0x7a7d1371, 0x075337b2, 0x880bb174, 0xf4800524, 0x7f41afde, - 0x487e05db, 0xa43ca426, 0xf2caf004, 0xbd7fe35b, 0x853c65a9, 0xef41aeaf, - 0x2196a101, 0xccc9dc61, 0x1c1be24e, 0x53fe7fd5, 0xc467c4f4, 0xff362638, - 0x1e544d95, 0x7e31d123, 0x8fe38736, 0xe90abf8c, 0xd3c73677, 0x2a7f05cf, - 0x9fc00520, 0xddbc70e6, 0x347aa664, 0x8356c3f2, 0x133c6f86, 0xcb6a720f, - 0xbabbfa80, 0xaa57c35c, 0xb92bb8f9, 0x092b7ede, 0x4a727ea0, 0x7a7a62f2, - 0x6bdbd30b, 0xbf50472c, 0xe98479e9, 0x8fc4b5ed, 0xbed68ffa, 0x9d53b359, - 0xe7536baf, 0xf9d5dbeb, 0x8e0f1c9e, 0xaea5b3d3, 0xd58aec18, 0x768bbf0f, - 0x5fc16aec, 0x42fe6abc, 0x5fc67115, 0xed06ba1e, 0x6f98df51, 0x6f4f4d3c, - 0xd0b8aac5, 0xfa9c02df, 0xb22f35ec, 0x613714f8, 0xeb1e8276, 0x4e70f988, - 0xa4791a25, 0x9c7927e5, 0x86fb089f, 0x84792fe0, 0x8e7a23c9, 0x8241d77d, - 0xd7ab5c7c, 0xbd73c4f5, 0x84d39f97, 0xfa0793fe, 0x35d3d00f, 0x4164480d, - 0xdb7f6439, 0x9fc88724, 0xc0668579, 0xee99be73, 0x6c978067, 0x545971c9, - 0xca05f0f4, 0x7bcf8199, 0xbd0d72ea, 0x2dd6f388, 0x81665e9c, 0xff8e8527, - 0xe781c97b, 0x32b7c3ba, 0x5963997a, 0xd1faf487, 0xe22f466a, 0xe7e577dc, - 0x4dfc873c, 0x747d79ce, 0x5ef54112, 0x17491e9a, 0x8fe67ce7, 0x1d1897af, - 0xf87d55d4, 0x82cfe818, 0x246e1c2f, 0x3e10faf1, 0x64cd34d1, 0x934a3b06, - 0xaa839d81, 0xbc5c7fa6, 0x38cf8434, 0x13134a22, 0x88ee5940, 0x5d6cfb47, - 0x669c7aa4, 0x7fbbf3a9, 0x4fd2f380, 0xd44ed123, 0x954130fb, 0x70eb77a4, - 0x6b3edb8c, 0x31527e60, 0x7707559f, 0x7ec3f3ee, 0x08ebff5c, 0x359f953d, - 0x5ac5f792, 0xe4c4b65a, 0x6a7186ca, 0xb3233e74, 0x5fa27663, 0xb03b8c57, - 0xf283d65d, 0x931af8d5, 0x106901c3, 0xefd2e1c6, 0xb5fea1d9, 0x4f8c89d1, - 0x2aeb11df, 0xca0f8848, 0xa43f614b, 0xc6a49652, 0xc126fd04, 0x376606f8, - 0x5c710bf9, 0x6361be32, 0xb69e7d88, 0x568f1b0f, 0xf5f8c096, 0x61ce29f7, - 0x1da307de, 0xd39f30e5, 0x9a7b8fdc, 0x474efdfb, 0xcce03f31, 0x752cfabe, - 0xf734f4f1, 0x518e9e13, 0xbd4487fb, 0x8ecc09a5, 0x6cd1b272, 0xbf07a8de, - 0x1c6f313a, 0x21ec4946, 0x93c60353, 0xea78602c, 0x6dbd13d9, 0xa5ff8853, - 0xfbf4a12e, 0xd87f9f30, 0xba43379c, 0x31b8f5bc, 0x23df0ed4, 0x0f77f3b1, - 0x089e97a7, 0xeb718a96, 0x0fbf2a12, 0xe799ec78, 0xe5f63c47, 0x13bc8ac7, - 0xc099effb, 0xfe5f6bf8, 0xb84f2c3b, 0xf5d843dd, 0x69f7f207, 0xd0547bfd, - 0x044073b0, 0xfd6bcfb3, 0x3f050bf3, 0x05f9fee3, 0xec2d1f9c, 0x45827e60, - 0x4a9cd266, 0x247717cb, 0x946e73b2, 0x9fe55b27, 0x515e44f7, 0xcba0863c, - 0x3ecef49e, 0x2123f67f, 0xee3aecfe, 0xeb13accf, 0xdf5eaddb, 0xbadf0903, - 0x8481fb3f, 0x6d6cfe30, 0xa08bc3dc, 0xe20b0c47, 0xc18dad61, 0x2dae42ad, - 0xef6f7b07, 0xe8718272, 0xd65adf6b, 0xb5e0f604, 0x2a0b003f, 0xa7d431f2, - 0x079c38eb, 0x53bc575a, 0x9d951447, 0x4251107d, 0x8aec9fe6, 0x4351e551, - 0x4d03890f, 0xb5514ead, 0xaa186f4f, 0xfd643faa, 0x4cf2aa35, 0x9f2abe4f, - 0xaaad72d5, 0x65ad55fe, 0x87f0fcaa, 0xcfd557af, 0xa3074323, 0x0c90ecfd, - 0xb57221b6, 0x3e554ab7, 0xaa2de772, 0x86919ff6, 0xbd69e3cd, 0x79fe42dd, - 0x8aa39d1c, 0x39ce7183, 0xed554b6d, 0x62b6a49b, 0x9f46f01f, 0xbd6893e4, - 0xcb5f1c15, 0x62ff993b, 0x556afb74, 0xd8a367ff, 0x5fad183d, 0xa32e7696, - 0x912ed61e, 0x7efea447, 0xfb8eeada, 0xa8ee219b, 0xf296bfbf, 0x356eda4d, - 0xfe80bf3d, 0x8e6fd5a6, 0x5d3f7026, 0x7461490a, 0x0b0ba5ad, 0x5bbd7fea, - 0xe627b465, 0xc687ec91, 0xc40cbc23, 0x5fc7f4ab, 0xae76612f, 0x76ada7de, - 0xf559ff88, 0x47a432d6, 0x2e9a9253, 0x5d351422, 0xd3508e44, 0xa6aed585, - 0x6a25c183, 0x3dc2d03a, 0x0ba6a1da, 0x43ffa7e2, 0x2ae02de0, 0x553b1ee0, - 0x785a374d, 0xda0093e7, 0xc95eddd9, 0xfc6123ee, 0x70dbede2, 0x1fd2975d, - 0xf86a89f5, 0x34701c16, 0x2c6e1059, 0x61e84cbe, 0x68ffae26, 0xaf4213fd, - 0x7ae44b89, 0xf847ef15, 0x0f259a17, 0xfe7d51ea, 0x865f12c2, 0xa7f4132f, - 0x44ecc206, 0xf0c4a4ce, 0x3efc4676, 0xc0519d90, 0x2620f675, 0x03886b2f, - 0x882be1ed, 0xc9ddf90b, 0x3ed15bca, 0x63f2cab4, 0xad9ebbf4, 0x35527a62, - 0xbf9f22f1, 0xaa02b8e2, 0xfb109287, 0x528e16ab, 0x02b3e487, 0x20f2e1bf, - 0x79087485, 0x1378c2e0, 0x62e6864a, 0xad471f95, 0x30df82e7, 0xbd097f84, - 0xe0278c57, 0x189af829, 0xe41a44cf, 0x1a17d824, 0x6846473e, 0x3b6a48fd, - 0xe0f3b08d, 0x22fe2160, 0x44265dad, 0xe9916e0f, 0xcc90f238, 0x57f14226, - 0xdda07360, 0xce7488af, 0xe625ef87, 0xc2bd26b6, 0x935713ed, 0x80c4fb3e, - 0xfe12eaf2, 0xc91e59e8, 0x7f6668ff, 0x6bf0b43f, 0xf89fe5d3, 0x5e3c6d03, - 0x55ef1052, 0x078f0f2f, 0xa76fea7a, 0x857d1fb4, 0x02eb23f6, 0xc3f6a1b1, - 0x9206fbbe, 0x1373d71f, 0x424ddc71, 0x693710f4, 0x133f3c9b, 0x4e54c4ec, - 0xecca4146, 0xab5da458, 0x8ed1eb07, 0x012ba3ac, 0x2121afba, 0x60ccda7e, - 0xfee5e639, 0x74371179, 0x42e27d29, 0x3fc78da2, 0xc22778b0, 0x5f38a0f9, - 0x139e740e, 0xcf701471, 0x2221fc16, 0x9139a84e, 0x4973839f, 0xf74ff42e, - 0xb444a6db, 0x29fdd01f, 0xbec7ee85, 0xef2c22b8, 0xeb351fb7, 0xb2147117, - 0x42ed10b5, 0x7bd742cb, 0x7a10f019, 0x3ea86fcb, 0x1234f780, 0x0dd7a615, - 0x0381f63a, 0x553b0b8a, 0x46f59e71, 0x7b01807a, 0x8e3c8bc1, 0xafad4daf, - 0xe3c89b3f, 0xe739f893, 0x181af052, 0x4eee3c1f, 0xf532e3e0, 0x27771130, - 0x7f42f8e0, 0xc151efb8, 0xd8bcefb5, 0xe13df707, 0x72e02ee0, 0x29f3a8ae, - 0x3d6c97c0, 0xeef00092, 0x83ee7288, 0xfd47e9fa, 0x705d24a7, 0x1772155e, - 0xb6f6cbc6, 0xcf3f78cb, 0x5bc5813d, 0xc8c8f7b9, 0x4c3bba1a, 0x6ead37e8, - 0xc2f51d7f, 0x68ca46ae, 0xa6761ea9, 0xbfa90e91, 0x0340bd88, 0x47ce81ef, - 0x681f3d62, 0x75e22fd6, 0x7f7f3ae8, 0x3efc3809, 0xe42a1c1c, 0x9ee18351, - 0x919c5f57, 0x1551903e, 0x75da1f42, 0xb0f4e66c, 0x013cef56, 0x4cef1dfd, - 0x55fd0cdb, 0x53071dc8, 0x24eb3e00, 0xd1357fbc, 0x26cbeec4, 0x2574fbf3, - 0xdc3b06fe, 0xb34a4e37, 0xe1a9fde0, 0xe09d91df, 0xdd78fe17, 0x4f70316d, - 0x5c3ff44c, 0x4efde1d2, 0xe4fb9e42, 0x57f0428e, 0xa26fb02e, 0x162685b9, - 0xddf99197, 0xe5165f48, 0x891aaf23, 0x61a3f619, 0x6bde0368, 0x68cb4409, - 0xc9938cb7, 0x313ba024, 0x561f716f, 0xfafb877c, 0x7c52ef70, 0x2814d89f, - 0x0ed34b58, 0xdd620f4e, 0x0503cb13, 0xfc20960d, 0x16a65c45, 0x3c385b3e, - 0x66c6f1dc, 0xcdbb17d0, 0x52c9fce2, 0x9f23d362, 0xfb666759, 0xe255d8e6, - 0xc2b3edfc, 0xe11dd4b9, 0xf6063c18, 0x7932fbdf, 0xb17f2692, 0xe3470639, - 0xc7d415fa, 0xbb58d9d7, 0xbf071e6e, 0x44b2a3ee, 0x6f8e5f88, 0xa66f1f0a, - 0x5c73b124, 0x8beff72d, 0x1f7ab5ef, 0x42d58dc6, 0xf04176bc, 0x6bc695fb, - 0x01fc788b, 0x27ad10e1, 0xef78d1fa, 0x7ab179dc, 0x0e4bfcaf, 0x3ebebe7b, - 0x0fe22749, 0xcf4defd1, 0x0be3615b, 0xf9d8934b, 0xe807182a, 0x7dc37bc7, - 0x4a7b85f1, 0xce45c913, 0x0ef3eefb, 0x889fdc55, 0x9f9f7737, 0xfd7e7184, - 0x29fda5fa, 0xe15c6096, 0x92dff040, 0x86e5e6c8, 0xd082bf78, 0xdefb0aef, - 0x8f1c4e37, 0xc147f3df, 0xbb45fd3e, 0x7feaf78c, 0x75374871, 0xd779987b, - 0x5db83127, 0x7dc7af13, 0x1c47d233, 0x2f8cc2db, 0x35fb89ea, 0x76aa9ee2, - 0xfccbbb7e, 0x10fe608b, 0xbc6e1c47, 0xc48e9ca5, 0x30c777bc, 0x99f7b87c, - 0xed059ef0, 0x77bde317, 0xe257f8c7, 0xf1a9b0be, 0xd7b73b7c, 0x9fdebeec, - 0xa6bcf781, 0x40c33b31, 0x728de0f4, 0xd8f504fd, 0x4a65699b, 0x06fac53f, - 0xffb216c9, 0x410f452e, 0x7854ebb8, 0x23770fed, 0xfbf457e2, 0x4fbe61f9, - 0xe702c389, 0xbe5c25b7, 0x8351d92d, 0x1f38affa, 0x8cb0fe7d, 0x139f17f1, - 0xbcf927e6, 0xcff3c255, 0xeb211752, 0xf95a1f29, 0x88334164, 0x844925b9, - 0xbec3175c, 0x46e909df, 0xf97c9fb5, 0x87ecfdbd, 0xaeae5424, 0x57280d20, - 0xdd58fe56, 0xfbdc9aae, 0xb49fd067, 0xdce1fbfe, 0xb1d6272e, 0x479e8939, - 0x2629ef40, 0xd61f20c5, 0x3185f93e, 0x1f78194a, 0x777ca69c, 0xaff81e98, - 0x46aed319, 0x48bfa61b, 0x44963c72, 0xc927b7f1, 0x9ed20db5, 0xbdff59f7, - 0x7e4cbdb5, 0xb9438d6c, 0x2efd64d5, 0x087975f2, 0xc0f7ebe3, 0x1e14093b, - 0x97d31326, 0x720d7412, 0x5e2dea14, 0xf1e387a4, 0x6266aa6b, 0x74049ede, - 0x29cbf71f, 0xefce3153, 0x800e9197, 0x4752a6f7, 0x3625d81e, 0x997bb255, - 0xb3f31366, 0xf6317f7b, 0x0c837035, 0x0cbfbb6b, 0x8eb6c1ce, 0xf7b03efd, - 0x7cfee8b4, 0x5a57e210, 0x8bf163ae, 0xfeff3a09, 0xe2f190d4, 0xe049bd23, - 0x691f8f87, 0x388f38c4, 0x21af34b9, 0xcdca5e24, 0x9edbd171, 0x1ec27685, - 0xb61bb083, 0xa8bde045, 0x8183a1da, 0x18435c8f, 0x1bdc459e, 0xdf5421cc, - 0x8470a2ed, 0xbf914ba0, 0x19f24da6, 0x12fdf0a2, 0xded4e3f4, 0x0f984be5, - 0x7ae7ea72, 0xf98983f4, 0x5c9abdc5, 0x212efe06, 0x364be69f, 0xfae34766, - 0xfe223cfc, 0x5cd97f31, 0xb8f3274e, 0x923f3f1e, 0xb1297bc1, 0x5bbb4067, - 0x474a24cc, 0xf2fcd4b7, 0x675c22b6, 0xf41a218d, 0x19f7e105, 0x6f08cf58, - 0x653f72ff, 0xa58df765, 0x72743640, 0x62e7c286, 0xf9c030fb, 0xdd9b3bb2, - 0x88c323bb, 0xee8cfc03, 0x81b7c37d, 0x8834c27d, 0x7f29aff9, 0xa3e49732, - 0x73866d5e, 0x44afadd4, 0x2f22f8f0, 0xc8ec4fbf, 0xfa9cf883, 0x8c7cb4aa, - 0xc01a3913, 0x0dba3777, 0xc7dc0cfe, 0x5448ef94, 0xf2da0e36, 0xb87a19fd, - 0xf54299af, 0xd92f9a35, 0x0fcb2f72, 0xd1d4aff5, 0x4f2d92fc, 0xfdd3d0cd, - 0x7fc6bee1, 0x5b35f20a, 0xbe7cb176, 0xf34ca57f, 0x655e5bcd, 0x4960e1f5, - 0x2dc1ec09, 0x68786707, 0xb9a267ff, 0xf1fbb7bc, 0xe5fbb59e, 0x3b50bae1, - 0xe332636b, 0x9db8675b, 0x59264cf8, 0x1ef0055c, 0xb2febe11, 0x5a0f1d64, - 0xac54c569, 0x4927b457, 0xf325dbe1, 0xf7e56e71, 0x924627a3, 0xb7e60896, - 0x3c5144f3, 0x8e18e81c, 0x93afc77e, 0x6e9e9862, 0x38fbe3f3, 0x4f011fa2, - 0x77189fd1, 0xe067c835, 0xac789acb, 0x3f8664ec, 0x1c46ce3a, 0xdd839867, - 0xcb4aae2b, 0xbc51fc03, 0xf4de39e9, 0x8dbbfcec, 0x1bf68fcd, 0xa0728b9d, - 0x07f8ec00, 0x33f5a2be, 0xd2d6f383, 0x93324149, 0x3136b72f, 0x3a206b7f, - 0x6269e90b, 0xa5677f24, 0x668ebd50, 0xe4c6870e, 0x466f7e68, 0xc2512bc0, - 0x1c389a71, 0xcf78fcd3, 0x5dd74af2, 0x775a1ff1, 0xf01cbe08, 0xf681ca5e, - 0xf5b3b7ab, 0xcd7bf0c4, 0xd4188cfe, 0xf557eef7, 0xa6836677, 0xb8c1097d, - 0x164c7736, 0x8227bfb6, 0xd93bf198, 0x332ed7de, 0xa0ade997, 0x2c778acf, - 0x123ae788, 0x7bec47ea, 0xc58da2af, 0x39d70667, 0xd3af90a3, 0x6369d7c6, - 0xe8aaf4eb, 0x64091c95, 0xa7f6b6cc, 0xf7f83ee3, 0x9f2a37f5, 0xe7daa7f7, - 0x7d83fae1, 0xd65e103d, 0xd6f93a73, 0xa9e622f0, 0x9c1f6781, 0xf013f335, - 0xed8dfd84, 0x52e9a946, 0x5926b3cc, 0xfb35939c, 0x8e1bf33b, 0xd5daca57, - 0xb9e2cedd, 0xeba6a289, 0x3a99ddba, 0xed102b88, 0x1027c16a, 0x3dffb41f, - 0x89edcc9a, 0x806d2469, 0x93c7c4f8, 0x0ddac28b, 0x9cf6bbf1, 0xe2cd13d8, - 0x8af6b5d5, 0x277b789e, 0x9cf4afdc, 0x8c0aef63, 0xc06fd8d3, 0x259cf4cf, - 0x5f282ed8, 0x9c73f9d4, 0x3fb7f63f, 0x7e603205, 0xe7b2a685, 0x47d53b15, - 0x7e431cb6, 0xecb8385d, 0x7f9a4cb6, 0xc88ff935, 0xcb530bcf, 0xfca4c8be, - 0x9fb27f7c, 0x7d9647e5, 0x5bf21431, 0x44feacfc, 0xefc0f3c7, 0x633fc789, - 0xaf507252, 0x41592d78, 0x3ae5c9b8, 0x02647402, 0xc7ae8625, 0xe309aaf4, - 0x075c04f6, 0xba4d0b4a, 0x6ff77086, 0x07a3eedf, 0x812957e6, 0xf3b0153f, - 0x5f803b71, 0xf403b2af, 0xdf7bb144, 0x8eff7b3d, 0x483e5df7, 0x1e027576, - 0x16bb23ea, 0x5dfcd265, 0x1fa09f91, 0x3dd0724f, 0xc515f601, 0xf9d01646, - 0x9c9b5d4a, 0xd5913fa0, 0xe11eb376, 0x745eedca, 0xfc28178d, 0xf3f7d95e, - 0x61b2a5ef, 0xb18f309c, 0xefd40f9c, 0xe06ff2fb, 0x633fadf7, 0x7af983b1, - 0xdb96c76c, 0xdb1aff40, 0x4c97f6f1, 0x39fbb30e, 0xc163de62, 0x97bf49ae, - 0xfe709bb4, 0x5eae3b63, 0xfdc7f501, 0xe80b23b6, 0x5f31c264, 0x9e85b013, - 0xaaa52fbd, 0xcf90e5ee, 0x39d71a2e, 0xc04ddfa0, 0x54aa53e3, 0xf478460d, - 0x857c7832, 0xf1dd67f1, 0x68fd9b87, 0x7fdf54fc, 0xfa3afaa2, 0x20c97b91, - 0xc433f83b, 0xbdad7a7d, 0x5d2568f4, 0x213efd1f, 0xa2106740, 0x6f3c4f4f, - 0x98248ca6, 0xaad1252f, 0x5939b97c, 0x96c2bf55, 0x929f2aa9, 0x7caab574, - 0xcaa7929a, 0x56311f4f, 0x7b06ff55, 0x637f2aa9, 0xfd5534c9, 0x2aa5474a, - 0x536be79f, 0xd4382fd5, 0x423f2eae, 0xfe43c064, 0x90ebfb51, 0xa0749d16, - 0x74f8b5d9, 0x8e90ebc3, 0x87030bfd, 0xed7c5ed6, 0xe1d7b6f9, 0x6b17b0bb, - 0xfb0933ef, 0xc5b2cdf1, 0x276f0c6b, 0x0567d24e, 0x75901fdf, 0x18d33eec, - 0x94eaebab, 0xa67de0a2, 0xa62f6089, 0x7c58a848, 0x00e347ee, 0x3d980b4f, - 0x062028ed, 0x68adbee3, 0x686a3c87, 0x2c0fe678, 0xf81d200e, 0x5cc084de, - 0x9e27bad5, 0x5dd6a977, 0xe0d56e4a, 0x5f2a8d69, 0x555dbb61, 0x06d24a7f, - 0xe534f955, 0xdd3c1a07, 0x60dfcaaf, 0xd3c1a2df, 0x7e9e0d36, 0xf4172aae, - 0x5aedc1dd, 0x451ec0fb, 0xcefef1d3, 0x75c3c072, 0x8f8803a7, 0x72d6ce92, - 0x47b5d3c0, 0x855f10db, 0xb039673e, 0x0d43e2cb, 0xa3ea43af, 0xf76831e7, - 0xa612635a, 0xb4151a07, 0x1c6c1d6b, 0x46a1e981, 0x75ff7e3b, 0xefa60963, - 0x7d303a34, 0xa62a71af, 0x4c4e8d9d, 0xb0db1adb, 0xed8d73fe, 0xdb162ecc, - 0x3a45def7, 0x75ba07d8, 0x8278377e, 0x77923f17, 0xeecbf003, 0xc86efe41, - 0x37ec45df, 0x25f9a24c, 0xbee844c0, 0x374f29fc, 0x80023aa4, 0xca1c3757, - 0x18f1828a, 0x1e473a6d, 0xa477e1e8, 0x3ea1f84c, 0x37bb909d, 0xd16c9338, - 0x79a66f2c, 0xb3c63644, 0x83a1f84d, 0x2033d712, 0x33a9d04a, 0xf7c806e1, - 0x7772b044, 0x401b84ca, 0xfec6ff0f, 0xff3f4773, 0x61291df9, 0x9ccfe7fc, - 0xd760ac56, 0x70d5fc39, 0x30e3c02b, 0x48396fb7, 0x4d09619e, 0x0679f54b, - 0x0747b390, 0x80f0b7b8, 0xe009b4ae, 0xcfb3a6d0, 0xebef78c1, 0xb7e8040d, - 0x5fe7624a, 0xca95cf51, 0x0dcf41e4, 0x1d4f3c26, 0x605639d1, 0x7814995c, - 0x3dbce00c, 0xdee112a5, 0x00640d63, 0x4e29bcfc, 0x3c0f8f96, 0xf243d926, - 0x079f0606, 0xb6fc6e52, 0x3858f3e1, 0x62913cf8, 0xcfb6fa63, 0x807a0e91, - 0x74a91fc8, 0x3e7ec1d4, 0x0ab8ea52, 0x4d38cfef, 0xad3aff6c, 0x3ed0abde, - 0x139a28e4, 0x9219e762, 0xd1f7606a, 0xd82262e1, 0x71916f3b, 0x39e16b9f, - 0x7be99521, 0xce702748, 0xe789179c, 0xf63a2382, 0xfeb6819e, 0xb3d70e02, - 0xe3dbc283, 0xbd32a616, 0xdd566ca2, 0xfed02f33, 0x6045d67a, 0xe1ce3dd7, - 0x34f58fa8, 0x342ae850, 0x8e70dd3d, 0x1cec9b95, 0x9dbfe824, 0xf2d17f0f, - 0xfb6e3a67, 0xfd68efeb, 0xda45d64f, 0xaed88651, 0xc2ddf841, 0x358c2f2b, - 0xb0b4fea3, 0xe40cbd2a, 0x07ee7ce2, 0x27d5645c, 0x1f503ba0, 0x1727846d, - 0x9af25b97, 0xcac90429, 0x3c234ab8, 0xb69d5525, 0xd5d219a6, 0xc237eec3, - 0xa3b52913, 0x1a833576, 0x70b7475b, 0xff3ff211, 0x5e748dbb, 0x0acbd78b, - 0xfb89cf3b, 0x145735ae, 0xf7e822cf, 0xa23b8f08, 0xeaf3c040, 0xd16f0e22, - 0xd787116e, 0x3fae1489, 0x0b9c90e6, 0x67d63f6a, 0x0b5def40, 0xc01ecddf, - 0xe72ea0cf, 0x4607e3fa, 0xfdf6ae36, 0xe2ee3112, 0x3afe7654, 0x0994a462, - 0x4c2de4fa, 0xfdcee40e, 0xba22aee2, 0x9b0edcfe, 0x1615e30e, 0x7800bdd7, - 0x78e76de8, 0xd8769034, 0x4b3cb34f, 0x221df93e, 0x8f754e26, 0xd2f252f7, - 0x0f2b69de, 0x7e859795, 0xbca87967, 0x96b4092c, 0xf2145c83, 0x7d4ff851, - 0x2f9cd58d, 0x3d3f2037, 0xf31eb8d0, 0x983d1b07, 0xe16c6a1e, 0xcb15b97c, - 0x987c69df, 0xe72f65f3, 0x7bf13bcb, 0x4c5ce347, 0x58ba35f7, 0x9519ca3e, - 0xecc4fb0a, 0x37c4f8c2, 0xf80898b6, 0x4c3b7ae7, 0x77419f18, 0xc68f63c4, - 0x0991fc41, 0xe36a71ef, 0xbe7cb490, 0xf7761e8f, 0x0525377b, 0x1f8be9c6, - 0xc8717d02, 0x9874f4c0, 0x4be05628, 0xe4fe8ff9, 0x0fafd006, 0xf4158a2b, - 0xcdd482e9, 0xac50ef2c, 0x7c2f9a06, 0x8a5de794, 0x22ac04d5, 0x5be421f5, - 0x358a3d87, 0x1f8be682, 0x7b95887d, 0xc7f33a09, 0x06f5ba3d, 0x2259f00f, - 0x51fd801d, 0x449cce6e, 0xd79505c5, 0x5f6007a5, 0x325a494c, 0xcec5f609, - 0x63e90514, 0x00e1b29a, 0xd88fa7e4, 0xfaab87a6, 0x46de4b0e, 0x57165768, - 0x937687a9, 0x846cd6d2, 0xdd879376, 0x376d0faf, 0x8daed475, 0xdf619f90, - 0x74fd07a6, 0xf8b1f027, 0x2f223f60, 0x169f05ca, 0x3ba37271, 0x720f289c, - 0x0f289ddb, 0x66ca5c04, 0xf60dde57, 0xc976facf, 0x663cc126, 0x0a417d4b, - 0x86e89310, 0xbf2949f7, 0x97f53ebe, 0x5db40dd6, 0xc5afe43d, 0x7c370ffc, - 0xa6fbfcbb, 0xfbfc30d4, 0x41dfbe43, 0xfbdc43de, 0x0ef64687, 0x2e1c33cc, - 0xac4b1df5, 0x712a8ef8, 0x7acf4159, 0x97f3cb9e, 0x9fe5a520, 0x7f8bb4f1, - 0x70e7407f, 0x52ab38c1, 0x3fb21fb9, 0x6549a87f, 0x8f735ffb, 0xce728064, - 0x6d52ea1f, 0xea3cf7aa, 0x76bfbb08, 0x6d3b38a9, 0xee36b89c, 0x3b693564, - 0x1fecc8e8, 0xf70b526f, 0xc7fab2dc, 0x6a788b7f, 0xdf781c6d, 0xe3106ab9, - 0xd78173a7, 0x496eba50, 0xde4f901d, 0xdc38097b, 0xfd0e0e1b, 0x9c5843d6, - 0x2438bf7b, 0x5daeef1e, 0xb3c57117, 0xfc798d77, 0x827d76bb, 0xafaffa2e, - 0xcf5fc195, 0xbbf54fe0, 0x157e60c7, 0xec04ad8b, 0xe7fca156, 0x3fe11777, - 0x6df67e5a, 0x179bc9f1, 0x65bbe1d7, 0xf3d8f861, 0xb898f8e1, 0x854dafcf, - 0xf3f70a9e, 0xde121e20, 0x7e738239, 0x1f6ba265, 0x1653d3f4, 0xce0e9bf8, - 0xddec71a1, 0xaed183f0, 0x325df0fd, 0x1106b8b2, 0xe75a7c97, 0x6de815f9, - 0x19fa3def, 0x106eb3f2, 0xbc8f7416, 0x97a0f341, 0x7ce6c3fd, 0x4647e013, - 0xefa18df8, 0x7f140f8f, 0xff2e1bfb, 0xdf6ca7fa, 0x9ed43889, 0xa0665f6d, - 0xfb12eefd, 0x54782062, 0x70fde3c8, 0x24b7a43f, 0x9767e512, 0xdef07c44, - 0x02695771, 0xe95d2dea, 0xdfa43d46, 0x2bb8b9f6, 0xd7fb1b3d, 0x92bb8f9e, - 0xdc6ccc4b, 0x7d2153c9, 0x2154f92f, 0xf0dfbdc8, 0xa376cbf8, 0xb03de0a7, - 0x408d8f0f, 0x928dfeff, 0xa0e010bf, 0xbd77573d, 0xc94ca0b5, 0xa6be7fed, - 0xeb049beb, 0xbbae3dab, 0xe95dbe1b, 0xfd76bb79, 0xb9c408df, 0x15ff5b8f, - 0xaeeff781, 0x19ddfcfc, 0x5e80ab93, 0x12026ae1, 0xf545d319, 0x54bf9a09, - 0x8939d6fc, 0x4333d39e, 0x6f25e5ce, 0x9e2e38b3, 0xfde7cf6a, 0xed5c09de, - 0x960dc751, 0x5e308afa, 0xe147f645, 0x7b1d60bd, 0x73c4436f, 0xf3cfc9bd, - 0x243ebcf4, 0x9d70ed0d, 0xfaf3aa19, 0xfa2d1f1d, 0x0881f21e, 0xa678ef8c, - 0xcc3c44fd, 0xf19d8ff5, 0x0945793f, 0xedbd77d2, 0x9df4246f, 0xbdf5dac0, - 0x86d77caa, 0x7056fbe0, 0x5ff6ab1f, 0x2a25ca32, 0x4f105ac7, 0xdae335e4, - 0xda4af910, 0xef07dcfe, 0x55df94d1, 0xbe50c002, 0xd074cf36, 0x3cfc9576, - 0x8de44844, 0x92aeda0e, 0x67891f9f, 0xe78f2b25, 0xb09f3df5, 0xff28ba7c, - 0x7fac4ce3, 0x1c6fe895, 0x79164f2b, 0x22d5dfde, 0x9623789f, 0x25f68a67, - 0xc6239f2c, 0xaded64af, 0xade4feac, 0x7a099cff, 0x33f7e08d, 0xe09cb8d2, - 0xfe5152ef, 0xba2b4cef, 0xba8ebc68, 0xf107cb9c, 0x1dc5550e, 0x85df22d3, - 0x6126dc7d, 0x9ded61ec, 0x9fe7b406, 0x0dcb698d, 0xe22f2fbd, 0x56e59c7a, - 0x7baaf38c, 0x9976f871, 0x1e813bc7, 0xe9fb9cb3, 0xfa0b642b, 0x65ef7a61, - 0x3d207e7c, 0x97fae570, 0x57ecf855, 0x46d3dfce, 0xef1d2547, 0xf1130fdc, - 0xd619027e, 0xee02f189, 0x27c44934, 0x116abde0, 0x45971757, 0x8e7e701c, - 0xbd82297b, 0x13b27aa7, 0x97caeff9, 0x6ebb7d98, 0xef28ebcb, 0xda0aca96, - 0xea1ebe97, 0xe9f0075a, 0x2f77b2b6, 0x87dfae57, 0xc531f4fb, 0x8160fdc6, - 0xbcf0a151, 0x3dfc3fb3, 0x8517f169, 0x3ffcbabf, 0x5dad7f0c, 0x5fd7dc5d, - 0x7ff1857d, 0x07e656dd, 0xfd3c73b6, 0x7314a749, 0xf0023d78, 0x33a2b73a, - 0x20865a3b, 0x778c4eee, 0x29df90ab, 0x6f56f382, 0xde009583, 0xdccea5bb, - 0x5fe0c30f, 0x9f38ae7b, 0x69715441, 0xf7c3fb3b, 0xf7d04be9, 0xfa4dffd3, - 0x8dfbd44e, 0x1f1bf076, 0x15e5ef65, 0x18c9fe77, 0x4ef41f1a, 0x0f073b1a, - 0x317e676e, 0x2c171711, 0x713c32b7, 0xd55d53ff, 0xffc1e33b, 0xc4c3f624, - 0xfe06d248, 0x76d74a04, 0xa076d74e, 0x41bf416b, 0x176d143f, 0xfa41be06, - 0x912e2c25, 0xfdb7e9c3, 0x25e1fae1, 0x7fe1fae0, 0xa9bbae13, 0xdbfe8c3e, - 0x4ed02217, 0x3ff385a3, 0xbc055c38, 0x0e2fd323, 0xfff4c8e7, 0xd3239c0c, - 0x439d9515, 0xf9207bc0, 0x988fc5a4, 0x5a7d9877, 0xe9f64df4, 0x4f9c1923, - 0x8f18fde9, 0x4c7bc5ab, 0x27bc3f7a, 0xef1c5fa4, 0x30fff2ea, 0xd370b5de, - 0x9fdcb5a6, 0x985efdab, 0xfbbf203e, 0x7ff8e056, 0xb0b04fcd, 0x7caabf61, - 0x54b7faf1, 0xef3c4be5, 0x415f965f, 0x5bfffbd8, 0x57e105fe, 0x2afcf998, - 0xb51ff81d, 0xc43741f2, 0xc7a023f9, 0x7afe5f1b, 0xf93087d4, 0xb78c6cea, - 0xe5af8dba, 0xff7ff18b, 0xbe947be4, 0xf66068be, 0x3ffb63d6, 0xfd392837, - 0x79e165e9, 0xd084711d, 0xeff5c2d9, 0x5acf401b, 0x54fbd848, 0xa60ffada, - 0xc6307b33, 0x30be5149, 0x710c4cd7, 0x9dcc1f94, 0xcf4beecb, 0x0c630705, - 0x2d173ea6, 0x3e27a99f, 0xd2bb8f78, 0xd099f7a2, 0xffbea9ef, 0x75efe26e, - 0xd558b893, 0x21d9783d, 0x9cdf9c63, 0xbd2fe612, 0xf786d2c5, 0xba1de787, - 0x60f7dceb, 0x14f46f2f, 0x7177b8b1, 0xbaf7f0ff, 0x3e83f12b, 0x9c2a7a08, - 0x5fee24fb, 0xff40635f, 0x2addb6ba, 0xca669fbe, 0xd9a38b12, 0xc533e2c3, - 0x3beba4fe, 0xf767ca64, 0x48f7e060, 0xbe0c1b2a, 0x67a0b9e1, 0xbb3d47ef, - 0x2e4364be, 0x927eafe0, 0x1b94dc74, 0xafd4ef3c, 0xd7b60bff, 0x7a6d67f2, - 0x4fd5f6b9, 0xbd210f1a, 0xb1d17388, 0xb5e61f46, 0x1305d6f6, 0x93fd17ff, - 0x6de2ff63, 0x57dc7482, 0xd0c70f8e, 0x3b1bfb75, 0x827b2dff, 0xbb0823b0, - 0x214ed682, 0xbf7888f8, 0xe36e97d2, 0xa296b2ef, 0x59e883df, 0xc1edf82a, - 0xd7f9fcfe, 0x27d717e9, 0x61ffe5d5, 0xf4b97cfe, 0xe4c49b5f, 0x8fee96aa, - 0xed0cfd56, 0xb5be82cf, 0x6200bff4, 0x0bf8e852, 0x27bc25ea, 0xab55773e, - 0xcdf49c61, 0xe5b57de9, 0x9b830664, 0xb15c2e46, 0x3c78503c, 0x0be78c87, - 0x0ec6bc93, 0x87810f76, 0xefd5d3af, 0x48bc5303, 0xab971719, 0xfafff2ea, - 0xa2e4e039, 0x8917266f, 0xcb489f4a, 0xe56eb7e8, 0xfe56eb12, 0xb90eeb9b, - 0xd648b4a7, 0x40e3ef05, 0x81c435fc, 0xfdd978f6, 0x56ccead4, 0x5203ddfc, - 0x7e028812, 0x995eeb77, 0xde8e9efd, 0x790e4fa1, 0xf88bad3f, 0x5c7a003e, - 0x3bbd9e35, 0x769b8da4, 0xd5ea78f3, 0xbf78dd96, 0x9a0efb51, 0xf376cb88, - 0xa1efb4fe, 0x9de2f689, 0x687bed03, 0x1c783253, 0x67c93e76, 0xe7172971, - 0xcf20dda3, 0xdd35fc43, 0x5da2355f, 0x4ac7c6e1, 0x05a4f3ee, 0xa32732f1, - 0x9799df1f, 0xa3be7171, 0xd32fff2e, 0x81dd6caf, 0x94aed8f7, 0x3a64477e, - 0x827f40dc, 0x9bf1f72f, 0x6fc84c57, 0x3df33bc4, 0xf7c19e6b, 0x24be7a87, - 0xd4bd97e8, 0xbb13e33b, 0x09c435d8, 0x564dbd27, 0xc771d78a, 0x1baf683c, - 0xf785c47b, 0xe3bcc776, 0x927f8880, 0xc329c077, 0x233e85bc, 0xff209bf4, - 0x78d9f7e2, 0xf2e5d59c, 0x37f52bb9, 0x8cfca7fe, 0xb75d5ee2, 0xbf0457c1, - 0x13d9e0e7, 0xa103bf81, 0x1993ff9d, 0x93be8bba, 0x7ae511dc, 0x8b34f012, - 0x5ef109cb, 0xdecc8572, 0x94edef49, 0xeeb85ed1, 0xabfb7e7f, 0xdb4b9547, - 0xbd6dea15, 0x2265cf61, 0x7bb1d7ad, 0x0ae5f92d, 0x79c249c6, 0xc287ec0d, - 0x7fada89e, 0x297b294a, 0xe35bed03, 0xdeda3df1, 0x067cd987, 0xfafd57c2, - 0x603f8e00, 0x7ebf1f39, 0xf42d916f, 0x19f3959d, 0xdb43e77d, 0xdf107329, - 0xff174b97, 0x332dced7, 0xa891e265, 0xbc91cd7c, 0x4c25ef4c, 0x3a405dff, - 0x02445d31, 0xbb08ba98, 0xd894b0cf, 0x9c4e5d31, 0x5c55ae98, 0x3718195d, - 0xf8c04814, 0x39ff17d3, 0xdce6e80a, 0x215ae375, 0xf2dbf146, 0xbef56923, - 0xbd853c9e, 0x3fc2f497, 0xd9f4077f, 0xcb863ff3, 0xa2471be2, 0x1848641c, - 0xa57bd33f, 0x54d7bb32, 0x17dc5df2, 0x325dfde2, 0x96e1f989, 0xfee26627, - 0xc4cdf209, 0x826f826d, 0xb8e7393f, 0xdcc3c58e, 0xc67be12a, 0x6e1d7eed, - 0x99159cb1, 0xb9ddf85e, 0x3cacddf6, 0x2bda2ea7, 0xd8ce7cd1, 0x26be5608, - 0x4ff70bda, 0xee3f1216, 0xfb70c5cb, 0x4bfb8644, 0xdf8a2f8c, 0x8227a00b, - 0xbf6d12a1, 0xeeccc3a2, 0x30ff1051, 0x70b9ffe0, 0x4f170a7e, 0xf1f18433, - 0xbf1943d1, 0xb6a65d1f, 0xe5e50c87, 0xdf6529f7, 0x0cb47807, 0x810d6471, - 0x9b9d31fa, 0x3b042c1e, 0x9f808e90, 0xb7b1b3e6, 0xb4535fa3, 0x1b29517b, - 0x959ff501, 0x67bfbc58, 0x4c6fbf2f, 0xfea10902, 0x794ab5b1, 0x1a2bd42e, - 0x40d3f8c2, 0x51df8570, 0x2f398674, 0xd1d1f88a, 0xbb436670, 0xd277c13c, - 0x7e58959e, 0x6f5be3f2, 0x5f4168dc, 0xe3f40782, 0x44d71517, 0x91b46f18, - 0xffcc0b10, 0x1b7efca7, 0xbb00c869, 0x4cc7aae8, 0x3e2fd03a, 0xee18e2a2, - 0x9e81fcf7, 0x98fd21b7, 0xfd219b9e, 0x43373d23, 0x9b9e9c7a, 0xcf413d21, - 0x38ae90cd, 0xccc7876f, 0x8e2189c9, 0xf0bfd0b9, 0x5be769f7, 0xd7f18439, - 0x1af7f1be, 0x14fbfc71, 0x0fb7c217, 0xfe087bdf, 0xd1b3edde, 0x8b989481, - 0xdecf5bd0, 0x749fa3bf, 0xff08b820, 0x0a7cb6a3, 0x6eee6bc7, 0xdcffca3d, - 0xcad47f76, 0x872b7a90, 0xce7db118, 0xa0a3270b, 0x1f5b6eff, 0x5d121d7c, - 0xcb1d4cf2, 0xb9fc7caf, 0x828e371b, 0x0fbe3bf9, 0xf9f74174, 0xdb73486a, - 0xfc00fb7f, 0x1fed2a5e, 0xa47a24e3, 0x2f3c66c0, 0x85a1d668, 0xb3d75883, - 0xa09b9dd1, 0x0c2fb3fd, 0xbe509585, 0x01bed843, 0xadc2923a, 0xe7ae0377, - 0x10a05346, 0x78dd0bee, 0xa71b0e41, 0x8a529f7d, 0x7a064e70, 0xcaddfe43, - 0x025f4653, 0x7f74df6f, 0xe223fb6b, 0xa5e015fd, 0xafa5c80a, 0xac2f40a2, - 0xed04f1e4, 0x06fd87bb, 0x2439e9d6, 0xdabdf813, 0xfdea31d1, 0x49e38bb7, - 0x8d7b39a4, 0xb3d7c04e, 0x830d4f7b, 0x7e2989f7, 0xc57bc186, 0x455c86db, - 0x31ef7f42, 0x8f97ec67, 0xf587183c, 0xe769f7f1, 0x10156d91, 0xbcdf3337, - 0xd2580dff, 0x0af1db42, 0x9c599b88, 0x74841d24, 0x19399289, 0x7dc465e2, - 0x4a236583, 0x9a96c20f, 0x7d44af61, 0x4c9814ae, 0x37287c88, 0xd847f247, - 0x558a3c85, 0xa524a7e5, 0x534feaaa, 0xd3e554b2, 0x95548c47, 0xd867718b, - 0x46f5540b, 0xc28604c7, 0x83ae8e79, 0xa4ff03bd, 0x3986f18c, 0x7eb91c2f, - 0x7ccfcd24, 0x43be0e6a, 0x9f2f2cf9, 0x17b95cf9, 0xe143d1f0, 0xd50aa469, - 0x6c1f92e9, 0xd33a107e, 0xf76a179c, 0xa1d0713e, 0xe179c65c, 0x8184e712, - 0xed164fde, 0xca04e7b5, 0xbe001f37, 0xd9c5fa39, 0x3edbf036, 0x14cbf63b, - 0xcdfd4788, 0x0caefe10, 0x440c3f3f, 0x43fb7d37, 0xbcdd1852, 0xc3279325, - 0xf2440dd0, 0xe9643a32, 0x7eecc3cc, 0xb5f295de, 0xa1af814f, 0x4243c0bd, - 0x6b577f7f, 0xb46d1bdf, 0xb036e6ff, 0xc32bbd47, 0x7bbea50d, 0x6fe12b93, - 0x64ef4839, 0x93bbb6f9, 0x07bbf0e3, 0xb73761f4, 0xb8520df7, 0xffbb553e, - 0x60c2e4ee, 0x5c775939, 0x29dc9f55, 0x1bf2ab35, 0x7bf9d533, 0xdb439b4b, - 0xad8fa40f, 0xd189787c, 0x6ef70395, 0x37bfb0a5, 0xfff3e62c, 0xd5800901, - 0x00800020, 0x00000000, 0x00088b1f, 0x00000000, 0x19b5ff00, 0x6554540b, - 0xcef7bbfa, 0x7860190b, 0x77421028, 0x840a4498, 0xb0285789, 0xd71ea08d, - 0x8f4c1ada, 0xe5935654, 0xe04d7903, 0xe3d8f4b6, 0xb68fad18, 0x695b6d07, - 0x9656356b, 0xb139e4e7, 0x36254644, 0xeb495bae, 0x66a254d6, 0x42d899e4, - 0x7a26704c, 0xf75a9d6d, 0x5efffefb, 0x5b602e67, 0xe74ed69d, 0xffffef9f, - 0x27ef7ffb, 0x70ca1490, 0xf60800ce, 0x9970ccac, 0xd6f70601, 0x8018e41a, - 0xe2eff4d3, 0xf9b8daf0, 0xcf03837a, 0x3a380057, 0x01cfe3cc, 0x031401d6, - 0x7b81295c, 0x5914f3a2, 0xff60e760, 0x2fbdf165, 0x00490801, 0xde8d179e, - 0xe38456ed, 0x6e67065c, 0xf08d9ef8, 0xd918064e, 0xbfefff72, 0x25f5c22a, - 0x8c0ee3b0, 0xbd0d43c4, 0x5c75d79b, 0x9fcd7114, 0x77d1d704, 0x98809679, - 0x55706b80, 0x00e207b4, 0x3c636a9a, 0x679e3e62, 0x2e990e86, 0xa6f1c804, - 0x01529bb5, 0xc0228a8e, 0x78074439, 0xe3ef14a0, 0x245f041b, 0xa4ef39a7, - 0x67c8b9df, 0xe7c72fcc, 0x35b03245, 0xe99432bf, 0x7ed77bc6, 0xbf1ce787, - 0xce91a203, 0x8f4a803f, 0x2e5c4c03, 0x19bdbb04, 0x3f233ffe, 0x1812bd4d, - 0xf0619f90, 0x605aba1d, 0x25a9ccd7, 0xa7e92b00, 0x061dfb4c, 0x196fd890, - 0xb2957f70, 0xe57cb2bf, 0xf08b10a5, 0x2040fd56, 0xa70fbd9b, 0x7fd5fff1, - 0xf198376f, 0xda53f57c, 0x530f427d, 0xfbe52f90, 0x77b3f03a, 0x3de277eb, - 0x235ef853, 0x8499fddc, 0x697636ef, 0xc7245fbf, 0xe0e60d24, 0x3828028f, - 0x916db12d, 0xf1366bde, 0xdf4ae6f7, 0xea097bbd, 0xc925e9b1, 0xd1adc46e, - 0x00e2d3dd, 0xa83983f9, 0xf2f1d4e4, 0x7a8cda6b, 0xa7c30c2a, 0xbdf34b76, - 0xca175f74, 0x5e319ea8, 0xe2c960ce, 0x5f1c2cf8, 0x0bd7c573, 0xf735f101, - 0x7ed0d0e8, 0x1146cf00, 0xcf3c08e4, 0xf2ae31ed, 0x07f4c39a, 0xfcc79c2d, - 0x66132f9e, 0x1d75f2e7, 0x1ced01d1, 0x98bf702f, 0x093e8021, 0x60b541f1, - 0x5f4b8edf, 0xc925724f, 0x9f004fbf, 0x589ec05c, 0x5cfd4264, 0x7da39fc1, - 0x8fe02433, 0xe11d6c94, 0xfdc8a859, 0x7c7fd28a, 0x8b77e023, 0x434f167b, - 0xd750e00a, 0x0cd43eb2, 0x0c6d906c, 0xe8f012df, 0xf17d2f49, 0xa416f4ce, - 0x604932f3, 0x1f17dff6, 0x7f10161a, 0xd0b4455f, 0xeff7b026, 0xbe55f7a4, - 0x74cef4fa, 0x8e6be337, 0x26f51065, 0x4e902e38, 0x47978f47, 0x183aae58, - 0x712bf554, 0x9c7f2177, 0xfb3edd2b, 0xd1dbf412, 0x223160a5, 0x684b97bd, - 0xabc30838, 0x49ab8fdc, 0xae5133d6, 0xe8813f82, 0x6e17966c, 0xe4bbf191, - 0x97417bd6, 0x1d372118, 0x2f5533f7, 0xd3c71caa, 0xf72de2a1, 0xd1bf903b, - 0x9fb3021d, 0xecccbb46, 0xe4fcb1b3, 0x7f104b83, 0x0bb25fa3, 0xeeb2cf48, - 0x7e4847bd, 0x403b6b1d, 0xe7401e77, 0x2eb66eda, 0x527d9933, 0xd98be31e, - 0x414688ad, 0x6056ad7c, 0x7c35a7c6, 0x0c7be61e, 0x7c3f51bc, 0x3804ce06, - 0x9e7ceb18, 0xfbf35bf8, 0x1096fbcf, 0xe3ca1bb5, 0xad901f99, 0x3fa61b9d, - 0x466000df, 0xa3db43fa, 0x3c304fbd, 0x6125af68, 0x27b13d7b, 0x9e0b70eb, - 0xcf53789f, 0xc55f75cc, 0x416ea7c3, 0x68f6cd78, 0x0913e726, 0xf3a549e0, - 0x3d7ba627, 0x18a56178, 0xb9216fea, 0xb7d8c677, 0x47f1f9e3, 0x13bb3fa7, - 0xa767dae1, 0xf24c89d9, 0x7de5191f, 0xda011d3c, 0x7d953e7f, 0xef1c2907, - 0xa52fc50a, 0x57dc6667, 0x24cfe74e, 0xaa8f09da, 0xa347a1bf, 0xfaf2801c, - 0x16797c12, 0x8293bd34, 0x87c45067, 0xc79dc4eb, 0xdbcbb404, 0xc483ae0c, - 0xfe47eaf7, 0xf90ca87a, 0x37e67aa9, 0xfa44cf0f, 0x0c9bdf6a, 0xaf584ef4, - 0x6c40e2e3, 0xdffc9720, 0x915ffdc6, 0x288edd4f, 0x7111c7cb, 0x5e23a1a6, - 0xa7753703, 0x888e3e5a, 0x65c07537, 0x8e82f50c, 0xfc57a9f8, 0x1d745eaa, - 0x201aba25, 0x8422e3c0, 0x0557640c, 0x78a0e092, 0xc8c7ba10, 0xced63fe4, - 0xd1916546, 0x8b822f51, 0x224179e2, 0x6fc85298, 0xc17e5c5d, 0x713fa67b, - 0x9266ca17, 0xfbf54135, 0x223385ac, 0xf1bfb3ed, 0xcdcfb215, 0xc39f6646, - 0x8d2f3c51, 0x391ff3c5, 0xc2bf7d9e, 0x87f305f4, 0xf5a4f933, 0x17385adf, - 0x0aef141c, 0x9bc2e4da, 0xf4516d70, 0x29c52c72, 0x1dee4958, 0xc03aeff7, - 0xe6f5b9e4, 0xbf7784a3, 0x0e0fe999, 0x0507b970, 0xf7d5279e, 0xa0429856, - 0xb77a242b, 0xfdd57a31, 0xf3872dc1, 0xe0fef85c, 0x8079390b, 0xf24cbcf6, - 0xe505fe0f, 0x7fc62a73, 0x3b5c36ec, 0x853bbff7, 0x7a58e0f2, 0xd9475beb, - 0x2c3c2a7b, 0x4f5438f0, 0xf7fee07c, 0xa264ce99, 0x8b08c313, 0xcd77030f, - 0x2b9bf260, 0xfe91c6e5, 0xf4b42783, 0x7d53a58d, 0x7d4fa55f, 0xcd37bd5f, - 0x8e39322a, 0x9479fc18, 0x90cc5ff7, 0xc48d7c35, 0xcde2f3fa, 0x75e16fb4, - 0x11c20244, 0x3f4356f6, 0x2635bf51, 0x5f48db8c, 0x6f608d4d, 0xa1efb603, - 0xcfab89b8, 0x29f5e785, 0x03722b2f, 0x78ed09a7, 0x906762b1, 0x6eecc894, - 0x5ebb7011, 0xabedc4ac, 0xe80f43a0, 0x75c4472f, 0xfda035bf, 0xa03c770d, - 0x5dc64577, 0x74f151cf, 0xbb8f4fce, 0xa6c84a9e, 0x31623df8, 0x9e66bab3, - 0x7bb1d055, 0xf74e90e9, 0x43eedcf0, 0x1a74f03b, 0xcf486ded, 0x8173a2e3, - 0x6f53e515, 0x1f91e5f0, 0x2e3ddfa8, 0xb0fed8ba, 0xe9056070, 0x3cbe741b, - 0x1bc4ef56, 0x233ac040, 0x77eed938, 0x25f65d50, 0xd412b8b0, 0xe2274d43, - 0xdd12aa2d, 0x3c70e69d, 0x5167e354, 0x5ca3ee0e, 0xf55f682b, 0xa29bb457, - 0x30fded7c, 0xb8f85a3f, 0x515dfb95, 0x98eee8a2, 0x576e5fc0, 0x1d06dcf4, - 0x9e67f712, 0xb914cb47, 0x4522dd63, 0x4a8d2dd6, 0x9ac60f9c, 0x53f2123c, - 0x82f51bb6, 0xb7ce9970, 0x028c5697, 0x9dfa8ad0, 0x5efe3e05, 0x539e36b7, - 0xf2ca590e, 0xcbcb0e72, 0xaf7514b3, 0x7a40dc17, 0xc2fe5135, 0x2fc12ef5, - 0x082bfad1, 0x1601d5b1, 0x06a8ad1d, 0x2701ceb6, 0x9b81e75b, 0x9da1f3ad, - 0x83a00bad, 0x9f8297ad, 0xaf8170ad, 0xb83e580d, 0xf98832dd, 0x52bd7e18, - 0xb45cbca4, 0xfc7ae264, 0x675e4571, 0xf9460797, 0x8f2f9f92, 0x614ae079, - 0x2e4d9d74, 0xdd99b353, 0x923172ab, 0x5177e27d, 0xb5a14de0, 0x9dec0202, - 0xf190c98b, 0xeb20d99d, 0x0702ae08, 0x48fee783, 0x5c069479, 0x04ee573a, - 0xd89aa972, 0x7628764e, 0x5d364c52, 0x87d7d61c, 0x54171e56, 0x49d201bd, - 0x3ebc60f9, 0x2ce88321, 0x5cfcae8a, 0xdaf190c6, 0x3a9df7b6, 0x8545a38c, - 0x84362d95, 0xe53f590f, 0xf3e55970, 0xd91f0899, 0x9ba9d276, 0x595e7649, - 0x1563b7a8, 0x39d86eba, 0x184dcf07, 0x4e50a3fc, 0x52824d92, 0xb1515d5c, - 0x677e8079, 0x74ebac94, 0xdbc657e8, 0x5719c580, 0xd59f8014, 0xe46568b3, - 0x7ebc3527, 0x7ae1635d, 0xbd706bdb, 0x60da7e4a, 0xc8cac5f2, 0x73759ad3, - 0x6e5f2993, 0x3ff7f030, 0xbce72c9a, 0x22327282, 0x9841533e, 0x44f73c4f, - 0xe4101c21, 0x186b5696, 0xf7c08fff, 0x77c21fcf, 0x5deb8a6b, 0x594dcf16, - 0x534ffa40, 0x676779f2, 0x245d8a59, 0x3f8616fc, 0xd2d59310, 0x5207478a, - 0x7bd21f9c, 0x776e18c1, 0x5eb95a1f, 0x329ab6ce, 0x27581f1d, 0xfbae0fd8, - 0xe28f977a, 0x084827d0, 0xd599f3be, 0x34744035, 0x428c8189, 0xd11dd7d4, - 0x27640cc7, 0xa80b1daa, 0x7fc8a5bc, 0x06bc039b, 0x96e51fe6, 0x2d98f533, - 0xe5c107ec, 0xa5ca1ef8, 0xd2ace9c8, 0x8d4971e3, 0xa5ad1f7b, 0x3c2af6ae, - 0xa2413c21, 0xad0a49a7, 0x1538bb20, 0x13e19eff, 0xb953a7e6, 0xabf12a3d, - 0x6def4f67, 0x42741c69, 0xed361f84, 0x0fabe6f9, 0xa34ddf50, 0x0f5d3b66, - 0x1696dffb, 0x1ab00bea, 0xd517c4d4, 0x1b75672f, 0x955fd47d, 0x397f3eed, - 0xaf78abdd, 0xfa7146df, 0x1b40fee2, 0x9ec1cb95, 0x2fdc69c3, 0x6bfe3ad4, - 0x93e4e7e1, 0x750512b9, 0x905ecbac, 0xabe446bc, 0x050bea99, 0xdc7c20f6, - 0x47137684, 0xa9bf79f7, 0xbd0d95f6, 0x2fa819af, 0xc43c67c1, 0xff42ad6f, - 0x5c37adaa, 0xad62f54a, 0xd62fdb57, 0x13d77bf5, 0xb43b75dd, 0xd9bf6afb, - 0x4f5f7ca4, 0xea8d9af5, 0x26bded3e, 0xa8f337ea, 0x67eed3fe, 0xa6fd2a66, - 0xa940ff92, 0x772a5733, 0xeb333f88, 0x235e0cff, 0x68fcd6f2, 0x7042dd8b, - 0xe2ced9ba, 0x6606fd6d, 0xd87deac7, 0x446cc89a, 0x8ddadbf5, 0x5567eac0, - 0x1b4ff98e, 0xfc8fa41d, 0x5d5993a7, 0xab3cf58c, 0xf09e3047, 0x22651efe, - 0x173ddda0, 0x1114ca1f, 0xd93d73cf, 0x5fb7aa76, 0x7f80eb5e, 0x4fa6179d, - 0x4ae7f7ad, 0xd40cab3b, 0x7d88dd47, 0xf7356e14, 0x4266d93e, 0xd01379b8, - 0x3b2d240d, 0xe2a6ea8e, 0xe97812fd, 0x503ef01d, 0x1a976b8e, 0xbeb0524f, - 0x9447908f, 0x09e4093c, 0xa2a379fa, 0x04ece8b7, 0xfd8c79cd, 0x71f7cd1c, - 0xefda99a5, 0x6e7f0e3d, 0xfe73c509, 0x02e3bc7d, 0xc136fdcd, 0xcd91f76d, - 0xbc3ff004, 0xb188ae57, 0xcd82bfc2, 0x17e7121d, 0x886fee68, 0xec9fb79d, - 0xdd0bfcbb, 0x4b703b18, 0x01657764, 0x2f504780, 0xe7b586b3, 0x21db07c5, - 0x1d47f116, 0x57998dd4, 0x16ea8078, 0x5fddaca3, 0x54c5daae, 0x4399aa98, - 0xb73b919c, 0x9121d1fb, 0x9c0945d9, 0x117970f7, 0x5e0f59c9, 0x46dcbc79, - 0x66fba569, 0x598bf303, 0x8a762dbd, 0x5a9d9347, 0x68d727f9, 0xd2ea9fe5, - 0x956d3bca, 0x6ee9de56, 0x6dcfbcad, 0xead7cad5, 0xb6cfcad1, 0xfee69671, - 0x0d4af6b4, 0x02f37d3c, 0xbdf3fdcd, 0xce70350b, 0xf734ab8e, 0xd32c7467, - 0xaf77e79c, 0x76ab9cd6, 0x2e0ed636, 0xb18f35f4, 0x08c41133, 0x567aabfd, - 0xff70a0ed, 0xff3c1aad, 0x1f6ffd6f, 0xc8a7ffa3, 0xbdde31d7, 0x37743b15, - 0xd165ebb9, 0x999dae3c, 0x59eb9427, 0x9cb6f6bf, 0x77431558, 0x54e6fc95, - 0xff941bf2, 0x0e16c391, 0x7df6fddb, 0x8e0acf14, 0xae88ab38, 0x1f7b80a2, - 0xa192f385, 0xba38aaf6, 0x32d900ef, 0xe89c8f85, 0x02a5e5fe, 0x857e34e8, - 0x3cb094f0, 0x93acf0af, 0xd972f0e2, 0x1636de77, 0x4be9c96e, 0xa120f3c2, - 0x6a85e794, 0x22e81447, 0xeca152e4, 0x29e92503, 0xf3abf961, 0xc007ec23, - 0x6880fd40, 0x2759b6f2, 0x9bec77aa, 0xb98f5625, 0x86f67d58, 0xa57362e0, - 0x067f2645, 0x25dff7c5, 0xc4cedebb, 0xb44a76b8, 0x139eaccb, 0x54c46d02, - 0xa4a31890, 0x76afa9e5, 0xed871f50, 0xff2bcd2c, 0xb56d4774, 0x6f919727, - 0xb6f09409, 0x67f5fe99, 0xa2648eba, 0xcb0407fc, 0xf6fc42fa, 0x332759ad, - 0x25197f28, 0xcd014494, 0xe9471c4f, 0x24dcccfc, 0x78c3f919, 0x0f65101b, - 0xab73c289, 0x9390fac0, 0x08ccd8f4, 0x67a8ddff, 0xbe940b79, 0x5e451aec, - 0x54b65f6a, 0x4f803fc1, 0x7e78c2ac, 0x4c1bf74d, 0xc329752e, 0x6dca1cca, - 0x37fbe0b7, 0x5017354c, 0x428e0a5f, 0xd5e7ef3b, 0xfa4d2d3e, 0xed557929, - 0xbf76cf6b, 0xd348652e, 0xc4cec32f, 0x6391e709, 0xbe615ee7, 0x9b03fbf9, - 0x1a1e59a2, 0xe6ce94d8, 0x4ff7e18b, 0x71aff7b1, 0x93b1a3bf, 0xd7df5aeb, - 0x9ef5dfd8, 0x81e7348f, 0x0d3e90a4, 0x4aec0ff9, 0xca35779d, 0x6305e46f, - 0xa8abf509, 0x715b38b7, 0x3dc0fdf8, 0xbe10e7d3, 0xa7e7cdff, 0x6bfdbe4c, - 0xa6ee6cfd, 0xed6c79f2, 0xd6070611, 0x963ad806, 0x55bfb54f, 0x20dfc357, - 0x90e5ea9b, 0xd13ec930, 0x1b31e6bc, 0x67fa83ef, 0x7ca4a94f, 0xd06e9fdc, - 0xc38b35f1, 0x0e26a5a9, 0x6b4f9bcf, 0x48de6f50, 0x00bf6dfd, 0x61ed010e, - 0xec7ce0a9, 0x3abbe47a, 0xa36b95d9, 0x2875727a, 0xd0fe874f, 0x56b81f94, - 0x1ebe7d40, 0xfe27caef, 0x53062c05, 0x599d1813, 0x890c37d4, 0x63013c9e, - 0x764f4dc1, 0x3ffd5357, 0x8a73c934, 0xadad7632, 0x83fa9aab, 0x8ff70321, - 0x847c9e5b, 0x16b7c3f9, 0xe77a4cd7, 0x31f24113, 0xf0497e7b, 0x16f6676e, - 0xf88c2c30, 0xaf3a82bb, 0xfa9b7ea1, 0x5f14609b, 0xdff8db67, 0xacc72a5f, - 0xae3c6d4b, 0x316b42dd, 0x2ceee5e9, 0xe8ca7bfa, 0x5f902366, 0x48873e20, - 0x5cf87af8, 0x40f20a76, 0x6f560d75, 0x78285fac, 0xf8a3e8d5, 0x1675cea1, - 0xbdecacdb, 0xd79f1b24, 0xf467dd24, 0xeefcb1b6, 0x3a46a8cf, 0xef58f5db, - 0x1070df50, 0x846d1cd8, 0x7a1161e6, 0xfde36c59, 0xc008dc17, 0xd1b793cf, - 0xc0ef4379, 0xdf278a31, 0x24aeba67, 0x72880c39, 0x8693c509, 0xdeacbdd8, - 0xecc9b66b, 0xf197a43b, 0x4ee1718f, 0x382fcfd2, 0xfa455c0f, 0x7805306d, - 0x03ccaadd, 0x91b726cf, 0x7287fee5, 0x9ecbfcd9, 0xf4a9f441, 0xb6cdfd22, - 0x4a9db988, 0x1f9df87f, 0xae750bf6, 0x5b83c2a5, 0x9f916436, 0xbcf85ea1, - 0x5bae1251, 0x0ff7c138, 0x963efa2a, 0xfe10f4e2, 0xf73e6ed5, 0xfb4ddb0b, - 0xcf4947cd, 0x271666bd, 0x58fdf6cf, 0xf4f61b3e, 0x9f207932, 0x117f12d7, - 0xc91bde7c, 0xe1cf48e7, 0x9fe57287, 0x9d305fcf, 0xb8291dff, 0x190c9bed, - 0xfdd86fbf, 0xbbb211c6, 0xdf1e7506, 0x18339da5, 0x9aff6127, 0x1d1cd130, - 0x5d444fb3, 0x9fbf5466, 0x8f7ed3aa, 0xa9cd3905, 0xa9dfc9bb, 0xbff0717e, - 0xb8f9a98b, 0x846be94b, 0x1f2cebc0, 0x87f23e10, 0xe58782f5, 0xd18e7545, - 0x23de6026, 0x585abadd, 0x35ce909e, 0xbb9ec9db, 0xe4fd06d0, 0x34473a07, - 0xe98f5f9b, 0xb835bfa3, 0xd6fc9176, 0x4c9953bc, 0x9be7767d, 0x8d7e940b, - 0xc562a9e7, 0x3f098b2e, 0xc71b9fd1, 0xa148b5ec, 0xf584c4af, 0x7c852650, - 0x15e7c48f, 0xd363fcca, 0xef3e9aeb, 0x685932bf, 0x001e0053, 0x00000000 -}; - -static const u32 usem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x1915c58a, 0x19d44418, - 0x18344c18, 0x20685618, 0xb58969c4, 0x9fd329b8, 0x90c0c2c9, 0x40b9c40d, - 0x7cc40f9c, 0xfc0c0c4c, 0x17ebc44c, 0xf5b04514, 0x84181904, 0x026ffc80, - 0x85d70c0c, 0x8bbe1818, 0x03083030, 0xf1402ef9, 0x01ce2004, 0x58a06f62, - 0x045e900b, 0x2c40ddc4, 0x7cdf8a22, 0x6bf20251, 0x37f95185, 0x847bf8d1, - 0x1057ebf0, 0x47af2fc1, 0x161b1e40, 0x3e3f22d1, 0x3bd02922, 0x015f5810, - 0xc7265f95, 0x0f27d0c0, 0xb8a87f8c, 0x4bfc9201, 0x0e5cbb20, 0x6096f6c2, - 0xf2062860, 0x9bb0150d, 0x2f9403eb, 0x857dca01, 0xcc0003ca, 0x688cbacc, - 0x00688cba -}; - -static const u32 usem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0x4514780b, 0x74f570b6, 0x9924ccf7, - 0xf2124c99, 0x00493de0, 0x210e0311, 0x9970c044, 0x46a2c024, 0x141a020d, - 0x84920275, 0x7e889790, 0x33feaeec, 0xa8a08901, 0x17acb9f1, 0x376141dd, - 0x0c06e8b2, 0x60e03518, 0xba2eb300, 0xe7c045c1, 0x36bc8026, 0xb9f04324, - 0x9d6f5ecb, 0xdd33d553, 0xc7c4099d, 0xffef7fde, 0xa55f9f8f, 0x71ebaaba, - 0xe9d4e7de, 0x278f3242, 0xdf210a64, 0x9f968fc1, 0xf890848b, 0x206f5950, - 0x8841922e, 0x6df466d7, 0x88cfa64c, 0x68e67a23, 0xd11d985a, 0xef435837, - 0x9ed5cbe9, 0x186934a4, 0x1c790f21, 0x23e21258, 0x5ab54e84, 0x16f50520, - 0xe0933ba8, 0x213e3a7d, 0x0ff8e8fd, 0x30f8e246, 0x1a18992d, 0xe0311067, - 0xf9ad537b, 0x421eb089, 0xc3e6476a, 0x213b16fc, 0x9f9f7bfd, 0xa7eb888e, - 0xf7c10def, 0xb59efa24, 0x6529efef, 0x13fd0e57, 0xf66ddff6, 0xf108146d, - 0x71c7fcef, 0x8699ef58, 0x5d130e39, 0xd9b7766f, 0xbeea053f, 0xb6899f6c, - 0xc0fb6ee7, 0xe5fed126, 0xda0944db, 0xf0233b0d, 0x8275cefd, 0xa695ea0f, - 0xa4ae47d6, 0x9136c0f5, 0xf8d30f3c, 0x4092062d, 0x613371c8, 0xeb15873f, - 0x5aac1145, 0x6dd77ebe, 0xa3495f30, 0xf7d04489, 0x2e88378f, 0x28d92fa8, - 0xaf9d08f8, 0x8c07b5fc, 0xc578e803, 0xc23ea13e, 0x1f1beb41, 0x3ee83a33, - 0xd8fcef97, 0x7ce146d6, 0x0e2663da, 0xa4a3ee23, 0x52908d3e, 0x03e996df, - 0x9ba5fbe8, 0xbe802705, 0x4ed9dd74, 0x83695f58, 0xe3a45c3c, 0x228bae2d, - 0xee6c918e, 0xd7cc08ef, 0xdbe7147c, 0xf9830f26, 0x65dfce4a, 0x6ee52404, - 0xca2e9193, 0xdf603ae9, 0x3da7bcca, 0x053e716b, 0xd22fe59e, 0x8abf68f9, - 0x6c270597, 0xdc40c2b1, 0xd7ce8eb0, 0xb05e0a22, 0x8daafec0, 0x7deaac23, - 0x7d876e14, 0x1bd6fa94, 0x7d605ba7, 0x69458deb, 0xd716f1a1, 0x7d76a7fd, - 0xdd13536b, 0xf3e3bd69, 0x748287b4, 0x4a5ea844, 0x4fe90b88, 0x8e8119f2, - 0x85e7e795, 0xe2f7c418, 0xcc38913a, 0x3a15f1a1, 0xe9c07ef0, 0xf1958774, - 0x12dbc701, 0x842ce03b, 0xc73b6eb7, 0x54c814a3, 0x8f94af8f, 0x7ae83e00, - 0x2c763d6a, 0x6124f71f, 0x81c7a4f9, 0x33da7b70, 0x1eb5cb12, 0xc67f3e27, - 0x75cb0133, 0xcf96171e, 0xe9606679, 0xbf63e4f3, 0x58053de7, 0xf1b8f06e, - 0x253d6ff9, 0xaa79d658, 0xcf26f9f0, 0x7b372c32, 0x65fcf8bc, 0xeb2c2acf, - 0x6e58b53d, 0xb2d17c05, 0x7ec3e3c1, 0x58753ddb, 0xf1ea7a36, 0x469eebf9, - 0x3870d72c, 0xb648b2da, 0x7360e144, 0x3b453b11, 0x6573cd89, 0x9b1eb4cb, - 0xf309eacf, 0x5a46d9bc, 0x3ad3704f, 0x3280cb85, 0xd689b67f, 0xf6b15407, - 0x1c92f721, 0xf10fad33, 0x3594f6b2, 0x5a089cae, 0xed65a94f, 0x7379d623, - 0x847d6922, 0xda8fb58f, 0xa289cfec, 0xacf551f5, 0xc9134c7d, 0x18fad0b5, - 0xefa7ab3f, 0x695ae573, 0xd595bd3d, 0xe6f13f33, 0xb33d68da, 0xa93fbd8d, - 0x2c3a27c3, 0x55b0f13d, 0x14202c76, 0xb9de4d57, 0x9bca892e, 0x5dc746ad, - 0x7bc849c4, 0x892ef9de, 0xd90687ca, 0xde6ded85, 0x746eacc5, 0x77b77b61, - 0x2edff629, 0xaa5db1bb, 0xb7db0fbe, 0x9ed8dd1b, 0xed835d50, 0xdb17b28d, - 0x8a3f5647, 0x2f468ded, 0x5eaa4fb6, 0x65d7f58b, 0x55e7b61f, 0xaffec7af, - 0xfed87d1b, 0x5c9bfdf8, 0x05fd6953, 0xe41dbdc1, 0x5dc10ade, 0x9e815242, - 0xee4093ea, 0xf9f970d5, 0x6d1d101c, 0x446fe9af, 0x6efadc3e, 0xbfc00be6, - 0xf507ebf8, 0x983edfa2, 0x89bce38c, 0x1c74c8e3, 0xa4e3e2f1, 0x334137bf, - 0x257bfa4e, 0x382d38ca, 0xc6df444e, 0x24defad9, 0x2bde7aed, 0x0fd9c655, - 0xdac2b4fc, 0xffa57db7, 0x9ebb4b39, 0xe329973f, 0x89eb847c, 0x1a7adbe9, - 0xa7c2d03e, 0x7c2083e1, 0xf138e28e, 0xc64f5b7d, 0x327c2d41, 0xd3e1060e, - 0xeff4e381, 0x070d38db, 0x3869f0b5, 0x97cf8418, 0x7dc19f08, 0x21c657db, - 0x0e327c2d, 0x5ff3e105, 0xbee49eb8, 0x53fdb38d, 0x7fb67c2d, 0x498f841a, - 0xef0cf580, 0x3f32bedb, 0xf327c2d3, 0xec7c20b3, 0x7da5ce38, 0x67fb671b, - 0xff6cf85a, 0xfe9f082c, 0xbee8ce38, 0xaff32bed, 0xfe64f85a, 0x149f0835, - 0xb633e001, 0xfc69eb6f, 0xc69f0b5c, 0xb9f083cf, 0xdf19c70c, 0x384cf5b7, - 0x84cf85ae, 0x64f841e3, 0xf626bee0, 0xe3c69c6d, 0x1e34f85a, 0x3267c20f, - 0x6fb9338e, 0x42709afb, 0x27099f0b, 0x8e99f082, 0xebbb64e3, 0xc7465198, - 0xce3ef6b1, 0xf0b467eb, 0x104cfd79, 0x38e3d73e, 0xa938e8d3, 0x52671f17, - 0x933e16a7, 0x29f0833a, 0xeaae71c0, 0x77af38db, 0x7af3e16a, 0x853e1067, - 0x7db5ce38, 0x2ea4d7db, 0x75267c2d, 0x3b8cf831, 0xa36b9550, 0x3a1754ed, - 0x95cafa45, 0x40972e1d, 0xd59da2eb, 0x8093bb45, 0xf62a225d, 0x89756906, - 0xe6cb7df4, 0x8907f498, 0xb9c8eeda, 0x4ac7e813, 0xddb531ad, 0x52213d11, - 0xb8c4e763, 0xb8f53562, 0xfd340319, 0x3453f3e3, 0xa30589ed, 0xddfded34, - 0xc0fa9ae9, 0xfe9a4992, 0x3472ab83, 0xaecba1f5, 0xf64ff4d6, 0xa7a9a0de, - 0xd359baae, 0x7ced787f, 0x6b25fb4d, 0x97ed354b, 0xea6896fa, 0x42fdd597, - 0xfd747fd3, 0xe5fb4d72, 0xda6a0f8d, 0xd71ffac7, 0x3cb5c7d4, 0xbe3fe9a3, - 0xfb4d79f5, 0x69378715, 0x6db627da, 0x3cafd4d5, 0xcecebaf9, 0x5f8fd8b3, - 0xd022ebc6, 0x7f76613d, 0xf8f7e67f, 0x1bac46ad, 0x8ed05807, 0x722d65df, - 0x35f8a31c, 0xd1c0b5be, 0x7017e28f, 0xf6457e0a, 0xda4b9280, 0x267bf3e8, - 0xd3b12fb9, 0xdd18f7e7, 0xd8c3db97, 0x041e94a7, 0xc3a50492, 0xfdbea500, - 0x63d19901, 0x23f3c0ce, 0x95fbe9da, 0x1888c086, 0xb312cf5a, 0x777e811b, - 0x8a2fcc0a, 0xf4154914, 0xf411348b, 0xce481e0b, 0xa2abc17c, 0x298355d7, - 0x71a10a1f, 0x24eec957, 0xaade33b0, 0x1d82f76e, 0xee983352, 0xcd21006b, - 0x4bdfbb42, 0x0607b4fd, 0xe9b92517, 0xb5232678, 0x1bf3d5d3, 0x3869fce9, - 0xebd00b7f, 0x7c7f307b, 0x294df9cf, 0x9bf33413, 0xe6689487, 0xfce91b37, - 0xafde4276, 0xa7e7c53e, 0xc8449848, 0x3853845f, 0x094869bf, 0x9180ffce, - 0xf9ea2bfa, 0x1ff38323, 0xd67ffd86, 0x2653fedb, 0xa43ff769, 0x237fbb54, - 0xea91ffdb, 0x48fe7cb3, 0xe151ffdc, 0x90ffdb2c, 0x137fb652, 0xbf38371b, - 0x93ff082d, 0x2f677f30, 0xb3529bf3, 0x5a1ffbb4, 0x89bfdda6, 0xfd5ddfcd, - 0x82df9f2d, 0xbe139ff3, 0x5a1ffb65, 0x4d1bf386, 0x8fd0276e, 0x95646071, - 0x1d4fce8f, 0x04490761, 0x40f3a172, 0xfd163239, 0x148497e4, 0x913dc75c, - 0x8abede8c, 0xf286f4a4, 0x58fccbc6, 0x996c951f, 0xb4e2efd4, 0xb67378be, - 0xb612e411, 0x21657f53, 0x8d1dea5f, 0x7937d222, 0x4e1be4d2, 0x28d9dbd7, - 0xc77ea17a, 0x207d9393, 0xe44d2aff, 0x4f787cf6, 0xfe787e22, 0x9fa353f9, - 0x5f4bef57, 0x8f95ac2e, 0x2df8a9b7, 0x90e547e8, 0x98165591, 0x1fa9aed7, - 0xa1107ea1, 0xd427c5fe, 0x249420cf, 0xbe6cca8f, 0x04bfa8cf, 0x2fea36f5, - 0xd5213b41, 0x75e25fb8, 0xae8c307d, 0x3f289f3f, 0x26f3ee17, 0x9e3a2964, - 0xc8f7f8c4, 0xf807c11a, 0x14597db8, 0x3d687e05, 0x4d38de85, 0xfb0fee9d, - 0x7c12ae07, 0x86380bcf, 0x9333e01b, 0xbd60478f, 0x67605eb4, 0xe8a21cef, - 0xb0514fef, 0x8a40d560, 0xb338d08b, 0xa44e4b88, 0x5a59cfef, 0xa2e84328, - 0x2f061055, 0x2059fa01, 0xe0119753, 0x69278de7, 0x7ae8389c, 0xf1b3b66f, - 0x63e4ba67, 0x14f5aa6d, 0x3e5766c8, 0xa1414f5d, 0x359feb88, 0xd1fedb43, - 0x619728ce, 0x3d572d0c, 0xc9ccf381, 0x54dfb6d7, 0x75cfada0, 0xef54eb6b, - 0x6ef7a0c9, 0xa73fd129, 0x9cfba160, 0x5d2b8417, 0xade75d28, 0x56b70e1c, - 0x5e0d5ec9, 0xda556dc1, 0x26e0a021, 0x5f7c2fb8, 0xf6ffd9ec, 0xa17ada65, - 0xb05f5b57, 0xa73e374a, 0xff1ce39b, 0x683e8047, 0x83e80279, 0xa718f3c2, - 0xd55c908f, 0xc18dc7d2, 0x50fa306d, 0x625c71f6, 0x8ebe3828, 0xdac2c7d1, - 0x50f4f0a8, 0x9707a418, 0x7a14be9a, 0xc3d38db8, 0x8a1e9ca7, 0x6ae96ad7, - 0x4cadf12e, 0xb2dfefa2, 0xe9e21766, 0xe8c850a0, 0x3d0a97e1, 0xc1e869b4, - 0x8f41e9cd, 0x3d38dbbf, 0x4673f6dc, 0xb67c7a0f, 0x5b687a71, 0x29264e7b, - 0xf14af13d, 0x3c53a9a0, 0x376ef0e8, 0x7c503d02, 0xf987a584, 0x8dd37dc1, - 0xde02fad3, 0x9c5f03d6, 0x053db01e, 0x4e104ec0, 0xcf6a7ef8, 0x684e54fe, - 0xc36bc5ea, 0x31b2bfe3, 0x6a98ee3b, 0x57f5e55d, 0xf5531dc5, 0x53375c5b, - 0x9be45f53, 0xbc5fe9ab, 0xbed350b6, 0xa69176b0, 0x3baac17d, 0xef42f535, - 0x6ffd35cf, 0x69ad565f, 0xb56ab5bf, 0x9296fda6, 0xb9f534c7, 0xfa6b5fee, - 0x5eb054df, 0xff273ed3, 0xacfb4d45, 0xf5345b19, 0x34d7ae99, 0x2f3b0dfd, - 0x31e81ebd, 0xc048a0eb, 0x71e638fe, 0xf71fdd20, 0xa4f2c48c, 0x717c89c7, - 0xcb0133da, 0x4fcd8d7d, 0x7cbb495c, 0x26882819, 0x91167f4c, 0x2cf64218, - 0xcaaf5777, 0x504e7d02, 0x7971feef, 0x1077b551, 0x07065395, 0xad6f39c2, - 0x11c7f891, 0xe2528022, 0x50c407f3, 0x6d1b567b, 0x3dbdeb8f, 0xb614ad6f, - 0x0a4dab3d, 0xe3e56e3b, 0x61ed4385, 0x7e2133e2, 0x3ec10326, 0xb9f6e2ea, - 0x204cbdbe, 0x84e7eaf9, 0x8ffe472c, 0x5cfd3031, 0xa2726466, 0x1cff6b6c, - 0x7fba8362, 0xe685d544, 0x95cca7ab, 0xaa91f408, 0xb5e2e3e1, 0x3ce46997, - 0x3c6de881, 0xcd38d9d0, 0x5775c5f3, 0xd8ebde6a, 0x2bbae225, 0x7d508640, - 0x07e48c3d, 0xfd97a00c, 0x8d6643cd, 0xceba7586, 0x355e401a, 0xd8fda3c6, - 0x771199e1, 0xe63c024c, 0x53d27963, 0x8f71e580, 0x9e63cb1b, 0x788f2c12, - 0xf36cb0aa, 0x33f2c32c, 0x4fcb178f, 0xfcb0ab3c, 0xe58b53c8, 0x2c5acf61, - 0x587c7a0f, 0x61d4f01e, 0x1ea7bef9, 0x234f56cb, 0x171e9d96, 0x29bf0a96, - 0xddd3d0f0, 0x4fa7ae49, 0x805dfd03, 0x07c4e2ce, 0x0a0d57aa, 0x8ae259d1, - 0x59bdab87, 0xd6f371a1, 0x249d389a, 0x0861e868, 0x81e364f8, 0x5e9c4c5e, - 0xade7b7c2, 0x9ed82f95, 0x1d8726d5, 0x7ff9f2bf, 0xf9cdbd0d, 0xa216f491, - 0x7a3a81a7, 0x3d18bd4a, 0x87c7124d, 0xc18e69e8, 0xa71ff4ce, 0x1f6087a7, - 0x628ffc61, 0xabc6ea30, 0x14573aec, 0x73f3678b, 0xb2d16a07, 0x7b9f3678, - 0x15ae1d05, 0x48df3fed, 0xc8f773c0, 0x78808fbf, 0xaa61f77d, 0xdf7b9328, - 0x7a5e9e9f, 0xfd0bbb87, 0x551f22a0, 0xb67ae3a2, 0xb8324447, 0x0cc81846, - 0xeac84e92, 0xce75bfe1, 0x44bac34f, 0x9f7de162, 0xf3986673, 0x4f670228, - 0xeb871789, 0x6357eb0a, 0xcfe3bc60, 0xca1323fc, 0xe6148639, 0x688b34df, - 0x0bff13df, 0x506f804e, 0x499c991f, 0x0c0f0710, 0x3ed1da37, 0xf0b459f0, - 0x667ad2f3, 0x29ab7e08, 0xdf515a8c, 0xfc2126d7, 0xa2357d86, 0x77e01f7f, - 0x317f3931, 0x0df7ce78, 0xf3c097f8, 0x62f1f262, 0x1cb89172, 0xfdd2372f, - 0x9d1ced77, 0xe403a0fe, 0xade185e0, 0xd7e95f9c, 0x7d28bcf3, 0x4aee3a2f, - 0x75b8e850, 0x88f3a108, 0xefc71da2, 0xc984b86e, 0xdbeec52f, 0x05f5f266, - 0xb59267af, 0xf9c53de3, 0xbbaf194f, 0xf81b05e5, 0x0c924b5b, 0xf06163f6, - 0xf5e594a0, 0xda8b76c9, 0xd6d46cfe, 0x19856bbb, 0x3a2768f5, 0x068f67a2, - 0x1fb7613d, 0x3b72061b, 0x9c654b09, 0xfb464925, 0x4ef72a31, 0x3346a5d7, - 0xe4c7cf3f, 0x9418e6c1, 0x663da717, 0xaf53ffec, 0x9471b7a7, 0x40d210f5, - 0x1e419a8e, 0xded4b6d3, 0xcf4af7fb, 0x3c4617d2, 0xbf926df7, 0x4cd0fb02, - 0xfc0effff, 0x5d61220d, 0x5eb2b719, 0x872e9af4, 0xf3359be7, 0xca1cf7d1, - 0x2977eb19, 0x891be217, 0x96e8571c, 0x5c638bea, 0x8bae2c9f, 0xcfed6bb0, - 0xb2bd4d18, 0x635dbfb1, 0x541fc28f, 0x412a92fe, 0xe329fa02, 0x5925d3e4, - 0x7d740956, 0x1090426f, 0xfd6056e8, 0x466dcdca, 0x95ce03b7, 0x5b7ade19, - 0x4cdfc51f, 0x897c9289, 0x61cf16b9, 0x9d2fea4b, 0x4ce67a0a, 0x88048ac3, - 0xbb162c1b, 0xf30fc9ef, 0x79312cbe, 0x0727c8bf, 0xa73df6b4, 0x55c7420f, - 0x945c639e, 0xeaab8e58, 0x8f16061d, 0x009b8fd1, 0x1c5fc6e3, 0xf79b153e, - 0x413b074f, 0xc68aa70f, 0xca3746b3, 0x665ffa45, 0xfc0a4e08, 0x13f314de, - 0x697e3a24, 0x2dc63b5d, 0x11deca4e, 0xbc80bcbf, 0x4b3fb9ec, 0xd528f1d2, - 0x15a4bcbe, 0x813f99e6, 0x371c444f, 0xf8e54c7d, 0x04c93fa9, 0x4f3910e4, - 0x4862657b, 0x063bfb86, 0xf90cc862, 0x161bf33b, 0x4fbc01e7, 0xe547bf81, - 0xdf241de6, 0xb5207886, 0x9cdfe099, 0x00198621, 0x7de433a7, 0x1e1538db, - 0x87232572, 0x94829533, 0xf1c14c1e, 0xefc1fddd, 0xb4d41532, 0xb9e0638a, - 0xc23ff8a4, 0x72471877, 0x50b7980b, 0x897b9ec0, 0x97e81ab9, 0x3f1a51fa, - 0x9a51fa8d, 0x34a3f53a, 0x437222f5, 0x1425e402, 0x9f13293d, 0xb4d27080, - 0x88ec928f, 0x555262c7, 0xafd1f603, 0xbe6dfc79, 0xe903489d, 0x7d5fcb3e, - 0xee90b336, 0xc5896ae7, 0xf57394fd, 0x0e0cb145, 0xa33e25a5, 0x7f73d2cb, - 0xddc61b47, 0x8c3f2548, 0x6fcfcec7, 0x051e6236, 0xdc994ab4, 0x7de949f4, - 0xa20d89ff, 0xfd06c22b, 0xbd6573e8, 0xff7fdfc9, 0xf212fdfa, 0xb4a3ee38, - 0xfa01266e, 0xc02791eb, 0x09d723f7, 0x7e185f2e, 0xaf74e42a, 0x013ba7e8, - 0xf143e37e, 0xf574fbac, 0x4abe1cd5, 0xfb5d29fd, 0xfd2f960f, 0xbcbe4688, - 0x93efba29, 0x027933c6, 0x00a417f0, 0x1e0fd7f2, 0xf8c7a93f, 0x7f1f81ab, - 0x6907f1b2, 0xff8e9ef9, 0xfeba4fd4, 0xbfd63d61, 0xcbfadc3e, 0xbb697d5f, - 0xd297ea97, 0x23653c3f, 0x494edf94, 0x8a4e09b5, 0x2b8db2f7, 0x3b902e6d, - 0x7c06d792, 0xce27ca71, 0x870f4708, 0x06a57cb8, 0x78804588, 0xc749fc2b, - 0xa1e9bd3f, 0xf89ec0eb, 0xc76ca36a, 0xc99d6a38, 0x5cf4a26f, 0x8f28b0d1, - 0x3b7ac18c, 0x16703fab, 0x51b2bfe8, 0xd3a6a23e, 0x953ddfd2, 0x94357900, - 0x921a0652, 0x7fa3f4a0, 0xf3e1b152, 0x546f60e9, 0xabf20092, 0xff983dfe, - 0x87d4589b, 0x9ee8c685, 0x499818ed, 0xafd9f780, 0xb3a1e1b2, 0x6afe0da2, - 0xbe9038c3, 0x37f7097f, 0x3f6b245a, 0x82b9273c, 0x54f2015c, 0x31f10781, - 0x8bc5637f, 0x4ed31abf, 0xe1b1d3d7, 0x0541364f, 0xea4fc527, 0x9bf05fae, - 0xcbbd1dd7, 0x87ca4eef, 0xd156bb6a, 0xee468e4f, 0xb2b13527, 0xaedbf64c, - 0x6ca4f2a4, 0xd2f4ecbd, 0xbd2f65c7, 0x2067dbf0, 0xc9a1fd7e, 0xbf8e9c39, - 0x073da5f8, 0xe2fad127, 0x3cbf722d, 0x908b0db6, 0x254bc210, 0x7a597ffd, - 0xafa50f08, 0x463a31ec, 0xc6f7e7b3, 0x78b1f086, 0x19232ecb, 0xb91e13dd, - 0x6d8cbbf5, 0xa9783096, 0x760e9f6f, 0xbf178adf, 0x3bbc8236, 0x892053b5, - 0xb9e061c9, 0x85da0f7e, 0x23c42700, 0x6f1053c7, 0x1495feba, 0x145fa02f, - 0x37dbe93c, 0xe3027971, 0x9e90d239, 0xce9d7e5f, 0xc991f25f, 0x792ffb09, - 0xec1b2ef9, 0xc55484e3, 0x95d9fae8, 0x4adf2009, 0x1d826f64, 0xe4bcf64b, - 0xde91bbb9, 0x9ddff78a, 0xae92e2c0, 0x95d406fe, 0xbfb0fede, 0xe0e6eb85, - 0x1b888afe, 0x59e4aee9, 0xcb47df31, 0x6332252f, 0xb8be184b, 0xf2726656, - 0x2354f3c4, 0x509dfdd0, 0x22fbc0f4, 0x627703d7, 0xbe6ef3dc, 0x62316a17, - 0xc3334bfd, 0xc0d930d3, 0x2bd32ce5, 0xf0dd7a41, 0xd38bea00, 0x70895d83, - 0xd21956be, 0xc437a80f, 0x1912d3fd, 0xc19e987e, 0xc99ea8f7, 0xbfd0e785, - 0x8c457655, 0x7a87bcd1, 0x297f9945, 0x3bae9f9f, 0x13b5ec12, 0x8ffde109, - 0xdf0acb9f, 0x4542bb53, 0x66fe2a5f, 0x3561befc, 0xdf856fe3, 0x4067337d, - 0x180717fb, 0xa07bc0ff, 0xfcbae967, 0x6bbed889, 0xc0f280b6, 0xf8e1fc44, - 0xf9cc837a, 0xd0aedb5a, 0x24b75d09, 0x05e8ab44, 0xf8458fc6, 0x7a2f5ea3, - 0x92a7be92, 0x9f309597, 0x0a78e7ad, 0xfe7316df, 0xf96b219f, 0xef8bac9f, - 0x99653e53, 0x33edfbec, 0x3f94afc0, 0x57e00ebd, 0xfdf61f39, 0x07cdcdb7, - 0xfa7ca66f, 0x4f857ab7, 0xcf53f2b5, 0xef5b25a7, 0x7a9f4026, 0xa0dbfd3e, - 0x4f96122a, 0x7cb0f3e9, 0x7feda83a, 0xf02a7e54, 0x45f802ab, 0xc8a7e085, - 0xa8e0dec3, 0xd9568797, 0xd21e5611, 0xd99201df, 0xba14fe93, 0xf4ade853, - 0x4143e5f7, 0x52e904ee, 0x5d20bba1, 0xdfa7742a, 0xfa7e16af, 0xc13249f6, - 0x26bfe575, 0xd65cffa3, 0xe942f2c4, 0x66077b7b, 0xa85c9c20, 0xdeed48c6, - 0x75d4fd81, 0xaf5eae9f, 0xd5d2efeb, 0xddfd75f3, 0xa6957aba, 0xb363597f, - 0xfdfe2091, 0xb2e27e9a, 0xb8d1c867, 0x63eaf470, 0x59c3597e, 0xc2e817a3, - 0xe5f7c012, 0x790bc4e5, 0x221d8186, 0x28ba05c6, 0x7e206b8c, 0xe7d939b1, - 0x656372a5, 0x743f8b04, 0x58b603d9, 0x618cae5a, 0xb1bc40f5, 0xf29ee406, - 0xe2c1103c, 0x01f95d8a, 0x9fca8c5b, 0x51126f6a, 0xc8f9b76e, 0x167e708c, - 0x47c828d5, 0x76b7a46d, 0x4d35ee76, 0x06590cb4, 0xd15aa571, 0x1df83609, - 0xe0d937d5, 0x29aba9dc, 0xfa02faf5, 0x451fe17c, 0x8ae97b4c, 0x75818db4, - 0xea4baf11, 0x4e6ff2af, 0x59d3ef12, 0x9a0b7f74, 0xc7739f98, 0x423d9d1a, - 0x153d20d6, 0x411a9659, 0xe27f529e, 0x86bcf688, 0x1f2945f1, 0xb69d64af, - 0xd29f795d, 0xa5f3fa01, 0x6eedb41b, 0xa07f0fee, 0x3258c9f0, 0x2ca3fb96, - 0xf2e5c30e, 0xfaed3134, 0xae8f8a02, 0x68989116, 0x4449bbbd, 0x166f747c, - 0x234f107c, 0xb7e478de, 0x7940120a, 0x03a9c0a8, 0xbbd8c9f8, 0xf6d8eabc, - 0x812fe669, 0x3c7fb66e, 0xd9693fe6, 0x11c3fdb1, 0xd5fd406f, 0x263e4343, - 0xeee7fb3d, 0xff73c08c, 0xa4569dae, 0xef1daef7, 0xd425f90e, 0x6139335f, - 0xbf3b5d9d, 0xd3f4031e, 0x0254dcb5, 0x306baef2, 0xd8aec78b, 0x3698f5f1, - 0x33f7afd4, 0xfe6461fd, 0x3fd37761, 0x41fa133e, 0x76057749, 0xe428cec3, - 0x23d7caa7, 0x6bbbdf30, 0x6e99d7c7, 0x9fb74fcb, 0xd1e79e0a, 0x5b052565, - 0x2c317d61, 0x8df2a18f, 0xd3542f89, 0x761bcbf9, 0xf6d01719, 0x39ff37dc, - 0xd768e406, 0x750f6656, 0x41cf6dca, 0xf194431e, 0xe29972dc, 0x8a9813ab, - 0x33bfcd3a, 0xdf02e466, 0x3fcb84f4, 0x57d63e31, 0xaffca478, 0x62e08781, - 0x33eacef2, 0x6fefb00b, 0xe318fb3f, 0x4ba4269a, 0xab7fbf65, 0xe57b46af, - 0xfecefb62, 0x82df6e7f, 0x76fb2fbf, 0xfbef9bff, 0x7abbd738, 0xe749e83e, - 0xfac1ee3b, 0xae27564b, 0xeef48fb7, 0xffc7fd85, 0x7bffeefb, 0xc52b7de3, - 0xfbe2edbb, 0x5affcdfe, 0x36f1ffbc, 0x7e3b778e, 0x3fe6f3d7, 0x57df7d71, - 0x6ff9bdce, 0xf6def78e, 0xadf5d8af, 0x067b2a86, 0xa9015f5d, 0x316182b5, - 0x92dbbe37, 0xd76c80e1, 0x8f30fd73, 0xc34bce0e, 0x23014df8, 0x904d0bf3, - 0xfb7e0747, 0x0b89411c, 0x1d751fa2, 0x1bae1fb7, 0xc8768254, 0x9987ae75, - 0xb55520dd, 0xadfed366, 0x989c0b39, 0x0fd24973, 0x7b3ea1bb, 0xfd6baf32, - 0xe204f7c9, 0x7f1da812, 0x2d35ce5d, 0xef5ed760, 0xa5eed112, 0x1fbbda25, - 0x9ece990c, 0x3dfad04f, 0xfadadd73, 0xfada054d, 0x8dde3e1c, 0xc6ffad84, - 0x7107c17c, 0x13f65355, 0x356710f1, 0x9089942d, 0x5542f90c, 0x98bfc12b, - 0x7f7daf93, 0xe3c1f81f, 0x531c3c7f, 0x971c0a4d, 0xb6485c20, 0xfa48dce8, - 0xeebe4700, 0x7d63d9d6, 0x244ccf90, 0x8de38327, 0x838c4ee5, 0xe65b7f73, - 0x5596cbef, 0xb2cfc0ad, 0xfc56cfce, 0x4de0dee5, 0xe38dffb8, 0x2fe084a4, - 0xbff444bb, 0xadff9d65, 0xe2fbe5e0, 0x8fe3c143, 0x3a97cbc5, 0xb8b20cbc, - 0xccabf008, 0x16a985fd, 0xca0fab27, 0xc8de7827, 0x9fa905fd, 0x42d3788b, - 0xcc8bdf79, 0x5f386ce6, 0x30148f33, 0x1afd71de, 0x3983f511, 0xe575c04d, - 0x8f31904f, 0x7e4373f8, 0x6f3be026, 0xbf1515dc, 0x0270cb60, 0xb871173c, - 0xb42a9117, 0xeff9c95f, 0x84cacbbe, 0xf6820673, 0x211722ef, 0xadbf52d7, - 0x47f04b28, 0x4b157852, 0x0e9d1bc4, 0x1c816f71, 0xb5bdc4d1, 0x47fdf875, - 0x8b9c6842, 0xbe4deff5, 0x5fe5d4fc, 0x323b3ca9, 0x1e41fa8c, 0x5849bb9e, - 0xaff156dc, 0x70626f6f, 0x7c132cac, 0x7e774829, 0xee755f39, 0x83e71cf8, - 0x0e3bdebf, 0xa3f664e5, 0xefd1a3a3, 0x6fd03977, 0x437ee4a8, 0x0d11d7b7, - 0xa6eeae71, 0x9b3e7e54, 0x55cb536b, 0xfdcfdca5, 0x7e40bfee, 0xa6bb2d21, - 0xf822b50a, 0xf1802471, 0x08d4ef5c, 0xfe4c31b2, 0x1931ffeb, 0x6154fd38, - 0x627e001c, 0xfd91e026, 0xd1abe98a, 0xadbc2ab1, 0x3494f6b9, 0xe01e27a6, - 0x0e754477, 0x0be163f9, 0x75c03e7e, 0xf4db447f, 0xadfb30fc, 0x5638b135, - 0xe2df5bde, 0x34379c77, 0x9700cb25, 0x9a8aa61b, 0x2655fb73, 0x238d97ee, - 0x795d60e3, 0x9b655d6f, 0x11697808, 0x66ddf09d, 0xa359d365, 0xb079cc3b, - 0x3e309e1e, 0xca8fd5c4, 0xe78022ce, 0x082387d1, 0xf2efd1f8, 0xf834c673, - 0x430d226e, 0x2b882e3a, 0xb5c39afe, 0x72c764d3, 0x1cb65e56, 0x6b4de74f, - 0xa3858fb0, 0x7fbc01d4, 0xe3211827, 0xbd878921, 0x501bf4a7, 0x1bb5fac6, - 0xf6e115ed, 0xed823c3f, 0xef3898bf, 0xfbfc2099, 0x51fb2de1, 0xec073fab, - 0xae3ca983, 0x09ae83d2, 0x0cf747f2, 0x1bfa07c1, 0xe7ac61fc, 0xdf84efb1, - 0xbeb3be55, 0x8559e981, 0xde70f5ee, 0xccace1cb, 0xe2c4dc7f, 0xfce27faf, - 0x8159c0a5, 0x4abd7eaf, 0xa6af2a7f, 0xd751e3a8, 0x197d8e37, 0x268a9bec, - 0x43a06ec1, 0x466d4855, 0xc6cac3e0, 0x6f3864c7, 0xe360eb99, 0x8c7f2912, - 0xd3a09f3a, 0x9a3bf2c4, 0x0dbcafd3, 0x1adce4e8, 0xe242e813, 0x0dace3ba, - 0x06bbf0e4, 0x7be19fe7, 0x227bef6a, 0x790178d9, 0xcea7b1f5, 0x8f525535, - 0x9ceb8c9b, 0x432d9655, 0xb296ecf8, 0x8aa2725d, 0xb14d3a9e, 0x1f3caed8, - 0x8748e650, 0x5c3e74e7, 0x1311f787, 0xd242ef81, 0xfbf15bea, 0x62aa5bd4, - 0xd4961d18, 0x3d6232ef, 0xf32bfb19, 0xf9e8f329, 0x369e7669, 0x6e4178ef, - 0x4b8020db, 0xd4bfc99e, 0x1f4e8619, 0x8ee72b33, 0xb84f53df, 0xf98edd28, - 0x2c4f48ff, 0x1b44f455, 0xef2bb9e6, 0x3e3335cf, 0xc489e957, 0x49627a70, - 0xf01123b5, 0x6a4764b0, 0x92c93022, 0x084b4e3f, 0xf03e27a7, 0x43e373b0, - 0xaeeebbfc, 0x5c4f54d9, 0xb313d2ae, 0xf44e9023, 0x959ae5ef, 0xe88b8d73, - 0xff6f0509, 0x03e6f2c3, 0xf86113d0, 0x56b346fb, 0x54d8dc4f, 0xc6e27a88, - 0xfbe6a2d9, 0x17cd6baa, 0x09d913d3, 0x3b2eb173, 0xcfd0c2a3, 0x39bfdc07, - 0x61fbf3c4, 0x6b17d01e, 0x9b8476cc, 0x26f46f5e, 0x55f6c7d7, 0x825fffae, - 0x97d722b3, 0x43f761cc, 0x8243a4f4, 0x2e64bcf4, 0xd002eb95, 0x4beb9323, - 0x4e71e56e, 0x07cd9c9d, 0x96a19b39, 0x0afdecb3, 0x950bd337, 0x9abfc98d, - 0xae6fdb47, 0xda669d95, 0xdc90e6ff, 0xddcb54cd, 0xe1096635, 0x96ee43dc, - 0xae7bb930, 0x4fda1c69, 0x53efedbd, 0x3ca96f2e, 0x430ce61b, 0xa2f3051f, - 0x1ddfdf34, 0xda76fb1d, 0xef2fc02b, 0xfb7e788a, 0xf603b739, 0x033b7d8d, - 0x7c53e9ec, 0xfcb8db3d, 0x5cf8f4eb, 0xc81ca953, 0xd3d983bd, 0x84459be5, - 0xe303455f, 0x91618aff, 0x4fad073e, 0xcf16ff4f, 0x60ef1761, 0x0774b0e7, - 0xfc2ad979, 0xadb77e2f, 0x1605ce06, 0x1cf017af, 0x005fbe19, 0x78731678, - 0xe3173916, 0xdaf14a39, 0xe53fe7f0, 0xa6a2dfbc, 0x5f0f18f5, 0x2bf6d3e4, - 0x29f5761f, 0x4cf247f0, 0xaf790f0c, 0xc9f5be08, 0xeba0cf90, 0xe78d5ce7, - 0xdaf5e547, 0x7ef907e7, 0xb4fe8a17, 0xe4fbe857, 0xd3bfcccf, 0x1ea0fbc3, - 0x123f252e, 0x5c29fb2e, 0x70f5fe32, 0xd40e0de9, 0x01f3c7be, 0x2b0e3c3d, - 0x649d2572, 0x6e7e1f00, 0xf15ca170, 0x42e143be, 0xb1e3bbe7, 0x40fb9ae1, - 0xbcb8738e, 0xf4d7706b, 0x02157e87, 0xb75e2bf6, 0xad024f65, 0x6327abcf, - 0x78a178e1, 0x070f56ad, 0x03837ef5, 0xaabcfaf5, 0xc7e4022d, 0xfbdfe42e, - 0xc31ef895, 0x5d6e547b, 0xed3cf546, 0xe4dd20bf, 0xfdf07386, 0x9b940111, - 0x47c6dd0a, 0x8e25fb30, 0x03a3a1cb, 0x3f515302, 0xe4760a35, 0xd3047f47, - 0x704f1457, 0xc4f34bbf, 0xbc73a7af, 0x2352b8b0, 0xc52563c3, 0xf4f3f01b, - 0x63af5e26, 0x4a2de076, 0x39f05ebd, 0xbbab9004, 0x8c5f7664, 0x8e04e240, - 0x847e9504, 0x04ecd5f3, 0xb4779e15, 0x28dffa33, 0x8f81f138, 0xf043f7fe, - 0x33dd2bdc, 0xf4afa63b, 0x3e29c0ae, 0xfde78b42, 0xe379ad11, 0x9bf9c1fa, - 0x737bc4e0, 0x9cf0629a, 0xbb2d58e8, 0xbf9525ff, 0xf00be7a7, 0xd1f7d43b, - 0x438584cc, 0x088cf37e, 0x79c50fcc, 0xa65d9853, 0x7bfa4f96, 0xfe6fbe80, - 0x45692551, 0xc7942c7b, 0x04de7ee8, 0x3410cde3, 0x09104ef9, 0x09ff3a03, - 0x7cd5bfc6, 0x9249f181, 0xef96f31d, 0xedcf2bb2, 0x5e2cbbec, 0x799c1e6f, - 0xef851e68, 0x13a255b9, 0x0c9ba85c, 0x2059838e, 0x09941e6f, 0x7db9cbf0, - 0x81e98bb2, 0x853bd428, 0xefc51eef, 0x0e590ad9, 0x8fbc291a, 0x7ca397e9, - 0xbd511f3d, 0x0a5882ed, 0xf70f1fa9, 0xee76cce0, 0x7880e69a, 0x95fec64b, - 0x2b39ce70, 0x20f07ed7, 0xbb3573e0, 0xaac8e907, 0xeed3f45c, 0x7e4053ba, - 0x06f14c3b, 0x9d99cfef, 0x9d20f07c, 0xf155d6f7, 0xcf396e78, 0x9c237f15, - 0x27dbce63, 0xdfb41d3a, 0x16adeb82, 0x66bcc738, 0x2adc48a4, 0x5a4adcf8, - 0xaf33be31, 0xb039ceea, 0x0faa12ee, 0xf72864c5, 0xfa844b4f, 0xafdf013a, - 0xf08dbaf4, 0xdaeb66bd, 0x3a0cc6b3, 0x07ed117f, 0xc75caf60, 0x106e55fa, - 0x5dfa909c, 0xca18f4d4, 0x020da2cb, 0x4ad3345e, 0x1b335fed, 0xe3a667d7, - 0xefa3aeb6, 0xbc317ad3, 0x886ee30f, 0x27ce11b9, 0xf13ae92b, 0x78d509fd, - 0xdf445d2e, 0x75a4cda3, 0xde389dc3, 0x810275a2, 0x264b03ef, 0x01323f24, - 0x3b27dbc6, 0xaed0fda1, 0xdd611b5f, 0xfaf9d1b7, 0x8817f1d3, 0x3fa0d36d, - 0xc760a5f9, 0x46ea87fb, 0x0baddc60, 0x542f0c36, 0xe63ac70d, 0x0c103b13, - 0x651f3a92, 0x4efb0447, 0x755968b8, 0xcdabec0d, 0x406c9f1b, 0x046b3aba, - 0xc28c7e3d, 0x3c874ddb, 0x2e79646a, 0xc6a3decd, 0xfd1c9536, 0xdf152228, - 0x1b31a3bf, 0x921626f3, 0x709bcc7c, 0xa47b3357, 0x0f84657d, 0xb2ed6ae2, - 0x6f3c087d, 0xe7c2695e, 0xfd312f9d, 0x0db839d3, 0xd627dbe3, 0x5fbe04c9, - 0xf52eb15c, 0x89e3c069, 0x9bd232cd, 0x1bcb2cf8, 0xc5897e28, 0xb1d79ac9, - 0x352c4f71, 0xa0b57bb2, 0x5f8bd69d, 0xb40af254, 0x51c8ac72, 0x2f4a728a, - 0x6b72f497, 0x46d593d1, 0xf21ed920, 0x9474e96a, 0xef54a557, 0x90f5a100, - 0x306a8357, 0x5797aa6e, 0xc8a2c495, 0x5f8874a9, 0xbe0f9616, 0xf1d02d6d, - 0x8183ecad, 0x5f6bff56, 0xb77a053e, 0x49e04acc, 0x5a7f6485, 0x80417460, - 0x6d35e65f, 0xa0f812f9, 0xde045e64, 0xf01c75c7, 0x26b37c00, 0x8bafcf0e, - 0x6f08857c, 0x78b72f25, 0x95ce96ad, 0xb75ce3f8, 0xfd6a5c48, 0x5c451255, - 0xee877eaa, 0xe74af4a3, 0xf051bdb9, 0x743ca881, 0xbbdefb5f, 0xc76eb033, - 0xf6e32d75, 0xd22b1ac1, 0x9f9fa1f3, 0x7af4095d, 0x0102bddb, 0xdd789d7b, - 0x2b0fa035, 0x880e0ad6, 0xcbdf170f, 0xefa62fde, 0xfd0fbac3, 0xa515d19a, - 0x7fd0076f, 0xf6c7bac5, 0x820dff62, 0xb43fc603, 0x89ed10be, 0xb048af12, - 0xfa3b437d, 0x614f540f, 0x57b3599e, 0xaffa004c, 0x0764dfb8, 0x23a14953, - 0xf9db2e85, 0xecc4087d, 0xbe8b331c, 0x15160ab7, 0xc51e93df, 0x4fa82102, - 0xbd2a4e81, 0x5fdace8c, 0x36409d92, 0xf64ba717, 0xae09fc1d, 0xe767c55f, - 0x74ef874c, 0x047ea98a, 0x975e6d3a, 0xe23b046b, 0xfcc04f84, 0x49749e8a, - 0x4a3b6a2c, 0x0567cba1, 0xd07baf26, 0x7b0e8ea3, 0x4ba71dd0, 0x5128fe85, - 0xb6595fa3, 0xfdf0264f, 0xdd1e9ebd, 0x908dfd72, 0x32f851ff, 0x6f5d0fdd, - 0xd1cfcd6e, 0x48e0575e, 0x2f5009eb, 0x8fde5892, 0x12e50fc2, 0xdefb0fcb, - 0xbfcdd3eb, 0x87e78229, 0x2c883f01, 0xe74fc97f, 0x0bf37b7d, 0x66792f98, - 0x6875fb53, 0xe941bcdf, 0xd9bfe000, 0x7fe8fc4a, 0x950e50f8, 0x6f988836, - 0xe67f244d, 0xaedf952c, 0xfe2cbfe4, 0x5de11583, 0xcbe4d5ba, 0x6e97efa3, - 0xf3063a3f, 0x30079611, 0x49bbc7bf, 0xde1fe760, 0xfdf031b6, 0xf2c4a950, - 0xc176f470, 0xe71648f0, 0xaa2d78ea, 0xa136ec00, 0x57b3dd8e, 0x6c937f5a, - 0x0775c552, 0x2f38ca45, 0x63e787ed, 0xb8678a5e, 0xa7d6011f, 0xc94ddfbe, - 0x9178e9bf, 0xa3695fd1, 0x695cf68c, 0xc84e96dd, 0x6c3d2cc3, 0xb2b73f42, - 0xfc11acee, 0xbc3fdcd8, 0x55f3f784, 0x3c9a8a36, 0x6ff91ebc, 0x04dfa275, - 0xe50d5bf9, 0xeb437e78, 0x0faf58ed, 0xb17a079f, 0x7fc5ad3c, 0x4bddb1d8, - 0x95f8b841, 0xbef0d9df, 0x368dd6be, 0xeea9eefc, 0x3da7f9c2, 0x57eaddf2, - 0xeddf305f, 0x0941fc34, 0x5d48baeb, 0x931d60be, 0x997d746b, 0xc4e261f9, - 0xa5eb7b41, 0x7c839f2f, 0x7fad8eec, 0x5bd60e7b, 0x9ee75ff6, 0xb21abc83, - 0xf60ec233, 0x0fa6e548, 0x79559f30, 0xd99224af, 0xfe2f9d7f, 0x3b80f30e, - 0x6139343f, 0x271dceb4, 0xd1bd8086, 0x04dbe5b9, 0xba5defc8, 0x73c61a63, - 0x4dcb6e96, 0x05e26124, 0xeb74094a, 0xb21e43eb, 0x0dcd5f1e, 0x73ff98cd, - 0xe41be286, 0xb17f3043, 0x83e59cbe, 0xe2de783a, 0xdef9f0e6, 0x1b14f23d, - 0x193f5d66, 0xb30362e4, 0xaf9a2e0b, 0xf1e28078, 0x6fe03ef2, 0x4f2e6af3, - 0x0cefe3c2, 0x54f141fc, 0x57cda913, 0xe161b2fc, 0xb6819e6f, 0xf35eb886, - 0x807dfd15, 0x3e4f929b, 0x58f5d22b, 0xd6cdf024, 0x287e63df, 0x01cf2de0, - 0x21cbf9f2, 0x293e1710, 0x10fe3007, 0xefc261d8, 0x1c774b2c, 0xdce9fe42, - 0xb5f31fb6, 0xeeebcf09, 0xcb1fc124, 0x9eb1e5c3, 0x96560dca, 0x0fe1c8e7, - 0x1b0e9079, 0x8ef9e73e, 0x3c958e8c, 0x1ff2dec8, 0xf853225b, 0x4f2c2a7d, - 0xc7c37cb3, 0x8430af3c, 0xe002612f, 0x7982fda9, 0xec1c0aa5, 0xd42b8700, - 0xf3e1bcf9, 0xdf79834c, 0x3f805f1c, 0x7cc1d390, 0x041f5a5d, 0xe13e9bf9, - 0x0f230910, 0x3cb3d73a, 0xfc394ee0, 0x7e4accf7, 0x4f9eb36f, 0xebcb7d7d, - 0xbffad8bd, 0x221a7c2f, 0x1eae381d, 0xc3e71d4e, 0x9ce3f1cb, 0xf7f07fef, - 0xfe826521, 0x81cf93fb, 0xda1bcb1e, 0x899f788d, 0xfdf13fe2, 0x5a78f076, - 0xf31126c7, 0x9bea6b3e, 0xe5eb8e51, 0x273f0545, 0x1bf7afd1, 0x468adebe, - 0xb63a27a6, 0x3a167d5a, 0xaf5bc74e, 0x6c573d21, 0xd3bcc76e, 0x18af75bd, - 0xcbe754db, 0xaa7c27a0, 0xbcbc77f5, 0x6dca0c6b, 0x7e98bf7e, 0x9b14631e, - 0xfc29b2a7, 0xcf9b953c, 0xec59e66a, 0x2dda37ad, 0xb4ef9f17, 0xc609bae4, - 0xeccadd3b, 0xe2f5d3a5, 0xf9985f0c, 0x49bd714f, 0x0f3b2d48, 0xef12faa5, - 0x7bb2b359, 0x245b44d5, 0xad4b5fda, 0xf7470e13, 0x7988d283, 0x79aa2b2f, - 0xce7dcc9e, 0x0af7c024, 0xd604d5eb, 0xabe012bb, 0xbb65e3f2, 0x26dd809b, - 0xa867e527, 0xf59459cf, 0x8819fb1b, 0xa5ff854f, 0xe08919d6, 0x3bc9127f, - 0x5d71d608, 0xe812d7ca, 0x8b0f56bf, 0x47f393df, 0x56f3c187, 0x8e27bec9, - 0x553adb8e, 0xb5e84270, 0x34fbdd27, 0x2e998671, 0xf8b17ded, 0x5fdd1c0d, - 0xf680d3b7, 0xb7e0d5a0, 0x1ac42ed3, 0x0e849ad1, 0xa43883ac, 0x0214fc04, - 0xf41e21f3, 0xfdc16798, 0xcd4236c8, 0x94e7e853, 0x449ff734, 0xf774904f, - 0xc30390a1, 0x385abd28, 0x39712abd, 0x8e9bfb2b, 0xacf786db, 0x6a91a4c4, - 0x5635df20, 0x4f0dda37, 0xe869fbf0, 0x41e4246f, 0xa74892c4, 0x3a26fefa, - 0x38fbe6af, 0x1ea6af3a, 0xe3d6d2e3, 0xc2c74866, 0xbe3897e9, 0x05a2e98e, - 0xcd3310e1, 0x796bf8a0, 0xeb4213c3, 0x4e27898e, 0x6b5fb43f, 0x2801efc1, - 0xfbd5797b, 0xebb458b0, 0xc8d3eba6, 0x36b4e889, 0x53ad81af, 0x1c4edcf3, - 0xa5dfee02, 0xabd74e7d, 0x714617a9, 0x09112779, 0xdcc59de4, 0xbbfc384a, - 0x5fbef035, 0x013837da, 0x5fb843f0, 0xcf9025ed, 0x41f7cd12, 0xb7f4d7e7, - 0xcd807443, 0x0c871daf, 0x43bfabb2, 0xbfeb9cbd, 0x25fc9651, 0x329e9451, - 0x62615687, 0x49125676, 0x9ba5efc3, 0x4a7ca1fa, 0x79839659, 0xa32d4227, - 0x086b61ab, 0x00b0cdf2, 0x3fba9bcf, 0x9351ed12, 0xd2237899, 0xe2367be1, - 0x1661d395, 0x7043cf1f, 0xa1d0372c, 0xd69455a4, 0x814d7be8, 0x8a42c31c, - 0xa2687a84, 0xb94657e3, 0x9f28a3aa, 0x2774ccd6, 0xf6c2c619, 0x3bb95ede, - 0x52f6b90b, 0xaa1a0888, 0x1969eef7, 0xef04228c, 0xbdde20f1, 0x6bc6807b, - 0xec153a95, 0x6d7f9df0, 0x32eeb064, 0x9b5f7953, 0x3e8feac2, 0xdc2577b4, - 0xcf6e9337, 0x49f6147f, 0x7851f6cc, 0xd58fe5de, 0x9bddf3dc, 0x39d6517e, - 0x173f8372, 0x3abe05ee, 0x1df5eec0, 0x777e0d6e, 0xa3787a8f, 0xd1fba945, - 0xd86fc88f, 0xbcad728f, 0x1bb63f7e, 0xa1cb4ea0, 0x81dcfe71, 0x472f9f74, - 0x74969a1d, 0xa1af1d29, 0xd93e0930, 0xd0ea357f, 0x30eef81e, 0x578f8704, - 0x82141eee, 0xc3fcb483, 0xd5932d3d, 0x0f70f870, 0x857d21d8, 0x7d0fabc3, - 0xebe87088, 0x6c5d29be, 0x935cbc07, 0xd6fbc06d, 0xc16c38ae, 0x45fd0af8, - 0xe3e23ea0, 0xbbe5efac, 0xa11fc56c, 0xd354ece3, 0x429ef297, 0x4dd1bd57, - 0x628fb12a, 0xe96a6cf7, 0xf5ca2ba7, 0x25abac36, 0x358f75ca, 0xf78ff71e, - 0x76e35c00, 0x0b8ea73b, 0xb8b135d1, 0xeefdc1c7, 0x5bf32ca3, 0xf2f254a3, - 0x6225ec9a, 0x81c9c40a, 0xfb43e217, 0x8de65f89, 0x19f74118, 0xde6032ef, - 0xfb8b28fc, 0x2b63cc20, 0x7721f808, 0x1ee20aec, 0xbe218827, 0xd9abe650, - 0x9af5fcc1, 0x396f8342, 0x6015ef3b, 0xb47d10bc, 0xc023e8e9, 0x1db1a3e8, - 0xa9a2a3e9, 0x6347d19d, 0x06644e75, 0x3f03373b, 0xc60496bf, 0xa23bde02, - 0x51269abe, 0x151a1ffa, 0x91ba01a8, 0xe5a6e7bd, 0x3d708a5d, 0x7c3f161d, - 0x7abeca7d, 0x4b6d6fc3, 0xe06943ca, 0xe033ee4f, 0x37029779, 0x858c5fa5, - 0x58b6c5e5, 0xfc035fdd, 0xedb4272a, 0x6d6fed85, 0x36f31f79, 0xd86efb6c, - 0x66dbef05, 0x42390c53, 0x5beed6f3, 0xd767f78e, 0xd87dd806, 0x05e024d1, - 0x3c3bdebd, 0xe104ff18, 0x1a4f7601, 0xf91da3c0, 0x5eff1365, 0x7051ab2c, - 0x1a1f9e81, 0x890deec5, 0xebf3b0b4, 0xd7111621, 0xcec2c439, 0xbdf7e259, - 0x95bf8225, 0xfb01bf75, 0xa69943c7, 0xbcfdffde, 0xaf89a4bf, 0xe854f82b, - 0x28d24a89, 0x4ce47fb8, 0xa2d13b8c, 0xa8d89fa1, 0xca78d514, 0x88788f7b, - 0x47aa0ef3, 0xff3dd8af, 0x94abd02e, 0xfc00be7e, 0x968dfb04, 0x4a6e0023, - 0x70cfa07f, 0x0defa1f8, 0x1e60f987, 0xecb617b0, 0x3de2225e, 0x6bc47d1a, - 0x491bdc26, 0x914667fb, 0xfdf4adaa, 0x425a68cc, 0x13d78e3d, 0x2b207d79, - 0x1a713f53, 0x3d7cfa04, 0xb64ebb8f, 0xc931fcf0, 0xd186ea3e, 0x5c766750, - 0xea245256, 0xe16f8505, 0xb738080e, 0x75f9f896, 0x00c5204a, 0x58f85378, - 0x56fc180a, 0x2452b4aa, 0x18f20187, 0x7dd0f1de, 0x9dcbbd4b, 0xdf652fab, - 0xcf9fea71, 0xc1f9ebe4, 0x3d17f5f6, 0x099eefbe, 0xb7372df0, 0xad03723d, - 0x0e7a5c57, 0x479707cf, 0xa1795c55, 0xebf42f7b, 0xdbfce77f, 0x4d874051, - 0x7ec298df, 0xe1c3550f, 0xc029e2d6, 0xbdf932f7, 0xc951242e, 0xb1e55633, - 0xcbb71b42, 0xf8299510, 0xffaced1c, 0xf8081140, 0xf0b14af4, 0x9e32547e, - 0xe5d14e1f, 0x9f87fead, 0xc132f9c5, 0x71250030, 0xcf3628c9, 0x324ecc37, - 0x9ce0ffd3, 0x173f1a69, 0xaf72477b, 0xdef1d2b0, 0x357cec21, 0x19aaae33, - 0xc6c4c4ea, 0xfbda26cf, 0x6b13320a, 0xb8c2c6a7, 0xdf18c9d1, 0xdaeb35ca, - 0xc812bd53, 0x8c9a9269, 0x88d38979, 0x7a633eca, 0x08eeed03, 0xe3902eba, - 0x742c8cd7, 0xe7ede54e, 0x4d43ffe8, 0x2a99f6e4, 0xc72ae37f, 0x8d54e75c, - 0xf78b52fd, 0x9fe9fd01, 0xf2e1ede2, 0xfce33e2c, 0x77c9e2df, 0x1eb3f9c2, - 0xe10e399e, 0x27a3ab7e, 0xd470f5dc, 0xab815dc3, 0x9fd98e1e, 0x86c6a738, - 0x2e1e9381, 0x48ed48d3, 0xdc0a63d0, 0xc77970f5, 0x9de2e8cc, 0xabde1334, - 0xe0c48ef8, 0x23350ef8, 0x9ba41ea1, 0x01ef1168, 0xf5e28cce, 0xbab04737, - 0x64a8ef82, 0xae1eb7c4, 0xc666387a, 0x58e3f7f1, 0x2f00bdff, 0xe202e509, - 0xcc9ba147, 0x31ddaad4, 0xec507a2a, 0x2e1c69eb, 0xfb46bed4, 0x8ade3739, - 0xafb02671, 0xe08425a7, 0xd6ce5b96, 0xf2dc3b95, 0xf4a9f83c, 0x72bfbc75, - 0xff3fe10a, 0xca2f3c14, 0xce0555e4, 0xdad1be53, 0xa69ad3c9, 0xc338829f, - 0x7efb9350, 0x1080cfa0, 0x1475e783, 0x707447ee, 0xd767bed7, 0xf870f5d6, - 0xb131fc03, 0x3a14bc27, 0xe3c2c0fb, 0x20c8034e, 0xbcc797b0, 0xf20d1196, - 0x86c5349b, 0x715c4b8d, 0x0e383f38, 0x63a457a7, 0xcf83b881, 0x423fa9ed, - 0x5aa3ed8e, 0x36c72552, 0x96d3ee8b, 0x4c729ef8, 0x8e64d3c1, 0xbbc4c987, - 0x934be20b, 0xd045f489, 0xed0e481f, 0xe7d95bbf, 0xf6103240, 0xc1c58379, - 0x67df3fe4, 0xbcd4df70, 0xf8b3f984, 0x0b6659fc, 0x02435f7e, 0xce104752, - 0x91df7829, 0x5a1b18d7, 0x4fbf9287, 0x66115486, 0x7bc3cdcf, 0xc85c29ae, - 0x75a15177, 0x8482ac98, 0x75f0fdf7, 0x7b33a99c, 0x5bad8f21, 0x9d814774, - 0x1bec21d7, 0xfc93fb83, 0xe9ff4023, 0xee35cfdb, 0xda7680ae, 0xf1fb08af, - 0x59162ff5, 0xc3b021fc, 0xb93e7be4, 0xb2953b77, 0x8509ea35, 0xfbe0b37e, - 0xde81cbd4, 0xdd6103fd, 0xd1d54053, 0xf659e772, 0x6376431d, 0xecf304ba, - 0xff7966e9, 0x8125c439, 0xdfa7ab7d, 0xa1a74bef, 0x08604578, 0x5d8a29f8, - 0x1eead536, 0x57cfa569, 0x9b66eff3, 0x05188ece, 0xf4c1f978, 0x4f4b4074, - 0xba511d0a, 0xecf00f1a, 0x69fcf8ca, 0xcddfc730, 0x7a009738, 0x43dfb151, - 0x026b8a76, 0x3b37a7ac, 0x3dd5897e, 0x3b017ac5, 0x2e67b15e, 0xdd9087e6, - 0x74a641d4, 0xcbc71b74, 0xccab733c, 0x600fcdee, 0x48eafdfe, 0x473b5ee5, - 0xb791d824, 0x54d94ead, 0xd586e707, 0x6b7efe2c, 0x83f1ac95, 0x86dd90dd, - 0x66fbb3ef, 0x6da65f6f, 0xfe604cff, 0xfb57a17e, 0x3412589c, 0x9cf6edf7, - 0xc035e0d7, 0x3123c3bc, 0xaf3f413f, 0x79fa7f7e, 0xe6adf3f5, 0x636ad57e, - 0xcaa748ed, 0x6560592e, 0xaaf750f6, 0xcae0ebc7, 0xe7e0deba, 0x93480f36, - 0xb5abf754, 0x082c8ead, 0x328c6f77, 0x79ef029e, 0x00e2cfc4, 0xc3dff255, - 0xe59b83dd, 0xde81f166, 0x98161de6, 0xe1a0768a, 0xf608bf49, 0x4100b0fc, - 0xe02b3bfb, 0xf8d02c32, 0xee4fcc01, 0xbdc007e1, 0xd65eb426, 0x01f98bb0, - 0x4fe8d5f5, 0x027f5194, 0x387accf4, 0x17c01e9b, 0x41fe8694, 0xfc85dfd0, - 0xcfb82ca9, 0x12c3fb92, 0x5ad497a5, 0xf5a37fd6, 0x096ae35d, 0x927755fc, - 0xe363294c, 0x98d7efc3, 0x93555fa9, 0xf508224c, 0xf8785eab, 0xc06be9fd, - 0x09758e5f, 0xad287f70, 0xf7fa58d7, 0xf8debfdd, 0xb81afef0, 0x65fa946f, - 0x7f2aaceb, 0x78fe37b7, 0x0b918c04, 0x3dba47f0, 0xa1f0237f, 0x8a68af12, - 0x111f7ce0, 0x8068bba4, 0x57274297, 0x7e8f9b2f, 0xe725c445, 0x589e4087, - 0x16ffc716, 0x46c38f2b, 0x129ff7b1, 0xbf905bdd, 0x023f3adf, 0x8cefcbe2, - 0x5cfe8a3c, 0xe7c59593, 0xd04a79f7, 0xb9f0527e, 0x3f702acb, 0xf8103fc9, - 0xcdf1daed, 0x6497e071, 0x43de02c9, 0x9efb24da, 0x7900cf4c, 0x82bedb34, - 0xa26b296e, 0x6b13bf11, 0xbc0ff08a, 0x35a7655b, 0x9b4cfbf1, 0xa81deece, - 0x661e63ce, 0x4565ddcd, 0x308bf3fa, 0xeec6567e, 0x7befa0c3, 0xfd212fd3, - 0x7f4012e1, 0x13fbf390, 0x61a8fcf0, 0x42e20d8f, 0x827efc1d, 0x09cd0d33, - 0xbe5969f3, 0xf0362fe5, 0x70e7ded7, 0xe2b52338, 0xdb654a3d, 0x83ffbc44, - 0x0b709bce, 0x161ba7c4, 0xf7efb264, 0x8a6777d8, 0x67ff4cfe, 0x167cc0f3, - 0xc8efc434, 0xb2727b14, 0xf583ebd9, 0x188b5535, 0xbbac9e2f, 0xbf0a6c37, - 0x5f6f4c37, 0x712ab49e, 0x87cc04e9, 0xf3676a5a, 0x594fc6f4, 0x9f12c4df, - 0x24b2df8a, 0xcfeb08bf, 0xc08126fa, 0x5a679715, 0x03c89e52, 0xcec89e3f, - 0x44ac30e1, 0xcafda376, 0x6fe89fcf, 0xbe43dc37, 0x6cde5793, 0x4aeb3738, - 0xfdfb6624, 0x77600997, 0xe0b1fbb9, 0x8a07d322, 0x1be5377d, 0x6f557c6d, - 0x8d34e6e7, 0x41207fbd, 0xa77fb378, 0x55eec022, 0x06ff61eb, 0x7bb587a6, - 0xe10c7909, 0xf52dbe90, 0x2947b81a, 0x3b068ffd, 0x7c02dbcc, 0x3cf80f11, - 0x54fcf787, 0xd08dff10, 0xda20d15e, 0x927eb0fd, 0x95f01971, 0x70283762, - 0x6cdf3c69, 0x91d7431e, 0x5f60d675, 0x3378874e, 0xcffa05f0, 0x2fbcfee3, - 0x5357f40e, 0x8273c240, 0xa3bbb3ac, 0x60e4a816, 0x3e0379d3, 0x5bfcf37f, - 0xd881e7da, 0x2dbde0cb, 0xef17e606, 0x28f7fbde, 0x9e6f4b90, 0x82f1c6ef, - 0xbb4f4376, 0x6b91e118, 0x67718315, 0xc44c5db5, 0xb79003ac, 0xaa9a2d35, - 0xbb77a131, 0x7213fb37, 0xb4f495bf, 0x1ec0721f, 0x11d8c311, 0x3e74ce1c, - 0x6f48f809, 0xe36e5c57, 0x24c1e6f1, 0x6ca3ee1d, 0x18b71f3c, 0x8a6e1fbf, - 0x7d472fb2, 0xaea5eccc, 0xbf1fa7dd, 0x13ef9e06, 0xe711fdd9, 0xb7a7e445, - 0xda1e2e76, 0x2a5be2a6, 0x5f4f1139, 0xf9db3ff5, 0xd5ffed06, 0x4716489e, - 0xa9979c97, 0xf50877bf, 0xf97871f7, 0x38f3b007, 0xd7b800ef, 0x2fdb07e9, - 0xfafc3d1d, 0xc3da1b3c, 0x1ea0e981, 0x376bac46, 0xac5bfe02, 0x90d9d7f9, - 0x00a3eadf, 0x33925e2e, 0xf3804c90, 0x7403927a, 0x7626a815, 0xb5b627f0, - 0x97800c18, 0x98c98d8c, 0x9f89b3a7, 0xafaa2e57, 0xe8ab2635, 0xef3f1162, - 0x877b293a, 0x1f9eaac4, 0x72f931b0, 0x6fe94f72, 0x43e34f30, 0xc61e1913, - 0x31b06cde, 0xd18afb7d, 0xe866cd7b, 0xdf80c477, 0xfbdeed0d, 0xcfb85efa, - 0xc761d178, 0x3dff8858, 0xbf607362, 0x6a9b7dc6, 0xf1b7cf20, 0x5452d013, - 0x14286caf, 0x37de740d, 0xefc58388, 0x1fd0180e, 0x893dc60f, 0xf9f60e2b, - 0x1bcf5f10, 0xf9cd062d, 0xdefc1bd8, 0x326d7bdd, 0x89b12fb6, 0x2dadc788, - 0x37a07139, 0xbbeeac5a, 0x8e2fa06d, 0x12c0d5b5, 0x629f7894, 0xb03c4daf, - 0xf4d19af5, 0x061d89cf, 0x71dba03b, 0xf61179e0, 0x484938eb, 0xd87a408c, - 0x8f3c746f, 0x3a37bc7a, 0x1d7478d8, 0x2abf016f, 0xff9aa7f0, 0x7f5a34a1, - 0x858a55a3, 0xfe052efc, 0xf9943eca, 0xb5c4f51d, 0xe4ac82de, 0xb8817ada, - 0x3a5f92b3, 0x7f944ece, 0xd2e9012f, 0x6a3d7368, 0xda0ef663, 0x30f727d7, - 0xae15e8bb, 0xe1524947, 0x829f8050, 0x8b1b7aa7, 0xe9eb2a33, 0xdbdffe6d, - 0xca549e98, 0x9bd74bef, 0xe9178764, 0x0fcb1b66, 0xe6fd7877, 0x6b23c854, - 0xcf7fc54c, 0xfb679549, 0x93e7a47b, 0x1b057bda, 0xf8060cdb, 0x8762ac0e, - 0x6de68310, 0x20ebed1f, 0x48f5499d, 0x09878d7f, 0xdd6971f2, 0x48ee2c9d, - 0x7fbf0de5, 0x81d1cf0d, 0x7a79f87f, 0x1396817f, 0x18afd69b, 0xdbf5f088, - 0x7042af80, 0x65037ca2, 0xe811ad55, 0x5652d175, 0xe973f316, 0xc8dd6b45, - 0x58eb459f, 0x5b1ee17e, 0x0ce7ae32, 0x886257a7, 0x27f9001c, 0x657f0e2e, - 0x6e9c79dd, 0xd13c354f, 0xfa52f30c, 0x73e013fa, 0x4f63e352, 0x7a1572c3, - 0xc641b53d, 0xb5224a71, 0x7cadf6e7, 0x18076dbc, 0x20dc4fbd, 0x5ffdc0e7, - 0x0ec4bd13, 0x3637ec71, 0x7e41146c, 0x9cf401bf, 0xf41cf8cc, 0x0f3dc9ed, - 0xf402fd46, 0x4081bb5c, 0x2315fcbc, 0xe2a2d929, 0x5febdd8b, 0x696ff0d5, - 0x1835f55d, 0x158b6f97, 0x7c2bce40, 0x15fdc0ab, 0xe42af3a3, 0xfc74ebff, - 0x2fbd953f, 0xdfb03b47, 0x9fff9c13, 0x9ff94198, 0x10d98a3e, 0xaf38c023, - 0x07dfc318, 0xa40ff5f7, 0x6d5ca0bf, 0xbf5721eb, 0xcdb57266, 0xafe74a96, - 0xe31bb6b8, 0x71f5c10c, 0xaa6279ba, 0x02c93742, 0x6296bfc0, 0x8bc01870, - 0x99e815c2, 0xdfb7cdda, 0xd95c8690, 0x0f39e122, 0xf9e2473f, 0x0277ca1f, - 0xe486bf0a, 0x6eb7c299, 0xd5d83473, 0x8056ab53, 0xe7971f5d, 0x253cfa45, - 0x52c687b8, 0xf80a767d, 0x383c8c38, 0x57c7e5c1, 0xf762fbb2, 0x7a000fee, - 0x221ea12e, 0x13ac87ec, 0xa51780ec, 0xdd8eb1dd, 0x5a3c3ac3, 0x2bbf9cd0, - 0xef0c1ff5, 0x41fb8f40, 0x7c634787, 0x3c84603a, 0xa63e11d5, 0x839088c7, - 0x570c40fc, 0x5b3e000f, 0xcdd7f544, 0x4a75fd2a, 0x553a45ae, 0x347970e0, - 0xc55f5f93, 0x95ff7db0, 0xe21585d3, 0x2f73aa85, 0x024890ea, 0x605167e3, - 0xf8c22e7c, 0xba4cf6a7, 0xdafde90a, 0x076ef4f0, 0xfe162aff, 0x48f5a73d, - 0xec33319f, 0x13cb1df8, 0x46223392, 0xb0f91f63, 0x57f1bddc, 0xfd01d7e8, - 0x46f7bf02, 0xff4025ff, 0xfbdd0c24, 0xf0abdd28, 0xa501d0a7, 0x55a26b8b, - 0x174f41f2, 0x02a379ca, 0xe7745797, 0x33474f95, 0x9780b079, 0x66f25e8e, - 0x60fcfd94, 0x81ec9f3c, 0xcf0cf9e7, 0x7c02be21, 0x67e1f22b, 0x3dafe117, - 0xaf6c76d1, 0xe60174f9, 0x73f2d4a9, 0x9f3e7aab, 0xd1a5eeb2, 0x4b7ce682, - 0xca34ee7f, 0x5a2bbee2, 0x48ea3e77, 0x34c7d10b, 0xd92ecf6e, 0xff73c268, - 0x7802d02d, 0xbdfecddb, 0xbb3de56c, 0x0a4f0d44, 0x4cd115ea, 0xe1f42b8e, - 0xc3246658, 0x55f2ffa8, 0xc86ee172, 0xab59f9ff, 0xdd346f37, 0x77a316c7, - 0x07e8b5f6, 0xf182af38, 0xd833caaf, 0xc6241f21, 0xde201765, 0x7c0a2481, - 0x33cd8fb8, 0x1979d52e, 0xe70ec9fa, 0x0f079038, 0xf8297c73, 0x9bd0e055, - 0xaf0deb9e, 0xe27c387b, 0x8e5ebb79, 0x9efe7314, 0x5c5dfbc2, 0xe045788e, - 0x2f711b27, 0x59fd6117, 0xe505fe4c, 0x73c11648, 0x727597c9, 0x5e9fe5e4, - 0x91acbc8e, 0xc2da1323, 0x0bfa11ca, 0x1bf1ffcb, 0x4b1da216, 0x63b7870e, - 0x3d334677, 0x93fa0f1c, 0xb2f78bf6, 0x3987def3, 0xc48a52dd, 0x0ddac9bc, - 0x5713cc26, 0x366d90e4, 0xaf7f81c9, 0x16fa06d9, 0x1f76cd7a, 0xc5e70c9e, - 0x9c074649, 0x03929f5f, 0xd453f788, 0xfa45af01, 0xc7fbc7c8, 0x0223c8c3, - 0x47ef12f1, 0x9cefd083, 0x9f213626, 0x5046992c, 0x78deee7f, 0x4955d205, - 0x74008a5e, 0x23175a5b, 0x54ec7b40, 0x94e401bb, 0x962b8fb2, 0x71b0c819, - 0xd40707c8, 0x6f0ae472, 0xcdbbfe15, 0x49dce343, 0x47210c72, 0x33fb3d1f, - 0x8da8bc75, 0x22f1d5d6, 0xfbe07f5a, 0x468e8bc4, 0x78801e07, 0xae6c3fd1, - 0x94779876, 0xea28ff25, 0x912ac4b7, 0xc5d6e4a8, 0x4a1fb7ec, 0x2e3c952f, - 0x34a95a45, 0x81c4d04e, 0x6073ab6f, 0x582bf81c, 0xe380c54f, 0x7870c34f, - 0x7b5846af, 0x1fa3ad9b, 0x13e40b97, 0x97e8f882, 0xfc42255f, 0x063b9145, - 0x2fe2ac7b, 0xa197900b, 0x037fdbf0, 0xd7b57d1c, 0x00008000, 0x00088b1f, - 0x00000000, 0x7dcdff00, 0xd5947809, 0xe77df0d5, 0x24cb2d9d, 0x7642c993, - 0x03bbec26, 0x4eb1ab09, 0x04906008, 0x8d441007, 0xb0900938, 0xd2910364, - 0x208196d6, 0x2b188a06, 0x0eb154b5, 0x4551fa14, 0xdb1ab61b, 0x1a4013a0, - 0xad563414, 0x61a5afd8, 0x80891d91, 0xe58ad3fd, 0x7bdce73b, 0x264ef333, - 0xe79f6a02, 0xcdcf0f0f, 0xcf7bde5d, 0x773dfb3d, 0x79632d49, 0x9b19223b, - 0xed50b390, 0xccc9a906, 0x831b163c, 0x43632f1f, 0x087a3e79, 0x6b9859e6, - 0xf26b6320, 0x01de7975, 0x9fc75d8c, 0xa269fd3b, 0x678e3e15, 0x30d6fe6c, - 0xb53349eb, 0x7fe1d767, 0x268c5d79, 0x649f595f, 0x9fc7d93d, 0x24bf8f9f, - 0x4c33ffc1, 0x2b1812cf, 0xe1a7e263, 0x70ffdfcb, 0xdfc7b418, 0x54dec655, - 0x805689dd, 0x12dcdca7, 0xd8ceddd5, 0x13c7f933, 0x52d491dc, 0x223ddf87, - 0xb97178c6, 0x71debde3, 0x55de798c, 0x0fc816d9, 0x4a3d1936, 0x64e2fc34, - 0xe8826b76, 0x06947e0f, 0x041967c5, 0x55437ff9, 0xfe97632c, 0xc5f4a3ad, - 0x32f2b89f, 0x7a8afbe0, 0xb439639d, 0x185068ab, 0xd1cc62cb, 0x19cd7995, - 0x4785d58c, 0x5fd0620d, 0xa748bece, 0x292fca01, 0x8329af66, 0x870800d1, - 0xa23fc241, 0xd41b7d35, 0xd8983757, 0xca5ec86a, 0xe119ac61, 0xd9a23bd5, - 0x077e3f00, 0x0fa67e1d, 0x6bca00cc, 0x630b2e1d, 0xff78c29b, 0x7b64c29b, - 0xb483347b, 0xecd192db, 0xd7a7c004, 0xf40d1633, 0x6983c481, 0x036e92f6, - 0x1f3099f4, 0x8018f33d, 0x3eadd94e, 0xadd2f115, 0x9163aed5, 0xadf471fe, - 0x4ddbe68c, 0x6039d76f, 0xf7813afc, 0x543b4d9d, 0xd873e03d, 0x156ada98, - 0xf728d2d2, 0xa8f3c458, 0x2c6aaaec, 0xa8f7cd8f, 0xa59f686e, 0x00b3ed54, - 0xe678d85e, 0xcce502d8, 0x848f8307, 0x18d616fa, 0x2398d905, 0x2828ce2d, - 0xd9c6751f, 0x1de60038, 0xf60a62ed, 0x1a32d8c7, 0xcba45fbf, 0x38b2fd85, - 0xfd0052a7, 0x2307fb0c, 0x767ec8bc, 0xec568d36, 0xf35c6f00, 0xc01ec518, - 0xe24d305f, 0xfeccf5ab, 0x73d7ec53, 0xba40e748, 0x7398ebda, 0xfaefb423, - 0x2c31bf72, 0xd2bedfca, 0xb778d0aa, 0x46b9ddbb, 0xd879f346, 0x9c8fdf0a, - 0x0067ddee, 0xf1cf8678, 0x03da33ec, 0x519733e6, 0x1e2d297f, 0x11d2479a, - 0x8ba60e77, 0xcfd4312d, 0xc6be33a8, 0x4baed001, 0xca07cc15, 0x543f9ad3, - 0x5569af10, 0x71d20acd, 0x825ed367, 0x3f79b537, 0xea11814f, 0x7201dd20, - 0x8f301755, 0xcd1d16c5, 0xa145b163, 0x99c5e574, 0x7fa82e89, 0x6c5eeac4, - 0xc79fea19, 0x62771cca, 0xbebff415, 0x7cfb5ba9, 0xb7bc027b, 0x278867c1, - 0xab72dfd9, 0xb269fa91, 0xf3847fb8, 0x72de9cab, 0x476f7900, 0x48a39fd3, - 0x88e21a2e, 0x8e8709be, 0x96123d13, 0x78a0ce00, 0x0a85a1fd, 0x85f5aa83, - 0x23a53340, 0xddb8279e, 0x8899318e, 0xf89f806f, 0x09311ac7, 0x8c62f2f8, - 0x91c706bb, 0xd91427ed, 0xb45f5022, 0xcf77c5e7, 0x598e652e, 0xfbcf003d, - 0x6eb2778b, 0x12f77748, 0xbb7b7ba4, 0x21878f81, 0xb38b313f, 0xa4bbfb16, - 0xce38e9b0, 0xf942984b, 0x979e064b, 0x95abfaf8, 0xeb11ebe3, 0x7896c5a4, - 0xf02b278e, 0xbc614bf1, 0x7a1eb05d, 0xb3bfcad7, 0xcd617e0b, 0x1e705f9c, - 0xbb64bfa8, 0xdbdfa2dd, 0x3d5cee9d, 0x08cd93e7, 0xde11c8e7, 0xc3b7c87d, - 0x90fb3cf3, 0xe098d3ff, 0x27ce3c93, 0xcfbefcc1, 0x467ea36a, 0x8865699d, - 0xb9852cf7, 0xd32ee902, 0xa1ae10d7, 0x89a3dfc8, 0xb61e407f, 0x52c378e3, - 0x800354aa, 0x13acc712, 0xdec67758, 0x5da9dab6, 0x3ee708e6, 0xd3ab37e4, - 0x207cf245, 0x2be54ac2, 0xc07f3833, 0xfc407ff7, 0x2ed3cb05, 0x7e01a394, - 0x7e438a39, 0x8fc8ec8c, 0xbcf013bf, 0x63a5e42d, 0x613feeff, 0x3acd71ff, - 0x0c9d02a7, 0x65e9123f, 0xa2f874d0, 0x8fe1152a, 0x00ffc063, 0x358e6da0, - 0xa52ce507, 0x5d20a1cc, 0x875c229b, 0x230fd4ad, 0x4732b9bd, 0xef86ade7, - 0x893b46e6, 0x3ed8df7e, 0x366667ec, 0xc01f6fcc, 0xe115fc1e, 0xb6b07b03, - 0x6ff4f508, 0x3d4469ff, 0xd7f2976a, 0x38a22434, 0x48ae3f80, 0xf7a7e0bd, - 0x410bd271, 0x73d60ef4, 0xebf6f4c1, 0x039ead05, 0xf4e05d7c, 0x9f226770, - 0x522f35c5, 0xead07eb9, 0xd1e8ceb5, 0x3a083f41, 0x7e708a5c, 0x0c5cf881, - 0x7ae38832, 0x583eb346, 0x0e1d99de, 0x76a4898b, 0x1c3b45ff, 0xd1df1316, - 0xadcceb0e, 0x47c01507, 0x576a8379, 0x8fd50a61, 0xff489cd9, 0x8714eb17, - 0x41a4e509, 0x71787e25, 0x4bd93865, 0xbb67ef09, 0xdbb107a3, 0xcff21520, - 0x8ec9dddc, 0xf188c656, 0xf18790ed, 0xd679592f, 0xc5277568, 0x1793e804, - 0x4308be1b, 0x644ff73c, 0x62c64e03, 0x0ed6a70b, 0xf0290883, 0x537f09bd, - 0x6b83af10, 0x69ac1454, 0x95269dee, 0xfb1dd6e8, 0xfe5ace1b, 0xbd700d9c, - 0xceb46dbc, 0xf537c81d, 0x05ec6757, 0xb8232bf8, 0xf7b4be5d, 0x33e42f5a, - 0x92f77f59, 0x3f7bd262, 0x13192b07, 0xeedf1fa0, 0x61eb8273, 0xd53d6856, - 0x2a76871f, 0x850023d7, 0x7a3ee651, 0x70d427f4, 0x27f5aa87, 0x7baa3988, - 0x7f107e02, 0xbf84e18d, 0x77209eea, 0x48e70419, 0xc5bf7fec, 0xfca092c8, - 0xb623c80a, 0x037f7093, 0xe2074778, 0xaa6f0fd1, 0xe08454f5, 0x5f0fd50b, - 0x0e905d3b, 0xd16abfd0, 0xb12e3cd3, 0xb3d20770, 0x4864e8ce, 0xe151cf7f, - 0x55ba081f, 0xd4bb9e08, 0x1b88f430, 0x91e2f7e6, 0x7f7e0754, 0x984afea9, - 0x46fd122e, 0x979c14f7, 0x851ad69a, 0xc35f70f6, 0x032dbe95, 0xc54dbf48, - 0x4e872bf2, 0xbe03dcd8, 0x8466fcd1, 0x7e7687a6, 0x9ac8fa95, 0x6150ff40, - 0x7cc17e7c, 0xfe3434a4, 0xf244194b, 0x7a1f50c7, 0x1ab799d2, 0xa072bde6, - 0x997ba7e0, 0x983ee51d, 0xabab46de, 0x6e402622, 0xaaed15ff, 0x9c70b842, - 0xcf342194, 0x741f9885, 0x41a66678, 0xc31bf387, 0x7f4a6ed0, 0xb0effd0f, - 0x4eff7e21, 0xfe7dafce, 0x3a0daf3d, 0x3fbe68c4, 0xf80071c6, 0xaf803ae5, - 0xeac18c12, 0xfb79c08c, 0x62e51e88, 0x48e6e57e, 0x61f30a9f, 0x5a170cbb, - 0xd6e81ea4, 0x4fa07e11, 0x19e7c20d, 0x46e238ed, 0xd235fefa, 0xd1f88d51, - 0x5fd15b37, 0xc6acf985, 0x28a2367a, 0x2fdfe711, 0xf505b9d2, 0x18cb4bfc, - 0x57a5f3f1, 0x4c137798, 0x1d7efb76, 0xd646cbf1, 0x9fbef88f, 0x570cf2ee, - 0x3af3c924, 0xb9ab3b84, 0xb77a8756, 0x43aed7a7, 0xb9b7da7d, 0x3e23a74e, - 0x8622ff70, 0x5799e4fc, 0xff5f00f4, 0x37ea556d, 0x686f07e4, 0xaf40ef7e, - 0x92f481cd, 0x7c16cb78, 0x43788d90, 0xbfaad083, 0xe3f662d0, 0x52c3e80d, - 0x63fb1d6c, 0xf11d25ac, 0xe9faf8d4, 0x5fd02d5e, 0x67a71bc5, 0xfe2a5e20, - 0x18262260, 0xd1be87f3, 0xe59fefc8, 0x2e67f684, 0xe872ad2c, 0x257a9fc1, - 0x85d91ba6, 0x446cd632, 0x6ebca13f, 0xa01f4381, 0x76ffa5cf, 0x8f9cd0c8, - 0xaa1a1ffd, 0xe78065b2, 0x5de18e2b, 0xd13b0858, 0xbfa12fee, 0x472fb006, - 0xafcf11d8, 0xff734567, 0x20f646d1, 0xa5a1fdb8, 0x7a631c73, 0xa1dfde74, - 0xbdd361c1, 0x907e7df0, 0x8634741f, 0x18b6b5db, 0x2141876e, 0x8bce113b, - 0x3d78b7bf, 0xc8717450, 0xfd0c5147, 0x641f5dcc, 0x2e8f807a, 0xfe47e6b2, - 0x35767288, 0xf971d692, 0x5cca3f83, 0xe5cbf166, 0xdcf8231d, 0x70ed78ef, - 0xe7da1d94, 0xe717df6f, 0x1ddfc009, 0x9db57f4c, 0x5c7033af, 0x7d33e346, - 0x07a42f4b, 0x04d9e3fb, 0xaff9a43b, 0xf9c715bf, 0x74874120, 0xdbf4245e, - 0xc028b0ef, 0x525fcedf, 0xf3247c41, 0xe6666de5, 0xebc80d8d, 0x04b88d9b, - 0x648b6f2e, 0x37b7685e, 0x7a4712c6, 0xa3259926, 0x5f14e99e, 0xe0cf8937, - 0x43cf8972, 0xa3a6cf83, 0x2759f15f, 0x1b6f70fe, 0xf7ced76f, 0xd74fc14b, - 0x7ceff3fb, 0x0aec3ea5, 0x8d845df1, 0x638ae9d3, 0xf7f41764, 0x1ebe8df2, - 0xe4ed10d6, 0x4f1832fa, 0x8d2b5f6f, 0xdf7f7ec0, 0x050bca66, 0xfba6de97, - 0x21ca7e76, 0x1fc02a80, 0x53baa6dc, 0x9c1fc26d, 0xbe8af90c, 0xbad1c657, - 0xd08bf25a, 0x4f30777b, 0x306fca23, 0xf77a487f, 0xfadd01b0, 0x296672a3, - 0x318bb748, 0x4237ce76, 0x047ca41e, 0x9d3831e3, 0x50ee6460, 0x62af80eb, - 0x98c35e24, 0x23e1f407, 0xdf640d1b, 0xf8fb5f0f, 0xf7e04cde, 0xd60c1bd3, - 0x9ce430e5, 0x3ea5f617, 0x0673f503, 0xe40aac9b, 0x3d7ddb4f, 0x5f4bee50, - 0x0fc85d50, 0x923c37a7, 0xf3d21330, 0x0065bf20, 0x0346e947, 0xf8d9cf95, - 0x159f9528, 0x42fa5d72, 0x97d47f7c, 0x4eaff787, 0xf9ce3a40, 0x486989ea, - 0x6b46ed97, 0x9690c1ff, 0x631c536d, 0x6f3df002, 0xbf269873, 0xe0e6c75d, - 0x995d243c, 0x47af6ee2, 0xa6d53f13, 0x1f7176fb, 0x04dfd69f, 0xa0aa72ff, - 0x3029c4e3, 0x57a18aef, 0x77dfafc8, 0xc9ec9c20, 0xf92a919b, 0xffc1be8f, - 0x20db9def, 0xde95fb9f, 0xa09dbe41, 0x674158f3, 0xb7a45cb0, 0x9f3ccc4b, - 0xfc9ebafb, 0x4a8b5ccf, 0x91f686f8, 0x7bfea163, 0xf40fbda2, 0x5321ca2c, - 0x848dd7b3, 0x0da36376, 0xf7d0ed0c, 0x19f2f37c, 0xdb3bc9d8, 0x025bc7f4, - 0xd59a33e6, 0x387f41f6, 0xca821987, 0xcf2c7a9d, 0xc7cb6b35, 0x2cfbb8f6, - 0xad630ffa, 0x77c972da, 0xfab4d88f, 0x7381df62, 0xf3009b3f, 0x92a4392b, - 0x7d237cff, 0xafc22efc, 0x5dbf3a47, 0x3bbe0db8, 0xf872b02c, 0x4915e9da, - 0x142357c8, 0xd3acf186, 0xe3cb42d7, 0x665ea41f, 0x7e3edf40, 0xe63816fa, - 0xdc51e7b6, 0xa0b119ef, 0xdff08f3d, 0x7afb1ebc, 0x8d9b753d, 0xed8233c7, - 0xfcdcb046, 0xfe46ecb7, 0x3dd2b7e0, 0x837f4a16, 0x5ced85e9, 0x89eb06ef, - 0xe1213b60, 0xbcb7860a, 0x0fb1a74d, 0x191ea15f, 0x8c27681a, 0xc3be2764, - 0x6d8370f5, 0x30f5c768, 0x2f8431f8, 0xad3d30cf, 0x6adfc1c3, 0x220376c4, - 0x0039b1ed, 0xb76b0ad2, 0x167fb208, 0x405b7ef7, 0xb6ffaa1c, 0x8dea1d5a, - 0x418cf8f6, 0xeb91a71b, 0x9d8477d5, 0x1cfa13a8, 0xceb4abd6, 0x4eee18df, - 0xc9b8e3d4, 0x8c96c746, 0x48f9f88e, 0xcfccefb4, 0xbeac7e95, 0x8fb1fb86, - 0x389a5d58, 0xa893eb19, 0x5fa2fb89, 0xd9edf28e, 0xfcf34e1b, 0x420d7154, - 0xe733d439, 0xf4016ddf, 0xf87036a9, 0x8f89e183, 0x319276e5, 0xb207f917, - 0xd0e8f67c, 0xd5895c7a, 0x679cfb53, 0xff474fef, 0x07c6d3ed, 0x7ebf51d2, - 0xede7141a, 0x169e1e4c, 0xb0a4faf2, 0x2e223123, 0x11ca14f0, 0x9dda41e4, - 0x55fbe1db, 0x57245d4b, 0x9d3a5d3f, 0x2e9667d2, 0xb613faa1, 0x9adf1a0c, - 0x775767f3, 0x35c9d3c0, 0xd989d92a, 0x18af5746, 0x59a4eef8, 0x1385f147, - 0xbb799155, 0xd19cb122, 0xb3f6727a, 0x0278b613, 0x6c277ee2, 0x6743a27a, - 0xfd8f8cf3, 0x9cbdfa66, 0xbda144b5, 0x23d7e76a, 0x2db5ec1d, 0xac7fe316, - 0x55db0125, 0xb6bdcd2a, 0xb7c71d29, 0x2c7c6732, 0xf59197f2, 0x0ba9b947, - 0xb828f6e7, 0xe72c4a5d, 0x1fa1bfc3, 0x8a7efd0b, 0x9e842b76, 0x2f3a0bb1, - 0xb1ed38b4, 0xc922efa4, 0x81b8275f, 0x728cbe5f, 0x60b84776, 0xd313d65d, - 0x7c785d61, 0x2ac5b16e, 0xf0a9c3f8, 0x5fab8e75, 0x5bf8886c, 0x609ef167, - 0x7811de38, 0xc9038e0d, 0x8681c654, 0xbcf9f2c6, 0xe26ab36d, 0x0eff1842, - 0x79f9ff15, 0x1ba3d72c, 0x2a3c5bc3, 0x7c03c3ca, 0xdb25de3d, 0x2b7c60a3, - 0x0736bf25, 0xc5775fe3, 0x2da5b8f2, 0xeb889dcf, 0xa344e4f6, 0x3736e303, - 0xea038f2b, 0xc05f7c9c, 0xd63823ad, 0x7ac27b37, 0xcd095c01, 0xa4231cee, - 0x0d317153, 0xaac2edf8, 0xa0dd2196, 0x6b23211d, 0x9157b87f, 0x92686c8b, - 0x4028f429, 0x6772861a, 0x454f728c, 0x559b0cba, 0xfa718d55, 0xffbe3294, - 0x77715670, 0x9c9f01b5, 0xa43c2b7d, 0xe8225c3f, 0xc9d194cf, 0x36b3fa68, - 0xacae081b, 0x819f3fcd, 0xf9b59f7c, 0xa012bd2e, 0x1ac79687, 0xdf67fe68, - 0xe295d79a, 0x58989f16, 0xea7a10cf, 0x1e5f8287, 0x69d87410, 0x8b7fcd0c, - 0xac6fbb45, 0x55405bcf, 0xe2f9f569, 0x5b3880d8, 0xd265f945, 0xed6393e7, - 0xfaf3ce34, 0x80c903ba, 0x3167e7cf, 0xe68a0787, 0xf148dd6d, 0xbac69dd7, - 0xe4efb8f1, 0xa431d0a9, 0x7f03fefb, 0x7e8c9038, 0x60fb2ce4, 0xbfda23f4, - 0x4ad2f43f, 0x0e7e7f2c, 0x4ff88c1b, 0x60ad3ef2, 0x619fe63c, 0x7faf84b5, - 0x65b1316e, 0xbf7db718, 0x210ffc6e, 0xc74cbebf, 0xcf04bf50, 0xe832461b, - 0x19f53112, 0xfd382374, 0xba4a0f51, 0x91190303, 0x886e921e, 0xee90edbf, - 0xc11af2df, 0x2a9ae12f, 0xb6f3dee2, 0x7c8f1f6e, 0x53665c92, 0xe1204e30, - 0x793d91ba, 0xd9dbf631, 0x0ed0ef93, 0x221b12bf, 0x0ec21d2e, 0x610d88ef, - 0x2fed8387, 0x637738b3, 0xe1d91bbb, 0x36ff82e1, 0x7fed06c6, 0x08597ee0, - 0xed8d0dba, 0x1fdf0f10, 0xe3ff621b, 0xdef0f146, 0x43ff72b1, 0xc97f0f1b, - 0xad6ff5c8, 0x293c3d8d, 0x1374bc84, 0xb5d6ebe3, 0xc67ed11a, 0xf5212835, - 0x518b62d9, 0x1c7e1fee, 0x125fb01b, 0xe0438fac, 0xefb628f7, 0x17b7cdbb, - 0xe9890d5b, 0x5bee8111, 0xdeb0ebbf, 0x29ce310d, 0x22fb3f81, 0xf6a6fb46, - 0x0afa462a, 0x141e5ef2, 0x371429f4, 0x934f38b0, 0xbec1badd, 0x1cd69dd5, - 0x3ee483f2, 0xd6ab54d5, 0x938b8c4f, 0x239f9ced, 0xd89d699c, 0x3c097f89, - 0x70dbfcc1, 0x4c45b8dc, 0xf7231fb3, 0x3caae261, 0xcd0b318a, 0x6af8a311, - 0x32f758d7, 0x1d6bb403, 0x209b1cc9, 0xcd685d1f, 0x9b6a7d41, 0xfdc468e3, - 0x7917959a, 0x02e57e3c, 0xfd4e5de6, 0x7732f9f0, 0x17ca2f37, 0x2e302dd2, - 0xe1c71110, 0x72e38888, 0x1cd27606, 0x8f0ae1c7, 0x9293b00b, 0x3e75ba1e, - 0x1adae895, 0xd0054eda, 0x77df46d5, 0x50efd742, 0x3771ed2e, 0x8cf71fe7, - 0x19be05bb, 0x7c737718, 0x4b4c14f3, 0x8f04dfec, 0x0ff38997, 0x2cf80f1e, - 0xf826ee2b, 0xee2deaec, 0x50881e8f, 0xa5dc5dbe, 0xc4275e23, 0x6b77d085, - 0x487d75f2, 0x4770b35f, 0x233abb28, 0x7dbff22e, 0xa086645e, 0x179d2df7, - 0x2d27f179, 0xdcb3a446, 0x06f090f7, 0xe591139f, 0x264a0d15, 0xf6733fae, - 0xc075a35d, 0xd37fc6a5, 0x79e3a03a, 0x42ee3e0f, 0x678003e4, 0xcea03aac, - 0x7977f207, 0xea56919b, 0x22ffb32a, 0x4df6e31b, 0x53b5e606, 0xefb6337b, - 0x7efb78c7, 0x633656db, 0xd31faadc, 0x547ac47b, 0xa8fdceb9, 0x7ee39468, - 0x8d5b2a4d, 0xbebcadf9, 0x6197998a, 0x847a3a5c, 0xf003d98e, 0x670ce319, - 0xc67c00f6, 0x7934d9e6, 0x2f9e4eb9, 0x25778dc6, 0x32efbe6b, 0x7da69bbd, - 0xa69fbb92, 0x10ce653e, 0x6aad3e4d, 0x577da694, 0xf981cfb0, 0x9addcf0c, - 0x266bddf6, 0x6b3df26b, 0x3fb4d01f, 0xcd9eaacd, 0x9c7a79c6, 0xce003dcd, - 0xdece0259, 0xdf358beb, 0x0dd5d7f5, 0xf920a1f3, 0xffee1f14, 0x326c16cd, - 0xfa73c44b, 0xfa69e77a, 0x5e6aff3d, 0x9df80293, 0x19386b5d, 0x7c219f18, - 0xea4b7e00, 0x8c1cf615, 0x5b5eba5b, 0xe9e1a73f, 0xce902995, 0xe7cb6af5, - 0x829cbee1, 0xdf2dadfc, 0x823d73ad, 0x71ed9deb, 0xe228ce22, 0x7f03ac3d, - 0x97b8d244, 0x9778f037, 0xc41de9ea, 0xb13a5a1f, 0x762fc96f, 0x44a62fc1, - 0xd984bf2d, 0x7a52fcb5, 0x1f30e770, 0x88ff88eb, 0xe47c413e, 0x78017f81, - 0xf895f897, 0x7cb438b7, 0x9de15df5, 0xdb91af31, 0x3ff96d0d, 0xb5f1b4e2, - 0xe3ee917e, 0xd4aeb7a8, 0xbf71522f, 0x7df1e58d, 0x57f52bfb, 0x6bb21d07, - 0xdb3ad7f6, 0x17173a4f, 0xfb175718, 0x3f709749, 0x137636f1, 0xfefb89fb, - 0xd900f885, 0x1f801b77, 0xb98708d8, 0xcc30ff7d, 0xac147fbf, 0x760a6537, - 0xb238cbe3, 0xd77dfe27, 0x587af86a, 0x085c5ff4, 0x9387dcaf, 0xf9e472e7, - 0xe7c91621, 0x3c01fb29, 0xf143f1a8, 0x022d9ffc, 0xf7dbadd7, 0x96f5a42f, - 0xc4c43f3c, 0x7e10bfb9, 0x3aefe93f, 0xfc8935fc, 0x6e78f081, 0x6d3123cf, - 0xf9c407f7, 0x3bcf692e, 0xb7ee47eb, 0x7b2a9675, 0x6c3fda55, 0x9b1dc255, - 0x5e93d842, 0xfd72dff1, 0x1c43a675, 0xe07c57ba, 0x2bd1ebfa, 0x00aed007, - 0xb962fbde, 0x5af602c5, 0x5febdbf1, 0xbf114444, 0xbd541eb6, 0xb2e0a1bd, - 0x036d1ed9, 0x6984363c, 0xab4c88ed, 0xf403c9cc, 0x3daf58b1, 0x11f727e7, - 0x6367db83, 0x27fd80fb, 0x8fe34ef8, 0xfdc21cac, 0x6e78ecb5, 0xe488bfdf, - 0x9114c1fe, 0x175a0caf, 0xbf70d655, 0xe9f8236c, 0x4cfd010d, 0xfb50b789, - 0x533911a5, 0xc08e29e2, 0x332bbbd7, 0x5627f214, 0x21f90a2a, 0x5347a267, - 0x9cb8b5fd, 0x623fc4c9, 0xbbe8299c, 0x6edaffc1, 0x38bb1e1c, 0x37fb238f, - 0xe6f6f3c7, 0x4e94d1f8, 0xb88ab789, 0xf21fb5b3, 0x93846547, 0xa1aa35fa, - 0xc7a6a5f7, 0xb5ad79f3, 0x6a27e930, 0x84e3fee2, 0xbf38c4de, 0xf9a3fb89, - 0x71fc1363, 0x7f66a67e, 0xf1138c68, 0x773e857d, 0x53ba9ea2, 0x78b3bdd0, - 0x758fb3bf, 0x75276e3f, 0x12fbf78c, 0x1dfbc643, 0x0fde28e3, 0x5e71ea5f, - 0xa47f71c1, 0x2fcd8443, 0xb7c48f3f, 0xd45483db, 0x7746f54f, 0x5abbae35, - 0x0eff8377, 0x2dbc7dc5, 0xf0301fb4, 0xae077750, 0xb06656af, 0xb7e416bd, - 0x7fa18c65, 0x5ba2df5f, 0x6bf5061e, 0xf58acc3c, 0x75f03723, 0xbb7ae95b, - 0x8069a703, 0x8865b075, 0x8bac1f5f, 0xd7bc218f, 0xc46e4cb7, 0xf73581fd, - 0xa19a1b32, 0x1b9b565a, 0x06d0fe85, 0xf8dd7216, 0x09b39094, 0xd4557b39, - 0xdfe8f117, 0x53d3a087, 0x0fa04e82, 0x879d22d6, 0xf0afbab7, 0x4fae38fd, - 0xfae22548, 0x1bcebf74, 0x373f3d6a, 0xf21d773a, 0xe86f40c1, 0x0b5ac3f5, - 0x1175b7e7, 0xdda8e7ae, 0xb5ee7e2e, 0x59dfea54, 0xba07a63a, 0x9d74114f, - 0xdf9f81b2, 0x5faed760, 0xc89fa557, 0x7a867fa8, 0x8b5ef4a5, 0xa543e317, - 0x821e190d, 0x7a38a5cb, 0x7868bea2, 0xd2f985df, 0xc62b2cac, 0x657f9c23, - 0xe43ea9ca, 0xbfae3262, 0xd494ecf4, 0xe3c76427, 0xb269df68, 0x16b5b7e0, - 0x0d473f3b, 0xfc008e28, 0xb6586e97, 0x7cefcf17, 0xfb466bf4, 0xd6d4474b, - 0x54d9d861, 0x2192ce40, 0x2159ea98, 0xfef82bc5, 0x1fa2bdd5, 0x5c61bfcf, - 0xa9dc7fb3, 0x3e69070d, 0x63cc0c47, 0xb4ba3e06, 0xfa3b3ee7, 0xcde32bdb, - 0xfb93c714, 0xf75547b2, 0xf48464e3, 0xda0815ad, 0x56110dfd, 0x43fc7f8c, - 0x82465df0, 0xc7d21f7b, 0x057c7cbd, 0x6596c1da, 0xa3c474a6, 0x1a92797b, - 0xd7ba7007, 0xd1ef342a, 0x788c93cb, 0x8ae6617e, 0x4f50e3c1, 0x95ce610d, - 0x2879df18, 0xd3948596, 0x9d7cf1f3, 0x60655c58, 0x849a68c6, 0x172fe311, - 0xbf8a146b, 0x015bfee0, 0x988e67d0, 0xf7aaf95f, 0xec3f88a3, 0x1e186ff0, - 0x733fe5cb, 0x1e494aaa, 0xe46bcec1, 0x19d58ca7, 0x799fa093, 0xdb39606b, - 0xf1fdec8d, 0xc043fe0e, 0x3af2ef79, 0x5b257d6d, 0x7f9d39f3, 0x5befe061, - 0xeb682ed0, 0xe8f2953f, 0xaba40e60, 0x8cc5b17b, 0x0b4684e7, 0x51ad14bc, - 0x665fa8ac, 0xbf8c68ae, 0x9b33f20f, 0xb4f20754, 0xe8eb0bc4, 0x8f39d3ef, - 0x693d4dcb, 0x6ed9703d, 0xdced82ef, 0x2bff5c51, 0x2c70f77a, 0x3dd6287f, - 0xadf1d71c, 0x9e18589f, 0x06d6399b, 0x1ec618fe, 0xc5106ccd, 0xd06cac1f, - 0x5a3b00a4, 0x6026b064, 0x16c3dfbc, 0xb7be3226, 0x779c0e65, 0xf90d79a5, - 0x07e89581, 0x1f91f9f2, 0x672c50f8, 0x15d7d6d5, 0xeac39f3a, 0x9a07e40d, - 0xd6781f85, 0xae009b5e, 0x6e3d7317, 0xde2d3920, 0x687e4316, 0x235c8af1, - 0xaef16ff2, 0xe043d218, 0x63d87e07, 0xc78e9f98, 0x481e6456, 0xeb8b7e84, - 0x96aa1c32, 0xb8ff5a7e, 0x5ba498e6, 0x4b4fbf47, 0xe8a193b7, 0x94d2f406, - 0xff0824a7, 0x3d8bd04e, 0x477e4b16, 0x7ab782e1, 0xcb9e019a, 0xee746155, - 0x83ff33a8, 0xbed1c6a5, 0xe6175c9e, 0xdfafb725, 0xcafcdf68, 0xb744a19a, - 0xfde57a60, 0xb470e667, 0x16afec27, 0xa1ec7a86, 0xc9e1ecee, 0xc2b0fe50, - 0xeaa1ebe5, 0xa72879f1, 0x6f5c0959, 0x6614b7be, 0xfdec6468, 0xece666a5, - 0x4b07d8c5, 0x68ff94ad, 0x3fe52269, 0xf4a76a5e, 0x287da593, 0x68e2293d, - 0x0180ce52, 0x25475f88, 0x951af970, 0x6cdee220, 0x8caa2251, 0x307cffbc, - 0xa1c56754, 0x4d8c27d2, 0x271eec63, 0xdfc02320, 0x046f7e99, 0xdf3db912, - 0x4b8eb062, 0x9571ff44, 0xd8befa42, 0x3da6bb75, 0x3c4625f8, 0x64facdff, - 0x9ce9cbfa, 0x1938dd98, 0xfcfef0f8, 0x69fb4d58, 0xfc9a2935, 0xcd3b04e4, - 0x775e527b, 0x8503f94d, 0xa2f935fd, 0x9e024036, 0xf8db302f, 0xb7d8aafe, - 0xd7c6cc67, 0xf6de56eb, 0x2ef0d56a, 0xaf7807df, 0x7d50321e, 0x5d243d30, - 0x31d7ad67, 0x73368037, 0xfa0dcc3d, 0x933b593d, 0x11fceae4, 0x95fdd90b, - 0x1ddf32db, 0xdb63f901, 0x7ebfb40c, 0x5aec456c, 0xb63e3fdc, 0x418a3e2d, - 0x32a95eea, 0x7ac1fa1f, 0xe80591ab, 0xcb15dcb7, 0x9156fce8, 0xf940e4d7, - 0xf9efda2f, 0xd1dbcc95, 0x5120441f, 0xbd543e3e, 0xe7e8853e, 0x14befc24, - 0xf902dde6, 0xf1afa033, 0x16ccf8c8, 0x8519d70e, 0xd9fcc0ad, 0xfaf5bfb0, - 0xb171c03e, 0x8744b6a0, 0x50f501eb, 0x1dcbe93c, 0x2dbe432a, 0xfda0605c, - 0xa91fb9bb, 0x94cf311b, 0xde9c2921, 0x64479d2a, 0x7fa8992f, 0x021c0ad6, - 0xd6fd16ed, 0x77d689b4, 0x0f77e44c, 0xfc16aef4, 0x26747c89, 0x08633986, - 0x3de08558, 0x46fc7ef7, 0xd3e3f7ac, 0xfde7083b, 0x32b5dea5, 0x5cebf801, - 0xe9107789, 0x49e2c7b5, 0x7ef182ae, 0x96f5c8d2, 0xf140e507, 0x9cbf4beb, - 0x9d3e272d, 0x38247069, 0x25655f48, 0xb93abea1, 0x98e740c6, 0x3519de99, - 0x3b3fd689, 0x38e58f88, 0x71f6f527, 0x9ac9df08, 0x96fb860c, 0xf2546bc5, - 0x78ff9007, 0xffe72f7b, 0x1b3755a7, 0x28d6fd0e, 0x23a5d66e, 0x60b23cdf, - 0x9a639d38, 0xc141d621, 0x9033e07a, 0x7f2f7755, 0x7e1ede7e, 0xb56586ce, - 0x181defe8, 0x7c158f38, 0xbfde44bc, 0xd650073c, 0xd1474fed, 0xd4dcbee5, - 0xf0ed1a3d, 0xe2550fd9, 0x6addb3b3, 0x3d022587, 0x0ef6e82f, 0xcfe43efb, - 0xe94e7817, 0xb854ff21, 0xae02677b, 0xd26b7457, 0x3e786e95, 0xdbdac4f6, - 0xaf73bbe1, 0xe6241c18, 0x7f49e24b, 0x6e697bcc, 0x8ef3c0d7, 0x2f97f51d, - 0x38bfef99, 0xe7c01493, 0x38dd7b7c, 0x775c00eb, 0xe21d84bb, 0xe6e3b1f8, - 0xbac5e02a, 0xc343c14e, 0xcb50c4ec, 0x3d773c6a, 0x3024c413, 0xec42784e, - 0x7a101f8f, 0x1109fa45, 0xa67e785d, 0x7b37f38e, 0x0dbf2155, 0xbffa347e, - 0x944f9c52, 0xebea5f7a, 0xfb4b5632, 0xf81247c1, 0x8ab9c639, 0xe055da97, - 0xa8a82ece, 0x420f2b12, 0x79356d97, 0x97d419bd, 0x480fd035, 0xfbe762ee, - 0x9e57c643, 0x652db645, 0x417e7ccd, 0xbc19ceed, 0x1d19cd25, 0x75894ded, - 0xf51b0ae3, 0xfc60706f, 0x69c854a4, 0xf5e2ad79, 0xdd9079f1, 0xd98af194, - 0xdb066ec2, 0x28f60ea7, 0x0ecd0ec8, 0x56acb3b2, 0xde01576b, 0xc2471c48, - 0x2ba70c1b, 0x987842c2, 0xbda17007, 0x0f7b712d, 0x15b8244c, 0x03b25007, - 0x35cca53c, 0x01e70626, 0x477b3ef5, 0xd5e782f8, 0xcf315e01, 0x1c4bb860, - 0xff70fb9f, 0x5187cf18, 0x1e6829bc, 0xfec11e92, 0x894ba49a, 0xa4b7e387, - 0x7e7a2141, 0x3207eeda, 0x7e491b8a, 0x9d500581, 0x44d77bf6, 0xeba567d4, - 0xf866ff40, 0xd3f247f9, 0x8517563c, 0x7cc152fc, 0xbe50932b, 0x46d3757c, - 0xe1bedfa2, 0x49ca237d, 0x53d7cda1, 0x5c288317, 0xb4bcd3fb, 0x1044f580, - 0xd7446f9e, 0x9c378a6f, 0xbdc65e95, 0x37b34f00, 0x41b0ceab, 0x1ce2769a, - 0x60e48791, 0xc463c78e, 0xb11cc6f8, 0x9c11bfee, 0x6e7e7a95, 0x76f086fc, - 0x5b7d27e2, 0x68baf3b8, 0x9fbf62fd, 0x943a33d5, 0xaff76a9e, 0xdffaec82, - 0x217e3c0c, 0xbd55f1f5, 0x5025e293, 0x2aaefc2e, 0x079b8f2b, 0x2cb4f1e9, - 0xc225e3d2, 0x4e71cbae, 0xf149dfad, 0xf768d9b7, 0x5d3fca03, 0xfee293b7, - 0x476657c6, 0x6a7dffa1, 0x78b5ccfd, 0xb6d4ebbe, 0x4be76499, 0xde76939f, - 0x1ff40c6d, 0xbd17d772, 0xdfe463f8, 0x9f1461ad, 0x16efd92f, 0xabd01eeb, - 0x9ebeced0, 0x8eb651eb, 0xb452d5eb, 0x1ec80387, 0x8b76c6f6, 0x51bddc4b, - 0xc9ca020e, 0xe99e2e4e, 0xe81eddfe, 0x11cbf177, 0xc2a10f0e, 0xdf91d3ea, - 0x3da1f56e, 0xf1f85f2c, 0x0ee73c51, 0x1fa3fff6, 0xd90ffb48, 0x92f77a8d, - 0xc26f282e, 0x1bab97ee, 0x27e8add3, 0x5ff13b08, 0x3439bfc0, 0xfe1087fe, - 0x01ff118b, 0x6bc720fb, 0x06679e38, 0x1ac4ffe1, 0xdb95974e, 0xfae147ba, - 0x774d78f1, 0x6f8eb3f2, 0x9ff849eb, 0xcff01ab5, 0x3f5a5fe3, 0x8ff006ab, - 0x3fc408eb, 0xdfbc5bc0, 0xe0eff02e, 0x78e1aff8, 0x3a786b67, 0x3d9e03ab, - 0xf1618e74, 0xf40e4daf, 0xf984ce1b, 0xb33a9fc8, 0x01d5655d, 0x83f4987e, - 0xbfb560be, 0xe24d7f42, 0xe6af6e7f, 0x0a7fa841, 0x1453fe9f, 0x76ee61d2, - 0x80efa41e, 0x82ece67f, 0xfc7fb8fe, 0x95e9bf76, 0x7e01f12e, 0xa9d24dd3, - 0xd918b982, 0x1d3f86c5, 0xe28375c1, 0x786d4f84, 0xd7dc468f, 0xd7ded7a8, - 0x851933c0, 0x382f8c36, 0x278466cc, 0x8a1ef835, 0xf91c619b, 0x9f3f3d9f, - 0xbce490b1, 0x6dbe7355, 0xba19f322, 0xa758ffa0, 0xf2c6fdd0, 0x39513945, - 0x55d4e30c, 0x2ee9c704, 0x78fce68a, 0xff23aab9, 0xfdc8ccb1, 0xf93fb948, - 0xde0ff0ae, 0x25d7c2ed, 0xd2b175ef, 0x18c29777, 0x164b81d9, 0x23ef17a3, - 0x112a7ac0, 0x31ecf7c7, 0x228edd11, 0xd57f804c, 0x6036e228, 0x1f4f9102, - 0x1f4f9c64, 0x38a26c8c, 0x5e54ac39, 0xd0f8bb40, 0xfc839312, 0x8a68b8da, - 0xf4203ed7, 0x2b9183dd, 0x1e1f685d, 0x313a348a, 0x783d7e85, 0x1a30ce88, - 0x0df18786, 0xafba46c9, 0x796e6853, 0x0fbe9705, 0xd4789e27, 0x06dea00c, - 0x55c637ee, 0xd75dd7e0, 0xc5d23b63, 0x9c6d1f4f, 0x743c32a7, 0xe055a3dc, - 0x293a714b, 0xbe82639e, 0x2b8e01c3, 0xdcb12f68, 0x9df1e56e, 0x8b27400d, - 0xe5c1be9f, 0x03f7c3cc, 0xe35cf0ca, 0x6419c628, 0x935fe104, 0xfaf2332f, - 0x26afc4f0, 0xec66cbac, 0x103ecccf, 0x3a8656e9, 0x45f7d704, 0x978c5ed1, - 0x25f183df, 0xe27aa61b, 0xe67ac997, 0x26b4f1d1, 0x89cccf12, 0x8144d378, - 0x9823a9cf, 0xeef01a2f, 0x778da83b, 0xf9d3e7dd, 0xef7e037a, 0x911afbd1, - 0xbb66753f, 0xb8e30ac1, 0xb82194f2, 0x7e5b292e, 0x25a6f073, 0xa5d7f39a, - 0xcfc75e42, 0x80feb585, 0x041e21c7, 0xcdbc4561, 0xeafdb3d0, 0x8807ce10, - 0xdd9b4a97, 0x2816ed43, 0x71950f14, 0xc1ff4936, 0x1d207dd0, 0x41f0141f, - 0xf851353f, 0xbd3431bd, 0xf5ca26fa, 0xabad1d73, 0x9bb90be7, 0x9b6de52f, - 0x27c6de56, 0x82bda9da, 0xede0307e, 0x26769141, 0xff44e317, 0x5cb912e3, - 0x78e2dd64, 0x9d35b22c, 0x7908b7ce, 0xfef13729, 0x88f7f8e5, 0x8da24c74, - 0x00f095fa, 0x7ec71ebf, 0x9001a074, 0x56d64f5f, 0x87347f93, 0x33b5c405, - 0x5f24edfc, 0xebb7cc77, 0x4c75dd11, 0x10b3ad8d, 0xc2f7caf5, 0x1f47a81c, - 0xacf5d634, 0x4ed8ec8a, 0xb214dbee, 0x3d230366, 0xc261e229, 0x23558cfe, - 0xa1407ce9, 0x5e0fefc2, 0x7478b1ca, 0x31a718d1, 0x630b6910, 0xf13f3a14, - 0xf27fb137, 0x89e2f450, 0x5185d728, 0x33a63d46, 0xfbf52b58, 0xe8b76b77, - 0x33de18fb, 0x0e763156, 0x77c88f03, 0xa8d5b8c2, 0x8d7e7877, 0x4aa29b33, - 0x21c77f22, 0xdee1e027, 0xca7f406b, 0x09df2f7f, 0x4b7a5ffd, 0xe93bb3d4, - 0x0b8f4bfb, 0xf2e4f63e, 0x7d65cffc, 0x92afcf1e, 0xff3cf9f5, 0xe45feca4, - 0x5faa0e9f, 0x4bff5416, 0x3ebc5f9e, 0x7e83df3f, 0xd2ce68eb, 0xd214a385, - 0xbe847b53, 0x23ee5c28, 0xf6ea16fc, 0xf33474f2, 0xdc6eb2e9, 0x6ba2536e, - 0xd51fda0f, 0xf682d272, 0x2764d5f7, 0x704f9fe5, 0x75c44b2f, 0x63c524d4, - 0xa1fb7d44, 0xc4c1ec97, 0xed1fce4e, 0xf8e3c2e9, 0xbfa0929b, 0x05fb7ea1, - 0x8c4eacfd, 0x1c7ef5bf, 0x80ae1c49, 0x26f99e7e, 0x23a7fcf0, 0x49be1b3c, - 0xb592b33f, 0x487f48fd, 0x86be7549, 0xe32763f3, 0xe645e734, 0x8d11c4ff, - 0xe78627f1, 0xf3f50045, 0x67a5d797, 0x5ff3ff42, 0x04bd3d7d, 0xe76125fd, - 0xcc74da2b, 0xdb34f789, 0x1be7a518, 0x7de2313f, 0x8d5d8ab3, 0xaed071c6, - 0x00dcd212, 0x9c04cab8, 0x93f4e760, 0x8373ec03, 0x3d8c1bd0, 0x5f37f7cd, - 0x7a47ab3d, 0x9dd5d7ce, 0xf6ed0e7a, 0x3ee42528, 0xddf166cd, 0x17ce4ed1, - 0xe87a15ef, 0x11b39a6a, 0x8c6bf9e7, 0xb73e4021, 0x60fb93ba, 0x855f1c49, - 0x1ccdeec2, 0x01db3166, 0xe43f43cf, 0x1b2554fb, 0x3c608632, 0xd184cdf8, - 0x6d7e24ef, 0xc795b53c, 0x3c781b53, 0xbcd6d0b5, 0x33379408, 0x31ad9526, - 0x84d8c1df, 0x0339485f, 0xf36f8591, 0x9d5f324c, 0xc79b263f, 0x767f30bb, - 0x506b63fd, 0xb9c29a6e, 0xf0d0fb1f, 0x17a8e181, 0x7422325a, 0x37e79056, - 0x498c8be3, 0x8efcb143, 0x639e5871, 0x222af4b2, 0x8be232fc, 0xc75de337, - 0x3db05f90, 0x46dc41c6, 0x307dfc5f, 0x2adbf70f, 0x0f75a79d, 0xda87708a, - 0xc087fa77, 0x4ac931ab, 0x19901369, 0x870917fd, 0xf9fc1f1c, 0xdfd0cd45, - 0x8349e5c9, 0x9f71db57, 0x3490c725, 0x467e3fd4, 0xe072fb82, 0xac7527f8, - 0x6e292e17, 0x024b8e16, 0x5dee030e, 0xd95dbe03, 0xac06732a, 0x898f26f3, - 0xcdefe4d0, 0xc0ce658f, 0x29bded38, 0xc2f4fc9a, 0x0ff69aee, 0xa9afeacc, - 0x6735302f, 0xb1f80555, 0x1e49fb9d, 0x62d2a782, 0xee7f4709, 0xfc5f0def, - 0xfff441e5, 0xf40eab36, 0xd9eee755, 0xa1db97f2, 0x4e3c65d5, 0x3b47f145, - 0xc9cecbc5, 0xa77a28f3, 0xe85f703e, 0xf3a66b22, 0x03ed9d3e, 0x7cee75c9, - 0x773a7eeb, 0x03ef5df6, 0xeb124af5, 0x086c21dd, 0x55cbc3da, 0xaebc511f, - 0xefcf9222, 0x8cc7ebe2, 0xfb8a0fb8, 0xdf81d78a, 0xd10fc2ef, 0x50f36c3f, - 0xfeb73b3c, 0x1d9bed18, 0xba7ae448, 0x1e817522, 0x42551def, 0x1c68768a, - 0xe068abe8, 0x3646e697, 0xbbee1770, 0x1fb85866, 0xb19936de, 0x1e2be458, - 0x884a69df, 0xf3d77ba1, 0xbca8f26b, 0xfa9c2da2, 0x1e6d4f7f, 0x5f09e747, - 0xa1ff6853, 0xe5a1e520, 0x29b87e78, 0x11e033dc, 0x77e0b718, 0xde21e577, - 0xf3f1762a, 0x9fea05b5, 0x5a4016b3, 0xdf479b56, 0x49aca817, 0x42617f01, - 0x05bfb72e, 0xaf21f368, 0x46acb30e, 0x7d1aabbb, 0x3d479ebd, 0x9e90b463, - 0x807b6e89, 0x336cafc6, 0x24f7f7d3, 0xd0d77f71, 0xdb1ae1c2, 0xc972a2e6, - 0xba93530f, 0x860fd669, 0x7c7acdf8, 0xc2d0c397, 0x6dddfda8, 0xf39528fd, - 0xafcfbb7d, 0x21ae3ee9, 0x14b8eafe, 0x71dbf798, 0x90dc958a, 0xa57c3d20, - 0x0b34786a, 0xc7daa7a1, 0xf4e7e369, 0xdcfc6d4c, 0x738a615e, 0x31c0127e, - 0x3d16b1f1, 0x48b107ee, 0x35f115b3, 0x7b60c471, 0xa97c8049, 0x2237ef7b, - 0xdeeb0c7d, 0x369da237, 0x501b9a41, 0x33ce2e5f, 0x05e9eb04, 0x2f4f5249, - 0x1dda54a3, 0xf9067576, 0x82ac33a9, 0xccfc8501, 0x7e54fa10, 0x1a6b4cdf, - 0x1e6ee3a0, 0xc5347fc7, 0x45f502bd, 0xbe9b0e73, 0x7366f483, 0x7cc3ee3a, - 0x9d03f057, 0x89f90acd, 0x751e742d, 0x0ebb08e2, 0x04abffe3, 0x6f8e525c, - 0xa2c58f34, 0x5b2a7bfd, 0x77befd82, 0x4ecd9de7, 0x47f1afe8, 0x0f689999, - 0x25cfb8e4, 0xcc297bf1, 0xd70d7ada, 0x446f9583, 0x0bde51d8, 0xfb863170, - 0xb44c7b9d, 0xda72814e, 0xc37ca8cf, 0x89ef09b4, 0x7ac14654, 0x7dcfc615, - 0x7c87cc33, 0x9866f8dc, 0xef46ed1e, 0x4873f774, 0x7b37dccf, 0xa1f5c18f, - 0x67a4c1b3, 0x9f38f7e4, 0x09db3d27, 0x5bd237bc, 0xe5267cc1, 0xe5c35dd3, - 0x69f048a5, 0xb73f90b1, 0x552ba390, 0xaf0e485d, 0xe340063c, 0xca63e93e, - 0x27e85dc0, 0x7ef42dd8, 0x02cb9493, 0x79410f5c, 0x3a18ff41, 0x8dfd2bff, - 0x6b2c3960, 0xe5bf52b3, 0xef21766d, 0xb94bca36, 0x6372162b, 0x2cc67e12, - 0x53bbe7c1, 0x5e20efdc, 0xee41aa0a, 0x3f1f68a3, 0xcfc9e50b, 0xf22b4637, - 0x624df017, 0x54fc8049, 0xd0cfde37, 0xb9c5313f, 0x41666f88, 0xcc9fe81a, - 0xac4ff76e, 0xfe0012e3, 0x74322b89, 0x9da9df78, 0xe6f9db7f, 0x8f7ff8e6, - 0x48e29790, 0x67f44f5f, 0x0e61550d, 0x397e873c, 0x2cf7ef8e, 0xb8f1c55c, - 0x45cae0d0, 0x2fe162ff, 0xa1978a15, 0x697a81df, 0x632a91d8, 0xfee51c60, - 0x0ecc41b6, 0xd6d29878, 0x1337d283, 0x0f1147dc, 0x04d36d45, 0xa37d06be, - 0x4ea1c5fd, 0x7832471e, 0x198d8e4d, 0xab724718, 0x6933e748, 0xe04cfacc, - 0x1d7ade7e, 0xbee4c3c5, 0x992b8ca3, 0x807cbcf0, 0x5f42fd1d, 0x37ef4e9b, - 0x7299c704, 0xb0bfddb8, 0xbf7640d9, 0xc3cff1ac, 0x2e7f5074, 0xed05d9c3, - 0x777a97c9, 0xbcf5f21b, 0x0d57dec9, 0xe4ff9f90, 0x7691a8ce, 0xf4eb3e3f, - 0x47689ebe, 0x188f00eb, 0xa35baaef, 0xbfb979e6, 0xc9f7c113, 0x7e4b7f38, - 0x79f3e60e, 0x9f88dd6d, 0xc89954ae, 0xbe015d0e, 0x48760165, 0xe7a91dda, - 0x7c91fda5, 0xfae7ae5d, 0xda323cab, 0xb408c9eb, 0x395c933b, 0xf87d77c8, - 0xddbf1a79, 0x1476b4d9, 0x38a5c1ca, 0xed28b73a, 0xbc1cb046, 0xd31c14b6, - 0x8eed1d5e, 0xcf52ebd4, 0xfa35bb4b, 0xfe772fe5, 0x8a55cd15, 0xe032407b, - 0xb73d6eeb, 0x2deb775f, 0xe3633fc4, 0x6f91e926, 0x1e8f5e6e, 0x98f47a13, - 0x74568f46, 0x27060762, 0x741c9adf, 0x4cf3ed15, 0x3d447fdc, 0xa3dfd81f, - 0xe0c7a329, 0x7327c63c, 0xc15dfb3b, 0x1ffe99dd, 0xfa6b7c9f, 0x88b2587f, - 0xff40ddf7, 0xfd732617, 0x99efac1f, 0x73a7bf95, 0x2f5f4f69, 0x0ca383da, - 0xc1da03ec, 0x16fb0886, 0x5ec80f61, 0xbf7b4784, 0x4d5c1ece, 0x7888599b, - 0x1e0f610a, 0xf616fe4a, 0x94a1f240, 0x5227291b, 0x48e5822e, 0x9f84c5ca, - 0xe9113ac2, 0x57bf1ef4, 0x6cf7ae50, 0x7b46fda3, 0xcf9460c4, 0x976e3f76, - 0xc1d6f242, 0xf1f9084e, 0x6ed68bcb, 0xf290b948, 0x5ca7e522, 0x20ecc5c8, - 0xd6a7d8b9, 0xf70a333d, 0x6bdd92cb, 0x72fde393, 0xd823b652, 0x57ca743e, - 0xb3645918, 0xf218aae3, 0x81a43955, 0x44ea657c, 0xbe499e1e, 0xd968bf35, - 0x6fd3f24d, 0xf4fcfbfe, 0xe9f84e9b, 0x3f0dbe7f, 0x3f63f475, 0x3c03b2ce, - 0xdf40b257, 0x6df9f866, 0xfb8c3bc2, 0x7af9dd0f, 0x0497d600, 0x8d319377, - 0xae133ee2, 0x2f8a2ab3, 0x7494be0a, 0x6cc0fe96, 0x93387711, 0xe1077ae2, - 0x82c0f5c5, 0x447bd39b, 0xb35c5367, 0xb327d711, 0x03f40d21, 0x9b7ff33a, - 0xbdef516f, 0x3e749371, 0xfb9dfc96, 0x4392c78d, 0xb1c78dfb, 0xb5d29bfc, - 0xf8899720, 0x300b8fde, 0x29e138de, 0x0acb6791, 0x46d38f10, 0x3c9ffac8, - 0xfa81ece9, 0x38b8c981, 0x53de39c5, 0xf4b3de45, 0x3f6818f0, 0x8fe619e1, - 0xd8fd439b, 0xb8f6e8ec, 0xedfcc288, 0x3b1fe795, 0x51e886bc, 0xddcce5cb, - 0x3ffbe7a2, 0x79059f22, 0x447e404b, 0x6f037e50, 0x616fa51f, 0x9045e781, - 0x9c21949f, 0xff00aece, 0x7fdf8601, 0x5585ed05, 0xa8d71861, 0xd6f8db8c, - 0xf56bd415, 0xb545ed0a, 0x14d581e3, 0xfbc55338, 0x735f94b9, 0xc23e09d8, - 0xbe78bb03, 0x93ed4a4f, 0x37e8bd1e, 0xa1bddce0, 0xb9d2714e, 0xb78a1183, - 0x7c47465b, 0xdad149f7, 0x6bd1fc27, 0x1e7867bf, 0x6fbe56ef, 0x8dd6cfbf, - 0x6e99f7be, 0xb2fbfc61, 0xfe7f9f43, 0xefe70a5e, 0x21d15931, 0xa8a5c7eb, - 0x37111fbc, 0x68a1f1a0, 0x7be85d4a, 0xb8c513b0, 0x425fb8cd, 0x24f6dcf8, - 0x28d9b7e2, 0x93f2fdf1, 0x196377c8, 0x60cfc4d3, 0x9fdfca7c, 0x8d4172f2, - 0x19d74f9e, 0x9bafaf84, 0xa91480ef, 0xf2f8fdbf, 0xf4cbd104, 0x8476f835, - 0xfb5db7c0, 0xe8ebefbd, 0xf7c3ac35, 0x48e76f82, 0xf86a763e, 0x22ef5a3d, - 0x538e8cfe, 0x5747e8ac, 0xe0d6c2b8, 0x9f2fc17a, 0x6cbe27bf, 0x1d03fb96, - 0x02b5efe4, 0x890abf94, 0x4febcf47, 0x74bafca2, 0x3cb9eded, 0x7335f3b6, - 0x52bc01f6, 0x7fbe0fc8, 0x27faf9e4, 0x7c092e31, 0xd794f541, 0x2c1dc007, - 0xf941758f, 0x15f920ec, 0x03fa47f2, 0xa9e001ed, 0xb8b7ea27, 0x007b4663, - 0xd04cfc9f, 0x27b8a2e9, 0xfb9a3cda, 0x78ddcd93, 0xfb8523ba, 0x7c09cf8f, - 0x9bed126e, 0x90f003c3, 0x1f1fe1aa, 0xe6025bae, 0x3fba784d, 0x93fbce4e, - 0x63d07c82, 0xbf5e36cd, 0x27a3e52d, 0x7cfed93d, 0xa6af7f70, 0x7880527c, - 0xf1fff7f1, 0xee23f461, 0x91db7817, 0x27b0e472, 0xc139d052, 0xf0214eff, - 0x5163bd07, 0x74a1fc8e, 0x761f8fe4, 0xd04f4fe4, 0x774ef4f7, 0x3a7bdf67, - 0xfa0cef7e, 0xea3de19e, 0xd05eff9b, 0xae883f2d, 0x1d744179, 0x942f9413, - 0xff46af79, 0x5c5cbd4a, 0x09e3f4ff, 0x54df1871, 0x9fbf38e8, 0xbd934f9f, - 0xfc956f99, 0xf230e67b, 0xcf9f9fab, 0xd7279e12, 0xce79ba09, 0x787a893d, - 0x51e1ea12, 0xd414fcfe, 0x5f3f9443, 0x7e61fb80, 0xea81757b, 0xed91abef, - 0x7afd922f, 0xefec8560, 0x3a4bca33, 0xb225cf32, 0xbd0bf777, 0xa4ad3cc3, - 0xf035e7f7, 0xfe7d3fef, 0x2b5fc3f3, 0x7841b50f, 0xf79410d9, 0x775fb504, - 0x22b6fb03, 0x82c7fbe8, 0xe504d7ea, 0x6be507d7, 0xcd17dfb4, 0x8b0e4852, - 0xc9fdf046, 0xe60cb960, 0xda522f8f, 0xf6ed63e3, 0xff24895c, 0x1357234e, - 0xfafe79aa, 0xa829fff3, 0xa7c80c89, 0xb21e89b0, 0xc05a30ef, 0xb9d041fd, - 0xc1f8151e, 0xbcde89d0, 0xecde99d8, 0x79ef6c13, 0xd7f03ffd, 0xd22fda24, - 0x54fb25f8, 0x9551be6d, 0xbbbd4770, 0x5f603228, 0xe2265995, 0xfdf3baba, - 0x6389889b, 0x22fc0352, 0x6744f84f, 0xfb653cc0, 0x575d5f71, 0xd4f8bc71, - 0x719b89f0, 0xd8b4687f, 0x14f1b4d7, 0xf68aa5ec, 0x6fc452ba, 0x5d39e1c6, - 0xebee176c, 0x0fd030b9, 0x70bd7562, 0x523f8d9e, 0xd550bbf9, 0x53c01f40, - 0x79d3b311, 0xea7899d3, 0x47d43bbe, 0x0df92f47, 0x47efb77c, 0xd3b412ea, - 0xd2c49747, 0xa945a639, 0x17dcefdc, 0x366135dd, 0x1e231be4, 0xf8db7d26, - 0xf74a58c4, 0xad95ceaa, 0x353ae856, 0x5f646279, 0x3c268fac, 0x4fc43639, - 0x9dfc065c, 0x38276a99, 0x426b36dc, 0xabdbfa3d, 0x085fb40d, 0xfc457e2d, - 0x3069a4f3, 0x968bb7ae, 0xb0fda7f5, 0x1a4f9fe2, 0x8ab0f787, 0x3ed0371f, - 0x4ace8b49, 0xeaf72271, 0x6a2e74b1, 0x7a910ad6, 0xcdf4a2ee, 0x1abafcff, - 0xbeb569ef, 0x0efbd0a0, 0x7bad5c77, 0x9b9e1067, 0xf74ee9ac, 0x7580de2e, - 0x3efb9e00, 0x17b7bebe, 0x089f21cf, 0xa473a2ab, 0x8bee9ed0, 0xbfb35e95, - 0xdb0b313b, 0xd0e5d6ab, 0xa39414fe, 0x956a7cff, 0x41ef09ba, 0xc2594515, - 0xa9f6fcf1, 0x75c518af, 0xa26e3d4e, 0x478e2277, 0x8fac67ba, 0xe8b8fba3, - 0x8a53b3e9, 0x3c014a3d, 0x67d0da4c, 0x96126262, 0xfb7d049b, 0x1e011544, - 0xfced748a, 0x24a4f643, 0xa527e786, 0x05b899f6, 0x97ea71e6, 0xd87ce9bd, - 0xe4e754c1, 0x2fd7c054, 0x52539cd2, 0x6e5e11e3, 0x0ffcdeb7, 0xe3fc8fdf, - 0xe404e285, 0x395287af, 0x56d1bf5f, 0xbef8109c, 0x3d45c977, 0x469bc1f1, - 0x277a22fb, 0xc14d3c30, 0x41f03675, 0x67cdc62c, 0xf00b7589, 0x219d92f3, - 0xa9e1abfc, 0xf1abd12a, 0x48d9f1a7, 0x0f5f3f5f, 0x19f5177f, 0x5f2037ad, - 0x2d7321b1, 0xa693b9da, 0x0f44ec25, 0x91fe7ed6, 0x3c230bed, 0x7985b619, - 0x7e3032c3, 0xfc871cea, 0x7aeb12cd, 0xc804b64d, 0x77ff68a1, 0xfbe73f0f, - 0xeb8f6877, 0xfe7bbfbe, 0x9fb812d7, 0x4697db21, 0x5ce83c59, 0xf458b69c, - 0xfaa38f48, 0x3cf0a7a5, 0x060bc95a, 0x2f2503b2, 0x8ad63fc4, 0x06f807fa, - 0xf3c16be3, 0x81aa63fa, 0x933a31c7, 0xad18cf4b, 0x1331b25c, 0xc99dbe71, - 0xdc86cd65, 0x3b239b89, 0x2b52cb97, 0x5ee34fd7, 0x9651efe0, 0x71e8b50e, - 0x0bf4737f, 0x7ba16d6f, 0x86c20b74, 0xd289bde0, 0xaf444c17, 0x63c58b16, - 0x13ef0dbd, 0x9031f458, 0xedca9b3e, 0x9f90bd69, 0xcde9955c, 0x7ba52843, - 0xf0df7212, 0x9e6792ec, 0xe797e3c5, 0x70da7798, 0x2765dfc0, 0xbbcbd3e7, - 0x063f8a54, 0x1f9623ef, 0x61cc69dc, 0x788fb137, 0x32c3fd83, 0xdfde22d6, - 0xf07dfd0d, 0xa9abe1fe, 0x0687fbc1, 0x2a5e4fba, 0x37730ff6, 0xe9770428, - 0x3fcf7e12, 0x8dc79637, 0xfa052e4f, 0x1ede691b, 0x0f3c10eb, 0x294eedcd, - 0xf866bc53, 0x0b0daef5, 0x13d98e28, 0x6e7184f1, 0x89e26ef1, 0xae3a4730, - 0x085e4bf3, 0xfe96fc23, 0x7e5fee6a, 0xfaf78599, 0xd702e20a, 0x2f91fbd5, - 0xde197e38, 0x9cfd941f, 0x7a63f65e, 0x45f731a7, 0x7cc31f58, 0xabd8634a, - 0xbd2067f7, 0x9f71d292, 0x5d2bb653, 0xbc5ea3fe, 0x61afac1d, 0x4ab45d1d, - 0xecc7efe5, 0x041d9136, 0x01644f59, 0xad672cf7, 0x72346838, 0x8712c63b, - 0xeedaff09, 0x1c769fbf, 0x6eeaf1ea, 0x2687b8a5, 0x51ef27f1, 0xfbf8e915, - 0x853a8574, 0x268157ee, 0x97497ba3, 0x7b5fb953, 0x679f953a, 0xd0774a28, - 0xb5f29cfd, 0x0cf2c726, 0x7dfb4fde, 0x95df584f, 0x684b9aeb, 0x26f7f33f, - 0xae54ab8a, 0x45867308, 0x3b17f3f1, 0x6af9d006, 0x51f011bd, 0xe2fae766, - 0xa56f98b2, 0x745dd27d, 0x8ecf419f, 0xdcbea1e8, 0x7963f5c2, 0x923de00c, - 0x186e8a33, 0xe8c767be, 0x9bf624dc, 0x7c602834, 0x3f439445, 0xbf7f28f6, - 0x83563a4d, 0xdf6c1b71, 0x31e21077, 0x8474da76, 0xe49515ef, 0x76b49019, - 0xaf7dfa04, 0xdeb899a8, 0x6fb55a2e, 0xf9dfea1c, 0x8de307db, 0xeaf45609, - 0xe63f6407, 0x88b7fa0b, 0x90c56773, 0x22b677c7, 0xb93cb8d2, 0x8a2f1e55, - 0xef345348, 0xf2fac910, 0xbf1e0655, 0x8a8f3d07, 0xc7d97ca5, 0xa5b96fd4, - 0x6ff50139, 0x30c36ef9, 0x6951d3d4, 0x978b2e5c, 0x011f65a5, 0x44362abe, - 0x6583bbd3, 0xe623029e, 0xca156acb, 0x4f8bbffb, 0xbf3d3e47, 0xe428b5e2, - 0xbe61139f, 0x5a97689e, 0xe8398417, 0xc795a1de, 0xe8afceeb, 0x6695f749, - 0xf82d9b59, 0x45acc19e, 0xbfa86ddd, 0x467d5a8f, 0x975a3fac, 0xd3bcc3a1, - 0xbcc6cd6a, 0xe51b7f53, 0x2df38bcf, 0xa57c83f4, 0x6d973a70, 0xbfc467db, - 0xcc44324f, 0x1f2be2f7, 0x4ff8c2f4, 0x2f737a79, 0x07c02bb4, 0xcf1052bd, - 0x9764292f, 0xf3f1b62b, 0x2a0f92ee, 0xee400f90, 0xa83e09e6, 0xf7daf5d8, - 0x902a1e51, 0xf23a43fe, 0x7ef3f011, 0x71b1df2a, 0xefdfe31c, 0x76913e47, - 0x0c2bf20c, 0xf1df8c36, 0xa71a667c, 0xe18f943f, 0xfc019ee5, 0x39fb5d1c, - 0x741c8d04, 0x1a575f46, 0xcbc587b7, 0x5d6fa44c, 0x5a1e5c69, 0x428eed56, - 0x657c5dfa, 0x67dc01df, 0x5601df29, 0x1e421eda, 0x712a3e04, 0x3f0451fe, - 0x389517f9, 0xfcff28df, 0xc85ef9db, 0xf3e32561, 0xd4adf393, 0x7acbf98b, - 0xc124fdf1, 0xe04c652f, 0x2e6f576b, 0x50ce4277, 0x0ebde98e, 0x4db73f31, - 0xf7e50efb, 0x22dcfcc5, 0x28bad665, 0x17d20fc4, 0x103e0ff5, 0x04fa9469, - 0xbedc5c9a, 0x4bf1ce91, 0x57f8497a, 0xdf403809, 0x7e6c6339, 0xf274b63a, - 0xe095644e, 0x778f639b, 0xfc07af49, 0xcf4adf9d, 0xeabf116c, 0x7c93c603, - 0x7dcbc723, 0x38ddd279, 0x87dfe86f, 0x8f71cbfd, 0xd8f4227a, 0xe5c651cf, - 0xe52fc243, 0xa1fab732, 0x614707bb, 0xee968bbb, 0x9cde7003, 0xacd2ab8e, - 0xfd13bdf4, 0x59def805, 0xfadc50af, 0x1fe75898, 0xa8b5fc7b, 0x7e7e01e2, - 0x277c427f, 0x307f0cf9, 0x6de1263e, 0x7038f1b2, 0x0f52dc30, 0x9f73b849, - 0x2c6eefb8, 0xbee3f097, 0x4a9f2051, 0x957e4a3c, 0xf982f5f7, 0xda4e7896, - 0xfe73b54f, 0x463d4cae, 0x943a77e7, 0xfc27f707, 0x5ce213a2, 0xe33c6b79, - 0x8915ff71, 0x8af735fb, 0xb40c8b18, 0xc08ed23f, 0x807d1acf, 0xa7bf69fd, - 0x8b3ce716, 0xd690bb74, 0xc73ffa8d, 0xd0398cea, 0xe699d96f, 0x9dcef871, - 0xb8ef43f4, 0x31a353ea, 0x9f8bb55e, 0x52fc9377, 0xc93f6176, 0xffb8b941, - 0x83eab454, 0xefc8e182, 0xbed035bf, 0x63e3d14e, 0xcfdfe88d, 0x187332dd, - 0x41ef01a2, 0xbb3f5ea0, 0xbf266879, 0x984d6059, 0x3621f786, 0x01ed333f, - 0xaf559f28, 0xd80dbbd2, 0xd16fca0f, 0x5f1499a3, 0x52d6113d, 0xf8fd0a30, - 0xf456a81f, 0x32df6fe3, 0x7f6c31f4, 0x0c6ba5bb, 0x39b1b63d, 0x7d4ef296, - 0xe907d934, 0x8073caf7, 0xc7dee2d5, 0x3fde845f, 0xe22a9edc, 0x2f755ffc, - 0xdd6f8fdc, 0xacef4618, 0x75ed1a14, 0x4f6f1c3e, 0x54675a17, 0x23eaf11a, - 0xbf255bdd, 0x99918e6c, 0xb9508693, 0x0fca0939, 0x451f9a1a, 0x51f0723b, - 0x3f7c60cb, 0x86d7a992, 0x9a7f7315, 0x6ac63bef, 0x70912ddf, 0x0fc6247c, - 0xdf7e4fee, 0x1b08eb84, 0xefa44fdd, 0xedf8aecf, 0x6783b434, 0xe1b4f6b7, - 0x09ef4fbc, 0xa703fba3, 0xcf77da0d, 0x57def56e, 0x79297df0, 0x9a74f56f, - 0xfc938fd6, 0x377bc37e, 0x839ed37f, 0xa5b9d1bc, 0xdd194b0b, 0x8d397efb, - 0x2263f7d1, 0xe789dabe, 0x4d6a4b08, 0x7307bc56, 0xf71ef912, 0xfcab76b3, - 0xcb99a5fe, 0x99ddc9c1, 0xe4b7bf74, 0x525f3c6f, 0x3ef178a7, 0x9fa7fef2, - 0xb30af3a0, 0xabc4cfc1, 0xf3feed09, 0xa1a7a7ba, 0xb8765c38, 0xfe7de257, - 0xf9f95bcb, 0x32ef0e8a, 0x2079dc1c, 0xdfb9dec9, 0xcbfb5dfc, 0x9f110e32, - 0x2fcfbdae, 0x4fd72cf1, 0x8c3f026f, 0xdbc7e218, 0x90e74b67, 0xa9617cbf, - 0xca4bd29b, 0x23b7b5b1, 0xe9a25b1f, 0xeb1fc0be, 0xbdf1519f, 0x835df2a8, - 0x783ae1af, 0xbd346454, 0xd2d9f293, 0x7a8fb425, 0xa5156961, 0x0e32de92, - 0x46aec777, 0xfab3eefa, 0x9fbc06cc, 0xb46446fb, 0x90b603b0, 0xdeeced74, - 0xb9d79cb1, 0x4afa701f, 0x9d6dcfb8, 0x6af38519, 0x61b63e7c, 0x2235d224, - 0x5f7e8ada, 0x724738a9, 0xabf73d6a, 0x7fa398cf, 0x3df40f93, 0x024a61b3, - 0xbb3737be, 0x5869def1, 0xb147b25e, 0xb1c07ae2, 0xae145267, 0xb7d53edb, - 0xa8fde144, 0x7bcbd74f, 0x3bfa5e55, 0xd8f2a354, 0xca3f6c14, 0x0cf667a7, - 0x7c8d75be, 0x9e82f232, 0x879ebfee, 0x5c938a72, 0x0938a70b, 0xb9e2c4fc, - 0xf3afd991, 0x3afb4af8, 0x6ef3ac57, 0x347ef317, 0x31f726dd, 0x04773ca8, - 0x61bd3f2f, 0xefec44e7, 0x158366ec, 0xb36cfee1, 0x079ffa81, 0xc01d33eb, - 0x5f2b667b, 0xd71e60f7, 0xf2b767cb, 0x3abccdf5, 0x5f29bebe, 0xfbf27060, - 0xcc7e5aa2, 0xef47680d, 0x5ef274fb, 0x9f273cc8, 0x97b03cdf, 0xbe60df38, - 0x7475618d, 0x9e9bec8f, 0xdbe60d17, 0x855f92f9, 0xd7e7687e, 0xe044f8ce, - 0xf91de513, 0xbcc3f255, 0xdedf7cf5, 0x07383756, 0x47f24ef9, 0xd5593bf0, - 0x57dfc646, 0x7bd385d4, 0xed2293b8, 0x530fb406, 0x20c65ae2, 0xe74e3e5a, - 0xab9a807e, 0x37bde273, 0xf90a6d56, 0x748acece, 0x744557ee, 0xdeefc465, - 0xcf3f2b74, 0xc97fee29, 0x86922614, 0x84527b76, 0x343b0bed, 0xaefd3a79, - 0xcfc0f47b, 0x3db76e93, 0xd8c1ddda, 0xee0bd32f, 0x267cc3d1, 0x7776da65, - 0xbff3fc83, 0xb7f3c09a, 0x201a86d9, 0x78994cbf, 0xd7c818cf, 0x4a9f3ba7, - 0xece7180f, 0x38692e96, 0x19ff283f, 0xbbc5d796, 0xa5698e7f, 0x49760fb8, - 0x24b41d69, 0xfdfedfc3, 0x7fa3963d, 0x2df3fbb4, 0x18ee9606, 0x7f097980, - 0xdd25b4e8, 0xf8f4abf9, 0x8cc5e58e, 0xf5e74e3d, 0x0e1efc3c, 0x09ccb8fc, - 0xf38a4f78, 0x97bcb15b, 0x2f741353, 0x9fefc1c7, 0xf252fbc9, 0xff5f543e, - 0xb70db27d, 0x92ec9f72, 0x2a1dff81, 0x0fbda9c5, 0x89fc34a6, 0xf6a9f9de, - 0xa23096b0, 0x4d9ef683, 0x7753be39, 0xa20bdd1b, 0x6f4c87fb, 0x57337d27, - 0xac683bfa, 0x29dff987, 0xfcfc8960, 0x1f82a3c1, 0x3d652f4f, 0x9fe8807a, - 0xca39b77f, 0x985c700e, 0xfa85ebe8, 0xfddc3220, 0xe9d7c427, 0x0ba9d50d, - 0xaa1ef0e3, 0xed0f91c9, 0x7df978cf, 0xb7e132ce, 0x42f1cdb2, 0x3bbea82f, - 0x46535da1, 0x87684ddf, 0x757c17de, 0xfe97c321, 0x192bd423, 0xed049d7c, - 0xde5d3ce8, 0xb1e2bbf2, 0x4fed85dd, 0x700d98f4, 0xbc06009b, 0xfa1e35a7, - 0xf7a3611c, 0xfb4a98aa, 0x7efe5ecf, 0xa2799e92, 0xd5eef86c, 0x3ee2e933, - 0x9413dd11, 0xeff89274, 0x1a181740, 0x999d59fd, 0xbeee1019, 0xfdfd036c, - 0xf91f492f, 0xddc2e2ce, 0x7742fe3c, 0xe31e4524, 0xe2cda748, 0xb0759fef, - 0xbf916f8b, 0xd1e9620a, 0x330d9fe8, 0x11c9db43, 0xf5d88d1b, 0xff2f6d77, - 0x92fc2e9d, 0xe0706cc1, 0xa2a5923b, 0xd0b558cd, 0x2d5bef8e, 0x7bd3378c, - 0xe85f0b25, 0x96c1fc4e, 0xb60590fc, 0x89621b63, 0xa866565f, 0xf5b9ff84, - 0x2a1dde8c, 0xf3a64fa8, 0x36f5f994, 0x12daa34a, 0x6fecfca9, 0x7ae2c9de, - 0xe0a7d389, 0xa68cba7f, 0xd3ff4b73, 0xd9d6529b, 0x6691a77b, 0xf0bbcfba, - 0x0b6bb720, 0xc7bfcaa7, 0xbbafefc2, 0xc8ae3804, 0xb90b8a1a, 0xe753dc3a, - 0xf0ba57ef, 0xe77e00be, 0x677d5034, 0xfc4a57ef, 0x82dd049a, 0x7a9cb3df, - 0xde913330, 0x59ef147f, 0x9aed174e, 0xceb3bdc5, 0x4fbcb5de, 0x6a227bb4, - 0xddf2135c, 0xc8696774, 0x9ef52d77, 0xcffa0730, 0x7a48d486, 0x373ee147, - 0xf59a97f8, 0xf11e8b4c, 0xbf9b2d30, 0xba753973, 0xfd90deb6, 0x4373e939, - 0x92778776, 0x4d8fa80c, 0xecfb6d2e, 0xf50ec2ae, 0xf6bf7d65, 0x2354d15d, - 0xbe3d4fd9, 0x69f90b3b, 0xf4515de2, 0xbfffd10f, 0xff10b4ec, 0xb83bc49b, - 0x112b2ccd, 0xbeadc2f5, 0xdbfffb27, 0xefc1b1fb, 0x03bf06c4, 0x42eb7fdb, - 0xdd607e4d, 0x6fed350f, 0xa9ae5fab, 0xad5bec1f, 0xfa6ccfa9, 0xb43f2699, - 0xfb4d39f9, 0x693647e1, 0xbcb647ea, 0xfdbfa9a4, 0xfe4d0ecc, 0x683fd68e, - 0xb6d9dfda, 0x61cf9357, 0xe7da68ef, 0xe4d03f9a, 0x57ff5ac7, 0xc4aefed3, - 0xf1fa9a13, 0xfa9af3f6, 0x68ae7d09, 0x2f8e05f2, 0x373fed35, 0x457757ba, - 0x0cea22bf, 0x433aadf1, 0xf944f861, 0x6629a6e5, 0xba6b07d4, 0xf8247d0a, - 0xd3b0b96f, 0x7ba307ac, 0x6cd563ac, 0x3d5ff11f, 0xc1a0bbff, 0xde7f4f76, - 0x1ff8c4e5, 0x6bdf8d7b, 0x527f068b, 0x8c7e301f, 0xff02ccd3, 0x9e6c5dee, - 0x778f9355, 0x77da6a25, 0xd4d76e99, 0x68fbb927, 0x38e653ea, 0xaab4f934, - 0x5df69a11, 0xf9353897, 0xa69e4f0c, 0x971af77d, 0x76b3df26, 0xef7da6ba, - 0x7d4d6ef5, 0x4d1cef5f, 0x55adff7d, 0xbac0fc9a, 0xb7f69a25, 0xf5347bd5, - 0x9a357d83, 0x5aa6ccfa, 0xf3687e4d, 0xe1fb4d7a, 0xfa9abc47, 0x355b2d91, - 0xa99fb7f5, 0x68efe4d3, 0xbfb4d7ad, 0xc9a7cdb3, 0x9a83b0e7, 0xf7e6b9f6, - 0xd6b1f935, 0xefed344f, 0xa9a63c4a, 0xab3f6f1f, 0xce7e97a9, 0x6b9f3e84, - 0x53df85cb, 0xe697f8e0, 0x6ef7f6fb, 0x1f742877, 0x6ed75cea, 0x96c57df2, - 0x24fd1530, 0x6c99c517, 0xf5111078, 0xb727de15, 0x8539f3f1, 0x238aaf14, - 0x944c887f, 0x810bcf1d, 0xab8510df, 0xf40c8cb6, 0xfefc23ab, 0xccf5ea5b, - 0xdadff79b, 0xd5dcff84, 0xf288beee, 0xfb6eaf31, 0x989f7a38, 0x1c225679, - 0x77bffdf2, 0x956dde83, 0x19f378e9, 0x17f00fa6, 0xa6d5860f, 0x389af90e, - 0x05f378c1, 0xb6c1ef86, 0x22e22bf7, 0x17bdc7f8, 0x16bff406, 0xf7f817d6, - 0x9a976b23, 0xffc76fe9, 0xf295a96c, 0x522696eb, 0x3a00fffe, 0x0047bf29, - 0x000047bf, 0x00088b1f, 0x00000000, 0x7dedff00, 0x4554780b, 0xeedd7096, - 0x9d248fdb, 0x777579d0, 0x493cdc9e, 0xf09d0848, 0x3a3e00d8, 0xc0406021, - 0x490435e6, 0x41a8c1a4, 0xf881ba43, 0xbb75744f, 0xb2021031, 0x10d191b3, - 0x0186c195, 0x099d1964, 0x09d1a32e, 0xe09af09a, 0x1c604c3a, 0x3719d9c5, - 0x8ee2a3a0, 0xcfe31e10, 0x7fc38fee, 0x937ba9ce, 0x380e9dbe, 0xf7ff3afe, - 0xb4fbfa3f, 0xab755538, 0x739d554e, 0x2aaa3cea, 0x89895ead, 0xde6d6322, - 0xf39f4a1c, 0xc99899da, 0x316f36d8, 0x0ebddbc1, 0x72defd82, 0x9d7a774a, - 0x5bcbbf94, 0xaf1ef041, 0xdebdd28b, 0x79f74a1a, 0x92fe543d, 0x9fe081b7, - 0xb6947d7a, 0xff299b7b, 0xc10b6f15, 0x046dbc07, 0x53f5eabf, 0x4bdde1da, - 0x76de1be9, 0x76f4ef2a, 0xb7a6fc10, 0x6f2ee08b, 0xbc87c10f, 0xf11f04bd, - 0x98f8269e, 0x1ed28fb7, 0xbe9467ef, 0xf2a7eded, 0x0957bc77, 0xdbbf8ebe, - 0xcd2afc19, 0x2631e49f, 0x7ae69730, 0xc9ccc21e, 0x00f63226, 0xff824bfe, - 0xcc8846e2, 0x8cfdd8c2, 0xb0d73eff, 0x9413769a, 0x3ff2fe77, 0x74c60285, - 0x1f8d8ca5, 0xf662690f, 0xc634c6ce, 0xe675b026, 0xd318724f, 0x63d75740, - 0x4e09fb07, 0xd6191319, 0x2d75dfc3, 0x58c7dffe, 0x94bffc3c, 0x834c78e5, - 0x14095369, 0x55befb42, 0x1a777f82, 0x3e20d755, 0xbf1c8dab, 0x95135a69, - 0xf82c3e57, 0x5563020d, 0x8be9f322, 0x587dfb18, 0xc11b0154, 0x2e8f25d8, - 0x2172c447, 0x04830edc, 0x443a8ff8, 0x2c5d7e0e, 0x9da5b18e, 0xd29b1d86, - 0x84aaf106, 0xfdf035ef, 0x0c1a562b, 0x3a3d64ab, 0x1df203c4, 0x9ec618da, - 0x4ba6b8b7, 0x8a60ff90, 0xf687a7c6, 0xed9fc999, 0x2dec648c, 0xe6066b8b, - 0x77dcf25f, 0xc07f1b0c, 0x7ec6cf6c, 0xe2ba1b66, 0xfdff4117, 0x9df6b5c7, - 0xe1f3f0d2, 0x6c67296e, 0xdfca0ddc, 0x02ec973c, 0xa2ffca3c, 0x9ffce175, - 0xf85645d0, 0x492f01f3, 0x1a4a78e0, 0xeadb3a55, 0x7cf8825a, 0x47b9e919, - 0xe5f85303, 0xacf6ab6d, 0xae552181, 0x82e11aca, 0x2582eeef, 0xcd8c1963, - 0x418e9265, 0x38e67cf9, 0x2d4d069a, 0x17822e64, 0x6fa51f31, 0xb1aabbc5, - 0x4fccc59d, 0x21b26bb0, 0x82b8d435, 0x78cb72f1, 0x947c65b9, 0xabab71f4, - 0x20e5e38e, 0xba4c4ebc, 0xa5c71b23, 0x5596f5e0, 0x58737aa2, 0xefc476ff, - 0x3f1783cb, 0xd2863211, 0x174077c7, 0xeb1e6826, 0x73ac3d31, 0xf7d18ea3, - 0x7e088f8d, 0x2e856ba4, 0xb791992a, 0x0be418fb, 0xf4027481, 0xd2fc8451, - 0x92373a9f, 0x0949e4e8, 0x92707c1a, 0x0b1fa7d6, 0xb3f8d4e3, 0x87d12d05, - 0x1efc005e, 0x48fa0388, 0xea0e9e1f, 0xe00d219a, 0x67afa01f, 0xaff3bdb0, - 0xce0e5dff, 0x49cdfb97, 0xa357ce12, 0xe801d606, 0xd6b6f7d8, 0x99925bbe, - 0x94ed6014, 0x6ba47e31, 0x73edda26, 0xb17ae0c7, 0xdfa84ea5, 0xfb0d65ad, - 0xfbf687f3, 0xb417ae2a, 0x2ba6c27f, 0x9cbb53f7, 0x9ff295cf, 0x63c5fae2, - 0x5eadebca, 0x16ad69f5, 0xe8713ff0, 0x131a5e9c, 0x6f0d1c62, 0xe00666e7, - 0x3338eeef, 0xe44261dd, 0x45e7f2fa, 0x949fe60e, 0x1fa144e9, 0xb5d23ead, - 0x178814c3, 0xf9e817ef, 0xd13744e7, 0x4419cf40, 0xe0f89fcf, 0x690639d3, - 0xfb4822c4, 0x20ba6a60, 0xd660bd75, 0x672cdd23, 0x99ab4a76, 0x6007d293, - 0x9d7e91f9, 0x38f4a7be, 0x76b20fef, 0xbe2bafca, 0x7cf482d7, 0x8a95c6bf, - 0xa5eb2d70, 0x2feb377c, 0x2dfcc1b3, 0xd47b5e6c, 0x6fcf5806, 0x025a6a79, - 0xff3cefcc, 0xce98a3b2, 0xe27c25dd, 0x7a3f8893, 0xc13eaf10, 0xfa113eb3, - 0x92a5fbbf, 0x3f9049f5, 0x85d7cb47, 0x175f2bfd, 0x8f047e45, 0x97a1f81b, - 0xe341cb8f, 0xab9546d2, 0x09f2a1f8, 0x9da010e6, 0xff0683fe, 0xfe00b4ce, - 0xdfe87e28, 0x898e5093, 0x7ae0f7fd, 0xc434dfbb, 0x083f7ae0, 0x29c71be2, - 0x806b1838, 0x2ad690fe, 0x882a8863, 0xe1621fde, 0xb9f7ac76, 0xa79fdf4c, - 0xcfefa230, 0x4060e605, 0xa67417bf, 0x5ae50166, 0x0456cbaa, 0xbe60acf8, - 0x6ee50626, 0x38054bcd, 0xd725234f, 0x1fd744a7, 0xa61537b5, 0xa7f7fca1, - 0xf7ff280a, 0x698dec19, 0x5d84fdaa, 0xe321408f, 0x3f9f3861, 0x0ec776c0, - 0x3e284bc5, 0x14429ff6, 0xf33d0663, 0xbf888b19, 0xebe444d9, 0x57f13d44, - 0x066d4e23, 0x3c94e3f6, 0x9feda1a6, 0xf9edf190, 0xef744b4a, 0x16ecf183, - 0xf7c3f542, 0x60f8432b, 0x2c3f243f, 0xa7d1fa8c, 0xfa563e71, 0x64bea663, - 0x6a75d027, 0x86974b84, 0xc716c182, 0xcb998be5, 0x4fb49e97, 0xe67d7133, - 0xc8a8de4c, 0xdd8f6a65, 0x09d1e5c6, 0xf843e49d, 0x1d9a4944, 0x9c80d724, - 0x97f8abbd, 0xbb8f11a7, 0x2d2ea68c, 0xdd16eca4, 0x7d94fa9f, 0xff707d30, - 0x7fd94bbd, 0xeffbe16f, 0xefb5991c, 0xf1babb12, 0x3aecc67b, 0xfd972fc4, - 0x6d8f995e, 0xf22adfb8, 0x0b7ec871, 0xf9c5eb03, 0x832b2513, 0xc7c0b574, - 0xdc253abf, 0x36c47c8f, 0xf4f8d2e7, 0xfe0cfcb2, 0x58c15ade, 0x13c651a6, - 0x19704bfe, 0x20ce6659, 0x5663549c, 0x9b1e29c1, 0x06c8feaa, 0xe69e5549, - 0x679551cb, 0x7055db34, 0xaab14b56, 0x8736a8fe, 0x97f5ce0a, 0xede7eaab, - 0x31e0aa75, 0xfaaa15ed, 0xaa5c3b63, 0x1aaec2f2, 0x1eb8f955, 0xd09e0a8f, - 0xffaaa0db, 0xaa7da777, 0xcd7d49f2, 0x9f29f2aa, 0x5be0a8b5, 0xf554dbfb, - 0x57eabf6f, 0x7fb09795, 0x354f9556, 0xd3c157ee, 0xeaabafcc, 0x16fb80bf, - 0xb61dcff0, 0x0cfe556e, 0xbbeab8e9, 0xaa4e733b, 0x75e417e0, 0x270e2df6, - 0xe72d68be, 0xfb6cd1fb, 0x5876aa07, 0xfebe68e7, 0x7b6f3c61, 0x510b1fcf, - 0xf4d76e4e, 0x4add21a7, 0xf222735a, 0xdcf16671, 0x2c664043, 0x14aab1db, - 0xf94e5bc5, 0x1d308753, 0x8a5fdced, 0x715f926c, 0x05a610f2, 0xd0a58bae, - 0x44d7b31c, 0xc8b4c61f, 0x8ad53853, 0x3dcc34a8, 0xdf44e98c, 0x5728a9aa, - 0x3f5c785f, 0x2a28f91a, 0x074fa146, 0x827d67d1, 0x7eb9f886, 0xf28fc9b1, - 0x24c532c7, 0x96139032, 0xb1d65a1f, 0x9a8b4c02, 0x1af66d31, 0xfa0f5f99, - 0xba519780, 0xfe666bc9, 0xaf67206c, 0x93fae08d, 0x43a795f7, 0x44ab233b, - 0xe699aa33, 0x48258f51, 0xe5f5bed0, 0x765d9c96, 0xb0edd6c6, 0x42e5d7cf, - 0xc59e19ff, 0x4e01a23b, 0x30058e63, 0x2398167f, 0x25b19936, 0xfa76df3b, - 0x97c287f2, 0x244d9d33, 0x5cf6c417, 0x7694ffd4, 0x6e7e9637, 0xdf2198d7, - 0x11e74bf7, 0xf1adf798, 0xc21df4e1, 0xa75f9925, 0xb60b475d, 0xf69ef90b, - 0x4cfc7c10, 0x977fdf1a, 0x0a7d73a4, 0x66eb8487, 0xacc6cbe5, 0x808ca7a0, - 0xa93adcb9, 0xf0ea0ce1, 0xa027d9a2, 0xe0d7627c, 0x892b907b, 0xe0832958, - 0x4e01c3db, 0x6c625840, 0xc7eb967f, 0xc5d5afd8, 0xfa00d9d8, 0xc351a849, - 0xcf9e615b, 0xa3e20e66, 0x89f1aa5b, 0x8fdd0630, 0xf43b769d, 0xc60aadb3, - 0x3d56f00b, 0x7a9437d7, 0xf68c34a3, 0xf8d32ff7, 0xcdaece7e, 0xf49ea3b7, - 0xe79e3ca5, 0x3e8bfdbc, 0xeb7b44ce, 0x3589a52a, 0xf205c11e, 0xb4e95acd, - 0xae9ea0fb, 0x8423e611, 0x348bf2de, 0x1dd7be91, 0xa090447e, 0x1269a7de, - 0x7e9589c1, 0x0d52771a, 0xbf801bb4, 0x6609f44d, 0xe63db7c8, 0x9b3f1013, - 0xf06769d9, 0x885a331d, 0x3cc8d7fe, 0xcbf86b61, 0x0f418fa2, 0x769d79d3, - 0x13bba7ac, 0x271f33e8, 0xb86663d4, 0x47e3c94e, 0xa3eb10b0, 0x0d3e86a4, - 0x9f40dc73, 0xd47d4a8f, 0xddc5fb43, 0xe80b2926, 0xa6c585fb, 0xda211d8a, - 0x9f9e54fb, 0xfeea310d, 0x1f3e5a2d, 0x6cbedc8a, 0xf0a8ebe6, 0xa6689af1, - 0x526be392, 0x846f5bc6, 0xc8cdb5af, 0x6ef8015c, 0xd0cc7e85, 0x55abe1be, - 0xe83f1c66, 0x4fea4ed0, 0xc764f2e4, 0x6ec8728f, 0x21c75e0a, 0x3f9408f4, - 0xa3e908a2, 0x7c08dfcf, 0xdbd2a868, 0xfeb26f51, 0x7b809343, 0x116b2273, - 0x5358be50, 0xdc447aca, 0xae5744d7, 0x793e8433, 0xd654ba33, 0x839fd94f, - 0x3d774bd7, 0x9c12fde3, 0x31d57fef, 0x1f56c7d4, 0x05718f8f, 0x3a4c53d0, - 0xd662cba7, 0x98fe45a2, 0xbd29dacc, 0x7a52f585, 0xd4a7eb1b, 0xa622ccc1, - 0x694ecca5, 0x3a527319, 0x2d28799d, 0xce942d67, 0xce94ed64, 0x8294bd62, - 0x93a9433d, 0x9aeec999, 0xa637fb07, 0xd293980b, 0xa50f31ef, 0x7e9ce999, - 0xc10b582b, 0x4a76b377, 0x24ef803b, 0x8c01fa3d, 0x9c827694, 0x904df4c3, - 0x79769873, 0xa3652625, 0xd287201f, 0xa53b5e23, 0x94c5bcc7, 0x541d78f6, - 0x396f6def, 0x9d78efa5, 0x56f09e94, 0x75ebda50, 0xde53bd51, 0xf5df4a1a, - 0xcf7d287a, 0x69e940db, 0xdfd28faf, 0x1d299b79, 0xc67e07a5, 0x2be9cdf9, - 0xf53e7d44, 0x0243bd23, 0xe591ecf9, 0xe68761d2, 0xb8f1dc99, 0x40661a6e, - 0x235b283a, 0x7359fd20, 0xa43f0e34, 0x0b56729b, 0xe1ba42f7, 0x0cdfd704, - 0x0fd248d6, 0x82f56dad, 0x0876ed04, 0x5808da7d, 0xa9e9e9cb, 0x9f208d73, - 0xbad93a4b, 0x19c23b08, 0xee81194f, 0xfd3ce876, 0x64bca03b, 0x08d734a7, - 0xc8e4d67b, 0x8fb1ff53, 0xe93e54c3, 0x03346b08, 0xfb3d2b3c, 0xe38138a9, - 0x7befc281, 0xaee6733b, 0x253c44cd, 0x34c5f3c2, 0xbf512c30, 0xfa44c47e, - 0xd9db6175, 0x93c00d42, 0x68454c1a, 0xebd40617, 0xae1fba42, 0xf2b9705e, - 0x9655b6dd, 0x0d879c46, 0x0e5a809f, 0x7d19a959, 0xd5f3ab85, 0x5ebe6aed, - 0x837b4cff, 0x09eb03fe, 0x7f6f6837, 0x7d32a396, 0x3a7effc2, 0xdd6fa60f, - 0x6bf68ff5, 0x8e640fc8, 0x5774fdc1, 0xfd339734, 0x04ee9fa0, 0xc8c577bc, - 0x1a4cc6f0, 0x5c43ca17, 0xd29b0db7, 0x77803efd, 0x1f573985, 0xd47ff2c7, - 0xd14277d8, 0xa6d770ae, 0xc933825c, 0xc621b13f, 0x8f931393, 0x97df3cfa, - 0x0d1f935a, 0xbff80293, 0xafcb9d39, 0xe95cb7ad, 0x447681dd, 0xc16586b3, - 0x979b3b77, 0x7681cc6f, 0xf419bc7e, 0xdc478007, 0x0b31bd5a, 0x6a37d3ca, - 0x19656a26, 0x78fc7887, 0x4d9ef573, 0x8f255fa8, 0x7686c98e, 0x99796433, - 0xb857db1a, 0x55bce806, 0x95a7b6af, 0x7e649ff4, 0xce6686a9, 0x954d6c82, - 0x3a1df4ed, 0xdfb81156, 0xefc64cfd, 0xd53c5957, 0x57fdcedd, 0xfee19186, - 0x25fc6027, 0xc3bfb923, 0xfe48ceb2, 0x7ff24b0e, 0xca03bc9d, 0x7634db2d, - 0x6b44e954, 0xea1d5aed, 0x3b598bfb, 0x810ee3f2, 0xe14bef7f, 0x0a28217a, - 0xec0373e9, 0xd3deadf2, 0xfc03328b, 0x9f0ab684, 0xc97bf680, 0x0fa15ac8, - 0x07e49ff7, 0x2dfbb405, 0x15c12e15, 0x8781f689, 0xb965cfca, 0xf80e927e, - 0xfbe12ad9, 0xb992fd40, 0xa15d7012, 0xd2768adf, 0x605158f3, 0xf8b3a77f, - 0x3b07ac3c, 0x75d5f499, 0x782bc27a, 0x97654ebe, 0x95f6c01e, 0xff2e0c75, - 0xabb7067e, 0x5d013d77, 0xe24c1f20, 0xdd89f376, 0xce3fa489, 0xa0770d69, - 0xa9e274fd, 0x6f0465d1, 0x3d40ec99, 0xc9eec4f2, 0xb39d31d3, 0x3bd52665, - 0xb41eb021, 0xb96ce787, 0xd4fcc45b, 0xdb0bc00c, 0x7a27a33b, 0x41e5b39c, - 0xcb47fbf9, 0xe358bcb0, 0x91da09fb, 0x22fb8dc5, 0x1c9e4ed0, 0xa6124af9, - 0xf57d3427, 0x5dffd0dd, 0xdc2bf666, 0xe31b9d9e, 0xfe1cb1fe, 0x74a9f731, - 0xbfd7ea1d, 0xf5a74f4b, 0xc41ccf9c, 0xec835007, 0xf6f65bba, 0x8a4d061e, - 0x3fded6dd, 0xe65ccc15, 0xc11f30e8, 0x5ecbb4b4, 0xd657d386, 0xe9823ce3, - 0x194f5ef4, 0xa7e52faa, 0xba608e5b, 0x3bf5d724, 0xff179f9c, 0xbcaf7be1, - 0xc7c8f008, 0x07a8cdeb, 0x37d13e65, 0xebf92763, 0x21f90c74, 0x45a7926b, - 0x746c048b, 0x787ca0c6, 0x835169f6, 0xad21b9fb, 0xc3610c25, 0xb41ae97d, - 0xb745770b, 0xb3b8d0d4, 0xe3ce19c2, 0x210fb0db, 0x3b45645d, 0x809f9063, - 0x3e1d692f, 0x10d3e993, 0x634731ed, 0x1fcf187e, 0xe1ce17a8, 0x5af503f3, - 0x27ea04c2, 0x13fb2046, 0xbfdc06d4, 0xddfef26d, 0x38093cc6, 0xcf48d61f, - 0x64ebf40e, 0x67fe7095, 0xb02e9c91, 0xfa44d37a, 0x96cd9c84, 0xb89dcf16, - 0xe897560e, 0x3ba40beb, 0xf40706d8, 0x19827491, 0x055bd7da, 0x219c830e, - 0x7e87f0bc, 0x42c98b0c, 0xbf828d7a, 0x0bda02b5, 0x1c7033d0, 0xdf834cf3, - 0x9b177429, 0x4235c7c1, 0x65acbfa6, 0xdf053dbc, 0x9f2e0cb8, 0x83496f01, - 0x7c6568f8, 0x009a1c60, 0xd1ea027c, 0x66f006f8, 0x05d21b76, 0xa7817a48, - 0xc703124c, 0x8471ad5f, 0x7a645da1, 0x4fe8fbf5, 0x02394289, 0xf753fe78, - 0x69f22324, 0x327238f0, 0x46df08d2, 0x6f5187d0, 0xfce2e99f, 0x11e958db, - 0x18423ec8, 0x3a2c9fc7, 0x35681fd0, 0x017416ad, 0xf326b5e3, 0xa5667a7d, - 0xcae51ba7, 0x3b08e2cc, 0xac9df7d2, 0xf3999d7d, 0xc04c91f7, 0xf81b146f, - 0x41c4d899, 0x4f47f0bd, 0x97127bbf, 0x97b59934, 0xf9fee2e4, 0x70b3fdf8, - 0x3a3eb6fd, 0x4ff107b3, 0x3baa79cc, 0x5e741a06, 0x197dd794, 0x6ca4ebf7, - 0x1c0e3f13, 0xe0079247, 0x8d44bf40, 0x41e81cba, 0x65742b05, 0x71a21a13, - 0xe444d1bf, 0x7a819ccf, 0xe486944a, 0x6129c83b, 0x33fd4841, 0xf9e4ae88, - 0xaee7d657, 0x375a4c8c, 0x03af89ab, 0x171bb7eb, 0x5583ca46, 0x6dfa09d6, - 0x011f3604, 0xa658df74, 0xd7680bf5, 0xac28fd62, 0x919de2cf, 0x8769d743, - 0x03399a4e, 0x1ac3f4e5, 0x74366ef3, 0x7edc815e, 0xc3ed7a4b, 0xf90e5471, - 0x7dfc91a2, 0x436af801, 0xb8f5eac1, 0xac6dfd59, 0xb48cee6b, 0xc989f9a1, - 0x3ee2660b, 0x68cb589b, 0x47cb83fd, 0x575ea63d, 0xa3c737b2, 0xbbf988ff, - 0xce7ac1be, 0x8655de4c, 0xbaf07cfa, 0x1a97742a, 0x105f7a1b, 0xa65f3933, - 0x954fd846, 0x92215e93, 0x114ce09e, 0xa2ed03e3, 0x1f7c190d, 0x1335fdba, - 0x23ec43ed, 0x5cb71fa3, 0x93ef577b, 0xa50eb0b9, 0xae683457, 0x1cefa3b0, - 0x484ce1fa, 0xddeafda7, 0xf50affd5, 0x1a657da6, 0xb06ff987, 0x10e819be, - 0x9d80f5f1, 0x2fdaf001, 0xa3a0b4f6, 0xd992b1a4, 0xfa55df71, 0xf3f723d9, - 0x49df9d0b, 0x645735f2, 0x820e493b, 0x2f401e65, 0x7e896900, 0x56731978, - 0x68dd90b6, 0x5907cccd, 0xf6bd6e8d, 0xfe5fb425, 0xefd0cf49, 0xd242af38, - 0xe7f8c095, 0x65ba4a55, 0x5917c7e8, 0xf311ea39, 0x3f94ec2b, 0xf3ced2bf, - 0x417f3c8d, 0x17f28385, 0xbe783a54, 0x3e61f209, 0x7bf85616, 0x42eed0bd, - 0x41a48c53, 0x93a5783f, 0x50355f97, 0x0f603bf9, 0x87c90264, 0xde49f987, - 0xe1a67cb7, 0xb84f12f1, 0x0d5c005f, 0x123d4591, 0x1a7ddfce, 0x8624167b, - 0x01999114, 0xe9c2b67e, 0xf3f942d7, 0x13809fcc, 0x6af546f9, 0xbfe43667, - 0x719a2c91, 0xc0386f7c, 0xabf9c66e, 0xe9de6915, 0x351bf007, 0xd8cf14c9, - 0x7dadfb21, 0x67e48c2b, 0xfc875d05, 0xa2456cac, 0xf2f0c7ac, 0x7ecdcb6d, - 0x0e40c7d4, 0xdff63ad2, 0x001e9227, 0x1cedf0f2, 0xca5e8bd4, 0x484987b4, - 0xb37e6ab7, 0xa12f2f54, 0x19992af6, 0x9559f2ed, 0x97c6bdbc, 0xea0d7e34, - 0x3379a655, 0xf71a0e91, 0xafda3b32, 0x2a9f56cf, 0x9b78458b, 0x87e5cedd, - 0x56342e5a, 0xe12e396f, 0x731a3c78, 0x7ee7d516, 0xe94f46ad, 0xc830ad2e, - 0xd2deb4cf, 0x2a18fca0, 0xd83dec6f, 0xa955424e, 0xb3d4137d, 0x8fd138c0, - 0xf3cf4dbd, 0x1488f77d, 0x8b54b067, 0x4182e65d, 0xa7914efe, 0x187c82d0, - 0xc545f245, 0x525fa35f, 0xf9923fc3, 0xc45df814, 0x3176f971, 0x5d95c93b, - 0x27207aea, 0x52af2835, 0x67f9d4da, 0x2fc504b2, 0xe0879aa5, 0xb87ab679, - 0xe71e0bdc, 0xc2bab8e0, 0x34b8d146, 0xd7285c7c, 0x74d73f20, 0x2b73f288, - 0xa124bb45, 0x853f6bbc, 0x92f51fe3, 0x9e00bac8, 0x13345d55, 0x66d669e9, - 0x6643b90d, 0x0b925eb3, 0xe2b71b37, 0x671e08df, 0x6436f8f0, 0x1cdf6968, - 0x1bd707d0, 0x7d6c1f49, 0xb8c1a4c4, 0xe15be822, 0x973857e8, 0x099e1a55, - 0x532230f3, 0x6bafd7d6, 0x34693cb9, 0xacea9d11, 0xfa04e58f, 0xa5d1841f, - 0xeebeb023, 0x72bcec7a, 0x68e91b8a, 0xac72c1dc, 0x93639658, 0x2a7c60fa, - 0x933873ff, 0xd6f7e602, 0x7c1518fe, 0x5544d5fb, 0x2e1012fd, 0x8d53e581, - 0x69f2aa79, 0xf82a71e6, 0x5514db0e, 0x54d219fd, 0xce677c15, 0xb3faaa9d, - 0xf055f3ed, 0x544bc55d, 0xee3ae7f5, 0x2fcf9555, 0xbe55487f, 0x0546b9d0, - 0x7bf8aa2f, 0xaec5fd55, 0x92f95546, 0xe555279a, 0x9293f6c1, 0x3f726696, - 0xe79b56cf, 0x8be483a4, 0x0e46704b, 0x14a967ad, 0x3dd703fb, 0x53eb822a, - 0xe51af5c1, 0xe04178f5, 0x48feb1fd, 0xe29df20d, 0x91ed637f, 0xd75cff2a, - 0x3ec6c9e4, 0xec72fa13, 0xb2dd23ef, 0xc51fdc13, 0xc53bfcfc, 0x04fdd57f, - 0x56f683d4, 0x715ba647, 0xabbf43bf, 0xf9fd0f4b, 0xb7bfe435, 0xb40bd736, - 0xe7ae6e0f, 0x7aab957e, 0xc00d8ae6, 0x7ef38583, 0x828e78e5, 0x70447327, - 0xcf1860ff, 0x95fb26df, 0x52bf439e, 0xb03f6336, 0x17787e28, 0xac509bb5, - 0x467fa1f7, 0x7a08f6a8, 0x662e5b94, 0x07284836, 0x97ff5397, 0x5823ec2b, - 0xd2567988, 0x398daf56, 0xbd5b7da0, 0xc61ead6f, 0x69399756, 0xbcd0b3cb, - 0x1fc8c3cd, 0x94e668f3, 0xe7816b2d, 0xa25321ff, 0xf9104975, 0xf75f3f3c, - 0xd03db9c6, 0xa5956b5f, 0x706ae508, 0xf3bb9279, 0x941bb1e2, 0xd5f2bf3f, - 0xd1bfee0f, 0x671d75f7, 0x87ca029a, 0x24568bf5, 0x1d004732, 0x7ed08648, - 0x74c81ff9, 0x27ac9ee5, 0x5a33d63f, 0xcfc893d7, 0xd7ff2617, 0xddf0bdc4, - 0x3dcae979, 0xfe43a7a8, 0xea1f300f, 0xcf9ebcd1, 0x29e744bc, 0xbf40f352, - 0x2c3bfd47, 0x941edd34, 0x95ad17db, 0x5a07e8fd, 0xd097a91d, 0x7e324fce, - 0x0eea7e46, 0x83abb71d, 0x07e7f7ed, 0xb276edec, 0xedcbf7bf, 0xad5396ec, - 0x8ccf7f99, 0xe45a263e, 0xf98840f8, 0x09b546d0, 0xab12af28, 0xf9024fc5, - 0x4f523ba2, 0x498b047e, 0x6a983bf6, 0xc5017e54, 0x791dd06f, 0x6f7480bf, - 0x7e415ae9, 0x6017f47a, 0x75e5077b, 0x2417f609, 0xe8b4ff19, 0xb51bd8e3, - 0x23f206cf, 0x04fd1084, 0x27f8a1e1, 0xa3f1fb82, 0xccfb813e, 0x27d270ca, - 0x397dc782, 0x6650e4b3, 0xff48f23c, 0x7e503bc9, 0x7ed1d29f, 0x84bd1c38, - 0x1fcce149, 0x266f7ed0, 0x7223efb7, 0x91f95462, 0x0fe644f6, 0x64b35ff4, - 0x321127f3, 0x48cc5b0c, 0x51c6df7d, 0xbcdbdfd8, 0xbb3a13bf, 0xd841f48d, - 0x7bfed0f6, 0xeee7e64f, 0xab69465c, 0x01b7976c, 0x9cfa631f, 0xd9fa4cd7, - 0x843fe036, 0x4a257bb7, 0x4a1cdefd, 0x54ed7a77, 0x4c5bcbbe, 0x83af1ef0, - 0x72debde0, 0x9d79f74a, 0xb792ff94, 0x7a9fe082, 0x7bb6945d, 0x15ff286b, - 0x03e087af, 0x5f8206de, 0x44507d45, 0xa533753f, 0xa85b786f, 0x46dbd3bc, - 0x3f5e9bf0, 0xbdde5da5, 0xdbc87f94, 0x6f11f04e, 0xbcc7c107, 0x78f7045d, - 0xdb7d287b, 0xeff94bdb, 0xdc134f78, 0xb1938f2b, 0xfa2f5ee6, 0x84a25c2b, - 0xaeb3ddfa, 0xd7ea336a, 0x331a65b6, 0x9736f38a, 0x39fa0566, 0x78f255b6, - 0x86956d9f, 0x87a040fc, 0xb39f51fa, 0xf8fa7b2d, 0x405f2a34, 0x49b15be5, - 0xabac4a30, 0x56cafeb8, 0x159ea9ea, 0x77c1020f, 0xfd2b6adb, 0xb25b805a, - 0xbadca9c3, 0xedbb244a, 0x3a278d79, 0x245deb9b, 0xae3aadbf, 0x1074283f, - 0x22e9fb21, 0x974a44b2, 0xa3fc7365, 0x23ef4232, 0xfc4a5919, 0xc707b9a4, - 0xf182ab67, 0xf555be21, 0x5a5f8c46, 0x49f183ef, 0x3aae3fa4, 0xc3247804, - 0xc07f1178, 0x6cc2fc87, 0xad97d719, 0xaf08eb55, 0x94f365e4, 0xda346778, - 0xfa9e6de9, 0xa56f84b9, 0x36cd7e48, 0xfbe8a1d7, 0xe7ca4e50, 0xe1f1ac7c, - 0x50fe7f4e, 0xf082327c, 0xddb8c6df, 0xd2fa0c90, 0x00e310fe, 0xc7a9478b, - 0x198f78fd, 0x26f1fa43, 0xb2627acb, 0x3d8ff9c0, 0x6dff122c, 0xc1f7a067, - 0x7e81cf77, 0x503943e7, 0xfa156fba, 0x72cd1eab, 0x3c02cc4d, 0x3f8d247e, - 0x531c0224, 0xaf4fdbce, 0x1ea0f717, 0xae7deb0d, 0x3e37f209, 0xb689d9b8, - 0x6966ec71, 0xdb5bb22d, 0xd01357b2, 0xa82c95ff, 0xcb4947d7, 0x3bb63c65, - 0xd5cf7b78, 0xb64fe48b, 0x76903aae, 0x865bf784, 0xfa8e26fd, 0x61ba187d, - 0x1a481632, 0x55c91914, 0x2fec45e2, 0xe5cda1ec, 0x66fc5fd8, 0x215fd287, - 0xe775f7f6, 0x65e3e469, 0xbc085756, 0x37279386, 0xb38b2393, 0x8e48e322, - 0x9424b124, 0xb8ebcf23, 0xe49df2dc, 0x861d24fa, 0x1fb43499, 0xc4ae7e25, - 0xe8e383d3, 0x243d3235, 0x61c74219, 0xfde80d57, 0xddb7aa3e, 0xe749c9b1, - 0x0b3e304b, 0x6c75ab45, 0xeaf3ae05, 0xdaf37092, 0xa4a0f410, 0x018e505b, - 0x468bdfdf, 0xb9b3b523, 0xe1a3b79c, 0x56cadced, 0x32625c11, 0x6bc842fb, - 0x6e5a7d25, 0x4e2c81e7, 0xbe0f49b7, 0xae18f1b4, 0x3a3adbef, 0xc69cf413, - 0x04ed11bf, 0xc92d09df, 0xfb6d44d7, 0x78013d8e, 0x79e3cb35, 0xb5cfef4e, - 0x7b40ff23, 0x915728f9, 0x7fc9f25f, 0xcc0566c1, 0x5addf2bb, 0xa3fd8fd9, - 0x29a21b6b, 0x2eb55cbe, 0x36a3f50c, 0xb07a2466, 0x85d13cea, 0x4560f401, - 0x1f410cba, 0x4af4b2fb, 0x3254d53c, 0x7c32e311, 0x728a9e5f, 0x583ef009, - 0xe1fb451d, 0xdeef65d4, 0x5be01639, 0xd47688ae, 0xe5ab9ecb, 0xfd2713e7, - 0x26e74351, 0xdb9c7cde, 0xb7fdb77d, 0x7bf41eb2, 0xb3e9c827, 0x7a41e768, - 0x77b3334b, 0x52dcbac1, 0xcdff226d, 0xb3c557ad, 0xb91a7681, 0x7da3c7a4, - 0x5335fdc1, 0x803ca1fa, 0xa67d26fe, 0xaa330fae, 0xa1233d45, 0xab6f9d4f, - 0x1a66703a, 0xcb56d3f4, 0xf6bb6e3f, 0x7d8471fe, 0x93f21af5, 0xf429f500, - 0x4dfe4093, 0xe78097d1, 0x191a3716, 0x32eb73c9, 0x41e519a3, 0xe49c25b7, - 0x1362db5f, 0x321ba1e9, 0x9ea18757, 0x8faaa86c, 0xdea474c6, 0xa77d03b7, - 0x7dffbbdd, 0xe4812d9e, 0x817f3f2d, 0xfa0c5984, 0xae7abdc0, 0xb6faf8e4, - 0x7944cb4c, 0xc3f2a1a9, 0x8b7dffbb, 0xac077d0f, 0x3490f085, 0x7e0f912c, - 0xe29bbe00, 0x2fdf02d4, 0x444e6740, 0xabae74f8, 0x4243e507, 0x8b1baf9c, - 0x56ce9ab6, 0xcae2f9d2, 0x5d33e238, 0x31e987b5, 0x18c8b2bf, 0x9f0ae7c8, - 0xfffcb5fc, 0xbbe71cb4, 0x59b81c99, 0xf7e337bb, 0xbe73a59f, 0x369ece19, - 0x154f230c, 0x9acf18fb, 0x4b6c8a63, 0x7d59eafb, 0xf6eafd48, 0xc567ce6c, - 0x643e7e7a, 0x72f4c54e, 0xfaf8c38a, 0x96c73c44, 0xa9f9cd93, 0x714912cd, - 0xd674b6e2, 0xdf037185, 0xf7f70d72, 0xdafff1c4, 0x3fc9d32a, 0xa2782ad4, - 0x3e78197d, 0xeb8695c2, 0x147306d7, 0xa6b7fd09, 0xfcceb972, 0xabc6331e, - 0x409a9da1, 0xf3dec1fc, 0x9198e9a9, 0x0bfe4c3e, 0xa49ef12d, 0xa3b7f00f, - 0x17fd1c5f, 0xdadddfc1, 0xbf6f86af, 0x984b86aa, 0x354f054e, 0x6669e1aa, - 0xe6c96c35, 0x361dfa7a, 0x490cfe75, 0x1ca7270d, 0x73f0d309, 0x7f01a6ed, - 0xbbf044b3, 0xa07e0199, 0x01769a0d, 0xafa525e7, 0xadb2fc96, 0x93dfdca9, - 0x73f6af5c, 0xb596b224, 0x6df90231, 0xfcb6f954, 0x73fa0255, 0x7cead56c, - 0x8c150798, 0xbff48acb, 0x9f95d724, 0x02e9718d, 0x4b3aee7e, 0xc5cde9eb, - 0x238b6875, 0xcf934a3e, 0x1fdd0d05, 0x95b8d0b7, 0x7c0f9076, 0xfa45e301, - 0xe62f840f, 0xc76726ba, 0x05f03e73, 0x7df997ee, 0xa503e43a, 0x41f8e1bf, - 0x3962c7e1, 0xab9ca26e, 0xa5b722b9, 0x97a9ab9c, 0x0475c7cf, 0x92b9c79d, - 0x81e7465c, 0x09aef4ae, 0xc877c50f, 0xce6cbe67, 0x946e9877, 0xdf20d7cf, - 0xef9cf4f9, 0xd5f0df30, 0xfd28672a, 0xafbcbcf0, 0xcc37b43c, 0xf8c071fc, - 0xab47b656, 0x82477760, 0xd3bcf039, 0x740ff843, 0x3a3337ba, 0x0f2b5a47, - 0xbf338be7, 0xe908d3db, 0x0b975a5b, 0xd66567d7, 0x338f3d59, 0xfe51ebf5, - 0xdff7979e, 0x38dd820d, 0xdb94c05a, 0xbb668da5, 0xccbdfd11, 0x57f2a19f, - 0xd5877e28, 0x31acd22b, 0x0188ff80, 0x4cd3823f, 0x33e34de7, 0x35118fc9, - 0x2b3771d5, 0xccf73c04, 0xa2046f98, 0x554e85dc, 0x658fc790, 0x97d0fd97, - 0x035e383c, 0xce02abfa, 0x0f441923, 0x3573b923, 0xe7014995, 0xff655bca, - 0x9b1f00c5, 0x7f609796, 0x7896cc3f, 0xd679863c, 0xda9fff72, 0x6ab8665f, - 0xd833b553, 0xdfaab27e, 0x722fd956, 0xfed5f6f3, 0xf4d5c337, 0x0ecfda61, - 0xb21cdf6a, 0xd576c1fd, 0x11afbc7e, 0x3e436f1f, 0xb5ffce18, 0x1ba7965f, - 0xf45e9e6c, 0xd818e97f, 0x06071495, 0x6a8898fa, 0xc369ff23, 0x5d5379f9, - 0xa60fdab2, 0x1f927e63, 0x90d647cf, 0x3e6048fc, 0x9859df8a, 0x47d7f287, - 0xbbf1e74d, 0x1371b960, 0x8798c179, 0xfd00dea1, 0x3f57f2a9, 0x46d3f7c2, - 0x3c42eec1, 0xfff3c783, 0x89abdd8a, 0xfa4bdf1c, 0x64b84a73, 0xdbde81b8, - 0xe32575ea, 0x3dc21bf7, 0xfeeb1835, 0x762ebb3c, 0x1b3de83d, 0x7c08c630, - 0x71bb3576, 0xfb84cfbe, 0xf58fa724, 0x27a21a71, 0x1d96ddcb, 0xb27a00da, - 0xa8695de8, 0xf2345af7, 0xa1fc2f39, 0x65bd6cbf, 0xfd10a6e7, 0x029bfa2b, - 0x8f002b5b, 0x956dba00, 0xfe81e6f5, 0xd0ee2496, 0x3163b406, 0x3fa90ab8, - 0xd2a35ce5, 0xeb37d35f, 0xf7ecab6f, 0xdeb3fa52, 0x559f1ea3, 0x59f1a1ef, - 0xe947fde5, 0x2f8e2b6f, 0xb4dd5f04, 0x1e8ed93f, 0x7aa96fe8, 0x8783567c, - 0x72d567c6, 0x7f40e1ff, 0xbfacdf4d, 0x931ef936, 0xe1d3e64d, 0x0e37fdce, - 0x1a76ab9c, 0x29b4ae51, 0x7f7940fe, 0xbfb414bb, 0x37f796ad, 0x714bfbe5, - 0xbddfe4e9, 0x18df33d4, 0xfdc35f6a, 0x247ac98c, 0x2648f593, 0xcf0891eb, - 0x3ea67a99, 0xf0b0e81e, 0x22f9b6c5, 0x1e73e3ec, 0x153e333a, 0xf62f19e0, - 0x5f6117cf, 0x99e2f39a, 0xc9f04903, 0xccbe2fcb, 0xe6787fcb, 0x9b94324a, - 0x2fcdef7c, 0x962a3803, 0xde0ac7ef, 0x8db7bf4a, 0xbba37ae2, 0xbfee73e1, - 0xfb8af904, 0x87aa6356, 0x42f17fa1, 0x32d47f72, 0xe94eefa8, 0x310f2cb7, - 0x6eea4a2f, 0x467e4f38, 0xff287914, 0x40bfe1e6, 0xee53cfb4, 0xefab9467, - 0x6d454467, 0x8c2ffd22, 0xef28cdf9, 0xba0e8c22, 0x28d6f84f, 0x642c1fbe, - 0x376e0af6, 0x39f25948, 0x31cfba0d, 0xd76e58bf, 0xb1cfcb7c, 0xb1c6a17c, - 0xdfd9ed1e, 0x478aaa4e, 0x173958f5, 0x7f783797, 0x1bf5d772, 0xbe0e1f9c, - 0x23e7393f, 0x23c2eb81, 0x3ba5bfb8, 0xb9f7e257, 0xa886fc02, 0x9f370ef7, - 0x7db8a3b5, 0x0e9f383f, 0x0e319f3e, 0xfee69f3e, 0xfeb0b5a8, 0xcb7ee8ee, - 0x5d9fc413, 0xc86be721, 0x5fcd06bc, 0xd8a628fd, 0xb7a45a79, 0x32b7cd9b, - 0xc1f9caaf, 0xa2ca4146, 0x794feafd, 0x3183fd2a, 0x8e2a14bb, 0xb819f483, - 0x4e6deabf, 0x5d19fe86, 0xcf073d9c, 0x45fe3795, 0xde5cf21b, 0xd63e796e, - 0xb9d38546, 0x3d28c6ce, 0x51dddbd9, 0x97fa1933, 0x9a74d345, 0x72a8b297, - 0x8da96f3a, 0x8f68ed65, 0xd7239f06, 0xce9bb88e, 0x68ad6901, 0x703a4041, - 0xa461d92e, 0xe8b989f8, 0xc5c8e786, 0x8f239d9b, 0x91cfc999, 0x7425e947, - 0xea45b459, 0x7f239e43, 0xf7df146c, 0x713c71bb, 0x278c3f88, 0xa21c706d, - 0x31d1c799, 0xf5f2023f, 0x7f231766, 0xc7de3cba, 0xea5075e4, 0x861ecc1b, - 0xb7ab40f2, 0x68a7a84b, 0x613ef9c3, 0x4e5869b0, 0xf7c8bf08, 0xfbe8e947, - 0x34cd724f, 0xd7231aaf, 0x5afce7cb, 0x7a4fe908, 0x4fe29475, 0xc3674d0a, - 0x0d3cc9d1, 0xf0a7473f, 0x9e9302e1, 0x302df7ce, 0x0fd14ad9, 0xef0800b2, - 0xfa8098b3, 0xf7e22db7, 0x0dbb4581, 0x5337e7e9, 0x6ff9ff6e, 0xb9f9ba18, - 0x43353e7c, 0x4ee3f747, 0x8f61cc09, 0xd57e7a19, 0x869e8ce9, 0x66bb9a6e, - 0xec87599d, 0xeff2e2f7, 0x867b6115, 0x167553e3, 0x779fec89, 0xa85ca146, - 0x0f1f5b4e, 0x42caa2f0, 0x94dfdd1d, 0x08ee44e3, 0xd19fc72e, 0xa28e4eba, - 0x51e7d178, 0x624748a5, 0xa3e22a7f, 0xea0289c4, 0x9e2a37bd, 0xd7e1cdea, - 0x18dea0c5, 0x7f67d394, 0x1eb462ef, 0x127a50b6, 0x302c4fda, 0x07cb236e, - 0xf302a3b4, 0x01627ed1, 0x2f2c27eb, 0x9085f6b6, 0x609a4a17, 0x0d5292db, - 0xd0909e7c, 0xff92a942, 0xee5b43ac, 0x57aeb10f, 0xc6fd75e5, 0x601b4c76, - 0x8ed0713b, 0x2ae5fb01, 0xd517dbce, 0x61e32ca7, 0x17657548, 0xe9b18ec9, - 0x88933e15, 0x1e6106bf, 0x45fb04af, 0xd5b0de75, 0xfba14beb, 0x6d38f2fe, - 0xa346d62b, 0x1c55031d, 0xbcdb9f48, 0x9965296d, 0xcec8e383, 0x8d13e991, - 0x17a889b6, 0x5c725ff3, 0x97f40ccb, 0x74349b24, 0x5326013e, 0x6e612f75, - 0x38b4f459, 0xccdd4534, 0x2ed0926e, 0x3f3d25ef, 0xf896bae1, 0x62f0e120, - 0xa4ab7186, 0xef0176b8, 0x23f40d03, 0x97ae6fdf, 0x5c57b9e3, 0x048e3465, - 0xcefec0eb, 0xf38d0ec8, 0x747945cd, 0x518e69e5, 0xe5d58fc2, 0xdcfc71c9, - 0xe1d5fdc2, 0x3ae8097e, 0x4057b6a9, 0x380c0138, 0x5c27c5f4, 0x426b4c6f, - 0x045af279, 0x6db58bf9, 0xf207cc99, 0x45745527, 0xfb3ce0e5, 0xc9a6ffa5, - 0xdf0b0790, 0x9c207cad, 0xa136b3f4, 0x25d90665, 0x285869f7, 0x1c98cf3f, - 0xc828c7ee, 0x609ffce1, 0x1ea94d6b, 0x44d3e987, 0xcf975f37, 0x1db39067, - 0x9f11d9f4, 0x1c58fa2d, 0x759a7bd4, 0x9b73e9a1, 0x7ec0efdc, 0x185fcf21, - 0x7f911973, 0x3b9382b5, 0xdbeef739, 0xce82cfb7, 0x55e74613, 0x8d7ac936, - 0x4e444ed2, 0xd846153b, 0x45cf0c1d, 0xdf07660a, 0x9b3ecc07, 0xf9abd60f, - 0x7b486d2b, 0x791cc1eb, 0xb26b491f, 0x4cb2fd61, 0x94fd0dbb, 0x1a55f7c1, - 0x70da26d3, 0x0c671a7d, 0x7031a9d0, 0xcb4ee85f, 0x53cf1f7e, 0x2c747a99, - 0x70591cf0, 0x2173c7aa, 0x972837b1, 0x1d3797cf, 0x9b42e7e2, 0x78bd454c, - 0x14c9a10e, 0xfec74457, 0xa99cfc4c, 0x3a64df52, 0x64def246, 0x1356f1e7, - 0xa2020fee, 0x3ba1e7c7, 0x83cd18ed, 0x0e5a6f52, 0x7b26ab97, 0x5bfbc317, - 0xd53f76e1, 0x3e9d130b, 0x161fe00d, 0x4ffee8c7, 0x55f39198, 0x318fac04, - 0x7e95ef80, 0xd1d1cb6f, 0x172535bc, 0x7e1096f5, 0x6704de22, 0x1b22b64d, - 0xdf38dbed, 0xb4636fd0, 0xaf9cdf42, 0x5be7971f, 0x3e51a769, 0x434f7aff, - 0x58b2fcce, 0xd73913f4, 0xa6bb60e4, 0x83b446e5, 0x6fe391b4, 0x6186ded8, - 0x285e6bdb, 0xf238f7b7, 0xc8b23685, 0x50e9ed8c, 0xc3a0845e, 0xfe76e467, - 0x30ede357, 0x97df74b3, 0x9f305a60, 0xa3de942d, 0xa38c46a4, 0xddfa1b8f, - 0xebbf9637, 0x90247ed4, 0xfc717bbf, 0x1ecf932b, 0xee1ca12b, 0xdb2eda3f, - 0x619d8a27, 0x2ededb91, 0x3ee87bf0, 0xef4edc21, 0x8776c836, 0x0f3d4c25, - 0xf941f783, 0xe0ae5c3a, 0xc72ee6e7, 0x046b8a31, 0x77e5f3f3, 0xb40e8a3e, - 0x73ef504f, 0x04bb7364, 0x1c4bb453, 0x610d9fb2, 0x9da01bf4, 0x80fdf0a2, - 0xfa42b75f, 0x3f005ba7, 0x0d6fc803, 0x7b242bb4, 0xc90dbe88, 0xe7c8697d, - 0x053bf2a9, 0x5cd7f643, 0x4785a72e, 0xfe434b3f, 0x4feb8b2e, 0xf982efc0, - 0xae4785fc, 0x5e78e026, 0xce703198, 0xab43e286, 0x7bf3a717, 0x1cffc7d9, - 0xfed10aed, 0x457feecd, 0x86b4dd9d, 0x5ce5c0f4, 0xdf5bfc0f, 0x8cbedb07, - 0x821d9deb, 0xcda4efda, 0x5fe77ae5, 0x7acc7de4, 0x2df7a455, 0x2eb965ce, - 0x0ab61f20, 0x7f28e5e6, 0xe7e11f53, 0x5e3f56e6, 0x2103d9ff, 0xed1841f8, - 0x804e73fa, 0xacdc5c3d, 0xa35a3f27, 0x8dc47d29, 0xafc31ce2, 0x71cb87b3, - 0x1e4b7d79, 0x24f3f235, 0x5b17ae2e, 0x39d3f75c, 0x23f3e095, 0x243bd5c3, - 0xbea53dcb, 0x7947db01, 0xfe479a62, 0x23684b80, 0x964dbfa0, 0x7678c17b, - 0xf3c864e2, 0x12b90463, 0x18456875, 0xed93abb6, 0x3f8aedb1, 0xe8c8a2a3, - 0xb75ef808, 0x1a58c8b8, 0x8c8d2f40, 0x6e0ddf9f, 0x01dcceff, 0xafa55a7d, - 0x459f70e8, 0xf89c50df, 0x433901a7, 0xcab8658a, 0x0ffa518e, 0x70163f3e, - 0xf38c2c5e, 0x5a67b729, 0xe818dcf1, 0x962b6bb7, 0x6df9c48f, 0x582f5d15, - 0x3ffa1e61, 0xe739d030, 0xecbe650f, 0xb872f993, 0x43b1f3f5, 0xf6318ca0, - 0x97823b04, 0xc64e80d6, 0x68fe408f, 0xfb94d4cc, 0x5cb38c43, 0xfd08671e, - 0xafdcd6fa, 0xe6975fa7, 0x51afd086, 0xc504767f, 0xd461021f, 0xf4211d9b, - 0xec8213eb, 0xedcf900f, 0x1d49d09c, 0x270f307d, 0x6f611d6e, 0x919ee894, - 0xf6045ec3, 0x32678bc3, 0x239f6f51, 0x23c7bc0c, 0x608c31db, 0x221623b0, - 0x6799735e, 0xc50203df, 0x48ee5a51, 0x5c04eea3, 0xa7ad9b8f, 0x3711fb24, - 0xdc613ac2, 0xb2daf5a1, 0x0ce2a119, 0x274038ff, 0xef02ba28, 0x042ac007, - 0xc48695c4, 0x63e282cb, 0x38194e18, 0x5a1dabff, 0x7562aeff, 0x35e36afc, - 0xac30bfee, 0x0427fe60, 0x2eaa1f3c, 0x0bae5f9f, 0xe2a9cf8e, 0xba9d0b5a, - 0x887c7c60, 0x6f8cb26f, 0x2907b6ca, 0x452d3e0e, 0x64acfde4, 0xc707cf64, - 0xbd850cbd, 0xc3ea2d0e, 0xf7f48c15, 0x9e363f60, 0x5eff2517, 0x09cf6305, - 0x7d5ade74, 0x59e9e4df, 0x1cfbf8e7, 0x8fd8e52d, 0x50c3532d, 0xafbe0e3f, - 0xf09bc4a0, 0x7de04c98, 0x22dde569, 0xe10d62cb, 0x53b77cc7, 0x8797e2b9, - 0x4b12a6fa, 0x55eeb9c0, 0xdd3ea06c, 0x1e85f2a3, 0x59d6d6f7, 0x1c4fef14, - 0x82ec29ef, 0xa33b24a2, 0x66aa4879, 0x3cc00764, 0x86fae2a8, 0xce345d94, - 0xc58c354b, 0xaaa038f2, 0x7076013c, 0xbf184fa4, 0xe30fce2a, 0x76c1c154, - 0x4deccde7, 0x0de64a43, 0xfccdf9e5, 0x5e39068d, 0x646e46f8, 0x633be91c, - 0x77d418d8, 0xa69f8b2c, 0xeb04b8f5, 0x34597e81, 0x03c54284, 0x68fb4337, - 0x5f90ba07, 0xc4dfd1e2, 0x30caef54, 0xc9f74887, 0xb38e6284, 0xf1e4eb10, - 0xfc467ce1, 0x9507086d, 0x9859f80b, 0xbce0706c, 0xc3000c1b, 0x333d0590, - 0x56be4026, 0x15af37f6, 0x33308898, 0x4fdc8ddb, 0xe36bbca8, 0x866d77a7, - 0xff7407eb, 0xcfec30be, 0xfa53bfc7, 0xdb8ef219, 0xfb27be0d, 0x7dfc1ccd, - 0x951df919, 0xff9b87fe, 0xfb6ddee1, 0x2777d4c3, 0x3267bf70, 0x20e56bd1, - 0x4cbc12bd, 0x1efc47a6, 0x4abdc2e5, 0x0c77adb1, 0xfb3c37de, 0xfd1d8470, - 0xf0e303e0, 0xefe5a9dd, 0xed75fdd1, 0x9361e00d, 0x8c0fbe48, 0xafef6e4b, - 0x02fd171d, 0xbc06dae4, 0x4fe78434, 0x279d192a, 0xcf4ab8b0, 0x000e7489, - 0x1392a0c6, 0x4013ef01, 0xf10e1b7b, 0xf15baf73, 0xb0710b9d, 0xd02bd45f, - 0x4255b06e, 0x483b087e, 0xbf19ab49, 0xd5e0ac1f, 0x1a3d07a8, 0xf5c352e9, - 0x3ea6d9e8, 0xe935cf11, 0xe445fae2, 0x2e68e71f, 0x37e807c7, 0x0bf9d19e, - 0xce7c926d, 0xdfc4a471, 0xfbe4cb4d, 0x84cfd29b, 0xfe591ad1, 0x47fbd2f7, - 0xd54e23b3, 0xf2c6764b, 0x442fc5f6, 0x11ecfcff, 0x00d3eaa7, 0xe167d82e, - 0x2ba9d270, 0xecc66669, 0xd10bacfb, 0xef3b3f9f, 0x807495d4, 0x78d9f68b, - 0x464614f9, 0x097df8ce, 0x319fd10b, 0xd559b461, 0xd7385bfe, 0xd53cdff1, - 0xcf21341a, 0x5a36df63, 0xe8c94f39, 0xf3b3ad3e, 0x2e31a797, 0x47f654e9, - 0xdf482e87, 0xde0b2281, 0x717f9323, 0x9d0f1451, 0x9dd9d329, 0x1452eef8, - 0x68bb2dfa, 0xfa0d477e, 0x6bfe9fe9, 0x4382f4fc, 0xccca9779, 0x1bff812a, - 0x2c2b981b, 0x99ee8023, 0x9f9d7343, 0x81b8a603, 0xffd28f82, 0x6960bc10, - 0xbc4098c5, 0x0a3b51b6, 0x0d0a175e, 0xc70587a4, 0xfd082e87, 0x549cf1db, - 0x2fd6cfc4, 0x10ba75c2, 0x002a9fd9, 0x9eb79e1c, 0x7c42edd6, 0x1ec176ff, - 0x3af8eb00, 0xa22bef56, 0xd6a3fc75, 0x027a3d51, 0xdfc5dbbe, 0xe396686f, - 0xbbc64f50, 0x019f687c, 0x32b9d1dd, 0xfc9e8a5f, 0x05e36548, 0xb03fa047, - 0xcbf7346e, 0x69d3925c, 0x49cf1686, 0x01f74ba0, 0xfa85ad81, 0xf5976bee, - 0xeecc9fa8, 0x3d47a33c, 0x19c0eeba, 0xad4bde3d, 0xa9da1843, 0x8477a6db, - 0x32feffd2, 0x97f2ab5a, 0xd1d77629, 0xe8f5ec94, 0x16abab77, 0xeade1ee8, - 0x6e1fb9d7, 0x251c32f5, 0xb2df7763, 0x55b8fc9f, 0x98f5eece, 0x477d652e, - 0xc588ddf1, 0xdceaad2e, 0x089a92c0, 0xcabe3c55, 0x9782ab13, 0xc0eac0b6, - 0x21b4bb3e, 0xc31df549, 0xef82cf5d, 0xd0fe0e28, 0xd790affe, 0x736db171, - 0x16bbfa2f, 0xcc7ad4bb, 0x62b5ceec, 0x11ede20c, 0xfece1aec, 0x84b77e12, - 0x00d2108f, 0x7de60abd, 0xa3d7075a, 0x648c2aea, 0x0c22549f, 0xab595af3, - 0x7393e3f5, 0x54f45347, 0xa810eeee, 0xbb972ddc, 0x576e046b, 0xa975f2cb, - 0x8392e38c, 0x75d1a727, 0x37a39f52, 0xa5df0033, 0x88e7e515, 0x437d651e, - 0xc4855719, 0x290d8df5, 0xddb0e9ef, 0x5817dfa5, 0x4b8d1a6c, 0xa92d47a5, - 0x1e55c351, 0xd59e905d, 0xbdf943a7, 0xff9d41b4, 0xbef2d1f3, 0x90f2c79e, - 0x2d18de9f, 0x07189f88, 0xbca53fe1, 0x81ef0277, 0x0f3ad25d, 0xead67d22, - 0xdf700abb, 0x1175a4bb, 0x7e4394ac, 0xb8afdf1d, 0xce01a2be, 0x751befc3, - 0xa7de330e, 0x8814adf5, 0x00b0976e, 0xb06d27bd, 0xa1dac13e, 0x7722bf70, - 0xe4f59cc3, 0x98283d0f, 0x13286f51, 0x83de221d, 0x8fc61c6f, 0x83e6517e, - 0x1f2fac13, 0x2246caf1, 0x9eca7585, 0x99f6823f, 0xf996b7ec, 0x3d948e30, - 0xc4bf204e, 0x4371809d, 0xc922a611, 0x37b03991, 0xad9a4184, 0xf920af6d, - 0xe66f563e, 0x58da62ef, 0xfc70bca0, 0xbe701333, 0x0bb27510, 0xfde87b93, - 0x9b6d39bd, 0xcc5ca22f, 0x3d1470cc, 0x193df805, 0xf27ffbc6, 0x16bfc175, - 0x3fcba9da, 0x0ad3f246, 0xd6fd81e4, 0xda3964d9, 0x5acff6a1, 0xc121ae51, - 0x7ea7cacc, 0x32f89413, 0xc3ed15d0, 0x9fa4a55d, 0x9f7ee558, 0xddb8942d, - 0x2e7ca0fc, 0xe2d6f98d, 0xd1befaf9, 0xf495f28c, 0xcaabfb1b, 0x5e283104, - 0xe61a3750, 0x4fada579, 0x5be9de75, 0xe901bf6c, 0x187db82c, 0x395e2abe, - 0x8a2d7b4d, 0xcc1d77ee, 0xfee8deb0, 0x3ea8d694, 0x8733a4b7, 0x53bbdd07, - 0xf6d99fcb, 0x777ba0a4, 0xeef74119, 0xddee82f2, 0x2df9efa9, 0xba094e74, - 0xe7bea777, 0x54cdb067, 0xe6930fd5, 0x9c88e0a9, 0x23f555bb, 0xe7d5cbed, - 0xbcff8eae, 0x77c74842, 0x2e7d7d06, 0xe0668798, 0xc198e28d, 0x0a2f247d, - 0x3e1a432a, 0x6984cc2e, 0x0ba1a173, 0x9139a4e9, 0xe386e7db, 0xa0badb0f, - 0x9788e31d, 0xfc6fe88c, 0x452fe089, 0x9f28c4fb, 0x18fd1953, 0xaf33ed53, - 0x52be7015, 0x5cf2dbd2, 0x7d61f3b3, 0x494af7f2, 0xdee01dfc, 0x463eb8d1, - 0xf9036c7c, 0xaf7e55e6, 0x476cac78, 0x5f3ced28, 0x0f353258, 0xcc7fcfbe, - 0xece28331, 0xf07efc1d, 0xa78f3d4e, 0xe7e55ef8, 0xfa3bf35b, 0xfe008e34, - 0xf5c7993e, 0xa59c6790, 0xeba91f14, 0xf9165d84, 0x1eaceda9, 0x75d465ef, - 0x7ee14776, 0xab3ce056, 0x60c9bf47, 0x89cfbcbe, 0xaf68e1fd, 0x743dacff, - 0x9e6d6d3c, 0x98e3f89e, 0x1eabd72c, 0x91bb72d6, 0xb9e16639, 0x575e4571, - 0xabe3e7ed, 0xe7e7a85a, 0x1d1a3160, 0x9c836e42, 0xc396ab3e, 0x707ef50e, - 0xca3d7f8b, 0xaadf900e, 0x4c174b7a, 0x12b7bb27, 0x31f236e4, 0x797573c8, - 0x17c91372, 0x7caae790, 0x3c80de77, 0xdf0ebfcf, 0x426a769d, 0x8170f38e, - 0xda78f348, 0xffe69535, 0xf4479819, 0x64333da7, 0xde7cf8de, 0xc65ebe6c, - 0xb7580fb5, 0x2ebf7ae0, 0xf2f6ebe0, 0x7dfaf230, 0x0a775d79, 0x4c2845bd, - 0xa270cedd, 0x634625db, 0x387b9e09, 0x1365f296, 0x7eaae1c6, 0xfd3dd02e, - 0x6e3eeb7f, 0xbf5ffd41, 0xfd05a8ff, 0xa3f6ee61, 0x594db016, 0x8b5a4ead, - 0x85d03c7a, 0xba9ef51d, 0x7fc22e8e, 0x6eb8fb65, 0x21d95fcc, 0xee3dfbd0, - 0xd3a71703, 0x135f5938, 0x0e770bc6, 0xf28fd783, 0x37befeb8, 0x307ee24f, - 0xfb89f417, 0xdf8301fd, 0x801d202f, 0x5ebc425c, 0x35e5f017, 0xb1a373b6, - 0xf51e9422, 0x1f7cf26f, 0xe867a8d9, 0xef85afaf, 0x52c71c71, 0x488de98e, - 0xb205fb47, 0x27edddb5, 0xfb604617, 0xfa863af5, 0x17df8285, 0xe21fbd29, - 0xd6a83ff8, 0x3580a7a1, 0xbe696b56, 0x52d7a83f, 0x74fbda3b, 0xc15e2f04, - 0xae1c55cf, 0x0929a8fe, 0x56a0fdda, 0x530c7ba0, 0x31f3fbef, 0xe0af1784, - 0x3d305afa, 0x4c1af42b, 0x3bf4c19f, 0xbe6b4e84, 0xc91e9d19, 0xe4d5ef93, - 0xe7dc02b1, 0x59a7dd61, 0xe11e7e91, 0xae2be3f7, 0x7fa1d61d, 0x6cc9bd33, - 0x31e0027f, 0x0b7aff5a, 0xbcc389ca, 0x8776b0bc, 0x748de5c0, 0x5261f237, - 0xbda19eb3, 0x971e7efb, 0x7ae3ef4b, 0xfad0e3c5, 0x31af8c05, 0xe51d37b1, - 0x4f1c9a52, 0x2ac7457a, 0x905c53f6, 0xaf319bcb, 0x96ef54d9, 0xbd71e537, - 0x40839143, 0xe4fdaee6, 0xc44f6d97, 0xcb2f147b, 0xe55341e7, 0xfa32b2f6, - 0xf485cfa7, 0x672f4caa, 0xf8143c64, 0x6cff4cb2, 0x1f68cfdb, 0x59c72d9f, - 0xd1743666, 0x833ccc79, 0x879453eb, 0xabdf52b3, 0x39ae7dc5, 0x3a7cedfd, - 0x25378d67, 0xc9fbe226, 0xd27877fc, 0x60d6dba7, 0x9c372fdc, 0xe0ec31d6, - 0x381e7453, 0x35bc6b2c, 0x49439c54, 0x7a2557dd, 0x6aeeb08f, 0x3c0aa53a, - 0x7d39d0f7, 0x1701d91f, 0x5c9f13a7, 0x2ddea9b5, 0x7bc654fc, 0x5d3ef28c, - 0x80f3f727, 0x8b8b169c, 0xf329eb06, 0x1c659e80, 0x2ed6586f, 0xab35af5a, - 0x75a92158, 0xcefe29ec, 0x0149ed66, 0xa458bddf, 0x304ce873, 0x608defdf, - 0xfc8b1f25, 0x3657241d, 0x748c4dc6, 0xd784fb2f, 0xd7af704c, 0xaf29f046, - 0x61ade944, 0x687c88ce, 0x4f11e167, 0xe1dbce16, 0xde275694, 0x8ef0bc57, - 0x336ba64e, 0xd32e2fbf, 0x2d4ee5da, 0xeb9c6233, 0xc2e3e800, 0x5cf7fe20, - 0xddfba44d, 0xa0fec3bf, 0xbf0d959f, 0xaf677921, 0xed1d38b9, 0x33dac2a2, - 0x1bbb084d, 0xf51d3cfe, 0xff610f89, 0xf41ebd20, 0x72809b7b, 0xd3bd24e4, - 0x8635795d, 0xd35979da, 0xcbf91d3f, 0xf740a6f7, 0xb8ec3e6f, 0xfdf2b7a8, - 0x7873dc89, 0xf2fd1c2f, 0xb9a3f2b3, 0xd42ce91c, 0x243afad0, 0xddeb3bd5, - 0x0a2bffa3, 0x20d8c3d7, 0x7e0a7afd, 0xc865a3df, 0xfb4a9bbf, 0xe421cca3, - 0xdff469ef, 0xb071f365, 0x15e5a1ec, 0x9e165f7a, 0xe990ac93, 0x3cbcb838, - 0xa13fc07f, 0xebefca73, 0xa1fe0108, 0x3fdfc62a, 0x2ba7bb05, 0xaab8f81c, - 0x67f92a73, 0x0dc23caa, 0xd1c333fd, 0xeb4dd7e1, 0x28cff718, 0x818dda30, - 0x1bb44d7e, 0x1f7faa99, 0x252b077f, 0x74f786f3, 0x14897ddc, 0x666bafcf, - 0x795aef14, 0xe7a53475, 0x2120df5f, 0xfbc318ff, 0x6b7ee95b, 0x8cec86b6, - 0xfeb53e95, 0xcb80a533, 0x7c052985, 0x60f95cde, 0x01b0e52f, 0xa2ec097b, - 0x5db9f37b, 0xa9887514, 0x7ce0a5ec, 0xf28c97b2, 0x13101d3d, 0xe04257ae, - 0x6941477d, 0xca977e0d, 0xd9ce885a, 0x72fefc3b, 0xe4d738f0, 0xf8553e73, - 0x35f2317a, 0xe7076fd2, 0xe776e0eb, 0x41ac9415, 0x4c38da3e, 0xe65cab7c, - 0x8c6d95fb, 0x16ddcbe6, 0x05f4f343, 0x0296736b, 0x78017e5d, 0x0bd23de0, - 0x3444674e, 0xe5c17f7c, 0x3df3c08c, 0x6ba81c8a, 0x36efa70b, 0xc58bce66, - 0x48cda373, 0xf9ded0f7, 0x9c46a98e, 0x38da7be7, 0x7dfd29ff, 0x1638b5d8, - 0xae8269f9, 0xf2876f5f, 0x5133cee4, 0x784df7a8, 0xf22c7e7d, 0xfe7870e1, - 0xcf1918fd, 0x1e12c486, 0x70bd8797, 0x004f6ca2, 0xba27ee7e, 0x87fa9de8, - 0x6fd1181a, 0x56ffabf7, 0xbe7c7c87, 0xfb8cc233, 0x230717e6, 0x0bcabde8, - 0x3de81a6f, 0x7df95a9a, 0x7d742fd5, 0x7cbf4873, 0x22f74b5d, 0x47fe6fdd, - 0xfba3f22b, 0x3b9d0355, 0xc373a87c, 0x6af7dc45, 0xc39c673b, 0x5f6b5677, - 0xc3f2dbfa, 0xd25486ca, 0x3ff8148b, 0xbe2746bc, 0xe45e7bf3, 0x8ea1e272, - 0xf77d217f, 0x0b976ba1, 0x17ca7cf0, 0x44c7ff07, 0xb7ee6b94, 0x79444f2e, - 0xe5c5fee6, 0x7eee5889, 0x4a13c22d, 0xc05eb95f, 0x7eca3efd, 0xa8aef699, - 0x90ad0ff2, 0x5d6d23e9, 0x3d07bd0b, 0x7b02e4e1, 0x130fbbe0, 0xac4e34b2, - 0x65b7e13f, 0x7c05f7b1, 0xa457aeb7, 0x93f8e338, 0x01d51165, 0x814f7974, - 0x7e2ff14e, 0x930ebf23, 0xf019c7df, 0x77f2f4e3, 0x8af6367f, 0x1aa37dfc, - 0x83a1ee81, 0x5ee432fe, 0x8affad1a, 0x88df7a58, 0xc73bce89, 0x8b38478c, - 0x3e6205de, 0x00ccd1e3, 0xaf71693d, 0x7400cba6, 0xe869d154, 0x57befd22, - 0xacb0433c, 0xf173dd3f, 0x2134c8d3, 0xe7267f84, 0xe39434d4, 0xf81a7ec1, - 0x8ade2245, 0x71e955be, 0xc1fe20a5, 0x15a59bfe, 0x287f9077, 0xd6937fd8, - 0x8f666a2b, 0xe9dff7c7, 0xf78c2f3a, 0x8bf22369, 0xfae287a2, 0xffc1081d, - 0x3970c66b, 0xbad5f0a6, 0x5dff1e5e, 0xcc6a5bd7, 0xe656b484, 0x9db003ab, - 0x75fda0fa, 0xa377f39d, 0xb5dd611f, 0x60631145, 0x3bbdd6be, 0xfc813d8f, - 0x66352e6f, 0xeed777e1, 0x1fcc2e30, 0xfee097a4, 0xf2e18ca6, 0x184f4072, - 0x97cbdf66, 0xed5bfaf1, 0xe463397f, 0x87ff6cf3, 0x87607fef, 0xedc31d8f, - 0x4fdc25f0, 0xe0f0edc2, 0xc791437d, 0x792ebb4a, 0x63ca879d, 0xc04877fe, - 0xec79265e, 0xbd51231a, 0xb1b9cee4, 0xbbbf4764, 0x0d325620, 0xb4433f6d, - 0x87f2626b, 0x71e8afb6, 0xa8e39f6e, 0x871ced11, 0x1749fb96, 0x99bef408, - 0x9db9f7a2, 0xeee3e902, 0xeb1f9d4a, 0x2ef57829, 0x85d57ee0, 0x4c3f9d0e, - 0x150fd418, 0xdca071fd, 0xa2b9502e, 0x637a2a4f, 0x71fb93af, 0xe5e78c17, - 0x16b986b7, 0xd87d7ce1, 0x13f94615, 0xc67cf126, 0x0093479c, 0x813df45e, - 0xfacbff11, 0xc1a742a4, 0xcea5e6fa, 0xd7be1b8c, 0x4fa64db3, 0x8352cf85, - 0xbfd943f8, 0xdd39f39a, 0x1dfee1d7, 0x7ff7fb8b, 0xe0f2f4aa, 0x7eff6176, - 0x466ff108, 0x1fbe121d, 0x19d15bff, 0x4aff3eca, 0x5efe0bd6, 0x23debf59, - 0x72af8825, 0x7db8764e, 0x6fd64eb5, 0xce6f2b86, 0xbcfc7aff, 0xdfdf1e47, - 0x8e779f8a, 0x9f43bff9, 0xf50bd01d, 0x4779c7a1, 0xc64fc941, 0x6b86bcc0, - 0x739e743d, 0x1ecdf7b8, 0xb055f595, 0x7c745573, 0x41af4534, 0xc35dc8bb, - 0xd1cd03fd, 0x7ec9afd2, 0xf7a5ae39, 0xef921e57, 0xd5783e73, 0xea2d694c, - 0xd92e90c9, 0xd9de927b, 0xc6a3525d, 0xb77d19bf, 0x34aafdf8, 0xb157eb8a, - 0x552bf232, 0xf19b4675, 0x7c737fbc, 0x2be431fb, 0xb4ad6edf, 0xc6feb03b, - 0x237d72d1, 0x44d5b7f7, 0x618fdfd3, 0x95407a41, 0x57df5827, 0x645305eb, - 0xfa70d13f, 0xc3ba2fc1, 0xd1e95cb8, 0x39d79f12, 0xd055dff9, 0xe0b97277, - 0xbf23086e, 0x886bda09, 0x820d67d7, 0x5f3ddf1f, 0x4cfbd729, 0x13ff25ec, - 0xcaa0d3c5, 0x2ca7ceb9, 0xd4dfb20e, 0xbb95a3f1, 0x33724b7e, 0x73148e38, - 0x0d0b8e40, 0xd2268dc4, 0x60959079, 0xbc9fe24f, 0x5dd24b72, 0x1f80ff38, - 0x71dc93f3, 0x9730fca8, 0xfb223e7a, 0x3cebc973, 0x7e2433fe, 0xc7933cd4, - 0x95ddf08f, 0xa5c87e10, 0xc51d8f23, 0xb374a3bf, 0xc75d51b8, 0x3247ba49, - 0xd208ff44, 0x518dae3b, 0x8a4719fb, 0xb23b8fdc, 0x7fa33053, 0x8f3ca46a, - 0x9c31b77f, 0x7fe9eaf4, 0x79458ea8, 0xf9d3aca0, 0xcf5e7cb9, 0x04a5707f, - 0x07f89bbf, 0xe3061cd1, 0xf507c5fa, 0xb0e249bf, 0xbbf09464, 0x63b408fa, - 0x7561ffce, 0x2febce04, 0x2fbfc520, 0x3169daf1, 0x2bd23fa4, 0x0fd82dcb, - 0xbfc80ba3, 0x45a5fb2c, 0x07230fd8, 0xdfc139fd, 0x6bbf976d, 0xfc853306, - 0xf8f3af98, 0x6b82737e, 0xa6cfc126, 0xa61efe33, 0xffcefc83, 0xfe8d7402, - 0x2c183ca2, 0x1a7f9fc6, 0xbc61d6ce, 0xf5de39a8, 0xb3d1f136, 0x08f9091a, - 0x9338a7be, 0xfb44bf6f, 0xc6194e23, 0xfcf40a73, 0x0cea465d, 0xbcb46bd6, - 0xc760098e, 0xb0093c62, 0xe6f18059, 0x53ae393c, 0x6c44ce10, 0x6b9d49ff, - 0xf997be13, 0x5f68b764, 0x8f604c4b, 0x83bf77c5, 0x83824be3, 0x3895c5c7, - 0x1f1f1293, 0x6024ce2e, 0xee9c053f, 0x8715b9f8, 0x25737180, 0xe7bec49e, - 0x635720a4, 0xf7ce87b1, 0x48c8533f, 0x718b7fae, 0x21f9259e, 0xc83548e2, - 0xd5cf2463, 0x394dc571, 0xfe9d10af, 0x3dc4f1b5, 0x1cb7d863, 0x13f3e2ff, - 0xe8f8f78c, 0xb7b2164b, 0x51effabe, 0x5e76cfb4, 0x42f0fda6, 0x8fbe41bf, - 0xecfdc7d0, 0x2ff23a9d, 0x2dbb005c, 0x3d9f603e, 0x3ddbcf9a, 0xe89539d4, - 0x596f40ff, 0x2f3fd604, 0x777c6fe7, 0x48d9fcc1, 0xbd22bd97, 0xe3e78b07, - 0xd03b0ed0, 0xbd404e2b, 0x975c5be5, 0xb1098fef, 0xd0f0c62e, 0xcbe44cef, - 0xc05f947c, 0x07ea63e9, 0xd772fedc, 0x598a38f3, 0x72ee0b96, 0x63c1c93d, - 0xf1411629, 0xc5435b9f, 0xa7ef5e59, 0x856aa37d, 0xbe1cf740, 0xa3a59c71, - 0x82b7de5b, 0xd3e5d3fc, 0xe70e6e49, 0x9b880eb7, 0x15b7caab, 0x23879c0c, - 0x815475ff, 0xe31dc699, 0xb3c12c29, 0xbff8ca87, 0x73b875c5, 0xfb3a086c, - 0x695fdb16, 0x9fdb6eff, 0xb6ddf792, 0x6e3be6bf, 0x77de6d7f, 0xf1dee71b, - 0xf57fe31d, 0xccff6e3b, 0xaf3f3c77, 0x73ffffe5, 0x70700300, 0x5cf83f9c, - 0xdfbc7040, 0x1f3efc70, 0x36106d96, 0x6a4177f7, 0x42b57a8c, 0x462d5100, - 0x0877a2ef, 0x71e24d66, 0x46658db0, 0xf0610eff, 0x5f32807c, 0x1db90b4b, - 0xe8bfce61, 0x4e79858b, 0xc596f475, 0x126c9fa2, 0x82fd877f, 0x132acefc, - 0x18cef4cd, 0xfbc04cd4, 0xa161cdf1, 0x7261aae3, 0x23edc37b, 0xdc9617cf, - 0xfe9e3631, 0xfbc8436c, 0xfec82f1d, 0x23077347, 0xa51324bf, 0xafd47984, - 0xd0fa8094, 0x3f3c2388, 0x76398baa, 0xda525e10, 0xa507b23c, 0x8b6fc434, - 0x998def1c, 0xfe869d99, 0x0bd018e8, 0x14f81e31, 0x8e2905c6, 0x4a7aa665, - 0xe58c1f7f, 0x31d16dfd, 0xe55bee81, 0xac4cf3f2, 0x9e2aa0f9, 0xebae8ef7, - 0xc50265e3, 0xfe2396f3, 0xe574d2bf, 0x89934cef, 0xff37e618, 0x8ce29980, - 0x48bd2627, 0x8956777f, 0xf331adef, 0x6ed1872a, 0x1cd63c06, 0xbbf4471c, - 0xf7a4d0e4, 0x7733e9f1, 0x750f68a6, 0x17f1514f, 0x1dfd969c, 0x8940bf8a, - 0xf65efd6b, 0xfe887c93, 0x221fba17, 0xab1dea51, 0x27f7b6f9, 0xfc10d8ef, - 0xfee045bf, 0xb8afdf21, 0xde9c687f, 0x6e78119e, 0xaf3cb372, 0xdc78bacb, - 0xecf7f142, 0xee33c793, 0x01976d11, 0x4d71d2f6, 0xcfb8f463, 0x094a6b8f, - 0xe1c0b4c7, 0xf07de0d7, 0x35fbd5c5, 0xa285faca, 0xb2b1d6a3, 0x9fa7a31f, - 0x12ff7ae2, 0x60ffe714, 0x30bf3f2c, 0xf1e390af, 0x0824d801, 0x1b12c9af, - 0x711c7d51, 0x2a1b598b, 0x7605549e, 0xacb9e231, 0xccade399, 0x34975577, - 0x7339fb15, 0xd309bfb4, 0xa9b49aa2, 0xbdaf6fe4, 0x9bfa84d8, 0x63e5dafb, - 0x4cbf93b7, 0x713da12f, 0xefda9f4f, 0xa5a30ab6, 0xfd2784f1, 0x0cdf5a9d, - 0x71e3ec91, 0x9fa24433, 0xb230aa98, 0x4c74635f, 0x2e78426b, 0xca8a8bd7, - 0xcc22a6e3, 0x3e934416, 0x4523d458, 0xe83f97df, 0x51998b07, 0x74f38f1f, - 0xe2aaf8b3, 0xcc35bb4f, 0xe7ae1af1, 0x5d5f1b5f, 0x74bbcef9, 0x971954ae, - 0x9c4a2f32, 0xaaf8b874, 0x5dc1ce72, 0x2e75457e, 0x4ff62dc3, 0xb8e3ff47, - 0xf2f46783, 0xfe334b39, 0xfe25611d, 0x8bf5ee3a, 0xe2557714, 0x45cf6eac, - 0x3be1abd2, 0x0e3f7e3d, 0x06213f96, 0xf1e217df, 0x9ef157d7, 0xffef1e94, - 0xd4bee999, 0xc5fdf21b, 0xe63f184e, 0xa1cde9bf, 0xa76bcbb4, 0x98b790f4, - 0x45e77752, 0x387ed78a, 0x53ef1d56, 0xb49779e2, 0xd56333ce, 0x0e0923e7, - 0xc369f78e, 0xddc6bfb9, 0x97bfa3a3, 0x48c77ee1, 0x73a4bbf2, 0xfaebdd19, - 0x246ba4f2, 0xf1875de2, 0x38ba00b6, 0xe187b0ef, 0x9de7613b, 0xb38c30f6, - 0xa73eeb8d, 0x752ff3c7, 0xfd1eaf62, 0x12718061, 0x1f744d1e, 0xf7cfc8b8, - 0xdfd09676, 0x5c69bae3, 0x136fe3ac, 0xe59ffb17, 0x00210141, 0x00002101, - 0x00088b1f, 0x00000000, 0x17b5ff00, 0x67534c5d, 0xb7b77cf4, 0x0bdf96e5, - 0x72223f2a, 0xa29862c1, 0xa740c2dc, 0xac741631, 0x4a8a5c13, 0x66b50102, - 0x2d09922e, 0xcbc2ccd9, 0x01893ad2, 0xb8b2c3dd, 0x26a9f364, 0x87b6e883, - 0x6ead93fa, 0x840b0b55, 0xc3e22e25, 0x52c9719c, 0xba33330d, 0xd8dc6281, - 0xdf39d85c, 0xd8bdb5bd, 0xa4da2cbd, 0xdf3f3d39, 0xfff9df39, 0x0730000a, - 0xb956e7da, 0xf84ce706, 0xffc6cfa5, 0x4fa43d0f, 0xbddde38c, 0x1726eb4b, - 0x3ebbf1c4, 0x036935c9, 0xce9c5df8, 0xf6002b94, 0x1c5ace87, 0xaccf1f04, - 0xedfc2176, 0x4ab5dfc2, 0xd2f7803a, 0xee202d4c, 0x96a666fd, 0xd2afdef8, - 0x4fe9027a, 0x8ed77bdb, 0x70045e97, 0x106b4196, 0xc12e55f9, 0xb8e08271, - 0x4546fac3, 0x25c06e5c, 0x80fce938, 0xe89b34ad, 0xd9a55cc7, 0xf5f4137b, - 0x00674539, 0xdaaf39e9, 0x09f489ac, 0x06a019bb, 0xc15c0ce9, 0x556bf624, - 0x7fdfdb81, 0x4a4f2ad2, 0xdbf11c7a, 0xe036cc1d, 0x3c8150de, 0xf7c71e59, - 0xfc028fd3, 0xd422666e, 0xb9e97402, 0xd77264b8, 0x3bafa8aa, 0x52816a3f, - 0x5c5b4ca2, 0xdf5e30ab, 0x12acfd4b, 0xbefcf860, 0x170568e2, 0xa0172095, - 0xe0373f4d, 0xb19c5bdc, 0x3d7fc010, 0x4698ca05, 0x4adf9113, 0x2a8e143f, - 0xa769da22, 0xb6e5785f, 0x4c27f7fc, 0xcdba11ab, 0xbdc268fe, 0xc3829dda, - 0x2eedc99a, 0x7920ce6d, 0x212fce31, 0xb74bd3a5, 0x51cc22ad, 0xf413e428, - 0x025ac217, 0x36ada8d2, 0x0406ef6e, 0x7ca1b07e, 0xa488539b, 0x70d69da0, - 0x6f50044a, 0xdf045395, 0xcd7b088b, 0x7c461281, 0x2be726f1, 0xbf11366f, - 0x042aae4f, 0xcbe7e3f4, 0x09417916, 0x3464dfbf, 0xf3aa8e21, 0x3c52fed3, - 0x953176af, 0x34ef6adc, 0x4193f1f2, 0xe3d6ee7e, 0xfc3433b2, 0x5ff72172, - 0xcb9e0136, 0x8e38031d, 0x18f67776, 0x756eedcf, 0x3f7461de, 0x337fa0f8, - 0x904d81ca, 0x6bde8907, 0x3b3aa394, 0x001ff18d, 0x43d62670, 0x0d41d537, - 0xe7e1c641, 0x45d513e8, 0x582a0615, 0xbf373f11, 0xf974467e, 0xf062faf9, - 0x5117f10c, 0xd80d567d, 0x024dbf28, 0xf5e10194, 0x9f412d92, 0x9eb9155f, - 0xfc01650f, 0xde17d728, 0x7e30c83e, 0x915f8f7d, 0x4a6e505a, 0xd2ca97ae, - 0x32f7b8e3, 0x401653d6, 0x036cf0f5, 0x9858fbc5, 0x794d1581, 0x28bef1f3, - 0x6eb17d57, 0xbc4ead9c, 0x31dfe6a7, 0x3a44f9cc, 0x0d9a81d5, 0x61205f9a, - 0x5817fcbc, 0x55ed1060, 0x491c3d35, 0xb2b9f8a3, 0xec8532d5, 0x23a50ed8, - 0x6b126dee, 0x3c2ee118, 0x160ef840, 0xf6e7f090, 0x005b9d2b, 0xd8b754ed, - 0x5bdc52af, 0x15aacc3a, 0x40dade88, 0x50596bf4, 0xff122937, 0xc4a97bc4, - 0x55aa672f, 0x9eb3be21, 0x445f8df8, 0xade7aa44, 0x7865a514, 0x8d28cbb7, - 0xeac1b37d, 0x551f500e, 0xf411a337, 0x3587476f, 0x84b5fe40, 0xce90cd9b, - 0xbea041eb, 0xedcf5b7b, 0x328f45b7, 0x099f48a3, 0x5f916757, 0x16d3cc0b, - 0xea356115, 0x7841c82e, 0xb005bee1, 0xb4e2bc1f, 0x73b94645, 0x05ac4c3e, - 0xc49f4be0, 0x8327c861, 0xd7c03963, 0xc30e7cbe, 0x2fd3853e, 0x8c39cafa, - 0x470e54f8, 0xa8356b7c, 0x959e3cca, 0xdd02fbe1, 0x7059a727, 0x7e6f9b25, - 0xf9623ebd, 0x29ef0baa, 0xba3e7ba6, 0x93962eea, 0x5a20c7c8, 0x6ad6142c, - 0x6730c9fd, 0x06c3e75e, 0xe881e3b2, 0x60a73a61, 0x460d61be, 0xef308421, - 0xaa6febbf, 0xd96f9b52, 0xf193b802, 0x04faf467, 0x3cd02287, 0xfad24b7a, - 0x5fc5787f, 0x48529e3c, 0xf31eb2b9, 0x413719e6, 0xd48fd20a, 0xbe7f736b, - 0x4f18eb9e, 0xc0ddb8c0, 0xcf9c1278, 0xcbf8b56f, 0x74ad1f28, 0xa7e7248f, - 0x0ac4faf4, 0xb432bb30, 0x4fbc329c, 0x600e6c47, 0x8f30b220, 0x4916211d, - 0x19df3ec5, 0x244774de, 0x96e0c3d8, 0xd73c7e71, 0x46e6d87d, 0xb6f389a5, - 0xf9268d33, 0xd54a5c13, 0x34592ce2, 0xf6d56fd8, 0x8b5d935a, 0xb56e0c73, - 0x9471756b, 0xfbeb059a, 0x381679e8, 0xa9e7fd88, 0x734ebb18, 0xd001cf2c, - 0x93c7c38b, 0xd1311e9f, 0xef990f3c, 0xd8e3993d, 0x0c8a791f, 0x3794391d, - 0x41f6260c, 0x24077e81, 0x63946dc0, 0x6e611c91, 0x192dca25, 0x9f7d259f, - 0x2f6e15d8, 0x01905777, 0xfe0450ba, 0x465f3483, 0x1a77502d, 0x639d77ed, - 0x3bfa9070, 0xf70502e0, 0x1bf1e8fd, 0xdd214f87, 0xb4c98e73, 0x5783ba8e, - 0x16ef9ef9, 0x78ff7827, 0xbc2d77c2, 0x3537831e, 0x0239887a, 0x403af249, - 0x6eed1dfb, 0x6e687f46, 0x05301f74, 0xc36ed052, 0xbdafad39, 0x41404b0e, - 0x1de8ac7c, 0xe79df091, 0x1cd1e419, 0xa5162653, 0x1980ff11, 0xafdc2502, - 0xfd84baa6, 0xfc855f84, 0xd8cfed8e, 0xf4c0f1fe, 0x6bd52158, 0x0a235327, - 0x8cb73fdf, 0x922f05fb, 0xed2fdf1b, 0xcd3361a1, 0x0643dc1b, 0x868eddb9, - 0x713f343b, 0x4be918cf, 0xf9e7df0e, 0x53af2880, 0x7e062fdc, 0xe1633d8d, - 0x58092c6d, 0x38731509, 0xca5536cf, 0x6eaddf3c, 0x1f18dcc6, 0x91757049, - 0xc991709f, 0xc7e76f34, 0xf5aed1ab, 0x419fa341, 0xc877e62f, 0xd0c7d5a2, - 0xa3f0163a, 0x94a2237c, 0x7b8ba1f7, 0x1cfd0cfc, 0x40aa62aa, 0x8c2120f1, - 0x3e3d16c7, 0x6e1f802f, 0x70a9fc4b, 0xe01aae6c, 0x2b61ac35, 0x5ea353d6, - 0x6e01000f, 0xd4e3f9a7, 0x8e23bd08, 0x2af9839a, 0xf9f8977f, 0xe055677d, - 0xe814d4fc, 0x6bafd649, 0x6ab375ec, 0xf33dc90d, 0x7b2ed3f7, 0x47d3f792, - 0x3b2276f8, 0x244ced7b, 0x2bbe30bf, 0x15efbfa9, 0x411ccb5d, 0xb5c981f4, - 0x5975ce8f, 0xbea9ab22, 0x1cdc981f, 0xee91f18f, 0x8b82fda1, 0x91f516ef, - 0x87cf8c00, 0xcc67e523, 0xa2769794, 0x125beec7, 0xe9b8e397, 0x0aa1fc69, - 0xa1efdacf, 0xfda79aca, 0x17fa867e, 0x7f57cfab, 0x1dbcb26e, 0xa497f9a2, - 0xe7d27e7e, 0x9912c01f, 0x3893cbf7, 0x6487b683, 0xaa3c75e0, 0xa67ef5ef, - 0xc87b48fc, 0x06199dff, 0xed5cf895, 0x7ff4d0cf, 0xc18beba6, 0x9bf61d51, - 0xf6f9b935, 0xfc39f427, 0x8a71c98b, 0xa4f2bdee, 0xdf824a00, 0xa0a982ab, - 0x195df824, 0xf6e031ca, 0x7c8362c8, 0x81a978f5, 0xc2b1335f, 0xbd735fc0, - 0x14bf80ca, 0x5f90675d, 0x01bd6bff, 0xc5bd30df, 0xcff1bf20, 0xd63c066d, - 0xb95875bf, 0x4936e789, 0x0ae41baf, 0x157e8d3b, 0x2afd18f5, 0x15fa35ee, - 0x37e25bd3, 0xdfacb7fa, 0xf64e5fe8, 0xde855c83, 0x91fcffa1, 0x2060fb49, - 0x34f3c33c, 0x13029d35, 0xa8c44734, 0x66c21fb6, 0xf0a617be, 0x84a2e2ff, - 0xd7a72c3c, 0x0919da3f, 0xb9d2b32f, 0x2b369d0f, 0x512edbbd, 0xfe3e600d, - 0x2e76d705, 0x000ee017, 0x00000000 -}; - -static const u32 csem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0xe3e3ff00, 0x51f86066, 0xb8d3c10f, 0x72361818, - 0x0143f821, 0x684333b7, 0x0606163e, 0xc77e2001, 0x9ef0c0c8, 0x38330491, - 0x207eec10, 0x27880abb, 0x7dcf5071, 0xe52f1143, 0x5f5d9fa1, 0x153d76a0, - 0x837f7818, 0x031083b0, 0x03309b83, 0x8408b483, 0x55045fbf, 0xc10851de, - 0x99412e7e, 0xfa819f5d, 0xbbeb8d01, 0x00038031, 0x00000000 -}; - -static const u32 csem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd5547c0b, 0x733ef7b5, 0x9993331e, - 0x420f264c, 0x084f0042, 0x21842a20, 0x38880840, 0x8d069009, 0x8808089a, - 0x420100ca, 0xa9113248, 0x676d5e97, 0x6ad11422, 0xa36d2d1b, 0x4101da97, - 0x180d45a3, 0x1d0340e8, 0x5abc414c, 0x5b4a0a8d, 0x3c3141b5, 0xe878490a, - 0xef5bd6c5, 0x33ef6b5e, 0x42667399, 0xfddfb6a2, 0x7f17dfbe, 0xecfb36fe, - 0x7b5ef673, 0x7b5affad, 0x231fb5ed, 0xd313c659, 0x057c8415, 0x7213d77f, - 0xf4842448, 0x0b3b4eeb, 0x108e3a68, 0xb0398e7f, 0xb4242055, 0x24edefef, - 0x4db39085, 0x267355b3, 0x98c7fb21, 0xf2d3d743, 0x80fc81b3, 0xdd4f9699, - 0xd121c479, 0x514ed57c, 0x3ed37282, 0xb1df7e2b, 0xde400851, 0xf1fd6e6b, - 0xb5df34b5, 0x699b2453, 0x376424d5, 0xda425491, 0xa9fd842d, 0x6a5f98f1, - 0x4daad965, 0xf682effb, 0x626683ca, 0x37b7dfa5, 0xafc86e89, 0x08042adc, - 0xf76aaf6d, 0x5a00ca83, 0xd080b2df, 0x7e695568, 0x1a8a63eb, 0xfb03c84f, - 0xb368ecfe, 0x67da7213, 0xfd82aa21, 0x491c6f28, 0x7b604548, 0x7dfa00e1, - 0x65c136c5, 0x6c57f5a2, 0xf401d73c, 0xc3c93455, 0x8adf5a44, 0x47511b06, - 0x22bfb6b0, 0x07cb5ed0, 0x794eded8, 0xfe57b428, 0x110a3de5, 0x1bb29fa1, - 0x74a2abbe, 0x76b5bf40, 0xb1eafb4f, 0x559f8d3d, 0xe8f6d1cf, 0x0a2fd57b, - 0xb562e82e, 0x8e807889, 0xb9d6dd8e, 0x7fa1db4f, 0xf8f0cab5, 0xdc2c7ec8, - 0x08a8fd05, 0xed0a526c, 0x6526df40, 0xfaeec8e9, 0x87fc3456, 0xacfabe9e, - 0x72889efe, 0x47da7a63, 0x3bbc3a59, 0xbb88415f, 0xa44bd691, 0xaa3a5280, - 0x4207f9fb, 0xa1e32122, 0x96a8917e, 0xe4a9faee, 0x23fe0711, 0x0f949ff4, - 0x81f1bdfe, 0x72dd99ad, 0x9904e95b, 0xbcedcb75, 0xea51cb93, 0x5fac8dca, - 0xf20c7f4b, 0xf9d4f4a0, 0xee3e989c, 0x8374c34b, 0xfdbe454f, 0xd30237dc, - 0x9f0b9f7a, 0xc3cbe93f, 0x8dcfa374, 0x22be53e9, 0x12be034c, 0x6fb36f7c, - 0x7c5ba62e, 0x8cfe7c1e, 0x06d31caf, 0x7f3e0d5f, 0xd31ab7de, 0x3e3f3e6d, - 0x1eb7d17f, 0x1d5f46d3, 0x5e403ba6, 0x05f26d34, 0xbe5dbdf0, 0xbe834c06, - 0xc7be7c46, 0x11f4c417, 0x64c747ce, 0x3e512f92, 0x49c4dc38, 0x8a924ec5, - 0xcd32f9dd, 0x7cb09527, 0x7cfe1dea, 0x3d53e685, 0x32f94f34, 0x6f9432a0, - 0x3501f9a6, 0xfdf07cac, 0xf342c0a4, 0x7cacfd83, 0x02ee23c8, 0xa90fcd2b, - 0x37c3e563, 0x68e20bfa, 0x9580787e, 0x542dbd5f, 0xabf9a360, 0x7679591b, - 0xa76a9933, 0xcb10ecf9, 0x9ee1bce7, 0x39f34f1a, 0xfb9f2cad, 0x83aa7f81, - 0xd8db73e6, 0x04ce93f7, 0x2d1ed544, 0xbab21d87, 0x6d595098, 0x4b70cff4, - 0x515e6913, 0xca2e21ef, 0x6eadff1f, 0x43f29d29, 0xc8796376, 0x9bcb1f3f, - 0xbf963714, 0xfcc32fe3, 0xe583d92e, 0x2c55fdc7, 0xfcb078af, 0x98bdff73, - 0x2c7eca0f, 0x58fad4b7, 0xf963f15e, 0x58f5da80, 0x80391eff, 0x1f6b23e5, - 0x4a3df2c3, 0x5f1fcb00, 0x1a7ba4fb, 0x3c11afcd, 0xd23c073f, 0x01649cb4, - 0x4ad31a9e, 0x09d69e28, 0xf7e02e64, 0x8a3a0007, 0x0ae975cb, 0x3f8ee1ea, - 0xfa0d3ee4, 0x90297f8b, 0xc3ccfa5f, 0xaffdf899, 0xd6991eb0, 0x4f5ef623, - 0xba799bce, 0x2cde727a, 0x8069ead7, 0xfb58d6f7, 0x378ecf56, 0x79e9e927, - 0x67ab42b3, 0xdf13d23b, 0xbce57eb7, 0xcf4f5935, 0x3d5a955b, 0xc49e907b, - 0x74d3d1be, 0xa69fcf44, 0xb4fe6123, 0xfafd3d20, 0xf7b8cf46, 0xf719fcf4, - 0x6f3f985e, 0x7de93d60, 0x3de9a7ab, 0xde9a7f3d, 0x08e7f30b, 0xdf506bf6, - 0x7dee35fa, 0xbdc67f3d, 0x47cfe61f, 0xdf664f48, 0xa1f5d9ea, 0x3ebb3f9e, - 0x04e7f30c, 0x6fac33d6, 0x48fdcafd, 0x8fdc9fcf, 0xc2e9fcc2, 0x5beaae7a, - 0xd23ebb3d, 0x47d767f3, 0x817cfe61, 0x5bea8cf5, 0xa2ff72bf, 0x5fee4fe7, - 0x0931fcc2, 0xbe98cf50, 0x54fc13d1, 0xa7e09fcf, 0xb0d8fe61, 0xa37df19e, - 0xcf5daf27, 0x30f6bc9f, 0x9004527f, 0xd5bec4fb, 0xf3d76c13, 0xe61ed827, - 0xe7ac20cf, 0x2bf5beba, 0x3f9e84ef, 0xfcc22779, 0xcafd8e19, 0xf40f7aa7, - 0x7c4f5a10, 0x39ecf5cf, 0x9ecfe7ab, 0x8cfe61b3, 0xd3a67ac6, 0xaf7ab27a, - 0x9e875267, 0xc23a933f, 0x7ac3c9fc, 0x9eadf466, 0xfe7a1d3d, 0xf308e9ec, - 0x73f91f27, 0x35fadf53, 0x9fcf53a9, 0x3f8c9d49, 0x4cd70f63, 0x3a72d075, - 0xfa44ba16, 0xdc67b5c9, 0x45e6816e, 0x4e8bcb27, 0x44bf0117, 0xd20dfcd4, - 0xf7e916ea, 0x39896df6, 0xbf48930f, 0xfa14a0a3, 0xb1bd4f15, 0x2123bf48, - 0xe7e74e2f, 0x7493ba24, 0x01a2e4f9, 0x95fbf7ba, 0xf795d10c, 0xaeb57b9f, - 0xa393dd3c, 0x4f9467cb, 0xa83fbdd2, 0xbf9740a6, 0xba0df562, 0xb7fd33f7, - 0xeb59f2ea, 0x3fbdd76f, 0xae916eac, 0x0afacafc, 0x8155f95d, 0x35fcba95, - 0x7baeff0d, 0x03e3547f, 0xc1d1f2ba, 0x63e57587, 0xf2eb8f42, 0xa93d0f63, - 0xeb7c7f7b, 0x84f95d66, 0xcaebcfa3, 0xd0edb627, 0xb93dafe5, 0xd9e7e0c7, - 0xf0d7ed9d, 0x27b808bc, 0x574fefcc, 0xc50bdfd0, 0x0657982b, 0xdf8fd1d8, - 0x3d54bf1f, 0xbcabe54e, 0xa14d58b2, 0x129905f2, 0x0fe7ae3a, 0x8db2bf28, - 0x9277bf3e, 0x7d274ae7, 0x19e2af7e, 0x9fe18ced, 0x24083c52, 0x04d5520d, - 0x41fcb1a9, 0x20b1e199, 0xc7e1cbe3, 0x535ef7e8, 0x9a44f0d7, 0xd7e62fef, - 0x129e5e03, 0x38d3884c, 0x7bc0d491, 0xf3826671, 0x73330782, 0xe047f69f, - 0xaa20fd75, 0xbd774287, 0x1a4f65eb, 0x6b9b19f8, 0x1f83f6df, 0xed106eb2, - 0x9e4200d7, 0xf90ede16, 0x07efd287, 0xd0f34d2d, 0xf50accfa, 0x57db23d3, - 0xb123fb68, 0xff6806fd, 0x37da1ec5, 0xb5d3c90f, 0xae5c196f, 0xd0a2df6b, - 0x1fd49df6, 0x6f23fda8, 0x12610a9f, 0x7f0b2f21, 0x83cdf6c4, 0x07fdb1cb, - 0x895f3a15, 0xdc2e3f6c, 0x77f4107e, 0x3e3fb41f, 0x4c87ff46, 0x707ff7d2, - 0x0affbe85, 0xb52bffeb, 0x71fb78c7, 0xe116ffd8, 0xe0ffeb18, 0x337fd60a, - 0xbedc37ab, 0x43ffcc23, 0x7b37ffd0, 0x64d67fea, 0xa8afff7d, 0xccdff7d4, - 0xf6a77fda, 0x8edf6f14, 0x9c2bbfed, 0xa2bffd62, 0xcc57db12, 0x47e0171e, - 0x09ab88c9, 0x40c9f6d0, 0x03fa986a, 0x903b685c, 0xa0a2488e, 0x6151e426, - 0x6f71d208, 0xe7dbc31c, 0x686f1471, 0x9cf8fc6f, 0xcb65a804, 0x8e2ef3a5, - 0xf2db15f5, 0x584bb015, 0x4b2be74e, 0x4165a938, 0x364df111, 0x28c30398, - 0xd1411dbd, 0x0db2f90f, 0xfec005d7, 0x4164cd79, 0x91277c09, 0xf4ff3c10, - 0x4736a367, 0x2e98cbf6, 0xdbdb93a9, 0x3c2df422, 0x23202a8f, 0xd37d286a, - 0xbbe30401, 0x79d31ff3, 0x8bf3a110, 0x833ce80f, 0x227e4850, 0xa23ef6b3, - 0xb7c825f3, 0x9412f9d1, 0xdf8b5213, 0xa70eead1, 0x384bfa51, 0x4c4b1ffd, - 0x43be3f5f, 0x7ea9f808, 0x31bdfe7e, 0xb05d4f38, 0xde9946da, 0x7f42c74d, - 0xfb4f2eb2, 0x753907e5, 0x360736ed, 0x155fc80b, 0xaa8a55f8, 0xf5e2c849, - 0xddd79419, 0xc54fbfef, 0x7f594e9e, 0xfdcb711b, 0xae77fbe9, 0x69390612, - 0xe6ddb3bb, 0xb84e361c, 0xd7a84c33, 0x4794c324, 0x634dadc8, 0x29035a64, - 0xb71fcb75, 0xb33bb445, 0x5d9f9f48, 0xc877cfa2, 0xe944d96e, 0xc81528ea, - 0x9cef5a26, 0xad72fab9, 0x8929bb1d, 0x57b799c9, 0x9be8ca92, 0x3c0e6903, - 0xe79ca276, 0x1ab7d93a, 0x32c5de3d, 0x3c82c29d, 0xc808fdfd, 0xef829fd5, - 0xfd64eedd, 0x573bd236, 0x684bb8b6, 0x142ee73f, 0x236f8003, 0x67da7ffd, - 0x69b29b73, 0x32a7feba, 0xc7f74531, 0x8f3cff48, 0x328d3fb1, 0xcbf3c38c, - 0x6e19cf8d, 0x3ffcb9da, 0xf4d07c06, 0xd283e004, 0xa3e39c7f, 0x7c32aedb, - 0x9b9ecd78, 0x4f5d0f01, 0xcae50488, 0xc71b72f1, 0x3d3a92cb, 0xc8f1082e, - 0x7365c720, 0x23879c85, 0xe3873070, 0x1ebd5960, 0xbf127737, 0x2e431e9c, - 0xfa6c36f3, 0xdd1a9a61, 0x6e390fbf, 0x1fb23fe6, 0x4fdd13f9, 0xb8bba726, - 0xd1acee9c, 0xe5c6df97, 0xeb97277a, 0x0ec7fadc, 0x6e41f350, 0xe8320357, - 0x4d3ef7bb, 0x793a6d9e, 0x8d3cb87a, 0xe5c5de74, 0x98f7d779, 0xb6f48d3c, - 0xd5b67971, 0x90c9905f, 0xf48d7a68, 0xd51d582d, 0xb9e4051f, 0x9e5b1fd0, - 0xf27e60de, 0x55e788f1, 0x8f92338d, 0x8ad9e847, 0x7e5d5286, 0xee9e6079, - 0x0bf565fd, 0xea4be575, 0x17caeb96, 0x975bbfaf, 0x9effe85f, 0xab05fdee, - 0x77e5756b, 0x2ba43cd6, 0x98fe5f9f, 0xf3cf3f2e, 0x39fdee84, 0xcae93773, - 0xa73c9767, 0xb4599f2b, 0x752f975d, 0x6fbdd6ef, 0x2dd577da, 0x8e37cf80, - 0x89fc0488, 0x30275ccf, 0x4b99f82e, 0xc73bc176, 0xbae22a7d, 0xd30237dd, - 0xe2173e93, 0x0f2fb4fe, 0x8b608ed3, 0x3a09c61d, 0x89252e2e, 0x6e9bccd4, - 0x103f5dae, 0xe38269c6, 0xacd316e9, 0x4264ff5a, 0x91526d7e, 0x0af5c5df, - 0x44258d09, 0xd386c180, 0x944625d1, 0x5e52f5b7, 0x727f0d4f, 0x5b717974, - 0xc7dee7ec, 0x8ce15e17, 0xd6e97711, 0x7e019253, 0xbbf7274f, 0x0295e58d, - 0x4e7c8929, 0xd7a803c8, 0x5bb8f8e7, 0xaffd30a9, 0x405e91dc, 0x0d0f901c, - 0x7b5cb9af, 0xfde4148d, 0x3a592701, 0x7f565e3d, 0x13bece8d, 0x03f6ca88, - 0x3dd58dbc, 0xad70d15f, 0xfb33bbee, 0x1abba445, 0x1844c56c, 0x375e4b16, - 0xb50e1d81, 0x0a399e0c, 0x61bf74e8, 0xd82a7182, 0x33c2fd0f, 0xe3e4a2be, - 0x04afc812, 0xb9be93d3, 0x3cfbb698, 0x95f71e98, 0xafb1fa63, 0xdf36d306, - 0xf23f4c6a, 0xc0fd31f9, 0x3fd31eb7, 0x3d30eaf9, 0xf4c7abea, 0xd3005f3d, - 0x4c06bec3, 0x6235f1df, 0x620beada, 0x6373e1da, 0x6f5de9aa, 0xc7c93bb8, - 0xbf80d3e1, 0x78eb3818, 0xfaed5560, 0x3b38ddc9, 0xd6afba6f, 0xcf9bb03f, - 0x8e66f5c5, 0x1e1d5487, 0x336080be, 0xf297ace2, 0xb0e3997a, 0x9763efa7, - 0x6bff377b, 0xc4de36f0, 0x8a6fccfc, 0x653c6eb7, 0xd594f018, 0x89fa9e1b, - 0x34f1bbe3, 0x7e64e4de, 0x8fd3c70f, 0xe6311fa0, 0x84e00515, 0xd7f08bf4, - 0xa71636dc, 0xd409ebe6, 0x6a716553, 0xfa1af6de, 0x75fa2b6e, 0x6e301181, - 0xb7f11f9c, 0x3f8710e1, 0x274cd47f, 0xcff73d7d, 0xf99e9388, 0xcdf9c6ee, - 0xbc1d00d2, 0x5b9746c6, 0xad5f18e3, 0xe8445226, 0xb0d0f6b8, 0x468b5c67, - 0x49225e62, 0x55c07df0, 0x5ea31f1a, 0x7f032bea, 0x9aebe37b, 0xa1b3cff8, - 0xff27f6be, 0x78e90b9e, 0xe397f313, 0xdbf4445a, 0x1769e849, 0x2e3c37f0, - 0x10695d99, 0xa61aeedf, 0x086fd138, 0xf3fcf5d8, 0x376e7cd3, 0x3ca21eff, - 0xb771c56a, 0x37f90d2e, 0xe9e1f3f4, 0x6f5fe07d, 0x7e37bdf6, 0xf80c0a2e, - 0x37b3f097, 0x5d9bd8fb, 0xc5f56e24, 0xe77fed20, 0x0f3951be, 0x870760ab, - 0x0f5a79b0, 0xa5d6d6fc, 0xff7cf48c, 0x33b8e26b, 0xeb71c355, 0xf9db4260, - 0xf9cbeb88, 0x40132ba6, 0x9c1eb42e, 0xe4ed741f, 0x722f7e7e, 0xafa99b3d, - 0x2fac6bcf, 0x68c22141, 0xa2bc6eda, 0x6a420490, 0x22a3cf44, 0x6d5c6fce, - 0xec1b887e, 0xa8d6b9b3, 0xfd3c6f30, 0x1a854866, 0xf385f1f5, 0xc0769e87, - 0x9a656c3c, 0x863c79c9, 0xaab4b51c, 0x8f69d331, 0xf504af9c, 0x4275f3f9, - 0xe7ce2351, 0xa35984d4, 0x3a719c60, 0xbb050f8f, 0x56a9869f, 0xc534cacf, - 0xddda9c79, 0x09590dd3, 0x6017fe6c, 0x225b64f6, 0x3ed39bda, 0xcfffbe0b, - 0x7aa7a7a6, 0x69087a34, 0xc0589f22, 0xacb2d39e, 0x51efdf9e, 0x0a8ba41f, - 0xb34937c4, 0x37cc39fc, 0xaffff4ad, 0x12bd4086, 0xbd7ab5e6, 0x3cdfa28d, - 0xd36f9e1a, 0x53bf47b5, 0xf857b5b5, 0x93bd67ae, 0x7b86bb48, 0xf957bf2a, - 0x068af0fa, 0xc7ef53ab, 0xdef2ea26, 0xe753ba60, 0xc03fc2d7, 0x2411af71, - 0x87255fc0, 0x5f64a75f, 0x0cda780f, 0xbf9843c1, 0x2abdec08, 0x51e29b4b, - 0x015a5d51, 0x34f28b9f, 0xfe73abfc, 0xa9d4ed4c, 0x7a0265d7, 0x54a4be46, - 0x20a9f2e5, 0x4c44cde2, 0xbf98bf34, 0x4569a8bd, 0xa75b8c31, 0x50fe6c4c, - 0x301c4a46, 0x75272e3f, 0x3d4f10b9, 0xa0454c4b, 0x3bc9679f, 0xfa11b18e, - 0xb0544e78, 0xf5ebc5d2, 0xdf9d3c7e, 0xeacbf2eb, 0xe4a5f9f5, 0x075854d6, - 0x2641ba5f, 0x86ec0101, 0xe898fcbe, 0x91977ac4, 0x6e30759a, 0xbbc79cff, - 0x94893916, 0xfaabe941, 0x17732fcd, 0x892e3a52, 0xd6d5fc6c, 0x31279771, - 0x05662bfa, 0xff7d3714, 0xb7b1a693, 0xbf440b51, 0x7583ac0f, 0x71297f6d, - 0xf2d1256d, 0x1bf4bafb, 0x81fcd5e9, 0x4e64f5a8, 0xe0834a47, 0x63b0c40e, - 0x3d30248a, 0x6aeef6e3, 0x838ba9c9, 0x223e42e4, 0xf18df20e, 0x78744294, - 0x067a2cda, 0x7e19e34b, 0xd4820f00, 0x4dbe78a5, 0xf55169fd, 0xfbf52d5f, - 0x903fd627, 0xabab9fd6, 0x4a9ff73f, 0xfa28d0ff, 0x5fd5620b, 0x76179bf5, - 0xa93da9f9, 0x0e67e978, 0x53c9c742, 0x8baa5d52, 0xeb72b5ca, 0x9a6e1d0f, - 0x0efc949e, 0x80a9ebc0, 0xde4b1458, 0x76f2c3ab, 0xbb8805db, 0xfd693fc1, - 0x11ff9fa7, 0xdf3e23c6, 0x9e313b2a, 0x990e60d6, 0x37563ea9, 0xd9262f2d, - 0xf2c63f98, 0x21139e0f, 0xafe3d41f, 0xa59fd9e2, 0x8a0afec2, 0x0a5f1e14, - 0xbd5b3fa1, 0x1c42d3e5, 0xea17489f, 0x683bf191, 0xda1252ff, 0x424a85bf, - 0x13a53974, 0xce5e04e3, 0x8fd36f17, 0xf80e89ce, 0xdfce1b57, 0x7397ef8d, - 0x14b974ff, 0xa36ed29f, 0x26409eff, 0xf8d43d80, 0x3fcc0241, 0x2fdcf35d, - 0x7a518fb2, 0xdd796cce, 0x49f04421, 0x8df3a3d3, 0x47b57f8b, 0x76ded9ed, - 0xf48b3d50, 0x4af1b483, 0xbabf720d, 0x7295a599, 0xd52d71c8, 0xb24dcafb, - 0x571f4fcb, 0x33f4f0be, 0xf31c424f, 0x30d7668f, 0x178aff5a, 0x8937bc0e, - 0x976c57e6, 0x37598a53, 0xb76a42ec, 0xfff4bc5c, 0x72dd39d5, 0x80f978a8, - 0xcf628ea2, 0x96ea4fef, 0xfbed8ac7, 0x9a2a3215, 0xf71b531f, 0x18f66d2b, - 0x563c6972, 0x9ac27e08, 0x814bfee7, 0x7da9e2f8, 0x199fe902, 0x0e9b9f83, - 0x7c001fa0, 0x39723942, 0x7866e585, 0x02e54bdf, 0x93935af6, 0x6e46fcb1, - 0x753ea04f, 0xc5f9e224, 0xf2fdb43d, 0xd05d993f, 0xef17f2ff, 0x4e3f4071, - 0xd70c3548, 0x2a61fcbf, 0xd972afd8, 0x94c4ea9f, 0xea7f2f3d, 0x65b788bb, - 0x15377f6f, 0x9dc449e3, 0xc7b1c26e, 0x5bfd0e9f, 0xf63671b2, 0x20f1296f, - 0x297fcaee, 0xfa680496, 0xb68a4499, 0x0e8bd0c7, 0x362717ae, 0xf68c4753, - 0x1fcc04ef, 0x23bf5ec1, 0x422abee2, 0xffa026ee, 0xa17de5df, 0x3fe6021e, - 0x1d3930b3, 0xaf5c4c90, 0x8919b7a8, 0xb60f2dd7, 0x0f4e7c82, 0x7587f772, - 0xfc912f16, 0x57c21f9c, 0xedf15eb4, 0x7c99fde9, 0xf2e52a88, 0x3f38e8ef, - 0xfbc39e15, 0x9adbb2ad, 0x7c8efbad, 0xfeddd995, 0xa53ede2a, 0xe7c60e3b, - 0xfdb1a913, 0xa6b201d5, 0x8e9c74f7, 0x7e8457c0, 0xf2df7d33, 0x4d6fd310, - 0x45a503df, 0x30f17e50, 0x0ef81fd3, 0x574a3fc6, 0xef963fa8, 0x3da0259f, - 0x58e6f3a0, 0xe645bd7a, 0xd72fad7a, 0x96e94270, 0xbc088484, 0xc849fd40, - 0x595f5c7f, 0x177e81ba, 0xd0bd2f61, 0x3eba239e, 0x71976f4d, 0xfa053ffd, - 0xfeb74d7f, 0xef4c8d93, 0xfc9ff67b, 0x07236e2c, 0xf412799e, 0x5fa7ea95, - 0x4b957d05, 0xdd7fdfa0, 0xeddef2d6, 0xdaff4f54, 0xdea9e9a8, 0xb4f51a7e, - 0x1278c77c, 0x6aff4f4b, 0x7a989177, 0xd4c79f4a, 0xe21b7b53, 0xfd94fff8, - 0x2897f8d4, 0xd9a7f9eb, 0x68f89ec3, 0x4a2f87b4, 0x68d3f22a, 0x61dfe90f, - 0x3f8d1b92, 0xde1a770d, 0x755d7e2a, 0x309dd805, 0x85dc352e, 0x2ee1a971, - 0xe3ab7e2a, 0xcffcb19f, 0x74a26b10, 0x4fd4b7cd, 0xa5847981, 0x2bbce08b, - 0xeb88967f, 0x048b96a6, 0xc880bef5, 0x7df06fb8, 0xf078cd53, 0xfdfca743, - 0x52f7b3b6, 0xbf13e77a, 0xebe5d6cc, 0xbfebf464, 0xc9abeafc, 0x73b73fb4, - 0xeca7cefe, 0x63ca89be, 0xe28424ae, 0x24f39d28, 0x82484fe2, 0x3e40acf8, - 0x7e63a08e, 0x7f0f3eb9, 0xebbb5253, 0xaffdede9, 0xa6f90f3b, 0xb63edbe9, - 0xa42ef576, 0x2979b143, 0x20a54f12, 0xef3fca57, 0x04302138, 0x549b52ed, - 0x7aaf3112, 0xb79ddb9c, 0x0f1ccda7, 0x9cfe4bfe, 0xe70c0951, 0xeb7e7183, - 0xbcebf6e5, 0xbb004d5f, 0x0b39be7e, 0x0fe7afe7, 0xb58f8e2d, 0xe385b26f, - 0x575f00ec, 0x750bb4e9, 0x277dc522, 0xc5ff42e9, 0xad92b76f, 0xbefdd631, - 0xe4f89b2f, 0xfe8dcb83, 0x736e5489, 0xd1e70e39, 0x2272134f, 0xa6eb36e4, - 0x5a239253, 0x71f7f00e, 0xdbeb3cc4, 0x0d7017f2, 0xb6b16dfc, 0x88c49615, - 0xf384fdd7, 0x5f2bca6f, 0x69d5fee0, 0xf012f9cd, 0xd45d9a71, 0xd41e39c5, - 0x192475f4, 0x794d7409, 0xe3a3f965, 0x87bd8e29, 0x57ec1744, 0x539f36f5, - 0xbbe6313c, 0xfd427e46, 0x901e47e0, 0x23afc89d, 0xe012c972, 0x56d991eb, - 0xef96eb02, 0x58aaae2a, 0xb3374e74, 0x523cc878, 0xe138d9f2, 0xe6fe3eff, - 0x150f89cf, 0xb79c7e50, 0xd1c0fdb3, 0x7f7a63f8, 0x6a0429de, 0xc8a1c005, - 0x004229f2, 0xc48564e2, 0x0164e8f3, 0x48fafdf5, 0x2c1f95fb, 0xd5f6017d, - 0x4e0b3754, 0x96af2d13, 0xb1c014da, 0x025db837, 0x9546fcff, 0x20de31b8, - 0x159a8cd5, 0x203ad711, 0x96afc84b, 0x277eddbf, 0x2cc2f7f0, 0xdcba0133, - 0x6039cf23, 0x3cd0bfdc, 0xa7a0f516, 0x47c1fd7e, 0xa0934ca6, 0x30f8821e, - 0xc530a1e2, 0x9ecfcba6, 0xa8ba064a, 0xdb98a6dc, 0x90c571ee, 0xe18532df, - 0xcdf6cfac, 0x7d99fff2, 0x1bed4c9b, 0x691cb5c3, 0x512b46df, 0x2c7fadf6, - 0x56b2b6fb, 0x58b80fed, 0x3fab37b9, 0x6be575c8, 0xb2c5fa4b, 0xd8faaf6f, - 0xbe35fdfc, 0x2073bb0f, 0x23a36fb5, 0x6a40dbec, 0x6dc462df, 0xffcd15d3, - 0x59bec5ec, 0xeff477fe, 0x316fb055, 0xd1523bfa, 0xe6a2b7db, 0x456fb45a, - 0x7edd4503, 0xcf852ca8, 0x6fb47ae7, 0x1b367f0b, 0x16cbb2f3, 0x57c03f03, - 0x71af6fb0, 0x80ed073b, 0x38a45b9d, 0xdabefdb1, 0xdabed2b9, 0x3e25ffb9, - 0xe56e766b, 0x239e7620, 0xcecc871a, 0x7664ccad, 0x665ee56e, 0x630e56e7, - 0xdf68ce76, 0x1beca20a, 0x047abefb, 0x8be71efd, 0x83b8bf99, 0x95cf1796, - 0x7efa165d, 0x5f9daab1, 0x691f19a8, 0x122916ef, 0xdeca39f2, 0x39e1ceb9, - 0xddecde90, 0x86ef605b, 0x0a1b1da2, 0xc7c4647a, 0xba6d430d, 0xbe4772fd, - 0x4bf5ff68, 0x107f2fa0, 0xbefd9e71, 0xf68bcd89, 0x163ed17d, 0xa7376ef4, - 0xc98551e7, 0x47e7c3b3, 0x24753a7b, 0x43aaf7d3, 0x544e3871, 0xbfac0937, - 0x15010bf7, 0x5dbf81c6, 0x9df2f9c2, 0x797cd97b, 0x83f1998e, 0xcec89bfc, - 0x2c16505d, 0xdcc3c08c, 0xd718154b, 0x0b112b9c, 0x0e0baff8, 0xfc0a70dd, - 0xd69705d6, 0x00bbbfa3, 0x89bec39e, 0x32eb6ded, 0x2e77bb68, 0xa1de7017, - 0x1798efed, 0x3f7a97b6, 0xec737e76, 0x38531a7d, 0x13ee533d, 0xa72fb002, - 0x2f107db7, 0x239bfd72, 0xc8bf21b6, 0xf8cc625b, 0x985ef6a4, 0x97c62e4f, - 0x6fcc55aa, 0xf289f30e, 0xf9a2154d, 0xbc5d2544, 0x2f9bb530, 0xfda4ee77, - 0xbfb9e94d, 0xf7a2df1a, 0x3e71b8e1, 0xd7bf80b3, 0x3e341f13, 0xf39ff547, - 0xb8a9fa9d, 0x8fc8c79f, 0x5ccecd46, 0x5e814643, 0x3cf26fbe, 0xf4701e3a, - 0x942f949f, 0x0de6dbce, 0xd9e79dd3, 0x9372f9c5, 0x54b4d8e7, 0x6a48f815, - 0x97b76700, 0x4a903f6f, 0x3b8b77fb, 0xe6420733, 0x78a6ffb3, 0x62d0fe20, - 0xa83b42ed, 0xcccd30e1, 0x8e57f870, 0x9c0323c3, 0x09bc70d3, 0xafd44e0a, - 0xf1cec190, 0xca5e647d, 0x6f5fd067, 0x144f8f90, 0x859fa09f, 0x720578da, - 0xa9bcffa1, 0x5bc5c999, 0x6e5ca023, 0x81075d26, 0x8229d5ef, 0x2aab442b, - 0x21ff6e0c, 0xd57ab7ec, 0x9e839f4a, 0xcdae0b97, 0xf4f61d8c, 0x963898d4, - 0x3718e162, 0x9b8c4609, 0x24bde00b, 0xc668b7d8, 0x1efceff6, 0x3f4647b3, - 0xf5b98a65, 0xe533d008, 0x09b264df, 0x7fe8061e, 0xfa303811, 0xf07a5131, - 0xa4fdf735, 0x2afdfb72, 0xfc0ec1c8, 0x1fc052ee, 0xf8d886f2, 0x257b95a3, - 0x4df21a75, 0x8e904393, 0x1c98e32f, 0xc8dfa960, 0x3cb45be7, 0x6fde1fe0, - 0x7ef86416, 0x324f9506, 0xfa6a9a2d, 0x7786a0e2, 0x2fcd1ab3, 0x47a42788, - 0x6fb00dd8, 0xd596eb91, 0x4f91b7c1, 0xeea2ac37, 0x27cd1a99, 0x07603e4d, - 0x28afc72f, 0x8fee09fd, 0x9bea7fb9, 0x599a4fea, 0xacfb3faf, 0x868faf5d, - 0x015eda38, 0x4e690aed, 0xf20fc5d4, 0xd65e6ccc, 0xce20f562, 0x5d935ebb, - 0xfb68d59b, 0x0b971573, 0xcf2257cc, 0x0e854def, 0xd3b1bac1, 0xfad13e4a, - 0x2ce1843d, 0xd5783c72, 0xf5f941ea, 0x5e04ff54, 0x98fe4f7f, 0xb40eff96, - 0x5516fb07, 0xf1c67b7d, 0xf5278b48, 0x6669afd6, 0x69be3f66, 0xbe76b4bf, - 0x9783baee, 0x4dfc62b4, 0x2cd87f5b, 0xc32e7e7a, 0xd048b8fc, 0xca5073ad, - 0x9ff2fd71, 0xe558ff50, 0xfc43f532, 0xfcf94428, 0x31a7b6ea, 0xf9f67d5e, - 0xfe833763, 0x48adf8ac, 0x3a9f542c, 0x1093c5b6, 0x80a207db, 0x24d1509f, - 0x91167ae2, 0x2333b942, 0xd6420cfc, 0x14bc7e30, 0x62a7768f, 0x4c503987, - 0xf5d8afbf, 0xddc43649, 0xf6601e3a, 0xc73cffcf, 0x1b2dbfa3, 0x242bfbd6, - 0x946f8eb6, 0x9f1cbdcf, 0xe6db7667, 0x1a16fd82, 0x8ad779d8, 0x39b239c6, - 0x6550ce22, 0x7b5c5996, 0x59f70db7, 0x70139ffb, 0x17d0329f, 0xdb52ce79, - 0x39e679ff, 0x822b9766, 0xcdce0072, 0xef6c3456, 0xc5783880, 0xaffa3351, - 0x0a7386de, 0x5f53a7f8, 0x23fd017a, 0xc5d4506f, 0x8fe2a341, 0x0cc8620d, - 0x2aa6b3f1, 0x7f3403b4, 0xb18df30c, 0xc5bdf0e3, 0xb4bc56c9, 0xb29f9777, - 0xcfcbc570, 0x6cdcf03a, 0xc60756eb, 0x1f2e1b21, 0x378a8fff, 0xd9743e36, - 0x8e69e378, 0xf5995f8f, 0x21a435eb, 0x9490e319, 0x1892dcbe, 0xee308b71, - 0x29ecf85f, 0xb33b0f58, 0x014fafe3, 0xb8ff95bd, 0xe07dd4f0, 0x3ab3ed8f, - 0x3ef6bc61, 0x13d7047f, 0x7376efb4, 0xee78ef3d, 0xe9875c59, 0x05d9a3f8, - 0x3dec75b5, 0x23d61831, 0x917fb63a, 0x55db710a, 0x3ce3a77b, 0xa9ced56d, - 0x798c49fd, 0x6e029680, 0x07587d03, 0xa5abca32, 0xd03065a9, 0x1bca9679, - 0xfc70b65c, 0xc58ab1b8, 0x371e55e3, 0xbd7b16de, 0xdc4e2a2d, 0xeb96f334, - 0x926efc60, 0x43e92a5d, 0x9530f8bc, 0xc83ee8e3, 0x9a43db6f, 0xbf298fbd, - 0x2a0ff0b3, 0xf20df7a7, 0xc969acfb, 0xb2849eaf, 0xe31ee4a6, 0xf03ea1c5, - 0xdbcf5b4d, 0x6c7f7662, 0xf1d9bd06, 0x83cf8c6b, 0x835ce8dc, 0xd9f0bc74, - 0x9cb38860, 0xc2eebb94, 0xcd7b33fd, 0x62aa2fb8, 0x3fa8fbef, 0xc6df3b1d, - 0xd7c232f5, 0xf8483ad5, 0xf083ad8f, 0x4b779c39, 0x73338b3c, 0x5a1c43fe, - 0x1e73e075, 0xd638666f, 0xc53dd0e2, 0x6c2dd39f, 0xceb6913f, 0xcfe5b558, - 0xf5c4310a, 0xd3903c85, 0x8baecbb1, 0x02707c6a, 0xae44261f, 0xf38ec4a7, - 0xb8ddd787, 0xe07e40bc, 0x4bd7857f, 0xc4207e68, 0xfbc203cf, 0xe83d8624, - 0x61d6c4d8, 0xfbd8e43a, 0x95f5b50f, 0x4f418b14, 0x575b7d03, 0xaffe8de9, - 0x26191fcb, 0xf9a3e39b, 0xd8cbe674, 0x45827c76, 0x61fb76f8, 0xf5a8852a, - 0xcfac0b7f, 0x60531d37, 0x638da1fe, 0xf0cf7f5a, 0xe799f279, 0xb1ef3c45, - 0xed05b1ae, 0x545ed1b8, 0x341f1613, 0xd3833bd2, 0xe3641d5b, 0xf11d99c4, - 0xe7ad3b01, 0x11bb2bcc, 0x8edbd5cf, 0xdf5a7e29, 0x959786c1, 0x52fd88b6, - 0x22044e30, 0xe2f33fe8, 0x7eb66cfe, 0xc6e5e6c4, 0x76f0e676, 0xdbb1cdbc, - 0xa73b6ef1, 0xbf85676b, 0x77e76151, 0x69dedf2e, 0xea073dc9, 0x132add3b, - 0xba7fbfd8, 0xc40a2c51, 0x45927f68, 0x4cf2e2d6, 0x8978e86f, 0xd9e31de7, - 0x493146f9, 0x557aff41, 0x84d1de7c, 0x15154814, 0x6a6b14e2, 0x35d2fed9, - 0x81a577df, 0xde24d7bc, 0x756deb86, 0x533afe06, 0xbf10f99c, 0x192b4e70, - 0xda357007, 0x49b7449b, 0xf8aaff47, 0x1e70fea2, 0xc7f72d7f, 0xf3c2e488, - 0xb0a3a297, 0x3a23fa08, 0x8c6b4e4d, 0x5ed905f5, 0x7c113c42, 0xf3fa9d91, - 0xb1cbe492, 0xeda3d42a, 0xb4b4a9a3, 0xa742c41e, 0x4b0ab71b, 0xfcddec79, - 0x77ec4e59, 0x4f3e36e7, 0x99d51370, 0xc183f6ca, 0x23b9d1b8, 0xc68c9b21, - 0xe29b890f, 0x0b9fc6d1, 0x07eff6db, 0x41d6b47b, 0xcf5489dc, 0x31555728, - 0x8e8dce0b, 0x805908b1, 0xfe6f73d3, 0x6d6bd696, 0xd0fe7116, 0x85f6d769, - 0xcf4113ba, 0xdc11e46c, 0xfe5007ff, 0x4e9bb92a, 0x0240bee3, 0xdf76a4af, - 0xb45d312b, 0xfce7bce3, 0x10071646, 0x98bfd5c9, 0x2470e2cc, 0xf1f3f400, - 0xf3a70564, 0x7ef0a43c, 0x3ae78299, 0x72f6bd96, 0x3930886e, 0xb92bf244, - 0xb4be7f48, 0x86c8eade, 0x77e27975, 0x9939c2b7, 0xbf5f5e32, 0x53b9fd12, - 0xd07e7eaa, 0x4f5c25d3, 0xf0b4baff, 0x32bfd810, 0xebb452cf, 0xcfeae7fd, - 0x59f71aa5, 0x2fb0bd21, 0x93ddea8c, 0xabbef442, 0xd6c7e6f2, 0x7a397cc1, - 0x011915ff, 0x482ac9fb, 0xe7ce0b9c, 0x97d068ac, 0x79bb03ef, 0xd893b015, - 0xebef172f, 0xc36dbf95, 0xdc79317f, 0x0aebf965, 0xe2dbfbc1, 0xecb2ae31, - 0x9f68c5b5, 0xfe7a69cc, 0x7f3d555a, 0x7c8c236d, 0xde39f3d4, 0x369be7a5, - 0xcf89ecff, 0xf3fa7909, 0x4b3e46be, 0x021bc784, 0xb5110e2c, 0x09b82dbf, - 0xd9f236e9, 0x0b76d7c8, 0x7ce2f75f, 0x96257fa5, 0x81b26654, 0x842974ee, - 0xa3d4617a, 0x80487b0c, 0x094a0f7f, 0xae57e2d4, 0x69efb478, 0x19423fbc, - 0x7a06cefb, 0x2ebd0224, 0xd13823d4, 0x46de7607, 0x5bb6703e, 0x909f5841, - 0x59e9aeaf, 0xfe94f79e, 0xfa22d8fe, 0xefc046d5, 0x762bd468, 0x0489376e, - 0x9e8264d6, 0x6e309cba, 0x6a2cfa37, 0x9ff70499, 0x286cb510, 0xc4e27bdc, - 0x1f7cc7f4, 0x8248e74a, 0x431b82fb, 0x3ec15317, 0xeba738fd, 0xde7bb066, - 0xec04a425, 0x6c71cde0, 0xa798b29e, 0xdc2ab77f, 0xed7b4eae, 0x59bef87a, - 0x785ce156, 0xcb56f367, 0x4507c830, 0x9bc47fbc, 0xb4157758, 0x332cd1df, - 0x812ccaba, 0xd8bf1061, 0x1dbb632b, 0x7cf19365, 0x6b6fd865, 0x3a40fb66, - 0x2c713f9b, 0x1de7b08e, 0x055e9fc1, 0x4c27acf1, 0x0c9ff7b1, 0xfdf89ab7, - 0xfc70df35, 0x7fda8c6d, 0xf6cadc37, 0x0878fdc7, 0xe97547ed, 0x330e3e79, - 0xcb96b87d, 0x6f4bf7f9, 0x6ceffec0, 0x47185416, 0x6e3bc50a, 0x39fb451c, - 0xe3c488f1, 0x392e2c30, 0x9bbfbf8e, 0x1f80d2b8, 0x0223af13, 0x3fc4f3e8, - 0x35b7dc12, 0xce2966ae, 0xa0eb7eab, 0x7586cf38, 0xb05b8a52, 0xe8ec6773, - 0x956f8fbf, 0x9c4cb874, 0x798169e6, 0x04a384e6, 0xa384eded, 0x123cf2fa, - 0x369db110, 0x4f6bf3fd, 0x5605f3ea, 0x49076f8e, 0xf86f7c05, 0x3aba4452, - 0x01eb88bb, 0xd9676f5a, 0xa6efbc00, 0xda9c22f3, 0x6297e9a5, 0x7e71ac51, - 0xf281e026, 0xe08509eb, 0x52c4f2f8, 0x5fefc63b, 0x05715a59, 0x7f9feb8c, - 0xac4573cf, 0x7611e073, 0xafed8129, 0xe2502772, 0x0ad7ae29, 0xe975df8c, - 0xebf63125, 0x70d6386b, 0x7d39e1ad, 0xd6279c69, 0xad0fc4be, 0x58290fcc, - 0x6050423a, 0x204fb65e, 0x078ed7c0, 0x373d973c, 0x640f27e3, 0xe0de3d00, - 0x2db3f405, 0x963b82cd, 0xeacab19f, 0x07bef360, 0x1fb0b5fc, 0x94aa5eef, - 0xae7b1f60, 0xabce0377, 0x2ba0876e, 0x5ba9677c, 0x9770e788, 0x8866c858, - 0xe9754b67, 0xee03c6b7, 0x4758cea7, 0xc4b27de9, 0x427e7284, 0xfefd2176, - 0xbe30422a, 0x03b5e3c0, 0x229b266f, 0xc0ff23cf, 0x95b0ff9a, 0xd5b0fbd6, - 0xf6497289, 0xdfa004b8, 0xe5ffdff5, 0xbceebd00, 0x0e394664, 0xed1ff3e0, - 0x4f9cadbb, 0x6bdce3a3, 0x3ca4ff01, 0xe5c3f505, 0xc965a871, 0xe5012f70, - 0x54758c7b, 0xf24d2fcd, 0xe946db50, 0xf09bb249, 0x76e22e7e, 0xdf6d4eab, - 0x45efe119, 0x090903e8, 0x69a5f604, 0x166854f6, 0xff14f142, 0x10f62ce3, - 0xca9233cc, 0x0929bf69, 0xf5616256, 0xc2674ab5, 0x9f71aae7, 0x2e65c53b, - 0xb8226e1c, 0xd2360daf, 0x9d9afd42, 0xdaf3ecd5, 0x66f68244, 0x605263ed, - 0xa367ad0d, 0xf88566d4, 0x2d5ba649, 0x4944ad80, 0xbde78a92, 0x7d339507, - 0x32fd65b4, 0x50afec31, 0x0ff31f65, 0xf5ac4171, 0xfcc38fba, 0xfc00bcf2, - 0xf5d43eca, 0x2e35b80a, 0x75cf6b2b, 0x79fe82c0, 0x3f706ed8, 0xbb8f90ac, - 0xb1353f13, 0xeba102fd, 0xb69dbf71, 0x1bb4668e, 0x15de0f54, 0x953eaf41, - 0x75cf9e08, 0xb572ffd3, 0xf611772d, 0xb9938f83, 0xf4169ac1, 0x2d91c4dd, - 0x5f6bc780, 0xa238bbc7, 0x3784c8ec, 0xde806b3c, 0x8c3f6a6f, 0xa2131878, - 0x33e5c8fa, 0x2a7b8552, 0x943ce19c, 0xfcf95ab7, 0x949bdb8e, 0xd1fd71d2, - 0x3338e5af, 0x6bd357f2, 0xace7bea3, 0xb198b576, 0xc13200d6, 0xba110ed8, - 0xc0b350e9, 0x8221bd1e, 0x4f99df7f, 0xbae942f1, 0xfc0ef417, 0x19818bf3, - 0xcd0d9b80, 0x7e82b1df, 0xa3f1e37c, 0xb11d7e99, 0xa227fabf, 0xf6cac3a7, - 0x0f803b87, 0xf22ffbd5, 0x728423f1, 0xea95cb0e, 0x443c6447, 0xe711bdc3, - 0x81ac5e9a, 0xf0b2330b, 0xf9011c7c, 0x0a234288, 0x3a364cd6, 0x7f9aaf81, - 0xcfec26bd, 0x9eb9e226, 0xded64e55, 0xcbf3591a, 0xefe8165d, 0xfe82f8aa, - 0xf5175b97, 0x97f3a25e, 0x5e30f388, 0x67e70ba9, 0x090a4bde, 0x7e0b7f24, - 0xb9eb6905, 0xc4a57e3a, 0x0757e0c5, 0xfff8d1e8, 0x6d93fb27, 0x6a83cfec, - 0x25ae7f77, 0x51b6df9e, 0x4f7b90bb, 0x05c33a7d, 0x89169c39, 0xd95ebe0b, - 0x51e77e93, 0x2dd706fd, 0x7a0d9f4a, 0xea99b13c, 0x8f5a29b1, 0xde09725d, - 0x6bdae75b, 0xd4677b43, 0x5fbc8beb, 0x7be31b5e, 0x1199e88d, 0x5371f307, - 0x5dc060d7, 0x8b924ab6, 0x41d9b129, 0xb6afad91, 0x91c6eb26, 0x8fddf1e8, - 0x2ff35276, 0xf8d2bf35, 0xe4afd85e, 0xcf1686e3, 0xff148214, 0xc7f7dfb4, - 0x5f01e679, 0xfcd938d7, 0x829a0e13, 0xab03fcbf, 0xcfa00ee7, 0x0710fb46, - 0x42231aeb, 0x125e2c99, 0x4f5be9d2, 0xe83365fa, 0xc248634f, 0xc74fcc71, - 0xcf4261b1, 0x4b8bf4f4, 0xab52f464, 0xc0ca7e02, 0xab1ac25c, 0x7bafb826, - 0x47bb3660, 0xbb0e6066, 0xe3dff1f7, 0x7dcc7ad8, 0xd0dc6c71, 0x4b581fd2, - 0xc97e81ee, 0x739bf112, 0x40dd39be, 0xef0fc42a, 0x0ddf738f, 0xb914b0fc, - 0x4e191fb1, 0xde2812e2, 0x0146a432, 0x552437f6, 0x1b8b02aa, 0x40ee3612, - 0x28cbeb4a, 0xdc61f356, 0x16b6a0ca, 0xcd1920e2, 0x6cf5cfb1, 0x5dbf9388, - 0xea29abbc, 0x3886ca3c, 0x541f6fe6, 0x8b937f68, 0x709479d9, 0x0f9286dc, - 0xbf88edfc, 0xf1db3b0d, 0xf50f5b19, 0x1b3e3227, 0x30205fe7, 0xf3c497e8, - 0x6488543f, 0x91f9c24d, 0x99df04df, 0xb23f382c, 0xd8235711, 0x58e297cf, - 0xe09d755c, 0x9ff90f5a, 0xb8165d48, 0xffc3476f, 0xeadf278f, 0x8e2be892, - 0xc367ceeb, 0xc3ea959c, 0x8eaf20f3, 0xaf87e7c9, 0x0d741ec5, 0x8b737866, - 0x9aeffdba, 0x4eb282dc, 0x8788566e, 0x78ebda44, 0x1df7e705, 0xe60b9c42, - 0x05cb1d43, 0xe160a746, 0x7d2403e7, 0x43db869c, 0x27781c6d, 0xb7e9132e, - 0xbc18ff11, 0xb2e2cc1f, 0xfd1a3d00, 0x86a473e1, 0x73c69e73, 0xe15969a0, - 0xee3a4db8, 0xe0512d93, 0xbe722f8e, 0x97fe86d9, 0xdff4c1d7, 0x60fe8788, - 0x6e732e3c, 0x15abf292, 0xae5fdbe4, 0xdb7b0449, 0x0ee3ceff, 0x0f91af90, - 0xcc7f829d, 0xfadf5841, 0x9f731c83, 0xa5a69688, 0x7f05280d, 0x0d3d2d34, - 0xbd79ed53, 0x07198a5d, 0xeef5cd3c, 0x9eb5e31b, 0xc3f30c58, 0xb39fd0d3, - 0x73de779e, 0x6177baa3, 0x8e3ebc7c, 0xd15ebbf1, 0x8026a8f8, 0x5de7759e, - 0x927eec09, 0x90ff7644, 0x8373c993, 0x492a52cf, 0xd1b9ef91, 0xdc47e91f, - 0x1181e633, 0xad9320d8, 0xbf166b88, 0x5065ced1, 0x97e4c743, 0xb9fae8c8, - 0xec294c6f, 0xcc6d919f, 0x30dc5d2e, 0x254bdb1d, 0x5387580f, 0x312d2ebe, - 0x73ae20b9, 0x1c9fd176, 0x517c1470, 0xe02e6b46, 0x91e888fd, 0xd431e36d, - 0x65b7f38d, 0x88409573, 0x9ea52a42, 0x9726241a, 0xb8eeb819, 0xff7314d0, - 0xe6c6ddb3, 0x4e71cddf, 0x06d2d34c, 0x8d8d9697, 0x39440fcc, 0x7aa47869, - 0xae365e98, 0xc5309cfb, 0x6fb40a47, 0x994ea7d4, 0x40dd6104, 0x9c2987b3, - 0xd63d9aff, 0xf40521f4, 0x4b01d60c, 0xe4d47da8, 0x9abf8439, 0xfc4af18a, - 0xfd5f9a13, 0x8e03e602, 0xded00aeb, 0x8f5ffd51, 0xd98232fa, 0xd3d82b6f, - 0xe7653888, 0xc107f7de, 0xdf87dffa, 0xeb0f10bf, 0xba917f40, 0x9e7ec1e2, - 0x78ddffbc, 0xe1f43738, 0x715e2cfd, 0x351e6197, 0xfaecc6c1, 0x6c92b6a3, - 0xdf02d7e8, 0x227ae77f, 0xb3564970, 0x01e58d75, 0x5c9e70d1, 0x554f2f7f, - 0x9ee1b263, 0x5bd63f1e, 0x32e7efc5, 0xcb92a1ca, 0x4db6f961, 0xed0a864a, - 0x7eb6dc7b, 0xa08f6e70, 0x14d93cbd, 0x8d11f38f, 0xc6db459e, 0xfa773028, - 0xaf99b34b, 0x6ccab77f, 0xc317705c, 0xf387967a, 0xc1e748cd, 0x6fac367d, - 0xfed8cfc9, 0xadb48594, 0x7abed4d5, 0x0b79d99a, 0x7c963f63, 0xa7f616a8, - 0x90f25bc2, 0x7862f380, 0x4e3a7eff, 0x883f5679, 0x7ec65eeb, 0x31cdef1a, - 0xe6d55f9e, 0xfcb8cb53, 0xf50788cb, 0x6b5cea2f, 0x369f5b33, 0x1fceffc6, - 0xff61b2ca, 0x91fe3c6d, 0x79c0264b, 0x86871de8, 0x3eee5c24, 0x1efc33e5, - 0x1a57b826, 0x823e93d2, 0x654db669, 0xbf3464f7, 0xaae02f7d, 0xef1db83a, - 0xf6bafb19, 0x94f9aaa6, 0x6b30f603, 0x91fa8776, 0xa43f01ab, 0x97f9d04c, - 0x282e9bd5, 0xf8cbbe6c, 0x7e7f0770, 0x1b37f407, 0x3fab59f6, 0x7ce54c9a, - 0x317ca547, 0xbf321ef2, 0xa6ee7f4d, 0xfad5fdaf, 0x2b5bf5a9, 0xd1fbe2af, - 0xf869df8c, 0x2c78e6cf, 0x6eba52db, 0x9ad16500, 0xf30627bd, 0x4e7868f3, - 0x1197c347, 0x4948cb3f, 0x8110ba61, 0xb147e693, 0xcb3c9a5f, 0xfef216ea, - 0xbaf8d3fb, 0x8fc41a5e, 0x118dc37a, 0xdb721d1f, 0x2367d060, 0xb87a3a3e, - 0x3627e45f, 0xa99427e6, 0x678842ee, 0x9d763751, 0x394fc233, 0xbc1dd529, - 0x0b6cf40f, 0xf8c479c3, 0xd7b99ccb, 0x57cf1c65, 0xe1fdabc6, 0xdb943d3e, - 0x6017d844, 0x5a7bc3f6, 0xb73eed3b, 0x7c04a86b, 0xb4f4c22f, 0x7435c4af, - 0xd2f97768, 0xc0382e27, 0x411cee8f, 0x11d38e30, 0x77f7a7af, 0xf9e91136, - 0xa543971d, 0x3f8ffad4, 0xd2da8d83, 0xda1dfb8a, 0xa071e4bf, 0xb145cd2f, - 0xfe27f9fa, 0x86f7e11d, 0x4cf5c5dd, 0xe02c979b, 0x99abbb72, 0xda2f67ad, - 0x30f28a58, 0x437ad7ee, 0xd0661670, 0x638d3caa, 0x51bf9014, 0xdf5c4b3e, - 0x51607dc1, 0xf08f2272, 0xdc1e017d, 0x2f5653a7, 0x28c3dc62, 0x93bb7cbf, - 0x6b57a39d, 0x42b71e70, 0x790ebd8a, 0xb5f4dda5, 0xc7ec63fa, 0xed0126c2, - 0x65fe91a4, 0x0dd76a5b, 0xd67fd020, 0x847ee8bf, 0xe25da206, 0x55fad4fd, - 0xff785c46, 0x50fad440, 0x7224f5db, 0xe6f2f53f, 0xbf2fb8c5, 0xb09ff69a, - 0x85c61238, 0x7a35fa34, 0x1428fd8d, 0x8816c8cf, 0x5c16aee3, 0xefa39f60, - 0xeeeb7327, 0xb0d85c3f, 0xafc8207f, 0x66fb625d, 0xce02fddb, 0x203f3b0b, - 0xbd607d6c, 0x3d69eb80, 0xed99afca, 0x8e59ea07, 0xe7dc0a35, 0x8851b657, - 0xf565c729, 0x11a1aef9, 0x60796a76, 0x8ea86b86, 0x1fdc46de, 0x54a1a2b2, - 0x9d807cf7, 0xfdb893c7, 0x48df4dee, 0x38cc624d, 0x9a5fa693, 0x97fa69be, - 0x3cd9576f, 0xcc1c0a47, 0xfebb04c8, 0xa84bce18, 0xcedabe5d, 0xd1e607d7, - 0xb89faa57, 0x581f5ba0, 0xb3e4c792, 0xe7c62c44, 0xca57d93d, 0x1e7d9d07, - 0x7fefd767, 0xd1fdb6f8, 0x85e9a1fa, 0x5ea33fd6, 0xc5aff918, 0x30728cd5, - 0x82e81ff2, 0x7b1bc1f9, 0x0407816d, 0xa74677d0, 0xe915af7f, 0x702b48ec, - 0x3fc839c1, 0xce9407c0, 0x31dbf4ea, 0x9496235f, 0xc75e71da, 0xfae34de7, - 0xe1c83f16, 0xab4ed67e, 0x473b2c7b, 0xb80c9254, 0x36db5298, 0xf8a4e2d3, - 0x2174647c, 0xe53a2bdc, 0x1099b6b1, 0xc8f25efa, 0x5fb84298, 0xb6d6ca7e, - 0xea2e2d77, 0x2d8ed5d7, 0x57e5fb84, 0xf680dd80, 0x10db9607, 0x89e53d57, - 0x9579f2e7, 0x5cce3fbd, 0xcbdd9f32, 0x292bcacc, 0x3c742d8f, 0xfc3c3cab, - 0x959fa0f7, 0x1045c5ad, 0x8884a9b7, 0xaacf1d37, 0x2d908edc, 0x93e78d9b, - 0x6cdb7be8, 0xf076559e, 0xc5ad2eeb, 0xb0f2adf1, 0x0e44fa84, 0x44a8b8b1, - 0xdfa56afb, 0x7ea38dad, 0xdaefe52f, 0xe60b8b24, 0x1fb9f4af, 0x936bb5e6, - 0xf11aaadc, 0x7c1f935c, 0x35ac7407, 0xfdfb75b1, 0x684f0daf, 0xbf78ccbb, - 0xc32647df, 0x67c5a43c, 0x9e58d4c1, 0x7cf138af, 0xc589be44, 0xbfe58c35, - 0x512cecd2, 0xd5170033, 0xaf161487, 0x4fe07fa6, 0x17a61156, 0xeb9d84d5, - 0xf04c3aaa, 0xa1f54b1c, 0x02c73c42, 0xd63ffcfb, 0x735ff0e1, 0x571ba58e, - 0x92054f8c, 0xc08a5930, 0x55bb34f5, 0x9bfb1797, 0x887f4046, 0x7382e718, - 0xa9866218, 0xbfed0766, 0x294d0578, 0x4ba7243f, 0xea5afb84, 0xe1114ea6, - 0x3235a9be, 0x62623fdf, 0xf6b5cce7, 0xb47f389a, 0x64bdb4f4, 0xecfdc807, - 0x36b9ad5b, 0xf3817eb6, 0x6bbfad61, 0x60113704, 0xe08075de, 0x149c80f9, - 0xb3fc02d2, 0xe01e7711, 0x127b3ded, 0x375b37e7, 0x90197fa6, 0x97a6ccba, - 0x57f78a55, 0xfa84591f, 0xdd304ae0, 0x6ff34993, 0x7cb197d9, 0x2642e986, - 0xf6dbf085, 0xc6bf9672, 0xcd086174, 0xce5f6bbf, 0x49c0b0f2, 0xf623b607, - 0x48ff428a, 0x7de38768, 0xc01afb9b, 0xf16264b7, 0x0515e917, 0x7db453d7, - 0x44e96b21, 0x1ef8f00b, 0xa7884dd8, 0xdafc16d4, 0x02eaf106, 0x3dfb0ab7, - 0x837bf336, 0xf1aa69be, 0x7099b455, 0xf02903fe, 0x4fce43ff, 0xc9a42e4d, - 0x8bec0d7d, 0x6bee8d25, 0xb4ed1d60, 0xf606d3dd, 0xad1bec66, 0x377ec053, - 0x5ca7f3bd, 0x0afc9fbc, 0x37d8cf56, 0xf6909ce8, 0x066fece7, 0x8f5c8a6d, - 0xffcf6d3e, 0x62a3be14, 0x5054ff40, 0xaa0ee49d, 0x44dc6b87, 0xbe60b255, - 0x362f9fac, 0xb69f6611, 0x82ce4ad9, 0x10c0c95c, 0xf6455b8e, 0x6bc84e92, - 0x26b49cf6, 0x9b5f69f5, 0x845abd92, 0x23293971, 0xd8117478, 0x7bb1dfff, - 0x1bb7043d, 0x14be73f7, 0xed8cd7be, 0xfec1b10f, 0x177fd010, 0xf2a7f349, - 0x2f8b17f8, 0x88dc9493, 0x07ef3079, 0xec1a7efd, 0x63609f37, 0xbf6807fb, - 0x63abb044, 0x58e98a88, 0x81656788, 0xdf983d28, 0xde8f1a43, 0xdc7feb47, - 0x9649e2ca, 0x0f8ba206, 0x38b3c766, 0x8b074ccb, 0x8dc9c60f, 0x10ff82b7, - 0xc1388e77, 0xa5fce87f, 0x22fee122, 0xae2379c9, 0x11341d8f, 0x3959f7a0, - 0x99f584e0, 0x7524abae, 0xafaee933, 0xab5bcb93, 0xbd4571f7, 0x7372e20a, - 0x7d3fcc1d, 0x7ee09f36, 0x4a53aee8, 0x934dd600, 0x91352c32, 0xf92b9ff1, - 0x0b390f77, 0xfe21e332, 0x408e37bc, 0xc5f613fb, 0xbf0e4099, 0x056396de, - 0x3c04bc3c, 0x32487ca2, 0xfa86ef3b, 0x7a502e92, 0xdb39f133, 0x63a92f27, - 0x277f2812, 0xe15760dd, 0xad67a9be, 0x7ee0378d, 0x784c17d0, 0x8a4beebf, - 0x2ff214ab, 0x609d579d, 0x6ccd9f7f, 0xbcfec38c, 0xbcfec260, 0xf575d714, - 0xc3f74a4a, 0x4a7c5823, 0xec0911b2, 0x502a64b2, 0x73cfa6ef, 0x493cd9e3, - 0xe3cbd3b3, 0x2e3cfe99, 0x200f3c10, 0x7f51f299, 0x9d3afdb4, 0xebf7045d, - 0x2ad59bf4, 0x4ae38e02, 0x4851b8b5, 0xe4cf7884, 0xdb7e8212, 0xe78cbb64, - 0x307f6072, 0xc29b1b9c, 0x0f94efed, 0x813d712a, 0xdc30e04a, 0xe762d97f, - 0x75f168f7, 0x4e39ebc5, 0x226d23ae, 0x5dd791f8, 0x07882e22, 0x8a497f5d, - 0xe74e47e9, 0x10233ef5, 0x97be8129, 0x0095517f, 0xef44f977, 0x2faf4de7, - 0xe0e3053c, 0x39e18b54, 0x8f4889f8, 0x4ff7cf1b, 0x4fee1a77, 0xd6f3e78e, - 0xe47064c1, 0x1d6d313e, 0xf238ba68, 0x8b53f409, 0x65f01714, 0x3efdddbb, - 0x5bfa7bac, 0x38b97265, 0xb63e33e2, 0xa5c46f9f, 0xa1ff5c38, 0x2e03b4f8, - 0xf3afaeae, 0xafbf695b, 0x07eaca1e, 0xb95d821c, 0xc92997f2, 0xf1cde760, - 0xa968decc, 0x97c03b86, 0xcbe18133, 0x3f5bba39, 0xe267c557, 0x01be9a7b, - 0x3d9ea0ee, 0xac7e6072, 0xd78a6575, 0xedd78055, 0xb3f38276, 0xe65ba51f, - 0xed699e82, 0xf86789ec, 0x6aeba637, 0x7587ee57, 0x6c67ff1d, 0xe03698bc, - 0xde391292, 0x3864e87f, 0x3375aaf3, 0xf3fda66f, 0xbf5c65da, 0x8be7e549, - 0x1e92f122, 0x770d1781, 0xef16761d, 0x7533f0d1, 0x3c22bbf7, 0x2119fa9f, - 0x9e124cce, 0x99f86887, 0x9c3867e2, 0x138d8872, 0xddc7e1bd, 0xe6069ce5, - 0x87370a31, 0x280a6e18, 0xb7f7f03e, 0x118fc07a, 0x8af54f37, 0x3cf12f9b, - 0x53bdaafc, 0x186ebb2f, 0x7df7e9f4, 0xb689d31a, 0x8f82fbd8, 0x56ef7e72, - 0x06cc6eea, 0x8993717b, 0x48937f9d, 0xe714adc6, 0x7bb4e3bb, 0x20b26be5, - 0xf6625dbf, 0x19b37b67, 0xbb76cfed, 0xd77183c7, 0xcb9e0b34, 0x0da79226, - 0x06bbf5f6, 0xdfc8d458, 0xc72ef8d1, 0x9a1ca361, 0xeffc0278, 0xf3fc98d7, - 0x1b81ca6e, 0x197a48ec, 0x93b8c393, 0xe21126ca, 0xfdfc8e42, 0xe04faf80, - 0xc3c02d4e, 0x25ef0571, 0xa0ae3eaa, 0xbecdfc5d, 0xbe210bb7, 0x9e1feda9, - 0xc2ede7b0, 0x3ef09182, 0xdc6bd9c3, 0x3c796aae, 0xd276014a, 0xc4fd2f70, - 0xfd2679f0, 0x8025f2bd, 0x72eeec9f, 0x73eb7de3, 0x1d1784e0, 0x736d6e77, - 0x60b3074d, 0x4e7d6fbc, 0x9b1f9d88, 0x1d3dd47d, 0x7dd4654c, 0xb70f1ceb, - 0x715dd691, 0xdffdf462, 0x163e7c74, 0xd7fbf10f, 0xc1c40a43, 0x6b9a951b, - 0x26a27cd8, 0xa68fec0b, 0xf947f877, 0x08e1f8d6, 0xc3ff7ddd, 0x88f3f8f8, - 0x38f7624b, 0x4eb829b5, 0xdf6128f8, 0xeb71f235, 0x39f7ae2b, 0x0f9c5eab, - 0xb96c70f6, 0x576dd71b, 0xfe7c4539, 0x64b21213, 0x125cbc81, 0xca3477ae, - 0x4213d4ea, 0x2a447bf7, 0xe5a76119, 0x8dc5fa7b, 0x70eff685, 0xf00e4c78, - 0x43aea42b, 0x4984ddf0, 0x6ec16339, 0x4dacc7db, 0xa34c7186, 0xb455d29b, - 0x874dded5, 0xc7275746, 0x858e1dc9, 0xf678c726, 0xe0a1d81d, 0x7c0b76b1, - 0x71a0e1af, 0xff2639ef, 0xfc803c08, 0x2c20f1bb, 0x07c6bc80, 0xfcb54f1b, - 0xa10f1f3f, 0x1e9f2081, 0x087100f1, 0x43c2b7c7, 0xc355f016, 0xaed7f503, - 0xfe68fe02, 0xf6c2a35a, 0x0d796a1d, 0x7cf64507, 0x10a5cf7c, 0xf6443fdc, - 0x6d39d959, 0x57ae224f, 0x6d64ecbc, 0x3ed87e74, 0x6498ba98, 0xebf983b2, - 0x8c89efda, 0x57e80909, 0xe106a18e, 0x06e3f40e, 0x71743da2, 0x4176917e, - 0x71377b80, 0xf806796f, 0xd064a197, 0xe2e6318b, 0x877fe010, 0xf8064a6d, - 0xc9b63987, 0x5daf8059, 0x0ebd5623, 0x01aed643, 0x516f2fe5, 0xcd27fdbb, - 0x6af0b5ee, 0x746ff6b5, 0xbd74fb30, 0x020f9d9b, 0x87491dbb, 0x2c41ff66, - 0x9a108740, 0x86cafa63, 0x0db9baf6, 0x41d039ec, 0x205fbaf9, 0xe41fe04d, - 0x5329dc9b, 0x17ebcfc1, 0xcece8092, 0x860c5fbd, 0xf3716538, 0xde8147ab, - 0xd43d6d62, 0x350f5fa5, 0xbf9ad1fa, 0x342bcda3, 0xcf9b487f, 0xe504df82, - 0xd3b9fcd9, 0x26add6cc, 0x6e782c87, 0xeaf3f1f9, 0xbfae6e55, 0x3147ed12, - 0xa42dc7ef, 0xeed2e915, 0xf399b91d, 0x9d10f8a3, 0x39436687, 0x3e513721, - 0x1defc4dc, 0xbfa5c9b9, 0xbc96e157, 0x688ef7d8, 0xbef6f4f5, 0xd6b87c71, - 0x6df46eb0, 0x763e43d3, 0xfa7fc8cf, 0xd2773cd8, 0xc12fd110, 0xce979a80, - 0x327069ee, 0x62521c3e, 0xb9fb578f, 0xb5324efe, 0xe5b9c365, 0x8efe7bfd, - 0x7b2be3e3, 0xf81efefe, 0x494f1389, 0x4eb5f604, 0x012e353a, 0xd2f3e7d7, - 0xab593d70, 0x9369fbd7, 0x88e7b08d, 0x5777ed1f, 0xdc7a520e, 0xc167d00a, - 0x1e67b7f4, 0x77d429ff, 0x2244b8f1, 0x2a144dcf, 0xc710a19e, 0xbfbfe42d, - 0xfe605073, 0x907e5692, 0xf3c5eeff, 0x21b0b71c, 0xc48fbb42, 0x9be7211c, - 0x9a193df8, 0x593a6f5c, 0x8eca4a74, 0xfdfc0f96, 0x5a0be233, 0xf399a15c, - 0x11fcb48f, 0xa77cb7cf, 0xfc096ee9, 0x89a4eff3, 0xeed11dc4, 0xe0ce950c, - 0x2f1ce223, 0x4a7e0c3b, 0xbd3f73cb, 0xde2b8e99, 0x4adc4437, 0xfede6de8, - 0x5be4367a, 0x8ff798c5, 0x9dfbf918, 0xfef1bbe6, 0x2a092191, 0xfb5bd3d2, - 0x38a6ae93, 0x27720d19, 0x65cbcfcc, 0xe51877f7, 0xff9ecafb, 0xd91b6e48, - 0x927bbf33, 0xbf0e51bf, 0xeb80533d, 0xc3c9bd4e, 0xb47ddb88, 0xbfda7e9f, - 0x9fa7ed10, 0xf8af63fa, 0xbdff989c, 0x1af30d2f, 0x9f7bbd5e, 0x4e7f064e, - 0x64f4e9c3, 0xbb899b86, 0xec4c9a7f, 0xf232f2dd, 0xf30773ed, 0xd710e66b, - 0x3fe99bec, 0x78ae0a77, 0xd27e17b4, 0x4ab3fb0a, 0x0e738d38, 0x41ffa217, - 0xe31079f8, 0x1c473638, 0x7bdee789, 0xa19bddfd, 0x5b9832f9, 0xbf0578e3, - 0x36b802c7, 0x6f45538e, 0xb2e049d4, 0x98ab4a15, 0xba7ee31d, 0xce519746, - 0xf6094847, 0x8d3a27a3, 0xabd23038, 0xefdae7f9, 0x4c7e50c0, 0xddf5a24f, - 0xff63e6aa, 0xce61c6a2, 0xdfc69e97, 0x9c95fa9e, 0x1cdee3c0, 0x4e4e17ff, - 0xdbd80b7b, 0xe519be93, 0xecd72c66, 0x90342147, 0xfc1fa983, 0xa9092191, - 0x97850fa8, 0xe3a6e214, 0x3fa8190c, 0xaf8a4eff, 0xe3ddbc40, 0xc27acf64, - 0x1325f55b, 0xe37724f1, 0x663e0e4e, 0x96eddc03, 0x1f106cea, 0xba5ecebd, - 0xda6f5406, 0xf0b305a7, 0x1336879e, 0xf4d99081, 0x102d73e6, 0x251ef047, - 0xa0a03e78, 0xc054ff79, 0x56a5efe9, 0x5e75479c, 0x08b1e424, 0xbcd8333f, - 0x587e06c6, 0x6f9d8530, 0x7448983b, 0x27f790fb, 0x8f06bc30, 0x1dd9bf9f, - 0x2f12fca3, 0x29dc499f, 0xc72e38d9, 0x70a3fc63, 0x3ffb09bd, 0x481d704d, - 0x9e65bf01, 0xce85f380, 0xa40e13bd, 0xee3b7a50, 0x333b444c, 0xdde0f83d, - 0xc6882a4e, 0xcf8b1eff, 0x780a16bb, 0xeaa140cf, 0x59617cc2, 0x98dfee26, - 0x99e48ff0, 0x433e50c5, 0x74cdf9c6, 0x788252b1, 0x2134d9d4, 0x7b8be607, - 0xf85ab684, 0x297f5c1d, 0xfd38876b, 0x7cff30c9, 0x0c7938a7, 0xaa9c76fe, - 0xefe187e5, 0x3cc31203, 0x0bced56d, 0x7cb4cdfb, 0xf7016cd5, 0x66774eef, - 0x7e047f10, 0x7953d70a, 0x6cb8a58e, 0xb8005fee, 0x3fa4599e, 0xc4bb3837, - 0xeb910246, 0xef138216, 0xf7c83b21, 0xfc097769, 0xe7ae7c5e, 0xcfbc7037, - 0xfbac9b99, 0x3f3094ae, 0x6453bbd3, 0xb3e471f7, 0xf4d6a1df, 0x87ae46eb, - 0xf1f9f037, 0x8e864f3c, 0xd288628e, 0x5b3f4088, 0x62e5be47, 0xa5cf0e1b, - 0xe78707e2, 0x1c6ef6d3, 0x8ad79861, 0x17116b95, 0x6f1d6c69, 0x1382ec36, - 0xdfea6ec1, 0x9f4f25bb, 0x97c7a18f, 0x3d9a13b5, 0xc457bd98, 0xf9d9c375, - 0x8902cf94, 0xaebfd3f2, 0x726098bd, 0xd078801d, 0x78dc97ad, 0xbd944e8f, - 0x1be8a0f8, 0x50df8bd9, 0x7aa3cc1d, 0x1f0264fd, 0x41910737, 0x8ba63760, - 0x380a7edb, 0xa6e3a4ea, 0xb48e0639, 0xef9b4771, 0x063d5217, 0x6c3390dc, - 0xa5fa659d, 0xa4efdc34, 0x76c3f7cd, 0xae25fa84, 0x6fd2fe18, 0xf774b212, - 0x4aed847a, 0xe7225f84, 0x64bf7b7e, 0x9547f53a, 0x206fa01c, 0x7b458ff1, - 0x42c97186, 0xf10518d8, 0x1873b4c1, 0x744af1e7, 0xf3e38afe, 0xb02f88d3, - 0xb752427f, 0x15fd187e, 0xd63cce2d, 0x7a53f9a9, 0x8de3849c, 0xa57dd8b3, - 0x810a4e1a, 0xb3ffa09f, 0xf4eb8c44, 0xfdad1b86, 0xa212f0de, 0x564c08f6, - 0xfae1788f, 0xf2f175f7, 0x197c6d17, 0x05f6864a, 0x343e1a27, 0x9bc718bc, - 0x83c434ff, 0xba6f1a7a, 0x0e6f197a, 0xaed1908c, 0x7cd7e6f7, 0xeaf3e4ea, - 0x37a62704, 0x7f1b355c, 0xd82c6897, 0xf937f011, 0x6b8e15b8, 0x1c9c33d5, - 0xc1245b68, 0xec1791fa, 0x1cb76647, 0xfff078b4, 0x81c4c600, 0x008000d5, - 0x00000000, 0x00088b1f, 0x00000000, 0x7cbdff00, 0xd5547c0b, 0x67b7efb9, - 0x332479ef, 0x49926649, 0x1d843c32, 0x09212108, 0x11bc210e, 0x11084937, - 0x88a80ca2, 0x1f01d68f, 0x4d092060, 0x6f53d5ad, 0x52812133, 0xbd583d6c, - 0xf4f47bd6, 0x41ed5837, 0x0108750d, 0x26702783, 0xd0f098a0, 0x7ac0f820, - 0x452968da, 0x5a18921b, 0xf5cf6a0f, 0xf6b7df7c, 0x8326664e, 0x73def7a5, - 0xd62e9f87, 0xf5af6b5e, 0x5ff9efad, 0x4a9b5adf, 0x500a9fc0, 0x982015b3, - 0xe1f95006, 0x06484a86, 0x01203be8, 0x96d40314, 0xfe1b41c9, 0xb1fdb4b5, - 0x0cdd45c7, 0x51df8956, 0xf5c02661, 0x950b7e20, 0x06e6c50e, 0xbc95e658, - 0xd6801672, 0xe1bfde2e, 0x62a82592, 0xf9af7afd, 0xe89b1ee3, 0x5fff35fb, - 0xb800c803, 0x197f7f51, 0x2ffb0ffd, 0x1860a4d3, 0x3b365d5f, 0x978dffba, - 0xa6913fca, 0x62d72c02, 0x3e4fc39e, 0x22f2a793, 0xac24becc, 0x8fb74457, - 0xcfb92673, 0xe32ff1d9, 0x32d7fc61, 0x65f3c5c0, 0xaff7516f, 0xc8ed77e9, - 0x523d48f2, 0xace80166, 0xdb1971b7, 0x7f016e5e, 0x4d2581c8, 0x0065c450, - 0x9d0a0152, 0x581998b8, 0x0d0164bf, 0x136308f9, 0x3ab9f7e0, 0xdf86131d, - 0x07e3883f, 0x8e30dc70, 0x3801c81f, 0xfae4ef54, 0xae1ef56b, 0x2f82935f, - 0x877fe3a4, 0xb8a8b0bf, 0xdfedc59e, 0xdf38fc51, 0x8f0a4be2, 0x93d69b3b, - 0x71830b4f, 0xf73f9eb4, 0x0de3fd16, 0xb6bfdc30, 0xbf8b33fd, 0xf9ebf2f0, - 0xa7e7f35b, 0xcd3f3ca8, 0xcf0c15ab, 0x180144bb, 0x9a5ceb83, 0x635fcd1b, - 0xc6f9589e, 0xfeb96fca, 0x56fcac7e, 0x90c7acc4, 0x32a2f40f, 0xffc38a8d, - 0xa6d0264b, 0x437e5e5f, 0xb3f8b1f2, 0xdb2305bd, 0x72c97e01, 0x974f1e1a, - 0xbe2b7417, 0x19974142, 0xb752baf5, 0x40efd40b, 0xb2b9ca0a, 0x4889c213, - 0x2be7f5d8, 0xf4a8513e, 0x9471f04a, 0x6c7c033e, 0x1e1e5bc8, 0xe425d17f, - 0xbcf0da6b, 0x7764148b, 0x0b1f3d11, 0xa8eb3881, 0xea1471a1, 0x6c39601f, - 0x155a61d9, 0x635c75c2, 0x547d3b81, 0xe0328a26, 0x937db894, 0xf6e3c4d3, - 0x8266c5ff, 0x3e5e01ab, 0x48025998, 0x3cead79f, 0x42011306, 0xbff7e066, - 0xdfb9524e, 0x240824e6, 0x74a0fce0, 0x945ec8db, 0xb45c8012, 0x25b4653b, - 0x364388d8, 0xd91f612b, 0x8157bf61, 0x2fdbb406, 0x050ef78d, 0xc914076e, - 0x4c738fe6, 0x7ef4598d, 0xf61e7bb8, 0xa8a4559b, 0xcb8bb0db, 0xda877eaa, - 0x9d580efb, 0xfeff5ef4, 0x699877ef, 0x1780bf9c, 0x0ed78429, 0xe7da8158, - 0xf241cc3b, 0xe3e48b1f, 0xfdeb09b2, 0xec560003, 0xb8557f3f, 0xd76e5014, - 0x13a37740, 0xc724b9cb, 0x8d7bf238, 0xfece9bd6, 0xe50a31c3, 0xd39740b4, - 0x956fdd02, 0x8fd9901e, 0x41c92694, 0x53f61ac8, 0x5a32ead7, 0x3a256c80, - 0x7ae1b416, 0x4bdafdb1, 0xb4bf5c4a, 0xe1771f48, 0x9321419f, 0x7ad1085c, - 0xf84da8bb, 0x14d012a3, 0x6d4b29c0, 0x97e4ed31, 0xce459e90, 0xc973e7e8, - 0xef5ea277, 0xf84bf18e, 0xf7bcd133, 0x8bbcc53b, 0xf726bfe4, 0xb65ffae0, - 0x43cdef68, 0x9a4e077a, 0x0e7c59e1, 0x6732b1e7, 0xd0da5f24, 0x973983ae, - 0x07fd8bb7, 0xe9153513, 0xc7f49979, 0x9ad1f541, 0xfdf2f53a, 0x940cf6a7, - 0xb9787760, 0x13028579, 0x7b4f1d58, 0x3df98632, 0xff3aaf82, 0x22d9f963, - 0xf91d9341, 0x5bddb0bc, 0x0465ae46, 0x8f913b1f, 0x80c95ef8, 0x295cf3c6, - 0x78fb0d1f, 0x46a25cf9, 0xb9f2fefa, 0xffcd1ad1, 0xfa6be92a, 0x3feffeb0, - 0xfe48983b, 0x2aa8f913, 0x2e0317a8, 0xd659f79b, 0xa1f7a15f, 0x6dc13951, - 0xf5d16f58, 0x81c4e5fc, 0xefc4f9a3, 0x67de4deb, 0xe3651a69, 0xe48515c4, - 0x9c96b737, 0x0d2477c5, 0x7ed107a4, 0x7709d524, 0xfb401960, 0xa40b7d21, - 0x1993eb02, 0x36f34042, 0x9534f06a, 0x29abe60b, 0x1c41efc4, 0xe341dbb3, - 0xe7a429a9, 0x338bd7f0, 0xf923857d, 0x0a8f52de, 0xd6b4f385, 0x1b2534db, - 0x93bd5f60, 0x1ef56deb, 0x57ad5f2e, 0x2c74dcb9, 0x8e20c1f9, 0x3459ab53, - 0x7df86d25, 0x8fb0aa57, 0x8867e805, 0x052005ae, 0x0b73a803, 0x5ef5d61e, - 0x249b8291, 0x27ae1392, 0x97289f82, 0x08dc9ec1, 0x4d2936fe, 0x35b26693, - 0xf28bbcb0, 0x063efc4d, 0x59f3e0ff, 0xdca3fb23, 0x4baaeaa3, 0xbae67e62, - 0x961724b4, 0x52f8743f, 0x6e916ca8, 0xb8017c39, 0x5bf512ee, 0xfe380be5, - 0x7842f0f4, 0x74c3e310, 0x15f10c14, 0xfd13b77f, 0x402c3a33, 0xca80c1f2, - 0xd3a45976, 0x492e7da3, 0x323e70e7, 0xe0c7af9d, 0x30cad67b, 0xe83ed1e9, - 0x17be2349, 0xb4767cdb, 0xc843a428, 0xf66e9355, 0x9cde3848, 0x26578b74, - 0xa6fa26d2, 0x75fe446f, 0xd884e3a4, 0x6323a3bf, 0xa6f68aac, 0x4fbc6f29, - 0x1cd9ad76, 0xcc2b8161, 0x71113dbd, 0x719e133c, 0x9f22bc52, 0xbdf235f6, - 0x01c977f3, 0x73886bf6, 0x9e758fc8, 0x7186f64a, 0xd92e6b9e, 0x7fd256bc, - 0xf5ed117a, 0x54f26260, 0x5dd0cff2, 0xd6b8ebc6, 0x6f91d626, 0xd8bb17f6, - 0x9f0f859f, 0x6dfef7c0, 0xe9fc8010, 0xca1fdd35, 0x9a94f480, 0x907b32f2, - 0xe4d2c3ce, 0xfc9f2a14, 0x9701725d, 0x897b92a7, 0x764d073f, 0xa77de695, - 0x46ce2d5e, 0x72ded17d, 0xd61d0098, 0x0a1cb782, 0xa1ea2795, 0xe5f51b38, - 0x971b7aad, 0x5c9deb27, 0x70f7aa9e, 0x49db1879, 0x76c75e9f, 0xb037b7d2, - 0xd85dea9d, 0x1c31e54e, 0xdba2ca97, 0x96bc7893, 0xb42c92db, 0xd0c9838e, - 0xfa4fcc6c, 0xb70c4e14, 0x3fe01782, 0xab6afb1e, 0x978c2aed, 0x34a17f56, - 0xb3f4f90d, 0xac142aaf, 0xee3c5b1f, 0xbb60bfa1, 0x1fa667f9, 0x9bde90db, - 0x8f5a394e, 0xaa9edd63, 0xfa41d8fc, 0x9d112c79, 0xb9b59923, 0xa63a434b, - 0xcd1c6f93, 0x3660d76c, 0x7af4d3d6, 0xd95d7cc0, 0xa595807c, 0x42e0f93d, - 0xaf597125, 0x577f21b3, 0xa3dffdda, 0xabb025ba, 0xaa2aeca2, 0x7b248863, - 0xb641cc97, 0x7b92b1f7, 0x95bbc605, 0x127fff0e, 0xd17b0dbf, 0x91a43fa4, - 0x49a9987f, 0xbcb372e0, 0xe1a49383, 0x95bf46e7, 0x49ff458e, 0x25debafa, - 0x98cd7db3, 0xc741692f, 0xfa35fb48, 0x96ab38cd, 0x9e66fc91, 0x72a26f2f, - 0xeb8b8559, 0x9ab355be, 0x1ccbfec8, 0x94bf7b97, 0x65d07fdf, 0x512dbd66, - 0x389c5fb0, 0x8e9bf468, 0x7bb8464a, 0xf8312ba0, 0x69f5e92c, 0xd612637f, - 0x8ab27917, 0x0337dd64, 0xb63b5dd7, 0xebe57b51, 0xde576cad, 0xf2e12f24, - 0x6990a899, 0x21d0bed8, 0x2a64c379, 0x4a6a3ff3, 0xe4a776a3, 0xd42db625, - 0xa6289da6, 0xbbd96cf6, 0xd5a7ea90, 0xa7510a32, 0x2ef38594, 0xb9c5bf60, - 0xbe1b5e29, 0xd0fc2a77, 0x85dfd245, 0x04de49b9, 0xf04af3f2, 0x7baa1ae9, - 0x9506dead, 0x6958f1d6, 0x4aa38d32, 0x5bd6135e, 0x1ffd286e, 0x2f894744, - 0xda892405, 0xd7e10a5d, 0xc3f77f27, 0x6bf62732, 0xd9012719, 0xde70a9cf, - 0x85fe889f, 0x026a899d, 0xb38b69f9, 0xb16bde8c, 0x5c4dce48, 0xff5295f7, - 0x7d598e40, 0x7e3dc71e, 0x41e39d9b, 0x8c055be5, 0x36df8e83, 0xe542e386, - 0xa84bf35b, 0x78126e3c, 0xcaadf2bd, 0x41376e0a, 0xe54a9c98, 0xf7e2dfed, - 0xb0fe97b6, 0x1fe38dcc, 0xdf62ef1b, 0x562a7282, 0xf624fc22, 0xbfde8907, - 0x77fb9abd, 0x9d0f9948, 0x0b17fec5, 0x38ac8a52, 0x213bb97f, 0x58c57faa, - 0x497d5457, 0x2562a8f6, 0x16564fc2, 0x6fd54564, 0xb38a9628, 0xe6fbfa23, - 0x57d54427, 0xb38ab994, 0x54dffa23, 0xbeaa2a39, 0xa8aca6f2, 0x1cd342fa, - 0x61ea3fe1, 0xf3b0997e, 0x20d965f9, 0xa9fc898c, 0x037df453, 0x3b26efdb, - 0xa9f812ef, 0x09f885c8, 0x55d652e5, 0xd8b971cc, 0x00affbae, 0x92667b74, - 0x2ebf17ff, 0x83de8f1c, 0x4999fe20, 0x16fc4878, 0x201e2376, 0xdc60a47c, - 0xcca7a08e, 0x2bc71d11, 0xff27cd40, 0x84b9d15b, 0x67b954f1, 0x319a1979, - 0xbdfa31f2, 0x8161f90a, 0x2ee86243, 0xa5c732ea, 0xf46c62b7, 0xabae06fb, - 0x316be9d0, 0x09529bf9, 0x6eb4058b, 0x7ac635c2, 0xb72e3a0c, 0x8ef90a9e, - 0xdfff1432, 0xfd2c575c, 0x7f791b00, 0xa0d74b11, 0x8881c74b, 0x760718a7, - 0xc43e32a6, 0x3e1e3b9f, 0x254f7030, 0xa45737fa, 0xee48737f, 0xf79785e5, - 0x97b8c66f, 0xb8c67bc3, 0x2cd0fbc6, 0xfbc6fcf3, 0x2955cf43, 0xd89df3fe, - 0x73ce293f, 0xf9ff14b7, 0x17fdd173, 0x03a36a28, 0x4828f8ed, 0xfbf100de, - 0x2410aab8, 0x35ad3d2b, 0x43e8b951, 0x747842bf, 0x1340d9f1, 0x837af395, - 0xfeb8adc7, 0x956572eb, 0x1e060df2, 0x8cd75d8a, 0x3a4fb154, 0xabb5497a, - 0x5012ded8, 0x68bfb4ed, 0xd3b55879, 0x8345aa3e, 0x6a2fda0a, 0x691b4d13, - 0x63e5a1bf, 0x549cf589, 0x52f3e7e1, 0xca318e05, 0x5e7f6567, 0xb6d5962a, - 0x8b09479e, 0x60317cd4, 0x94703021, 0x48c15e70, 0x0954779c, 0xa3be683a, - 0xbe1d070f, 0xa57e3f08, 0x29146f38, 0xa7e93a5b, 0x91fa45a4, 0x16825b52, - 0x391637e9, 0xaff5515d, 0xc7d8aa9c, 0xbd45467b, 0x159a9d77, 0x6bf10fd5, - 0x46a0e12e, 0xe42ae40b, 0x5e894d47, 0x7cb177c2, 0xfd7d17fc, 0xe093875e, - 0xaadd9813, 0x97138fec, 0x7f82a5bc, 0xa457cfb1, 0x6fea7d8a, 0x6e583d68, - 0x35f4154f, 0xe2013ec9, 0x3e933710, 0x4f71d6c4, 0xc3c68aba, 0x77a43d91, - 0x22e9bb5e, 0x4ef86f42, 0x29d7d5ea, 0xe9decfa8, 0xc44eefa6, 0x8ba923fa, - 0x699e7d44, 0xffac04cf, 0xd45cb534, 0x374d36af, 0x057e017b, 0xc32baf8b, - 0xe7dbba7a, 0xfb79c54f, 0x12ad8ecd, 0x24c519e2, 0x787b9141, 0x0588fbff, - 0x160a29e3, 0x21734c95, 0xd8ab76ad, 0xa024d72f, 0x25fea3ff, 0xaafc4a9a, - 0xdce43049, 0x1d714193, 0x9134ceee, 0x6ff630bf, 0x87be0b76, 0xfcd8e7ef, - 0xc25f42b5, 0xa5fa2ac9, 0xca2ff7fb, 0x9ed8bd24, 0xe7f5e4ea, 0x21e799ef, - 0x7d74857f, 0x7ffdfa97, 0x3c536ba4, 0x62cc9aba, 0xfc96de9e, 0xf9bb8a52, - 0xd21c51e3, 0xbb70bcb0, 0x4213cfcf, 0xcb8c2ba8, 0xf5848f35, 0x4bc59746, - 0x90fb7d38, 0x6cacaf7c, 0xb213f3d4, 0x9c8de85d, 0x1bb8da62, 0xfaeb9fcb, - 0x3bcd14f2, 0x1819e683, 0x01f51cb7, 0x56e3039c, 0xe93a8a14, 0x0d172c83, - 0xf81ede10, 0xf7979256, 0x7e0763c7, 0xbfac03fb, 0x97be4777, 0x8907f470, - 0x82ab3f82, 0xb07b1a13, 0xbc1acd3e, 0x3e748c2a, 0x967fe694, 0x6b36e0f4, - 0x9beb1270, 0x8d126363, 0xfbc0692f, 0x877f6310, 0x32d538fb, 0x1fee2471, - 0x88d82f39, 0x11ccb7cf, 0x45e6367c, 0xee28da9e, 0x3c5b37bc, 0xf9c0e837, - 0x06ff885b, 0xc074433d, 0x03c72758, 0x45a47910, 0x61e443b2, 0xbce260ff, - 0x1f192d49, 0x359cf7d6, 0xcfaebef1, 0xe68057d8, 0x9b933d58, 0x27399e78, - 0x6c4cc936, 0xd4ccff00, 0xb6af4859, 0xfa7de7ad, 0x7de8ee8c, 0x7f4eacfa, - 0x9bdf03a9, 0x7cfc7ef5, 0xdc7d3cc8, 0x299410d9, 0x89e9cf5e, 0xdf4f37ee, - 0x1f3bcfa7, 0x54cdfcfd, 0x868dbe3d, 0x8e7991d1, 0x33ff7d3a, 0x0a427c78, - 0x3af929e9, 0x516ef919, 0x3a9d9865, 0xeb5a37ec, 0xf90e5fb1, 0x85971b47, - 0x11779da7, 0xa8f56dfd, 0x93f216d0, 0x7b0d2e1e, 0x770d3c2a, 0x7988d4c2, - 0xf837bd74, 0xe0bef838, 0xdc9eb4e3, 0xbac7cf9f, 0x410cd3b9, 0x739d7875, - 0x820d3e75, 0xd3a0f3e0, 0xd99e7cc2, 0x61e9cbf5, 0x98f5647c, 0x5f588d40, - 0x6a089a82, 0xe7b53f84, 0x65d546a6, 0xce3a3e43, 0x9f8fae98, 0x351d1de4, - 0x0c37818e, 0x5a9abdf9, 0x643849de, 0xe31d63ba, 0x13d9948e, 0x3e2dc6a2, - 0x64272b1e, 0x2476e11c, 0xd7089ff2, 0x70a2569f, 0x80772cc6, 0x3fb30038, - 0xc9706254, 0x68ec9976, 0xe7e8d9ee, 0xc8cbb4e6, 0x84fc72ed, 0xef9f3fa9, - 0xe9f9fbfe, 0x99f9a2d2, 0xcfcd1156, 0x3f345f74, 0xf3455733, 0x9a3f946d, - 0x4dd6632f, 0x6abf6a89, 0x7d545163, 0xa37383fc, 0x006167fa, 0xdc4fac8c, - 0xffaa24ba, 0xa22beda4, 0xba9f93ea, 0x5e7faa2d, 0x7b544d70, 0x2baacefe, - 0xa8617f92, 0xb11faa2e, 0xf20df4d7, 0x1fedbabf, 0xeff9e6a2, 0x34a2ff96, - 0xcbaf2f3d, 0x438e997f, 0xc7fa1a5c, 0x4538e1a2, 0x93f215e9, 0xbe37f6ae, - 0xa04bfca0, 0x53bce544, 0x1b780960, 0xd909edb1, 0x1b5f9127, 0xa136ac83, - 0xc13268df, 0x8ff7f23a, 0x879c4c9a, 0x2abcec34, 0xaa8be04d, 0x9ff7e134, - 0xf8a69b46, 0xeccff066, 0x78449ede, 0xa0993643, 0xe29ae29b, 0xc671bf65, - 0x716be101, 0x7034793e, 0x7934ab5e, 0xa899b2f6, 0x329bf287, 0xd1e51fef, - 0x7d71507e, 0x3f1fc78d, 0x8b9ff941, 0xfa4a9b0e, 0x03faa72a, 0x7d70b714, - 0x2461e7a1, 0x3eaf795e, 0x49f6893c, 0x67957d46, 0xbfea66e3, 0x93858eea, - 0xf43aff68, 0x498e8efc, 0x88721165, 0x388adf5c, 0x697be8f8, 0xc4673f22, - 0x6aacdb87, 0x6bca0f63, 0x3ffc2c9a, 0xa5ef85c6, 0x903ffae1, 0x9c0b361e, - 0xbad33015, 0xde724e31, 0xba8085df, 0xe194cb0e, 0x8d7ea478, 0x84c1f54a, - 0x26f9dc68, 0x08fb4411, 0xffc72a5b, 0xbb7f0d5b, 0x36f98f2e, 0x3fee88e8, - 0xc144f778, 0xd7236fcf, 0x2c67df90, 0xdd061d62, 0xfc3f75e7, 0x7b87eea9, - 0xe446ffc9, 0x78edd79b, 0xf5f0893c, 0xa7815c99, 0xe8cfe78d, 0x4d267d72, - 0x3bf5e9e0, 0x79919c13, 0x2b90eac7, 0x36db5eaa, 0x423679ca, 0xeb1bd70f, - 0xad0a4bf0, 0x3f6e8363, 0xc93d9dd5, 0xf1e301b7, 0xdc70d3a7, 0xbf171d9a, - 0x37de8fbd, 0x3888640d, 0x6ef9e01a, 0xd7180f79, 0x4415f2df, 0xd297d2e1, - 0x25e57e44, 0x95cb0ba2, 0xdf513858, 0x776c6256, 0xfcc6f951, 0x7c3bb272, - 0xbeb0961e, 0x84cc13ac, 0xb3fb96d3, 0x53f4c4cc, 0x2f677de0, 0x9a5f6d2e, - 0x04dcf3ca, 0xc5c5333e, 0x9d5dbf77, 0xc686fd44, 0x4319c633, 0x2bd459b9, - 0x419cc057, 0x246b9af9, 0x9f380dc6, 0xeefb9e8d, 0xe299b318, 0xbbdf31af, - 0x0ef0bfe0, 0xf00ac5ea, 0xf8c6b8f2, 0x7e51a900, 0x90cb03f8, 0xbf24ed1c, - 0x98532eba, 0x677539f2, 0xd1fe7cac, 0xebf030df, 0xdfce9007, 0x57b17d55, - 0xbb7fba42, 0xfb57e07a, 0x4fadf9f0, 0xb5c5dfa1, 0x87fddb66, 0xc3ce22d3, - 0x917ddcce, 0xc8f10ced, 0x33924ff3, 0x25eac97a, 0xeaa0f8fb, 0xbc489ca5, - 0x616d227f, 0xb307bd27, 0x479ee2d3, 0xab2beec4, 0x6ed93f48, 0x8699c655, - 0xeba7de5e, 0x930bdd65, 0xd25d79f9, 0xfd447ad0, 0x57f39979, 0xbcac0775, - 0xd7477fbf, 0xbf17aa87, 0x9f991998, 0x54bd416b, 0x7274a873, 0x2a9ce749, - 0xf1cf66f2, 0x6fd4a9c1, 0x21efeca3, 0xe978393d, 0xefaa64e3, 0x5e4bf379, - 0x6574dc0f, 0xf323f7f4, 0x9b5cf922, 0xf92ef034, 0x567dea93, 0xa550f295, - 0xdd8ef2fb, 0x4e9af58e, 0x9eb83bf4, 0x239eae0b, 0x6a7ed34f, 0x979404bf, - 0xb02709aa, 0x9569af73, 0xaac79482, 0x65bddb6a, 0x9aabd60c, 0xba931797, - 0x3f0b26d6, 0x0522d356, 0xa7f03c69, 0x748a7f31, 0x357d28db, 0xb00b1fef, - 0x18a8efbd, 0x787d5cff, 0x4ff459ea, 0x9d9f2d7d, 0xb4363a23, 0x763f3959, - 0x196c292e, 0xd85ef383, 0xea02852d, 0xb9f6ddb0, 0x5d6a3ec4, 0xcd0b31e8, - 0xe5b9eebb, 0xfb0f04d9, 0x90b49df6, 0xfad75c7f, 0xbcfeb958, 0x20fb8458, - 0x9dfac5db, 0xf322931d, 0xfc21f749, 0x81f8c883, 0xf70805f4, 0x09e39082, - 0xdaab3e5d, 0xbb123627, 0x7dedafd0, 0xe6bf625a, 0x3bdf9374, 0xffdfebb8, - 0xffdde695, 0xff98932f, 0x7fc657c5, 0x4f1805f0, 0xc0f3e8d4, 0xda1653f9, - 0x9ab4d61f, 0x173bc5cf, 0x77dbbefa, 0xf0c67b95, 0x571636fe, 0x3880b16f, - 0xc10099b7, 0x381e29e7, 0x91ab2c06, 0x07511f9e, 0x0e7147a4, 0xdd60d658, - 0x71467646, 0xc608e3c2, 0xb9d717db, 0xf70f9e15, 0x9de31b08, 0xedead657, - 0x858f6aa5, 0x9e3570f2, 0x75e90b5e, 0x7113f84d, 0x51f6df5e, 0xbf6716b9, - 0x7e16ed5c, 0xc303d0d3, 0xa7d2ebde, 0x87985db0, 0xc6c860e2, 0x66b85f76, - 0xdd53e280, 0xda0ed47e, 0x03fcb817, 0x6f607744, 0x2beb4a82, 0xccc9f7dd, - 0xfe79889e, 0x5187dba4, 0xa3f979af, 0xe7e266a9, 0x2aa68f9e, 0xfbcfc349, - 0xe2eb1c32, 0xddaa55e5, 0x4e6f4e22, 0xb68f9df6, 0x186f0483, 0xb769ade7, - 0xda07f9f3, 0xe28e96c1, 0x75b83b48, 0xf3d20edd, 0x168bd976, 0xcb6d3501, - 0x3fdc0dfd, 0x91e24bc9, 0x480616db, 0x8fa7650f, 0x8afe13f5, 0xcfd4cdf3, - 0xae52267d, 0xe91b7fdb, 0x4f08e291, 0xd46bcc8a, 0xd17e7a98, 0xb75c9121, - 0xaf9a266b, 0xc96fd808, 0xef0f5f0e, 0x54338a9f, 0x9e1ec7da, 0xa7c40e51, - 0x38901e9f, 0xf54e6b5f, 0xf922cd6f, 0xbfb9951e, 0x010bf0e5, 0x9bee973a, - 0x9f44c506, 0x4e9fdeb1, 0xe38c830b, 0x2f042e6c, 0xff79bb4d, 0xdfd21e2d, - 0x611fa69f, 0x86f7617c, 0x234afc80, 0xe7ca06e2, 0x61420bd8, 0xd721271a, - 0x3ce32c57, 0xf3276e79, 0x7bf562cb, 0x4d941f29, 0x4d875c75, 0xfa23adf1, - 0xb144ee6c, 0x657b1e9f, 0xb23eba79, 0x1bce857f, 0xe92f9cfd, 0xed3d0b33, - 0x5f180abb, 0x399d1df3, 0xbe09a4d4, 0x6b2e76c1, 0x46a63adb, 0xf044dbc6, - 0xdf79e8db, 0x44bc5bfe, 0xd75139bf, 0xb6448cf7, 0xfff9d88b, 0xe499f499, - 0x35b35a6e, 0x7c4cf88b, 0x7bf64753, 0xf067ef5a, 0x2e7f1403, 0xaa922bd9, - 0x8d0fcbc5, 0x4e3c9777, 0xea9cdd72, 0xf01575cb, 0xc300acf1, 0x76b8c49e, - 0x57fffd87, 0xe91fff64, 0xf8a2dcfc, 0x4ddfc46d, 0xf16cdd7a, 0x7fb64ea9, - 0x0ff34a9f, 0xfc746fad, 0xf6e9b5f5, 0xff8265ba, 0x4fb7d71b, 0x15399f5f, - 0x4bc68df5, 0x4e67ee06, 0xff48060e, 0x78a0929a, 0xec3e3e13, 0xdd90f72a, - 0xc5f4396d, 0xa6f7b238, 0x2807af24, 0xd66075af, 0x2dfbb22a, 0xfd636fa3, - 0xbc85f4ff, 0x9e623922, 0xad256913, 0x697ebfe4, 0xcfe2cbac, 0x42fc75a5, - 0x5d6323d7, 0xabdf6ee9, 0x11bc88ee, 0x915f758c, 0x9fbe80fe, 0x17f1eaf3, - 0xff9c73f7, 0x2f4487eb, 0xd6ee279d, 0x3e02b771, 0x783b1bd6, 0x1a55c655, - 0x1f7ba31c, 0xd8261d8d, 0xe4a6cb46, 0x5d39c454, 0x36326cb2, 0xb70d9a7d, - 0x4c6c74e6, 0xebba6fed, 0xbd213496, 0x0b2021fb, 0xaf9d167c, 0xa4d24d00, - 0x6bc53cc8, 0x14f3f155, 0xc91bf8cf, 0x9e56ff2e, 0xb4d84e62, 0xf7f292da, - 0xbace2be7, 0x9f3df7a3, 0x2a2655ba, 0x31f42b94, 0x8a0c4e14, 0xa74c17bc, - 0xf133537d, 0x067bff12, 0x2df6cad7, 0x5cdae5f5, 0xfbee4f68, 0x8b1d6db7, - 0xd62d9776, 0xfa46f54f, 0x3dc0a77b, 0xd78ff943, 0x46ee30a6, 0xfef3273f, - 0x12d3a9df, 0xc462b723, 0x88f7c06b, 0x27f2a352, 0x265f23e1, 0x4aed7e93, - 0xb922df55, 0x7cc9740c, 0xe941244f, 0xd8e2b8b1, 0x03c23ed9, 0xd38bf7e8, - 0xd6c43ec5, 0x6d17ce26, 0x317ec6aa, 0x269ce9c1, 0x79c5d847, 0x579fc8b7, - 0x9c60f91f, 0x05dc3105, 0x02e4f1d3, 0xdec37f1c, 0xc34a6496, 0xf6f33fad, - 0x5392ba4c, 0xe91df8a2, 0xa54ffeb8, 0xc236391d, 0x53835ba9, 0xf0a13f89, - 0x93f21484, 0x94040a85, 0xf1f138a2, 0x14de22a9, 0x87c53cd7, 0x3ed850ff, - 0xe5e12d7d, 0x2f58b0da, 0xa6c661cd, 0x7ae036bc, 0x2a635b5f, 0x6ffb578d, - 0xbf934607, 0xe05d297a, 0x4d2f179a, 0xa02bef11, 0x74acff50, 0x41e7ae97, - 0x5f0be513, 0x7d8cf3d2, 0xcfdc4c97, 0x6db0bf98, 0x3d44eca1, 0x3f6f0828, - 0x76cd79c4, 0x4df24aab, 0x3f040e78, 0x771813da, 0x0c5c1ed6, 0x5dfae714, - 0x7db095e0, 0x6fc0e257, 0x0e061f49, 0x773a5558, 0x876e704d, 0x977f1c54, - 0x0f2b4f7e, 0x31c5b215, 0x2f98dcfc, 0x94e7fda1, 0xe0bd2413, 0x6504dff3, - 0x88e35c3b, 0xd31277e4, 0xd5eba25d, 0x89b0c4ae, 0x260645ce, 0xe9875ee1, - 0x7813a61a, 0x3cce835e, 0x2cbbfbf6, 0xe07ee703, 0xa49cba66, 0xe8207907, - 0x2ac9f684, 0xa704d1f9, 0x7048ebc6, 0x3480deaa, 0xa9daae92, 0x6ed0fc08, - 0x35e7251e, 0x6baed877, 0x36eb8713, 0x135d85b4, 0xff8f3f40, 0x8f3a36d5, - 0x8393aa1f, 0xfefc3d99, 0x6c2fe92d, 0xf9cb1a6b, 0xa28c80bd, 0x949963b6, - 0x7954eb4a, 0xb545e87d, 0x07c122f4, 0xb767afba, 0xfea1f689, 0xaa0ee7a8, - 0xaf3f443b, 0x925f69d5, 0x8742f6c5, 0xf07843d7, 0xee7c297e, 0xded7b45a, - 0x05297cc7, 0xd35eaeb8, 0xb19a07a1, 0x87569fdf, 0xe93ee872, 0x1aff5673, - 0x3e57cfd2, 0x2148f35c, 0x665ddbf9, 0x9df9256f, 0x18cfc09e, 0x5668bf87, - 0x1dd845b7, 0xe0c81d8c, 0xf33180fb, 0xf4d99ed4, 0xfdd7c233, 0xce9525fb, - 0x03cdfbbd, 0x9aee88e3, 0xe85a3ff6, 0xfeed64be, 0x4b4f188f, 0x9a1afe19, - 0x035b766f, 0x039b6bdf, 0x1b5ef9db, 0x9fbe43fa, 0x7f08f218, 0xe73a7832, - 0x390886d9, 0xec2e913c, 0xe3fc060d, 0xebb55e29, 0xf6907af6, 0xedee58dd, - 0x8d2275b8, 0x07cf57bf, 0xc035ef18, 0xf7c431a1, 0x971af04d, 0xa0fef3c6, - 0x967a4152, 0x4eedaeff, 0xa3ffa22d, 0x3dbf02e9, 0x66702e9a, 0x89bf8676, - 0xf1df5de8, 0xd69925b1, 0x8e343679, 0x4521b9f6, 0xf1c6714d, 0x1bf64323, - 0xcab54f63, 0xd7fa8580, 0x2bf6079e, 0x14a6ef28, 0xef4bdf94, 0x8d594db6, - 0x4ca2f7cf, 0xe2ae2852, 0xefe294fe, 0x0c6fb35e, 0xe7786ff5, 0xc7e4a9f3, - 0xe74f481e, 0x607e7ff5, 0x1be278fd, 0x22497fea, 0x606ed9d9, 0x69d866bf, - 0xbe29d901, 0x5ffa405f, 0xf63cf54c, 0xdd2cbbcb, 0xf72ed84b, 0x12ec809a, - 0x01ed9ff5, 0xf849dff5, 0xf689c0ae, 0x664fefc0, 0x6dd5df3b, 0xa32718d2, - 0xf5c49f5f, 0xbea91b92, 0xc9ccbbab, 0x05f74e76, 0xc35ec88a, 0x109c7887, - 0x9d1224c0, 0xfca8be04, 0xe9993b88, 0xe7e5fc36, 0x86e3d06e, 0x75c5e29a, - 0xca3965d8, 0xa4e2223e, 0xf4711ba8, 0x9edb33c9, 0xee817b40, 0x0fdc28d4, - 0xffbf0bef, 0xd5563d5d, 0x59773ebd, 0xeeb3ae33, 0x07edcc84, 0x585e7df5, - 0x7a4393d7, 0x86e2867e, 0xefdc5d3a, 0xb033e7a5, 0x675df74e, 0x094b1b6a, - 0xd8aecd63, 0xb9ca987e, 0x412950be, 0xbaabf9c8, 0x99859b0f, 0xb5fe93e7, - 0x9f2eba1e, 0x9ff5cdee, 0x920242b1, 0xc0e5fad8, 0xb5c45f6f, 0xf910703d, - 0xe14e271f, 0x10ff5872, 0xcf018d6f, 0xc97ef6c8, 0x4bbd23f0, 0x5afb1f48, - 0x123ae1e5, 0x4d8a8352, 0x3fd277f5, 0xbac016dd, 0x9f7b433f, 0x99c7e254, - 0x3f49f7fe, 0x997e4ffb, 0xf7b96641, 0xb7c7d8b4, 0xd27cb45a, 0xb809d69f, - 0xa7a38db5, 0x3c8ba5af, 0xe215b14f, 0xa57e4b9e, 0x009cc1c7, 0xfef1223c, - 0x5106765c, 0x655a17ee, 0xe7f882cd, 0xce56043c, 0xe7a37f23, 0xfd01ef6f, - 0x941fe1a7, 0xf57abdcf, 0x182bc21e, 0x627deeb7, 0x89bfb9c4, 0xbb6d69f4, - 0x6b84ff04, 0xfc4cf75f, 0x5e46097b, 0x1db6beeb, 0x3ca0c647, 0xee8b9eab, - 0x9ee861b7, 0xbdf7887b, 0xefa39a1b, 0xae957c1b, 0x308996e3, 0xea0b7091, - 0xb307fb13, 0xd4569d02, 0xfd3257df, 0x7e5e109f, 0x84f824c9, 0xf2ed957e, - 0x671eb713, 0x1a3f844a, 0x8f7c00b8, 0xe8676f28, 0x99d7dd30, 0xa5e59cdb, - 0xa22ae639, 0x165b6e7d, 0x825019c7, 0x9837dd32, 0x19cbf9ad, 0xd3b4075f, - 0x9d642f74, 0x89c127ee, 0xa3bf287f, 0x8e9d6baf, 0x460beee7, 0x82073dd3, - 0xdacf348d, 0xd1fee29d, 0xbff19dfa, 0xc7d5a813, 0xc9d4f0d9, 0xac0e9423, - 0xabf7450e, 0xdb53f9d5, 0x05bcfd16, 0x9f181278, 0xfccf7d11, 0xfc43ef4a, - 0xc5f02cc9, 0x4638fadb, 0xc219b5fb, 0x7920d67f, 0x410ddf24, 0xb37a4839, - 0x0b240a4e, 0xd58e0b7c, 0x865df748, 0x65f7e8be, 0x73f9d6ef, 0xbc2fae97, - 0xfabf7c2e, 0xe7482919, 0x24ff7780, 0x427bfe9a, 0x1f49cbab, 0x5d6af562, - 0x6df199b3, 0x10b46c15, 0xabd58dbe, 0xd97d21aa, 0x1638a16e, 0x7e354fab, - 0x0b7432e9, 0x4b7ffe5c, 0x98737af7, 0xffeb4cf3, 0x3ca5e4a7, 0xdfadbdd4, - 0x745e50b1, 0xf9087da4, 0xa27a1956, 0x5defebaf, 0x7c86edcf, 0x9614c0a7, - 0x15da456f, 0xf1a283ee, 0x50cb6ef4, 0x7cf3929e, 0x38139d83, 0x51e86e3f, - 0x3ae538ec, 0x14fc5f2e, 0xada17970, 0xa2f84ed4, 0x2bc9b8ff, 0x4c7f9ca9, - 0x4c3e442e, 0xe103203f, 0x89f6fe8d, 0xfe90078f, 0x37c513a2, 0xfa7cbe52, - 0xd83f8c09, 0xf8b3a7be, 0x115fe457, 0x7d91a4e1, 0x4ecaec2f, 0xc783bdfb, - 0x7fddf8e1, 0x4af1e8bc, 0xcbc7c3f2, 0x095c698a, 0x787ee9db, 0x1a871e91, - 0x7bd9178e, 0xfdd1e222, 0xbedf2219, 0x47fbf3c5, 0x78b05f69, 0xf94bd9b7, - 0xff66c58e, 0xafa404a6, 0xdbc905e8, 0xe91db380, 0x8d24f43e, 0x52a4f68b, - 0xeef166be, 0xf6a21def, 0xd3125dda, 0x28bedfdf, 0xc7c5177f, 0xb8a5eca0, - 0x577edfd7, 0x7384bdc1, 0x7053dc0e, 0x477cc457, 0x595f8552, 0xe399957c, - 0xfb68ef71, 0xcf292b2f, 0xff60eda9, 0x1eeafbd0, 0xb0577f0b, 0xae0f024b, - 0xf0e788f3, 0xbd0f89af, 0x085a4efb, 0x9eb697e4, 0xf1c4f4b4, 0x017946cf, - 0xce6171b7, 0xf0b76ebf, 0x7fbdca3d, 0x6b7ad0b0, 0xf388fb9e, 0x126d5569, - 0x67aaa7fb, 0x794aa0e4, 0x58af039e, 0x9a6b3f48, 0x8accc825, 0x3b73376c, - 0xffaa51f9, 0x65f859b1, 0xe8d7ef43, 0xbde86e7a, 0x746b0761, 0xd6d775ff, - 0x17bf3d68, 0xf1a32db4, 0x579a7bfd, 0x7ba03df3, 0x5ff7c7b6, 0x4b5c1f86, - 0x2b8c52fb, 0xee8a9f6b, 0x7e90df77, 0xc7bfd807, 0x3257c9fa, 0x3cd8f3f4, - 0x1efd23c8, 0xaf19af0c, 0x7e7d3da0, 0xc43c6ab2, 0xd71e3bc9, 0x8f1180f1, - 0x8e26c307, 0xfafdb167, 0x285a2eda, 0xfe76d68e, 0x796bf199, 0x872c67fb, - 0xbe0ef6ca, 0xf83d7aaf, 0xaf1f1037, 0x093bb76f, 0x08f65747, 0x6ed25fbb, - 0x6a25060d, 0x7c91350f, 0xef8a0ffb, 0x4aaf023b, 0xf740a38c, 0x7e756b7f, - 0xb7f9d5ae, 0x6367f716, 0xbe8adee8, 0x772fbeff, 0xe2ba11c7, 0xdf3fa351, - 0x993875d0, 0x8404b8f8, 0x12125a7f, 0x8790c9fe, 0xc6465f11, 0x936f81d1, - 0x5bb7d73c, 0x52f8bef9, 0x6d2d3fdd, 0xc593df16, 0x51fe8bfa, 0xddff9176, - 0x8d8de82b, 0xd1ad35a7, 0xd232bbfd, 0xea0fdfd9, 0xc313f878, 0xa8f2e8df, - 0xe53b001c, 0xb2a897e7, 0x756fc837, 0xe77f342b, 0x63cf8954, 0x2989d53b, - 0x194beef1, 0xce3a9be5, 0x28cbea37, 0x43fd864f, 0xc88eedce, 0x998dfc7d, - 0xcd54af02, 0xcf240391, 0xb2cf7d88, 0xfbb8aca2, 0xba44c81e, 0xd77b18df, - 0xee45a64f, 0x391db47b, 0xf23f67a4, 0xf7495e3c, 0x859b6a8c, 0x8d9be87f, - 0x8e10a6e3, 0xb5c5c607, 0xed20d6cd, 0x4f516a4f, 0xd2307bf8, 0x76bfb20f, - 0x07e91169, 0x991c1bee, 0x3a72cf48, 0x2ff5c4aa, 0x8e38c36f, 0xfb2f2fc3, - 0x2baaf58c, 0xf91bac5b, 0x1f6f1996, 0x6a1fec61, 0x6a9c092e, 0x7a51af3c, - 0xd3511f78, 0xb749ee2e, 0x5c62fa1e, 0x7fdbd216, 0xadc63fe0, 0xa64172c6, - 0x25adbf88, 0xbee98fa1, 0x6cbbe7cf, 0x90e8f171, 0xd89a97bf, 0x3dcc6a0e, - 0xf6578c19, 0x859c2e23, 0x4fedf37e, 0x7ad1df79, 0xca4ee128, 0xf1adf5c7, - 0x837e778f, 0x13601a9c, 0xd04ddae3, 0x9ee125c4, 0xd6b81c48, 0xdd0fee29, - 0xaa49c7ab, 0x7d7a8c3f, 0x505df62f, 0x03eecf14, 0x2349e65b, 0x1bf0dded, - 0xafbebad5, 0x85b1d82f, 0xf163e08e, 0x476eb551, 0x2e39fc88, 0x1ba2e2c6, - 0xb4f5a333, 0xc644ede1, 0xb25dfdb9, 0xc8c47293, 0x268c5fd7, 0x7ef887dc, - 0xeb3c9c42, 0xf65ebaa7, 0x0dbee7ea, 0x9be665b3, 0x0d288e69, 0x63fc851c, - 0xe93fe97d, 0xcb1c5208, 0x04caf83f, 0x9dfaff92, 0x2445e7d1, 0xdfdf3f3f, - 0xaafcb20a, 0x433e7643, 0x3a5fda32, 0xd214caf8, 0xbfb786b3, 0xf97211cc, - 0xbee2c722, 0x29467d3c, 0x6bff6249, 0x77fec492, 0x4c93d2af, 0xfddaaefb, - 0xfef22fb2, 0xbbe721bc, 0x4501fd75, 0x65d7f3ec, 0x686f5caa, 0x3a617a17, - 0x7f9c4a20, 0x98f3c8a5, 0xed11fe79, 0xdf2fa825, 0xe880b710, 0x9ad7d942, - 0x6aef5807, 0x9e989a4f, 0x198393da, 0x05ef11d9, 0xf24cdc68, 0x801b0d7b, - 0xc81d88fd, 0xefa52ebf, 0xf4beb10f, 0x59c604fd, 0x523c2647, 0x64adce29, - 0xc0f5bf20, 0x239355db, 0x3d05fffd, 0xc1f103ee, 0x09e72843, 0x87cebf31, - 0xcf42b04d, 0xae3d0813, 0xee2c71d2, 0x8ec89aaf, 0x5757f763, 0x0e1b938a, - 0xc7f28158, 0xf9581fb5, 0x07e7d03e, 0x1dfef2d6, 0x9327f92e, 0xffbf019f, - 0x381f2a6a, 0x3d3276b8, 0x7de0fcff, 0x53de7357, 0xaf9514da, 0x1e7d1008, - 0x797f51c2, 0x97c276f7, 0x90e30a5d, 0xefd3aea2, 0x9eeaf9d2, 0x9b7f3356, - 0xc677bd59, 0xc22481e3, 0xe94b454f, 0x9d3d9dbb, 0xe21feb0a, 0xd947032a, - 0x289d4719, 0xe3851c66, 0x165c82f8, 0x71a4ab1f, 0x5314944f, 0xc9db0937, - 0x1c274d9f, 0x55c618e5, 0x9cff3d06, 0xdfd9f829, 0x13f9c091, 0x3d082609, - 0xba28ec83, 0xcebeb437, 0x9b436438, 0x86bdf51c, 0x4ceedef1, 0xd7b0ae71, - 0xa490b3d0, 0x16ed1eb1, 0x3db686e5, 0xf58eb419, 0x49eb10e6, 0xb459b343, - 0xd02512ef, 0xfe0ccdf9, 0xfc4038d8, 0x508f4639, 0xc12c4b2e, 0x77db84b1, - 0xea079d0f, 0xe28239f7, 0xe7635d5e, 0x686efe44, 0x3b8f73b0, 0x4e39fc5e, - 0xda4833e7, 0xcfb12cd1, 0xf3af6d89, 0xd1c67c88, 0x1e2fc233, 0x1c9fe85d, - 0xa0063fcf, 0x25fbec44, 0xe6ad7e5d, 0x86e7788a, 0xdf223d1b, 0xe06c73b4, - 0xef71e928, 0x373e04ee, 0xfc8975ec, 0x974b696c, 0xac9fdf42, 0x5066956f, - 0xfb9f5a3c, 0x829f7f1e, 0x83f662f5, 0x6e7cfde1, 0xbbbcdd5a, 0xc7438b5c, - 0x1f111eb5, 0x01dfe897, 0xbd57d08f, 0xd37814fd, 0x23da7df5, 0xaa735e74, - 0xdf14ecd2, 0x4aef8999, 0xf9fdd06f, 0x199bd78d, 0xd5029d37, 0xc43fce2c, - 0xdd32c539, 0xfba0df2f, 0x3bdf11f9, 0xe99b033f, 0x7bf6229c, 0xdfafc367, - 0x02bf8fac, 0xf6371e34, 0x759bf5bb, 0x2fb3783c, 0x4ca5f9fa, 0x40e6071d, - 0x10f3f90e, 0x1fbe17c6, 0x71c09791, 0xa4e1697a, 0xbe8338b8, 0xeff55703, - 0xe434a9c0, 0x1ef790de, 0x1da3bfc7, 0xdfcd7e67, 0x80499c13, 0xc5ce7109, - 0xe19fe386, 0xf2126e3f, 0xaa2dcfd6, 0x4346829d, 0x077017ee, 0x331f9916, - 0xe7463ee4, 0x3df1ffff, 0x22505ca0, 0xcacf25f3, 0x3a1e31fe, 0x32f5b09f, - 0x7015c6fe, 0x8d75c41c, 0xce35d7d3, 0x2edf111a, 0x571d5a8c, 0x97d7877f, - 0xc471101a, 0x9e4765cd, 0x75627195, 0xfbefe248, 0x5f62c3aa, 0xf6265d5b, - 0x02ad39b5, 0x49bcaea7, 0xbb126a0a, 0x9f44d3c3, 0x6ccb3fa1, 0x7a180f02, - 0x5d2fc432, 0xf09da87f, 0x3e3a0dc1, 0xc9a3d588, 0xf94e5dd0, 0xc9345be6, - 0x472af74b, 0x6abf3f7c, 0xeee4ebda, 0xa83fa72f, 0x22effc6f, 0xf7d1eac4, - 0x0f12fe3d, 0x07bad3e5, 0xb8e21657, 0x38fef347, 0xe6a6f48e, 0x2df37632, - 0x3b13888f, 0x7ca3811d, 0x3f45a4df, 0x6bc96fef, 0x747e21eb, 0x5ec7e302, - 0x3a96f757, 0xbcf9ab81, 0xc09c3abf, 0xb75643df, 0xb0bbf9db, 0xc486d6ea, - 0xdb7fe429, 0xeb1daf65, 0xcb27ad95, 0xc5959f88, 0xad4a3ee2, 0xb38bdc5d, - 0x10b7fdb9, 0x3b7bd77d, 0x2df9cfa2, 0xfba8bf3d, 0xf58f3d06, 0xa3091b6b, - 0xf9f7ffa5, 0x5f3a8d9b, 0x662ebaea, 0xfea9c14c, 0x26afe690, 0xfd7fec7d, - 0xd71d0b45, 0xa5794ed5, 0x6d88ae9c, 0xefdca8f4, 0x268ee6fa, 0xf41af34a, - 0xf93a6477, 0x707351f9, 0x82d2e32c, 0xd30fbb2b, 0xa98dffb0, 0x3afaa714, - 0x225aa6ba, 0x0eb7bbf4, 0xf91c73fd, 0xb7498035, 0x494b855b, 0x25e3a15a, - 0x07b5c761, 0x3e50670e, 0xb7ec97a2, 0x9277ca80, 0xdeacb1b3, 0x12792a7d, - 0xa2bd96e1, 0xed19c21c, 0xa503f732, 0xa4e6e727, 0x3336fa48, 0x6242177d, - 0x9c9e801c, 0xdb230b1b, 0xdb5fff1b, 0x27a4d3ff, 0x289eb6d5, 0x84f837fb, - 0x3efe7cbb, 0xcad07037, 0xbce808f7, 0xc72115c6, 0x347f7457, 0x644b370b, - 0x7ce873a7, 0x3b41227a, 0xbaa0ee05, 0x95256102, 0xb2c38bce, 0x96377fb8, - 0x7d4cf7fd, 0xb84a59fe, 0xcee9ee83, 0xe737cfd1, 0x5bf73742, 0x6a5c0300, - 0x8befe4e0, 0xe5cbc04b, 0x29785b6c, 0x5082f1c1, 0x099fbf88, 0x73ae2867, - 0xe63bfd36, 0xe61ef238, 0x0ce7029b, 0x0e74c87e, 0xc51bee26, 0xd75ba7ae, - 0xf09a59c7, 0xe81d043b, 0x086cee7e, 0x35fbb9f1, 0xbf9fa3d0, 0x3cc75fc7, - 0xb9d1f7dc, 0x3b6835db, 0x208fcc89, 0xeb4f9ff7, 0xa7ade391, 0x198b2967, - 0x9f449cca, 0x7d30ce14, 0x75f2bf6d, 0x4d6dd3f4, 0x35df57ca, 0xe283f7d0, - 0x6f4b73e1, 0xd3ef1bfb, 0xd349627d, 0x97b1bef8, 0x7da6c7be, 0x1de9584e, - 0x001363f2, 0xe6b3ddfe, 0xc66f6437, 0x07e01af7, 0xfb11e7be, 0xf72d06bd, - 0x3df0c67c, 0xedfee335, 0x950ae0ce, 0x72ac6fee, 0xaddff8db, 0x9b8db229, - 0x87ca794e, 0x21bffcd2, 0x6a40fabd, 0x2883c49e, 0x638c19c1, 0x83b2bd75, - 0x2fd69b36, 0x22f7c669, 0xf432fac0, 0x006401ef, 0xb763b77f, 0x1e69ef8a, - 0xa5b43d41, 0x74abf6b2, 0x2e1e1a0f, 0x6f2f0955, 0xf4bcd971, 0xe895ae5d, - 0xdbd30fb5, 0x2ff71368, 0xb16bfb8c, 0x19b46c7c, 0x8daf4a79, 0x77cc7671, - 0xfcda773e, 0xbfe89bff, 0x9324a93f, 0xcbfe6070, 0x3f7c3df3, 0x7758c129, - 0xc3eb8d89, 0x37191af7, 0x6a7dd136, 0x1d31aba4, 0xe1e21ef8, 0xba149ca4, - 0x25d8d51f, 0xa63753ee, 0x9b7fd807, 0xf3fb12fd, 0x4ed2cec6, 0x0e83078a, - 0x6eabdf0b, 0xaa34f974, 0x4421d207, 0x3ef89ffe, 0x69bbe0df, 0xfd21ef98, - 0xed91505e, 0xde5157d7, 0x4a1b9a7f, 0x6169bde9, 0xc0f1126d, 0xe5061ef8, - 0x4e9519e0, 0x7befa3cf, 0xfbe4e281, 0x501c8617, 0x9d995831, 0xb90d7cba, - 0xf8ef8d38, 0x3bea2535, 0x8f5e437e, 0x98b90a24, 0x44cc26e9, 0x71a5577e, - 0xf061e563, 0x8f00bffd, 0x30b1ae40, 0x0030b1ae -}; - -static const u32 xsem_int_table_data_e1[] = { - 0x00088b1f, 0x00000000, 0x243bff00, 0xa3f0c0c3, 0x4aef811e, 0xf1303031, - 0x12d18aa2, 0x6064e3ef, 0x6062e010, 0xfbe20530, 0x330c0c3c, 0x204cf480, - 0x6066e516, 0x1ae20310, 0xc40dde20, 0x19f8807b, 0x1039fc50, 0x1be200ef, - 0xbefd103c, 0xfe0c0c4c, 0xc4081c40, 0x95fc40c1, 0x1be18181, 0x73f6f103, - 0x4c30330a, 0x2ff04715, 0x249fd903, 0xc1ffe7e9, 0xe90c4386, 0xa071df6b, - 0x10acf37d, 0x7b20467c, 0x9aaa15be, 0xcdf85605, 0xbf268858, 0x18bf8d08, - 0x0372fe8f, 0x4d5afe54, 0x81b5b334, 0xcd4909e9, 0x6efc4d3a, 0x40aac741, - 0x3101a9ff, 0x5ff1ad00, 0x000368ca, 0x00000000 -}; - -static const u32 xsem_pram_data_e1[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd5947809, 0xe77df0d5, 0x9926665d, - 0x6c81bc99, 0x44d84eac, 0x4242740b, 0x61db101a, 0x8311688b, 0x9817054b, - 0x264f6408, 0xdac7f520, 0x0040cfef, 0x8b435151, 0x03b45a35, 0x341b0504, - 0x024180d8, 0x2d82e00e, 0x5d6ad8d5, 0xc8a0d2da, 0x1b80931a, 0xcefc5dfe, - 0xc9bef739, 0x82264efb, 0xf5ffffb5, 0xf8f8fefb, 0xf77bee5c, 0xce73ddb3, - 0xe28ef73d, 0x8b94c718, 0xff12fb18, 0xdd98c7be, 0xd71b18c6, 0x2356329d, - 0xcf2d4ad2, 0x03d058cd, 0xac62ccff, 0x9785addc, 0x653633a7, 0x5ef91a87, - 0x4837e412, 0x6de43b61, 0xde549d7b, 0x23e79ebe, 0xa0cfcd6e, 0xc83aa3fc, - 0xdeded04b, 0x5065c0f2, 0x6643b9de, 0x91dbb11b, 0xc2963671, 0xe30731d8, - 0xcf90597f, 0xc9c0ac66, 0xf61be5b3, 0x45f6c5cd, 0x84e6764d, 0x1577cafe, - 0xf20cbcce, 0x86550785, 0x2f37ca55, 0xbe43fad3, 0x60352c38, 0x9f3263be, - 0x1ca7685f, 0x3bf50cde, 0x37292d3c, 0x553b18b8, 0x8d5e60e5, 0x4b776ab1, - 0x18a3f5ca, 0xcf6f092b, 0xf52576c5, 0x3a970f92, 0x97e6c765, 0xb6bae1fb, - 0x97bb3e4a, 0xf12dd2b1, 0xcf923bcc, 0xfff84be1, 0xf91ca358, 0x862f941e, - 0xb7e83275, 0x32e4d590, 0xab5fc719, 0xf0dddd79, 0xd3a5553b, 0x7cbe4638, - 0xed038c2b, 0x7c969e2a, 0x1b0ac4b8, 0xf8c0340b, 0xb39cbbed, 0x7d70b937, - 0x6e11b4cb, 0x1addd75c, 0xe70c2bd6, 0x717a74ef, 0x5cb41b7e, 0xbf592f28, - 0xd5182b41, 0x96e95fdd, 0xd579d6be, 0x980d4d0e, 0x53d3a3ca, 0x47798c55, - 0x184be774, 0xbf4037f3, 0xb36b094c, 0xff7f7746, 0x96322580, 0xcccbfd8c, - 0x1feee8eb, 0x43df4920, 0x013fc16f, 0x6e3da15e, 0xb781ab82, 0xdbfc3ac5, - 0xb3b78ddb, 0xd2a3c0ba, 0xdfee6d99, 0x3c401f48, 0x106a7cc0, 0x11ae904e, - 0x644cf3f3, 0xdfe81493, 0xc4ba67e3, 0x918f5f7a, 0x9f2ca8d6, 0x420b58c1, - 0x78cafda3, 0x116c6bc8, 0x93f631f3, 0xa9fed915, 0x059fbf90, 0x57bce2e6, - 0xc4228148, 0x690d6313, 0x24abbf48, 0xffd71b36, 0x94349c03, 0xf407eaaf, - 0x99af7009, 0x9649bd96, 0x3093dcc4, 0xbdc4f05f, 0x214fd4e9, 0x3f42a3f5, - 0x8fdfcf43, 0xe9639b9e, 0x322dcf47, 0x7ea4a9fa, 0x4fd6179c, 0xeb04ee4d, - 0x8c4b727c, 0x7ea4ee7e, 0x2eb617dc, 0xd6898afd, 0x46515cf9, 0xf54e24fd, - 0x97d400b1, 0x2d607a0d, 0x5dca197e, 0xef6389f5, 0x98ba6665, 0xdff912bc, - 0xa6625c0d, 0x389c848b, 0xfa261d0b, 0xd0f258fb, 0x5bec7e93, 0x44830f22, - 0x5f1a3512, 0x5c91afeb, 0x41dfd498, 0xbbfa3bf9, 0x31dc2e48, 0x0eb17021, - 0x59b1c0f3, 0x816bc83f, 0xe831eb6f, 0xb129e61a, 0x36bd4c34, 0xefcba34c, - 0x261c3956, 0x88dbf80f, 0x683ed023, 0x08911ceb, 0xa4d2f5f9, 0x365c205f, - 0x27c11b33, 0x5895664e, 0x48cece2f, 0x9e9ddd3e, 0x826429bd, 0x8041ead3, - 0xdfbba97f, 0x0d206ad5, 0xbb2b6be9, 0xb6f48421, 0xa7ac106a, 0x854f633f, - 0x14848fae, 0x20a83f68, 0xd769e10d, 0xe3cdbf80, 0x28fe306b, 0x1c19ff1a, - 0x3f8e0777, 0xf6f8e7ae, 0xf1963921, 0x2c8b831d, 0x18343be3, 0x177de81f, - 0x0f8c55bb, 0xd8c09bf0, 0x685ba1f3, 0x22e0fb7c, 0x8d6eff1a, 0x8fc65915, - 0x05ff1aeb, 0xdea5f71c, 0x82643fd6, 0x4b83fd75, 0xf8d7ebac, 0x0b655ffa, - 0xb471f8c5, 0x16875ffe, 0x2e0ff5f0, 0xf3b7ebe1, 0xf7c6bb7e, 0x75ffc174, - 0xdeadf71c, 0xa2743fd6, 0x9517fd75, 0xe76fd759, 0xcacbbfe3, 0x1a2ef8c5, - 0x1950bdff, 0x6545ff5f, 0x0f66be34, 0xb48e90f8, 0x61957101, 0x040d9f18, - 0x19254886, 0x6474a7e5, 0xfda0c61f, 0xe084363a, 0xa71c4770, 0x80e2cfbb, - 0xf2dd5cde, 0xa381858e, 0x08559e40, 0x9fad2f9a, 0xa59ca1a4, 0x0b7b9072, - 0x341754c5, 0xb0dfb4c9, 0x70f0f675, 0x937b6f98, 0x82fcc21c, 0x65879775, - 0xbcd8efda, 0xb0a76c3c, 0xf0ff7e08, 0xcd1bd1a1, 0x174e8aeb, 0x5ac7a8d6, - 0xe7c47c2d, 0x46cc9a13, 0xa6fcc256, 0xeb8c1121, 0x39031fce, 0xbe7e40ca, - 0xd314720f, 0x078c2ae3, 0x9c828fdf, 0x6f999a65, 0x3c7df196, 0x991cdec4, - 0xff827282, 0xbc38531d, 0xc2912d8f, 0xd6cfff08, 0x3e50d22e, 0x0789ac2d, - 0x23cf77a0, 0xb9d4f028, 0x28de1ecb, 0x08bd3c11, 0x15891b9f, 0xa033fb19, - 0xb6801fb5, 0xa5afb6b0, 0xbc2c2ddd, 0xcfea0d32, 0x483f935f, 0x3cdff587, - 0xc6563edb, 0x07f983fd, 0xd98f88d8, 0x630e5b00, 0xaad71bb3, 0xe3732003, - 0x56fdf56c, 0x0139fb53, 0x22e6fe6b, 0x0d5dbe6b, 0x37d436ab, 0x01b6258a, - 0xd2b5bdfa, 0x938c6e5a, 0x78e1f528, 0x20fde315, 0x56f7cf85, 0x67e2c74c, - 0x573af09d, 0xf98d6de7, 0x5952ef04, 0xd6cbf684, 0x4ff84664, 0x9d017aa6, - 0xbe7a3baf, 0x3f875573, 0xf733e60f, 0x19e0994e, 0xbdd6ff3d, 0x18db7ef1, - 0x563f6b48, 0xd7a30491, 0x79ff3d13, 0xa3d7a34b, 0x1f961e93, 0xe9cefe8a, - 0x829e9a24, 0x1efa934d, 0x6f2bd535, 0x51efb2b8, 0x6e957d13, 0x17c96599, - 0xea58e787, 0x5be6d617, 0x14d617ca, 0xafe7ca5b, 0xe7c9645e, 0xd4b4ee87, - 0x9974b79f, 0xcad6fca5, 0x37e52c7b, 0xe4b5ad17, 0xb11e04e7, 0xf671bfd4, - 0x6db94b06, 0x20d725ef, 0x25bf551f, 0x3e37dc33, 0x007b1d75, 0x5d4fc1f5, - 0x71f10f8a, 0xf88d2aa2, 0x979554e0, 0x4ca6f6d2, 0xc1cb8047, 0x16715402, - 0xad086b2e, 0x9972889e, 0x5e2cfc91, 0x1a1433b6, 0xe4adda08, 0xb5c9f825, - 0x09008b1a, 0x174fac4b, 0xa6ca771d, 0x94f3d6f2, 0x67a302d7, 0x5b972cf6, - 0x6e0f7f63, 0xe508bfcc, 0x00f26f4e, 0x3ee006fe, 0xf7f621d7, 0x8932f2e8, - 0x33bf99e5, 0xfcf89cb6, 0x65b3909c, 0x6507971a, 0xcc9bf6cf, 0x8c8f983c, - 0xf1aafca8, 0x28a8001a, 0x4f3b5127, 0x2e007a46, 0x50cbd0b0, 0xedb77f0b, - 0x155e6993, 0xa3c61328, 0x235bc9c8, 0x1c899ca1, 0x68dd7c18, 0x7eff879c, - 0x29aef909, 0xb6f5f699, 0x8f7de9aa, 0x3c9f882a, 0xcd544f4a, 0x5558f4a6, - 0x55a3d280, 0x5fbe9445, 0x6b694955, 0x0f4a52d5, 0xfd288557, 0x4a6ad553, - 0xa1aaabdf, 0x5aaa9df4, 0x1550ff4a, 0xcabdb4a6, 0x0fc1a94f, 0x4937f25d, - 0xaec2abe8, 0xf2879d80, 0x565ac567, 0xe216dd40, 0xf21a5f73, 0x67d759f9, - 0x3f1f5023, 0xa19d8efb, 0xbc1bdfbe, 0x77ade9a2, 0x5f49fa3c, 0xfe030829, - 0x3b967b33, 0x9c9e38e3, 0x819d3636, 0xf867ba3c, 0x46dbbe13, 0x92415e51, - 0x37c90d81, 0xdfa31dcb, 0x75f08c61, 0x7f313c3e, 0x016b98e7, 0xfd1ec71f, - 0x7bf6366b, 0x717fec4e, 0x87da6407, 0x0f936459, 0x1b8265f1, 0x3b9d6bed, - 0x0f3fbc84, 0x82ea3efc, 0x0660cb5f, 0x274904e9, 0x68db3bfa, 0xb1c20a67, - 0xc40c3e39, 0xdc1ececf, 0x5c7e41e4, 0x8fd3669c, 0x918380c6, 0xeba43796, - 0xd3fef32e, 0xad9fcd64, 0x9037a691, 0x5c26f63c, 0x4ae91a3f, 0x430e8fd7, - 0x6a51a7fc, 0x4d38b3f4, 0xbf028fd3, 0x3432da9e, 0x61dfef81, 0x27d60fbe, - 0x5d82bd12, 0xd5fff548, 0x1fade9f3, 0x358c3e63, 0x281c0fb2, 0xe86ca00f, - 0x1e9dedf9, 0xd13e5778, 0xcd5f10f2, 0x2fa867ea, 0x5fffc1c4, 0x157ec10e, - 0x06fd1bca, 0xfd90e41b, 0xdebdf8db, 0xf3b41e32, 0xb637361a, 0x156e9deb, - 0x2ba0cc76, 0x1a1a5790, 0x3a2764cb, 0x92beeb75, 0x9b07c968, 0x7d96e9fa, - 0xfc01ff06, 0x4152820f, 0x541329ba, 0x56b8a1d4, 0x23bf304b, 0x2f013f28, - 0x2bd78941, 0x016ab477, 0x0b63912f, 0xe5b719ea, 0xbde77418, 0xef208ff1, - 0x6546fe4f, 0xdff962f7, 0xae505660, 0xf720c51a, 0x2f9f906c, 0x9635b772, - 0x77b940ce, 0xf9f7c6d2, 0x83cf2c05, 0xab114f46, 0xe73d46c9, 0x8e9b6623, - 0xfb11fff4, 0x64d3279d, 0x1a6cf86f, 0x6afe73ad, 0xfa0b3eeb, 0x585f2599, - 0xb017cd6b, 0xde90536b, 0x2ca9d60b, 0x5a5f212c, 0x9d36bdcb, 0x95642dfa, - 0x41dec8ab, 0xbdc6057b, 0x00ca674d, 0x73f95f98, 0x43e7658f, 0xae363bfe, - 0x7bf61ba7, 0xff3e1f71, 0xe6b0a492, 0x1a0ff287, 0x19707f33, 0x55e1f6c3, - 0x6e42a728, 0x7accdbe6, 0xceebefe2, 0xc6be7a3f, 0x8fc3d27e, 0x6f21e620, - 0x18e1fc91, 0x9b34da76, 0x10adf424, 0xbae037a5, 0xbe6b7a4d, 0x2f918380, - 0x19dfca8f, 0xe9a7ff95, 0xe859892d, 0xc81488ed, 0xfa7325b7, 0x52417d42, - 0x37c0b53a, 0x47ad3fe9, 0xd2ffe5ff, 0xff4207fe, 0xeffe96d9, 0x3ff697fc, - 0x57fcc7ac, 0xfcbfeac6, 0x433b6db9, 0x9e4a6f20, 0x60c3c879, 0xd4a93a1f, - 0xef00f8a4, 0x7a579b65, 0x284e0e90, 0xf3d20f21, 0x3d3cb0c9, 0x46ec3d16, - 0xa23f207a, 0x5da125df, 0xfe84ff85, 0xdf753d4f, 0x3e67dc4c, 0x64eaacdb, - 0x47b16d2f, 0x15afc0ec, 0xd833c58d, 0xe11fca18, 0xc8cfbbf9, 0xd2b26f98, - 0x0f93c967, 0x0dffa0a5, 0x13d84528, 0x2a97d211, 0xc5cc3eea, 0x3ac8287d, - 0xdba2cf89, 0xfae7f8e1, 0xd7cc7c90, 0xc3967a12, 0x0fcf493c, 0x1b04b80a, - 0xa3233bef, 0x72b593ef, 0xfd54683f, 0xd4ffa122, 0xc749dcdb, 0xdf6274c0, - 0x7941df61, 0x8583c069, 0xbd53feb9, 0x4731e1f5, 0x756d3e60, 0x2648f1bf, - 0x767c1938, 0x2ffe61b6, 0x2ef6f79e, 0x9d85db8f, 0x4c2eddd7, 0x424dbced, - 0x69e66b6f, 0xa0f11a99, 0x41b65c5e, 0x73e085f5, 0x4f4db6d9, 0xea768a3c, - 0x70df76bb, 0xdb74bfe8, 0x00987f4b, 0x6aedd2f9, 0x0cbe0cd2, 0x8dd29497, - 0xbffc2097, 0x1e376c74, 0x92f57e4a, 0xbfcd1de6, 0x374fb8ff, 0xefb74a3e, - 0x9ee8d8d3, 0xb0d298f0, 0xc5756b4f, 0x91c34bc0, 0xaaafd45c, 0xa1ae7eb7, - 0xaf72793d, 0x63d352c4, 0x4bc373c0, 0x9c2027a4, 0x4f028f08, 0xaa8b785d, - 0xa0bc041f, 0x14f0373c, 0x9080fe5d, 0x779fd83f, 0xd3f3d114, 0xf95fa3cf, - 0xd70fbb3d, 0xedf4f45f, 0x71c75c1e, 0xf5d392a5, 0xfc532b63, 0x1a916e30, - 0xe529d14a, 0xff1e8bdf, 0xe15bd121, 0xe14c3f1b, 0x9fbfa0f6, 0x50a6f68d, - 0xc2df5c3f, 0xfad037f5, 0xe880580a, 0x3931e8ae, 0xa7e90c2f, 0x3dbe9b0a, - 0xc8645f06, 0x6f8e2f9c, 0xd60b8504, 0x12ed1c77, 0x4efeb3f4, 0x7f266f0e, - 0xfc8622c8, 0x3fc343ff, 0xfe5316ce, 0x93c70753, 0xbe09b643, 0x4ccf6d02, - 0xb77775af, 0x0d4e7e20, 0x1fa2a7f2, 0x9094c82d, 0x25f48780, 0x31bf2bf4, - 0x87e3952d, 0xd16c9579, 0x2980f40e, 0xb7eb1df8, 0x18e77ea8, 0x65f63b4b, - 0x4bf8f77a, 0xef30f8c4, 0x8fbfdc38, 0x86a2b0a7, 0x55bbeb18, 0xf61ef836, - 0x997d1371, 0x7bf39bf8, 0xbf9c3ddd, 0xcf0f7e0d, 0x9fe58e9a, 0x07f9c9bc, - 0x08fee1db, 0x52a48af3, 0x25ebbef9, 0x16760792, 0x75d7c589, 0x6b6be0aa, - 0x302741b9, 0x304a456f, 0xdff60bd1, 0xfe4fe087, 0xd07582b3, 0x832f24ce, - 0x67a79e38, 0x16df067f, 0x251ffe0a, 0xad9ff95b, 0xbbdf7ce7, 0x7da2157e, - 0x3f0d4cae, 0x2bf228f1, 0x8bc867f0, 0xe1e6aafc, 0x1fd74fba, 0xc04dc3f8, - 0x0c1ba7a7, 0xcfcab53e, 0x7a2d3e68, 0xf484b376, 0xa7a7cd19, 0x891b408b, - 0x3df0a7c5, 0xb5169f26, 0x9f953ffe, 0x8faefc06, 0x0f219f82, 0xb463837b, - 0xf3633c3c, 0xe5a33c12, 0xc9bdfc21, 0x9fd27bb2, 0xbd067741, 0xfcb2fc95, - 0x1817f222, 0x5dd06974, 0x741a5d17, 0x62ffc3d7, 0xf9745f81, 0xa005a460, - 0x2a5dbc93, 0xcd6555d9, 0xda0c3cfc, 0x8b203cbd, 0x6da7e4e0, 0x3cbcd58c, - 0x0f9cc920, 0xa21be547, 0xf2a3fbea, 0x03f55179, 0x4b4af951, 0x03a6b2fd, - 0x47fc231a, 0x4becf52c, 0xc41f651f, 0xfd8c87b0, 0x4678d826, 0x0c5d210b, - 0xde50d4ec, 0x0541cba9, 0x1ee0ff45, 0x0ec5ec99, 0x182af180, 0x3d3ea3a7, - 0xb1b9021c, 0xf0edc9d2, 0xd3d3bd0e, 0x8995d207, 0xac99df3c, 0x67b942ad, - 0x7274ef7c, 0x5e47473f, 0xe4d127a7, 0x2cd238a7, 0x0d6edc93, 0xfcb1e9b3, - 0x10a3b020, 0x6f595bde, 0x39ffdce5, 0x5e0d764d, 0x8d68f68a, 0x771343ec, - 0x3d1bb2c1, 0x68e92ae8, 0x6ccd7a1e, 0x55f0bef8, 0x3a558e99, 0x70633ce2, - 0x57e42c5e, 0x89ec99fa, 0xb3f42c13, 0x6ccfe889, 0x82c576e6, 0x08fa5135, - 0x54f4435b, 0xa1a25ae0, 0xe03b053c, 0x973fab7d, 0xe88945f3, 0xb5bd68af, - 0x278f68dc, 0x95df685a, 0x03cb59d4, 0x65da3ec2, 0xcb0649f0, 0x86833920, - 0x42e7da0f, 0x47934f2e, 0xf01b335d, 0x665071d1, 0xb6799e78, 0x9c7c2659, - 0x97e7e7ad, 0xfc4c942c, 0x493ac156, 0x6a701a1e, 0x7ad27e43, 0x3b6d5797, - 0x177d9cfe, 0x3fcecdd2, 0xa439f98e, 0x1ddf3b6d, 0xcff31bb1, 0x8ff83dbd, - 0x29fd67ac, 0x37e49d7b, 0x26ebd8ee, 0xf3d8ef7a, 0x6177c1db, 0xfc9d977e, - 0x3f7b1d75, 0xd7f4831f, 0x845edcb1, 0x1063aef2, 0xf7aa87b7, 0x95a63e7c, - 0x8415d7f6, 0xc6b2a3b7, 0xbfe6a3f5, 0x3092961e, 0xdea15585, 0xf89e37b0, - 0x93bcf829, 0x7b1d0bfc, 0xb80ecf3e, 0xa9eb75fe, 0x1d39e710, 0x59fb366e, - 0xf7225f9c, 0x8f770783, 0xcf0cb4df, 0x69f71ba3, 0xca7ca1f3, 0x831f7f0b, - 0x59e3b472, 0xabb50fae, 0x79e38fad, 0xe1fc8745, 0xdce01532, 0x9fd54c8e, - 0x1194fbb1, 0x62a34393, 0xe4efe5c1, 0x7850b937, 0x4fb70a68, 0x21e1fdff, - 0x73bcb9f9, 0xae121d87, 0x7fc38bfb, 0xd7b0b944, 0xac69744e, 0x32c374f7, - 0xb7ce57d2, 0x7fcae1ee, 0xd0b83a17, 0x0b914b75, 0x7fd4f759, 0x5aff7c73, - 0xa2fcd2f6, 0x9d27a0f9, 0xf283b9ef, 0x9a3edcdb, 0xfbd205ef, 0x7869ff82, - 0xeef0167f, 0xabbaff39, 0xddd7cdff, 0x9d5fde3b, 0xe3aef02b, 0x85f07f79, - 0xbefcd3bf, 0xf4db9cae, 0x0dee94df, 0x9b15febd, 0xa80ccdf7, 0xb8d59d3f, - 0xb2b8b150, 0x19abff7c, 0xc0cafa50, 0xdf388903, 0x37e751c9, 0xc2a6fa46, - 0x92c9a6ed, 0x9641ec8d, 0x907b0928, 0x840351db, 0x496030fe, 0x0321e901, - 0xf5cfde06, 0x0ebbc506, 0x195f1fcf, 0xb147df3c, 0x3bec6c14, 0x97ebcc01, - 0x9ed5bc8b, 0xfcc4b9fc, 0x603a3478, 0xa20ff7f0, 0xa0703b5e, 0xa42f7a4c, - 0xe8beefa4, 0x97bfce99, 0xe7bb1669, 0x0ed5af4a, 0xdab24dca, 0x7f45534b, - 0xff9f18d3, 0x0e149734, 0x0f261c03, 0xfa1269fa, 0x570f2747, 0x5cf90499, - 0xf6815816, 0xb59754c5, 0xc33c06bf, 0xe1cdf719, 0x380d5768, 0x8797590e, - 0x93241c70, 0x70bcf49f, 0xdc1379c4, 0x2f18c232, 0x871f14c3, 0x1f729f63, - 0xbd859df9, 0x904d474d, 0x5aab5c57, 0xb4159f90, 0xc81c3997, 0xe5ec36ce, - 0x84cde0de, 0x2188adfd, 0x032bf80d, 0xdad3bf65, 0x06dfd91f, 0x3e2ebe5e, - 0x537e3c0c, 0x851bbcbc, 0x45ae8197, 0x74ebf20a, 0x62fa17b4, 0x1f9e0cfd, - 0xdce85218, 0x570bd84d, 0xa4291778, 0x50cc0cf7, 0x8e855f10, 0x1cf0aba6, - 0x6893e1c4, 0xd9b7171e, 0x64707f68, 0x91f70449, 0xdfe50ab5, 0x10e3e9b0, - 0x7b2f33df, 0x0c9df4ee, 0x8d7ee6fd, 0xf1e53dc7, 0x7dbf8ff3, 0x8c44e5f9, - 0x2c781417, 0x46afff84, 0x167aff3f, 0x2d380389, 0xa1285854, 0x25bdfa0f, - 0xefc5bef6, 0xdfe3cd6d, 0xfbba5377, 0xdefd5f39, 0x3abfcae4, 0xd8e40e7d, - 0x5df300fb, 0xe1a30e98, 0xfd5db315, 0xaf0e669d, 0x1e1621e0, 0xe42ae3c2, - 0xe139d33c, 0x9ffe821d, 0x99b3d3fb, 0xea4ed768, 0xe5c09518, 0x17b230eb, - 0x385ec282, 0x3e09bccb, 0xa1d7ca17, 0x79fe7409, 0x8ac77650, 0xec2adc2b, - 0x7c625fed, 0x751da409, 0xfb4646ac, 0x1f92758d, 0x60e75437, 0xb7c4639b, - 0x9f86abe4, 0xfe0de04a, 0x8f3c6ce4, 0x842fe3e1, 0xbc6609a6, 0xa938cdb5, - 0x0789e98c, 0x74df7bfc, 0xe14df51e, 0xc23df68b, 0x35b3ab77, 0xfc862f37, - 0x6fc05db8, 0xc82ffee6, 0xf36979ff, 0xefd21b06, 0xcb3675a5, 0x2aa96af9, - 0x6cb1b1ec, 0xe66bce2c, 0x0b3ba77e, 0xf65072f1, 0xb0673c61, 0x88168cf9, - 0x0d182e71, 0xfd1fec4f, 0x9d555be9, 0xdab76bf8, 0xbae11f30, 0x430723fb, - 0x56977a3b, 0x9e6b1a53, 0x9e7cec03, 0xedc3590b, 0xfdffd263, 0xc3a93be0, - 0xf68c9915, 0x7e131d67, 0x63fa688f, 0xb767c744, 0xafee30b0, 0x5ca2af68, - 0x68cf5b38, 0xdc90077f, 0xf037768f, 0x7eccf7fb, 0xb69b8b9c, 0x82f512ff, - 0xc749668a, 0xa50a8623, 0x6d3f4355, 0xc65129b0, 0x6bc3387d, 0xa3eabbc4, - 0xc5f137af, 0xf8215556, 0xfbb0981e, 0xe3f71c66, 0x9ea18d36, 0xd3b17fe2, - 0xc7f8fb83, 0x07c499cd, 0x57ebadbd, 0xa9aaec55, 0x972a3748, 0x30f4d187, - 0x92ce3eaa, 0xf40e4cbf, 0x699afe47, 0x8be25d6f, 0x6befbf81, 0xbc173892, - 0xfe16f940, 0xbdbe4cff, 0x80b7c869, 0xa3e2679c, 0xf90f5abe, 0xbe4b1a96, - 0xa9bc962d, 0x7bc5f708, 0x5e22a686, 0x26aabf17, 0xdb6f92c7, 0xe739f8aa, - 0xb94e2233, 0xdbe411a3, 0xadf24db7, 0x8c5be411, 0x5fbf9078, 0xff0b7ca8, - 0x36dff0d7, 0xd6316f94, 0xf9566bab, 0x08f9a636, 0x8d31b7c9, 0xaf3c4b36, - 0x7c9f3b5d, 0x47af9293, 0xeaa0f8fd, 0x3f418f8b, 0xfe3e84db, 0xc44b888c, - 0xe5ce5071, 0x7f8d3a6a, 0xe2ee72a1, 0xff73950b, 0xe4367045, 0x8c1de2dc, - 0xd27b9ce2, 0x8b739721, 0x939c8177, 0x9cb91e90, 0x7187bc5b, 0x7c945cbf, - 0xbe43d91b, 0x115faa31, 0x4d83ede1, 0x02df0fe9, 0xabf58dfd, 0x1fd4073e, - 0xc6ef2ddb, 0xae5de599, 0x7adc10a6, 0x1783bbc8, 0x0876ef26, 0x6c720779, - 0x68d7ca08, 0x5b35f0fa, 0x8f77c1e3, 0x2bff5e3f, 0xcadf97e4, 0x86f8de74, - 0xbd0f9f8d, 0x1678fe36, 0x6263d7d2, 0xdc848b3e, 0x510aaf6b, 0xe45e53ff, - 0xf1772beb, 0x468af138, 0xd4561fae, 0xfc2f614b, 0x17c27733, 0x78bfce1a, - 0x2152c48f, 0xebcecb3f, 0xf38d27b3, 0xc3233632, 0x720b0f44, 0xbfcfc94a, - 0xf40e6140, 0x72ba97e3, 0x5bfea24f, 0xfefdc39a, 0xf17be2a5, 0xd0abadab, - 0x88fc5dff, 0x46a5e744, 0xe711ab7c, 0xa26e23db, 0x77f91979, 0x6627e3a3, - 0x99a9b88a, 0x1bc294bf, 0x947fc462, 0x7fe6b16e, 0x966ff822, 0x62f04adc, - 0xe331cbaf, 0x5d7a8c38, 0xe0283a70, 0x7ed32754, 0x802705da, 0x27bd379b, - 0x33d3009c, 0xe1ba5232, 0x585bfc52, 0xebef566f, 0xbd16e035, 0x5d7fc36e, - 0x0de9fa2a, 0x7b9c060e, 0x1dc05fac, 0x939202ec, 0xa758f0d1, 0x33b5f975, - 0xe8094e31, 0xe84ce486, 0x181700d7, 0x70d26f2f, 0x47977dcb, 0xd664fd05, - 0xe1829a4c, 0xae30b30c, 0x6a0bca1c, 0x0fdcbd17, 0x1dee31e0, 0x4edc58ef, - 0x0f609b2f, 0x56ec39e0, 0x41c92767, 0x35db0e83, 0x141c07ae, 0xbfddddf0, - 0xf9d93272, 0x7a8e924d, 0x24e23048, 0xae0106b8, 0xa828ff78, 0x8106fc70, - 0x0eff911e, 0x8719f23c, 0x8bc91ee3, 0x635c9dfe, 0x40bc42bf, 0x8e66ccfd, - 0x22586097, 0x4eb164bc, 0xa8a97f3a, 0x84117c95, 0x8206d35f, 0xe19f219f, - 0x93c665cf, 0x58957e89, 0x4c954bf4, 0xa8a965fb, 0xf35ed337, 0x99e7a407, - 0x036caa4f, 0xfbfe1b81, 0x4f3e7a2a, 0x9e34501c, 0xb6bc04da, 0x085d3c21, - 0x77ae4eb7, 0xfba0be45, 0x50794650, 0x39e05909, 0x5f73d1e5, 0x0671af09, - 0x518e90bc, 0xcbe735be, 0x92682f98, 0x9ef4df58, 0x50f3c5eb, 0xef17bf33, - 0x7ffbc239, 0x18b1f24c, 0xba60beeb, 0x8b9e85ee, 0xbcf16e80, 0x8eba37a4, - 0xd23b5386, 0xe9bab7f3, 0xe76735f9, 0xe7a44ca1, 0x43f7123d, 0xce5a2734, - 0x1e763d35, 0x09d5b5f7, 0xeeeb0f74, 0x6df5557c, 0xcb90c6f4, 0x7ed1ee82, - 0xbb37df30, 0xf1821704, 0x141c5ba2, 0x18f347ef, 0xb353f5c2, 0x64e6de7c, - 0xf567d7c9, 0x2edbbfde, 0x37278cc5, 0x3f2323f4, 0xf8c3c71a, 0x6f1826f9, - 0xd178f764, 0x2fe183fb, 0xfabadf38, 0xbad9bfdb, 0x6ebe718c, 0xb590543c, - 0xb88d5e10, 0xe05223a8, 0x73ea2a47, 0xfc4b25d3, 0xc85ccc15, 0x7fdc6fad, - 0x7bdc96aa, 0xa74d2cff, 0xebb774fb, 0xe89d77c6, 0xe2674f33, 0xdbe26f7c, - 0xec7fefb8, 0x5998e7e7, 0x44d6f636, 0xab263fdc, 0xe3eae90c, 0xa1f92a43, - 0xe3ca9e3f, 0xedf9af6e, 0x3e5d0501, 0x3898f0d7, 0x8938cd76, 0xb037acec, - 0x87a8f1eb, 0x047f983b, 0xef132fc1, 0xd5d465ed, 0x5f02f14c, 0xae12dd8f, - 0xa537d4c6, 0xc435e933, 0x219924db, 0x7dfc5ade, 0x7f20b8a7, 0x032c87fb, - 0x1fa0a05d, 0x07b1fb50, 0x9bd63259, 0x33264fe0, 0x27e37c66, 0xf3075e6f, - 0xf6487f18, 0xacdea179, 0x03172e03, 0x7ae47a7d, 0xe0980b1b, 0xab858135, - 0xfe34dfd1, 0x9c3affa8, 0x3be81177, 0xa8a44f78, 0x07b54379, 0x6a25ebf3, - 0x72050c1f, 0x6d9eb03d, 0xbf7267b5, 0xea017285, 0xf5c13761, 0x4eb05ebc, - 0x728861f2, 0x8a5af341, 0x93a82a2f, 0xb6e142e8, 0xbc1cc4b0, 0xfa03b0df, - 0xda1eb6dd, 0x05fee167, 0xbadfb1ed, 0x875e6f33, 0x49e60772, 0xb9f9ebed, - 0xf3b4017c, 0x2dd4bf22, 0xd78afea2, 0xb3ef0c4b, 0x7df3d514, 0xea90e8a9, - 0x7dc6f2c3, 0x3b7ed08f, 0x97ebc603, 0x6450fb8e, 0xca0bdd2a, 0x2fba7494, - 0xf84c1a19, 0x7f1c60eb, 0xf220fa6c, 0xabbc520b, 0x98a0c097, 0x64fe63e3, - 0xb3f2421f, 0xeb4cb7c0, 0x96bcfd0b, 0x236e9c93, 0xe7433aba, 0xde0147ed, - 0x1bf78001, 0x40e55e22, 0xab5a07ce, 0xc2fc5f69, 0x9b9f943e, 0x38a24d34, - 0x8f2c858e, 0x8e6638e2, 0xebe6fae7, 0xe8c33b97, 0xed5d7be7, 0x0fdf881c, - 0xefa76e5c, 0x1cb8dbed, 0x4ad41f6e, 0xebe3f6fe, 0x58f78655, 0x24cbd7aa, - 0xabd78e2f, 0x7e563f74, 0x1431c78c, 0xc7fae36e, 0xdfbcf581, 0xe1b7a8e3, - 0x439607b9, 0x11ab70be, 0xb4e5c0e7, 0xe8167f61, 0x90c2fe3c, 0xdd62e5bb, - 0x75a1f63d, 0xd92434cb, 0x2e5b7968, 0x8b0971e4, 0x2d1cbd90, 0x1cf1cb77, - 0x197c83dd, 0xeae6271d, 0x0e9063b6, 0x5d105f22, 0x19521c57, 0x07d231da, - 0x9714b96d, 0x73a247b6, 0x92cdf18b, 0x8a1ae31f, 0x4987b1de, 0xcfe70eff, - 0x2fee11fb, 0x8619daef, 0x3c431f2c, 0xb1ca9c80, 0xa7e9fe77, 0x1be4fdf0, - 0x02088c0e, 0xb827c9ba, 0x59be711b, 0x4f3c799b, 0x52eb1bd6, 0x9b2f3ef0, - 0x40e497da, 0x02ccad61, 0x52713926, 0x13775ff2, 0xd4741fdf, 0x667c0c77, - 0xb8053569, 0xc1cb7ebf, 0x66ef55f7, 0xd8646315, 0x043d84ef, 0xf51f81f6, - 0x6b5de29b, 0x1d133453, 0x9b59ef14, 0x55f7c322, 0x1aa61e22, 0x576857f7, - 0x8a71f1ac, 0x06fa4af7, 0x3f4638d3, 0x2edabf46, 0x1ee86ede, 0x7fd6f69e, - 0xd68fce31, 0xf286a9f9, 0x1e9fba22, 0x4fd2f7e3, 0xadcfefce, 0x395e6093, - 0xac14cbaf, 0x8cc1f39e, 0x1d73e6a1, 0xcafc3523, 0x98da6fd9, 0x9cbf04df, - 0xbf31c53f, 0xe38ddf09, 0x7f01ef80, 0x61493757, 0x23f984a7, 0xe516795a, - 0x0af3e475, 0x98ae7fe1, 0x1aebcfca, 0x8158de33, 0x4b233f7c, 0xa1607a22, - 0x8937d680, 0xfa2f35f4, 0x78b30bfd, 0x8f6842fb, 0x08f8d8fc, 0x13904fe7, - 0x1523945e, 0x52e6d7eb, 0x8bc93afd, 0xc86e37fd, 0x28a47d27, 0x5e546647, - 0xa3f48477, 0x4923a6a2, 0xb7c0c7c8, 0xa81f50eb, 0x51d76898, 0x68fc1b8e, - 0xe2ebf7f0, 0xe8732b3e, 0xc67ef1a3, 0x8be646ff, 0x21f2d7c1, 0xf583d72e, - 0x39831f9c, 0xdf5f5f9c, 0x2f0ae2a6, 0x9f89bf84, 0xfce16f8f, 0x43763f2a, - 0x2f87de2e, 0xc3efccdc, 0x453f581f, 0x78fa7d43, 0xa6fda258, 0xbd737f27, - 0xabbf9a35, 0x7defbe25, 0xe0d2fd5d, 0xe18f836f, 0xaf1c6aef, 0xef14f80c, - 0xf5f3464f, 0x0fe1b54c, 0xaf7cc3b7, 0x03d61a79, 0xddf29df3, 0x26ad3d3b, - 0x14f90939, 0x3c2817cc, 0x2b90cb9e, 0xfb8f0ae5, 0x8bf3dafb, 0xb76c3f1a, - 0x677e47fa, 0xebf1e44f, 0xfdd12a75, 0x07b3f8f9, 0x7f205d9f, 0x9d5f285e, - 0xf18d3f8f, 0x7ed63de5, 0x2de8277e, 0x8076bfba, 0xfae0046b, 0x8a26fd4a, - 0xa9e8fdf3, 0x3f113323, 0xce81bba5, 0xddeabe91, 0x4e72822c, 0x557ed309, - 0x3dd328d2, 0xb244a601, 0xf99b73af, 0x956dc798, 0x7a26e33e, 0x1ed6792a, - 0x4bed019e, 0x86307e76, 0x779668e2, 0xe85a5c52, 0x872fa129, 0x1f20c75a, - 0x7e3c2894, 0x042e5a2c, 0xd70fdc1c, 0x367e2bb6, 0xc2da4fae, 0x69288fdf, - 0x9bb551b8, 0x746e25ce, 0x3a3d46a8, 0x1d010dd7, 0x9c5dfde3, 0x02ddf99f, - 0x6dac6e23, 0x2513972b, 0x81d92a4d, 0xb7b65b25, 0xc970fc63, 0x77f2763b, - 0xa19cb705, 0x9e5310fb, 0x94fe46d9, 0x396c9360, 0xb711eb7f, 0xd88e45b9, - 0xb1b0ee31, 0x211dce9c, 0x0df2847f, 0xcf97e3b1, 0xfa585f17, 0x219d9ecc, - 0xafe96100, 0x7ca0f49e, 0xd9b2d539, 0x7e877083, 0xba6e32bf, 0xc3669c47, - 0xa7195f3d, 0x01ff0a79, 0x438f738c, 0x9c4635d8, 0xa4be96eb, 0xb2fcc247, - 0x739c62f3, 0xdbe5e974, 0xef1c7d3e, 0x7b3db411, 0x6f9c71fa, 0x7e3e3fd9, - 0xd8c1e31c, 0x77ed275e, 0xa2dea7c1, 0xdda36c38, 0xb5dfb126, 0xe2927d6f, - 0xb5dfdbd7, 0xf6b7b0fb, 0x6307c73d, 0xf6fb603c, 0x6fd0522f, 0x34cf64b9, - 0xd92eebf2, 0xc5952531, 0x148c2fd8, 0x017c36e9, 0xf8d1f3f1, 0x8078d03a, - 0x023ed6e2, 0xebfca37c, 0x286dbb8a, 0x5ecc71e7, 0x1f5b6f11, 0x8f429efb, - 0xebc6daf8, 0xe51cb9ae, 0x1fd7237e, 0xfb671bcf, 0xdbf1e026, 0x7abf8017, - 0x1b102fc3, 0x3fe11f7f, 0xa2fb4f00, 0xe369f7f0, 0x8a3c5fc2, 0x7b7d8d65, - 0x5c8db38d, 0x7b8cdc00, 0xfc380f10, 0x88c91c87, 0x5c525fe7, 0x866de233, - 0x4f9ff717, 0x91fde307, 0x5ce76a13, 0xc7b85fba, 0x68bc63ae, 0x89b79ec9, - 0xbc77da7f, 0x26687e41, 0xb3b423ee, 0x3f1e3fae, 0xd675892e, 0xae7c79b9, - 0xefc63f80, 0x5df43d7a, 0x3a72e9c4, 0x7b77e236, 0x9d95db8b, 0xee36cf5c, - 0xfdd79467, 0x76c3c451, 0x41ca4be3, 0xcaf91d3c, 0x0e036878, 0xddc390ba, - 0xe3b1e871, 0x2beebba3, 0xfe217c08, 0x8aea1f70, 0xc0fc8733, 0x7a37e4b1, - 0x0790c59b, 0xfc781bed, 0xfb1abb7a, 0x9711b05e, 0x3e688ffe, 0x3c585f0d, - 0xffe6f9fa, 0x81d3e175, 0x4f724fca, 0x2dfdb538, 0x774f1cb6, 0x9eecdf4a, - 0x7d149961, 0x1cebca6f, 0x473b7187, 0xbb83b434, 0xdeb16cec, 0x6f57e136, - 0x78a64a7b, 0x070d55e5, 0xcb478e48, 0x2f7c0a8b, 0x337cc625, 0x9a2b7cc5, - 0xf6d13ef8, 0x82ec3bac, 0xeff6da7e, 0xa8ae7a22, 0xd2f1423f, 0x95f96f2f, - 0x8b8a6ad6, 0x6c227dc0, 0xd3db7f9a, 0xdc90c6fb, 0x44b2ef16, 0x8c49338f, - 0x3d8e6c13, 0x8cfeb04e, 0x50d29c65, 0xcebba683, 0xc529de3f, 0x77f6237f, - 0x83eb85aa, 0xe9e41aa7, 0x0fe318e1, 0x77d6aa73, 0xa4bf60a1, 0xfcdc67f7, - 0x13d919bd, 0x12e5fa47, 0x093bce77, 0x146a9849, 0x4cbd55af, 0x87fd77c4, - 0x5df10d2f, 0xe18abeed, 0x7c22577c, 0x551e7e4d, 0x4bd4300f, 0x2cbcb4d5, - 0xcb442bf4, 0xc6c92d1b, 0x2ffc26c2, 0xf54f4f71, 0x644779d2, 0x70f3e220, - 0xfb1571c6, 0x9f944bfd, 0x5b0a2fea, 0xfbf30a95, 0x2df2484b, 0xdfd97e83, - 0xe794183e, 0x977fd9ee, 0xd963f11e, 0xb0aa57e2, 0xbb461e77, 0xa4e0bd84, - 0xaf7906f8, 0x08f9de93, 0xf5a4ee3e, 0xf9f1d81e, 0xff5fa413, 0xb9f8cec2, - 0x202f580f, 0xde750aaf, 0x9f1df1c7, 0xd457fe3f, 0x8c31b19f, 0xd438f85f, - 0x3ea1bb47, 0x8e9cec9e, 0xa0c61367, 0x85f0a45f, 0x3ca266bb, 0xf4e78c2b, - 0x6a4cf858, 0x3bfa1ab8, 0xc7f3cc96, 0x77a20db6, 0x759f4a25, 0x81e8dc53, - 0xe055cf1d, 0x4cfed4be, 0xa97dc33c, 0xe7a105fd, 0x53bc52ff, 0xcd7aab55, - 0x4cc5e3f1, 0xf3ef9af1, 0x12de6294, 0x2fc8c4af, 0xfe847c41, 0xba04a6aa, - 0xaffa0407, 0xd48f9fa5, 0x447c3bce, 0xfcfea1c7, 0x3fa453fe, 0x7ae883ca, - 0xcebdf946, 0x395ee221, 0xd77573b4, 0x059d6a0f, 0x9fd35f3c, 0xaa1693cb, - 0xf853b0ff, 0xcf79458f, 0x87fd797e, 0xeeeefc84, 0x10afb787, 0xd344d0ef, - 0x6fd146ef, 0x5fbf96e9, 0x959deb1c, 0xefa7f318, 0xc858943f, 0x76ca7a86, - 0x857fbd27, 0x7de028ef, 0x3f1a9d85, 0x44f32ad7, 0xdd9b9de8, 0xc5971e42, - 0x9ddde845, 0x581e62fe, 0xd1ccf31f, 0x9fbd34fa, 0x61939cf6, 0x0bf9595c, - 0xbbe23f6e, 0xc7e7e77c, 0x71859e7e, 0x1714f189, 0xffc2fe5f, 0xb7283a22, - 0x3f22e647, 0xb3b76e74, 0xdbe7c88d, 0xfc8c1d5f, 0x0646a6da, 0xf38af9f7, - 0xbb06f2ba, 0x58bffef5, 0xdaaaa9c7, 0xbbbef0cb, 0xa4b6af71, 0x57f33917, - 0x5fa3d727, 0x725ffa71, 0xdf5bbf12, 0x35553a73, 0x59df133b, 0x3897ea30, - 0x77c5cb62, 0x137c5e51, 0x71eaee39, 0x9c5df53f, 0x25ac47cf, 0x153efd05, - 0x3ca377a0, 0x3e92d92f, 0xfb04fd10, 0x043bc69d, 0x8fdc04de, 0xb25eabf6, - 0xef3531a7, 0x7caa2733, 0xf430ca99, 0x54cc8cdf, 0x1b1d1d60, 0x67f414ce, - 0x9cea4718, 0x9dee4b1d, 0x3ad3c676, 0x98f61c4a, 0x09cf9df7, 0x8d0f7aba, - 0x1e3e64fe, 0xee3187f2, 0x724c357e, 0x2f388ef8, 0xbb012bd5, 0x6e97bf08, - 0x79699399, 0xa1a9457f, 0x04a7c07a, 0x4eb662cf, 0x6fc932cb, 0xa5e2bc63, - 0x264a9959, 0x4ffe577e, 0xddcabd17, 0x24a16678, 0x01150bd2, 0x9faeb663, - 0xa2887ee5, 0x7e1039e6, 0x15d3cb1a, 0x86a54919, 0x358e3df8, 0x7502ea50, - 0x5653bf8b, 0x9e4e50c9, 0xe8f6e710, 0x1bb4c2ef, 0xdc92775e, 0x6c620d0f, - 0x07be3a78, 0x4dd04de1, 0x10f153f0, 0x5763e61e, 0x1797192a, 0x93b47433, - 0x7d8050a5, 0x5d54f409, 0xe9133d35, 0x18fcfe11, 0x07a64907, 0xbfa3cfcc, - 0x41ea05fc, 0x3dfca740, 0x70b2efbf, 0xc3188035, 0x3aafc981, 0xe877f199, - 0xccc3bf56, 0x71a5c6f6, 0x68e77892, 0x1731c91f, 0x84ebfeeb, 0x94558a3c, - 0xff09d5b7, 0x4473c1c8, 0xa822ce97, 0x58bbc617, 0xd7521e24, 0x9994e528, - 0x90593dff, 0x3ea9d137, 0xcd1e5ad1, 0xa2d72017, 0xf8206dc6, 0x449fbf41, - 0x5449fbf5, 0x557c9fbf, 0x829c06bf, 0x7c3e8d8e, 0x556562a7, 0x1f1b809e, - 0x06e021cf, 0xef8919f0, 0x9c5b31e8, 0x13879c4f, 0x6cc4e35c, 0xf01f58ec, - 0x4e971e5a, 0x612fb978, 0x41c6276f, 0x865aa4b3, 0x890aef76, 0x97f0d3ef, - 0x63b532e7, 0xf0f883ba, 0xb94e311e, 0xc30af380, 0xbea3d53f, 0x1eaff493, - 0xd5bd9df5, 0xdf5d8b8f, 0xe27cdbdd, 0xb127cf63, 0xe26bfe97, 0x75fff663, - 0x0bc552e5, 0xe786bf6f, 0x49f25db6, 0xf55bd007, 0xd438f2cc, 0xfd8f1333, - 0x70be95a3, 0xd031d33d, 0xa438ef8a, 0xb8b7a06f, 0xd1efd661, 0x7d1bd274, - 0x40758be5, 0xe00fd5de, 0x7f189370, 0xf73f1d6a, 0xf70965be, 0xe87981d3, - 0x8b37fac7, 0x0a3937fa, 0xc470dfc9, 0xbabfdfc6, 0x91eb96a5, 0xa658fcb7, - 0xef1ee9f3, 0x803fe151, 0x2a5d6edf, 0xb1e92385, 0x7562d7de, 0x9e6e3f78, - 0xbdfa3f18, 0xe6f300aa, 0xbd6396ae, 0xd2e9c557, 0xfd1757b8, 0x9602c54e, - 0xb321de27, 0xd4eb3f7e, 0xcd67e4bb, 0x2c7deea8, 0x1ee816b4, 0x7ba04ff5, - 0xebc7973c, 0xe2171462, 0x485c78d1, 0x4f3a20cb, 0xd9dfe433, 0xdc04de91, - 0x307f99af, 0xeff3aeff, 0xa6f4af8b, 0x2a1def9a, 0xef2ce2e7, 0xbeab54f5, - 0xea6f9434, 0xc15fd039, 0x0dced654, 0x39535e61, 0xfcc4ade8, 0x7249be18, - 0xa3094d2a, 0x3cf4545c, 0xaf7a8856, 0xa8c3ef78, 0xd55d25af, 0x0ebe67a5, - 0x4b8e6fff, 0xbc5cbe26, 0xb6f74bd6, 0xdbcf8b3f, 0x7b24f489, 0x57017c72, - 0xed087a4f, 0xc6aeebe0, 0x5cf7a775, 0xf3e6b54f, 0x157dbe91, 0x6ffc8080, - 0x4fce073e, 0xf6df7bb6, 0xa37efce2, 0xf4bbf432, 0x44ef8f84, 0x86cfca18, - 0x887c5007, 0x0463309c, 0xbc46bf8e, 0x6ababa6f, 0xaa2ba524, 0xbc794898, - 0xaf2a8adc, 0xea447348, 0xaa74e917, 0x1a556f77, 0xf95557e5, 0xebe03528, - 0xfbd0d5f0, 0x7c618e93, 0xf02e877c, 0xf0136497, 0xe5fe900b, 0x73a4ab48, - 0x195ea745, 0xd8df77c1, 0x7077d840, 0xc10d7a59, 0xf919d357, 0xe53ea135, - 0x548798ed, 0xf8419dad, 0x564af452, 0xc56fe508, 0x5c228e07, 0x2d4bde9d, - 0xd3da5aef, 0x7fbd46c6, 0x836f051a, 0xb871b6de, 0x7a712fdf, 0xfdfb868b, - 0xe3178b6a, 0xb2bfee22, 0x82295deb, 0x1c43983b, 0xe7e6bfee, 0xdee13db4, - 0x09be7b32, 0xe9eceeee, 0x04fbf704, 0x7016ef9c, 0xa87816ad, 0x46acf016, - 0xa47e53b8, 0x3a44fbc8, 0xc47bd29d, 0x112bb7fb, 0x08ca901f, 0x7d878077, - 0x30c98854, 0xf179ba1e, 0x7412eecf, 0x1fc8dbab, 0xfcf2bb2a, 0x127b7708, - 0x05c3bb87, 0x06ba2078, 0x3cb17bb8, 0x5d54f044, 0x9f50ce1c, 0x15e441e3, - 0x7e267b84, 0xb800f8e7, 0x871f8df7, 0x058270f2, 0xe4d25ace, 0x23fb830b, - 0x124b7f7c, 0xbf0d1e7c, 0xafbf8d24, 0x6f77f06b, 0x88b571fa, 0xef16aeb7, - 0x511c2227, 0xe00879af, 0x4f0e34c3, 0xc8a47dfe, 0x164d28fb, 0xe0357ff6, - 0x161fcb01, 0x19c210fa, 0x73c51fd3, 0x56c93cfb, 0x38454fb9, 0xf2efe1f5, - 0x1b10a4b0, 0x6878cd98, 0x85a5fe2f, 0xc6f31798, 0x4ad7aff9, 0x44aeb23f, - 0x7de903bd, 0xdd6de918, 0xcf0daaab, 0x57a5e43f, 0xcb67ee59, 0x5e89fdb3, - 0x42407f82, 0xc13ee6bd, 0x5e916b87, 0x1edc7e68, 0xe0e8295e, 0xeefef16e, - 0xee7e823d, 0xa0fcfc17, 0x7e3e3741, 0x74cd643f, 0x9498c71e, 0x20ef1361, - 0x4e399846, 0xc0d7d130, 0xd9179834, 0xe94a5e36, 0x8ef64b9d, 0x7e36f89d, - 0x7d23f314, 0x6773be25, 0x9b43bf98, 0xa1f50fd7, 0xd9dde344, 0x39c4de89, - 0xa23d3174, 0x6520f788, 0xc4b64f6e, 0xdab5df7c, 0x7e81dfb7, 0x13e6de99, - 0xafa7f3ef, 0x6be2f184, 0xf54764dd, 0x59cde40d, 0x2d577908, 0xcb0c55d8, - 0xc1707cb9, 0xf44d0bbc, 0x5f8bdf11, 0x595d7547, 0xf64af480, 0xa93fa438, - 0xf844ea1d, 0xe8bdac02, 0xcd487abf, 0xc1fb87eb, 0xfdb18943, 0xb9e2b370, - 0x7593c4bf, 0xb09fc5a9, 0x3b53f54e, 0xde55a27d, 0x43fb13ac, 0xfe56a99f, - 0xcb83f630, 0xc59f7f44, 0x0f147e07, 0x6e729674, 0xa4cfc92a, 0x0fef636b, - 0xc216aad5, 0x47aa39f7, 0xe50ebe73, 0xee6f5c6b, 0x9d187721, 0x8c0d9c83, - 0x2ffe88d8, 0x3396be83, 0x8c42e72e, 0xbac693eb, 0x3ef4867e, 0x9d01f702, - 0x01f71ee8, 0x34c3cbcc, 0x5b949ba2, 0x587fe46c, 0x5eecf825, 0x046b5fc1, - 0x7c803d5f, 0x81df0235, 0x13fa51f6, 0x90eb4fc1, 0x12dd20ff, 0x78f5ce9f, - 0x6197bef1, 0x8c772cc7, 0xab1cf7a5, 0x0fda365d, 0x61ed7794, 0xfb05da17, - 0xf7e8ebc6, 0x7a59dd91, 0x59e58dc0, 0x43c03f0e, 0x91d2cc4a, 0x2f733e5e, - 0xe2abe8b8, 0xf4fd015b, 0x72a2b0ae, 0x949ea47f, 0x451fdec7, 0x9ef453a7, - 0xcb5faa80, 0x70fd3fd0, 0xe113a552, 0x8f3c70fc, 0xcfcdaad3, 0x3e03b826, - 0xe29bc5b6, 0x5f6752a5, 0x1f1ef5d5, 0x2f70ff76, 0x12ec12ef, 0x0c0d82f2, - 0xf92661b1, 0x7bde2b50, 0x1b10de64, 0xcb139269, 0xf432e787, 0x0f94f5eb, - 0xcdcbc8bd, 0x90ae5e5c, 0x434bcb62, 0x65e4377f, 0xd2315cb4, 0xb74d1795, - 0x5d54a7dc, 0x66f2463e, 0xc1ff6c64, 0xfcede3ef, 0xf3e66a1d, 0x2cf7a7e5, - 0xdefd7807, 0x83d42f0c, 0xf7c57f0c, 0x5a27ac62, 0xcab89e3e, 0xf40357d8, - 0xcd02d03e, 0xaff8f0fb, 0xfbad57dc, 0xd5b9e141, 0x9c140fa4, 0xa8b4a1cb, - 0x11f13a76, 0x9318d3c3, 0xfd7c7c9d, 0xdf883d0f, 0x7ce2b5e3, 0xc61abd7c, - 0x1b7da4b8, 0x0e607aef, 0xe3c175c0, 0xe38f9d32, 0x14d90d3d, 0xbcb2c2df, - 0xef1ba7a4, 0xdf0f1e23, 0x31c731ee, 0xe9d4fc14, 0x37bffd47, 0x1f582c7a, - 0x8d537fdb, 0x83bb44ff, 0x5da246f9, 0x675dfa01, 0x9fbff504, 0x18dde938, - 0x18da1f23, 0x8fc733ef, 0xf15be918, 0xdc21ced3, 0x33f78adf, 0xab9dd217, - 0xf4d79d0f, 0xdc7c17ce, 0xc733e863, 0x4547d273, 0x7dc0359c, 0xca7fc596, - 0x098f49cf, 0xf473187f, 0xca271e52, 0x7b94bdbd, 0xd3133c78, 0xd3ff9763, - 0x3d51a47e, 0xb821b4ec, 0xd3daf2fe, 0x2fa5deab, 0x6280f3d6, 0x60bdc711, - 0x79787c63, 0x2059be0c, 0x102f07ee, 0x7d065de7, 0xd0df7f15, 0x465d39b3, - 0xd4f4add3, 0x1fa74425, 0x5fc9541f, 0x87f4015b, 0xd4f4987a, 0x698f7a78, - 0x3d9713d9, 0xf9c00b78, 0x95324393, 0x10739d97, 0x87ffb65d, 0x3bfce28f, - 0xefd2ab7f, 0x70727c26, 0xb7ebc51a, 0xbb9ef78b, 0xedc5cef8, 0x5c5c1bda, - 0xbb9c14ae, 0x8bbbe897, 0x35f3c2ae, 0x7382dbe4, 0x565e900f, 0x4ebdef80, - 0x788f75c0, 0xe8229279, 0x1fb60277, 0xea1cbb92, 0x3e72b615, 0x15431361, - 0x10de8fe4, 0x0637bbef, 0xf2e0df3f, 0x0b45e25a, 0xff50d75b, 0x24c3f40c, - 0x02c85c53, 0x8507fbf1, 0xe584b878, 0x21a5887a, 0xd6f908df, 0x77d6ff4d, - 0xd69ddbb0, 0xc2e91a75, 0xb04e75ae, 0xebdd61d8, 0x73e72efc, 0xb6146fa1, - 0x7579f0e6, 0xe3e7e7ad, 0x7ba7ad63, 0x7da9131d, 0xf1ec627b, 0x1fe317ef, - 0x9bc22aab, 0xbc44ac5b, 0xbe105bb7, 0xd5f7c35d, 0xf627d60a, 0x2aeb4c91, - 0xc4b52dac, 0xe6d4152b, 0x857afbd3, 0xdbb5f3eb, 0x1753fb4c, 0x97fe425e, - 0xc6eb0d27, 0x2e6bfdcb, 0xaea8bc23, 0x7e913bbc, 0x7c553d8f, 0xec5e7bc7, - 0x84e9e397, 0x49531a16, 0x4f76eaf2, 0xf74dfbac, 0x56a9e347, 0x80ec09e0, - 0x0c9e132c, 0x3fb744fc, 0x8efcb9b6, 0xe21cf0f7, 0x509afe11, 0x0a2bf2ef, - 0xe1b1e97f, 0xd7a0a4f7, 0x040fa063, 0xdf7e082e, 0xf5cbc4b2, 0x6f813f0a, - 0x77c63e03, 0x08c2e7d0, 0x379127b7, 0x4e3fb193, 0x5b83e70f, 0x1e82f8f7, - 0xcf5ec526, 0x59eb5d6b, 0xc7a042ca, 0x3eb8d49c, 0xee7afbd1, 0x05c72162, - 0x4f8ba7ac, 0xfa7c2df3, 0x385b9ada, 0x9ffc0a9f, 0xd10f7fdc, 0xbc70b1f5, - 0x7a54e30f, 0x486bcf5b, 0xd062e307, 0x1b10b0c1, 0x8f7ffd95, 0xfe684e0e, - 0x3ee08f11, 0xee15fb02, 0xde4fc5d3, 0xbf3cc63f, 0xfd27e2b7, 0x9aa5f69e, - 0x0ea73b0b, 0xf41df64d, 0xfb277ed2, 0x434961aa, 0x633f815d, 0xa3cf12fb, - 0x6e9fa19f, 0xc6cfe245, 0x578bd2c4, 0xc72e0556, 0xaaea8bf3, 0x8fd1cba2, - 0x973d0aaa, 0xce9b9ea1, 0xd623177f, 0xcdcc7d7b, 0xaab2bbf1, 0x983fce92, - 0x94f4c423, 0xd80077ee, 0x47f24c89, 0x7eab2e2b, 0x1d01a9a6, 0x789adffd, - 0x025540a7, 0xd0b3d3ab, 0x1194945f, 0x1fefc132, 0xb2ee7e2e, 0x8ebf6d26, - 0xe8761ae7, 0x8e60fd1f, 0x8b59ca81, 0x6545ecff, 0x93c05f41, 0x1c731cf1, - 0x124bf06b, 0x46cf13f9, 0x5acf13f9, 0xf30491e6, 0x5b3b0afe, 0x1ce87871, - 0x8fc26152, 0x5f01e02c, 0x5bbb1f68, 0x1e5cebe7, 0x607d21ef, 0xb23645d5, - 0xff09d6eb, 0x2fd0cff4, 0xe851704d, 0xe0c301bc, 0xc096beb0, 0x73c4e1d7, - 0xaded190c, 0xf8dde508, 0x4f4c9762, 0x4f984a1f, 0xf3095e64, 0x1564597d, - 0x931d0fda, 0x3f20ef5a, 0xe69033a0, 0xd67ebc06, 0x84b0e5af, 0x817912e7, - 0xb5ce118b, 0x0bc32872, 0x77217ff5, 0xc1bd6066, 0x1f4ef450, 0xf7845e9e, - 0xf3a60212, 0x8eb421ce, 0x33dcbcee, 0x2552d17f, 0x6feffcea, 0x5fcb9b17, - 0xc62ffa71, 0xf93b5479, 0x1f4960fb, 0x57be7448, 0x94ee75dd, 0x64f2fb47, - 0xd123c737, 0x41d5d205, 0x559d37ae, 0xc87d09bc, 0xf3323d9f, 0x7c3ccb45, - 0xec22bc96, 0x53a03ad1, 0xe832a73c, 0xb7e29863, 0xaf0d1d21, 0x3c66ef81, - 0xfb77d0c6, 0xf079e8b8, 0x31b9fa98, 0xe897183f, 0xcb973e55, 0x7a28e3f7, - 0xf9f12dd8, 0xdced8a87, 0x1921646e, 0x20c73af1, 0xcf05653c, 0x8fe33227, - 0x8d77b5ec, 0x82b62773, 0x0b9e75e7, 0xb9cfc6de, 0xa733e7a3, 0x3c16eef9, - 0xdcd399ef, 0x7b9e3e6f, 0xf8ba29ce, 0xab774c43, 0x51e3fb9d, 0x2250fc5e, - 0xb7a6f67d, 0x21e3545e, 0x46e6f1dd, 0xae609f7a, 0x73bfef9b, 0xf88aa759, - 0xe35d300f, 0x5a6156e7, 0x27cc6ddf, 0xfa2a0df2, 0x84896e1d, 0x721ab86f, - 0xbe18beb7, 0xb9bdd51a, 0x425f3b07, 0xf41a05b4, 0x321b3a5c, 0x5ef935da, - 0xaede79e6, 0xf14e0e0b, 0x838a47fb, 0x6ebdd5d6, 0x58c1c107, 0x7c24d427, - 0xbc49c174, 0xa5c066cf, 0x37f1dd6b, 0xf8fe855f, 0x1cdce4de, 0x790fe8c7, - 0x579f3c9c, 0xc13e9c34, 0x0b939022, 0xb91ffedd, 0xb77afca1, 0xcb4c2eff, - 0x95839d1c, 0x5537c421, 0x0390af98, 0x1c00a517, 0xb8141a3e, 0xd1e11938, - 0xf482f7d2, 0x2e4ec3fe, 0x1ba70e0f, 0x1bab6d7a, 0xc8bd9be9, 0xf7e35af5, - 0x38ed5632, 0x008dff7e, 0xe55e8f9f, 0xcb95cdef, 0x22ee6bde, 0x62ccb2ff, - 0x7a4621d9, 0x1e0df858, 0x7bc4db76, 0xf39d7cd1, 0x79ef0e14, 0xcf74f18d, - 0xd952de6e, 0xbcfdbef2, 0x957e3ca5, 0xae632d29, 0x2b09d8b7, 0xecf75d04, - 0xd11afd07, 0x3a5fccfd, 0xd92dde99, 0xc893e9a9, 0xa738f1cf, 0xfd53f9b3, - 0x4ffdc632, 0x1f912d58, 0x6f51fc69, 0xe7e42b53, 0xc87d1387, 0x5ceff3ae, - 0x97ef899c, 0x3f70b454, 0x28bcaa67, 0x7d203fe3, 0xefdf3f68, 0xe108bf31, - 0x5d7bf2e4, 0x369af3a6, 0x474332b5, 0xe5d5be7a, 0x7f907947, 0xc45dffbd, - 0x30e7e1a7, 0x40e7ddf6, 0xce38c00f, 0x39bc5bfc, 0x0df91f48, 0x0ea53f4e, - 0x5c81c4a6, 0x039857cb, 0x298d54d3, 0x98e34c4e, 0xe5ecd303, 0x9daa7f42, - 0x2783fa45, 0xf7c34f27, 0x9f9bf3c4, 0x17db14fc, 0x927d912a, 0x9bf29e89, - 0xee82fd5f, 0x28f3f9c3, 0x5b5bf74e, 0x39dd8b34, 0xff9ac1ba, 0x9f359376, - 0x33e6b111, 0x03f35a0f, 0x7d266d70, 0x1e1eff73, 0x9a7a529f, 0x1e7defdf, - 0x3c22a060, 0x3e49d9b6, 0xce6d294e, 0xd38778c6, 0x586dbb4f, 0xdceffbbe, - 0xeadceeee, 0xf72577a4, 0xe2c717bd, 0x6a1df092, 0x3f2c46e7, 0x8d90d71d, - 0x4fa845fe, 0xbbb04b71, 0x71bb408e, 0xbd06a5e7, 0x69be2986, 0xfdf83fe7, - 0xf6adce94, 0x9c51c630, 0xd3e4f5de, 0xb7a79f48, 0xec7d200e, 0xc3642979, - 0x70f7437e, 0xf3884ffc, 0xe954e458, 0x7e3dab16, 0x1d01e842, 0xe879b527, - 0xd6b8ba17, 0xc24beeba, 0xa8a77cd6, 0x7d331b7f, 0x10f8c74f, 0xdc34aaef, - 0x7ec53767, 0xc173fdbf, 0xa53d4f17, 0x8b2b7419, 0x37991ef7, 0xe2befba5, - 0xdb73eeee, 0x8e800325, 0x4316114a, 0x4697bfba, 0x0f85db8d, 0x38927fd1, - 0xadfceb2f, 0x5539f04c, 0xef896455, 0xaafbd2e8, 0x4d53697c, 0xed4151fb, - 0xd27c94be, 0xdca5f757, 0xca67da66, 0xb9481eb6, 0xdb6bfa19, 0xebefd0a2, - 0xe279cd95, 0xf8490981, 0xf9c06e5d, 0xe7fa3962, 0xf25e1ada, 0x8bd03d60, - 0xbde39ac7, 0xa5c76b0a, 0xe9f1354d, 0x834ba5d7, 0x0e74ca9f, 0x5a72e79f, - 0x461ef172, 0x1dff2d69, 0x1b86d2be, 0xe11abbae, 0x4fdf9ebe, 0x9e5856cf, - 0xb653fc0c, 0x8fef86fd, 0xc7c1ef86, 0x3e70f9c6, 0x2d24f8d9, 0x3fadbbde, - 0xee76f743, 0x44ff71b5, 0x7b465c34, 0xfdef7e38, 0xe508ab81, 0xa2f7f412, - 0x3fb52c6d, 0xe47d0368, 0x6bd0e4c4, 0xd3954337, 0x570fe1ac, 0x95965c53, - 0x253e809e, 0x373ab7d4, 0xf48dbe4b, 0xb5f67975, 0x97fb5aa8, 0x943a3c51, - 0x8a37b4c7, 0xa27ed6c3, 0x47a57cf1, 0x68f77e32, 0xa25e99a4, 0x119df5eb, - 0x2ab7dfa2, 0xcd720a5b, 0x1d97efa4, 0xd878a1ad, 0x19c871e8, 0xc13b8a68, - 0x7c4bd1fd, 0x027a14ec, 0x22d91c93, 0xcf287c5e, 0x48a7bbd3, 0xa5104097, - 0x5ea9b297, 0x6cb5eb84, 0x4bcfa63a, 0x99640791, 0x33f203cb, 0x79278b6d, - 0x3eb7a6d0, 0xa3a473f1, 0x1e74d1fa, 0xefdc5fd6, 0xe846f36e, 0x77e358bd, - 0x9e74da71, 0x5276692f, 0x8fe9d53c, 0xcb979234, 0xeb138e30, 0xd9b4ed3f, - 0xbd3b5f40, 0x8c64efbd, 0xe06b6e0b, 0x6a9f8aef, 0xfb593be8, 0x9a37fd8a, - 0xf17d8def, 0xdf13fe08, 0x8bf8f54f, 0xacdfb83d, 0xa9d371e0, 0x2a332b7d, - 0x68c9e063, 0x6655a497, 0x79d2bda0, 0x91b7cbab, 0x0ae953eb, 0xc8d3ddf9, - 0xfc2f92af, 0x79e9f749, 0xbea07877, 0xe1faea1b, 0xe5073eff, 0xfc77e88d, - 0xa1ddf640, 0x1f3eed0f, 0xa015905f, 0x03f4e3fb, 0x7cfe3036, 0xa0144585, - 0xafb8f9b7, 0xc93ca18c, 0x25ebf9cf, 0xb05c238a, 0x7c1ebac6, 0x1fbcdae7, - 0x292fe116, 0xb0b8c50e, 0xd68b4a06, 0x718bcb5b, 0xbc50f0ff, 0x94cbc517, - 0x19cb59d4, 0xad1f908b, 0x7b4bfeac, 0xca7db82c, 0x6bf9f58c, 0xa3b9163c, - 0x50f9dc92, 0x95f5a3ce, 0xd20037a2, 0x1cfec49b, 0x6d2733bc, 0x4b1da401, - 0xc82da427, 0x7cee7bc4, 0x8ed3231f, 0x8fbf98f8, 0x45953a57, 0x7177f106, - 0xa58fee18, 0x346452cd, 0xe42c1de6, 0xe3bfcb19, 0x6eb820fb, 0x63313df3, - 0xf35eb8dd, 0xc726f677, 0x10cf71ab, 0x2f2e6bd7, 0xab287013, 0x3afc5bb7, - 0x90a5ea13, 0x7f78dbfb, 0x55da95a9, 0xb7697e34, 0x5ff62bf4, 0x1399b7d8, - 0x68a135f0, 0x798b8c83, 0x878e4ba8, 0x0f75892f, 0xdf80b0e5, 0xf4143743, - 0x107d7e43, 0x02fecff5, 0x9f2439c0, 0x45809f84, 0x5c5e301c, 0xca9e5766, - 0xfcf397b3, 0x8ae04f3e, 0xaf6081da, 0x873a01a9, 0xbde72f9a, 0x471bf78c, - 0x425e0626, 0xf9b7ccbc, 0xb7c42b07, 0x17e411fe, 0xf0e1ca5d, 0x4bcad8f0, - 0xc5d9632a, 0x933fbf02, 0x3e5ce81a, 0xa3ef8bb4, 0xd54eacee, 0x8bfef7ec, - 0xfb094790, 0x4f5ee95b, 0xee890ee7, 0x1d223f13, 0x8fb6fba1, 0x6865e95c, - 0x9e01a7c7, 0x223eee50, 0x5ef815b1, 0xace3565e, 0x9e212f45, 0x787ce2b3, - 0x38de5fde, 0xd1772e49, 0x15beb9fa, 0xcf01b95f, 0x8de75283, 0x0e748b1c, - 0x2d779eeb, 0xe3d0ff7c, 0xb9faf1a5, 0x96d3de38, 0x8f17d287, 0x16f3f1c2, - 0x387c84bd, 0xa1ee8e3a, 0xdcac02a7, 0x8d5d287d, 0xcb1a547a, 0x60fa87d8, - 0x58ef0cda, 0xe43fb9f4, 0xdb24e3e1, 0x50b379e4, 0xf3cb1bcf, 0xf92c7e7d, - 0xae111237, 0xed5271a5, 0x17ce3a6c, 0xe85ea3bf, 0xcb823f40, 0x9529ef84, - 0xea7e3819, 0x69269e50, 0x3c0f8a11, 0x99bde064, 0xd12de9c7, 0x25e9c919, - 0x454a4c5f, 0x1b50ee3b, 0xbf20d418, 0xec340d0e, 0xf48b88cc, 0x792361f0, - 0x2df7617d, 0x5ff7e0c9, 0xfa1b0692, 0xa1d7af0f, 0x513213fa, 0xf5c1beae, - 0x7e5c4ff1, 0xa65f57f2, 0x4fbf8ec5, 0x0a78e048, 0x61638b9e, 0x3838ff93, - 0x13d233fb, 0x2c3ce783, 0xf027da6c, 0x1c734dbd, 0x7ed15977, 0x72841dfa, - 0x01f742d6, 0x71ac1bca, 0xc5c597e7, 0xf3a0d71e, 0x0b1b39e0, 0x1e3225f5, - 0x21d7f688, 0xc2d573a9, 0x4b17ba24, 0x73c13be7, 0xc6990b1a, 0x63eb9e0f, - 0x33cd77cd, 0xaee9fa85, 0x9af5acc7, 0x2c7aa73e, 0xe383d5a7, 0xb4adebb4, - 0x29cf048f, 0x6fd8ced4, 0x90b6c23a, 0xeedcfc0a, 0xe21de5e5, 0x6fa8cf3c, - 0x5b3ed7f4, 0xf8def713, 0x556de8bb, 0x2e007820, 0x219f368f, 0xf359747f, - 0x418b823e, 0x89f0dd0f, 0x7c132167, 0x225baa52, 0x69ede036, 0x7bb86e0f, - 0xc990d814, 0x871f05fb, 0x9feddd36, 0xbbf8e508, 0x8ebe260f, 0x73e2eacf, - 0xd90f3312, 0x42172e64, 0x9d4f7775, 0xfa8bca68, 0x9b43ed5d, 0x340a98af, - 0xb78a3595, 0x27c1e6bf, 0x4e4e595e, 0xdf111a8b, 0xcf3839df, 0xa23bca6d, - 0x8fc82ef2, 0xa8f5e536, 0xf2a8a4f2, 0x40fca8b4, 0x1dcdbf5e, 0x40fb2c19, - 0xd4f83fde, 0x9efbf815, 0x7322fd6d, 0x358f05f1, 0xf02bb6f2, 0xb3cb7cf7, - 0x56d3eff8, 0xc93e4b34, 0xba2b3f24, 0xb55bf3ce, 0x0e10a3f9, 0x1ca32f2d, - 0x74926b28, 0x0d5debd4, 0xc79423db, 0xbb535e76, 0x963f6e06, 0x76a11c35, - 0xd23ff6bd, 0xef7c7c46, 0xdea9f7c8, 0xd89fcef9, 0x5befeb0c, 0x751e76f5, - 0x4e2c0a44, 0x7f7eee48, 0xdbfb6dbd, 0x0a2fbfdd, 0xf9fbdbdf, 0x8d1c900f, - 0xc41e07ba, 0xf9bab8f9, 0xbde380c4, 0x7bd2cf23, 0xdd1c7fb4, 0x03aa16fc, - 0x2cce4bf1, 0x9fdda053, 0x438f8fcb, 0xb4df0b7d, 0x67e37dc5, 0xdc12f852, - 0x81651e8f, 0x5bdc704b, 0xc3ef87cb, 0xac384c9f, 0xef863eb6, 0xf0786f95, - 0x98142be5, 0xeb7761df, 0xb709fc20, 0xf06f094d, 0x7f2b727c, 0x1dff4551, - 0xa0f0e7e1, 0xc83641d6, 0xa6c0993f, 0xeb787e53, 0x3d7f9863, 0x3faf04e1, - 0xac9075ba, 0xf27209a3, 0xdf90a98a, 0xf7e6c7ac, 0x37ae04da, 0x369bf31b, - 0x8453ffdc, 0xfbe32b0b, 0x76335e0d, 0x5b9d3c80, 0x66db6a72, 0x1fdcc780, - 0xdb9c93c5, 0x55dd76dc, 0x50870479, 0xa611c61e, 0x7ed3780a, 0x215d7248, - 0xee1fa27d, 0xf1ba7d81, 0xe2dc1ee9, 0xd2e2fda5, 0x37a8edca, 0x451dcea4, - 0xc7a145fb, 0xddc9e92f, 0x52193869, 0x3ae92fa8, 0x8db2eb97, 0xef5223e2, - 0xf51e9372, 0x033df8a0, 0x0fa23be0, 0x36cbc097, 0x096d9eb1, 0x80f6bfdc, - 0xf3f51a67, 0xc47fe49e, 0x42ca6321, 0xc5a7f24e, 0xf372be91, 0x202b9006, - 0x7989d7d7, 0x097b5baf, 0x466e29f9, 0xfc28f13f, 0x67d7efee, 0xbffeb754, - 0xaef2032e, 0xdd6ebb6e, 0xf33f7f2c, 0x0dbaf6b9, 0x5b90dcbc, 0x7b79d2eb, - 0xad4abf63, 0x3ea4e3e6, 0x5c46c978, 0x28c2bc47, 0xece17b7e, 0xd1971b11, - 0xad2d7ffe, 0xfdfdf99f, 0x5a3f0ed0, 0x7a86c43c, 0xc29f81a9, 0x1257fee1, - 0x89373d60, 0xf035efdf, 0xb74f8c64, 0x907f51e2, 0x3b407f41, 0xeb403135, - 0x0c627d07, 0xfae06e0f, 0x3316d204, 0xad2997c1, 0xfffbf0e3, 0xfdb53820, - 0x4ff4e02b, 0xc947779f, 0x0c379021, 0x7a5f2ffb, 0xedff72dc, 0x23d1013f, - 0x8000702a, 0x00008000, 0x00088b1f, 0x00000000, 0x7dc5ff00, 0xd554780b, - 0x733ef0b5, 0x9992bcce, 0x924c2664, 0x84e3c849, 0x71100840, 0xf0444312, - 0x51888431, 0xd4503b69, 0x20717ad8, 0x9926023c, 0x4b62d5a8, 0x79120cff, - 0x22341809, 0x0281c150, 0x06f55bc5, 0x701a8c45, 0xaf7a8a44, 0xb7ad8ef6, - 0xff7f6c57, 0x4a8f8808, 0xd2f5a232, 0x5ad7fd97, 0xce64ef7b, 0xb6b4a924, - 0xdc3ef9bd, 0xd9cfb3ee, 0xd7b5ed7b, 0xf6b5af6b, 0x4cf5a61e, 0xd8c05c0a, - 0xce6a2566, 0x7c2c64ae, 0x61edf148, 0x67cf07f0, 0xf7fb193b, 0x95d5a0b4, - 0xf19fd8c9, 0xe6c60aef, 0x2729bf7e, 0x8ded0658, 0x61cb1823, 0xcfbbf52c, - 0xd500ded4, 0x7a3f4bb9, 0x3f7c0f7c, 0x8ca97bf7, 0x43ef03e9, 0xf7c18c8f, - 0x5b6dbcef, 0xd2842ecf, 0x793519d2, 0xf986bca0, 0xef7bc056, 0x27435898, - 0xbe0ef7f4, 0x5563097a, 0x35e5bbdf, 0xdbb19136, 0x93632a5d, 0xf8ab5b18, - 0x258a9873, 0xbbe0db0b, 0x644b2cf0, 0x7d63114f, 0x0cd85311, 0x23b875fd, - 0xb8c1175b, 0xf995d71d, 0x1f5fd0c2, 0xef867e63, 0xf7a54b2d, 0x4c3ddc3a, - 0x744bf6c3, 0x0ec24017, 0x19faa17e, 0x5a37e3d4, 0x7814bb22, 0x76c2ce5e, - 0x3e325f6c, 0xf3fa8612, 0x7f7d0e30, 0x0f644a63, 0x8f82cfb6, 0xa371dea0, - 0xfe861237, 0x47622cec, 0xfa763a78, 0x8c1c3273, 0x05acaae5, 0x8228efe1, - 0x2b59943a, 0x0701cdd9, 0x713fcfe2, 0x0f007396, 0x6899775f, 0x3d95a93e, - 0xf437ff4f, 0x7ddbd6c7, 0xe1b0a063, 0xcf6f58ab, 0x3b997826, 0x66f88558, - 0xb803fc1a, 0x89c81fea, 0xcce7c3ac, 0xb1eb8557, 0x479fe9da, 0x5520fff0, - 0xb61ff847, 0x0ab635b3, 0x66d61528, 0x0bfc00cb, 0x43fb5878, 0x37630c00, - 0x978000e3, 0xd670d7ff, 0x2bf3c3a9, 0x07ad0a5d, 0x556df9fc, 0xbc67cd8c, - 0xd4f2fe7d, 0x58899577, 0x1a6b51aa, 0xa5735b3c, 0xef46c7bf, 0xe28f3fb1, - 0x0bfa0da5, 0x25b7f132, 0x09ba44ee, 0xd86977e2, 0xba9defff, 0xfdf0eb03, - 0xf8765c44, 0xfbe074be, 0xf9a3173a, 0xfc3955cf, 0x475535ac, 0xc8fc4afc, - 0xd7c24eb2, 0x713f90fe, 0x724e393c, 0xfcbaf7bf, 0x00be2237, 0x0f74d1ef, - 0x75a545e2, 0x63d7864d, 0x43b06f89, 0xd556dcfb, 0x33e0377d, 0xf349ccb8, - 0x9cdef095, 0x158cbf1d, 0x74ffee0f, 0x8695736a, 0xe9c65ff3, 0x02b72d9d, - 0x62f112e2, 0x5d03a819, 0x63f1642c, 0xe7886526, 0x8445f45a, 0xc247517f, - 0x2fdff4f7, 0x49ef89ac, 0x92ba617e, 0x2ba0bf04, 0xdd70d15d, 0x375f0a82, - 0x373e258b, 0x6e183650, 0x82d5cf89, 0x245d24ee, 0xe2357be3, 0x7c60d27b, - 0xf93d2c7b, 0x99706fd8, 0xdc94f095, 0xfa11633f, 0xf03b21ee, 0x16ddd00f, - 0xdd7a2145, 0x646a5772, 0x3da7f225, 0x19f117be, 0xad157c3a, 0x1492ef77, - 0xdb2bc19d, 0x9441302c, 0x9c9d8733, 0x4a7a4b8f, 0x617a9f90, 0x9f587ece, - 0x9dd5d7de, 0xc1024561, 0xeaebf358, 0xdeffa42e, 0xfde6af67, 0x19d548ac, - 0x618843d4, 0xfe143718, 0xbc032b43, 0x2cc5349e, 0xe0175e34, 0xff09c257, - 0x435fe17a, 0xe8bc80c5, 0xbf1c06c3, 0x9807cb8b, 0xe71a12e1, 0x1d6c29db, - 0x526cdb8c, 0x6f6826fc, 0xb23e3a5e, 0x4361c392, 0x20146a3e, 0x9b589b35, - 0xf7c03152, 0x2513a6cd, 0x36f195b7, 0x85bbde0d, 0xf78175f1, 0x5f002a8e, - 0x4c7d6da3, 0xfa45ba45, 0xd8a5f687, 0xff80345e, 0xf9bff5e6, 0x7cdfc213, - 0x8d1748c0, 0xb1e7198f, 0x8a9e9134, 0xb524e806, 0xd589e392, 0x8018c8b0, - 0xa9ea29d7, 0x8a88b1b5, 0xcd565a78, 0x66e9024e, 0x8199e91e, 0xecace3f4, - 0x0ca1f364, 0x11fcc07d, 0xf74a7b80, 0xc24697ce, 0x58daeefb, 0xb4374e3e, - 0x4e8bb6ec, 0xbeb0345d, 0xba4bce12, 0x41cca937, 0x0077d1e3, 0x83bf7f8a, - 0xfb371bde, 0x6ef2c482, 0xa4d32efa, 0xe0f6bd12, 0xcd1be423, 0x38c0a39f, - 0x328c979b, 0x82a67ae1, 0xbcb9437c, 0xaeec7db0, 0x7f678415, 0x07b7ca09, - 0x09ce80d3, 0x942abe9f, 0xeaeea52f, 0xbfa0bb5f, 0xffd5dca7, 0x138e258d, - 0x47f4e270, 0xa648be90, 0x23bd64e7, 0x6e2ecbdf, 0x0c716f29, 0x17f01eff, - 0x35be2de1, 0x4d0fcb9d, 0xffa2faa1, 0x475cef30, 0x374469f0, 0x222f6db7, - 0xdac0dc79, 0x591ade89, 0xbbf482c4, 0x69c2c6c8, 0xe08b1740, 0x172874b5, - 0x3d32b16f, 0x4496fd61, 0x2146f58c, 0x31616e0f, 0x7d96fefa, 0x2c35ed49, - 0x26f684ea, 0x62a68b1b, 0x6f6c69d9, 0xef417166, 0x3e26b67f, 0xbe7c1d67, - 0x77758b37, 0x20d444d7, 0x1dab7bcc, 0xbe065774, 0x33eb4ed0, 0x5a4ef965, - 0x7f0af4cf, 0x4fa83dd1, 0x76fb355e, 0x27bedd01, 0xe7e24bd6, 0xbbf5575e, - 0xd514f788, 0xdf8ff344, 0x9cfc2563, 0xeb8dbd02, 0xdd9b9f7f, 0xdeca1b3c, - 0x7a3bdd56, 0x55c9a234, 0x1839db30, 0xb39eebcf, 0xb8dd2037, 0xb7c226dd, - 0x65cc7e7c, 0xddd57aa6, 0x522bff02, 0x088abb23, 0x9e9113dd, 0x7d4946aa, - 0x82ce26ca, 0x5666bbfa, 0xe6f509d7, 0xec411deb, 0x07ed07af, 0xb9b817a8, - 0x5b7028de, 0x2eb27e68, 0x06e92be7, 0x52fea1c6, 0x84a5e22e, 0xc85b8c63, - 0x7f89b641, 0xe6eff427, 0x493b2925, 0xafd3f6ff, 0x96fd1189, 0xd7882c05, - 0x795c84e7, 0x3695ca4e, 0x9a2b972b, 0xa832ee6b, 0x9941f73f, 0x95e01d6f, - 0x83de8295, 0x4a3f1bef, 0x5e9e91d1, 0xef5fe8f9, 0x9fb419fd, 0x5ba2c0fd, - 0xd2017da1, 0x73dbac18, 0x6047970a, 0x8fd4307f, 0x38f6c08d, 0xb1c1e36e, - 0xb41c7f64, 0xc846fb08, 0xe0b4c6cf, 0x4fd085d6, 0x3e9993e3, 0xbcf664a0, - 0x5ee8f239, 0xf7643f6c, 0x1b7e81ed, 0x1b5e3853, 0xdf491b9f, 0x4e0f613f, - 0x733cc377, 0x3c9f91ad, 0x05e37281, 0x677bd92b, 0xc2117459, 0xaed3b67f, - 0x70277be0, 0x4250e95e, 0xeaf3829b, 0x043d9276, 0x10b39a7c, 0x36b93bbe, - 0xe04bcf9b, 0x0986e4e9, 0xcd9b17c4, 0xb3f0bc7c, 0xc27fbd0a, 0x0391981c, - 0x974f13f5, 0x534056fb, 0xb512c05f, 0xee873d00, 0xbd5e76e3, 0x7881df49, - 0x09538762, 0xa11eb95e, 0x62678b8d, 0xf2e9687b, 0x1c7ca3af, 0xde51cf8e, - 0xd9b904b3, 0xc805e2cb, 0x461adb4f, 0x9f514675, 0x91f38f74, 0x585e655a, - 0x171ba07c, 0x9994f77f, 0xc87e35e3, 0xbe7cf44c, 0xb57ce3fd, 0x707fae2a, - 0x65c8109c, 0xe48ff926, 0x1d5d4272, 0xfec8ceaa, 0x2d973d0c, 0xfb633aec, - 0x1de0ceeb, 0xe6bfa06e, 0x9de7fffb, 0x38df8465, 0x9ed645c9, 0xca797c49, - 0x748b9fec, 0x5a89aeeb, 0xf3e827e6, 0xeaaf820d, 0x63fec2ad, 0x1f224b51, - 0x6aaaf6ca, 0x72cbdd23, 0x677fa0bd, 0xc1f7cb8c, 0x1fc126ed, 0x1ea2b4df, - 0x6641c29b, 0x1c47a885, 0xfd4ebfd8, 0x6a20f94f, 0xe17a87a9, 0x9165a8f2, - 0x004f9128, 0xcc1b51df, 0x2756d4fb, 0x03406fe7, 0x3268b3f6, 0x48b97d23, - 0x02b5fb05, 0x3d5deb9f, 0x9fa72eb0, 0xfafa7376, 0xf0056023, 0xf7898f3d, - 0x82ef60ac, 0x4da67b1c, 0x607ee289, 0x2eeb16de, 0xb5f2117b, 0x7ae2755f, - 0x8e48576e, 0x569b6bcd, 0x4bea15b2, 0xeb405c0f, 0xd399369f, 0x9b88d2e5, - 0x2114e2f4, 0x11adeb1f, 0x3fdfd90b, 0x01f21851, 0x74764ff4, 0x53947c23, - 0x280f1831, 0x10f40dd7, 0x5d83a849, 0xcb93a534, 0x9cf20655, 0x524bd825, - 0x671ca3de, 0x919ff649, 0x1f52c23e, 0xf4c7b971, 0x527b946c, 0x0aebdf2e, - 0xae49b974, 0xf5c6ce8d, 0x72e4f585, 0x7842bf73, 0xa42d626d, 0xe81ea44f, - 0x91e8571f, 0xeb986ad3, 0x2a26eb2b, 0xd117775f, 0x27594b78, 0x57a913e9, - 0xd783a386, 0x7e0e84bf, 0xed007486, 0xe8b01f8d, 0xe35e3065, 0x9a6d1672, - 0x44e74bc8, 0x4f5c8fd2, 0xc49eb8da, 0xf43ce532, 0x4c7eb265, 0x7ac987d6, - 0xf5c2db30, 0x69675c9d, 0xe74f64cf, 0xe594c076, 0xfcc19511, 0x3ff9a636, - 0x60349cce, 0xb2de84d7, 0xb10bf4d9, 0xe0a3601e, 0xd369c5bd, 0xf686ca6e, - 0xc8fcc690, 0x9780a957, 0xbb7cf09d, 0xb36b7bb0, 0x2d7bdd39, 0x5acd7e9c, - 0x703b9580, 0xcfb4625d, 0x1732678d, 0xe7c4a3d2, 0x577c2776, 0xfd71df81, - 0x8dbdffd4, 0x7c24a5b5, 0x9d9cfd5f, 0xcfe7eae4, 0xb256233a, 0x6e858247, - 0x57eb2fe8, 0x7b53b256, 0x3e92739f, 0xd0fa15ed, 0xd128f683, 0x5fae2acb, - 0x21275d71, 0x648f5535, 0x35cafb48, 0x4a045123, 0xcdc9acfb, 0xf6c1aced, - 0x8a2f6890, 0xcae9cf5d, 0xcfccfb4a, 0x62773ddd, 0x6861e01d, 0x588fff9f, - 0xe981d0e7, 0xe787dfe5, 0xc7c380a1, 0x472c1fb1, 0xdfaab57a, 0xf406deb9, - 0x1e5d4335, 0xd1e60bbf, 0xa170ef94, 0xfc29ab9e, 0x846f2ff5, 0xcc0787fa, - 0xbceb8acc, 0x1b1d7a67, 0x5dfcbc35, 0xe89f3112, 0x5b97e049, 0x4deb19f6, - 0xa87ac69d, 0xc82f58cb, 0x4f4e7a70, 0xfbe1d920, 0xd5b5d033, 0x4ec1f2da, - 0xbcfad780, 0xa7d1f495, 0x067160ee, 0xfc535bca, 0x5ad9e218, 0xf444f1f8, - 0x3fba846f, 0x02b4b051, 0x38cac4ed, 0x3faf91fe, 0x742bcfb7, 0x01b7810d, - 0x899b31fc, 0x3ad60cf0, 0x85ce492f, 0x2c789f04, 0x845f0ffe, 0x9d9a2ff9, - 0x9e9bbae2, 0xaa4e67f8, 0x60927b42, 0x572da164, 0x2dfb887f, 0xae096f78, - 0xf059e9ff, 0xb0d5c01e, 0x46c3eb85, 0xbe434b16, 0xd3bb066d, 0x477c4b06, - 0x5b875f06, 0x5155e2da, 0x8c8edff8, 0xa70871da, 0x802d27f6, 0xfb1ab1f4, - 0xaf93b04d, 0xe07ae0cd, 0xd7767d96, 0xdd1e0329, 0x2ba87a86, 0x912a75c7, - 0x61fc84ff, 0xb8968a79, 0x09577a1f, 0x6bf88b5e, 0xa658f5b2, 0xfc57f8c1, - 0xf79233e9, 0xa7cd978b, 0x5d80c47d, 0xb4f9256d, 0x3d20aef8, 0xdf2b697f, - 0x6ade9e17, 0xa7ef11d7, 0xe3fdf3b7, 0xc4473ce2, 0x857bff06, 0x8bdbdb9b, - 0x19453be1, 0xbc64c78c, 0x55f0ffbd, 0xf7a3a45e, 0xdc2f1f19, 0xf78fedc9, - 0x62af805d, 0xf7f60efe, 0xefd8177e, 0xaaf9e20a, 0x2e2e510f, 0xd0faaede, - 0x9c87604e, 0xbc598fe4, 0x0b71cafd, 0xa7dfd81d, 0x5fa1a623, 0xe895c768, - 0x02f7c289, 0x89d7ee11, 0xb5cf015d, 0x1d93171d, 0x95bb7477, 0xedb6e9c3, - 0xf15c79c5, 0x4af89527, 0xda20b133, 0xff161dc7, 0xfd67e438, 0x70333de1, - 0x959fde5d, 0x1ff7a26b, 0xf10b9857, 0x85965ee1, 0x5a2b17cf, 0x61b7f900, - 0x899992cb, 0x866a4ef6, 0xad35eb4a, 0x8f567970, 0x7ae9f883, 0xdb4da3d4, - 0xfc707f81, 0xf2ff6fd9, 0x3f224f46, 0x4cc55edd, 0xc3cbf609, 0xc27a235f, - 0x6be028bf, 0x57d7c0b1, 0xaa6b2be5, 0x12968be4, 0xef8ba394, 0x0d71296e, - 0xf3f45761, 0x0f9cc3c5, 0xb850cbef, 0xc32f20ff, 0x6e18cfb0, 0x3528e65f, - 0xf9b15e91, 0x940f7f98, 0xc62db0d9, 0x0c81f7fd, 0x640fda8d, 0xfb5f7b70, - 0x5efb6ddd, 0xcd4d7987, 0x80cf6e08, 0x97f3217a, 0x71ebbae3, 0xb1983557, - 0xbbb26288, 0x6e56c3d8, 0x8edc6ac7, 0xf6c99cde, 0x8fd84bae, 0x997f6277, - 0x62f61724, 0xffc7bd3f, 0xdaf10c78, 0x44f1f05c, 0xe7420fb4, 0x1fa0b33e, - 0x90add1cd, 0x02f8773c, 0xd425e90c, 0x282d8b3d, 0x21c3901b, 0xc913d71f, - 0x0653faf3, 0x3c84efdf, 0xfde7ea71, 0x3b7f9c11, 0xb73e9cdc, 0x3f214b2d, - 0xc44f36e4, 0xb5ff408e, 0xa5ed2a7c, 0x67efc225, 0x5f94fddb, 0x288efa45, - 0xd75831ae, 0x35f47f39, 0x30a88dcc, 0x8bbb87ce, 0x77d9dfc9, 0x854f9a60, - 0x1feec736, 0x788519ad, 0xf0fb32ea, 0x27af877d, 0xe1f7e70d, 0x386993ee, - 0x2add86bf, 0xf221bbcd, 0xb2c2d649, 0x33f0b901, 0xca3af825, 0x1c52e601, - 0x0f94be38, 0x34feee1f, 0xfb83816b, 0x567f480b, 0xa7978d0e, 0x8e7ed3dc, - 0x39715fdf, 0x1e8f975f, 0xee5046b7, 0xfd07647d, 0x3f6f2096, 0x777d7272, - 0xefee432a, 0xdf500b3a, 0x2a6fd7f4, 0xf89ca135, 0xdfcf8b8e, 0x402ce963, - 0x628dfc7e, 0x1ae967ec, 0x6c808b13, 0x5006b25f, 0xa3e8f203, 0x40299f47, - 0x9ee1ff79, 0x27e60a67, 0x9dfc97c0, 0x78e57b2c, 0xfd266fc2, 0x344b1ea8, - 0xef9bc70f, 0xe57f72b3, 0xf9547e30, 0xfdc2db3e, 0xab3e7da1, 0xbf28748e, - 0xf1486beb, 0xc7db7da3, 0xe6ff246c, 0xacbf0b77, 0x83da3fdf, 0x7df918fb, - 0x1e15ff52, 0x974a4f4e, 0xd483fe42, 0xe3c938b2, 0x7bde59bf, 0xe4133d60, - 0xbff3ac3d, 0xd9345f21, 0x3246c7e2, 0xe20b0fa2, 0xd0ecd2cd, 0xad653f50, - 0xbf15f4e4, 0x2afb44c3, 0x81d7ae4b, 0x928aecf2, 0x30133694, 0x6d2527a2, - 0xf201c622, 0xfde94b73, 0xfba73570, 0x7f231670, 0x516b0e5b, 0xb8bb5e48, - 0x326f3edf, 0xea83ad73, 0x9edc11ac, 0x16df32f1, 0x5dd698b5, 0xc490ff41, - 0x480bd487, 0x3f1f283f, 0x3f446c52, 0x7642b74a, 0x9cea6aa7, 0x470efd8b, - 0xc847134f, 0xa7a73ffd, 0x893ffafe, 0x188f269e, 0x3a829e8e, 0x36d793d1, - 0x3f093d34, 0xcfbf79f1, 0xbfdc01c2, 0xdd7c0b66, 0xfc4ee427, 0x9bf49b0e, - 0x99df382b, 0x3699bfa2, 0xfd455447, 0x9c7f33e1, 0x187dffe8, 0x27dc5fec, - 0x0efda0e5, 0xf395c8e5, 0x16375a74, 0x417f41eb, 0xd236c5ea, 0x629af78f, - 0x64af6845, 0x8fd96f8f, 0xb73d9174, 0xed2562ac, 0xa8dcf2ff, 0x92b7500f, - 0x7559741f, 0x0488d4e0, 0xdf10e17b, 0xe5df34cf, 0xbbd3e7a7, 0x1a107db9, - 0x387b216d, 0x7184a5d4, 0x96039b9d, 0x6b41da08, 0x095fee15, 0x3cebb06f, - 0xa0afa3ee, 0x740fcfb8, 0x488a171e, 0x8ecf6fff, 0x35bd23ef, 0x91efc838, - 0xf83a3f1c, 0x1fc7ca85, 0x8efc68c3, 0xeaaf1e72, 0xfee75ab8, 0x1d7eb115, - 0x6e39fcb3, 0x18d607b4, 0x85c659f9, 0x18809cfa, 0x7afe6f18, 0xae43ad3b, - 0xd2ccf1ca, 0x0cff5c6d, 0x67e40b96, 0x162c9ace, 0xfa6fc446, 0x05241cf9, - 0xbb4573d6, 0xcb39378c, 0x79684502, 0xb7e9bbbf, 0xbd00a4af, 0x8e9fa166, - 0x68c2ca6f, 0x987f93f7, 0xfc7dc9d7, 0xc90009a0, 0x5cffd6c5, 0x42697357, - 0xf03fbc5d, 0x6b6bdcfd, 0xf6ef48f2, 0xa0d823b7, 0x6fdd658f, 0x351e31d7, - 0xbd81aed0, 0xf852eb6b, 0xb5c761f7, 0x3c068e57, 0xfffc7228, 0x7f47eb5c, - 0xc6199da1, 0x4b4f844b, 0xfd0cdfea, 0x7ef9743b, 0x784af6bc, 0x590ac1e1, - 0x1fad66bf, 0x6ccfbbe0, 0x2a508fec, 0x1c8ac7be, 0x6dacd6ef, 0x0de7d6eb, - 0x276005d8, 0x39911aec, 0x7eac1f60, 0x85fb667b, 0xebaa5630, 0x5dea0b53, - 0x1e43e7a9, 0x648fec85, 0xe4203d7e, 0x572cdfc3, 0xf47641f5, 0x57241181, - 0x4b20667b, 0xe483fec2, 0x80796876, 0xf6073da1, 0xdbc21748, 0xd3e3fc7b, - 0xef7b422f, 0x1b1fdfec, 0xb77be3a9, 0x37bb45ce, 0xba234e74, 0x2353ed0d, - 0x4dadd00a, 0x71e80bf0, 0x7a480b8a, 0x7412ea5a, 0x8c330eea, 0x521c7473, - 0xbe898526, 0x83ae0a5a, 0xf8f7ccb5, 0xe438425f, 0xde7932be, 0xf7c11ebf, - 0xead2a10f, 0xffd825ad, 0x9da1856e, 0x44f4aeb0, 0x37da02d6, 0x30b59bbd, - 0x5d25bbe1, 0x973e120f, 0x890f33ec, 0xe08f5fc7, 0x67e6de71, 0xdca3f69f, - 0x90a228f8, 0x22d0684c, 0xbd40a76b, 0x9684c1a1, 0xcc8cab20, 0x1ce291bb, - 0x06361675, 0xed0477e6, 0xdf638426, 0x7053c337, 0x814ff0de, 0x8b02db47, - 0xab6e9f48, 0x4e2839b3, 0x56ff3a54, 0xc52b83c2, 0x5758788f, 0xe3839d5a, - 0xe19acf34, 0xd808f8a2, 0x7cded871, 0x2fc8b7d7, 0xd75ae124, 0x3b45ae65, - 0xb9ec0aa7, 0xfcee00a7, 0x7d6a6b8c, 0xd523c7c0, 0x3bb7e5fd, 0xb43e5e30, - 0x266eff1c, 0x25368ba7, 0x2546fe10, 0xa25941f9, 0x8bb0b35f, 0x8d9f8ddb, - 0x2be218b0, 0xf6e08d9f, 0xd8e1a5ec, 0xc39f2474, 0xda2a4f5a, 0xffe621d3, - 0x2ccff704, 0xd0f7d0e0, 0xe479713a, 0x3fc9d569, 0xdcf4f366, 0x5fb6217b, - 0x85fed1aa, 0xe00f3d69, 0x3d6bbdb8, 0xf04c75be, 0x2aefd601, 0xbd4f7da3, - 0x3278a827, 0x7d70bcf9, 0xaabd9f7b, 0xd288fd1c, 0xa8fb5aee, 0x5ae6f49d, - 0x2d7f7ea7, 0x69dfd3ca, 0x16c01f3c, 0x7e874d8f, 0x833efe96, 0x8f6b5dc6, - 0x0ff5c5ac, 0xbda954ef, 0x607411d8, 0xb9be4bbf, 0x2bd22265, 0x504a4473, - 0xed3d9a8f, 0xb618e90c, 0xb12fe42b, 0xe30c0279, 0xf3c3d3c4, 0x45f50534, - 0x1d333d92, 0x5fb455fd, 0xb6bf90f1, 0x18c7f05a, 0x36d382a0, 0x3fb68562, - 0x6fb0188f, 0x1ce3f95e, 0xbb4a1f0d, 0xfee364c7, 0x14ba9af3, 0x5b2df686, - 0x42663f15, 0xc627bd7f, 0xea6e0ed0, 0xa69c6854, 0xb82d27d2, 0x93a5b96f, - 0xec4877f3, 0x057f0033, 0xf18c5768, 0xa07b0aa4, 0x5839fb8d, 0xc448d8ec, - 0x3d7c63f3, 0x12f78319, 0xad8cabfc, 0xf440f2e0, 0x86711167, 0x0257e126, - 0x3eed484d, 0xef5bb48f, 0xf3b7fd16, 0x59bb8c52, 0xc455f989, 0xf062b96b, - 0x2af2cb87, 0x91fa7df1, 0xdfe40cf8, 0xfa17d038, 0xb32ab697, 0xcc29fd6e, - 0xf1a4eb6f, 0xbcc1343e, 0x056a4e40, 0x0452073e, 0x7d7657bc, 0x86e90332, - 0xd7e232d5, 0x6a69aee6, 0x6fc78393, 0x4ec85ed0, 0xed89d96d, 0x929737d9, - 0xc8f8c67e, 0x35fe786c, 0x1cb3e70f, 0x79d7f707, 0x61170eef, 0x48fd33bc, - 0xe29fd6e0, 0x90a417f8, 0xd61b35bf, 0xe54199c6, 0x796ff41a, 0xa88bf959, - 0xf533bd7f, 0xc647840a, 0x382e30f5, 0x38e48cab, 0x8a7c33d5, 0x3794177f, - 0x0e34dc78, 0x116aefec, 0x711e7c5e, 0xd119c40c, 0x62e3876f, 0xdecb0f1c, - 0x7e46a89c, 0x7be7d07e, 0xacbb4e90, 0xccd7c42e, 0x42df97ae, 0xc6d33b7d, - 0x9aee293a, 0xd3c4b764, 0x3a4419be, 0x7a733bed, 0xd7083dc7, 0x947d0775, - 0x8f6492cf, 0xb739715c, 0x93da3fcb, 0xec3f23aa, 0xec1b7212, 0x797f1e47, - 0x9323ef9c, 0xf6efc8ed, 0x23b72faf, 0x777febfb, 0x17c3923b, 0x28f3c3de, - 0x890f7ca4, 0xc35f5f7d, 0x5fd434d9, 0xaed23d2b, 0xd8f7ca4d, 0xba3df22d, - 0xd0f7ce87, 0x0ff8f276, 0xee494186, 0xae222dba, 0x43cef7e5, 0x84bb87ff, - 0x7b2bc0e4, 0x3748c353, 0x64ed3b67, 0x4b6e6997, 0x7b6ae114, 0x3cc11ada, - 0xe0453688, 0x578890eb, 0x2c1c4459, 0x834744a3, 0x4025a0e2, 0xa4fc3f72, - 0xd2abc799, 0x85ee8f22, 0x1ce1e37a, 0xd462cf11, 0x54d9f87f, 0x8a6377c2, - 0x37fd8e9e, 0x8608fbfe, 0x183eaa71, 0x09f9d70f, 0x87bb707b, 0x7fbc5ae2, - 0xe75582f6, 0x8968b3f1, 0x33b0f01b, 0x93bfedc2, 0x05a8a6a5, 0x8993bde6, - 0x32f59f3c, 0xd9e7c5ae, 0x8f2461b7, 0x8231a0cb, 0xdcb5b2fb, 0xe32f545f, - 0x1fb98755, 0xa5c45eae, 0xf45ece4e, 0xb458a608, 0xb8b52d29, 0xdd7cfb4f, - 0xdf9ff234, 0x2a2cff79, 0xfd18d7eb, 0x3fd08bfd, 0x3f103c5f, 0xf9f77e96, - 0xf6e167cc, 0xd0ff80f3, 0xbe8cf604, 0xfd46ab46, 0x775cc459, 0xc3d03ea3, - 0x43177ab0, 0x1a2506d9, 0x19600af1, 0x7ad6d3de, 0x57bd7052, 0x6f4899b7, - 0x7e4cdb85, 0xcbd24f7c, 0x67ae1eab, 0xbd70f5df, 0xe08ea803, 0x336cb238, - 0xe883788b, 0x4533056f, 0xbc2934b1, 0x6ad2ed5c, 0xb2dfd287, 0x8b7336bf, - 0xcdda1a6d, 0x77f226f9, 0xd7f16e7f, 0xa338bf91, 0xcda9d684, 0x96a6b2d9, - 0x7d2f13b7, 0xa8078f6e, 0x1b8d32fd, 0x40cf4c96, 0x8782fa79, 0xf19217c7, - 0x58ddb0b6, 0x2cc38e4f, 0xf5eb1889, 0xa736382c, 0x120dc798, 0xf420bf9f, - 0x8aebe7c4, 0x167dbe04, 0xfe72bb94, 0xde38f22b, 0x1cbcf94c, 0x875d5f95, - 0xe30a3074, 0x725845ca, 0x84cc2abf, 0x99751fe0, 0x48fa2147, 0xcdcdb782, - 0x96bc29e9, 0x5aff21fb, 0xfee193f8, 0xf82593d0, 0xb8c5efd8, 0x42cbbd65, - 0xf5f3e871, 0x1a64a497, 0xf5fdb7f7, 0x96feffbf, 0xaad7e7ef, 0x45c6bf22, - 0x8bbe6972, 0xe2a4e5cf, 0xe7c51bdb, 0x701fb00e, 0x0ad56b1e, 0xbfd32394, - 0x3479a0e9, 0x8239061f, 0x3de5ac71, 0x9bd7a805, 0x304a7bab, 0x5f8c935e, - 0xf2935684, 0xef9bde0c, 0xda08fd81, 0xf18c6b0d, 0x55f1c1b8, 0x2666617f, - 0xee4e7bee, 0xd7f5197f, 0x2fe93b7e, 0xad17bff8, 0x16cfffc8, 0x388b5c91, - 0x2e316383, 0xee894a14, 0xda1171f8, 0x6a8edc31, 0x44eeb6ea, 0x5b7e713b, - 0xff0f7c42, 0xef18deb3, 0xc8326b63, 0x8c3aceef, 0x4e1e1bcf, 0xfc506efa, - 0x65d69daf, 0x0e3825b3, 0x10f41df9, 0x599c1de5, 0xbeb86262, 0x116faaf5, - 0x7633a92a, 0xc67e7da3, 0x466bd7c9, 0x3e3fd4a6, 0xebfabfb2, 0x57d9d683, - 0x6f5ceb82, 0x7ec4c162, 0x619d709a, 0x3ac51b7d, 0xe2fa799f, 0x8fe75c12, - 0x825c5ff7, 0xdcd9bceb, 0x29be47ee, 0x41af0775, 0x32ba9cfc, 0xe615f640, - 0x9d1f20ef, 0x94de3d2f, 0xfd378f44, 0x2eb1e8e3, 0x59321f31, 0xe3f4363f, - 0x3d1fa8cb, 0xe50f3d16, 0xf59b7cc1, 0xfc49ea2f, 0x679fd21b, 0xe3ff92b3, - 0xdd3f1ff0, 0xdd18f948, 0xb227d92a, 0xb05ac3bf, 0xc3a3ed18, 0x617d796f, - 0xd3fef865, 0xb5e5fd85, 0x59fa30b1, 0xda40bee4, 0x78f2c997, 0x03cf98b9, - 0x8cdffe99, 0x3ce21bf8, 0x20dc7fd2, 0x3e45b1de, 0x6eef76e5, 0xc7fdc7c5, - 0x6e4fe49d, 0x85cf343e, 0x220fe2fe, 0xfcdc7fdc, 0x8ff93974, 0x8a5e4497, - 0xeb193e62, 0x1fb85c56, 0xddfbb259, 0x9003cc34, 0xe7d85efb, 0xf9499fde, - 0xeffdc635, 0x69939107, 0x70003798, 0xa7708fbf, 0xa416e27a, 0xffd866fb, - 0xb360de61, 0xfd863f16, 0xd9187b36, 0xc65d9505, 0xef8ca0fd, 0x48580b6e, - 0x56eb6eee, 0xb3af2822, 0x3ca2c12c, 0xcf2c6bd4, 0x80753a75, 0xfe9922cf, - 0x077e9017, 0x5dfeeae2, 0xa7fe9758, 0x44e9ad9e, 0xe6663dbf, 0xdb3ca177, - 0x4cf214ea, 0xdbf6f923, 0x7591dd87, 0x6fc37609, 0x584edc23, 0x34c1f322, - 0xbd60d516, 0x1ff1cd16, 0x7946f5c7, 0xf7924d1f, 0xaf197589, 0x494585bf, - 0x9eb1352f, 0xc4b0bcfe, 0xf9e392f7, 0xf4370718, 0x75ca5ac3, 0xe4dd93f4, - 0xab9c51f0, 0x6356cfeb, 0x9bef987b, 0x55961f81, 0x5cafd00c, 0xcdbf4907, - 0x6a1d1fc2, 0xe90ab138, 0xb8a5d437, 0xe8dd7f70, 0x08dbf4e3, 0x9bcc2ffb, - 0xd677e64d, 0x1d13cc69, 0xdd7fff8e, 0xff9c77cf, 0x9cac3d7f, 0x5bf8c7fa, - 0x3f97efdf, 0xfce5ef9c, 0x7fbeffa5, 0xe70add9e, 0x2579a4cb, 0xfd935bef, - 0x79df72ee, 0x8bf0f2be, 0xf17c7c24, 0x70c7c60f, 0x6b2530f2, 0x7242fde8, - 0x96afe35c, 0xf8e0ff87, 0x1e8723c6, 0xa881334a, 0xf6145258, 0x6fcebb72, - 0x50cf1788, 0x371e7e1d, 0x453e7955, 0x9f5ddc72, 0x9ceee221, 0x5a7a5f9f, - 0x126af5a5, 0x43a6e1f1, 0xdabe1f4e, 0xf14c58e0, 0xe9f8e4d9, 0x067fb652, - 0x1c72512e, 0xb8f911b5, 0xa9e3cbf8, 0x3d396517, 0x56749f24, 0xc90a7984, - 0x392f5a79, 0x4c111d3e, 0x32eaef58, 0x410c08d8, 0xcc2d36d7, 0x4f9e1232, - 0xf4f6e2cb, 0xc89f224b, 0x05e7e16b, 0xfaa673ee, 0x35e31f71, 0x7ca77cf1, - 0xd67a604f, 0x02ef9424, 0xc0decf9f, 0x4797804c, 0x4f249dcc, 0x1f0e4dc2, - 0xc7e93fca, 0x10effd91, 0xa5f38b71, 0x19676ff3, 0xfebfbce9, 0x85fbe24f, - 0xdaffbe92, 0xc016ddb8, 0x181f818d, 0x186befd1, 0x4c1a2a67, 0x33f5c3b7, - 0xcb2efd1c, 0x459edc0a, 0xa44ff178, 0x94f3e6fc, 0xf195a92f, 0x622fe893, - 0xfa3aac07, 0xfce26d37, 0x239f5b0b, 0xaabeebf6, 0xcd979459, 0x73c88fcf, - 0x8fd9c336, 0x9ff9fb1b, 0xf5fd8fdb, 0xc8fd93bf, 0x9c7681dc, 0x7e69a9e7, - 0xed5ffbca, 0x5f71f804, 0xc875a8f8, 0xdcf22cf3, 0x5df997c5, 0xcdc3f6f6, - 0xb0ef6ae9, 0xe563ff70, 0x34ff93e7, 0x34fbf9f9, 0xdf0ea3f4, 0x7be4584f, - 0x9e22fcc6, 0xf82576c6, 0x9e3143b7, 0x8092f7af, 0x447f3e57, 0x6cf4c5e8, - 0xa75c51ff, 0x6cdb8f8f, 0x9e4c1d2c, 0x9b172e4a, 0x2f8a0e03, 0xbcf27734, - 0x8ce5e697, 0xfa3377e4, 0xafd0cb4f, 0xbda18b38, 0xf8233537, 0xf57efc33, - 0x9ab08edb, 0xd9f77e8e, 0xdebbed0c, 0xa9febce3, 0x6c73f83b, 0xa1ef2d0f, - 0xecc74678, 0xaaef288f, 0xae9fcfea, 0x7824adaa, 0xb1e08fc9, 0x7cadcf1a, - 0x0fe3c591, 0xbf43fcb2, 0x5f93f13c, 0x9e06e3ff, 0xf8f21d9f, 0x908fe85d, - 0x3d54f17e, 0xe6a67e46, 0xab68dc03, 0xd87cf952, 0x9e88f3f7, 0x2b4c0f9a, - 0xeb29ff47, 0x9da397b4, 0x072bf55b, 0xbe3ef7ed, 0x24f2972b, 0x0fc13dea, - 0x2b3a3e51, 0x5da35723, 0xa0e3085a, 0xfef1fbbd, 0x6e11cbab, 0xa336ff29, - 0xdfc61cff, 0xc7fa34ec, 0xd9e78d99, 0x4f9bdd2f, 0x4762cbfb, 0x6fec53f0, - 0x11c39db3, 0xa3ce23de, 0x3279bf08, 0xcfbe4bff, 0x4e344d56, 0x146db7f6, - 0x6172972f, 0x6d0599b3, 0xe4f203c5, 0xf22e9678, 0x635e444c, 0xa79e2cf7, - 0x8f0eea22, 0x81f3bf31, 0x238f2bcc, 0xb4b3c73c, 0xe61f96af, 0x402f9418, - 0x187e62fd, 0x9c5805c5, 0xe7a92dfc, 0xca3d1db8, 0x727a2165, 0x9c51df02, - 0xed09e806, 0xb1e34bf9, 0x6b9e78e9, 0x52f44774, 0x73e1f3c4, 0x3693c226, - 0xd38a35eb, 0xbc7c2ba4, 0x6b3df5e2, 0xc61fa2c7, 0xb865e6f5, 0xabbb7aa4, - 0x353a511a, 0x4d9f9023, 0x52968cfb, 0xbffaaf1c, 0xf29f3ccc, 0x17f92a50, - 0x291a0a3a, 0x6df7b29f, 0x4e3ce1ab, 0x77661972, 0xa8e4fe53, 0xbc505fae, - 0x194079c0, 0x72762f32, 0xd6f083b6, 0xa0cd8e1c, 0x3d4b9b1c, 0x43b56724, - 0xb538a2bf, 0x094356b6, 0x7eccdac4, 0x0b439e13, 0xefe460af, 0x32e1d31c, - 0x8a157ae1, 0xc3be98fc, 0xa418987f, 0x0f8c8afd, 0x937e7844, 0xee1567b9, - 0x3d15b4c3, 0x3d718797, 0xcd4db80e, 0xbc5fd865, 0x872dfc99, 0x4fd21952, - 0xddf15761, 0xb85ea153, 0xb0f145c6, 0x296ee7be, 0xcc2aff24, 0xf310cc73, - 0xf336ca2c, 0x9aa50ffe, 0x9b699f50, 0xd5470f98, 0x04d559dc, 0x875083f7, - 0x3c8a467e, 0x453f1955, 0xa9ea143f, 0xd7e0ecf4, 0xffb63f30, 0x14b2d21c, - 0xe3490e7e, 0xb2e712fe, 0xf3c71fb7, 0xfc2c3b3d, 0xc391e79c, 0xdf936613, - 0xe0a6ad6f, 0xe6ee7c3a, 0x663794f9, 0x42e70c9b, 0x847ff006, 0x1d4756f2, - 0x6bd705fa, 0xaff61630, 0x68bd3999, 0xd13b3d6b, 0x2d38b8bf, 0x97ba7948, - 0x8a5545b5, 0x3d4eb99f, 0xec27ab50, 0x3d70b673, 0xef8fbcd3, 0x35f793cb, - 0x6e5fa65f, 0x2dda36cb, 0x927ff5fd, 0xfe83f2dd, 0xfdc6fff1, 0xf3ee330a, - 0xe497ed92, 0x3b20dd7d, 0xe1bfa93c, 0x8f9918ec, 0x0e303d52, 0xd29da7b7, - 0xf21b0a4e, 0xe21daa75, 0xd8cda17c, 0x5c23e5ff, 0xbf995f34, 0x5f52b593, - 0xf1fa7981, 0xd7f2301f, 0x70a23cc9, 0x09f7cf35, 0xee746c9b, 0x29dacbd0, - 0x8b24687f, 0xd3f90a2a, 0x6d7ce87a, 0xc111e636, 0x47b2eb77, 0x99dbbf51, - 0xf24a8d6f, 0x6e105752, 0x509fe63b, 0xeb646abe, 0x3ae71c22, 0xc7638d07, - 0x308b93fc, 0x15bfc085, 0x06f4ebe5, 0x05c85f1e, 0x9bf48c7d, 0xa1d39a3b, - 0xa1e78ebd, 0x99133cc8, 0x50f12217, 0x3b9bf02d, 0xca115176, 0xf04ab5c1, - 0x99ae7151, 0x4e0dffcb, 0xec195e71, 0x79c0cf6b, 0xfbc63ee4, 0xf898370f, - 0xaf376479, 0xf9d18c77, 0xf82fa079, 0x728ebb39, 0x2832779e, 0xaf09253f, - 0xc9e53f32, 0xe411e0b4, 0xcbf3e497, 0xd6124e92, 0x6f47ce8f, 0xfaedc43b, - 0xcd0b06ea, 0x35c96fa3, 0x5bec97e4, 0xffa86262, 0x9cadbbab, 0xdbc692ee, - 0x51616756, 0xd88b57ec, 0xf5ca7e51, 0x16bb32ff, 0xfd14b5d6, 0x6b5a47be, - 0x38053a2f, 0xa01ada3e, 0x74aecfb2, 0xf9d217aa, 0xa928b9d2, 0xf9f2d89e, - 0xe60e5ab5, 0x140bc4db, 0xb7e79920, 0xea93347e, 0xb077f199, 0xcf16eafe, - 0xc39034d7, 0x3be2637d, 0xffff7814, 0xdbc47f79, 0x19731691, 0x87a1f77b, - 0x5f1d8666, 0x91fddf41, 0x9c71e725, 0xc4d3bd41, 0xc8c5567a, 0x5df4245f, - 0x5e879725, 0x25ec8587, 0x653fc8af, 0x151f2235, 0x5f503b23, 0x714e5399, - 0x0fd3077b, 0x8f3db0c4, 0x7682cf9f, 0x6395ffa2, 0x26da7fb8, 0x49e582e8, - 0x184f54bf, 0x22cadbe5, 0x2fdf7d37, 0x23580f8f, 0xc7c63fdc, 0x0be9e37f, - 0xf325be28, 0xe573196a, 0xf280b9cf, 0xfbf50c6c, 0xa61ce2ec, 0x73c7cae6, - 0xc2cd2bec, 0x36f515ee, 0x8bc53067, 0x043e44f3, 0x2b8dee7b, 0x7c865bbf, - 0xf7e0e674, 0xbb5ca347, 0x82fb02ca, 0xeed8e421, 0xfac72e1c, 0x0a358ecc, - 0x0ce3577c, 0xfac2f08e, 0x773a95bf, 0xa8291e06, 0x82cd311b, 0xf8581747, - 0x9af11551, 0x3dc4e829, 0xaee7c387, 0x77982809, 0xc7ced2ba, 0x7e6a0ccd, - 0x9c10f73a, 0x70075ca3, 0xbcb854af, 0xc9d28f86, 0xd3d52a8e, 0xa3611cf1, - 0x0aaad738, 0xe74971b9, 0xf5ed1526, 0x35beb79f, 0xe006d355, 0x878885fb, - 0x78c8a2ff, 0xcbdca23e, 0xce5962ed, 0x900bf556, 0xf0ad56fe, 0x12f336bc, - 0xf8e9ce7c, 0x9565b4ca, 0x557da798, 0xfa254b6a, 0x4f3d0769, 0x0965e787, - 0xaf7f2b75, 0xc02f16d1, 0xed0be673, 0x8f8849c1, 0x7bbde7cf, 0x3b87ca27, - 0x0778df73, 0x30de24f3, 0xaf91390b, 0x98eef588, 0x79eb069e, 0xf22dd8ac, - 0x0f446c3c, 0x3f72c6c7, 0xdb1e7f64, 0xfaf28538, 0xe7e1ce66, 0xb165af49, - 0x9ef81eb6, 0x3ed0159c, 0xd9117263, 0xde453391, 0x02b78cc5, 0x9817e869, - 0x435c4371, 0x5d9c3a39, 0xacd79574, 0xc3f024f7, 0x7eb1bad5, 0xfeb1a96d, - 0xfeb19f35, 0x1a7fc98d, 0xd97f589b, 0xf48d9fee, 0xf3c2bcf4, 0x3097c33e, - 0x47bdd117, 0x32fda309, 0x715c99e1, 0x27e7970e, 0x77d8abfe, 0x5199333d, - 0xdb3ed67b, 0x20373c2e, 0x68aad7fd, 0xb665e09f, 0xef7e0cc2, 0xb8bbea03, - 0x3d1cf222, 0x0761d314, 0x3f71756f, 0x816bbc2e, 0xd3ce0e7e, 0x46aa3f89, - 0x4e9052da, 0x76261cb2, 0xa552f239, 0x239aec8d, 0xb9e4ee82, 0x058d2aea, - 0x8602cf30, 0x1be5839c, 0xe88bd766, 0xc87f0ea7, 0x69dbe718, 0x8a5be51a, - 0x415b1831, 0x5d0487f5, 0xfff2911f, 0x57589a07, 0xef1840e0, 0x1e5cfaec, - 0x74652e87, 0x656cfe5e, 0xdd25d509, 0xae01fe4b, 0x41a18d1e, 0xe927f445, - 0x0b4ea7f9, 0xbf7a83d1, 0x34bbf849, 0xea590213, 0xb8807092, 0xc93d42c9, - 0x7195fec8, 0x6c9b7cba, 0x7ef8fcd7, 0x7e75930e, 0xd44b2bde, 0xaa6a29a1, - 0xf2fcfd40, 0x3b7f48ef, 0x879c417c, 0xe746cd25, 0xa3e38693, 0x767f825d, - 0x4b91f125, 0xe8f89abb, 0x3b92cea7, 0x9c6bee08, 0xa5afd42e, 0x0cba9730, - 0x2a23fd2a, 0x4fce3bf0, 0x474f8a6a, 0xed66f9be, 0x825aa9f1, 0x9bef869c, - 0xc6a9f7f8, 0x7df0bdef, 0x69f7c246, 0xe0d97df0, 0x6d3b77ef, 0xec44d351, - 0x21ef4aa7, 0xc9a5187d, 0xade6235e, 0xaeeff166, 0xa3b17911, 0xd47de0d3, - 0x3cc6a55b, 0x67d93613, 0xa4e4fca3, 0x94ab92bc, 0x57c839e5, 0xba9adb57, - 0x97bfa07b, 0x655e3ac5, 0x82e67e0a, 0x2dcf2fe7, 0x57fc8a39, 0x98688b6b, - 0x8b2d77d7, 0xedc5c2ae, 0xc47c169b, 0xe1f24c5d, 0x6693e459, 0x03363835, - 0xedcc67ea, 0x222d6fa3, 0x9bce79fe, 0x495e1839, 0xa45e1227, 0x493fa417, - 0xf770c92f, 0x3bd7e7af, 0x3b6f1129, 0x4a5851d8, 0x16b18abb, 0xe7ad779e, - 0x880bcc0f, 0x65ad8668, 0x2f35da34, 0xdc93092f, 0x00fdcab8, 0x9cbd65e5, - 0x944ffc1b, 0x7e177567, 0xcbe1a052, 0x716379de, 0xc6f000df, 0x95e137fe, - 0xbca0e3f6, 0x862d0fe3, 0xf8e1e3bc, 0x421b8e4c, 0xfcc550bb, 0x47949de4, - 0xf0e39a1c, 0x109179e1, 0x5256c1e6, 0xc2ec8afc, 0x6f6e14e7, 0xb09b1587, - 0x3f37cee3, 0xaf7b7199, 0x33dedfa9, 0x9477d7e4, 0x6e3bb873, 0x35fde5d5, - 0xc79c5edc, 0x4b393db8, 0x51742fb4, 0xefc3ccbb, 0x86fdc9d8, 0xd58f4f1d, - 0x03b05fb1, 0xe9607ec9, 0x322ccec2, 0x7f839bde, 0xde40d64a, 0xb73366f8, - 0x7c99b75f, 0x62e79455, 0x9ce2f7e1, 0x318cfe91, 0xff64fc7c, 0x628e6e62, - 0xd7f74f88, 0xc5fe4eff, 0x3f307752, 0x585bfa07, 0x4c502fe6, 0x33f71708, - 0x1c3e7d02, 0xd6fe9863, 0xfeed1a32, 0x9bcb59ab, 0xcfa262a6, 0xcfa41ce2, - 0xc59f4009, 0x9d1cfa06, 0x24e5c993, 0xb3e925c2, 0x934b2e9f, 0x1782caf3, - 0xee1d3f60, 0xa3355fce, 0xf56ddcbd, 0x9e5abcf1, 0x072c9827, 0xa059e012, - 0xaa3c7871, 0xc24cf04a, 0x39e19371, 0xa4493e1f, 0xf9c66ccf, 0xc97e3861, - 0x59d858d6, 0x2f2fc031, 0x083583db, 0xacdf3f7f, 0x41a3fbe2, 0xa20eab70, - 0xe46febaf, 0x2a509471, 0x4f1847d7, 0x67f181c9, 0x5faff189, 0xfaf0e9cb, - 0xdd10b17f, 0x8451f802, 0x9f68b67f, 0x7944ddd5, 0xcc6bb354, 0x00ed1227, - 0x13a9b719, 0x94f1cdef, 0xe605919b, 0x4bc634cc, 0xf1e26eea, 0x8b58eb9a, - 0x7ebde119, 0x3a9fb18e, 0xcc13feb6, 0xc9bbab0b, 0xd3983cf8, 0x8b19671f, - 0xc2a39671, 0xfc07d08f, 0xd3f4fc82, 0xdf0fc5cc, 0xf63bf40a, 0xe8156587, - 0x6b32ba77, 0x504deec9, 0xf1b6f1ff, 0xd669ff54, 0x06f3bfb7, 0xa128efb6, - 0xb9260d7a, 0xf9083ee1, 0xd54df511, 0xc114d78d, 0xa2ed47b8, 0x39f95bdf, - 0xb04a6f02, 0xe7bc1663, 0xf28a389d, 0xbc846b21, 0xdbc85be9, 0xc9d0bdaf, - 0xd66f5e53, 0x9358dfc9, 0x79f5efc2, 0x2bbffcad, 0x66b73f30, 0x3c57a894, - 0x47eb1e3f, 0x1ee84f95, 0x8726de80, 0xce6ff886, 0x09da7ee5, 0x1c744aa5, - 0x4326a5e0, 0xe7c4dff4, 0xd1e2b335, 0x9a8fe45c, 0x04cfde6a, 0xc5b5b4df, - 0x2ce99ef8, 0x6d737bd5, 0x250f2869, 0x70e7b59f, 0xa9ed2cfd, 0x67fbe080, - 0x8db6effc, 0x36037e80, 0x0c5387c5, 0xdf977e4c, 0xe7e0e55f, 0x22fe02cb, - 0xd3bcfd0d, 0xb37f3cfd, 0x0722b6da, 0x0f5fe7f7, 0x5e712a5a, 0x51f95b2e, - 0x27d26fb4, 0xf9449b4f, 0x466636be, 0xdf74073d, 0xf1787c41, 0x48690527, - 0xdd230e6c, 0x259aba4b, 0x48c6bde9, 0xdbafc0d7, 0x5cbf3272, 0xdae81b5e, - 0xc3d7403e, 0xd700b9d9, 0xa9ae098f, 0x3fd5fd46, 0x265f124e, 0xbc9c3b8f, - 0x7944bfc0, 0x275f003a, 0x661e5ff1, 0x7f2315c5, 0xecfe4bb6, 0xa62c3842, - 0x29b39d18, 0xe9e37c54, 0x7630ea60, 0x1f2f8486, 0x8315ae7d, 0x4d3fc2e1, - 0xcffc7fda, 0x3cf2fb83, 0xf9df0ed1, 0x5c00c659, 0x242bfe30, 0x7871570f, - 0x5c2d2bb6, 0x5c7b08be, 0xe59be7ee, 0xf38cbb7c, 0xe7e14aad, 0x77e8bdde, - 0xf97bdf21, 0xcfb87ef8, 0x7ce41d63, 0xcf6f4242, 0x169c05b1, 0xee75db98, - 0x1b9fa27a, 0xb469f858, 0x8339968f, 0x74f117ff, 0x843e14c4, 0xcc859cfb, - 0xa057f14f, 0x1272778f, 0x6f090dec, 0x879a9e32, 0xf3c9a791, 0xc0cfc649, - 0xbec8c5ba, 0xfad8e793, 0xf39e7be7, 0xc7897694, 0x6577f462, 0x8654ff08, - 0x452147f0, 0xc99e7ea1, 0x2fb87c52, 0xc853ee98, 0x6cc998be, 0xd6679724, - 0xe19e7d72, 0xd487f6e0, 0xc7f1c3fb, 0x92339715, 0x991b3357, 0xe7c73738, - 0xd9874c95, 0x2c0ee7ac, 0xadf4da67, 0xd1ef900b, 0xe007d14e, 0x7ee0e99f, - 0x215cecec, 0x24cf583f, 0xf5fdf3d4, 0x67be7a41, 0xe49fca12, 0x9e66c9fb, - 0x8cd2fee3, 0x99ca8c73, 0xa12777be, 0xeda8cf9e, 0xcc728499, 0x737bf2e9, - 0x1fdc0d27, 0xd1c78c98, 0x871926b9, 0x4cfa2f3b, 0x3f191fe6, 0xc706736b, - 0xcfd238e2, 0x55894671, 0x1e154be1, 0x583fe897, 0x76ec7484, 0xff434d15, - 0xe81b1cc5, 0xcbba1823, 0x1730bc15, 0x008fede9, 0xf10e6e0f, 0x75e3c055, - 0x347bc135, 0xe1e12c3e, 0x2b878136, 0xfb3d5e85, 0x89f14ab0, 0x43e97f1a, - 0xbd084218, 0xe2116662, 0x45e93f57, 0x59d8bf79, 0xf8a2a030, 0xb24e63fe, - 0x5abf1633, 0xb195f14f, 0x4f4c4c5b, 0x22e393d0, 0x327b8629, 0x30cbec26, - 0xcce82fd4, 0x617fbc35, 0x7b4328d7, 0xa1bc7479, 0x2a57a2fd, 0xb149f50c, - 0x2ff78629, 0x50daab7e, 0x1ae7a4bf, 0x3f53fbc3, 0x83a86d98, 0xde70d0c6, - 0xd8559f7b, 0x65f79836, 0xbe196ff1, 0x19b6cdff, 0xf3bc60af, 0xb2f7d8a4, - 0x0a563fb0, 0xe9205878, 0x637cdcf6, 0xaa25517f, 0xf3df2154, 0x79eb05bf, - 0xc034f6be, 0x0bbf625c, 0xc4f68ddb, 0x7ac62de2, 0x55a6f743, 0xe7071b28, - 0xe354b479, 0x79c93955, 0x79ae351e, 0x50cfa426, 0xe317d82e, 0x62ec1110, - 0x8e1b33cc, 0xfd6cbfcf, 0x2fe8d84b, 0xfefe7f5b, 0xf5d90b16, 0xaa7d5f8b, - 0xac8f0a2a, 0xdbfae35e, 0xa7fae375, 0xdfd71a96, 0x7fae33e9, 0xfae364fa, - 0xf5c6fdbb, 0x5c6b511f, 0x7180ccff, 0x8cebb3fd, 0x34139feb, 0x06c8ffae, - 0xb7e7fae3, 0x70bbd718, 0x8b3d7199, 0xed0d4bc2, 0xe52febc9, 0xdb9af165, - 0x7a01ef8c, 0x2074094d, 0xa04168e9, 0xc677f281, 0x30cf7fb4, 0xc03d324e, - 0xf744d1be, 0x6e3ec1bf, 0xf4fe729b, 0xfc8ad201, 0xf1f4c9bd, 0xeec2b96f, - 0xfa017414, 0x0ae513a8, 0x614f17d8, 0xd8563759, 0xeda181fb, 0x12bf290b, - 0xbee279f5, 0x36b93878, 0x7d894f48, 0x0a7ab0f2, 0x81f6c9f7, 0xf470f27d, - 0x8fb31c7b, 0x4f5a8ec8, 0x5d1ba57e, 0xf14f8e1c, 0xcfe825d1, 0xf2f4827d, - 0x32700071, 0xe71c7bc0, 0x4f1fe303, 0x8dfe4099, 0xd928b36f, 0x1982ffed, - 0xcdd83096, 0xe2ada898, 0x953a4f3d, 0x2f6f42f5, 0x858ffe14, 0xb95be0f6, - 0x9851efdc, 0xc5e6e385, 0x7b14bce8, 0xdd79c46d, 0xe3027123, 0x4f782008, - 0xca011c61, 0x9ba73b5e, 0xf8ae52d3, 0xc049ee99, 0x4ae9fce7, 0x6ab5d929, - 0xcd3de50a, 0xfd2141bf, 0x787fff34, 0x2cfa1719, 0x4cb95cb9, 0xd85db3e2, - 0x482edc03, 0x149ac3c7, 0x07416277, 0xc2e7cde1, 0xb8fe8675, 0xfc47ff1f, - 0x0ae3cd7c, 0xd06726d3, 0x675a3331, 0x0f3c6f5c, 0x9c38daa5, 0x0d999b8f, - 0x058139f1, 0x57bc0ec9, 0xfbc6d103, 0x7bfbcf1b, 0xd3fa1463, 0x7cfff554, - 0xcfe306ad, 0x9ffa2e38, 0xfe863e1d, 0x63ebd566, 0xf41abfe8, 0xba14c0fc, - 0xcebfa324, 0x87f87bf8, 0xc27e9178, 0xbb2f413c, 0xbdfb8c9d, 0x2386fc92, - 0x98c09055, 0xe7e663bf, 0x16dabdc3, 0xe63c9fbe, 0x984d635b, 0x37666337, - 0x32fbe79e, 0x6df3087b, 0xc7e4274f, 0x790cbac3, 0x3cb4e98f, 0xb657efae, - 0x71865c36, 0x07115ea2, 0x7835a7bb, 0xaab7ae19, 0x0e2f28f9, 0x277257ef, - 0x40f16f7c, 0x6a9f027b, 0xdd43068e, 0x5e1008ec, 0x10b6b556, 0x3dc598dd, - 0x6ef3ab50, 0xfc130573, 0x148e1712, 0xcc2d86f6, 0x984c595c, 0xc1f7f0c6, - 0x55f38674, 0xc4e9da5d, 0x0bd5a87d, 0x2bca25fd, 0xfa2590ad, 0xb6b4d7ad, - 0x94abdc10, 0xb33b1060, 0x3b51668e, 0xe1aadbe0, 0xbe785459, 0x67922af5, - 0x3e6de716, 0x3867f7bc, 0xdabd59fc, 0xc87289e7, 0x8728d23f, 0x5db56fee, - 0xd95af88e, 0x93c68cba, 0x756f6b78, 0x8df58e5d, 0xbed15ead, 0xb54dda82, - 0x71f482ba, 0x8621681a, 0xc7ad1671, 0xb03d7189, 0x03c61933, 0x045b5ecd, - 0xe1eac899, 0x05a3b2f0, 0x5d731f44, 0x8df4061c, 0xbc7d03e5, 0xfb4cccb3, - 0x1df3dbd3, 0xafedfef4, 0x0fd1798f, 0x1e01607c, 0xf98aff51, 0xf0238ff4, - 0x88721167, 0xf200c169, 0x23572595, 0x6b86747f, 0xdfe3ad36, 0xbbc49fda, - 0x1f28cec5, 0x20ef92d4, 0xe17cebbb, 0xf7148d0c, 0x27bc0950, 0x44f00fe3, - 0x8176f472, 0xe2efdba7, 0xefdbbe7e, 0xcec79460, 0xd55fc196, 0x148d5d00, - 0x059b25f2, 0x056f6ca8, 0xeb8252c1, 0x0b416365, 0x49d675e8, 0xbfd1db2f, - 0xcd7eed83, 0x4deaa18d, 0x58599e35, 0xaa7c9c6e, 0xbef1d91d, 0x618b3f4b, - 0xc474be89, 0x4581ab97, 0xc51fccf0, 0x1d783d8e, 0x89a7af35, 0x5e3ab4f6, - 0xe9ed174f, 0xf7cf5e01, 0x20d4a93f, 0x97f14960, 0xd5c6477c, 0x2dbe51a3, - 0xb27cfc60, 0x3b60e7b8, 0x91c2f213, 0xdb06ab31, 0xbe74626f, 0x50ffb640, - 0x4e38e7b4, 0x394629ac, 0xfdf8c73c, 0x6c878156, 0xe9f689c7, 0xb6319f14, - 0xa64af8cb, 0xf42bece3, 0xfdb1997d, 0xd3bdf141, 0x1d363671, 0xc71b47db, - 0x53da20df, 0x08ef3c1d, 0x473f21c4, 0x15efda2f, 0xc76c76ed, 0xed8d4bf1, - 0x2bf8c56b, 0x43ad0095, 0xf8899f3f, 0x9d568ee4, 0xf67cc9ea, 0x7e0cc8ea, - 0x99f0598e, 0xf21b196b, 0x23abfcdc, 0x9a4cbe79, 0x0ff7e3de, 0x7b650f21, - 0xb8a34b86, 0x10b5eaaf, 0x421d591d, 0xec3e088e, 0x8b4a2397, 0xf717138f, - 0x3d197f97, 0x8e7ee103, 0xfe00acf2, 0xbef39e90, 0x04c16263, 0x98db9679, - 0xef0982c2, 0x1864177b, 0xe53759ea, 0xccf7de1a, 0x77686519, 0xb4378e54, - 0xf13e58b3, 0xae826dc7, 0x0c2aca52, 0x02bef2ed, 0x923e73a6, 0xf479b576, - 0x677bc314, 0xa474f54b, 0xcb57d3ed, 0x367cabfb, 0x39b70b94, 0x1f236547, - 0x3275a4fe, 0xef20df1a, 0x8974a26c, 0xc9474bd2, 0xa2eab656, 0xc7f54a5e, - 0x7aaf3cdc, 0xd78fab65, 0x6f9d188b, 0x4b5ad95e, 0x2f81c7f5, 0x56d7fcb1, - 0xa07b953f, 0xfb0e160e, 0x43aff411, 0x7fa13b3f, 0xfd023fac, 0xfa1db963, - 0xd087f2c7, 0x856fb63f, 0x10feb17e, 0x83e585c0, 0x7f3e0fd0, 0xfac7fa00, - 0xd500d6a6, 0xa3ad6bef, 0x20d686fa, 0x36b6f795, 0xadb5f3d0, 0xdd5f542d, - 0x7bca8cba, 0xae54c35a, 0xed435d6c, 0x1f37a116, 0x1f1fe713, 0x7dcfc69b, - 0x467faf27, 0xeed5f29e, 0x4504a8bb, 0x93c8655e, 0x7dc3c8c8, 0x2f31a775, - 0x7047f110, 0x931e39d8, 0xe02b18e1, 0x2b62cf18, 0xa0dcb952, 0x2e98eb38, - 0xc0a9dddf, 0xf85b23a7, 0xc57517ba, 0x81a73da9, 0xcc56378f, 0x2cc27993, - 0xef1f8aaf, 0x957af7c5, 0x8f2a7558, 0x831f9337, 0x553f0179, 0x9133dce2, - 0x7084c479, 0x7f419369, 0x1fb3cc27, 0x270e6e5f, 0x78286de2, 0x7c78f22b, - 0xe4ecad43, 0xb6d49bf7, 0x52cd9147, 0xbf742dfc, 0x102ead89, 0x04f4a0d5, - 0xc24f7482, 0x603373f8, 0xed720593, 0x874ce5dc, 0xb8d1af32, 0x505dcaff, - 0xa8e7d861, 0xfd3236e7, 0xccb7e822, 0x194a4fb8, 0x3be19b7d, 0x0cf7de5b, - 0xddcf16ed, 0xb7f9f686, 0x22f2ad14, 0x8a32473e, 0xafd7593b, 0xd7003960, - 0x044d8ec2, 0xbde05057, 0xfdf9d157, 0xefc5fbed, 0xfffb0844, 0x2f812ec7, - 0xd7da7adb, 0x6af3758e, 0x84d87a49, 0xa7e3e7fa, 0xee8e49d2, 0xfe44c47d, - 0x622c71ed, 0x01337942, 0xbf6c48cc, 0x56726f00, 0x151ccae9, 0x574ce5eb, - 0x8b117eb1, 0xec08bed3, 0x17a43aff, 0xb11fffb0, 0x7e4cfd43, 0xbf3cc7f0, - 0xba7a4a2b, 0x8967ac44, 0xd16d07dc, 0x73c3fd92, 0x635fc8f3, 0x26d6073c, - 0xdc2b01f6, 0xef18d955, 0xff261ded, 0xd6fde9ce, 0x1eb005d4, 0x2a3a9cce, - 0xba0df3e5, 0xd173c869, 0xbf2abecb, 0x623d016c, 0x086597e4, 0x9fca99ff, - 0xaabba167, 0xf89c7479, 0xe52ccda6, 0x728e9e98, 0x4beea06c, 0x3ba2bb27, - 0x89a3f087, 0x1adbd9f5, 0x3900fca4, 0xd377ed4f, 0x560f985c, 0xf74ff222, - 0xb53adeb5, 0x661f2126, 0x52dfa0b7, 0x3d45ab16, 0xf2665a5a, 0xaf27a845, - 0x1f617fc1, 0x73c7eedd, 0xf3055afa, 0xc71e18a1, 0xbabce9da, 0x794a85f6, - 0x4b91da40, 0xb0760e98, 0xe16511c3, 0x997e81b2, 0x477c83f0, 0x5ccff5c8, - 0xad0f3435, 0x3e47da40, 0x33ecddd4, 0x74863f87, 0x998759f7, 0x6309e5b3, - 0x9183a97b, 0x6a545b9e, 0xa60ae889, 0x3dd3b423, 0x850eda8b, 0x1c2115e5, - 0x50f3bdd3, 0x254c1f8f, 0x52dd4dba, 0x7bc35745, 0x79f5c14c, 0x1e99c700, - 0x1a49a0fd, 0xd35ef057, 0xb42ecb04, 0x5e22c71b, 0xa5d19c70, 0x6285c784, - 0x575afbbe, 0x159e9e10, 0xefcb68f3, 0x87873bc7, 0xcf78fcf9, 0xe90ea2e9, - 0x73ce31bf, 0x37f56543, 0x95c6def0, 0x74d85531, 0x33ae7c46, 0x53ce26c7, - 0x3802e006, 0x5538459f, 0xbffc9b84, 0x8f4d7e7c, 0xc819bf70, 0xbb8a5ab1, - 0xc4b1324e, 0xa32cabb8, 0xc8cdfe42, 0x4ebc1173, 0x0ba9dcef, 0xdfac4a2e, - 0xb8fd7444, 0x761fe7c2, 0xcd2f3c6a, 0xfd13d7ef, 0x7ee4ebc4, 0x487f9c59, - 0xdff6f011, 0xe79e36e3, 0x6c583a61, 0x0d2de60b, 0x25fe1fb7, 0xc4a4ca2e, - 0x18e830fd, 0x649d5718, 0x759f3ca3, 0x7f4b8f32, 0x337cc743, 0x8afcf12c, - 0x6ae9d04d, 0xe4af31a7, 0x77b71e5c, 0xe8f589ce, 0xc6be71b3, 0x567964b8, - 0xdd17bdc2, 0x91ffe4f5, 0x6ebecc71, 0xfd2e0f9e, 0x09044b6b, 0x78e51df4, - 0xa5587be8, 0xee92e5f8, 0xa17df96b, 0x7ba01e87, 0x1d2fa156, 0xbc5ea1e9, - 0xe8c6bf5f, 0x3bb059ef, 0x1f452ab0, 0xc45a57ec, 0x48d7e4c2, 0xfb2527f6, - 0x279b7e91, 0x563e69f6, 0x93ca718e, 0xa58f8beb, 0x88a67ee0, 0x91dbb9d1, - 0x8f7493ea, 0xedfb5831, 0x2b294f78, 0x24f4f7e3, 0x0525fbaf, 0x3ef3c216, - 0x1c63aeb9, 0x37d867e4, 0xbefff389, 0x7d7ecf17, 0x96f3f40c, 0x81ce18ae, - 0x099ba5bc, 0xae81e38f, 0xac64ecb1, 0xa0fba876, 0x5f4df3b2, 0xa5c0bced, - 0x68d7dfc6, 0x9639eaea, 0xcbbc93aa, 0xfa7807ca, 0xad3efd8e, 0x4e27f88c, - 0x575107bf, 0xb841e1c4, 0x7ecbfcf1, 0x137327d3, 0xbe7c60e9, 0x7c83edc6, - 0xbf9357d3, 0xceb84635, 0x7599bd94, 0x1c6b870d, 0x3d1bd5c2, 0xb7689591, - 0x0ff6b848, 0xa5fabf73, 0x934f155f, 0x0120fa8d, 0x12ff534f, 0x865bf69e, - 0xc0966786, 0xf28e4fcf, 0xb70642fb, 0xd5fd457f, 0xccf78461, 0x51ebb163, - 0xb3bc023c, 0x53de7f08, 0x15331459, 0x14acebf8, 0xe42959f4, 0xa8ce8f8e, - 0x17dbd0b0, 0xa75e7e53, 0x7743dbc6, 0x79e08a2e, 0x0b8bdf02, 0xe0dfd10a, - 0x7ba56e3c, 0x7949429e, 0x2f5cb222, 0x573fb1e6, 0xab0f1219, 0x78bcb9f3, - 0xd4f9b5f1, 0x596fbddf, 0xed83ca19, 0x5ef5df22, 0xef0da757, 0xc47895ef, - 0x2194057a, 0x2a117c4b, 0x3f2b7bba, 0x218ee9b3, 0xf1f133c6, 0x1be24bee, - 0x572c9e39, 0xbb7297e4, 0xe2aa3954, 0x2efb8739, 0xd9ee937d, 0x2352afba, - 0xe337fb99, 0xfe127d7f, 0x7d666fa3, 0x8acbd39d, 0x2aa3f47c, 0x037da5ef, - 0xfe2521ea, 0x9fc432b3, 0x0ff34825, 0x3b656dbd, 0x6a78c195, 0xe72bf414, - 0xe12fe727, 0x80b65e76, 0x7ae099ce, 0xc5abe020, 0xa44f52fb, 0xf387bd0b, - 0xa9713d22, 0x4c89cfc6, 0xef5d68d2, 0xce853c9b, 0xf917ecf5, 0x2c4bf114, - 0xc32efe43, 0xf76f0233, 0x0c45fb9e, 0x770da9ef, 0x055ee99b, 0xbf78f5a6, - 0x7a147409, 0x9a7ba35d, 0xf16a9e81, 0x5f17a8de, 0xfb869b3b, 0x66f903e8, - 0x3e40fb82, 0xe77d8797, 0x6f3a5ad4, 0x2e67daf3, 0x9ffe8135, 0x5d8557ce, - 0x39e18b12, 0xfc158d9a, 0xd84380dc, 0x4ed78e01, 0x8efc2035, 0x2ab3dfc9, - 0x4f767a09, 0xdbbe95be, 0xf9678968, 0x48740e30, 0xdfee5165, 0xfaeffba1, - 0x38ba0bcf, 0x8f2b9a1e, 0xe8e09d92, 0x3de2f7e6, 0x5c13af9d, 0x7841f708, - 0x33ee329e, 0x57b63d57, 0x06a378c2, 0xf8ba77be, 0xe24ca67a, 0x77dcd0f7, - 0x785dcfe9, 0xc2ba5eef, 0x4be8fee8, 0x3906cc0a, 0xd7c45f5e, 0x1632b3a1, - 0xe5fc851b, 0xb6af28d2, 0x0d9b7a33, 0x17c97aed, 0xf4a947a3, 0x97916add, - 0x29727abe, 0xe3a499f1, 0x57c105b9, 0x02366e91, 0x76493c5f, 0x9d302c4e, - 0xc72ae3f0, 0x95c7e3fc, 0x3fb71d58, 0x2fd42e2c, 0x819326a5, 0x380b8adf, - 0xec12c8dd, 0xee77b252, 0xf52cb410, 0xc6c45b7d, 0xb7ffbf30, 0xa3a566e7, - 0x2796da5d, 0x0dbf3ced, 0x095db5f1, 0x38e117a4, 0xbed2a5ff, 0x4ed7c5ef, - 0x6db8e034, 0xdbe42f30, 0x58ea7e7b, 0x9b49f68f, 0x2a7c4fcb, 0x26dcd7c7, - 0x9fbc1eb1, 0x2bff16fd, 0xbb8c6fe8, 0x47447df9, 0x43635ca6, 0x4cf787fa, - 0xad7bcfd8, 0xd81a0bf8, 0x07f90d4f, 0xcf66ba16, 0xb116efc0, 0x6bb42ae0, - 0x86a87517, 0x11ee177b, 0xb9e162f2, 0xd84d1614, 0xfc9c2c1f, 0xb6373a2d, - 0x8b1a5cf0, 0x8f75bd82, 0x8f7d1738, 0x0ac45738, 0x443b3d38, 0xdfe515e9, - 0x24bef7cc, 0xcbf995bd, 0xdf39f3bd, 0xb7e802b3, 0x14b1e949, 0xa71b10c1, - 0xebce9efc, 0x62ead7bc, 0x780492d1, 0x0473cd07, 0xd38c268b, 0x1b39deff, - 0x7d6067cd, 0xcc0efd39, 0x787841d7, 0x784bd5af, 0x91ffbe1c, 0xf40e3c06, - 0xc780ca3f, 0xd097fdc1, 0x96b5eff8, 0x13ff497e, 0x375fe986, 0xefd03fc0, - 0xf7b71a68, 0xa71ffcc8, 0x891ddf02, 0xf9edbdde, 0x331dfc4a, 0x017efd2b, - 0xa6aceaeb, 0x338f8473, 0xe77a673a, 0x83bddfe1, 0xee779af9, 0x8c70f8b2, - 0xae7c733e, 0x333d086f, 0x78c2b99a, 0xc72c979f, 0x7cd31417, 0xb4db9f92, - 0x32f30b88, 0x0b9aa56d, 0xc6d11f7f, 0x71bb9162, 0x236952df, 0x42e32739, - 0xe53fdfb2, 0x3b3cf2a9, 0x6f7907c9, 0x979112cb, 0x5e08ec57, 0xd4beeb81, - 0x13fcded4, 0xd283f6f8, 0xcc373a36, 0x33f69b98, 0xe1a36e32, 0xa315bf2f, - 0xf0c0305f, 0x7a13cdfc, 0xf77e0670, 0x18271043, 0xd82f51c7, 0xb5bcc41d, - 0xb8df620d, 0xfaf31ec1, 0x0de6e412, 0xb357da05, 0xe893da17, 0xf72fd276, - 0xdedd3946, 0x227e8050, 0xfcc4f635, 0xedb7cc22, 0xe976f711, 0x55778a16, - 0xfefba31e, 0xff7dcbe6, 0x8ebce49a, 0xd1da377c, 0x8694ce32, 0x6b687779, - 0xbef7e46c, 0x7af2a7d5, 0xa08c7ffd, 0xffb01073, 0xf9432d49, 0xfee55fb2, - 0x3adf1120, 0x67d0e62b, 0xf94058db, 0xe41f22f7, 0x744bf76c, 0x35d9e4af, - 0xebfd6863, 0xdd3ef85f, 0x973fb70b, 0x43beb1eb, 0xf563d24e, 0xde155f56, - 0x973fb85b, 0x5a9dabdb, 0xc122ad34, 0x579d5d7e, 0xe3f9f24d, 0x894c6335, - 0x0aef8ff1, 0xfa51b079, 0x1578b537, 0xb8f9679e, 0xd233fa32, 0xf4ec07a3, - 0x83a6513b, 0xfba2abbf, 0xe95a372d, 0x0faa0177, 0x875cdb8e, 0x8d34c3fb, - 0x074d91f2, 0x99cf04ed, 0x2d7efc75, 0x5de516fc, 0xf491c1d3, 0xa9f556fb, - 0x6c27ca71, 0x6095f14a, 0xe0feafdc, 0xffd7ba54, 0x057186e4, 0x644eff28, - 0xaf7405ea, 0xf43c06f1, 0x6343f509, 0x17b5f3f9, 0xe75579d3, 0x50e0d4c6, - 0x8fa9107e, 0xdaefef92, 0xdbde5b9f, 0x6719f885, 0x7dfca1f3, 0xb8f1f14f, - 0xd9f12bef, 0xf915c53a, 0xd77ad2f9, 0xbc7dfa69, 0x6f778efa, 0x43dcf462, - 0x73f72b74, 0x0bd5e3c9, 0x12dfb57d, 0x4bbf8b9f, 0xe052bf56, 0x624efc5d, - 0x7e9ca9bd, 0x7de24faf, 0xb73dd263, 0x24fd084f, 0x69af93cb, 0xd8205f74, - 0x1fe80511, 0x4ad8793a, 0xe3727674, 0x2eaf3a04, 0x9c07abc7, 0x4f2f80b8, - 0x7113e864, 0xf2169f5d, 0xdf257eaa, 0x30e7caa7, 0xe77f0c7e, 0xa5487e30, - 0x573eaebc, 0x92e30d3c, 0xef593df2, 0x4ab74f9f, 0x3fb597bf, 0x6f5a45f7, - 0xf48627a0, 0x49c17a64, 0x82f43a7a, 0xe7ae1775, 0x8c2c95c7, 0x5bf0cffe, - 0x8ec7f7fc, 0xfd92b21c, 0xef9c77dc, 0x9fdd076f, 0xe01788e6, 0x17a1a1fd, - 0xeb1c9246, 0xe0ef8fcb, 0xdf9db6f6, 0xf046f8ab, 0xcdff1162, 0xe611f711, - 0xf9f79da0, 0xed147b21, 0x9e29283c, 0xbdbb6610, 0x2a70fcf4, 0x940fff43, - 0xca63cf14, 0xeefd2f01, 0xdf176b0c, 0x3bfbe8c7, 0x5163820b, 0x0c59df2e, - 0xfbf03bfd, 0xe7def453, 0x521782a3, 0x5cb18a0c, 0xf52e5e31, 0xa42c1f9b, - 0x5e67cae7, 0xed2a7bfe, 0xed463da2, 0x62f06b21, 0x9cafc79a, 0xf310e76c, - 0xeef7aafc, 0x41182d1d, 0x06e128eb, 0x98dd933c, 0x05b3978c, 0x3b7bf126, - 0x74c91f1c, 0x5f9ebfd9, 0x5ffa1f02, 0x21f6bce8, 0xc6eb8ebe, 0x591cb859, - 0x63ec813b, 0xc86296d6, 0x88715b9f, 0xbbd0c3df, 0xdceb49c1, 0x843ff667, - 0x86fe28fa, 0xed7bf199, 0x3f4022c0, 0xf9a1e4c5, 0x4f9123e5, 0xcf2d64bf, - 0xd1e8fbb3, 0x39e60bf7, 0xfbf25cf0, 0xd2c97386, 0xa49d085f, 0xe1c63fa1, - 0x97e6d3d3, 0x255d7b71, 0x7aeff8f8, 0xf4eb346d, 0x0de16bbb, 0x711fc8e3, - 0xa41fa2d2, 0x775b87df, 0x4ae90981, 0x77f2172d, 0xbc9f9f13, 0x7bde4b2f, - 0x8a9f8c95, 0x7f9262c2, 0x33782c4d, 0x827ea1de, 0x61c259e9, 0x91fff746, - 0x6984df7b, 0xe29f9a88, 0xf485acb6, 0xf67be0c2, 0xbbf25f2c, 0xf5bbff6c, - 0xf42b5c2a, 0xd38795ef, 0xe07eaf50, 0x3a46fbe2, 0x5d7a8f7d, 0xc36cf3e5, - 0x83af300f, 0x4e14a605, 0x879276a2, 0x5dbc281f, 0xf341b9ca, 0x7ec17a47, - 0xebe83df0, 0x7fee429a, 0x710cae63, 0xc16c2bc8, 0x9fa94d3c, 0xc2668a42, - 0xdca7f373, 0xe3d21a7a, 0x19c5b5a9, 0xc60f302b, 0xda2567ad, 0x8ca3a1d5, - 0x78eb8bce, 0xf8c5f8df, 0x89fe32fb, 0x9fdbf7e8, 0x243bf461, 0xb4e4f3c3, - 0xed89b99e, 0x9eb90a73, 0xf6285f9b, 0xe44c8599, 0x8de32657, 0xb162fbaf, - 0xf0796aee, 0x2687da72, 0x4b78b7bd, 0xa487a0ba, 0x7fcfede7, 0x1ea0f297, - 0x4913de36, 0xef185fb1, 0x612c5783, 0x532c42e5, 0x61bdaf28, 0x0d739713, - 0xb92cceaf, 0x5ee9d78b, 0xef3b6985, 0x59e3dfa1, 0x12caebb0, 0xad16e5c6, - 0x05c7a483, 0xb412fe05, 0x555be2e3, 0xc345f217, 0x51e09516, 0x56d73ecd, - 0x8b7a7e78, 0x06bbec99, 0xbce9cf01, 0x9bad1a60, 0xe00b34c6, 0x4c16b4fd, - 0xab75fb23, 0xa4a1ddf8, 0x6f7bc079, 0xe043156a, 0x99d7c6c7, 0x043c53f0, - 0xa261bc1d, 0xbf805a75, 0xec70890b, 0x79bfc854, 0x33783f3a, 0xfec14fd6, - 0xabe9cf1f, 0x7dd0969b, 0x3ef8c936, 0x7d120b6d, 0x91f3162e, 0x471e4cf8, - 0xf10fb3e2, 0x2bd2f689, 0x85ef4853, 0x6291541e, 0x9fdd8bd9, 0xda7cbed2, - 0x99df2ba1, 0x8137cf8a, 0x9ea3a2dd, 0x6fb3f51d, 0xa35b9ea3, 0xfe7a8c52, - 0x962ce2a1, 0xff71afa4, 0x39f5ff39, 0x3d04a669, 0xf1c83ea9, 0xa4e73aa4, - 0xcff7a42d, 0xebe91d7e, 0xaacbee84, 0xf1ef7848, 0x83b8fec2, 0x37eabd61, - 0xc70d21fd, 0xa66f5869, 0xe975c979, 0x7ca079c3, 0x208d4f6b, 0xc5e5f7fd, - 0x4eb95fa9, 0xeb8df4fd, 0xde09e920, 0x9742affb, 0xf24c2718, 0xb05154e8, - 0x9d0437ca, 0xc6007a2c, 0x38b6fec5, 0xf3d2fee9, 0xa3e2571d, 0x5f05bd7f, - 0x71d71d53, 0xd1f91147, 0x74686f4d, 0xfb44e0c8, 0xc7c80555, 0xd02fa0f5, - 0xc4af516f, 0x647ba1df, 0x1ee9590f, 0xb74dfae6, 0xd5e38cdc, 0xb09ab71f, - 0xabe1d4fd, 0x495c1226, 0x2a780aeb, 0xfbde8a18, 0xbe05e28a, 0x3d81fc04, - 0xe72dfc41, 0xc1370093, 0xba29fb01, 0x08afa88f, 0x0e4133d6, 0xedc859bc, - 0x65df782e, 0xf7e6fa21, 0xd7cff561, 0x575f3495, 0x64df7cd2, 0x17ccdf44, - 0x782cf9a4, 0xe7c26adb, 0xb6bfee0b, 0xa73df704, 0x79a74dd6, 0x4ff0ca9d, - 0x553afe44, 0x210ffd00, 0x0fdc172f, 0x0bfb2cf3, 0xd3b76cf3, 0xcf3b0d7a, - 0xf60ef88c, 0x89f9e617, 0xcf3943a0, 0x0d3d34f7, 0xcf43f9f3, 0x2efd0caa, - 0xc6c0fca1, 0xbf4ebca9, 0x73321713, 0x4a6d087a, 0xdedf7ca5, 0x04fbfe6e, - 0x78c00e52, 0x260f49e7, 0xd55387a2, 0xd0c9e6fa, 0x3f07ffdf, 0x00b71737, - 0x0000b717, 0x00088b1f, 0x00000000, 0x7dcdff00, 0xd554780b, 0x733effb5, - 0x64932666, 0x08124c92, 0x3c984081, 0x49849009, 0x768a8802, 0x02d10478, - 0x89794f0d, 0x42100793, 0x69b5a05e, 0x0240cd6b, 0x350d45a2, 0x01d45a2a, - 0x0da2a281, 0xbc150a0a, 0x45622a03, 0xb68b57c5, 0x514026e5, 0x5ea0c679, - 0xffd7b5ae, 0x4e7dadfa, 0x5490ce72, 0x7dfbdedb, 0xdf1f7cff, 0x5afd9f66, - 0xd7b5ed7b, 0xe7bdaf5e, 0xcbaa3dc2, 0xe4e216ef, 0xff6f05dd, 0xf7a517bc, - 0xfc812eaa, 0x02cddf58, 0x2cc38ff9, 0x934a14fe, 0xfe70a68b, 0xa56b9b65, - 0xa689c422, 0xa141fdbf, 0x367d85fc, 0x0bf2a0b7, 0xcef74529, 0xea8f7e46, - 0x2fed415a, 0x259f680c, 0xd8b97386, 0x5deae544, 0x2e509a23, 0xcae61e1e, - 0x0df2f2a0, 0x09644261, 0x6856fbfe, 0x3be9237f, 0x6ba50b52, 0x34786f55, - 0xfd2f4da5, 0x6fa5c944, 0x578f3756, 0xf724abf3, 0xb97e34dd, 0xf9ed5855, - 0x399edca8, 0xf388472d, 0x03136d7b, 0x233f32d9, 0xb03fcb87, 0x5d8d7952, - 0x7bf85af8, 0x0e6a7dad, 0xd2b6e28f, 0x0fa98b38, 0xfae94a91, 0xea60ef18, - 0x938d317f, 0x8b7de342, 0x0e5c1fbf, 0xe7cb0edf, 0x9fa88a0b, 0xf6626d7b, - 0xf55dd973, 0x4ddb34f4, 0x6d46f61d, 0x553b577b, 0x3cc62588, 0x2422a1e1, - 0x477914bf, 0xa432be57, 0x7ca42abc, 0xa7cfbf47, 0x1f2f3914, 0x1fc6037f, - 0x12c785d1, 0x2c3b8f0d, 0x72eb1df4, 0x44d8128f, 0xbab12dff, 0xfe09cbed, - 0x9b88c6e7, 0x55a94fd1, 0x47cdae38, 0x5f9e0ebd, 0x86345589, 0x87bbe3e5, - 0xa6f3e9eb, 0xe2c31afe, 0xced11f28, 0x89bd53e3, 0xda9e4376, 0xab9ae09b, - 0x4ba7a3c1, 0x4ebb85b7, 0x7fa0f3ea, 0xa6b12d55, 0xbeeecd7c, 0x7c0693ae, - 0xfa7fc52f, 0x3449bfd2, 0x8bc091fb, 0xdddaabfc, 0xe892307a, 0xcdf14da7, - 0x17bf5375, 0x9d1d7e0e, 0x1f75e6ed, 0x9beb4459, 0x7f3ea6af, 0xbedbe698, - 0x426cf547, 0xfdd86fbf, 0xe7fd0c4a, 0x6e0f8b9b, 0x2fd5efa7, 0xddbb89a7, - 0xc50ff35d, 0x17dd85e3, 0xfbe953a3, 0x08f643f9, 0xb9e68c31, 0x9dac7e37, - 0x5c4762e8, 0xaf78b77b, 0xef5dd6d5, 0x35b5bcef, 0xdea1aa7a, 0x3d1ad179, - 0x252f40cd, 0x8bd62fbb, 0x5f9fc65c, 0xefc2efcd, 0xc7bd7d89, 0xf4bdf4aa, - 0x5ac6fdf7, 0xc35fbd28, 0xf736bddb, 0x6e096b13, 0xcf309eff, 0xfcfb8216, - 0x682db31b, 0x728dfe7f, 0xcbcdbd2d, 0x244f5fe9, 0x8b68fc63, 0xbc7d77a4, - 0xf70b6e35, 0x7b696a53, 0x8fda1aec, 0x93ebbfa5, 0x55d290d2, 0xcfc96a5e, - 0xb76f3ac4, 0xdc002fb5, 0x46b115e7, 0xe7eaeb89, 0xdb9bb77e, 0xc9f3df9f, - 0x270fe063, 0x4f901dee, 0x41f94d64, 0x3f2a3eb9, 0xa64151ff, 0x7f3dfa8b, - 0xf80f5f4f, 0xfb9b76c2, 0xbbb7a636, 0xf7d83ca2, 0xa7187f7a, 0xb9effd16, - 0xe90fa462, 0xca5e1247, 0xb8e4fae7, 0xabbf257e, 0xfb8b68df, 0x17e0d1be, - 0xb679b7bf, 0xeffcb250, 0x31627d69, 0x6ee7ec3f, 0x4d74a1d6, 0xf89b7098, - 0xbb864ac9, 0x22ec7844, 0x030b964d, 0x228995bd, 0xc9b0befe, 0xf1117dfc, - 0xbc5f7c09, 0x5cbdfcde, 0xa56ead34, 0x98092df9, 0x3fda0bbf, 0x6bec04fe, - 0x5ec5affd, 0xff7a0514, 0x4f54cc36, 0x40fe35f8, 0x255f091f, 0xc7c11fb4, - 0x8102519e, 0xbbdf5895, 0xe8679e54, 0xa775debc, 0x2287bb70, 0xab4167ff, - 0x5b8f5d61, 0xf0913584, 0x1c2edc7a, 0x47e8f989, 0xf5fa8508, 0x6c0b0bef, - 0x0f7726a1, 0x04b92afe, 0xc231af7c, 0x5bbe0822, 0x427ce05d, 0x49f7d8ac, - 0x5d29fa32, 0x356de853, 0xe6c177c0, 0xd4e7e87d, 0xe25dfdbe, 0xf8ef54d7, - 0x58d340d8, 0xddf8eb82, 0x1ba1a7aa, 0xb1af4eb8, 0xe1014088, 0x02212ee3, - 0xf27f94f1, 0x5a62e493, 0x7cb6cf97, 0xa4625c92, 0x36cc457f, 0x129ea3d2, - 0xef3ebc24, 0xfcd2ef61, 0x305cd38e, 0x5d7ad09f, 0x57866beb, 0x2ab867c7, - 0x87a3bb6a, 0x54f740cf, 0x5577f59e, 0xf7efb178, 0xcfa002d9, 0x3c5f8dc8, - 0xb9f40f38, 0xa14ae6d7, 0xa9f66bb1, 0x2de6955e, 0x0c81a8f6, 0x4f7b639c, - 0x9ce05744, 0x52e053d9, 0xd9aef30d, 0x7ce116a3, 0x62fbbf39, 0xf7366942, - 0x44edc533, 0xa03c07fb, 0xf8e09edf, 0xf7fd5b9b, 0xccd79ff8, 0x7f65ceff, - 0xf8037090, 0x9953c6c0, 0x07c4efe0, 0x79a6e6ff, 0xc6fccf9e, 0xad10bc8e, - 0x047f4123, 0xe09bb45f, 0x2af810bc, 0x8e5c105a, 0xd037aabd, 0xa5443acd, - 0xff4f19d8, 0x09137c32, 0xf82e84be, 0x94a89e08, 0x56705d11, 0x38eddbbb, - 0xa2382f67, 0x694fc173, 0x12f29342, 0x0dc9f3b4, 0x493a5afe, 0xbf1d7f10, - 0x70cae167, 0x8a4d0bc8, 0x97be8c27, 0xdcf955ed, 0x191bdb2a, 0x3f1816c0, - 0xd2f9c9c8, 0x1840d547, 0xa3a827e5, 0xea9b30ff, 0xf547be2f, 0xfb148ed0, - 0x07f6de37, 0x8375d61b, 0x881ca04d, 0x344b5c03, 0xfdec96b8, 0x8d0a67e1, - 0x2ddf78b3, 0xe2ce3007, 0x170f1407, 0xe8edf3a8, 0x8a43c977, 0x67405788, - 0x3a46e3b6, 0xce64d85b, 0x0bad122f, 0xc1fc1554, 0x9ef09dfc, 0x96fd415c, - 0xdd730eef, 0xa102f18d, 0x4abc42e5, 0xff68d4f0, 0x3b58cacf, 0xcfd500f7, - 0x3c6768da, 0xe2170f9c, 0xb5abf608, 0x0d204135, 0x1d6326b6, 0x6bf9efcf, - 0xe6b1d632, 0x2995ff77, 0xcebf59ba, 0xaa37b4fd, 0x2148a9d7, 0xc4514eae, - 0xfba0a9b7, 0xba8a538b, 0x201b6fa9, 0x9b36c5f7, 0xca879fbf, 0x8afc6c0f, - 0x3d85c1f9, 0x6eae81be, 0xbf6bb7e8, 0x892dc3fa, 0x02e18348, 0xd716f0e9, - 0x2427d80d, 0x35be620f, 0xdb4f569b, 0x97f0f944, 0x44b9386c, 0xf793864d, - 0x42c7f60b, 0x3efabf43, 0x80be06d9, 0x0fe48474, 0x1cf201b6, 0x7b9daa3d, - 0x4c77f6db, 0x9e06e8c9, 0xd71b6ea3, 0x5c100db3, 0xd17759ef, 0x845bd05c, - 0xbe0d1fc5, 0x775ebc2d, 0xa2b3c22f, 0x5d4357d1, 0x89ef82ad, 0xfed389a2, - 0x47d385a2, 0x5139f085, 0xc05c785f, 0x620310b3, 0xf3de3f81, 0xccbecf8c, - 0xadac7f37, 0xe8357821, 0x022b1fc4, 0xeaffe85b, 0x63508746, 0x46b5ed20, - 0xce5451a3, 0x5206fbb4, 0xd503edb9, 0x1dde40a2, 0xc7a7afa0, 0xa5f7fd85, - 0x718c4673, 0x2e1ff6fd, 0xaafe8899, 0x8c22a976, 0xd3b73bfa, 0xd44e8226, - 0x7c02fda7, 0x9ec2fe1c, 0x57b4be02, 0x6b979011, 0x35ef8f28, 0x80deada3, - 0xa4772f01, 0xd50f18d8, 0x9cf29929, 0x4d0f7ab6, 0xbbcf7ea2, 0xeb90ec4a, - 0x26cb876d, 0x25b1bce2, 0xd701d896, 0x1d63c3fe, 0x58b75829, 0xd59bef2b, - 0x8f71f57b, 0x547fd0b8, 0x6f0c07ec, 0x4445b663, 0xa3c6bb53, 0xa6460161, - 0x30a1f243, 0xc18daf0d, 0x37770ef1, 0xe317e3eb, 0x2a28c493, 0x044ea9df, - 0x255ce79c, 0x2da3ac2e, 0x0aeee896, 0x4ef36f6a, 0x0dfa9abc, 0x078b8d8b, - 0xd2526b7c, 0x8abf3d78, 0xbf3865ad, 0xcfc2f122, 0x08b6b7fb, 0x65fec6f9, - 0xe9bee32a, 0x35cfde21, 0xd47e390e, 0x51cf953e, 0xe343a571, 0x4abbefdb, - 0xc9059c69, 0x0f4147be, 0xc46dfc9d, 0x39fc02ab, 0xf96162cb, 0xe735f1ac, - 0xbd21f05a, 0xa48a6cfc, 0x563d7d37, 0xc0bab2f5, 0xe8d51e3f, 0xc8ab9573, - 0xa7986f91, 0xc345b7ad, 0x78039157, 0x3a2f61da, 0x9da5f384, 0x3cdce3be, - 0x01cd3890, 0x59ea853d, 0x7aa9cfd0, 0xf47631da, 0xfc01c33b, 0x3255ea2e, - 0x8b16ed01, 0x6fd8d5da, 0x22abd78b, 0x8dabe068, 0xa2ee3936, 0x1822114b, - 0x22ee35df, 0x7f6e3f5a, 0xe9045a29, 0x970c6ddc, 0xe4a31af5, 0x452379fe, - 0xb50f9fee, 0xf969b4f9, 0x7baf997f, 0x5cfd7ccc, 0x96b61fec, 0x46fefe48, - 0xa55bf50a, 0xa1484eb4, 0xec4eadf9, 0xa7bf03b0, 0x98225dea, 0xb2f78069, - 0xa08bc679, 0x7acedc61, 0x9f3c1c97, 0x3370f5ae, 0x75f35dfc, 0xd54e1e32, - 0x7b1e3227, 0x84c93fee, 0x53feaec7, 0xbcbc784d, 0xff1e4cff, 0x77d67d54, - 0x87b43ff4, 0xf826ddfe, 0xe74dfabb, 0xdf6ec571, 0x3b97f040, 0x980fc45d, - 0x505f886e, 0x3df15db9, 0xdbe4357e, 0xe404c28f, 0x7dc2afbe, 0xfe065c83, - 0x65ce0df0, 0x4982e7d6, 0xd17eb7e0, 0xeecd69cc, 0xded0138b, 0xfb017c4d, - 0x11af2f49, 0xf8270ced, 0x3583e885, 0x7cb9bab4, 0xf4106fb7, 0x4e8e1d22, - 0xa775e679, 0x20fb42df, 0xa3dfdf6c, 0x582f8fb1, 0x2878a7db, 0x46abd96d, - 0x7c75f71a, 0xb1a7a4aa, 0x6dc8be03, 0x68d5efa5, 0xb6ef7c47, 0x020e9797, - 0xdac3aa7e, 0x81f70173, 0x8b96ff97, 0x7dabe473, 0xfbe2074b, 0xf2cfaa36, - 0xdabdbd87, 0x5d2fe863, 0x5196fcb8, 0x5533a95d, 0xefd0ffee, 0xf435f6db, - 0x89db1c03, 0x0b9209bd, 0x0a2aebab, 0x0d83c64e, 0xff07ef79, 0x58b7c412, - 0x5d3dda1f, 0xeef9031d, 0x28799243, 0x948f7c3f, 0x100f861b, 0xe40a4b01, - 0x83670fbe, 0xb08f544f, 0x470aa0bb, 0x79611de4, 0xc384623b, 0xbffd50a5, - 0xdbe397f7, 0xa1a42f21, 0xe83c617d, 0xf164caf9, 0x1b6dc9ef, 0xf04ff642, - 0x34edeabd, 0x3ada955e, 0xfbc29c65, 0x7c153f28, 0xde2fadfb, 0x04d7f4d6, - 0x9c01cfac, 0xfbcf046b, 0xa9653f5a, 0xcf502bbe, 0xe7bd68e7, 0x7337aa0a, - 0xe864df56, 0x7e9ac547, 0x52112626, 0x947e64ae, 0xe5c83b03, 0x83d4b6e7, - 0x3e7c525e, 0xd7dfc1e0, 0x35f9c1e1, 0xfa384934, 0x62455e12, 0x8d1a7520, - 0xa2d5213b, 0xc0140fdb, 0xe39b443d, 0x965afd33, 0x1939f2c7, 0xfd1d0388, - 0x4b4ee3b3, 0xfc064ef5, 0x670ffd7a, 0x75f1cbcd, 0xf2e86e73, 0xb2deddbc, - 0x57b6700c, 0xfc7f5939, 0xeed44500, 0x41615989, 0x8a7a1a35, 0xf9f40d73, - 0x0e0b91a3, 0x8c7c26f6, 0x43cdf28f, 0xbc6fb3ff, 0xcaf2357e, 0x72f77881, - 0xeb7173d0, 0xc2efd648, 0xbca3377d, 0x981be1d2, 0x373c5340, 0x062837c0, - 0xbc517c87, 0x9451275c, 0xfc2dd453, 0x45629e12, 0xe518df8e, 0xc53f472b, - 0x5d8f2396, 0x23d66f81, 0x8d106f6c, 0x739fb9bd, 0x9dde5176, 0xe1e3affc, - 0xfd8f3698, 0x25ed7136, 0x75fedf9a, 0x82069e31, 0x1bceecb7, 0xba50d417, - 0x109452d0, 0xdf704d54, 0x575d4a96, 0xf6078bfa, 0x9cee7925, 0x4ebb834d, - 0xcaeadb83, 0x50e7ee34, 0x79741bb8, 0xeb0a17e5, 0xf947fc83, 0x81b1fd17, - 0x661f29bb, 0x74c1f8b9, 0x16395b9c, 0x886c93b6, 0x7a45bda0, 0x9c1a3be4, - 0x73bed28f, 0x35f7f1c4, 0x21189ef8, 0x683e27db, 0x507ec009, 0xaf0f7634, - 0x4ed513d3, 0x15634a8f, 0x721db70b, 0xb2f0a950, 0x31d7fcfe, 0x4ad7db7f, - 0xf54e6af3, 0xddbc07dd, 0xfe496f1c, 0x0df0e180, 0x6b790a9d, 0x3fc79cb4, - 0x1e793790, 0xc6cb84d3, 0x6b589942, 0xcd31fc81, 0x50b2a725, 0xba63fb91, - 0xde30daf0, 0x7ae3e14c, 0x7bb79def, 0x07bc4fa1, 0xbee0885d, 0xfbf9f851, - 0x74e0111c, 0xfd72089e, 0xe72b449b, 0x7d137c75, 0xd24bdcdc, 0x547d27c7, - 0xc056ffc6, 0xee646efd, 0xc79a3a80, 0x650687d4, 0xdcd57eb0, 0x5df3f19b, - 0xe8d54f70, 0x6feff686, 0xbfd88eb1, 0x699fa833, 0xdfec8437, 0xf5f5bdf1, - 0xfb47f8cc, 0xa74748e8, 0x4bece4fe, 0x5b4eb878, 0x4bbcebd2, 0xc2127f59, - 0x8fd1f2c5, 0xa85b7db4, 0x5a2f453a, 0xd26e239f, 0x89960897, 0x62259663, - 0x10afafbe, 0x3ad0156f, 0x15463ebe, 0xcbd35c0d, 0xfd68a6ed, 0xe13fe94d, - 0x0f5bd833, 0xe1af608b, 0x92f0aed4, 0x8218d5ef, 0xbdba8a7b, 0x27ca9631, - 0xc6bd27f6, 0xefaeefc0, 0xfd0ac3b5, 0xf37486ee, 0x66d949f7, 0x68b267fd, - 0x94fe3152, 0xfb7ae6e1, 0xb3a22781, 0xfea553f7, 0x21888622, 0x0b7af2df, - 0x1d3e718b, 0x2fda2e93, 0x69111c10, 0x2eb18fbe, 0x75ff27cb, 0x5615c601, - 0xb7ea9f39, 0x1debb655, 0x288b7927, 0xa7ac9c50, 0xca532293, 0x4a7fc825, - 0xd3d203f2, 0xcf4e6ef5, 0xf28f79d2, 0xce1ef5f3, 0x9d15a417, 0x6b25bf40, - 0x7d62b73e, 0xf8970cee, 0x9a696f2e, 0x762ab000, 0x5a441cb7, 0x809a2c16, - 0xa1d17663, 0xef4883da, 0x6adbd4ec, 0xe1d3be59, 0xd3a345be, 0xfda6a25b, - 0xe1d68730, 0x87aa3d96, 0x4da603f3, 0x790bdc9f, 0xa27be71b, 0x444baaa3, - 0x54572433, 0x012fdeab, 0xdb6f7797, 0xdf9a78c1, 0x18a3f527, 0xbdeacfee, - 0xfa99f70c, 0x4a4e9c89, 0xe81bfa2b, 0x673e2bcc, 0xf6f26c79, 0xd5126b36, - 0x5e2af42f, 0xbd6bdbec, 0xfda01022, 0xcf26deb7, 0x0e74f581, 0xc98f1f60, - 0xade8f699, 0x67da7c02, 0x6671a34b, 0x10a4b0de, 0x55194ce3, 0x1bbd456c, - 0x201921bf, 0xbf4e8ba5, 0xf9f5ee8b, 0x76eb6957, 0xf18565ee, 0x2d33b1d8, - 0xf2c17206, 0x907d695d, 0xf5d4bf12, 0xade048dd, 0xe18592e3, 0xc11a38ec, - 0x6ede86fa, 0xe648aef9, 0xd807cb3b, 0xb760c203, 0x2ceb433c, 0x99e6f20c, - 0x36e27e67, 0xe2672b9e, 0x18fabe5a, 0x922fedfc, 0x736491bf, 0xbff011ea, - 0xa03cfdfe, 0x9c9af393, 0x24467a4d, 0xcd6abfce, 0x84fe08ae, 0x690899fc, - 0x6cf91dcf, 0x2fec58d2, 0x4e1c478c, 0xf32bfce8, 0x7f5287d9, 0x6f1aeeee, - 0x8fc2cb5b, 0xb9fca11f, 0xa36fc580, 0x689ce9f3, 0xf03bff39, 0xb64ecddf, - 0x10a9ddeb, 0xb77f383c, 0x967ce3f4, 0xc3a88d62, 0xbc022bf9, 0xb714b3bf, - 0x55f88eb5, 0xf70f73e5, 0x44bdfd03, 0xe5451838, 0x648bad2f, 0xcd92f67e, - 0xfd0eac73, 0xfbfb2a3d, 0x3d3fbdcd, 0x3de91bbe, 0xc53ff955, 0x31c5a4f2, - 0xb57ecbfe, 0xd3da0864, 0x52fa2ef9, 0xa8bf4f7f, 0x3f69c304, 0x5fef34e7, - 0x1be097d9, 0xd2cda1b6, 0xcdbcd28f, 0xa1d2034a, 0x04386e03, 0x690df3bb, - 0xb05f6e6e, 0xc24d453d, 0xf817ec36, 0xee7c07f8, 0xec81e59b, 0xf6c7cfe6, - 0xc1725d13, 0xf4e5a510, 0x2c358246, 0x8fbe68f9, 0xf3c4d7f1, 0xfa77b5d9, - 0xe604f3fb, 0xe0071241, 0xf87bb62e, 0x37f80a1c, 0xf9cf3d62, 0xd7ac3cb2, - 0x061ff915, 0x25f39d9d, 0xbd2e7078, 0x55fc7a40, 0xcacc7fa8, 0xf3717cf3, - 0xebb0d1bb, 0x1c7e90c4, 0x5e487f0e, 0xafd404fb, 0x7e16e01a, 0xb1e03f6a, - 0x3f0226eb, 0x6d773bd5, 0x1d2a7ee4, 0xe5b9e81e, 0x4c1e2ebb, 0xbd789c82, - 0x0e8064f0, 0x2ffcca77, 0x2a3d7bc7, 0xe37cb54d, 0xa47f3297, 0xa445f388, - 0xbf515a75, 0x0f47ca54, 0x689fe769, 0xc8fe65cd, 0x5aeeeda4, 0x31525faf, - 0xf8a7d7ca, 0xadaec2fb, 0xde749b9f, 0xab61a555, 0x23fb65d8, 0x3325e763, - 0x79e7be5e, 0x2dced767, 0xec87bfbd, 0xfd4e1fc2, 0x3b036cc0, 0x3cbb06fa, - 0x7f10b7a7, 0xe7e8bd01, 0x0bfb8d34, 0xef6a5fec, 0x524d3f05, 0x849d9c95, - 0xc287a48f, 0xbef8ce58, 0x598ecfe3, 0x2eb6e7cd, 0x4844d567, 0x0567c83e, - 0xe5185fb5, 0x5bf30bbb, 0xc2f39da8, 0x1c86ceea, 0x7bca2332, 0x3a57be37, - 0x073193da, 0x45ef3f3a, 0xb9255abe, 0x7720cd2b, 0xd7bee339, 0xe51759f9, - 0xbe7cc66d, 0x91b1fd6f, 0x520c6704, 0xad22cf5d, 0x9c7e5ba3, 0xfc05bdba, - 0xc93081f8, 0x980aa38f, 0x0bf3e91f, 0xda15ffed, 0x33e23ef7, 0xe279d1af, - 0x738fdc23, 0x7af2b18e, 0x3ca96abe, 0xa170e748, 0x6c84011c, 0x79ce1d8d, - 0x6fe1146f, 0xbe1553bc, 0x3d45f46e, 0x1e7af5a5, 0x2bd099f8, 0xb0af54d2, - 0xfb1dac57, 0x5bcefbf7, 0x8d47d6d5, 0xbba9f9d0, 0x37767097, 0x5bcf396f, - 0x01f447c2, 0xdf2ac65e, 0x5b0ebe6f, 0xc3ac41d1, 0x9f1e6738, 0x539ce38b, - 0xc304f98f, 0x43df187f, 0x1f3a19e7, 0xf27ef8e1, 0xe1158fd2, 0x7dff60b7, - 0xdafb676e, 0xd3eb5b5e, 0xee7c25bf, 0x81ed925d, 0xf005e89d, 0x68cff05e, - 0x7bb3cb3b, 0x7c1f84a3, 0x84d4ef65, 0x2f45ec00, 0xdf044f41, 0x79642de8, - 0x77bfacb8, 0x7f53950e, 0x5f68c2fd, 0x2f345ec0, 0x069feb42, 0x7d15fb46, - 0x52837db8, 0xda0e66fb, 0xbe6488af, 0xf9203473, 0x706c7378, 0x9bdf4a9e, - 0xa814cf3f, 0xd6045477, 0xeddea2a4, 0xe5435fd2, 0x6fd43549, 0x122192f3, - 0xf951ffce, 0xf3ce68dc, 0x32738df6, 0x4cfb671f, 0x5f6f54f3, 0x697aaff8, - 0x51bcd5eb, 0x3d83f796, 0x9429e514, 0x9b63f4a7, 0xab573fac, 0x974691f7, - 0x0f99cfb4, 0x5a44a6f8, 0xd2fde741, 0x99d2c24b, 0xc2fb7929, 0x5948f3ef, - 0xe728db06, 0xc29f5c56, 0xcbd9a3f4, 0x5b7c6b66, 0x1c0d0fef, 0xcb2f2123, - 0xb70b39bf, 0x679e8384, 0x41b78796, 0xbe5a3bee, 0xfb7a0a32, 0x0c1a9f4c, - 0xa3395c83, 0xaf29dbd0, 0xaf5c62a5, 0xd74cb71c, 0xc0a582ff, 0x0eedcbeb, - 0xf7cb3771, 0x3ea302c1, 0x556fafa5, 0xa37898cb, 0x27615cde, 0x2cf042fe, - 0x9a6df6d1, 0x7d3bd7d3, 0xebe9f404, 0xf4fa8de3, 0xe40f65a7, 0xc6d2fef2, - 0x8def5b3b, 0xb90e993f, 0xfaa7226d, 0x0f7a9d78, 0x57e74dd6, 0x25db97a0, - 0xfb6b08bd, 0xdf298b47, 0x07887b30, 0xd389eaf6, 0x1d6f4c1c, 0x1f2ce12d, - 0xf08ecc37, 0xb0d76ec2, 0x06ed8c2b, 0x83fb6b37, 0x1ba628f4, 0xee28beff, - 0xf32ed2a7, 0x3065cf95, 0x0f60bcdd, 0xe515b93c, 0x7fb3872f, 0x8e5a32b6, - 0x24bbf95b, 0x29bd2e8d, 0x5fb17aab, 0x32a5e98e, 0xe5c31dc2, 0x7a678fbf, - 0x57dc367a, 0x7d127c00, 0xd2bc5db2, 0x258ccc1e, 0xe8d31ffc, 0xfb237a0f, - 0x98a36af5, 0xf796856e, 0xf59e3cfd, 0x797f9238, 0x437ddf3c, 0x7bb3ef39, - 0x3ec42efb, 0xf0c91e5a, 0xf2c9731c, 0xbcb19563, 0xb7dfe60f, 0xc5fc30f4, - 0xbcec8ac7, 0x55ed8e5f, 0x73fade59, 0x9f841a9d, 0x9acfa75b, 0x86dfc725, - 0xe1baa8f9, 0xd4dde4a3, 0x5595fccf, 0x7e6ed093, 0x7053edc5, 0xf69af6de, - 0x4369fb29, 0x4afcf3f7, 0x97d47fb3, 0xf98c9dee, 0x760764d5, 0x1e7ea41c, - 0x116a739c, 0xee9fd3d6, 0x3ef5869b, 0xe17d6f6f, 0xeb77044f, 0x5eb23f8a, - 0x6fb47d74, 0xd85fbe26, 0x5fae1bf3, 0x16bff2bd, 0xb6afce41, 0xcfd17a4a, - 0x7e8d1ae3, 0x1e6f8645, 0x7cae57ea, 0xc881f59d, 0x7f9223ec, 0xf8fdfede, - 0x5bbde9ce, 0xdda8505e, 0xd5bd88d2, 0x5c81aa9c, 0x94676b9c, 0x0692b460, - 0xed3d4a7c, 0x8d182bac, 0xa459f175, 0x5b74b89c, 0x4b181f88, 0x7fd9a091, - 0x16d2dda8, 0xf242bf19, 0x19f41d82, 0x7d297f5a, 0xf3df7ae7, 0x9168857b, - 0xdf7763df, 0xf75cb57b, 0xfc387060, 0xb09b19ae, 0xfd76e7ee, 0x77e8d326, - 0x872f4d0d, 0xacffce57, 0xeace5fb6, 0xbdb665fb, 0xb9005ed3, 0x7d33fceb, - 0xfe76744c, 0x3f9cc1c9, 0x112bb4ad, 0x577f974a, 0x72465a78, 0x65b78d7c, - 0x07e7e424, 0xe34befb5, 0xaf82465b, 0x384e7ce9, 0xff59725a, 0x85c96acf, - 0x47f3abbe, 0xc992d451, 0x992d03df, 0x4582ff68, 0x8ff853da, 0x3a78a8e0, - 0xd2dde369, 0x0cb7e10f, 0x26e87e47, 0x1a71f5e4, 0xe91f25c2, 0xa58fbe69, - 0xf9e63b4b, 0xbd9bf639, 0x7ad07f54, 0x707ca9bb, 0x9adf9cc0, 0x03e7ed2e, - 0xfa6fe243, 0xc3fbeda9, 0x213c8e70, 0x3fd7f5ba, 0xd4f38da3, 0x3c719d53, - 0x0acfa6aa, 0x6e1f4eb7, 0x80dbdf29, 0xf13a8fef, 0xf1126b7d, 0x6398a5e5, - 0x9e5fcf2a, 0xfb494f67, 0xbe790bcd, 0xe7179c24, 0xff821781, 0x67ca5885, - 0x7892be43, 0x3e3af3d5, 0xf2bfe743, 0xb04945a3, 0xae947edf, 0x7d3cf9db, - 0xde3a9740, 0xefa46c1a, 0x2e3f4364, 0x8569382f, 0x2c49ecde, 0xdaec1ab3, - 0xd81cf3eb, 0xe4378b57, 0xd6748c39, 0x10e0adb0, 0xece21c49, 0x2007ab36, - 0xf7035837, 0xd86f7e42, 0x05f8b6a6, 0x54bc3b97, 0xc0f3acff, 0x68b7a8db, - 0xe43e6c43, 0xe2fdbd6d, 0xcb1223f5, 0xdd0e700c, 0x9c875e66, 0xd87e7316, - 0x04fe736e, 0xffde80ce, 0xa0bcbb7c, 0xc8705f39, 0x83e4ff9c, 0x9c81675b, - 0xbdff55cb, 0x3f89f42a, 0xf384384d, 0x5e17d3f1, 0x2cfac68c, 0x41d94bfd, - 0x71a149e8, 0x0a6eb422, 0x56ff08f4, 0xb2e3e985, 0xf81e9178, 0x810f1e81, - 0x93a4619d, 0x683fe10a, 0xfebcb94d, 0xcb32d119, 0x5955744b, 0x64e0bcb7, - 0x57bf5741, 0x43b3acb6, 0xb71d0bce, 0x9c2ffda7, 0x6aec375e, 0xd964a3c5, - 0xc5637555, 0xd62df809, 0xf4013bbe, 0x854bfc57, 0xe7e28ae5, 0xbe0abd07, - 0xce63b6df, 0x9ace9c0d, 0xedd0f8c8, 0x2af78b7d, 0xbbca28c1, 0x5dba4946, - 0x7d615eb8, 0x1cd1a4bd, 0x36b65747, 0xd9a6de24, 0xf778be5c, 0x9f86fffe, - 0x18f1dcbe, 0x1e5c33c7, 0x05781827, 0xa7c55b7a, 0x153ded82, 0x330dbf9b, - 0x2d79cb97, 0xbfe1e7d4, 0xaee1e396, 0xcf3a5592, 0xd0c893b7, 0x574bf0f9, - 0xe1066a51, 0x8de6aafd, 0xbd9b94aa, 0x7597ecc5, 0xb0ce39da, 0x918221ca, - 0x28a1cf04, 0xdf45d7bb, 0x628fae2f, 0x18516179, 0x9cf99fc9, 0x438e708a, - 0xdda0c4f4, 0x965477a9, 0x25e2aa83, 0x571eaa1e, 0x56c5b002, 0xfc8a48c1, - 0x04bf3213, 0xd25526de, 0x3f00d78f, 0x1798cdd6, 0xab6f524d, 0x03f706b4, - 0xc0e79d2f, 0x4abd7336, 0x38d1e79a, 0xefe659c8, 0xeb9da2d5, 0x36feecd7, - 0x60ddf8cc, 0x527d65df, 0xc8556bd7, 0x7aa70433, 0xb3cb0447, 0x402398c4, - 0xef14ab57, 0x29150ec3, 0xefa0e39d, 0x2f964e25, 0xe7946ee6, 0x838c3347, - 0x0dd78390, 0xae67b966, 0xbe04cde2, 0xd670bac4, 0x1fdca9a7, 0x64e58bde, - 0x4e484396, 0x7daa3966, 0x12e39d8e, 0x825af39b, 0x1f9ac790, 0x0ad0f148, - 0xf3e47f32, 0x96709ee8, 0x4aa79a7b, 0x5d79a7b9, 0x31ff6e1f, 0x390beb40, - 0xf9b9e25a, 0xb71e1c9e, 0x89db2a9f, 0x200f523e, 0x7a133ab9, 0x41e5c102, - 0x67472eb9, 0xb04afac5, 0x9bfcfaee, 0xe0a3db63, 0xf1e512c7, 0xd86e4bdf, - 0xed879da2, 0xf003c2eb, 0x8a549c53, 0xf60c5a0e, 0xe4325ba9, 0xac7231f9, - 0x8f56ab77, 0x966519fd, 0x80ff77a9, 0xd07b29e0, 0xe9486ee2, 0xf5e1075a, - 0x27fe6266, 0x83e785d7, 0x958e46ee, 0x7963a7f6, 0x0e479f92, 0x73bf1c17, - 0xedefd6bb, 0x9a531619, 0x48f44118, 0x942c9cfd, 0xe1a8edf6, 0xa4076c45, - 0xbbb9ba35, 0x19359038, 0xb32a9cf2, 0x9afefd17, 0xa4e9e06e, 0xde52f18b, - 0xd94cb93d, 0x72f2e124, 0x5fc8dfbc, 0xf0fdb385, 0xe8de76a4, 0x347441eb, - 0x8d71cf82, 0xe8d3ad9f, 0x74cf5d66, 0xb98ba263, 0x3741b790, 0xd8b9e473, - 0xfada5749, 0x7af0dd12, 0x485d13b7, 0x6be211ba, 0x4b742fb4, 0xdf443b79, - 0x7bb7d4ea, 0x0e88b7d0, 0x6de8c89e, 0x074217a8, 0xf1181ac2, 0x252cfc8f, - 0x2a4762a3, 0x564904b4, 0x2cdc47e1, 0xd7c646ce, 0x4ac0d65d, 0x55bfa782, - 0xab00cbae, 0x653a3ba4, 0x5cf911fc, 0xd9f88bdf, 0x0b17fbe2, 0x4e2fd52f, - 0x4ab76c12, 0x2626f927, 0xa409db8e, 0xb0aa0770, 0xf68a50e7, 0xffb231c5, - 0xc46fa262, 0x5e7f51b3, 0xdcc69c4b, 0x2a7fc246, 0xfb407e58, 0xef6e7ce8, - 0x5ef6c8b7, 0xd303a52b, 0x5f6a3ee4, 0x2bf8c615, 0x264073be, 0x58d264e8, - 0x66249d33, 0x4f41394a, 0xbadd331b, 0x7e0890dc, 0x9838d250, 0xf08699cf, - 0xd85daaa2, 0x7d48cfa7, 0x4df578a3, 0xbe004793, 0xd83de367, 0xeca7a7c2, - 0x494aff60, 0x7f1f9ce3, 0x5b653d08, 0x98df7f38, 0x780f7be9, 0x17b8ad3f, - 0x250fa2ec, 0x27b15f33, 0xcb5f7b52, 0xa3bf73d4, 0xc77f8a74, 0xa62390db, - 0xfeb950cc, 0xb9ed2114, 0x338e51a2, 0x35b9ffd9, 0x3c9bfa91, 0x94f0e15a, - 0xf25770b6, 0xb455f832, 0xd1a63df5, 0x98b84377, 0x70139cfd, 0xcd4cc80d, - 0x24821f86, 0xe4e46ed4, 0xfd5a9901, 0xc806ca31, 0xc9c70343, 0x47d7a7fd, - 0x2d37e83f, 0xcfb7ee53, 0xe7a77db4, 0xbf5caf09, 0x5b584d6c, 0x5b52345a, - 0xf3a51070, 0x039ec6b2, 0x2a94999f, 0xde07ac26, 0x4d8aaa7f, 0x317b6f0c, - 0x4ca885f3, 0x8f82f837, 0xfba65914, 0xee99836d, 0xb7b4c6db, 0xb6f949dd, - 0x7ed2392d, 0x0bf3e9a7, 0x82e5825d, 0xef9231b6, 0x64896fb5, 0xd5cc73fe, - 0xed27151a, 0x97dfac5d, 0xd7f1246a, 0xe17b86ba, 0xda752e37, 0x2c7e70db, - 0xfb3a607c, 0x499b4bfb, 0xfd5c47bf, 0x4f7eb35a, 0x6658787a, 0xa87afa37, - 0x019a0e5e, 0x55ad951d, 0x36070e98, 0x997dec78, 0xcc2e29cf, 0x4c19ccaf, - 0xf32fff07, 0xf05c7384, 0x37fb7a65, 0xb091f784, 0xba0e0b1f, 0xd7c83a1a, - 0x3716e30b, 0x1a7eb315, 0xfe63ed99, 0xbc255035, 0xd4cf1d10, 0xec126fe8, - 0xd64be0a0, 0x97d8bed6, 0xdf6865af, 0x4e995ce3, 0xbe70eba6, 0x7366d06f, - 0xb6be0265, 0x9c16e155, 0x4a5693b7, 0xe77da6fa, 0xbb80bdc0, 0xfc0222ac, - 0x7ed6b8e0, 0xd16b0afe, 0x77f7ca46, 0x1c546b08, 0xe98f2be8, 0xfbe5903b, - 0xe9f7eb0c, 0xc828c42f, 0xd76ba50d, 0xfa34b849, 0xe323d610, 0x4f9c69e3, - 0xc3e4a4b7, 0x53d3a0ae, 0x766c6b20, 0x5d0308e6, 0x1e9850cc, 0x60873e68, - 0x55979d9f, 0xfa728f92, 0x32f41fbe, 0x1d306c69, 0x6a85d871, 0x76abc725, - 0xe20f0a24, 0x3b443a87, 0x241d23cb, 0xea3f808f, 0x27e7467c, 0x475e1744, - 0xeb7ad742, 0x3d6b657c, 0xde784681, 0xf4e0ef56, 0xb0977aa9, 0x5ed84f12, - 0x67f9c89f, 0xb69cddeb, 0xf7f167d4, 0x9c3deae7, 0x8a3f59df, 0x7bd42ff3, - 0x7ebbbf39, 0xabbfa722, 0x84efe22f, 0x3a4be61f, 0x93f9d1df, 0x9f3a5f4e, - 0x05aba50a, 0x33dc6684, 0x0fccf6a0, 0x79883e75, 0xf8bbf258, 0xa9cebe93, - 0x113f914a, 0xceb450fc, 0x5428ff01, 0x22f33ecf, 0xdca3b9e1, 0x1da1f1c9, - 0x0ec1f242, 0x8dcf83a7, 0x0dd8bb64, 0x32c340fb, 0x869ddb6f, 0xb95e7873, - 0xba06ac22, 0x5c36a9bd, 0x7d740d58, 0x29ac5d73, 0xfdeebf3f, 0xff50fad7, - 0x2df18b3f, 0xbb1cfac2, 0x7fa3d4e3, 0xdf8fefa4, 0xeb033a71, 0x796c704e, - 0x1edee308, 0x2ad1c1a1, 0xceddbae1, 0x08c0d2f2, 0xcfe14fa9, 0x2d738861, - 0xfb7d894e, 0x31e70437, 0xda061d6d, 0xc146b35d, 0x754ab32e, 0x1f2aa4ad, - 0xfbe8bd63, 0x2af5b59f, 0x7c630ba9, 0xfb6a3496, 0x4cff18d4, 0x57de3cf8, - 0x78a75cb0, 0xe91f8085, 0x41ec2ff8, 0x71c41192, 0x685011c5, 0xad94851c, - 0xae17b0f9, 0xe428fd79, 0x10eea574, 0x873ed5cb, 0x8428e393, 0xd8d676df, - 0x9077529f, 0xfed689eb, 0xc8c838a6, 0xf83b5ee1, 0xeb1b6805, 0x40759256, - 0x268b9f60, 0x94f1ef85, 0xd6cbdf69, 0xe2f8a628, 0xe655337b, 0xac32878b, - 0x14ca0e9c, 0x89a5139a, 0x5e9d29cf, 0x3c707f89, 0x9e535963, 0x2f81917d, - 0x4bdf6897, 0x78a62cb3, 0x321943c7, 0x98106a2e, 0x6777a505, 0x3217daa5, - 0xdc7373df, 0x24bf5ebd, 0xea757f2b, 0xe883f470, 0x8ff6aea0, 0xddb95a64, - 0x84970ca1, 0x59e741c7, 0x74e9c714, 0x72e82e7b, 0xeff8a7cc, 0xeb3f0c95, - 0x3ecf1559, 0x7bfc2cfd, 0xe30a7f15, 0x9862a9f3, 0x0ec8df66, 0xf2ce9c8c, - 0x8ca9d78f, 0xd72dfc84, 0x7fd3fc7f, 0x547c4689, 0x57694ecd, 0x690db4a5, - 0x6ce5edf5, 0xd0f6ab57, 0x9f0388fe, 0x5fcdfb35, 0xd14ff67d, 0xf897acad, - 0x5bf8b493, 0xdeaaf78e, 0xc0e38279, 0xd0afb8f4, 0x37ca3576, 0x71eaa7ac, - 0xb63fba01, 0xf78d9f70, 0x851ecd4d, 0x5d9a98f5, 0xe7c01317, 0x4aadf66a, - 0x272e2ee8, 0x5e3d5fb4, 0xd5bfb740, 0xc39fb588, 0xc384487f, 0xffad0ff8, - 0xaf546676, 0x62054353, 0x3b60aed5, 0x1c705588, 0x8e2d72c7, 0xc19023b3, - 0xe49ee17e, 0xc4f59aed, 0xedbf49f0, 0x1063bab0, 0x88417caf, 0x53addd89, - 0x7e7920fc, 0x047da39f, 0xed85f0bf, 0x1791cb2a, 0x7ef147b6, 0xff7edea8, - 0x55dbc441, 0x8dd8566f, 0x308e2557, 0xaa77aade, 0x0fe061c2, 0xc50bb035, - 0xd2e70cf7, 0x416aa3a7, 0x145a4b5f, 0xadf816ef, 0xde98ee1d, 0x35da7806, - 0xd61a5afa, 0x45d79232, 0xf814ff83, 0x5cce419a, 0x8e7ef7b2, 0xe77aa413, - 0x6df9ae59, 0x51b3c724, 0xce036f0f, 0xd80a1b33, 0x65a4bd4f, 0x05cb3547, - 0x105d23db, 0xccdb4e69, 0xd1be29f7, 0x9346fbc6, 0x4fc0ced3, 0xaacff682, - 0x4e030f2c, 0x5ad3cbec, 0xcedeab3c, 0xb3b64832, 0x0dfb7868, 0xae88e7f6, - 0xda5a4bfa, 0xfea9d3a2, 0xe7dfbb27, 0xee4839d4, 0x23ce25e3, 0x3f4738b9, - 0xf7c919d9, 0xf9d93eed, 0xd12f09eb, 0xc65ae778, 0xfb0c52f4, 0x1b20e06c, - 0x41b73fd7, 0x25f301c6, 0x5a0fd611, 0xb6673e78, 0x27ac2927, 0x9f84df03, - 0x8f9f3b33, 0xf63ef0b6, 0xab717bff, 0xc86b15b3, 0xb2eb847d, 0x5bfe8047, - 0xed11fbb5, 0x7fe5fd9a, 0xed6affa7, 0xa4529b7b, 0x3bef238d, 0xc20e3d08, - 0xd53beda5, 0x796efbc9, 0x2fef9d94, 0xbee6182c, 0xe8f81e71, 0x518e329b, - 0x043f77f4, 0x3bc16ffd, 0x596f6cf1, 0x41f7736e, 0x36c38bfe, 0x282c13f6, - 0xa1f51cf0, 0xed9d8c7e, 0x75b1224a, 0x6dadec04, 0xa8be5229, 0x933b435c, - 0xe88fdc50, 0xacf84fcd, 0x8f84580c, 0xa50793f2, 0x523ebaf2, 0xd9daf16e, - 0xfbe413ff, 0xc2ecc792, 0xfe2f7b8f, 0x5d7ea4e7, 0x0efd2a99, 0x517f608f, - 0xcc17195a, 0x4edd878c, 0x69ca9ba3, 0x9fa06e54, 0x4cc14dca, 0xed674fc8, - 0x72891ed2, 0xf9954de8, 0x46835eb2, 0xfd07e8a7, 0xceb8a5b6, 0x2bbbbcb3, - 0xb0ef404a, 0xed2518bc, 0xdf09bf21, 0xaf386614, 0xe9241a6f, 0x07f341b8, - 0xf848b7fa, 0xf8e41700, 0x4ca6f625, 0xb8fab9c8, 0x789ba24b, 0x78dab3bc, - 0xa49a224b, 0xc78b44ff, 0xdf1e7d43, 0xd3bfd826, 0xcb1864fe, 0x1efba7cb, - 0x9fe30179, 0xc730727e, 0x04a5b411, 0xf2e6ed16, 0xaee38e70, 0x082c2a78, - 0x327b3f78, 0x9f58ed8a, 0xf61ca4d9, 0xcb025459, 0x1ea28761, 0x3afe805c, - 0xe0298736, 0xc2299fa3, 0x2df2889e, 0xa80e59bd, 0x3f63afa8, 0x17b10549, - 0x4e94afc8, 0xd9f7dc84, 0x276cc196, 0x950decfa, 0xf7d0292f, 0x13eef835, - 0xc67e0b4d, 0x3ff4bff2, 0x6fea7e9e, 0xaff3bb83, 0xdb366c54, 0xd7f5f4c3, - 0x2418efcb, 0x0c7703ed, 0xcac97a92, 0x7fe92e41, 0x30796c8b, 0xf929e795, - 0xeb03ad03, 0x131fb47f, 0xd63f6f60, 0x714127b2, 0xccc1cf02, 0xdbef035f, - 0x7a759ea4, 0x42fd8dbb, 0x79462f15, 0xe774fed9, 0xb0ef7c15, 0x78729542, - 0xdbde4585, 0x99eed0ab, 0xb2674456, 0xcdf08b7d, 0x16fb6d7a, 0x8e471b55, - 0x01d6d9fb, 0xd4109fd2, 0xf0e42ff2, 0x7149b83d, 0x2c69e6e2, 0x05c86d5f, - 0x8e6e2f5e, 0x1a79f8e4, 0x87b88bc7, 0x5cfd9f8a, 0x116633e2, 0xae7407eb, - 0xd4ae7f31, 0x9dd573f8, 0x5ee0c757, 0xe5477881, 0xad1712fb, 0xbfe03e9e, - 0x4f7af8a1, 0x5f4b63e3, 0x41f99478, 0xc417ed25, 0xfcd52d59, 0x529f4bcb, - 0xba5c9e58, 0x9887eafa, 0x136dbeef, 0xb6705fb8, 0xe368fee5, 0xf8d5ec7a, - 0x0f7b5767, 0xf54a5fd7, 0xa337fb65, 0x36ad9e19, 0x5d09e00f, 0xfeddefc7, - 0x6a5ff529, 0xf242d15f, 0xf3e5ee45, 0xdc8e28bf, 0x95f027f6, 0x676ce1ed, - 0x7be7f5a3, 0x2d6c6746, 0x33ff308b, 0xbf3384cf, 0xf72b1339, 0x9e7427fd, - 0xe780edfa, 0x5db1f787, 0x02e9bded, 0x80e2d0e7, 0xae1d5fb9, 0xafdf1afd, - 0xc0c4f78a, 0xeb45534f, 0x7d68fe81, 0xdfedc47e, 0xd0fb71b1, 0x768e3cf9, - 0xf4fb0c23, 0x9ba64899, 0xbae4fd33, 0x1076799c, 0xb16d679f, 0xde09de92, - 0x674be864, 0x1b8a6562, 0x0a87a03e, 0x3387a497, 0x1ed85a63, 0xc1d94670, - 0xb64d9b69, 0xfcd3a8ab, 0x897f44da, 0x26d01fa0, 0xb58ea9ec, 0x80c72047, - 0xe7cc8fcf, 0xcefb8834, 0xd07376a1, 0xbebfce29, 0x84dcf259, 0xcf3e0578, - 0xe3f61b7e, 0x733df0b4, 0x564f269f, 0x4fdcbf6e, 0xdcaa7588, 0xeb3fb0ae, - 0x02fe7692, 0xddba5eea, 0xa972e89f, 0x6e22f15f, 0xb2e3696b, 0xa5fba025, - 0x81e6ebb5, 0x2c79f5ee, 0xb75feed5, 0xd3c32a29, 0x27fb4e16, 0x74f1f2fb, - 0x8a59aafc, 0x5c279f1e, 0x7b45f9fa, 0x2dcb2c38, 0x4db288e9, 0xa3655fd4, - 0x49c796b2, 0x395bf5d1, 0xb84f1d3f, 0x5efb02cd, 0xb9df769b, 0x70ebf9a7, - 0x524f04f6, 0x6d4fe496, 0x6f9ef229, 0xbef25bfb, 0x0a6fc5f6, 0x81fee262, - 0xfa91c83c, 0x7f047f7a, 0x72106816, 0x96e7c68f, 0x704eaec2, 0xfb306e66, - 0x9b36b273, 0x9bb643f3, 0xcd3bd9f3, 0xe6bddcf9, 0x7355e7bc, 0x7b7185de, - 0xfa09e177, 0xa103e236, 0xbe85236f, 0xfa94ceed, 0xb7d0f236, 0xc6df4291, - 0xc8dbe877, 0x1e46df43, 0xd0f236fa, 0xdf4291b7, 0x1a39f7c6, 0x7b352a9e, - 0xe381d629, 0xeb84f6d4, 0x5fbc00f1, 0x6049cc2e, 0x52ac2a3e, 0x24b0bd1f, - 0x4ec7e59b, 0x0754d33b, 0x38f499db, 0x7ca2b7a7, 0xc37ab2e3, 0x75647b7f, - 0xc76e14df, 0xdf9ae7f6, 0x6573fb49, 0xf613b87e, 0x9f55d68e, 0x13d886ac, - 0x444df288, 0xf6b60bfd, 0x556fc0ad, 0x6fec2bdd, 0x7ee15d6f, 0xfd7207e7, - 0xc7a2eed8, 0xdce3152d, 0x7d26df03, 0x7b6fc649, 0x6a3b461c, 0xac485fa8, - 0x3f21e435, 0xa1f39b35, 0x35f0207e, 0x355f69af, 0x6e3c1d31, 0xbe0bef6b, - 0x0749e27f, 0xa13af3df, 0x6cc4edd9, 0xba63cb17, 0x8f29df3c, 0xc26ca3dd, - 0x2b24bdf9, 0x1c77db8e, 0xd3dd30ca, 0x2f4b4d0b, 0xdabcb3e5, 0x58ab5f99, - 0x8cd94e30, 0xaf59fb15, 0x73e68c4e, 0xb60d16e9, 0x0dff9041, 0x440e0f70, - 0xe868e898, 0xbf10b8b6, 0xfd533f65, 0x4353bb61, 0x4c4396fc, 0x16d7d3e5, - 0x17b5ef98, 0x1f2a6d5d, 0x878cef68, 0x96ff4873, 0xd64b9f06, 0xe7cce8b9, - 0x4bd686f9, 0x847f3c56, 0x25bc56bf, 0x9a32d3e5, 0x7b40b787, 0xfe1f239f, - 0xe014ef39, 0x16c5bcaf, 0x54bef38b, 0x9d44873b, 0xb72e5cf9, 0xae2bbf0a, - 0x5dcaee8b, 0xed4b1bc2, 0x2536b4bf, 0x71dd1d33, 0x14255934, 0x2472192d, - 0xe57d0837, 0x8246278d, 0x8dd4aaae, 0xbf2a2ec9, 0xc56c0955, 0x71d3ec45, - 0xa4ae123b, 0xf8b4fff2, 0x75a2c91e, 0xef05b64a, 0xba3e0f9d, 0xbde04d23, - 0x9f6b1391, 0x3cb8e68f, 0x6d92fe8d, 0xc1d008ae, 0xf59526c6, 0xd4cdd814, - 0xd93a2eb8, 0x011f14d8, 0x8c7ca6bd, 0x717297e2, 0x0bdf49b4, 0x9aa147c5, - 0xe69b8efd, 0x2a90f17b, 0xf36a40ef, 0xf592ee5c, 0xaf6cba45, 0xe7d7b3df, - 0x47d3527b, 0x96be362b, 0x3f7d0b79, 0x2e7f783b, 0xd65784ae, 0x2f79e6ef, - 0xdadf6cb5, 0x1d7bd297, 0xd7985dbe, 0x45c6b7f2, 0x7ce3495f, 0x87c65db9, - 0x89f9b5ff, 0x4fc4fcc7, 0xc27a6cef, 0x8541fb0e, 0x1e876035, 0x46e4fe5c, - 0xae18e23b, 0xbf91b6db, 0xcc56da2f, 0xbefd00f6, 0x7c7aa7da, 0xf28f86b3, - 0x1706cab1, 0x60ffb3cd, 0x23ca4fc9, 0xa14b1c64, 0xdc35fa3a, 0x4db8b813, - 0x66bcc3c9, 0xe3b0ed14, 0x1a3bff1e, 0x37dd09df, 0x17a7871d, 0xabbd86f6, - 0xdf20f145, 0x89993ed3, 0x0f4472cb, 0x39b92fd3, 0x0869719d, 0x0a1fd5eb, - 0x8e70bed2, 0xd7e88764, 0xcf695587, 0xad123c43, 0xd83db973, 0x85e43a6b, - 0x0ffbe597, 0x8d0e7455, 0x2ede87ca, 0x169455c4, 0x744d568d, 0xd23e335e, - 0x0b660fb4, 0xfea2bec3, 0xa67e8966, 0x69498cfc, 0xce37faa6, 0x67e21a18, - 0x672aefce, 0xe99575fe, 0xdbaa975d, 0xe3856efd, 0xbf9ac67b, 0xd33b7a53, - 0xf6a60dd9, 0xe99a6255, 0x9b25975d, 0x133c65df, 0x8fa1d995, 0x41f76b95, - 0xb4dafb66, 0x9dfcadef, 0xafda6226, 0x7f3cd303, 0x8da5e794, 0x1dba08fd, - 0x9ffe367d, 0x1979ddd6, 0x898f19d1, 0x3bd85bf8, 0xe479667c, 0x42a9eb08, - 0x669543ae, 0x92caaa8f, 0xff2aa8f6, 0x9be23b11, 0x24d6ff09, 0x93754942, - 0xaa46f6c2, 0x938a48ef, 0x7df1dbf9, 0x075ef9a7, 0xf284bbfa, 0xf6316a43, - 0x35796857, 0x42e71bcd, 0xb047ec35, 0x6bfde983, 0x19f4eafd, 0xb43ecf7a, - 0x3760df1f, 0x6d8ae7ef, 0x23f60e3b, 0x8a2f4cbc, 0x497c43cd, 0x5b54cb65, - 0x74e5f671, 0x8bfdf3a6, 0x7fb616e5, 0x857e1c75, 0xdca3ace9, 0xddf191ea, - 0xd51f18ff, 0x0d6f695e, 0x3445bfa5, 0x1799f81f, 0x013c54ed, 0x5e03d645, - 0x432e81fa, 0x0dd492f0, 0x753c74be, 0x7ca42de2, 0x1c33fe31, 0x004a11f1, - 0xbc32f27c, 0xfad478e8, 0x2c13e45f, 0x013c1267, 0x3fa42786, 0xff742a31, - 0x20efc2dd, 0x84506c74, 0x3c6ef94b, 0xed24bb4c, 0xe4d30336, 0x2977dbbc, - 0xb3ebc81e, 0x7bf9592e, 0xc914bd27, 0x9319f538, 0x93b3fbcc, 0x7ee48a7e, - 0x81297999, 0xd36ffddb, 0x8fd177d1, 0x8d099fee, 0x5defd6ff, 0xddac1a2d, - 0x46211a4b, 0xc44ffb7c, 0x4072ebaf, 0xe749e74f, 0xf0d2e379, 0xf6ed4cef, - 0x951e5e1c, 0x3edaf1ca, 0xf3a88ecd, 0x4ed69f63, 0xca98b71f, 0xefa005dd, - 0x17b009fe, 0x4b4c6eaf, 0xe317be36, 0x3b63655b, 0x788af26f, 0x5dc38b4e, - 0x8a473809, 0x4d77c857, 0x27d5df8e, 0xe388fe01, 0x26bd6cab, 0x7fc7d751, - 0xe4593c3a, 0xe9c85f20, 0xb3617589, 0x3d78768d, 0xed2c1a6d, 0x7e39fa35, - 0x7a3872ce, 0xaadff636, 0x0508d15d, 0xfdeaba5a, 0xcf3a2e91, 0x8f7c5957, - 0xef7f660f, 0x85cf3e46, 0xec2e636b, 0x513cba70, 0x0fb0aab1, 0xffcafdce, - 0x9c31e579, 0xb615befb, 0x9fa3c804, 0x840aa07d, 0xc679d0ce, 0xe1a7c472, - 0xdd3fae92, 0x10f7c912, 0x1784553f, 0xea25a6fe, 0xe9975cfe, 0x0b3bdd5c, - 0x41deffe3, 0xb8c08ee3, 0x1889ad81, 0xc4cfe3d7, 0x1915beb8, 0x57d9dd31, - 0xbd66b4f4, 0xeab6f394, 0xeecd64f6, 0x791ef90c, 0x6270f7c8, 0x1e47be41, - 0xc8523df2, 0x4dbef8f7, 0x6c0c2ff3, 0x7e83cf68, 0xb22b1fea, 0x75bcf96a, - 0xbf7e4166, 0x80f08945, 0x78a2dcff, 0xc1bc70fa, 0xc4def966, 0xd57590f2, - 0x49da6bd3, 0xedd03306, 0x84392e0f, 0x8c6e6e31, 0xc7e53588, 0xea9afa39, - 0x4c52ba17, 0x0e25d7e5, 0xef5f9536, 0x7fe533ce, 0xa9a57598, 0x18cf64fe, - 0xa347fe53, 0x9fd537ae, 0xca6a9dea, 0xc7389f4f, 0x51667f54, 0xc6fca9b1, - 0xe54c4bd9, 0x4ccb7c73, 0x3fe579f9, 0xa9bfd535, 0xdca98576, 0x9c565c2b, - 0x77a17b77, 0x865fde11, 0x2de945de, 0x8d38656f, 0x9c7a3aeb, 0x7977dba5, - 0x5072694e, 0x36dea1bf, 0xd7ee25d0, 0x68070e80, 0xc0be67f7, 0x7e1bd2b9, - 0xf522a0c9, 0x417d23de, 0x42f5a137, 0x1e4747cb, 0x35a6e8b8, 0x7a2a7a2c, - 0xc4f895a6, 0x140e2be8, 0xf57e51a4, 0xad338553, 0x5f465fc4, 0x54f9e07d, - 0xb53d37ca, 0x3b0f964a, 0x51e51170, 0xf320df4f, 0x1a8b05d3, 0x7af90c8f, - 0x31e69f86, 0x6ba907fa, 0xd26ed23d, 0xa769bc6d, 0x80f0883d, 0x01e04d78, - 0x13e89069, 0x4fa201e9, 0x7d12afa4, 0x710ba596, 0xe913e890, 0xf13fd221, - 0x7fa4f7fd, 0xfa4c3d22, 0x49b7d227, 0x847a44ff, 0xefa44ff4, 0xf4e6cfd5, - 0xb71f7a83, 0x397d43fb, 0x6beb47a7, 0xf5c7fbf9, 0xb9fe9c75, 0x5ddfcfde, - 0x433b7443, 0xba31ed90, 0x7e1aabff, 0x76edd847, 0xfd1acedb, 0x9e578ac2, - 0xb2bfbaa7, 0x46b456a1, 0x5ab69f62, 0xba394f63, 0xf33d90fc, 0x6538ab5b, - 0x0f5ebf90, 0xe10d26f7, 0x98bbfbf1, 0x8fdf6b6f, 0xf203e989, 0x520a9d69, - 0x9f28297d, 0x2aba5f99, 0x0fc7f886, 0x81b5a9be, 0x74b43e5e, 0x0bfb7f7f, - 0x87da4e8d, 0x8c873378, 0xebbbf2e8, 0xf8ceef7e, 0x1e5f831a, 0x8e3d6cfe, - 0xf3c7f747, 0x473e219f, 0xf1eb93f7, 0xef6ad741, 0x707ee923, 0xef47fe3d, - 0x6092f0b7, 0x1acd77be, 0x512dcb2b, 0x38c41156, 0x35cf9c7a, 0xc43c968e, - 0xe9535c3b, 0x3eb738e4, 0x23ef1df4, 0xde2f3d52, 0x25fcdb99, 0xf2edcfd5, - 0xe6d1f7bb, 0x8f3ce541, 0xb63e4bc2, 0xc5a35ed7, 0x43bda01d, 0x753bf396, - 0xfc831188, 0xe1db2941, 0x7da8551e, 0x001c577e, 0xfaca47ea, 0xfe97f441, - 0xdd178d15, 0xc4068fb5, 0x6e21e4b5, 0x93b5406c, 0x8c36c6e3, 0xb9bdf209, - 0xded7b1e9, 0x4e22aad3, 0xd8c7e638, 0xfaa74f47, 0xefcf0266, 0xf00f73ee, - 0x5c5a7e50, 0x53a46f5a, 0xebb5de43, 0x62e67d66, 0xe97c755d, 0x4bd7d778, - 0x9e21b7c7, 0x5dfcf18a, 0x6eba17eb, 0xafa5eba1, 0x2ea5e153, 0x977f03fc, - 0xfad74faf, 0xfffb3ec1, 0xb70cfacb, 0xcc7df0b6, 0x07874ab0, 0x7ad77d70, - 0x262edcdd, 0xf1783ee0, 0xa441f725, 0x5f7cd24b, 0x8a967f80, 0xc05c1331, - 0x81cd4b91, 0xdeb4279d, 0xef59eff2, 0x077a90e1, 0x7cd60ae2, 0xbd79769d, - 0x1af521dd, 0x7ed60b62, 0x374ced2d, 0xe43d7ce2, 0xed1fb1b6, 0x1e3d70cd, - 0xa3ccebc3, 0xf1a71c75, 0x96a243a3, 0xd7120fcf, 0xf1df58fc, 0xcb8f52da, - 0xee72cc5e, 0x6e59a778, 0x514df09c, 0xd09dc623, 0xd68e442b, 0x6837e1fc, - 0x9a275efd, 0x7bd0dfb8, 0xf26837f2, 0xf93de869, 0xf26886e7, 0x01488a65, - 0x3c2f1a9f, 0xbded2e12, 0xd92ef183, 0x2f46926f, 0x8c556e69, 0x9f083d06, - 0x55f1cc15, 0x8b9077bc, 0xbf9cfd71, 0xfd38045e, 0x3f7208a1, 0x22918993, - 0x6c2123ff, 0x79039df2, 0xf55ab33f, 0x2ce427fd, 0xc2e65efd, 0xd8abdf70, - 0x4e44af77, 0x28f78f99, 0x4b8c15c6, 0xe303bb47, 0x1c9f2cdd, 0xbcb1a470, - 0x8b657d84, 0x6f7fdaeb, 0x6e92f9d0, 0x9106f795, 0x3a60dee2, 0xe9d7966d, - 0x86fe41fc, 0xed0215ac, 0x71cdb826, 0x1ffb7a38, 0x6b0ac6ba, 0xfdfccf41, - 0xfa7bb987, 0x66f3aec3, 0xb0f1a0ec, 0x7b19bf83, 0xf7cc78c5, 0x163ed8cd, - 0x39d98699, 0xbd3179cd, 0xa74e793b, 0x26f1aee7, 0xcf7c6b08, 0x1af1d678, - 0xcf1d4f8a, 0x2f5e02ff, 0x2fd78774, 0x37290b06, 0xa23e4a47, 0xac2ab7e3, - 0x1f671ef3, 0xa5445c63, 0x33e9e243, 0xb87b8c80, 0x3cf15775, 0xfd17a93e, - 0x7545ef81, 0xd43cb8a3, 0xc736250e, 0xc77f5e70, 0xef83ccec, 0x7c122746, - 0xea7c39d7, 0xd9cbc250, 0x492660fc, 0x0d93e230, 0xfaef7c0d, 0x07aab3dc, - 0xeaa57ff2, 0x4f01eb5e, 0x3f655379, 0x95e6f8a0, 0xc509f864, 0xa3e3eee6, - 0xaf121d2b, 0x32b3feba, 0xa7f788ad, 0xca241570, 0x3de4d5f7, 0xe81e5d72, - 0x8be3261f, 0x3dccfbf5, 0x232307c9, 0x1feb1f24, 0xbeaef926, 0xf38ed49e, - 0x48cfd449, 0xf74953e2, 0xb03eb045, 0x1a4de5db, 0x78ca7f0a, 0x75a79261, - 0x97a3bfbd, 0x5af03f7c, 0x68d0f991, 0x643f8fca, 0xef2a0113, 0xf14c2f18, - 0x946f8564, 0xfa16bbf2, 0x44b098fd, 0xfc0cafd2, 0x611ddc20, 0x32346f7a, - 0x8f94ce2b, 0xd533f4f2, 0x6a95198f, 0x0ef58f2a, 0x4fc79531, 0x7be537cc, - 0xaa655d17, 0x58f667df, 0xefafbe53, 0xa4fd5306, 0xbca669f2, 0xe49297ce, - 0x76a03127, 0xc0fda9ae, 0xfd5312ba, 0xf9857f14, 0xf7bf54fd, 0x9e025648, - 0x697f9477, 0xbc87966b, 0x96116aaf, 0x90ef5d91, 0xde5a3afc, 0x5ce89907, - 0x6491efc4, 0x0cccfd34, 0x8a8dfa8f, 0x46292673, 0xae24f7e1, 0x60f99b73, - 0x3f39a261, 0x2af795de, 0x2b9c6e96, 0xa828fe34, 0x6a929e80, 0xf3efa6ad, - 0x347c6a86, 0x9eb2e457, 0xefeb5dfe, 0xff5a621b, 0x4e5d7c50, 0x05e7cf0f, - 0x6f9ed2dd, 0xf9ec179c, 0x9ec0bc46, 0x9ec3cc6f, 0x7b0fac6f, 0xf61cb1be, - 0xc179637c, 0x8c1d3321, 0x83a66238, 0xe99a8e2b, 0xd0cfa740, 0xd5b2baf5, - 0xa7c21f4c, 0xb07f94f8, 0x6a7f575e, 0xf5d09fa6, 0xd78b0921, 0x1153826f, - 0xfbfca48f, 0x642eb5eb, 0x87d73abd, 0xf6f90df0, 0xbe50e0da, 0x48785b27, - 0xe4b77815, 0xd79e6d51, 0x27e5ad0d, 0x7d5bb6c3, 0xae7de6bf, 0x5f4355d1, - 0x871d5749, 0x1f070f9e, 0xffa4347d, 0x02f9fbd7, 0xfe3b3fa8, 0xf41db262, - 0x45df2ed1, 0xee1f036b, 0x49b715dd, 0x77bcba7a, 0xe39533f2, 0x9a598e18, - 0x82ebf014, 0xf036df18, 0x6bb39bcb, 0x1367f815, 0x458ed145, 0x8ff9cb88, - 0x17e464b0, 0x77f7940c, 0xdf2b7645, 0xe2f9d07f, 0x17192482, 0xf35432d8, - 0xdc647af3, 0xa543f3ce, 0xe3ca24dd, 0xe2e338e2, 0x83bf796c, 0x05e499d4, - 0xe1c7c039, 0x47c041f0, 0x69df85b3, 0x39b9b56c, 0x86ffc46e, 0x83f7e02a, - 0x72f90b1c, 0x35df2680, 0x0070e47c, 0x85eb41fe, 0x1c1d9ce9, 0x5be29870, - 0x99736e87, 0x892d39f2, 0x76c3faa6, 0x79e54dbb, 0x79532cc1, 0x298f21c1, - 0x28c8e23f, 0x8e2bfd53, 0x2bf94d7a, 0xea9a275b, 0x9169fd5f, 0xda249f29, - 0x077e061f, 0x3e8f522a, 0xe2553433, 0x7e382dc9, 0xb19dc16f, 0xa6a7def2, - 0xba72eb5f, 0xd3ecf71e, 0xde5439e8, 0x71f7681f, 0x5f43751c, 0x187be1e1, - 0x129f4d0e, 0xa7c03d66, 0xde772dc5, 0xe39bf0a3, 0xe578f596, 0xd3417d4e, - 0xdd39740f, 0x35ecaf10, 0x082f2bc6, 0xe03dfeeb, 0x3dd6d2ff, 0x7681fe14, - 0x9f86df39, 0x88def9da, 0x3c28570e, 0xda38b533, 0xefee8e2d, 0x25b2d8f5, - 0x1465259d, 0xfef41dfd, 0xcad3cd98, 0x365fdd6f, 0x4fd5a79e, 0x0bf0d5f4, - 0xfba567bb, 0x305bc7bb, 0xbe67ce4c, 0xd4f372c5, 0x32cf8e6c, 0x3bdf83bd, - 0x51fdea5b, 0xf3b74ab9, 0xe323105b, 0xdd8c44a7, 0x79edfa0d, 0x44cf893c, - 0xfbe468bb, 0xff9c5a47, 0xee5b6b4d, 0xf3454419, 0x7bda4ded, 0xe81b0160, - 0x9258d261, 0xd884f2c3, 0xb35765b6, 0xc7a2e493, 0x3f6cacea, 0x35ddbfe9, - 0xceb8248b, 0x49031bfb, 0x407d01ef, 0xb4be81b6, 0x71e54721, 0x1b9ec1ae, - 0x4df6fd81, 0xfb3d9c67, 0xced08405, 0x754fa90b, 0x874c6f43, 0xaffe3cfa, - 0xf143ede3, 0x42adeba4, 0xd74c338b, 0xd7f1d2e0, 0xf0d07769, 0x707fdfa7, - 0x6d15b32f, 0x8a3df272, 0xd2db8889, 0x4725afd7, 0x86ad65d2, 0x3f03d40f, - 0xa15ea9ea, 0xfb031d9a, 0xc7708772, 0x43a1bab8, 0xc2bffd3d, 0x9eff8e8b, - 0xc4f557ee, 0xc2f9421f, 0xeab7dd77, 0xd9ff4e89, 0x3e06577b, 0xb468e321, - 0x5ba40975, 0x677d3fd8, 0x6f3f7994, 0x8d7696cc, 0xa2beda71, 0x6799ddf3, - 0xf60217e6, 0xaa5586f1, 0x39e42fc6, 0xc4529c5e, 0x3a8b11ef, 0xe533cb17, - 0xcfd62f1a, 0xc80f85d7, 0xf5aee0f7, 0x455c2516, 0x9b6692f9, 0x15a048d8, - 0xf38fbbfb, 0x1b93bf66, 0x449efe71, 0x3726cdc0, 0x49b4b71a, 0xb94fec09, - 0xc5ecbdfc, 0x5c7ef94e, 0x8bd9bbe8, 0x2f17fd35, 0x86df602a, 0xcfee65fa, - 0x8f6bced6, 0xe12b7cf0, 0x0ba5bd67, 0x02de8d7e, 0xe8311df2, 0xf3b4aac3, - 0x8e969c70, 0x24fc3737, 0xc2795df1, 0xce16446f, 0xb76b46f3, 0xf89d7471, - 0x9d2afdd5, 0x1cc3c27e, 0x171a1faf, 0x4affd670, 0x1a7e7774, 0xd3d37fdd, - 0xdff4e83e, 0xa85f877c, 0x1e8969c3, 0xff043e05, 0x57e8dbbf, 0x8248f3f9, - 0x3127fd90, 0x6ab48ff0, 0xb98d89fd, 0xf44fdddd, 0xf1c5d8ad, 0xbe2cab10, - 0xf25c40ff, 0xef1fea19, 0x3ce5deb0, 0xf8fb8090, 0xd3bb3493, 0xe4d6f3e5, - 0x7ef2d1b0, 0xe55f8740, 0x2898eef5, 0x1f1373ef, 0xba77d815, 0x08aa7f1f, - 0xfbaa42f6, 0x466b7c49, 0x3f75fe31, 0x14707149, 0x61b339c3, 0x484f0db1, - 0x7b7c3eb6, 0xcbbb8461, 0x403ad27f, 0xe4f4e7c6, 0xc97e9947, 0xb8cdfdc3, - 0x73f71574, 0xca453b2c, 0x2cf78d6b, 0xd90d9d03, 0x67986c26, 0xdffbadab, - 0x23929819, 0xf852d1f7, 0xe21b7bd2, 0xac28567e, 0x84572c07, 0x7cc4071e, - 0x6c5fcf5e, 0x3285f2d2, 0x992acb7f, 0xc5ded56f, 0x3bd9aada, 0x98a44f30, - 0xedf0f40f, 0xf3043d9a, 0xe0798a40, 0xf21af83b, 0x83c86be0, 0xbe0f21af, - 0x0d7c1486, 0x51444bdf, 0xfd2a9e72, 0xfb0de33d, 0xf19efe03, 0xfe09b906, - 0xfe1e631e, 0xf87d631e, 0xf0e58c7b, 0xe1cb18f7, 0xe1e631ef, 0x87d631ef, - 0x8798c7bf, 0x1f58c7bf, 0x1e631efe, 0x7d631efe, 0xe58c7bf8, 0xcb18f7f0, - 0xe631efe1, 0xd631efe1, 0x58c7bf87, 0x629d737e, 0xacdd07f2, 0xba503bbd, - 0xa3e98e3e, 0x2928b539, 0x3ff7d687, 0xc7e7ff23, 0xf3ac54b6, 0x6efc25de, - 0x47845560, 0x44d373ae, 0x2116eeb9, 0x0e7db9d7, 0x76edf3af, 0xf1942f99, - 0x03f4a1c2, 0x74f8cabf, 0x0a4157e9, 0xf8520abf, 0xafc29055, 0xfd2ade32, - 0x57e1482a, 0x55f877c1, 0x82afc290, 0xa4157e14, 0x8520abf0, 0xfc29055f, - 0xbf07682a, 0x55f8520a, 0x157e1df0, 0xe0abf0a4, 0x038231fb, 0x2e1d15fe, - 0x26e9f9c8, 0xd0e8943d, 0x4cba87a4, 0xc6f9c879, 0x8df390fa, 0x8df390e5, - 0x8df390e5, 0xc6f9c879, 0x8df390fa, 0x88f11bf9, 0xef296f71, 0xde41db1b, - 0x9a73e637, 0x86c1affc, 0xf9c37935, 0x46b69157, 0x2e298f29, 0x9e72eb92, - 0x58ff059a, 0x1c92b86b, 0x763921eb, 0x8d676fc5, 0x89f892bf, 0x2b976f16, - 0x6f582dda, 0xbad37bf6, 0xe38282f9, 0x3bfe7383, 0x7f75cb91, 0xbad1ff2b, - 0xac14ede7, 0x90cb6c37, 0x3dede970, 0xd522a5c2, 0xbbe577eb, 0xbe3a17af, - 0xa5f98f5e, 0x28520e01, 0x910710f3, 0x1f33bb77, 0x2d5bedf1, 0x5d0b8c8a, - 0x4372e329, 0xe349aae9, 0x3b2d5b4b, 0xbb50440e, 0x83c562f6, 0x5699077b, - 0x0f96c871, 0x43e6d53c, 0x89cba89e, 0x6b83e2d5, 0x903c42af, 0x7f6eb70e, - 0xf7c13e24, 0x0bb746dd, 0x738d197b, 0x8ec217cd, 0x64985bdf, 0xda04f297, - 0xea1cdf41, 0x0c9bbc57, 0x4732bdf4, 0xff3e7b9e, 0xe8caabb2, 0xb5edd0fb, - 0xdd1ee157, 0xeed908a4, 0x33478f37, 0x2a34a71e, 0xc9fef09b, 0x8bc2ede8, - 0xd4bfb1fb, 0xddba1ee0, 0x71e32f65, 0x4eff7c5d, 0x4378b7ef, 0x2c17df32, - 0x13e3ad16, 0xf0a127d9, 0xde3ae6fb, 0x62af7e68, 0x0fe2c47e, 0x2ffc8ec1, - 0x7121c3df, 0xc3dcfbf1, 0x6c7866b9, 0xc4dbe221, 0xe40ef95e, 0xabc5e1e4, - 0xbe5c137a, 0xf2077c80, 0x5f6a2f9a, 0xf966fce3, 0xcf93240e, 0xcf8f8648, - 0x857e41c3, 0xe298ffdf, 0xe5e968df, 0x15e0bdc6, 0xdfd404b6, 0x0b503c2e, - 0xaf790906, 0xb6579f55, 0x57096238, 0x95e22f40, 0x11fd0378, 0x7a0198e7, - 0xf8d8f3c9, 0x56a9907d, 0x46fc0d97, 0x5d8a7397, 0x7542ec72, 0xf7df0c74, - 0x2e13910b, 0xb8e6f636, 0x8e3d7f8d, 0x93ef83a4, 0xce15df2f, 0xf88f8572, - 0xb9e6f807, 0x5977193c, 0x91c3ecb9, 0x38aed496, 0x8129d392, 0xf3df78ad, - 0xe88eea74, 0x11cb0a51, 0xdb5fc087, 0x7be79f1a, 0x5eabc582, 0x1710fbe3, - 0x96881f1b, 0x7fa4aaf7, 0x9bc34ca5, 0xa85a6f6e, 0x16994fad, 0x5ebc743f, - 0xe74bcfbe, 0x71f7bf30, 0x72c6d1b1, 0x28bca846, 0x880feb84, 0xb46f2b73, - 0xc5d3ddf1, 0x27578b6b, 0x777eee8a, 0xcfe32bc5, 0x349771b5, 0xa84e38da, - 0x2b477b5c, 0x965877f4, 0xd2e8726a, 0x27efe66d, 0x4fe44272, 0xad44fdfd, - 0xaf5bf14e, 0xa83964cc, 0xee71c6d6, 0xb94857f3, 0x0110ec48, 0xbf9867dc, - 0xef059c62, 0xe5dfcc58, 0xd0dd28f5, 0x7c9a3bd1, 0x12830934, 0x8a5ea7de, - 0xed32be60, 0xcfce3f52, 0xe9c894ba, 0xe4b2978d, 0xd11dac77, 0xbca16b4b, - 0x26beff5f, 0x1c44cd17, 0xb2e40165, 0x1dd74c3e, 0x2218d744, 0x4357e357, - 0x302bcabc, 0xf9b24fc3, 0x734e2156, 0xf7c146d2, 0x7e432691, 0x90d982a2, - 0x2fb00aa7, 0x3ef90a52, 0xef8544c6, 0xbe1e4cb7, 0xb407db4c, 0x11f3042f, - 0x37c3f77e, 0xf1006a7e, 0x3b7db337, 0x7d77582c, 0x6dfcf83f, 0x64e60efc, - 0x7bc762bf, 0xcf4d3e81, 0x743de9d6, 0xd4882c5f, 0x694e63ec, 0x8fb4eaff, - 0x9c7e5801, 0xc446f227, 0x2d802eb3, 0xb0b69fb3, 0x6ca8aa84, 0x1b9c9e59, - 0x94236379, 0x6ed37fac, 0x9162df32, 0xfe489ff7, 0x717578e3, 0xe50fb0a4, - 0xf92ad78b, 0xe1d79788, 0xd8d87afa, 0x777ac349, 0xe74941d1, 0x03eeccfe, - 0x5df960bd, 0x4cff2619, 0xf84a5a68, 0x105a3ec6, 0xfc63fad3, 0x5c84d0d2, - 0x889f1de1, 0xf9f5c877, 0x02e2208a, 0xdbf96ae7, 0x8ff2bd9e, 0x278c9c6b, - 0xedcd8fce, 0x3fe22377, 0x38fe65fe, 0x7f1ab15f, 0xf14daa37, 0x3de57379, - 0xdf5809c8, 0x7e76ecc8, 0xa66660c7, 0x212f9e4b, 0x72db9676, 0x845df2dd, - 0x694b7b10, 0x846f3cb6, 0x8f3c9dd5, 0xb66e3afd, 0x3ef3ea57, 0x33df336e, - 0x5cead3d5, 0xbff83769, 0xa0f127ba, 0x7ffbde45, 0xf1d812c4, 0xa06bd122, - 0xe6016fb7, 0xbde208fb, 0xcf1f7e19, 0xa3477f4f, 0xef694f93, 0x74f4e865, - 0xdf22eeac, 0xda712897, 0x9e81aadd, 0x7c28d6ca, 0x4ea4b11f, 0xadf627de, - 0xfcbde451, 0x8f57ec1e, 0xdf9af9cf, 0x17fc7a51, 0xc350b211, 0x91fb7cef, - 0x5d291cd7, 0xdd53fdf8, 0x7f926caf, 0x6f103306, 0x9c36b73f, 0x7afe41df, - 0x018fd158, 0x87b6647f, 0xf11269d7, 0x1a9fd434, 0xbe29fbe3, 0x07238897, - 0xf05c6f61, 0x7df8b7f3, 0x29bd9ae1, 0xf161eefc, 0x78d5bcee, 0x61ebe547, - 0x89723bbe, 0x2e9d8b7e, 0xea90e43b, 0x973e58c6, 0xeed1f417, 0xf6768ba9, - 0xf3ebe9e7, 0x0794ae60, 0x9c723c8a, 0x453e9a0b, 0x354db308, 0x7fe793d5, - 0xedd43ee8, 0x95f6a1a2, 0xbe2af7d0, 0x7b029ecb, 0x5760dd89, 0xb631edd5, - 0x7073e3ac, 0x77b7cf9e, 0xaf8dbbff, 0x4d4776eb, 0xa9d85d9f, 0xe84f66cf, - 0x9d7fb903, 0xbd1d82e2, 0x11bee9cc, 0x8765f5f1, 0x14f0886c, 0xf2dce293, - 0xe4bb92dd, 0xb72525bb, 0x9b3f31e6, 0xc7c9358f, 0xbc5187bd, 0x9402cb8f, - 0xdfbcf7c6, 0x657bade7, 0x53d01ec0, 0xe0f7cbd0, 0x7b5e5ccb, 0x2a2e419c, - 0xef4c526d, 0x17f9e818, 0x721da573, 0xc019a93e, 0xa6b74ddf, 0xd086f1d8, - 0x108f127c, 0x46baf837, 0xaa3b7a27, 0x932571c7, 0xf941c552, 0x9dc114ae, - 0xfe33c722, 0x9349514e, 0xaa063df9, 0xfedd72cf, 0xafee28dc, 0x4ef345d8, - 0x3862ea41, 0xa78c0f09, 0x3fa87bf6, 0xebc38f37, 0xd80c1a51, 0x8f983760, - 0xcfca1678, 0x186c0575, 0xbe51a4a7, 0x2b5be28f, 0x89adf1c7, 0x2e40e7b5, - 0x03ecbab0, 0xa360f28c, 0xbe78cf7c, 0x0411fbf6, 0x65cbcb2f, 0xf3dc2784, - 0x867defd2, 0x8358abe2, 0xd629acbf, 0xad365f2c, 0xe67d61b3, 0xc35ef0f4, - 0x971d1a97, 0xfbe18e34, 0x2f5665f5, 0x69f097df, 0xb2ebfef8, 0x27e1bbf0, - 0x90fcd399, 0x8d79052d, 0x3c097d2f, 0x829e06f7, 0xd23efc19, 0x678e70b2, - 0xe26ae39e, 0xfbe276f9, 0xe40fc201, 0xe3115715, 0x8fc4e89b, 0x66b2c038, - 0xc176faf3, 0x65df2513, 0xfde62e6f, 0xb3eac8b7, 0xac708cbb, 0xfb819fdf, - 0xdf68735b, 0xe127fde3, 0xcc7df1f2, 0xc8dc0f53, 0x3806fbbf, 0x8f28e781, - 0x3bde027b, 0xba61ba22, 0x4167e9d6, 0xfacfdc81, 0xacc35178, 0xec3f0ed2, - 0xf7a9f6bb, 0x06f3e420, 0xffd86f5a, 0x76a7da7b, 0x71a4005c, 0xddf265ed, - 0xab7dd0ba, 0x9f7d57ef, 0xdf56fbea, 0x8ad98fcf, 0x174a8982, 0xbdf3a1df, - 0xf06eb9f6, 0x77834934, 0x84aeb6ae, 0xc18557d7, 0x986237ae, 0x53f3dfdc, - 0xfd1ffbcd, 0xbd54dfa1, 0x03306c7c, 0xfaf53df7, 0xe3f3b8fa, 0x03ec3b64, - 0x30ea5bd0, 0xe5fd674b, 0xe262df5c, 0xfc9da51f, 0x04aafb63, 0x0a1d8ff0, - 0xdf96e1fb, 0xe5bee523, 0xe17bc8cf, 0xf8bf9667, 0x77aa2cf6, 0x0b8dc1fa, - 0xca2ff78c, 0x2c5f9282, 0xfc0b7924, 0x0f269163, 0xe5f4cc6c, 0xe7ec330d, - 0xc99ffbb2, 0xdb98fec4, 0x6f0a7792, 0xf9bcd1a8, 0x3f3fa3bd, 0x5787d2f3, - 0x5dcebbb9, 0x6b251e7d, 0x3b15b5de, 0xf493788d, 0x0756777e, 0x38a55b9f, - 0x6953e8b7, 0x61f33163, 0x8f7a4891, 0xa1eeb5d2, 0xa8dc50f4, 0x5a579cb0, - 0xfea03237, 0xd2ebf22f, 0x8df953b5, 0xf4bd7d28, 0x73f45f77, 0xa67f8757, - 0x35734eb6, 0x4c3d9e7a, 0xe5b9c3ee, 0xbc45f629, 0xf8ec53ff, 0x5a39cdbd, - 0xf3329cf9, 0x72f5cef7, 0xd5fbf275, 0x9fb827d8, 0x58eaf584, 0xcbf6936b, - 0x57ad97ed, 0x1d02e432, 0x9d9ac58e, 0x6f66a172, 0xcbc9a45c, 0x8d8b5eb4, - 0x71f8b5eb, 0xcfa55eb9, 0xbc17f5be, 0xd3f34653, 0xef93a3de, 0xecb4940a, - 0xb39b75e0, 0x852d9d66, 0x5864fdea, 0xa8fe298a, 0x05cf36b4, 0x35dcfd3b, - 0x07e06d1b, 0xf126193f, 0xf3f74a16, 0x1d62f8b5, 0x148f38af, 0xaf473f83, - 0x83b83e0f, 0x5975b9c6, 0x77f1b478, 0x3d1a02ed, 0xc6c6d697, 0xdad2bc61, - 0x7fa17be2, 0xe840e7e9, 0x2e113bfe, 0xf50945f7, 0x6279fd87, 0x55ef878c, - 0x377ed7cf, 0x43feb42f, 0xdafddd1a, 0x4cbfdf26, 0x92796c8a, 0x226a3be3, - 0xe913e03c, 0x8c01ade9, 0xdc067a0b, 0x2f7c8b76, 0xf5b2bd33, 0xa241c073, - 0x20f5c73c, 0x105b7bc5, 0xbf2813ed, 0x79ef22c9, 0xdd32aaa5, 0xa607e1a7, - 0x5e8b9437, 0x5f1efcad, 0x2151bbe7, 0x9b176af4, 0x1fdde0d7, 0xefc12f7b, - 0xa9f4e9a6, 0xa7d3a3f7, 0xcd3dbf4e, 0x9cf7d76f, 0xcd1489df, 0x49e592ce, - 0x0bb8d076, 0xbfc41bee, 0xf35df16b, 0x35ef6bb4, 0x4c37ce76, 0x65c7defe, - 0xfa974df3, 0x6df3cf52, 0x66e84c2e, 0xd4f3a1be, 0x431e89f7, 0x694fe9df, - 0x1394fe92, 0xd4639d0a, 0x70b2c4ee, 0xe7d3ab8e, 0xbff5dba5, 0x8f87bdef, - 0xf669c586, 0xc828d6aa, 0xdfb5f397, 0x99411151, 0x86a9f7c7, 0xaff9faef, - 0xf3a75fbf, 0xdab593e9, 0xef5a28f9, 0x75167ec1, 0xf50f7c69, 0x2889d358, - 0x627313bc, 0x6f4f848c, 0xde4dab77, 0x76511673, 0xbbcfde37, 0xfe3cd6e9, - 0x8d8594bd, 0xbd9f587d, 0xf98d2ea9, 0x587e4dc2, 0x1ea74517, 0x83e348b0, - 0xaf16b791, 0xd7f502be, 0xc2eff0a7, 0x4e7a742d, 0x43f6e7ad, 0x2313903d, - 0x53daa79b, 0xfa961e59, 0xbb17ee82, 0x7c451155, 0x127c0d4f, 0x3fb2cbfb, - 0xe2cfe71d, 0x983f52f5, 0xe06b1164, 0x50d81d3f, 0xf82fa134, 0xfc8ac3c4, - 0xe60d9a3d, 0x0e86bcf7, 0x7c02fa2a, 0xbc5df426, 0x5e2d6d5b, 0xe482a7e8, - 0x16d1d80e, 0x9e588b3a, 0x93e345bf, 0xf8db9ac7, 0xaf1d7ebd, 0x78bfe08f, - 0x7ec42aa7, 0x1a276a14, 0xff07d9a8, 0x7b8faf1f, 0x0080003d, 0x00000000, - 0x00088b1f, 0x00000000, 0x7cb5ff00, 0x65545c0b, 0xce7bf8da, 0xc0cc2b99, - 0x1245c880, 0x85848b87, 0xd780c034, 0x508151da, 0xb9bba0bb, 0x658e21ba, - 0x500665ca, 0xd7775ddb, 0xa6a18cfe, 0x45fa7d66, 0x80ed65a6, 0x76c36a97, - 0xa8283448, 0x59990bc9, 0x6a37627f, 0x5b63b92f, 0xba402de6, 0x6dbfedfc, - 0xbcf3cf7d, 0x511730e7, 0x6fbefddb, 0x797bf9fc, 0x9f5ef3df, 0xcfbcf3fb, - 0x8c346339, 0x63181b75, 0x418e8b2a, 0x89486839, 0x8d8c9964, 0x615f6909, - 0xf6c3894c, 0xc645db25, 0x7cfb4046, 0x1962c893, 0xfa31d72b, 0x1fbf8f7d, - 0x3c1f7631, 0x42f3c337, 0x07d634a9, 0xcc37d7fd, 0xd6c972a0, 0xf1ae6dc2, - 0x2509258c, 0x606393b1, 0xb66ae3c0, 0xce258a07, 0x2b307719, 0x8da4d3cc, - 0x73c325d2, 0xc7292bb5, 0x496f9fe0, 0x0c4943e3, 0xd4699dc6, 0x7b4377cf, - 0x414e6981, 0xba5f8c14, 0x325b2a33, 0x6f5dfbfb, 0xc91b1811, 0x4673a558, - 0xcc614b1c, 0x67e1ddf1, 0x1fb0a94c, 0xf304d398, 0x7709e57f, 0xa38ba0bb, - 0x82492dae, 0xb3aa3c23, 0x7fa058a7, 0x6f31d895, 0x4e73cc12, 0xa04def70, - 0x5338e6fe, 0xe5a1fac0, 0xccc63ae9, 0xff398ce9, 0xcf3487cf, 0x3b89e2e7, - 0x8778c016, 0xce047f73, 0x1ff8f553, 0x6c3201f2, 0xb2cf689d, 0x8dbce1e4, - 0x1c124d7b, 0x56637b74, 0xbee39c09, 0xda46c7c7, 0xf79f2f33, 0xa8b668b6, - 0xdbcbda04, 0x6957c118, 0xd48ee85f, 0x5eeddc20, 0x696131a6, 0x28689a62, - 0x956c48cf, 0x52dbca07, 0x06b9a2d8, 0xe10dbb7f, 0x899eeb00, 0x025492dc, - 0x9f7b15ed, 0x79433248, 0xa5ebc8d6, 0x9c7a7f7b, 0xddff4045, 0xd5e20d5a, - 0x0b1a62ae, 0x25d7bb8c, 0xb250dcd8, 0x12c668f2, 0x7d6ea310, 0x59b19199, - 0xaf9a7096, 0x630e7b62, 0xc17dfeb9, 0xab3f6a73, 0x8fb8c562, 0xd903f531, - 0x8bfca1cb, 0xe21f7bca, 0x7ab52ff3, 0xf1192b8b, 0xfcbc2662, 0x84548b65, - 0x05fbaeed, 0xfac05636, 0xac1a637e, 0x6ac9165f, 0xf4a17c71, 0xcf049b57, - 0xb2101c57, 0x787b30b5, 0x1ee6b766, 0xd1169103, 0xd389b559, 0x75768ad9, - 0x7fe02251, 0x2d408b45, 0x3357950e, 0x2f2abe1c, 0x80e6664d, 0xb6b656fd, - 0x8eb0cc68, 0x09ce19a3, 0x539e1dfd, 0x5e78a59a, 0x7cb185b6, 0x89fe27c0, - 0xa53e6bf8, 0x3f0037b9, 0x2e1cadd5, 0xbede56ce, 0x3b900338, 0x1362b699, - 0x26dea0d2, 0x6b3ebd50, 0xaa35fcc2, 0xfcfe7ac0, 0x9a586935, 0x354c4e08, - 0xf0025490, 0xa3d194dc, 0xd73bfc41, 0x5d42f3ca, 0x0d5eb01d, 0xde48e512, - 0xf1c06a9e, 0x3caf1a66, 0xd146b677, 0x6c33af78, 0x3609bb03, 0x61506d51, - 0x4434ef59, 0x56b3b960, 0x715950cc, 0x09166173, 0x1611dfe0, 0x6122c591, - 0x3d5eaaca, 0x3b501240, 0xf6845870, 0x83fb48dc, 0x0c719f48, 0x33e802b8, - 0x06057991, 0xf9dfdff4, 0x7fce2e59, 0x17df18cb, 0x5eaeb60c, 0x017e7d33, - 0x8b26c3d0, 0x5f4c8e7c, 0xc8f1d22e, 0xb0af4043, 0x6cd5a7bf, 0xcf073e83, - 0x42e6c257, 0x08c2cc3b, 0xb984dfcf, 0xafdfc0f7, 0xce226f31, 0x54de74cf, - 0xcc9af71c, 0xc35a25a7, 0xf5f60106, 0x63fb149b, 0x053b8fb8, 0x116cf8f5, - 0xc58d2071, 0xfe6afd7e, 0xc2796d9c, 0x4ffc03a6, 0xa367e8e7, 0x4062e645, - 0xf1519aa2, 0xc163a406, 0x60ab6366, 0x0f3307fd, 0x2e80cbdd, 0x31d01e1e, - 0x5eaf9c2d, 0x7d3dcfcf, 0x0094ec20, 0x2a8f46fd, 0xf4165916, 0x2958ab37, - 0x29943ff4, 0x9fd8557a, 0x9fd8dce9, 0xbe6d0ae9, 0x8196590c, 0x7a88d0fc, - 0x78eff51b, 0xca011bf3, 0xe1e2e944, 0xe2573848, 0x3d4b052f, 0x3c1b29f4, - 0x85fff4fd, 0x5352f4b2, 0xfca1efcb, 0x19bda475, 0xb0727751, 0x501d94f8, - 0xa3c9b0f6, 0xf9f264b3, 0xf1dff702, 0xa2226fab, 0xfabeff45, 0x7bef4e07, - 0xcea58ad9, 0xe9b8c022, 0x9b57921d, 0xfa7ef975, 0xa9e361e3, 0x39e18fd4, - 0x5ba20dfb, 0xe1ffb010, 0xd37f710f, 0x14af0675, 0x17d4e381, 0x38ff3a7c, - 0x751d1e66, 0x284646fa, 0xb1913ef8, 0x8c3cdc58, 0x7068b81f, 0x6fb9c137, - 0xa14ff991, 0x488b1eaf, 0xf191e9f8, 0xe991c0a4, 0x7e9122b2, 0x5e8ad5eb, - 0x4cb385f0, 0xe8d67f3f, 0x5e0cff38, 0xff386d12, 0xcdd6b960, 0x8ec18a60, - 0x5727d254, 0x007fa792, 0xd740ca79, 0xfb6a97bc, 0xf90fc233, 0x78fc074a, - 0xc02f0c97, 0x25f9c33f, 0x64bbfe79, 0x1065ddb8, 0x127e9c39, 0x6e992702, - 0xf650ba14, 0x5863982f, 0x9f1fb469, 0x47ddd7ec, 0x8f099323, 0xe383ffe3, - 0xdfc213ef, 0x01d62737, 0xff51b11b, 0xfc784598, 0x579fc05f, 0xf80bfeb4, - 0x9fc50eeb, 0xe23d7f57, 0xd2d171ef, 0x0880fc84, 0x26d2a1c8, 0x0658f9c2, - 0x932ffe23, 0xe09b2cc2, 0xffe4767c, 0x8fef889b, 0xfc2bdf22, 0x37d8a63e, - 0x49e4f51e, 0x7dc19ec6, 0xb50f44f9, 0x10a766a7, 0xbac75f9f, 0xf01db013, - 0xf117379c, 0xe876d82e, 0xfb7d2c24, 0x5df5865e, 0x1ecb0615, 0x5bbf6f38, - 0xfe61a974, 0x8ef72886, 0xc36eb0a5, 0x1716995d, 0xd59633b6, 0x3ca07286, - 0xbe7a82cc, 0x85cb8a21, 0xa4e90586, 0x277e0f87, 0x73c2ad25, 0x34b3082c, - 0x6c86ff41, 0xa01323df, 0x6cd630de, 0x57d74171, 0x1dbe9605, 0xd1d1cfc7, - 0x38730d3a, 0x323c36dd, 0x057a8dda, 0x7af3cff4, 0x1e593fa8, 0x0d9cf0c6, - 0x6884b68d, 0x2297cba0, 0x61b3a3ec, 0x4e24a3ff, 0xd0c90dd7, 0xa136e50e, - 0x387dc164, 0x6fbe78df, 0x17b082df, 0xfa2cc2f7, 0xd0591034, 0xb195727e, - 0x42a5e509, 0x73a57797, 0x75c63779, 0xc9c2076a, 0xd4659d35, 0x937ffcc2, - 0xbb814be9, 0x556c6360, 0x0afe1fb4, 0x70c8c59d, 0x7a735617, 0xe5974d73, - 0xd7733562, 0xe65f080b, 0x96f8070b, 0x42414169, 0xadd93469, 0xe5faefb8, - 0xf7091780, 0x527fe1cf, 0x619ee564, 0x2847e7f8, 0x4c88f32c, 0x328fe404, - 0x0ca3f9c6, 0x6fe908e9, 0x0051d015, 0x75df31fd, 0x65c3a751, 0x6bf1823a, - 0x70d3258d, 0x3f85cfbd, 0x89e363e4, 0x87f34a7f, 0x3656675b, 0xf40b0397, - 0x9fd899f6, 0x51148eed, 0xf130ae5f, 0x7f644ef5, 0xc5f51a36, 0x79bd5fc9, - 0x23c7961d, 0x86cb6e4a, 0x7c16dbfe, 0xfce2845d, 0x353e096f, 0x0b6fe39e, - 0xb468fffe, 0xbf56ca43, 0x43fef449, 0x192859f7, 0xaf4e5032, 0x15a67d04, - 0xb074e4b0, 0x74463ef2, 0x896ac890, 0xfd65e36e, 0x47a30c05, 0x00f37539, - 0xbcca8ed8, 0x9747fff0, 0xce896c74, 0xa2c69f5f, 0x7433ea82, 0x0bfd4109, - 0xcf41c94d, 0x171f8d6f, 0x39a67cf4, 0x3b3ea83b, 0xff505263, 0x82d32ddb, - 0x9c4e77ea, 0x8e7fd419, 0xdd504e6d, 0x1f244cc6, 0x738aea3a, 0xe1bb013f, - 0xdc92bab5, 0xe397544f, 0xd0f6aa63, 0xe805b37e, 0x5f3bdb24, 0x91ea0935, - 0x43265687, 0x11cb537d, 0xf43c4f5e, 0x66e03245, 0xf9d1cb73, 0x53dbd02a, - 0x45f43c6f, 0x6d1fd40a, 0xa7cfe2e9, 0x40a362c0, 0x39bcb6ac, 0x9af805df, - 0x8adf629b, 0xa9779af8, 0xf98a28f6, 0xbdccd7f7, 0xb942592f, 0x06746730, - 0xc53727ec, 0xbf3e10fe, 0x759ef62b, 0x1ffb0091, 0x46ab5b7d, 0x5d98bf3c, - 0xa1e915b2, 0xf3a722ff, 0x91978853, 0x96097eff, 0x8a61d903, 0x3c92bd9c, - 0x03adf854, 0x1512c6f4, 0xa54749c2, 0xe544ceb7, 0x2a78baa1, 0xd999d48f, - 0x57638012, 0xc795065d, 0x7ed42cea, 0x95226ebc, 0x546cea27, 0x4c575bbe, - 0x095d7765, 0xb2ff0a95, 0x6a0d96bd, 0x2a974224, 0x4fceb4ea, 0x63d2578f, - 0x69d92820, 0xf9d09f05, 0x39adbd4d, 0x9d75ce9b, 0x6959e909, 0x81f9da3f, - 0x9dfa0459, 0x3d11d56a, 0x9b74354f, 0x475e5675, 0x22fbb8b9, 0xbc118af3, - 0x5fb02a9f, 0xfd1b278c, 0x030ea998, 0x841b4bf5, 0xefd8597e, 0xf79404cd, - 0x16356b53, 0x509e63b4, 0xf61e9733, 0x90df146f, 0x20e31d70, 0x05d86cca, - 0x903ad518, 0x6ba07157, 0x63f439f1, 0x0f77283a, 0x4746f5f2, 0xf9472ed7, - 0x60ccba34, 0x95f2e7a9, 0x08e24be4, 0x2fee026f, 0xda86a571, 0x198f628d, - 0x9d5f60e5, 0x69d21677, 0x0ae72c81, 0x30ef5c34, 0x80bde411, 0x576dfb7c, - 0xedf3da22, 0xd02f9edc, 0xfa44ec96, 0xfe7156ae, 0xf77a3165, 0xd5475c1e, - 0xf42cf15d, 0xb44d89eb, 0xc568426c, 0x6069641f, 0x14d617b7, 0xeddca267, - 0xaf885b61, 0x13fd5ec1, 0x338fdbd2, 0x9945df81, 0xf89e6048, 0x4da6f0e2, - 0xd7adda02, 0xce5d21e7, 0x300f9ad5, 0xf65f07e0, 0xdcfbd100, 0x7a1e7348, - 0xafecbe0a, 0x7cce3d79, 0x26e78040, 0x00bf3036, 0xe9cf55ea, 0xf0049f4d, - 0x1513d3a9, 0x4b69af54, 0xc0127d30, 0x07f855a7, 0x09b747fa, 0x0ebb942a, - 0x04a72b79, 0xb7c405fb, 0x0d73f8b3, 0x0680dfdf, 0xd98bd8ed, 0xb06fa266, - 0x0fef4997, 0x9bba34cc, 0x2371bf60, 0xa057b36a, 0xce6994fd, 0xea497ec3, - 0x63f40881, 0x1555bffa, 0x19efc9bb, 0x78c9f888, 0xd33d7d3f, 0x287b5121, - 0x70e6b5dd, 0xcd26af7f, 0x50f119b0, 0x51d3af1d, 0x88b171d9, 0x92569d91, - 0x4db97686, 0xd0cbfdc3, 0xb8737bf1, 0xaf5e491e, 0xa240b921, 0x0b6cb608, - 0xc5dd4a63, 0xf8d63226, 0xbf21b08b, 0x34c9c007, 0xc83f6563, 0x41476235, - 0x1b7f505a, 0x8e7a1ff6, 0x8ff31cf6, 0xbb49794f, 0x5e4aad63, 0x2965e90f, - 0x183fa373, 0x72abc72a, 0xc0b965a3, 0x8c74fcf1, 0x9cf111be, 0xe77d0126, - 0x504cc950, 0xb2338626, 0xd75f1337, 0x773e91bb, 0xa7fd39eb, 0x2ddcbc89, - 0x309afef2, 0x577a42e6, 0xb94d87fc, 0x79b929f6, 0xe6978f34, 0x91b25a91, - 0x879813ae, 0x24ec57d6, 0x43d81fa5, 0xaa02127a, 0xd7c47481, 0x161c4954, - 0xa672279e, 0x448ce515, 0x4fb1b0fe, 0x5f77e403, 0x40aac478, 0x78e355fc, - 0xe9b8e043, 0xef194e34, 0x4fb2255c, 0x245c9047, 0x89a6723a, 0x4b562fe4, - 0xfe8088ec, 0xa0d6eb16, 0xf5c6539e, 0x14fc1c82, 0x9047f0f0, 0x087e588b, - 0xffd710f2, 0x2c43c833, 0x10f20aff, 0x3c824fdb, 0xf207d2c4, 0x063fdb10, - 0xbce58879, 0xe4568dbb, 0x69b69a9f, 0x7e20d3ec, 0x017ddb50, 0xc369def5, - 0xa64391d3, 0xe1e4dea3, 0xe1cbaf9f, 0x2def457e, 0xa0fd9f1c, 0x00ffd1bf, - 0x8a6b5cba, 0xef1eb2be, 0x1ef9b237, 0x7cb6d380, 0x27f4876e, 0x1cd2faf0, - 0x226dd535, 0xb7e38edb, 0xfaf86be5, 0x3e396229, 0x79f345b7, 0xb245d37b, - 0x9e4ea69f, 0x9e0724b6, 0x3da162db, 0xbdef5fc7, 0x8db73f81, 0x7a43ede2, - 0x253e7e56, 0xeff8a4d7, 0x652fdce9, 0xbd012764, 0xff4afcd3, 0x3e7226f7, - 0x4eefed0c, 0xc3dd8b13, 0x992de3c0, 0xd02f896f, 0x483e469e, 0x6a8be00e, - 0x4285f133, 0x55fd0a87, 0xa73872e5, 0x073a6569, 0x43f042dd, 0x3a72831d, - 0x25f64f4e, 0xe0c6c5c0, 0x9905bb3c, 0x01f9425f, 0x0a07d44a, 0xa07c283f, - 0xf0227bd0, 0x3fed1099, 0xf421cdc7, 0xca8f94aa, 0x358ee8e7, 0xdaf09cfe, - 0xdfa136a1, 0x87cc3377, 0xc1c513e3, 0xfe46ef77, 0xd19a358c, 0xc87c2cf5, - 0x1c9c3b50, 0xc2effaeb, 0x570b9143, 0x7065c780, 0x5ff2f0d0, 0x39c90385, - 0xbf48e394, 0xfdadc8c3, 0x5db2d139, 0x44f7e9ce, 0xd21f6d8e, 0x57a0bf51, - 0xafd0dfa1, 0xd9dac367, 0x7f39f2db, 0x05547428, 0x89eb103a, 0xcbd4ce78, - 0x9e729ee5, 0x632e73a1, 0xc2d2ff24, 0x9e287b78, 0xc8057395, 0x0139c3bf, - 0xb8c61ff1, 0xd81d717d, 0x4d4fe817, 0x3ed335c9, 0x567e47fa, 0xcff995b6, - 0x6f0e477f, 0x88944a7f, 0x32fd141e, 0x8b482ed4, 0xe90664e6, 0x3f42661d, - 0xfc4b53af, 0xe67f05ee, 0x3e871825, 0x3fe49b21, 0x71e320bf, 0x1158fe70, - 0xafbebbed, 0x63d42e0d, 0x4e06a37d, 0x6fbe300a, 0x6436183b, 0x136ed897, - 0x07deef40, 0xd4f5063a, 0x2c7b9005, 0x7273b19d, 0x73cfa11c, 0x73fa24f1, - 0xa6243b35, 0x3b4a5003, 0xf4879abe, 0x6d53b4b4, 0xf6d0b8a2, 0x3d218ec7, - 0xcc156e9e, 0xb5f49768, 0xbfa1f1c2, 0xd6e8c1b3, 0xa822ff43, 0x0665ff63, - 0xd7ccdb8d, 0x4383f8a3, 0x7d53ef5e, 0x85c60a75, 0x1350ec66, 0x2f3e97dc, - 0x3b3ed1b9, 0x0aa57dbc, 0x02dda7eb, 0x4571838b, 0x04aeead2, 0x2d3e57a8, - 0xce30b458, 0x8b3a2861, 0xe7ca82f1, 0xf30bc599, 0xc918b657, 0xa0da5dcf, - 0x6017d8fe, 0xb7bb945f, 0x29eed06a, 0x5edc19df, 0x0eb83bb9, 0xeff922f8, - 0x00f68668, 0x8e6dfcf9, 0xcdec8631, 0xed1b2c71, 0xe3c0d64d, 0xbf7c8ab9, - 0x71756edc, 0xcb82ba39, 0x8cbec66d, 0xea5f7f45, 0x63e92afc, 0x91cfaf03, - 0xfea0a7eb, 0x2f1c57f9, 0xe5aa5c0a, 0x604f3fb5, 0xb79c0f56, 0x426f53ba, - 0xfdbabfff, 0xb71811ef, 0x51f309af, 0x22bd9f7c, 0xdbded099, 0x10b926d8, - 0xfd0ecebe, 0x56e0112e, 0x8d3de07d, 0x5f7088d9, 0xadcaf64e, 0xe31eb5cc, - 0x64515edc, 0xdd4744dd, 0xb666a714, 0x4f38a581, 0x84debb5f, 0x2bf54076, - 0x8ddd741f, 0xd30203f5, 0xfb471e23, 0xee964e88, 0x2da58640, 0xfbe426dd, - 0xbc4244e9, 0x913d9e22, 0x8865af84, 0xe033c477, 0x212cf11d, 0x51bc713e, - 0x2274e6e3, 0x73f4fd51, 0xde0abf1c, 0x1acda48b, 0xe46caf6c, 0x63b19e78, - 0xa230b6cf, 0xe9933503, 0x7a7ef080, 0xa6bbc727, 0x14669d73, 0x08636fd2, - 0x876bb41d, 0x77f700e8, 0xe0841d19, 0x8df002bf, 0x0e942072, 0x93dff142, - 0xd806e5c3, 0x429fa7df, 0x7e08dbfb, 0x23c7f301, 0x1ef55646, 0xcaf5818d, - 0x973bcfa2, 0xf8d8fb43, 0x08da5897, 0xe4157f8a, 0xe66bfc62, 0x5d10eb3b, - 0xc85eb33d, 0x57a97a46, 0x813cf6fb, 0x70a88b71, 0x27f4e38a, 0x32f9d9cf, - 0xfa20bb9c, 0xd816a49b, 0x5a6bcd7f, 0xc928deba, 0x35ec8715, 0xf129978c, - 0xc533c074, 0x5a1d9cc9, 0x2d6b171e, 0x73fa05b4, 0x5cfc09fd, 0xb2819a85, - 0xc017e8e5, 0x608eb87c, 0x555e7ee3, 0x28178f07, 0x1295597e, 0x8e0e6837, - 0x77a6081b, 0x2e455fa8, 0xc6a55f8f, 0x3b466cdd, 0xb3017ebc, 0x4d5ea587, - 0xcc78f03f, 0x74dfb2d3, 0x0af1fb45, 0x1bb1427a, 0x6e382b99, 0x65a9c8a1, - 0x8f1ef913, 0x6ab8e2fe, 0x76fdc604, 0x8a8f840b, 0x704f900e, 0xdab70ade, - 0xf802166d, 0x19ffee49, 0xedc01bd2, 0xa0f6ab8c, 0x19dd2128, 0x990ebf68, - 0x8e91ab3e, 0xd695bce0, 0x9cf02237, 0x38ae590e, 0x7f148dda, 0x8a5b64ab, - 0x612aee90, 0xf430ef3d, 0x0b5cf954, 0xa2d729f9, 0xaccec527, 0xb7ee0d6e, - 0xce487731, 0xe01eff8c, 0x396401bb, 0x992e7bd7, 0xf12332fe, 0x99906fde, - 0x879f9123, 0xedc09ff4, 0x5cfe4537, 0x3c581dbf, 0x6e71de60, 0xac05531d, - 0xa673e37f, 0x4f78faa0, 0x9bff507c, 0xcf41ccda, 0x4119bdb3, 0x598f73cf, - 0xdd79ea82, 0x4ffa8313, 0x5416d0f8, 0x0e2be49f, 0x4ce53fea, 0x307d5049, - 0x9573ce13, 0xe35bc1fb, 0x33fea085, 0xf9a0facd, 0x05446767, 0x320d07d5, - 0x52bb647c, 0xce5f77b1, 0x686ef6e5, 0x76f7c0a9, 0x8a3af04b, 0xc4e77ebf, - 0xd8e6f5e0, 0xa1fbd782, 0xfa0bd978, 0xc27e0554, 0xb15fa073, 0x13f81dfc, - 0x9a13f02a, 0xfac09fc1, 0x604fe08b, 0x027f01e9, 0x7f025fdb, 0xe0adeb02, - 0x20fd604f, 0x6f583ff8, 0xf2a62bab, 0x6a12ba95, 0xbafc16bf, 0xc98f75e4, - 0xd7971eeb, 0x74e177fd, 0x5def9e42, 0x9c6ebe79, 0xdcffcd2f, 0xbc563c59, - 0x2d3cfc04, 0x87c6acfa, 0x5f0ac37e, 0x062dc611, 0xc61892de, 0x7ddd99a5, - 0xf5062eac, 0x338a08d9, 0xb78192b3, 0x7d52ae31, 0xc9b4d520, 0x0fecfa8c, - 0xbef3e2ef, 0x7c8cc956, 0xefeda879, 0x85cf3811, 0x5f74614b, 0xef107a4a, - 0x5461bf1b, 0x31cf04df, 0x05b33a0e, 0x37e90804, 0x0bb7e90f, 0x4ddd4a69, - 0xcd25bdf7, 0x53c41a2d, 0x3c29f215, 0x0ea3cb7f, 0x635cfe7e, 0xf61373d0, - 0xe54ab287, 0xb9c238a6, 0x2f3e6536, 0xf1a477f5, 0xcf73cf7b, 0x053f5e1d, - 0xe2cb6ff5, 0x5e7f7811, 0xec5efcd5, 0xc7c157bd, 0xc85f07e7, 0x76cafba4, - 0x9fe0cf98, 0x96aed9cf, 0x8eff7ceb, 0x68a296b4, 0x02cd1c54, 0x05c50b1b, - 0x5fee85b6, 0x38f6daaa, 0x65556e50, 0x0066addc, 0x248f7e9f, 0xbdf837c7, - 0xb8c4c391, 0x22f9e71d, 0x5f57ef02, 0xc3bd1cf7, 0x38edf886, 0xf6eb811c, - 0xfe414ab7, 0xb72b68d3, 0x355b478f, 0xad0bbf84, 0x5ef02387, 0x30e7a377, - 0x4bcabb87, 0xd7243fe7, 0x7824a1fb, 0xfe7449b7, 0xd0624b8a, 0x5586763d, - 0xb66679a2, 0xb9e2358d, 0xbd7c3c7a, 0xb799ab1c, 0x825e2da7, 0xbf1e3ffb, - 0x7b224f20, 0xca350410, 0xef661bf1, 0xcaa43b41, 0xf386d923, 0x79e40aef, - 0x4e9cd4bb, 0xdfdb4adf, 0x78f8f285, 0xd26c88f1, 0x699f8a11, 0x916f76e5, - 0x7a869ec6, 0x3660c7a4, 0x583f9d22, 0xfc446a9c, 0xdb12c21e, 0xec69778b, - 0xe6c7bc06, 0xba98f5eb, 0x7aee9023, 0xb425735a, 0xf2f99477, 0xe88775e5, - 0x2e6f087b, 0xbbb953c2, 0xf8f380d1, 0x73dbc7f1, 0x7fea26ac, 0x3cdefddc, - 0x327aabb4, 0xe92ec9c2, 0xa7f230d2, 0x5db99aab, 0xd891d3dc, 0x924f7818, - 0xf2fd9563, 0xdaf0910c, 0xfb96a6d7, 0x0587bddd, 0x39d353f5, 0xde0eec2f, - 0xea7dc98f, 0x1dc7b451, 0xf50c4b4f, 0x1b5d43a2, 0x6cffe78b, 0xcafef067, - 0xd43b3865, 0x00d8d8de, 0x0fb4757a, 0xe8818df1, 0x13e15dbc, 0xc153e133, - 0xb7064f63, 0xf9e27ae7, 0x65a3a4bd, 0xe5f5d10f, 0x64eea4f1, 0x7f121ff4, - 0xe778a3a9, 0xc567fcb5, 0xaff0086e, 0xea8bfa18, 0x313cd4e2, 0xbc1f6fc5, - 0xb6ab6b96, 0xabbf448e, 0x1ecafc84, 0xac2cf606, 0x3a7b44e9, 0xb61ff292, - 0xad83bae1, 0x76bfba6a, 0x7d66daea, 0xa0d97602, 0xf6051805, 0x2d53b83d, - 0x0cd97bdf, 0x952ed768, 0xcccfdaed, 0xf4097cf6, 0x488d73af, 0x866473e7, - 0x27d31f91, 0x5bcfbdcb, 0xbb24ef92, 0x426498e1, 0x8786687f, 0x668ec1db, - 0x7b56d76e, 0x2a63ff92, 0x6acdedda, 0x8a60d4cc, 0xed94e21d, 0xddb2d390, - 0x80cd7a7b, 0x4e9bfc86, 0x8c963d81, 0xbb5b2a79, 0x33b9e112, 0xb3d91673, - 0xec99a94e, 0x83db6589, 0x6fb007ed, 0xcf55ea82, 0x7217da85, 0xdc13cb7c, - 0xdb87f8ae, 0xc67643ac, 0x0a67f438, 0xc871a9a5, 0x78c82f0f, 0x959bfc55, - 0xb7942de3, 0x9e6551b3, 0x1021c4a5, 0xfb9d355e, 0x6edf702b, 0xfc859847, - 0x10af558d, 0xe4bffb5c, 0x3c7f4c7e, 0x33f47823, 0x36fedf0e, 0x6a35e74e, - 0x48f98dc1, 0x34b64035, 0xaf704e9f, 0x6bb338c1, 0x13e48230, 0x17c8c563, - 0x7f70162b, 0x5f3186d5, 0x7e156b28, 0xb7abd108, 0x54527ca8, 0xb3689c80, - 0x02bf50a6, 0x3ea3b30d, 0x90b4695b, 0xe3a31b7e, 0x6ae17a76, 0xc3d2364f, - 0xb5c7f018, 0x31f8f101, 0xfb010186, 0xc7807eed, 0xc27895ff, 0x1d49951c, - 0x191fa015, 0x95fd435b, 0xf0a241f9, 0xdf9ad7f1, 0xfc1bf304, 0x23bc03f3, - 0x585fde11, 0x93b7a42d, 0xfff728e6, 0xca97c4b5, 0xbd002e79, 0x63181c61, - 0xc7378834, 0x9fc837ce, 0xf5eeb273, 0x8228ae38, 0xf708a3ef, 0x5e30f583, - 0xe79651fe, 0xbcbc79b1, 0xf9152e4d, 0x7b6790d5, 0x95f50adf, 0x593ff679, - 0x8899ae49, 0xb4ca573e, 0x9c4cf602, 0xbbf9186f, 0xf0891de2, 0x03f005fa, - 0x5ac2fbf2, 0x64169cc1, 0xaf3a712f, 0x3cec4de1, 0x454ef4f3, 0xdd6cb838, - 0xc6d79819, 0x5a2d7f38, 0x05a737a5, 0xbd2007de, 0x0251ffa3, 0x2fd1f2ff, - 0x5372bfe3, 0x57946dc5, 0x8cd62ab5, 0xc83517f7, 0xa6d7290f, 0x87ba50ff, - 0xb7a44edf, 0xa0b5a66a, 0x0b69a97e, 0xa1516e7d, 0x084dfe3d, 0x74c9245f, - 0xe81768da, 0x5bf1bd7e, 0x95a38f15, 0xbb37140a, 0x4e911a0b, 0xcafd87e9, - 0x7e71b9a7, 0xfba0b3cc, 0x391886ae, 0xee862bef, 0x9f227ee1, 0xf7952eff, - 0xa3efe40d, 0xc6324f6a, 0xf93a8e71, 0xe602d53d, 0x52dd7ba1, 0x6f654dd6, - 0x2f01f578, 0x8d1aee4d, 0x7607f87e, 0x1a91c52d, 0x511936d7, 0xb5b166ce, - 0x031fbc26, 0xfbee7936, 0x1bdb2bdc, 0x9468f7a1, 0xc7e7959f, 0x92bccaf3, - 0x83a03cf8, 0xf8a38033, 0x57c7cb9c, 0x02207fbd, 0xfefe7ee1, 0xca7ef3fd, - 0xb9020fd0, 0xd654f305, 0xbdd064b6, 0x67758b8c, 0xabf1fbe4, 0x1fc153e0, - 0xf08399b4, 0x0eb9670a, 0x0d9f33e0, 0xd36e63e4, 0xc0a9f0b5, 0xf03d4939, - 0xe8250463, 0xa1439231, 0x5ee05678, 0x3cd56acd, 0xeefb56fe, 0xb3ffe802, - 0xed19a2b5, 0x7ef0cbca, 0xf578fc0d, 0x28d791fc, 0x257b3f90, 0x5a78297c, - 0xff54bcc8, 0xfb8f8a30, 0xf144a170, 0x7c69ffc3, 0x4bd9e435, 0xb7c2aef2, - 0x257a7ca1, 0x2ab45cbe, 0xf8437f84, 0x2d2f8874, 0x7f002ff0, 0xc41155f6, - 0x1d7e0a8f, 0x5193f066, 0x2d1875ff, 0x3e39766e, 0xfdc5dfd1, 0xec0ab654, - 0xf087e149, 0xe3fc8fab, 0xad017c50, 0x541f50d8, 0xa9f305e7, 0xc92bc782, - 0x7dee452d, 0x4d47bcc4, 0x7067dd02, 0x9685fe3e, 0xfb94e9f2, 0xe2dee50c, - 0x6fae3cd1, 0xc08fcb42, 0xa27bc16e, 0x233d194d, 0xd5ebded1, 0x7bf0f328, - 0x74d68fd7, 0xcd7cc68f, 0xb2f1a68f, 0x4cf3c357, 0x8c2dba94, 0x4a3f03c7, - 0x6e10bad0, 0xa6e3091f, 0x91f01da3, 0x783bcbf0, 0xc6634e3d, 0xe9b882fa, - 0xaaf7a826, 0x83e1f895, 0x5376fcb2, 0x0982d1f9, 0x604fd405, 0x661e1047, - 0x3ad09581, 0x0c5d1082, 0xe7e8f9fb, 0x5ef07363, 0x03ff3940, 0xf48e3c79, - 0x431cf91b, 0x095ff6f1, 0x045f6f14, 0xf784c3aa, 0x289fd302, 0x93f6814e, - 0xa6cd4ebf, 0xc115cafb, 0x4dfea3eb, 0x56e538a6, 0x4b96e79a, 0x99c5ea03, - 0xe90d7dfe, 0xbc8b82cd, 0xa0d8c97d, 0xf45b667c, 0xbb27ee38, 0x8f512353, - 0xf06d7a29, 0x60437ed8, 0x1cacf51c, 0x8faa1e77, 0x5029247b, 0xf7b1be2f, - 0xa79c74e1, 0xb2cae35c, 0xf98f3018, 0x1fb424a9, 0x943ef7ca, 0xdeed764e, - 0x9fe8e98d, 0x9c3d3794, 0xb87aa36e, 0x1523fc9d, 0x7df9f73f, 0x0a6d7693, - 0x9d6fa3b0, 0x52fbedc0, 0x68851bdd, 0xf1bacedf, 0xb71875f3, 0x816bfb1f, - 0x590b70e2, 0xb7d43af7, 0xaf9c1965, 0xe48e8358, 0xf747cc3f, 0xddc67ba4, - 0xfee51bbe, 0xabbf8cf1, 0xcdfea097, 0x657cd153, 0x0e39bdcc, 0x041b6fe3, - 0xfbf9bf8a, 0xd77ba68f, 0x4d056bc5, 0x51ea0c7c, 0xc7fd779e, 0xe38228bc, - 0xbbb21b3d, 0x356cbdb0, 0x75a59f6f, 0x3ce0f6b7, 0xcf28684f, 0x4a65140a, - 0xf63dc049, 0x3df8f31f, 0x72cda2dd, 0xcebcb1be, 0x8db16dd8, 0xa3fce781, - 0xfe567f8c, 0x3b83c901, 0xb6dcbc65, 0xf123bdfa, 0xdaa46f30, 0x2b9467fe, - 0x3a7e3eef, 0x4159e50d, 0xa44cd9f4, 0xfb1ab1f3, 0xee781593, 0x2bc52d26, - 0x528959ad, 0xb9cff41c, 0x5863da7f, 0xf8bd5a2e, 0xfb8c0ac9, 0x1f91d76e, - 0x856feca6, 0x5fd11660, 0xd3f8dc3d, 0x676e107b, 0xa479e71e, 0x8faf1a2b, - 0xe2fe5abb, 0x1f3c75b3, 0x1d3af9fc, 0x99d42f95, 0xb88e1998, 0xea9e2eaf, - 0x5333afbf, 0xfa73e6c9, 0xaea6f252, 0xa5ee5f34, 0xb65bca30, 0x1e51d06e, - 0xf6d6ae7d, 0x6bc01e55, 0xa6ce0dec, 0xc6b9f28d, 0x576cf8c2, 0x83840cf2, - 0x2ef2e375, 0xe54f6134, 0xedeaff71, 0x64490d9e, 0xf53eaf87, 0xcf3c054c, - 0x0ef92fcc, 0x5e76ebc7, 0xe1c178a4, 0x10ca87f6, 0x5a4de5de, 0xdcf93e7e, - 0x8f4f1e67, 0xbce3127b, 0x7fc9a96f, 0xea79d9af, 0xde508d99, 0x26b979bb, - 0xe87fde90, 0xf795bf79, 0xbabe2d73, 0x75fe1c12, 0x89387abe, 0xf809a7f8, - 0xe7dff32a, 0x6bd59aab, 0xf3737e08, 0xc3e6c64b, 0x5da8cffe, 0x674fc849, - 0x744cddc6, 0x0814eaee, 0x571c8afe, 0xf3e6a7c6, 0xd12ae8fb, 0x48ec99b3, - 0x057f8e59, 0xf7c2239e, 0xd2cff68d, 0xaafe8ed1, 0xcf55c16d, 0x3d0eb07d, - 0xe99b8c22, 0x9e7d0ca8, 0x62a7b1af, 0xc8be715e, 0xe7d0e7ed, 0x712be7b7, - 0xc5b71e78, 0xa790109f, 0x458d84e2, 0x13fea346, 0x972061bc, 0x9eb76d9d, - 0x06ffa155, 0xc1c7e17e, 0x38fb2876, 0x695faf40, 0xab2ad7bf, 0x5f951e71, - 0x50f84eee, 0x3d00de64, 0xc617c93e, 0x0eeb01bc, 0xa6d02bf9, 0x049efba1, - 0x37880b92, 0x6bea87cc, 0xf584d71f, 0xc78e1ab3, 0x97e083be, 0x930cb8f1, - 0x3ce7fdf2, 0x0b3e7edb, 0x79e86ce5, 0x4f395fab, 0x7b68e1f4, 0xe740a2e8, - 0x9556799f, 0xbff3ed75, 0x167cf7b1, 0xdaacefe2, 0x57fe8f97, 0x8597c69f, - 0x957ea878, 0x157ff3cb, 0xc57b4a0e, 0x138f0d06, 0x23f2260a, 0x140ba50b, - 0xc63be807, 0xedd500e3, 0x0e9e48bb, 0x4c78f076, 0x145dd88d, 0xda8bf187, - 0xcf285d53, 0x5fb9e306, 0x28dbf306, 0xd65521cf, 0xa481aa83, 0x1ed72039, - 0xee07a219, 0xfe419e0f, 0x1e3ce0d5, 0x6561e507, 0x2bb43385, 0x433f21ce, - 0xe4aad97b, 0x67e748f5, 0x507323dc, 0xf59dbe3e, 0xdf8a6a8f, 0x926e1ebd, - 0x30958ec8, 0x4e0878c7, 0x4b70e743, 0x2987d13c, 0xb3387176, 0xd1abf405, - 0xbf24ef98, 0x9fbf38fa, 0xf381b9ab, 0xf3857b13, 0x1bed7393, 0xf980f89a, - 0x93f3257e, 0x7ace4f62, 0x97c41ffd, 0x9edae70f, 0x470cbe40, 0xc5f38859, - 0xb51e5247, 0x72871ef2, 0x90e8691f, 0x8962f8fd, 0x49b4d79e, 0x58e5ef0c, - 0x0af291bc, 0xca16d98a, 0x3cc59cb7, 0x8f5e7953, 0xf029d1ef, 0x52ebf67c, - 0x81a1e62e, 0xdbf74d3d, 0x34f66145, 0x15ead3cc, 0x1eae1905, 0x7d009ceb, - 0xf73e7ef6, 0x024aa757, 0x8481b1e9, 0x6653b270, 0xe29677ce, 0x5a7e957e, - 0x9833eb91, 0xe62cec87, 0x7bc2c81e, 0xc81de655, 0xa556fbc2, 0xc3d7bcdf, - 0x322f496b, 0xc05e758f, 0x79f3a73a, 0xbc0bf3bc, 0x5279071f, 0x16c3df23, - 0x436edf4a, 0x27456b7f, 0x15ec7fbf, 0x3cc03f93, 0x19c01733, 0xf01e7af1, - 0x63fd436a, 0xf21b3667, 0x6e91f8cf, 0x7d9a9fe4, 0xbd7cc302, 0x136d76ea, - 0xd5aa85c6, 0xe7a458be, 0x6bef6d8d, 0xf06b9e90, 0x8e3c765e, 0xdcbc7267, - 0x35bf7944, 0xf5efc626, 0x00ffaeda, 0x63ce76e3, 0x553a8b5c, 0x003c51ef, - 0x57ae36e5, 0xfe42dad5, 0xc97983bf, 0x073477ff, 0x3c60cdd3, 0xf287e78f, - 0x737ce9c9, 0xdccc7f10, 0x1e63f9ce, 0x681b73e6, 0x675fc538, 0x5d91c7c6, - 0xf1c71fe2, 0xafce9360, 0x3fa63b43, 0xfc7ca045, 0x5ad730fe, 0xe95c8fb4, - 0x7fe9aedc, 0xbd2b05ed, 0x5b73a3f7, 0x3cf98c7f, 0x733bddb2, 0x149556c3, - 0x1d999fb0, 0x1fd8de3c, 0x120fcac6, 0x21d7edde, 0x25b97c3e, 0xbe31f267, - 0x777819a3, 0x4483c60a, 0x3d0d1f1e, 0x6b8e5d87, 0xfdfc671c, 0xb3df6528, - 0x3cb91313, 0xa3a26e63, 0x5bbf392e, 0xc651d7c9, 0x504132df, 0x9fb8d1ee, - 0xfaae5824, 0xd7de1a5e, 0xde2b9e60, 0x3bf960d7, 0xef161f39, 0xa2feb06b, - 0xf78b0f9c, 0xf78ed835, 0x956f5835, 0xbef161f3, 0x5f78eb06, 0x722be583, - 0xdc71ec3e, 0x6df1e52a, 0xa2e90a7c, 0x946d790b, 0x1d1bdebf, 0xdc151f52, - 0x085a37bf, 0xa8128fae, 0xc6c269bf, 0x78ff30a7, 0xc52f9293, 0xc3b446cc, - 0xfbf9c22a, 0x7b06a91a, 0xf3f404ec, 0x45ed778b, 0x9bf81e7f, 0x882b9fde, - 0xef4a505e, 0x1968c497, 0x27dba3ca, 0x804f47d8, 0xcd8ec7f1, 0x724adb48, - 0xecf74f52, 0x31bb3fbd, 0x6f7ae292, 0x25824c49, 0xaee465a7, 0x9a7d42b5, - 0x85fa2041, 0x512a6ef9, 0x67984cfc, 0xab62c746, 0x1307cb8a, 0x9285cbda, - 0xb3ae0963, 0x8b9f4122, 0xd588f872, 0x51fb819e, 0x6a345de0, 0x45da1a59, - 0x07f36a5d, 0xbd759f18, 0x57e866a3, 0xa53c7129, 0x69d693df, 0x99bfb8f9, - 0x736ba919, 0x36607e70, 0x0d367794, 0xd9fdc66b, 0x9ea170c4, 0x855997e4, - 0x027f20f2, 0x66e99ba7, 0x357b1f6e, 0xfa345566, 0x62d361f5, 0x4bb75ef0, - 0x1931f3c6, 0x3c65c7cf, 0x81573de3, 0x6173df8a, 0x585cf789, 0x2da3e686, - 0x4db12fcf, 0x240f7820, 0xcdb3e605, 0x0097df92, 0xd4f7a10a, 0xf31c729c, - 0x34ee594b, 0xcadc95e6, 0x9e6879c7, 0x778e392a, 0x6f7c1d5e, 0x8ff38ca8, - 0xbdce5467, 0x166bcb89, 0xbf79e1a9, 0xe61731d7, 0x397dcf15, 0x7d50e281, - 0x06a5d16e, 0x5e05cfbc, 0x5ec67947, 0x8b2efee6, 0x77337ce7, 0xabf51c7f, - 0xcea9e397, 0x7c74eee8, 0xe64fa3af, 0xf07ea52f, 0xe4979e3b, 0x81ba81cc, - 0xf3a123de, 0xa776e739, 0x4fbd4147, 0x5f488bd0, 0xbcfe26ce, 0x673fe647, - 0x7c9f3c8a, 0x24f3a61e, 0x3bfa3e21, 0xf7c24e5f, 0xbc193710, 0xf7fcb94b, - 0x66dc93a6, 0x6fcc74de, 0x4e782f3a, 0xadf1be62, 0x98a5296d, 0xed5e7f6f, - 0xb3eb0679, 0x5d78d2db, 0x0a693968, 0x93d23e7c, 0xb7c8f984, 0x6296a5b6, - 0x91f9f23e, 0x5944cf2d, 0x97eaea02, 0xcd73e24e, 0x98a56983, 0xeb5b3c9f, - 0x7487563e, 0x5f4e7bf3, 0x4e077dfa, 0xdaaa7c23, 0x7d3efdb9, 0x2f0b81df, - 0x603e7ea1, 0x7582bca4, 0xdf099213, 0x6ecfedf5, 0x6beb7a46, 0x6c3f1351, - 0x99ff7e6a, 0x2d3f50df, 0x6b665985, 0xc90c563d, 0xba1db494, 0x3b35f71b, - 0xd625f3dc, 0x89bc4f17, 0x047b31f6, 0x13a5ebe7, 0x4f914a73, 0xfbec0efb, - 0xd9b3ea05, 0xe2d86091, 0x13d05e7e, 0x8ff72a7e, 0x40b8c02b, 0x0cbbb19f, - 0x9dfeafe7, 0xec1fe796, 0x718e9b8f, 0xc09cff82, 0x6e2a31f3, 0xfa8492d8, - 0xf9e57c56, 0xf8c1bfbd, 0x74f4efe6, 0xcd1353df, 0xa94abded, 0xe1397f31, - 0xcc5ed76f, 0x5e7be95b, 0x15aff74f, 0xe2b39318, 0x2963ac7b, 0x3feaff3e, - 0x78865eff, 0xee769428, 0x772ff6c5, 0x438445eb, 0x7916c68f, 0x8f61f233, - 0x0acefc9a, 0x3bd15eb9, 0xdc27ef82, 0x8bf84457, 0xfa8492d9, 0xafc472b6, - 0xcf7dc0ee, 0x833cb696, 0x567b0f7e, 0x670e774b, 0xc1b8079f, 0xd47bb3b8, - 0xfb034998, 0x5e90aa30, 0xca5b0bce, 0xf7f9c49e, 0xf5e77ef0, 0xae9e085b, - 0x5c33d73d, 0xd431fa0f, 0xad85e7c7, 0xf767ed41, 0x7e859b3c, 0xcddfb9e9, - 0xa154ff26, 0x2a5f8573, 0xf4836b77, 0x58824922, 0x3fca5b8c, 0x02198b93, - 0x0ee759e2, 0x927be8ee, 0x6b9fc7f9, 0x00357b56, 0x5b2d0aa3, 0x0acdf98b, - 0xde26543f, 0xabe78c5a, 0xd1d31b14, 0xf5c8a97e, 0x9c5f2195, 0x3c5d33d5, - 0xd65b7bf4, 0x6bad955b, 0x7c1da0e6, 0x45fcfda5, 0xc95f4796, 0x9b55f87c, - 0xdf781dde, 0xb5fe5a18, 0xa84f998e, 0xb585f5fc, 0x95e5b25a, 0x78d6def9, - 0x55afe81c, 0x71f97347, 0x8337fa12, 0xac93fb1c, 0x0aad16ef, 0x04eeffee, - 0xad594f9e, 0xfea3a5f1, 0x7b7fe653, 0x87db8982, 0xca3a5f2a, 0xb371d0ab, - 0xbcde5925, 0xa9bc9020, 0xd14e156c, 0xd20824fb, 0x2b3c3f58, 0xe6372e75, - 0x87870d13, 0x0f197cf8, 0x70f1e612, 0xd66caabe, 0x4f30f4db, 0x022f9855, - 0xd18725ed, 0x50768117, 0x6b122bdf, 0xa317d192, 0x5fe29fcc, 0x5653894f, - 0xfd36d478, 0x71c1eb70, 0x865e4fd0, 0x5628037f, 0x537ce44f, 0xeb4e16de, - 0x1f2f9331, 0x677cb6e9, 0xa73c38f0, 0xfb1f8029, 0x06c576da, 0xf70cebfa, - 0xa751f74d, 0xfffa6f88, 0x07bd31f9, 0xb5b2295e, 0x4e794f78, 0x4083efe0, - 0x3907de9d, 0x5677df27, 0x43086d7e, 0x95f739fa, 0x4fb8f883, 0x7b9c91f0, - 0x7246cdb1, 0x23ed4fac, 0x626bb739, 0xf947af11, 0xbd6e50ca, 0x24a7f138, - 0x7c12fa3f, 0xd29ef865, 0x2f8ea566, 0xd01d81cc, 0xe490b6d1, 0xe7896cc9, - 0x6a5db051, 0x71138f13, 0xe1932f78, 0xde86d8c4, 0xd443f23a, 0x3a97b466, - 0x42f72a27, 0x25f9ff1a, 0x31f53f3f, 0xe456bef3, 0xc50372cf, 0x6abec07d, - 0xc0ed097e, 0x8c16b105, 0x4dc287a7, 0x898c5fb9, 0xe22966fe, 0x7da31de9, - 0xbc3cc4ec, 0x9f91f4cf, 0xf64ed401, 0x5a6bf57c, 0xd5fb37f2, 0x7e517b03, - 0x71f68db9, 0x0e9e0113, 0x547af74d, 0xbed41771, 0x67ed342e, 0x1c91bd21, - 0x97d6f4e1, 0x07bf8bb9, 0x4e4fdf22, 0xfa00f192, 0x7d22358c, 0x87cf1c08, - 0x409ff6db, 0x9dd7d379, 0x943a724a, 0x3db6ce9f, 0xe3728116, 0xaeefd043, - 0x87c07880, 0x7ca59f8b, 0x0798f980, 0x6b3de502, 0xf837cf83, 0x2fc98fed, - 0xda039b64, 0x821b1e91, 0x4170a1eb, 0xf106f4ba, 0x7df68b81, 0xc01bf23f, - 0x777a6aa7, 0xa861c235, 0x52ea173e, 0x4850fd40, 0x2b3fa43d, 0xfdc3f6e1, - 0xebcd1813, 0x25eded18, 0xcf1f7e3f, 0xbd07adef, 0xe103f546, 0xee2d3f74, - 0xc315bd03, 0x8bea16f5, 0x8a6e88aa, 0xd01df55f, 0x83cabdd2, 0xe1259fed, - 0x291e81f9, 0xfed5534e, 0xf7fa2c72, 0x699826eb, 0xb18fd07e, 0xa0731794, - 0x11fd163d, 0x7a21dda5, 0x0cf7e5d2, 0x287e50b2, 0x9bc94eed, 0x42e5794e, - 0x5f3e1677, 0x8719cb27, 0xeb097508, 0x10e1ce8c, 0x76b3df38, 0x287ce489, - 0xf4c956de, 0x8b21f20a, 0xe15e39f2, 0x1e4503f1, 0xe572c854, 0x7267b610, - 0xf72937fe, 0x84cf7852, 0x9c8c3f7c, 0x23815af8, 0xcef8a5ab, 0xbccd13fd, - 0x79a78f2e, 0xe789fc79, 0x3e7abded, 0xc713252b, 0x45f79599, 0xd528f2fd, - 0x0e505f2f, 0x781c93c4, 0xe70b1d50, 0xb0467caa, 0x8a90c3d4, 0xd04535d2, - 0x2d532d9d, 0x1ab8a22f, 0x2e1ae7e6, 0x1d2857df, 0xf8e44e45, 0x1fb914ad, - 0xa057b95e, 0x6a73a5fb, 0xf2076f7e, 0x580fde86, 0x08a6b056, 0x18beeff9, - 0x5fd026a7, 0x4bfcd6be, 0xcbeb821b, 0xc514d76a, 0x95e7c30d, 0x8d76b6ab, - 0x57cf9764, 0x8a2c6f61, 0xaede5f35, 0x5e9cfbec, 0xf574e7d9, 0xcc7840c8, - 0x1234535f, 0x7fba65ca, 0xdcfc1e17, 0x5eb5dae7, 0x5d2d57ca, 0xb7c4f743, - 0x8a0daa5c, 0xbe6b5eb3, 0x7ba6e60a, 0x3fed2b90, 0xde0874b4, 0x312b8c5e, - 0xc43dafe0, 0x0137c067, 0xf4cbc5eb, 0x289f143a, 0xfd063c5f, 0x3c5f6653, - 0x113e3026, 0x339be25a, 0xb88ae522, 0x2c3e04a8, 0x0f030cb3, 0x89d1ffa5, - 0x3f1ace3c, 0xa8f1d391, 0x5e3b55d9, 0xe9d71462, 0xa57bf941, 0x22fe4cf7, - 0xbf07efef, 0x9c233267, 0x9bd4ebf7, 0xdfd3fe30, 0x87c50df9, 0xe619d7fb, - 0x03077bf3, 0x5de7804b, 0x029be3f1, 0x26abc0e3, 0xdc243b71, 0x9a9dedca, - 0xe3d5f50c, 0xa1c6994b, 0x1bd912f8, 0xdf74e199, 0x05f6d7d2, 0x8efeb7e9, - 0x8bde133c, 0x0dbb75f4, 0xff356fc8, 0xa8b17ffc, 0x3e3afb87, 0xbeb4bca5, - 0x7ca33f6f, 0xde728db5, 0x3936a1e0, 0x6cdbabdf, 0xe2fef6c4, 0xbf6117bf, - 0x8fe9724d, 0x98f8f02f, 0x83f12a52, 0x3bf9ff00, 0x4c7b53d4, 0x54c51f1b, - 0x2db0ca99, 0x7fc0bf24, 0xe1bd468e, 0xe3982b8f, 0x04c38b86, 0x54d215c6, - 0x2580ae3c, 0xd2d215c6, 0xeb015c78, 0x12c05718, 0x8ed80ae3, 0x63ac0571, - 0x18eb015c, 0xc63ac057, 0xb8c4b015, 0x297fb602, 0x0fd1e7bf, 0x3dc78b82, - 0x57f7240d, 0xc0337e62, 0xbf27656f, 0x47b95abf, 0x7c617ba2, 0xdff503cf, - 0xad3b7965, 0x678ede72, 0xd607dd2b, 0x882c901c, 0xc41f7c22, 0x3bf98e95, - 0x1e314703, 0x5822d354, 0x7db198d6, 0x6363ed3e, 0xa507de47, 0x6d47bed8, - 0x4f44cd11, 0x828d9f1c, 0xd57c8f5b, 0x57e287b1, 0x949d7105, 0x2cd35fef, - 0xcebb8c30, 0xd93f72d3, 0x0e6b4129, 0x1d92abdd, 0x9376d4ed, 0x9cf552ff, - 0xef7c0e60, 0x45e266bb, 0x7dca1392, 0x88fe52f5, 0xf37a3d39, 0x6b3d2092, - 0xf85779e3, 0x29c7ec27, 0x1d9377e7, 0x2d176012, 0x6c6c7bc5, 0xf7a5be97, - 0xe0e09c4d, 0x9dae108e, 0xd1d95577, 0xb5f31eb2, 0x55fe687e, 0xdef924e1, - 0x47bf9b3a, 0x92f8fc52, 0xbd60077d, 0xb25a2dc1, 0x609f6e53, 0x1e526dbf, - 0x28d819e6, 0x53b472ee, 0x27d67e4f, 0x8a0faf5b, 0xd74a14bb, 0x8563dc51, - 0x7dfd205a, 0x3b9f6ac4, 0x4672e809, 0x6f14bdf1, 0x246f1199, 0xf0e8563e, - 0x4fc96b49, 0xe315de70, 0x0a9877f9, 0x34e7ecb5, 0xa5cf9c9f, 0x5eb0a9e0, - 0x2cf7e370, 0xbd0b3316, 0xc008b03f, 0xe5517187, 0x188b1ffb, 0xe850afcf, - 0x8156c56a, 0xbcbe8ae8, 0x84bdf010, 0x103df845, 0x6af77fd0, 0x289bfdb9, - 0xc4f27bf2, 0xe28f3c4d, 0xfca7663e, 0x7d486591, 0xd7d7e912, 0x0f6ed07c, - 0xdb892ebf, 0x9c38e6f7, 0x3571f17f, 0xc61707e5, 0x276e9edd, 0xf9405f3d, - 0x6ef78213, 0xaf1bfbe9, 0xf3833f26, 0xb9aa8e27, 0x927801dc, 0xf485d59f, - 0x3b1ef14a, 0xcaebc795, 0xbf229ca9, 0x5efa161f, 0xcbe77f43, 0xb0be382d, - 0xf84160c6, 0xc03df15f, 0xffbfabb0, 0xebf394e6, 0x5c9ec512, 0x6be3c233, - 0x51e10583, 0xef49d718, 0xf3caa589, 0xb25b9c3f, 0x8b69f109, 0x1f5c2e60, - 0x00b669ef, 0x40f08b7c, 0x3dd1c602, 0x66cf7c36, 0x513053a0, 0x7265f53e, - 0xcc3aeb74, 0x1349a953, 0x2daf184c, 0x1852db0a, 0xa517f30b, 0x7677d324, - 0x1c78da6a, 0x4e4a0fb6, 0x92dc5307, 0x62aac7c0, 0xf1cf7e31, 0x3fb5cbe8, - 0xdfcf293d, 0xb3e65b3e, 0x782f8efe, 0xe3b5f11e, 0xfbe9bbb4, 0xef4f4c1c, - 0xf60fd3af, 0xd1c6fb35, 0xe855af14, 0xae39b068, 0x45a8e909, 0xa5a513d6, - 0x8ed1a9ef, 0x37b3cc68, 0x96ca1c23, 0x4b175c5c, 0x4e3e1ce7, 0x87dfe4a6, - 0xe502c9c6, 0xde46ffed, 0x5aba89fd, 0x5baddf2a, 0x9d776545, 0xe8079e8b, - 0xbf08238b, 0x7d6f101f, 0xf130d27b, 0x4733a656, 0xbe05be92, 0x90edf1e7, - 0xbbf02af8, 0x33efc018, 0xd9eea23a, 0x8348f680, 0xcdf782c6, 0xd2bcff98, - 0xfde1f240, 0x59c6c349, 0x2819f815, 0xf4c83b2e, 0xe9878839, 0x112aa919, - 0x926dff9e, 0x44e71410, 0x2273c1be, 0x7c8960df, 0xf9f952a3, 0xa30d69e6, - 0x7da194ef, 0x40fb22e0, 0xbf5df84f, 0xd40ae406, 0x20a665ef, 0x442172b9, - 0xf32380ae, 0xac5f7a33, 0x0936cb43, 0xe9cffcfe, 0x19ca5c50, 0xb878ce46, - 0xe61d199c, 0xb3be9e79, 0xf9461d50, 0x44efc0c5, 0xf2374767, 0xac25bdbc, - 0x461dd684, 0x3e7bd0de, 0x38188ef7, 0xbff414f9, 0xd90361f7, 0x9613eb39, - 0xe477ffe6, 0x71279fcd, 0xdf813c78, 0xed5d5073, 0x059b0e7b, 0xb15d8fbc, - 0xbe236590, 0xc439ef95, 0x7bf218c1, 0x39eff5ff, 0x123c988c, 0x0ae0e7bf, - 0xdc439efa, 0x30e7be15, 0x6171b26a, 0x461cf7e0, 0x30b11e4d, 0xc60e7bf8, - 0xb29df885, 0x39efc1ff, 0xbbce4fa4, 0x370e7bfc, 0xa0ff364e, 0x3d8039ef, - 0x4fe3899b, 0x63c6d8e4, 0x3b9f2899, 0xe3e5fdf4, 0x97643df2, 0xb2c52f68, - 0xa2a5c228, 0xc56dd176, 0x73d16df2, 0x5f03b63f, 0x1578444c, 0x037d963d, - 0x5125977e, 0xf2bca1eb, 0x49b6ad27, 0xb96bff38, 0x3cf8c9b6, 0x2f5fde34, - 0x73f60f9f, 0xcd0bf60b, 0xe2e8531f, 0x0e5cc9ae, 0xa9cb93cd, 0xc7bfc3f5, - 0xbf326f3f, 0xbed6be4f, 0xe077bf61, 0xd9feca7a, 0xdc56c596, 0x4ef7ec0f, - 0xb7ec27dc, 0x88664b04, 0xf80f7a0e, 0xc9757a72, 0x2e7462fb, 0x3fb38f90, - 0x9528f6e1, 0x14772ae9, 0x1ea30dda, 0x7ee14770, 0xe80e3547, 0xdf907df1, - 0x68f406ba, 0xf576fc3f, 0x7fdb1e80, 0xdaf9e36b, 0x9f6ff3a1, 0xf491fdcc, - 0x7e3403a9, 0x4dddfc0c, 0x1440c1fe, 0xe5e96dda, 0x14ae3447, 0xf66d4f7a, - 0x93764127, 0x8c7bf899, 0x01e636dc, 0x8c3d2191, 0x1e78c1d9, 0xe90c4163, - 0xef1d4ab9, 0xfdc0f95a, 0x38d1d222, 0x803bec37, 0xaedfaefe, 0xaf7e0c1a, - 0xaae34bd7, 0x5ec025e4, 0x64ee7a0b, 0x9474bf3c, 0x5ed08f2c, 0x39d9efc4, - 0x77d08fcb, 0x0b8ec0a6, 0x79be8f99, 0x594f9430, 0xe6bfb3ad, 0x62be5333, - 0x77a5bf50, 0xfa3d66ff, 0x5ba5e5b5, 0x2f17e435, 0xa58f5969, 0x269ef1c3, - 0x197d918e, 0xcbec1fd4, 0xfb65faa0, 0xf547d90c, 0xc7d717fd, 0xd02eb30d, - 0x13a456c1, 0xaa8e0e85, 0x4fd0e33d, 0xb30cea3d, 0x3c1df7f0, 0x269a5df4, - 0x5df4bdf9, 0xcadd39ff, 0x5d3965f3, 0x3f1df8c0, 0xa9ea8e8c, 0xaf1df2bf, - 0x1c8a956b, 0x8dcefa1c, 0x5e28b986, 0x7248cb39, 0xfff646ae, 0xc89897aa, - 0xbaf8511e, 0xb539e55a, 0x18c5fb1e, 0x8a9bfe79, 0x7aabf7d1, 0xcf9451c4, - 0xcfac3f4d, 0xacfba54a, 0x178f7ad8, 0x5db81de7, 0x15b9efa0, 0x5ab97384, - 0x9e389628, 0x4447e785, 0xa7815dfe, 0x98487e51, 0x37bfc147, 0xbf972530, - 0xf8cf103f, 0xca98db77, 0x369df21c, 0xed7a1e39, 0xeff1b4ef, 0xf7e7cd92, - 0x25510d72, 0xf9f1cba5, 0xf9e81b82, 0x1f52efc1, 0x2afee2b1, 0x71b4ef94, - 0x4e61bf7b, 0x557f3d06, 0x3d41af30, 0x5d807ae1, 0x7a6d3be9, 0xef80fbe4, - 0xf887bdb3, 0xd9f7d6ba, 0x1c0fef94, 0x23c3705d, 0xbd1c397b, 0x3355ef78, - 0xafe418cb, 0x3c3117ff, 0x56c0d29e, 0x000056c0 -}; - -static const u32 tsem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x3370278a, 0x45e39c30, - 0x8381e9f0, 0x5fd32918, 0x50c0cec6, 0x4055c401, 0x3f880bbc, 0x7c3032b1, - 0xff5e2566, 0xdb042935, 0x21818248, 0x88d7881e, 0x49a83031, 0xa41dc422, - 0x03261819, 0xb150a1f9, 0x5f3a4047, 0x0f77328a, 0x80a69c16, 0x872ae629, - 0x9163a760, 0x6819c647, 0x50e54bf2, 0xf40499f9, 0xa2be340f, 0xa2ffca8e, - 0xa013a10a, 0xe4d157e2, 0x3be542bf, 0xa6bafea0, 0x4edcdd8e, 0xc35dfd32, - 0xfc01a102, 0x9847b099, 0x009847b0 -}; - -static const u32 tsem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7dedff00, 0xd554780b, 0x733ef0b5, 0x7993331e, - 0x31e424e4, 0x1e4e1081, 0x03086820, 0xb78a8884, 0xf6301027, 0xd57876d2, - 0xaf0e2d58, 0x6b86f210, 0x7fb6bd2d, 0x78490806, 0x111fc1a8, 0x29e1d5ad, - 0x311d82f6, 0x0388b622, 0xbdabd228, 0x557c5837, 0x0bd11feb, 0x2a44908a, - 0xe5b5ef6a, 0x3ef6b5ee, 0x09939cc9, 0xafdb7b04, 0x7cfdffff, 0xc7ecee9f, - 0xf5ed7bd9, 0xfdad6bda, 0x8131c918, 0xe4230da4, 0x06fbfc22, 0x109d9221, - 0x9d37a132, 0xd72120e3, 0x66924218, 0x92ddfd2f, 0xbadc4214, 0xa349bfe2, - 0xe4febba9, 0x5f5f9a1a, 0xa4aff0ec, 0x4d1f5b4d, 0x2d096a78, 0x2fa1efbf, - 0x7cd04fc3, 0xad79ecfa, 0xce7eb4c5, 0x5d0fc924, 0x10ab1a1d, 0xd8e7ed02, - 0x520176c2, 0x9097e581, 0x927fa130, 0x45f8e8af, 0x9fe8b884, 0x37fe9724, - 0xa5b21c89, 0xd1e43e60, 0x99029ea0, 0x31364846, 0x7e6055fe, 0xf509fc36, - 0xd0677744, 0x779e75ef, 0x7fec13e5, 0xdb0a5f8e, 0xf27347e9, 0x4dc87203, - 0x6d08c6d3, 0xfb1dc749, 0xf908395d, 0xe4990cc0, 0xd8b68763, 0x0fca6ffe, - 0xd214754c, 0x080b67fe, 0x49d9f9ff, 0xcc82da36, 0x3be1eda6, 0x1a1f4e22, - 0xd99f67cc, 0xe0dfb8e8, 0x40dfdddf, 0x5fc0a7ff, 0xe5a1094b, 0x9e0c1ccb, - 0xc5d9d9e4, 0x1989ce30, 0xbf4316d7, 0x3213a673, 0x9d4d5688, 0x4490f63d, - 0x891aebf3, 0xcddb4edf, 0xcf1c0d29, 0xcbf8d981, 0xe80293a7, 0x60ee8e97, - 0xffc45f7d, 0x64ef38eb, 0xcc3fde3e, 0xfa102b1e, 0x8a97f641, 0xa0725da9, - 0x4bd153f9, 0x2d056a48, 0xee53191f, 0xd09a769f, 0xe6e9e4f2, 0x721340f6, - 0xc425211d, 0x1aea7293, 0xc91677fa, 0xad4228ba, 0xee8c0b6a, 0x4a6b0fe5, - 0x22f9fdff, 0x12fa01d0, 0x6a1fd6fb, 0xa0e9e99c, 0x7b375af8, 0xf4d08796, - 0x0f2cc0f5, 0xd9f5efe0, 0xd68f10b3, 0x676673f6, 0xfb5e0227, 0x06feef1b, - 0xfa08d03a, 0xb5b3c73d, 0xea48907e, 0x39fbf423, 0x31c3d13a, 0x9301dffd, - 0x0964254d, 0xb34d1b30, 0xd2a6d525, 0xe88d6cfa, 0x95e33891, 0x3b69b102, - 0x28994992, 0x0ff352e3, 0x2637bb61, 0x71c34ad9, 0xef0773e6, 0xb81a55c7, - 0x6fa50e67, 0x751274d6, 0x2912ba51, 0x75e2c6aa, 0x1a548a5d, 0xddc7038e, - 0x68425e1c, 0xe1c0cf7b, 0x02d86571, 0x47329fd0, 0xf5c2c40c, 0x42678003, - 0x4ca24a6f, 0x18f8e6ee, 0xfbbf72fd, 0x338f506c, 0x8e00bb8f, 0xecaa9009, - 0x0c8f0e3b, 0xb201937c, 0x43fc8296, 0xe02463c2, 0xb91eccfb, 0xe5070124, - 0x17f0a18f, 0xa42dae15, 0x1412d47b, 0x47ec56b2, 0x0324a4f4, 0xde1157bd, - 0x4f51290f, 0x42157e51, 0xd78b84ab, 0x129e6a5c, 0x35f06539, 0x193ba9f0, - 0x5e1cbfc7, 0xe518a048, 0x88d43152, 0xe307c078, 0xed4df92b, 0xbacba502, - 0x947ee5d1, 0x90218a6f, 0xe17e4333, 0x3bf457df, 0xbdccff37, 0xca91d29c, - 0xd3396b91, 0x2cdf8a8f, 0x8e92eb67, 0xc82008b5, 0x0f49b964, 0x40241210, - 0xeb6f0377, 0xbc78a2be, 0xfb5bbf04, 0xe7c86fdd, 0xc9983260, 0x053f9327, - 0x79bd07fa, 0xf0077ed3, 0x5edf3af5, 0x5d6bcc07, 0x7a825efe, 0xe8c7d38a, - 0x5daf95d7, 0x81d6ce52, 0xee808d7c, 0x9ea748c3, 0xc6a7d1f2, 0xa6767e02, - 0x748bf72a, 0x08933b7e, 0x6b75d9ea, 0xd02b7848, 0xb5e594b5, 0xb5e1696f, - 0x9d3b8e74, 0xd698bebc, 0xed06bcd3, 0x3adbbea9, 0x68870b49, 0x8d8b6b7e, - 0x85ab1fb5, 0x311f9a45, 0x8a148491, 0xc2c56d4f, 0xbe5a4e95, 0x17eaa375, - 0x34fd5eb5, 0x2d6725a2, 0xdeb2dfb4, 0xbdf00aa6, 0x3b23ad8f, 0x443849f3, - 0x39b1dfc7, 0x69239bf9, 0xf9b2143e, 0xf24fd387, 0xd945faf8, 0x022844a5, - 0x9c3a31b4, 0xae5c7921, 0xa9e50204, 0x7ecb7cbc, 0xa48ebfff, 0x5d363df0, - 0x45a0aff2, 0x4ccfd63b, 0x769e28d0, 0x3f048168, 0xc0f07f4d, 0xccefcc7c, - 0xdd00260c, 0x9f9c6e76, 0xc0f14c00, 0x461b99e6, 0xd2617b41, 0x6ce91d61, - 0x1f47ffd6, 0x00ec3a28, 0x9e994b38, 0x7e0d6a4f, 0xbcf9a253, 0x89b91249, - 0xadcf214e, 0x1fdbdc21, 0x4f5811b2, 0x8b6de8fb, 0xcdd44ebe, 0xb4eb5779, - 0x5d7f818f, 0x2009160f, 0x86353bda, 0x923741e7, 0xbeec8af0, 0xc85cefe3, - 0x5d2913ea, 0xbf2e0e80, 0x96675962, 0x4756f85a, 0x3c717079, 0x1c755ab9, - 0x897a488f, 0x578bd690, 0x62469ffa, 0xf07ae9f0, 0xe9f58128, 0x8163e78a, - 0x7ca05d27, 0x9cab830f, 0x1c1eb9ef, 0x6357caf7, 0x21b1f1e3, 0x7fa01eef, - 0x6177c522, 0x50eb0424, 0x0a24617a, 0x57c9e2fc, 0x9a0bb034, 0xc5c93109, - 0x7cfbd1a1, 0x1337201d, 0xaf583e22, 0x837e8dd7, 0x81568fc9, 0x6fe630f8, - 0xb7e4f7b4, 0xc1fb5893, 0xf87287a8, 0x697853ce, 0xcb87bb39, 0x847f4f59, - 0x732447ad, 0x4f75c21c, 0x5e7561e1, 0xc84c7d1c, 0x97cb940a, 0x817ae049, - 0xedcddea6, 0x6c06a751, 0x7900dfae, 0x910240b7, 0x134ddf38, 0x42d27ad8, - 0xe9a05d74, 0x162f44a3, 0x664b9d70, 0x2eb2d7fa, 0xbc9fd1f5, 0x16e9165d, - 0xd468df40, 0x8734803e, 0x23cd31f8, 0x92474c01, 0x26af4c56, 0x49f34c11, - 0xa405a63b, 0xaf43531b, 0x422a89f8, 0xfac4c47e, 0xa4e720c9, 0xe58b63da, - 0x3264d0bb, 0x3cce3eb2, 0x73782d9a, 0xf8ebf890, 0xe75f021d, 0xfc8aa648, - 0xf17af843, 0xe818b06e, 0xfc2854c5, 0xefccdbbb, 0x0ebe24e2, 0x693dea38, - 0xdd335780, 0xcd54548d, 0xf06d5a7c, 0x1c2444a9, 0xc41f32c7, 0xd6b8cc63, - 0xfb7356fe, 0x9c9f98c6, 0x491f23a2, 0x50cf666e, 0x71bdf438, 0x0828d1f0, - 0xab419e7c, 0x29b23adc, 0xb6494bbf, 0x6b9a5ac8, 0xe8764f74, 0x893f2f38, - 0x7ceb6747, 0xbe2af0ac, 0xa9b3c181, 0xcb0a9e07, 0xc297fa3a, 0xfea64ff3, - 0x1db24ca4, 0x86a20bd6, 0xbc56de70, 0x42def9f6, 0xd2e4fe8f, 0x57d66991, - 0x02d78a4a, 0x069f8587, 0xe37c7f68, 0xe47fea4b, 0x211bfac3, 0xa9ec2a41, - 0xe60101f9, 0x1a40ad7f, 0xc85e2913, 0xa0eda268, 0x6af5cd70, 0x698b8ecc, - 0x91f41937, 0x74c90b66, 0xee92cfbe, 0xe43ed023, 0xf41d9127, 0x6df367b3, - 0x7d695ba5, 0x63b69faa, 0x1e4005fd, 0x0b6d1dae, 0x9fd1b940, 0xf5329e4e, - 0x112efd47, 0xe836e1f0, 0xe4c3f163, 0x1fb436b1, 0x6fa27c95, 0xc75f2389, - 0x1d157cb9, 0x9eb0ea71, 0xb094cab8, 0x8ffa1b33, 0xb53e4314, 0x5d61f89a, - 0xe6cdd49f, 0x30e1c651, 0x59fa9de6, 0x6a7e0040, 0xc03b31f7, 0x3fd04855, - 0x74da3254, 0xb4dd1ff0, 0x7e42f50e, 0x50531754, 0xd83fa23f, 0x5f3d9e1f, - 0xd00bed3d, 0xb9d47d7e, 0x92be076a, 0x9fa0e9fc, 0xc8568f57, 0xf8bdfa60, - 0xfff63b3b, 0x1862a7b9, 0x47cf9989, 0x0bb1d10d, 0xa670c1a9, 0x67a618e1, - 0xed31da1b, 0xd30b786c, 0x594ae9fe, 0xebceda8e, 0xc0d7e27e, 0x3f0f101e, - 0xc00f3447, 0x5c75d51d, 0x12a21c17, 0x82802eb3, 0xd36fff06, 0xdaf0bcd8, - 0x086bc46c, 0x67d54de6, 0xe0367878, 0x9e000a5b, 0xc2223887, 0x77867cd2, - 0x01d03fc0, 0x3c8e8bca, 0x5cf102b7, 0x9e02c64d, 0x0ca4c937, 0x13e03cf4, - 0x827d89d6, 0x03800eed, 0xfe69f3f2, 0xc1fa8ffa, 0xf78659fb, 0x9e29978c, - 0x4b494e00, 0x8eadc664, 0x913b95f2, 0x27d7120b, 0xf9927abd, 0xbdf6bdd9, - 0xcf00eff6, 0xac894696, 0x68a6bc85, 0xf7b7114a, 0x15824a41, 0xdcdfc1d3, - 0x28fd3e56, 0xe2b90bd8, 0x5a648757, 0x3a5eb43e, 0x4f2311d9, 0xfd746559, - 0xb0c276a4, 0xecf2e6e5, 0x074f3990, 0xb7347f40, 0xc43e5cc5, 0x87aef5c6, - 0xad1e4078, 0xe8b65af3, 0xd3fd7157, 0xea240d55, 0x02f26396, 0x1791a7c3, - 0x423b13bc, 0x46cb7e74, 0x4c038c11, 0xb3f5b1b7, 0x7ca3be15, 0xd74f2f71, - 0x5231fa5b, 0x46dba269, 0x193d30c6, 0xddba7d6f, 0x46ce3c56, 0x4db06bfb, - 0x72a3671e, 0x042292e4, 0x5b9777ec, 0x93f9e3d1, 0x8e126dd3, 0xebb5209f, - 0xfbab8522, 0x4adfe23a, 0xee4cbef1, 0x2c7c828e, 0x21fcd62b, 0x30fe4750, - 0xd51263ca, 0x15f66261, 0x700253c1, 0x6c4a7850, 0xfb044e38, 0x0738a6e9, - 0xcc997dfb, 0x4a365dfa, 0xf6376823, 0x3655e703, 0xd80ce119, 0x34fd0904, - 0x1555974e, 0xa34df739, 0x9f554ed9, 0x2667fd05, 0x78c16705, 0x7e6fb946, - 0x1963fa29, 0x2bf4ccc3, 0x0167d477, 0x2206547f, 0x4e7f80d3, 0x926c5f7b, - 0x36b7bce9, 0xf144bf10, 0x702b9eff, 0x7357f41b, 0xb008fd7b, 0x5e06df7f, - 0x3b2a0098, 0xa5ac7a80, 0xa25fa564, 0x148972e5, 0xca3f2995, 0x25bf0f13, - 0x2a1a4017, 0x938b3886, 0x477d33d4, 0x35224bf5, 0xf5231cbd, 0xa27e218f, - 0x72d03c80, 0x60256f55, 0xdba8380f, 0xef863270, 0x1e734c94, 0x7cd8fa6c, - 0x72e37a7f, 0x27e79829, 0x09fe0387, 0x49dde9da, 0x26927fcc, 0xde000bfa, - 0xa6ffaf7b, 0xc4fcf006, 0x67f93366, 0x5a4d7f56, 0x79696ffe, 0xfee26810, - 0xd5fcb4b6, 0x80f1bcb4, 0x979c5697, 0x9432ca63, 0x24f0050b, 0xbf07f932, - 0xe41d67be, 0xcf5bf878, 0x572f58db, 0xf835bc37, 0xa720e1c3, 0xa43f831d, - 0x052d59c4, 0x3e42ff91, 0x1c28b5f0, 0x098f9992, 0x62134f78, 0x18176e52, - 0x5a9c9bf6, 0xdc947488, 0x988ea9d2, 0x8fc0ddf5, 0xc1ddfcb2, 0xf4878e1f, - 0x78ad4c6d, 0x0120a455, 0xd768d03f, 0xe018b713, 0xe234effa, 0x1fc479a9, - 0xa47338a5, 0x7a6a78b0, 0xf30a285e, 0x09fd5272, 0x233dd3eb, 0xf0c56b5f, - 0x3b0fc581, 0x3f20ad94, 0x61b68cb4, 0x7865b35c, 0xf90290e4, 0xd1406a0c, - 0x5dca677a, 0x4c6d8821, 0xe37c63cd, 0xd4f5b3f4, 0x7e8c3c35, 0xbdbfa198, - 0xad5e1f1c, 0x67b3f51c, 0x31ded9a2, 0x2b2701d6, 0xdb36f4a2, 0xa694ce51, - 0xbe82c54f, 0x9b539a7e, 0x69e51a76, 0x233fb9a4, 0xe36ed1de, 0xc96b8bf1, - 0x593768b5, 0xe1fd12e2, 0x71f86bcd, 0xdcbcd913, 0xfc1849d3, 0x5189f4e6, - 0xcfd79bc4, 0x9bd866f0, 0x9bbf3e1e, 0xfc04234a, 0xf3f89ebe, 0xeb6f0ccd, - 0x7fa28baf, 0x29ec7eb7, 0x85bd67b4, 0xce3f261d, 0xa1ca1ef8, 0x76c4fcfe, - 0x18f6a1a8, 0x23711bcb, 0x19e9a78a, 0x61ebbd69, 0xaddbb72b, 0x92275374, - 0x4763d062, 0x8315a747, 0x84b7bede, 0x3cab4ec2, 0x6297587a, 0x7ef2adf0, - 0xdf867cd4, 0x7cd8cb7b, 0xd3f47b69, 0x93989def, 0xf266e304, 0x7f11b0f8, - 0xebcbf1ee, 0x284f78cd, 0x2d85c4b4, 0x67eab77e, 0xcc4b52f4, 0x5f39abe5, - 0x57a7222b, 0xe8ce192a, 0x4f3e3035, 0x84bcf832, 0xdf3279f1, 0xd12f4837, - 0x921d010e, 0x4dff994a, 0x4df37e2c, 0x5e8c1d29, 0x00c88f37, 0xa9fefc3f, - 0x97663edd, 0x7126ba30, 0xc6efbc7e, 0x71c80211, 0x40268972, 0xc33e727d, - 0x13c53253, 0xa5c977ac, 0x4ef6efcc, 0x525db0d4, 0x0b5ba309, 0x5fe14c7c, - 0x898a7403, 0x5b4b3b1f, 0x6b7fa075, 0x741d4ef1, 0xe1c53259, 0xd4cf0a20, - 0xd81b0a52, 0x805fb49d, 0xc51853d7, 0x49525ab8, 0xfca5d870, 0x82a2427a, - 0x10f887cd, 0xe94b686c, 0x7e58253c, 0x20b26268, 0xa7ef7ed0, 0x80f1c07c, - 0x8f173c71, 0x785fdfa3, 0xfddcf512, 0xc8364df0, 0x1cebf6a9, 0x36a5279a, - 0xf707f83f, 0xf108e697, 0xbcc6e7e2, 0x2acb83fb, 0x35f812c7, 0x9572fc31, - 0x16dee3c8, 0x22475dfe, 0x57c82e6a, 0xa5f76f48, 0x830feaf5, 0x65e47aff, - 0xfecbe312, 0x87a189f4, 0xb21824dd, 0x1fd5f765, 0xdef8ce92, 0x7940179e, - 0x24ef03eb, 0x8a52afc6, 0x9136fcb9, 0x5e867fdb, 0x140792d1, 0x00a12727, - 0xd72277ae, 0x02da4f4f, 0xf054c50b, 0x4eb8c3bb, 0xae74c8b8, 0xca9f1937, - 0xe6a6ff9c, 0x4ae2bd33, 0x9776b089, 0x903aa78d, 0xa834d6df, 0xc65a1fa8, - 0x439ed5de, 0x7866b0f1, 0x73be1f93, 0xb9196b8c, 0x3cdbf68d, 0x2b70797c, - 0x30fdc00c, 0xac22bfd4, 0x8d5f8c83, 0x0e03307d, 0x61d21992, 0x7e09cc9f, - 0x2467e011, 0x24905fdb, 0xeb8fb512, 0x4795df1d, 0x6967cde1, 0x0dc19f28, - 0xb6ebc9fe, 0x6f9c2ae0, 0xa2946b7e, 0xc99bce9b, 0x42216acb, 0xebcc225c, - 0xb21e7c72, 0x9f8ebe31, 0x025df7f6, 0xe1c4d3ec, 0xdb22dddf, 0x472d59a7, - 0x7e085088, 0xf289ed1b, 0x6a6ceac9, 0xa381c797, 0xd56bf391, 0xc3f8672e, - 0x89ab7e18, 0x75f29924, 0x1fc233fb, 0x7711fac6, 0x514fb80a, 0x4358d1cd, - 0xcf00b23a, 0xf61a29ef, 0x48eb6b57, 0xe9177c83, 0x78025b4e, 0x8b8f0310, - 0x5277fd74, 0x90b8c4be, 0xd6eb607b, 0x81a7f0e5, 0x4085d10c, 0x0fa9e4cb, - 0x178e9879, 0x69e307dc, 0xd2bf2b2a, 0xf5f0e371, 0x4d7cb10b, 0x6a5957c4, - 0x147f6be5, 0x129ddaf9, 0x9fb77ac5, 0x8fc1b5f1, 0xad1f9c89, 0xbf8c687c, - 0xd6afc79e, 0x335f3e72, 0x708549a1, 0x9b51dadf, 0x2ce69e30, 0x7c015cda, - 0x25aa32de, 0x64de7c0c, 0x17df35f0, 0xdb2efea1, 0xa35ad31f, 0x72264eb0, - 0xeed456be, 0xeb7b9006, 0x38935d7c, 0xbe0534bc, 0x5f39b806, 0x93f807bf, - 0xae08ddfd, 0x076bd7c1, 0x45bad7cc, 0xfed39b6f, 0xc2d927fc, 0xf1891ed7, - 0xd7c067e7, 0xb30a4f00, 0x963edc63, 0xdfea7eca, 0x06e7e9c7, 0x6b99f989, - 0xe5ac1cb9, 0x1fb6b072, 0x223ff839, 0x9afe03f3, 0xc98b3072, 0xe5a24381, - 0x8cae9389, 0xd3b0251f, 0x9e7bc8e3, 0xe1b5fc24, 0xbc4334de, 0x27fe3c72, - 0xbe84cd30, 0xcfd234f4, 0xe4c0e744, 0x73c98f3b, 0x76be727f, 0xfe387c68, - 0xa7f46453, 0x26922ef8, 0xffbe395c, 0x7215705a, 0x43f0367e, 0xb728c582, - 0x3a667a31, 0x86a92bc0, 0xd304799e, 0x28ad79a9, 0x81be86a7, 0x2bfa0a58, - 0x3bc62b6a, 0x68ad999c, 0x98f3399f, 0x24fc31be, 0xb88d7ceb, 0x33d71378, - 0x02217949, 0x853d9feb, 0x9eaa3f70, 0xcc9951f9, 0xd5e2301f, 0x18a8fd86, - 0xbbd0d47e, 0x79a79f70, 0x97da3d78, 0x3bd637cd, 0x36c3ede2, 0xf077eefb, - 0x3ed35f4d, 0x0e5a1aeb, 0xbbc9aefd, 0xc3b3c49f, 0xfb18798c, 0x6e3e4e46, - 0xa8b51e73, 0x32df5c60, 0xc76adefc, 0xfeb26734, 0x7ae7be7a, 0xbbd1ee57, - 0x54768f2c, 0x6f9f8c6e, 0x03e0c7e9, 0xa343e885, 0xe4183710, 0x4ce7091e, - 0x3f04849a, 0x924dc7d8, 0x90729d20, 0x5aa97b1e, 0xff401689, 0x9cbc6627, - 0x3db2f685, 0xbce406b8, 0x0380abe9, 0x53aba9e2, 0x96c6f35e, 0xe6f19d9f, - 0xa56cc1b7, 0x7ee2d5df, 0xb148838e, 0xdc2763fb, 0x4b7ed1db, 0xe9c737c8, - 0x09ae149c, 0xcc13c402, 0xbf8f0ae5, 0x72e69928, 0xa45fc799, 0xe7394b14, - 0xbe34b90f, 0xeb93795e, 0x7602df15, 0x1cc4e74e, 0x713bd716, 0x30674f2b, - 0xdbc73efe, 0xc234f375, 0x535feef5, 0xf6e5251f, 0xe29befc2, 0x9922f8c7, - 0x3ebb4765, 0x2b9d852b, 0x26e7b120, 0xa26b5fe0, 0xccfc6244, 0xff9781a1, - 0x61d4f108, 0x06cabe0b, 0xea156b3c, 0xdb465861, 0xc79c6ca5, 0x28f74263, - 0x3ae6cf18, 0x02f5fb8b, 0x6a72e345, 0xdbf40b12, 0xef8521db, 0x3a52c0bd, - 0x91057b8f, 0x37c0ecbf, 0x8c29d022, 0xb1448ba9, 0x303a43de, 0xe61b089f, - 0x5187e0b9, 0x33c44bbf, 0xc61b614c, 0xf6cc7e8d, 0x7888d643, 0x03a8836e, - 0xedc9bfb4, 0x4297f82a, 0x1ae77e88, 0x40be77f8, 0xc4c8316b, 0xc608b2e0, - 0x7cedad93, 0xa039d853, 0xaffb7a3e, 0x5237df4f, 0x548f8173, 0x1ce8372c, - 0x694ef514, 0x5ff2df42, 0x12f38189, 0xdc58abc6, 0x2a5f5acd, 0xde4017e9, - 0x0bc2e5ac, 0x7e053a7f, 0x6467aaf4, 0x3ca7a3f4, 0x41bf4723, 0x045b35f3, - 0x076d53f4, 0x770fe89d, 0x51f2c23e, 0xfb43a28f, 0x8c05db73, 0xdbd9d507, - 0xe201bdef, 0x0488cf8a, 0x19708dfd, 0xe29d8bee, 0x59fb2673, 0x80079cbe, - 0x9a1cb66a, 0xec57df0b, 0x77d813b7, 0xf16e79a8, 0xf9a06fb7, 0xf464c7c5, - 0xac766a51, 0x657f6050, 0x40885849, 0xc1326bbe, 0xc4fb43f1, 0xbeda0ef0, - 0x369edbcb, 0x2bfb0dc7, 0x455da20e, 0xa7b4f6e1, 0xa9f4a6cd, 0x0d353f0c, - 0x2ddcabbe, 0x98ffc1f8, 0xa38eccf2, 0x9abbf419, 0xa73c0427, 0x45cbb550, - 0x9cba18b4, 0xdfa3136a, 0x9d33f880, 0x8bc5f827, 0xc034eb49, 0x0d8ecd7b, - 0xb713168a, 0x9230d33c, 0x7cdef668, 0x1c7413cd, 0x93ed5dfa, 0x58a61f82, - 0xe041236b, 0x9ce7ce8f, 0x30dcdb65, 0x08ca15bf, 0x59abcc0f, 0xc38b7681, - 0x7ec1f6f3, 0x8b78657a, 0x57d68d32, 0x2945b23e, 0xaaa7e18f, 0x2d10d75d, - 0x6d4e3f86, 0xd4bf4dce, 0xae867b7a, 0x54f0b15b, 0x88b7a612, 0xc4665614, - 0xc8767bec, 0x453f9c49, 0xdf06ff53, 0x18275e87, 0xef3d0ac7, 0x741abc41, - 0xbd32a65b, 0xbcedd060, 0x7528e9ca, 0xb388cd17, 0xd02f7aaf, 0x2af10ec1, - 0x1bfbd315, 0x6c6e987c, 0x9b3e90d0, 0xe1577f00, 0x7b9606be, 0x88629127, - 0xa275788b, 0x3c9f52c2, 0x21962f5d, 0xf960124e, 0x8283dbb4, 0x1bf98976, - 0x383926e9, 0xb75c820f, 0x964c4fc9, 0x49bebae8, 0x7e252e09, 0x77b4be3a, - 0x6075c972, 0xc8e705a7, 0x1d9fb0a9, 0xe8f160ac, 0xa2e40f88, 0x7ccbef89, - 0xd6f2664b, 0x7c60a194, 0x8bf7d364, 0x41eda1b6, 0x7d365e18, 0xec277cbf, - 0xe67ed1ab, 0x1aae54ca, 0xee4fda65, 0x9b49fbe5, 0x4fd4d13b, 0xa30adcda, - 0x8fd8c59f, 0x6cfd6073, 0x19bd7b9a, 0x4695b99e, 0x8fd8f53f, 0x4af36067, - 0x199263bb, 0xb1aa3b9e, 0xfddbf49f, 0x06881f68, 0xdc7690ff, 0x4eef7517, - 0xc496b71a, 0x1fe4d1f2, 0x2a1e78c3, 0x947cb155, 0x24c13138, 0xb27a494f, - 0x74a83f29, 0x6a7da9b0, 0x9f54c720, 0x85b5765e, 0xbfa8dd2f, 0x8a814f31, - 0xab38b126, 0xbd415832, 0x81d83c53, 0xbb06bbf9, 0x75dcef51, 0xb02af07d, - 0xd05600f7, 0xc12977f3, 0xbe1c6a31, 0x0812f3a1, 0x1b34cfc6, 0x32ec7da4, - 0x7939efbe, 0xde2357c8, 0xd9d7dfa7, 0xd12447ba, 0xf14a43fc, 0xadef3023, - 0x8de3b332, 0x9d824338, 0xce6bfea0, 0x8a16da2e, 0x50cb6bc1, 0x6f422fca, - 0xd0722dbf, 0x73b8fc07, 0x4a576ff5, 0xa1a6be14, 0x7a6e1e0a, 0xe1edfe5c, - 0x9b99b510, 0x00fb9687, 0xea8576ff, 0x15f1d88f, 0x8e3e7e3a, 0xdfc61bbf, - 0xd93b332b, 0x673dbe3a, 0x477c69a2, 0x7c698556, 0xa7c74287, 0xf56fb1f2, - 0x8a7c7c3b, 0x7909ebbf, 0xc7077e56, 0xe05567b7, 0xa90acdf8, 0xd09f8d30, - 0x9001fe33, 0xcdfdc39f, 0xf37ae73f, 0xcd2ab3fc, 0xfcd857f3, 0x80feae8f, - 0xf3809f8f, 0x80fe597f, 0x92ab3fcd, 0xfacedfcd, 0xdbdf19ed, 0x6157ff83, - 0x37f5affe, 0xe649dcff, 0x36ab0ff9, 0xc6cedfcf, 0x27f5637f, 0x8e377c7c, - 0x09fca6ff, 0x6ab0ff9b, 0x07b15f1c, 0xca47c0fd, 0xf07a8490, 0xa461a99f, - 0xa35d4061, 0x923a40e3, 0xc837a9c5, 0x5dc70839, 0x3eef8c09, 0xe6fca04f, - 0x24a7d5ee, 0xea90254c, 0xd3ce5acb, 0x158bbb55, 0xd0842fe6, 0x41c4585f, - 0xc45fb85d, 0xb46c8cf5, 0x78538787, 0x218bf73b, 0x78dc2fc8, 0xac5b9e23, - 0x77dc13b3, 0xfa3056a7, 0xc0f1ff1f, 0xf3b1ade8, 0x5a8ba6b2, 0x13fecb65, - 0xef38c783, 0xa6ab2454, 0xa78829fc, 0x127c3d50, 0x9e9a1ffc, 0xb478e996, - 0x83f043fc, 0x1b958aae, 0x768c2e76, 0xce9f2277, 0xfe1cbbeb, 0xf7c31253, - 0xdc053ba9, 0xc37cf847, 0xd9f40552, 0xc99756a2, 0x74e3a86f, 0x8ece7eea, - 0x79c68dfb, 0x14505bbe, 0xc1fdf909, 0xbb051d6f, 0x41e6f171, 0x276eefa6, - 0x1470d5e1, 0x79fac173, 0xff3a5543, 0xe3eccadb, 0xeb6b8c44, 0x9c1c5843, - 0x49b8810c, 0x7906db59, 0x52dccd08, 0xf9ec9b26, 0xfce6835b, 0x7ce6156d, - 0x6d961ca7, 0x112ccf60, 0xefda16c8, 0xcb65ebf7, 0x8e3600b9, 0x76e64957, - 0xbbef1b25, 0xb4198694, 0x8e90fbe8, 0xe9156283, 0xdf65573a, 0xddd4f01a, - 0xae28932d, 0xb8a91dc7, 0x454a140f, 0xb2a82dbf, 0x9de15b79, 0x00f43b2b, - 0x8fee6785, 0x15a7c444, 0x2e838efe, 0xf3ed46dd, 0x907fcd8e, 0x9d6c7e21, - 0x3bfe158f, 0xa3e75b96, 0xcc3eb02a, 0x19cb590b, 0xa9f9589f, 0x36f17f6e, - 0xf37b3db3, 0xb5fb58b6, 0x530cd76a, 0x56f8497e, 0x9bc5fb53, 0x17ea99e7, - 0xd5312eb5, 0x6a59682f, 0xfd0bcfca, 0x8efed4c8, 0xf54c2be5, 0x635fafdf, - 0x62adbfaa, 0x6b7f2983, 0xfb5321f0, 0x98b6ca5b, 0x47076dea, 0x68e4077d, - 0x9e22ebd5, 0x3ee0bdfd, 0x9bd82f75, 0xee12dc17, 0xed447e73, 0x33839015, - 0xb4815ed4, 0xf478ff73, 0x2c1ea9a7, 0xf9a24d87, 0x2d5598ca, 0x0997a099, - 0x6572cfea, 0x24d0aac2, 0xd7b0178a, 0x9b887ca9, 0x041d1215, 0x0f724cce, - 0x318b771f, 0xa9971df5, 0x7d054cdf, 0xb17adf7c, 0xdd797e23, 0xd4c379d6, - 0xaf6a7e38, 0xb02192dc, 0xce5975ce, 0xb569189f, 0xb1a73ce5, 0xeb817dbf, - 0xe9856ad9, 0x19bdea83, 0x86736193, 0xe223e5fa, 0xf9ec9b9d, 0x0db0223e, - 0x53feb048, 0x98861f81, 0x76aa6bf6, 0xfbe49ae5, 0xe11121ec, 0x409d05aa, - 0x5217eaf5, 0x72028d60, 0x35923d16, 0xa1c0346b, 0xef4055af, 0x75c54fec, - 0xe9436cfd, 0x3fafd836, 0xf4c010d3, 0x4c3286a3, 0x3104354f, 0x02a1b0fd, - 0xf50d93d3, 0x2c347698, 0x86bdf4c7, 0x36efa610, 0xbbfa60b4, 0xdf4c5686, - 0xe98cd86a, 0x4c610d1b, 0x4c741b3b, 0xd1e8790d, 0x0f6e01bf, 0x84d71b1b, - 0x2e7cc3db, 0xe73da98d, 0xf7ff70c2, 0x11f3fbbc, 0x7f9fef60, 0x6cfb8ecb, - 0xcacbe1fd, 0x51d3fd6f, 0x3ca57b47, 0x639d083c, 0x8133bd6b, 0x2369c9d1, - 0xec1c64a5, 0xcff4ecff, 0xc4bcc7cf, 0xfd84f52e, 0xfa713c33, 0xfa5d7885, - 0xf444e9e5, 0x949982ee, 0xfe1ea71e, 0xf7e822af, 0x607fac02, 0x71111c07, - 0x6dd1261d, 0x95d7a07e, 0xe1784de2, 0x2f1059f7, 0xbf83d73b, 0x8b882cf6, - 0xd8a8ab5d, 0x3b36f9ff, 0xf9d2f881, 0xcfbc2e03, 0x36d8fe75, 0x32e3c82f, - 0x3d8e189f, 0x6b4d6147, 0xb761d922, 0xe736efc9, 0xa50ab7cf, 0x689a1e78, - 0x0347b389, 0x3861a95f, 0xe0d9d20f, 0x67e8d4c3, 0x71c14f99, 0x65caecce, - 0x5e7e3371, 0x424eec83, 0x277ea57e, 0x869fffb6, 0x0c7ebfa7, 0x23690878, - 0x5e08381f, 0xdb98bb71, 0xf97efb7f, 0x814cfa49, 0x20392af8, 0x82f60e7f, - 0x1177fe9d, 0x6122651c, 0x2eb7e8de, 0x63ec8622, 0x69b77ca0, 0x669dfa3c, - 0x7317f4f8, 0xe6b7c52e, 0x042234fb, 0x9c46bf68, 0x80fe0aa4, 0x02f530f3, - 0x788cabc6, 0x6ee49749, 0xc6f4c611, 0xbc78ea4b, 0xa1d1c6b8, 0xb9d16904, - 0xee4bdcb6, 0x38699e9f, 0xaf39c2a6, 0x02ab470a, 0x64454fce, 0xb9e80954, - 0xd2ab6d73, 0x12ac1ec0, 0x2f15dfcf, 0x67679b7e, 0x6125bd71, 0x8ebcdbb9, - 0xb420fe72, 0x1d9ca35f, 0x8a9f7472, 0x31b59fc9, 0xefdadb3b, 0xf6c0fb04, - 0x1f776a2d, 0xd683769f, 0xfbb54f17, 0x3e30553f, 0x5c53112e, 0x7bdfc0c9, - 0x9d82604a, 0xd772a9e2, 0x7e8f68fb, 0xdc468724, 0xd4fd097d, 0x9f6e7e77, - 0x88727ce9, 0xf338c3b4, 0x8881f227, 0x743bcb76, 0x15f8fd3d, 0xe4db9d99, - 0xf67b80e7, 0xfebef995, 0xdf9b9e02, 0x84e78556, 0x8ff7de3e, 0x242dff68, - 0x81d22f01, 0x1d8116b4, 0x4ad88e79, 0xc8e74f01, 0x31f1de6b, 0x3a95b874, - 0x05ef404a, 0x863b662d, 0xfca6bfda, 0x7ce6cde2, 0x06999939, 0xa37ca4fa, - 0xce02c24c, 0xb37f54cf, 0x177ec55d, 0x5826fa93, 0x8fee2557, 0x348957cc, - 0x9ad5ea84, 0x34567f67, 0xb411c28f, 0x88c83f33, 0x66492cbf, 0x4a656076, - 0xc27d8158, 0x7fc6da0f, 0x832006f7, 0x7104dc3d, 0xfc489228, 0xfc5f483b, - 0x56fc295e, 0xbaf58d78, 0xc3881c4f, 0xe212ee21, 0xdad603ee, 0x86cf6e05, - 0xe7c03d30, 0xc705f86d, 0x7615f92c, 0x2452de7e, 0x9cfdd022, 0x12d908ea, - 0x851fdeb1, 0xbb5edc78, 0x7106957f, 0x7b6ac0fc, 0xdfdc6f6a, 0x0f649768, - 0xe159f962, 0xf73c72d5, 0xf00b4520, 0xef8f21de, 0xc41f9c2b, 0x9c016f04, - 0xdc40f523, 0x3a75ce1e, 0xdf215bbd, 0xf3c0a9e4, 0xef20751f, 0xbc7bbfb4, - 0x9c418ed3, 0xa35a41da, 0xbb5fe53a, 0xa01fb2cf, 0x902ef399, 0x5067d04b, - 0x09a2e780, 0x235cb9c6, 0x7e3cedcd, 0x2e31fe73, 0x4381748f, 0xdf39ee3e, - 0xe14770e6, 0x2899093c, 0xb7f1ed9d, 0x63dfc072, 0x56fdc3f0, 0xcaa77f68, - 0x7df2d7da, 0x9edf3bdd, 0x097c9e9c, 0xa5f7547d, 0xeb31c240, 0xadd49d48, - 0x7dd61f00, 0xd7f96129, 0x5d1a9bd6, 0xe6f46355, 0x59f04a2b, 0x27a604fb, - 0x8e813e01, 0x64dfbb13, 0x027087bd, 0x2f4261f8, 0x386d7c3f, 0x7f498852, - 0x8f04a7bf, 0x6be383c5, 0xd3ebeff7, 0xbbe009ff, 0xf3feb1ff, 0x11dff4fa, - 0x679afe0f, 0xd10becf7, 0x17f2b5f5, 0x10e1780f, 0x6b52c7d3, 0xacef9c1a, - 0x0bdab1de, 0x1491f972, 0x3f5d02f2, 0xef718b0e, 0x0c3ba6e7, 0x70ddd3be, - 0xf396b08f, 0xaf9f99dd, 0x2ff836fb, 0x5590ef9f, 0xb2ec0f8c, 0x2994ed47, - 0x3096db6b, 0x7f65d8f9, 0xf19be59f, 0x7edd53bc, 0x7ca8beb3, 0x0d3481fc, - 0xb885550f, 0xff451cff, 0x7ffb76a0, 0xabbb034c, 0xdea3748e, 0xe3077eb3, - 0xf68c997f, 0xb1253cc0, 0x0e71bd6f, 0xa5e38eab, 0xde1d6dae, 0xbb6baf13, - 0x9a1334f9, 0xad3bf40e, 0xbb7055df, 0x9f30e1df, 0x42f034df, 0x5feeccc2, - 0x0583c4f5, 0xceb853ef, 0x2bc57f6e, 0x29f2c7e4, 0x23e77fd3, 0xa5fb1e0b, - 0x755cbfd6, 0x6b18fd52, 0xb4eb1b5f, 0x2bfb9fb6, 0x2d5a5807, 0x0fe0bd47, - 0xf1916f56, 0x9ef57bbc, 0x861f3b6d, 0x76dbccf8, 0x7fda70ff, 0xde979ed5, - 0xabe69eb8, 0xa653929e, 0xe1b869b3, 0x9f41a29e, 0xf2dffa3a, 0xa8f4bd71, - 0x4525fa7c, 0x7fcacd1b, 0x974bdc9c, 0x290ea7aa, 0x7c5f7464, 0x521c894c, - 0x85b67ed8, 0xa7f7913e, 0xeab15f81, 0xd0142f89, 0x141f1f5f, 0x1c767a48, - 0x09796e7c, 0x13c063ed, 0xabd393d2, 0xf6967e87, 0xa82e9475, 0xb2f42d17, - 0xaf98fbb6, 0xc42fd007, 0x3f7f29e3, 0xb7d84bf9, 0x0fdd9df9, 0xf278a878, - 0x9f30bc9f, 0xe33d52d3, 0x4ead9ff3, 0x1520fb83, 0xc54d2872, 0x3c579594, - 0xbfe403fa, 0x907fc7c5, 0xeac5cec6, 0x575cfc19, 0xd173cc06, 0x9e707323, - 0x7c8824e5, 0x7633f158, 0x4482fccf, 0x238a9f4a, 0xd839f727, 0xab7a763a, - 0x4f11371d, 0xfb0242c3, 0xe189af18, 0x640f181d, 0x607f0de7, 0x65913fec, - 0x60e0bf98, 0x30e45af4, 0xa5d1f1ee, 0xb77f9624, 0x9d03b737, 0xd3d50cce, - 0x475c8e21, 0x87c710a4, 0x2bf69170, 0xce9a9f1e, 0x52681dcf, 0xea8eff11, - 0x0e5029ff, 0xdd65dbed, 0x8efa6059, 0x1deecc5c, 0x3e3e4eff, 0xec013b85, - 0xd469d3d7, 0xbf338c1e, 0x9d630e03, 0x0c5676a6, 0x3bc8c59f, 0x6bedff93, - 0xf21bbc98, 0x0a519e1f, 0x609d9ff5, 0x81df0472, 0x8ae142fd, 0xa1fd63a6, - 0x07ea02d9, 0x93c6893b, 0x9732edf3, 0x95bd7373, 0x12fc285f, 0x7c3dc7ac, - 0x2324e303, 0x2dbed01d, 0x8fbf48df, 0xae30abd5, 0x86bf6fb7, 0xfae62f1c, - 0x1f45ad60, 0x07524790, 0x2d5b7fb4, 0x0c3e7787, 0x35e54bf2, 0xcafc81a4, - 0x27c15ef8, 0xf1bc8fbb, 0x9fb72a3d, 0x35b90c44, 0xdcab55eb, 0x409dec56, - 0x27edc9e2, 0x2b893f6e, 0xae3cb4b7, 0x903bbadc, 0x7ad6ff9f, 0xd3e3c0d5, - 0x7a1a3c16, 0x5a7c3fb2, 0x1db7e4f5, 0x493d5c5a, 0x45209dff, 0xe0d1f97d, - 0x2aff8343, 0xcf06a5ff, 0xa9f0f50b, 0x7c3d87c1, 0x9f61f06a, 0x8f09a478, - 0xe1bbfad6, 0xc0853a6f, 0xcfc63273, 0xfdb00fab, 0xd1ddfa67, 0x2f888521, - 0xd239971d, 0x4a48747a, 0xc96c3e6c, 0x75ed2c47, 0x69603e4b, 0xebe4b41f, - 0xf7abed4d, 0xb9d8511f, 0x9da9a89e, 0xe4a7fcb8, 0x01f13883, 0x6baa1d63, - 0x010954fb, 0xf1bbb87f, 0x0925797b, 0xfe5e2079, 0xf2f188bc, 0x26e38a2e, - 0xeed74e3a, 0x608f7c6c, 0x57c593b5, 0x2f6ed4ba, 0x93ab93d8, 0x553bbe58, - 0x683d0269, 0x593b7794, 0xd02bafdc, 0xb18a4ded, 0x203fdeef, 0x08ef1ea2, - 0x7e78d293, 0xa140de28, 0xfd20edf8, 0x80fdb3d5, 0x61d7b02e, 0x30ac84bc, - 0xd154e3f0, 0xe21cb59d, 0xde22ad35, 0xe2b85b6b, 0x239c2f16, 0xfb903ae9, - 0xbe5a329d, 0xdb22d7e8, 0x52e90ca6, 0xf81f8c46, 0x9a6d0911, 0xf5fec024, - 0x059fe47a, 0xb85f9807, 0x797c7d70, 0x95dfe4a8, 0x4054efbb, 0xee7f52ef, - 0x87beec64, 0x23c54fd1, 0xff03f296, 0x15a6e5c8, 0xdb951fe3, 0x1e41f5cd, - 0xe4ec183f, 0x92c7bee7, 0xb77fdcb1, 0x9e0fdec5, 0xa77fe62a, 0xeba7d28c, - 0x3ce04898, 0x2203f9c1, 0x6efce7d2, 0xe3007e76, 0xbf01d7fc, 0xe7b12b77, - 0x7c82cea9, 0x1ebfd55d, 0xefccfb3b, 0x3e06ee8b, 0xc14ef7da, 0x767a694f, - 0x7e23dbdf, 0xdf67f905, 0xf4877acc, 0xa0e53f6d, 0xba55f713, 0xff907a0e, - 0x4dff9ebb, 0x7f90ddd6, 0xecf18ece, 0x145f83ae, 0xad753f00, 0x1e8057b4, - 0xefe7e2ec, 0x45ff3d56, 0xbfae0741, 0xa9c7488d, 0x9f4fe64e, 0xef5ff03f, - 0xf381fdc1, 0xc0ace807, 0x42e838be, 0xa5fbaaf9, 0x5d6fe313, 0x14517fcf, - 0xa5fc27eb, 0xfbe5a9f3, 0x521e5d9d, 0x4be017b6, 0x7544fb62, 0x1b6ebabf, - 0xd3512fbc, 0x40594876, 0xf0bca7eb, 0xafd002a7, 0xdd997b5d, 0x3c7729d4, - 0x8179fb0a, 0xca340f35, 0x209d5e94, 0xff698364, 0x0128de6b, 0x978bea39, - 0x715c613f, 0xfc58f8a0, 0x043e0d7f, 0x4f3fe99d, 0x29854c18, 0xdef8ff07, - 0x0e27a03b, 0x8d2f91da, 0x59127ef9, 0xe5ccf681, 0xfff4dde6, 0xe885bcdc, - 0x03bde640, 0xefe13de6, 0xc0d7de77, 0xbed4a1a1, 0xcf97d072, 0xf30bbf9f, - 0x847e3c7b, 0xfefc8077, 0xfcf9dfd2, 0x7bee98af, 0x97bddd29, 0x7f87f79f, - 0x9feef3e7, 0xcb9ebfee, 0x79c2aee9, 0xfe17ba98, 0xa95df084, 0xfe12939e, - 0xbfbde5be, 0xfef61bf9, 0x35bf9b5a, 0x93cf1b27, 0x70b0c03a, 0x40b6667b, - 0xc8ed7178, 0x9dd82a99, 0xd5ef3f62, 0x7e60484c, 0xf7b02895, 0x1650c821, - 0xcfdc240f, 0xf80d6382, 0xdd9b880e, 0x4ddc933b, 0xc9137768, 0xbc53aedf, - 0xbe7abdac, 0x911acf1f, 0x21056f71, 0x8fc9399f, 0xbf8b6ef1, 0x5d1028d9, - 0x74aef6a0, 0x818f37f5, 0xb48f23df, 0x9805ed45, 0x33690fbe, 0xaaca638f, - 0xdc87f262, 0x53bce6f9, 0xbcede733, 0xf061073f, 0x0c247c3b, 0xd4716cf1, - 0xd3ce1561, 0x02256389, 0x4938a54f, 0x0efc086b, 0x7dfccfbb, 0x7ee10252, - 0xc7865fef, 0xa716048a, 0xed718512, 0x9471e03a, 0x78dce30d, 0xe2f11b48, - 0x08baf7c7, 0xf17baff7, 0xf80ed4da, 0x663fc094, 0xd5fa17f6, 0x12d3fb84, - 0x691a42ef, 0x76e69dd3, 0x2cbe8fdc, 0xb25d189d, 0x969d39aa, 0xd062e899, - 0x4c7d0e21, 0x7cf03174, 0xd2b1f4a5, 0xebff8ac5, 0xf75f1813, 0x2e832f47, - 0xef1d6e99, 0x7fdcc9d7, 0x133f0128, 0x820199f2, 0x7fdcabfb, 0xbc745290, - 0x7eaa24a7, 0x7e0097bc, 0xe01a945c, 0x86deef2f, 0x3f73a4f1, 0x00dbff7f, - 0x44afd54f, 0xebf8a0e2, 0x5121eddc, 0x2b0a5ef8, 0xb6569fe0, 0x404fb889, - 0xacd168a4, 0xc3627d98, 0x85faa80f, 0xb953e707, 0x4e9e1ed7, 0xf7dcafbf, - 0x61da0141, 0xcfd1bb2b, 0x605cfd09, 0x14750f74, 0xa5703ec0, 0x2b11fcc4, - 0x6049acbf, 0xcfb396f1, 0xae20cab9, 0xe762ec23, 0xb7232b7f, 0x7398f6c8, - 0x9904a14d, 0x739e9bc5, 0x3d085ea1, 0x28f9e021, 0xdcf62f80, 0x9c87e1a9, - 0xf060427d, 0x9df197ed, 0x4f5dca98, 0xaa7c4275, 0x1fbb2df2, 0x5dbaf8cc, - 0xc87ee29f, 0xf1ec5f94, 0x2e1fa076, 0x7d12e29a, 0x44bb01e2, 0xb6da8fe4, - 0x6843f41a, 0x36a2f91e, 0x2beffdc2, 0x7eab57f4, 0xb83efcf1, 0xf4f55670, - 0x7f885ee3, 0xe1df699d, 0xaec0b8c5, 0xfae7c74b, 0x3591fff8, 0xd6ffffdc, - 0x3b4f7669, 0x067fffbe, 0xf176a0fe, 0xfb9609d3, 0xb106bbab, 0xb44914f7, - 0x71ef52e8, 0xf0b9ed55, 0xcfafc428, 0x51e4fdee, 0xcffabb80, 0xfc14787f, - 0xa9d0720a, 0xba827dc2, 0xf18ebf9f, 0xdfbbe33e, 0xf9d03d70, 0x2f18e3c4, - 0xfa9b7ced, 0xe75ff41f, 0xc0b3a7f3, 0xea7ceccf, 0x4f10698f, 0xa9f9f3b9, - 0x9dce6ef8, 0x27494ccf, 0x9189f471, 0x0786ff02, 0xd2b5af10, 0x11db48ed, - 0x51ce7ff4, 0xd9ff83ba, 0xd489d713, 0xc69978b0, 0xe3bb39e3, 0xc4fbc7c7, - 0x7d66da6f, 0x4842c6e7, 0x0646bf65, 0x4139c710, 0x006639e9, 0xe3cddc74, - 0x5d6f9175, 0x0e738e32, 0x3af4a0fe, 0x85e3a16b, 0x3d8f45b6, 0x836d750c, - 0x44e38dfa, 0x233f8007, 0x413fbefe, 0xe40122ff, 0x60bfef68, 0x37e80cfc, - 0x73b84e9d, 0xd82c85cf, 0xee48f8bf, 0x85ef8b9e, 0x21576f3c, 0xfcf9511e, - 0x9d4f289b, 0xf8c71ccf, 0xf071e136, 0x8ff3d24e, 0x99f92bc5, 0x1eedbacc, - 0x74e1ff16, 0xe690f880, 0x071e72c5, 0xc46d7c62, 0x0b8bfa87, 0x73b1718d, - 0x40bec627, 0x7877f6cd, 0x6e97a5bc, 0xd7a044c2, 0xcfdc97fb, 0x02a0f030, - 0x8d8dae1e, 0xc38fc67b, 0x2d3dc4f5, 0x427a0374, 0xae27b3bc, 0x7b13d849, - 0xcde16175, 0xcef47178, 0xda5e2c2d, 0x8f3fc729, 0xaf41c465, 0x9fe25976, - 0x3fc581e1, 0x2b8f372f, 0x9760d3c5, 0xf15afd86, 0xf8abf675, 0xae5bfdfa, - 0xe85f9d81, 0xdaad7f77, 0x3de61f7c, 0x05dd3825, 0xef6d6bfb, 0xa7cf042b, - 0x2b73b374, 0xf967be7c, 0x3fb3d3f9, 0xd62e3117, 0xfa823914, 0x8c3faadd, - 0xbc2b57fd, 0x6b787077, 0xe3f5b3f7, 0xd84f5eec, 0x7b39fb4d, 0xebe439f8, - 0x63efddda, 0xaee8ee5c, 0x988e95a7, 0x8fd616f5, 0xce7ccc70, 0x80a8793e, - 0xdfe379c5, 0x3171ab1b, 0x40eeb37b, 0x76ea71fc, 0xa71a6a7f, 0x9851142a, - 0xf1e9701d, 0x2dfa48ce, 0x7699dfd0, 0x3a4ddf19, 0xbee31113, 0xc9701c17, - 0x95a11f7c, 0x475d0fc9, 0x71c09ef1, 0xf0a77f76, 0x573c04b5, 0xd2f1e77f, - 0xb7fde077, 0x8358a93b, 0x82b6dfdd, 0x4fdb69f1, 0xef4021f4, 0x13dfe3b6, - 0x07dafd61, 0xffb18df8, 0x4fd44e8b, 0x50fd50f1, 0x10a06ef4, 0x77aad5d8, - 0x66cb7dae, 0x938e9f82, 0x2342eb0e, 0x83ee07ed, 0xbc39b9c0, 0x569dee57, - 0xaa88f00a, 0x7d0a754d, 0xf9bb21e7, 0xafde557d, 0x21ef9aac, 0x6bc6af90, - 0x266f8fd0, 0xcc664b8b, 0x9f165232, 0x87f7190c, 0xabc213ca, 0xaf7f7ce8, - 0x28bb3706, 0x8d9e7c5e, 0x78112fd9, 0x06a26a27, 0x2e63d3f6, 0x4bc1de7e, - 0x83bcecbc, 0x7aa3643b, 0xf6ff61fd, 0x9e08930d, 0x7c06d867, 0x819e73d9, - 0x2f800b44, 0xea7d768d, 0x321de72d, 0x5a2a13e1, 0x17338722, 0xfd5025ee, - 0x77866ab2, 0xf11fe42b, 0xb2cdf7b0, 0x3821f748, 0xdb8db0df, 0x1560d9a3, - 0xe77df6e7, 0x6fbeebec, 0x78a53296, 0x853f30e9, 0x535ff5d3, 0xca7c5ce1, - 0x0d4fc52d, 0x2d856951, 0xa3dc1a63, 0x78bc7949, 0xcfcd066c, 0x34f4ff5f, - 0xe2f7ffac, 0xff3459b1, 0xb20e7b93, 0xcf012afa, 0xaeb0bec1, 0xeff01a76, - 0xd9fb96d7, 0xb9663314, 0x77f0057f, 0x77eef02e, 0xae706917, 0xefe15ba2, - 0xdda00465, 0x7f0c89d0, 0x9f77ee99, 0x98657f02, 0xf00563ad, 0x7fcf63eb, - 0x16f78491, 0x2aa1fbf9, 0xdce15469, 0x789a2d15, 0xf3e712f1, 0xccfbbcfa, - 0x498dcbf5, 0x3f8177c1, 0xbc8de79a, 0xef1d1a6f, 0x0e718ae1, 0xf2d00e76, - 0x829aa34e, 0xe9c85d74, 0xcb3df84a, 0x8b3e7c45, 0x02c290c5, 0x7f5caddf, - 0x5751ef19, 0x1ef4578b, 0xdbab8735, 0x67fbefd5, 0x3378007f, 0x007f8293, - 0x3fdf59fc, 0xb815c57b, 0xe519f500, 0x5c7de25f, 0xeb333de3, 0xea4468bb, - 0xfb3efb8e, 0x5a2efe56, 0x9bfef07f, 0x69ba283b, 0x682f39ff, 0x39518f7b, - 0xf150b31b, 0x31cfd1c3, 0xd2fd0bcb, 0x0426c220, 0x1fa71076, 0xf788cf3c, - 0xb822ee1f, 0x1765db5f, 0xbbaff074, 0x7d4549fe, 0x3a70b99e, 0xae5d5ffa, - 0x339c08ec, 0xc35bbaea, 0x018a3d7d, 0xe869e401, 0xf828c481, 0x3e1e5487, - 0xe7c3c8b7, 0x8f37fe66, 0xdb5175db, 0xa9fd81df, 0xa06a3fbc, 0xed8bdcc5, - 0xee9e9912, 0x8e10d06a, 0x087424a1, 0x8e81fdd6, 0xebe6e397, 0x46cfa737, - 0x9eeb9e9b, 0xee1ff880, 0x28ffc18e, 0xcc74bf77, 0xe63a3377, 0xd1d0e3bb, - 0x7bdd6efa, 0x6858e0ae, 0x28fcba77, 0x7d675fbe, 0xdf4aceaf, 0x21f5a93a, - 0xed2b3b78, 0xfeb8a7c0, 0xb31bf418, 0x29d22c7c, 0x00939e86, 0x3e07318e, - 0x06bc01b5, 0xe7ec1f1d, 0x9ba9793c, 0xf1d673ad, 0x063acad2, 0x9fb4e307, - 0xf74cd6e5, 0x451c0a0e, 0x69ca897e, 0x87c58dba, 0xb7efb6fa, 0x9d4b9cff, - 0x59502cf3, 0x73ff14bf, 0xfe064f00, 0xfbf3756f, 0x7ff17dea, 0xf8a3b43b, - 0x3fe61dbf, 0xbbcffc00, 0xfb0dfe14, 0x87eb8abf, 0xa29fd82a, 0xda1ff47c, - 0x3a1cb4cc, 0x8dd134ee, 0x8764b072, 0xd931f7c8, 0x3e865ffb, 0xfd5d7259, - 0xb917b821, 0xf20267e4, 0xfefe42eb, 0xfdfc27e5, 0xc1b9eb4b, 0xea10b2f2, - 0x1f9fcbcb, 0xaa3ea30c, 0xff2e65da, 0xbbcf7767, 0xde785997, 0xad352417, - 0x2b4ebdf7, 0xb9bbcffe, 0xb4e858de, 0xd72f7bc5, 0xdbd68748, 0x33cce74c, - 0x83f4f4a6, 0xa6cfa0fe, 0xb8f189bd, 0xc409957f, 0xa5297413, 0x2019de10, - 0xf4094285, 0xd7e5cc5b, 0x72d86fe8, 0x1d9ffaf3, 0xcc43df32, 0x43df316d, - 0xbe6ade1c, 0x66d57887, 0x51c43df3, 0xc43df361, 0x338d766b, 0xae4747e5, - 0xb31fb537, 0x3f29b27f, 0x534dfa36, 0x66c7f1fb, 0xda13f29a, 0x7f6a67bf, - 0x4df35bed, 0x5475d7f5, 0xf86fea9a, 0x7f299968, 0x9b3ff763, 0x311747da, - 0x61b878fd, 0x5bdc1179, 0x7872f030, 0xa15362a9, 0x9b08e97c, 0x9e5b105a, - 0x90056ba6, 0x7fe0e916, 0x532f27f5, 0x8a2a3f1c, 0x898ba75d, 0x536fd26c, - 0xd47ce61c, 0x8f7dfe6d, 0x35722c97, 0xcb527ea4, 0xbc1d9a08, 0x63cf0f24, - 0xc63af953, 0x01b1dbf5, 0xa0dfb7ea, 0x9b46d57c, 0x2f956f20, 0x9a01bde3, - 0xad8fd886, 0x1f9f77b0, 0xd4f99a72, 0xf95e8fd7, 0x0738db9d, 0x53facad4, - 0x264bc6cb, 0x3fca3139, 0x172d8c2a, 0x73c74f16, 0xabf5fd40, 0xb35c16f8, - 0x3bbc107d, 0xa3530f3c, 0x16cca9bc, 0x67dfdcf7, 0x7fd0bfee, 0x8ec7dcda, - 0x7cf00cfa, 0x26daf7ce, 0x7b56bf38, 0x51fa377b, 0x5e337619, 0x5decf37a, - 0x479e0363, 0xac3e481a, 0xb6fdc6f7, 0xebe13445, 0xd177ce36, 0xe0d333db, - 0x3f66419c, 0x87a155fe, 0x1b47ebe9, 0x042cd742, 0xe98711c2, 0xb456795e, - 0x39f81a6e, 0xeb79f8c3, 0xe7f8b64d, 0x0c3c92a0, 0x48a0e92f, 0xdd505ec1, - 0x2b9c2f68, 0x4f0bd77f, 0x0f68dcc7, 0x38e87926, 0x17b4c7f3, 0xbad4fbb1, - 0x5ee8e67f, 0x947d0db8, 0x026c0ee5, 0x93e592fd, 0x17dd9688, 0x83dbf49e, - 0x788ef02d, 0xefcdb263, 0x00b77cc6, 0x4c7fd9e3, 0x5e3a20c8, 0x84459fe3, - 0x75f0f1af, 0xeec83e78, 0xabb8c7ae, 0xcfc24f31, 0xe6711809, 0x89d9be0b, - 0xabc6cf80, 0xe107ee7b, 0xdc17907b, 0xf7e876c1, 0xc71946c2, 0x982c9c6d, - 0x4b798dea, 0xf78dbf9b, 0x6cdcb2be, 0xde74e5de, 0x933db700, 0xa8f8d5c1, - 0xae113240, 0x28f4bdff, 0x5cfb35f8, 0xc507def8, 0xc7c010c7, 0x73fb3d39, - 0x3a79319b, 0xee419aaf, 0x9ed16bad, 0x4ea7ef89, 0x8fa1e637, 0xe33bd134, - 0xe2fc332a, 0xc6fd1946, 0x3c6e4945, 0x886e10ef, 0xe79afa72, 0xf99be4df, - 0x5c295b9d, 0xf8884eab, 0xd1d6b6de, 0xfd28f4ba, 0xe5cdbcae, 0xf17d6b0f, - 0xf0634e7f, 0x7ba7f852, 0x4f36de40, 0x79e3f9c3, 0x31ff806a, 0x0d9c3c81, - 0x452c17fc, 0x236c183e, 0xc7d36fb0, 0x7930f04e, 0xd951ed9e, 0x72be357b, - 0x85be8726, 0xfda76cd7, 0x5dfa7995, 0xb0f36ff7, 0x4f36ff75, 0x72ff759c, - 0x975707ef, 0x54851fb5, 0x37b445d4, 0x111fa908, 0x3d53476b, 0x1bfd0e56, - 0xc7f13179, 0xff6fd005, 0x65bf9a76, 0xede5f644, 0x80cfb034, 0xecfb0d0f, - 0xaed98f4e, 0x3fbbd18c, 0xfbbd30f4, 0xf4c0cf43, 0xfda18fee, 0xe345efe9, - 0x4aa935da, 0xb4f7bd7c, 0xac1fdd87, 0xe7821553, 0x0fd9fb03, 0xdae5c9d8, - 0xd6feef3a, 0x1ff9cba5, 0x4f832e39, 0xfcfefacd, 0xf4112d31, 0x4207ca54, - 0x86b777dc, 0x3c6dbf2c, 0xad9b6bd0, 0xf7cc3378, 0x78fe1667, 0xf59f4d68, - 0x18f1cc2b, 0x6ac78b8e, 0x099b478a, 0x973c3b8f, 0xb6bf0fb0, 0xdf30afbe, - 0xf8e4e9f3, 0x09bf7aa6, 0xeb373bc6, 0x6b8822bd, 0x1cf9ced4, 0x1ed7fef5, - 0xaebccca7, 0x1d397e18, 0xa1e00567, 0x799fd673, 0xe303ae7c, 0xb99eab4a, - 0x58e2112a, 0x7a0d9335, 0xaa7df044, 0x4839f9f3, 0xecfb7397, 0x2e79c03a, - 0x3d139d99, 0xa3daefb7, 0xa4f8f710, 0x2c7258e1, 0x793dcf7d, 0xfda648bc, - 0xbc7bdb9d, 0x7703c248, 0xd43bd361, 0x5b7f1735, 0xdef77014, 0x37e1e84b, - 0x368f5b07, 0xe57c593a, 0x37173841, 0x6abfda86, 0x7a65f212, 0x285eed9a, - 0x1dbf1d17, 0x395c21fc, 0xa62fe63f, 0xd04ab259, 0x7ec11633, 0xee373cd3, - 0xc972f967, 0x9dfa6cc8, 0xe387ad12, 0x6af9c4cc, 0x04efc098, 0xf1444eb8, - 0xef3c02f7, 0x3ef86076, 0x02b243f1, 0xbdffc29e, 0x78093c1a, 0x09ab3a4f, - 0x77c41a89, 0x471e6e8a, 0xd30a6953, 0x3ab7ddbf, 0x848cf7f0, 0x53aaaf05, - 0x3cdafea8, 0xdd8efd93, 0x920b63f9, 0x55691fc0, 0x0df2de99, 0xb463e1eb, - 0x6be7078b, 0xe6231737, 0x40577c75, 0x921d1955, 0x8a6b6c33, 0xf9c78c35, - 0x25fe98f3, 0x3dff1a52, 0x1eb7ca29, 0x1c43a6cd, 0xc5cef8d8, 0xfc522bbf, - 0x7803cebf, 0xf0fcdb46, 0xabfb8f4e, 0x92ca386f, 0x28ccfb69, 0x945e5fbe, - 0xc39de1c0, 0xfbef07de, 0xd345e34e, 0xd4b5187d, 0x27b74efc, 0xe214b4d0, - 0x6defd0fc, 0x8bcef8c9, 0x38a29eb9, 0x0bbb9691, 0x0aaee5cd, 0x47e18f9a, - 0xf6d677eb, 0xae925f86, 0x37f63832, 0xbf0f1038, 0x79fd506c, 0x340e8f94, - 0xb07f30f8, 0xda34c341, 0x0fcb1230, 0x2f31f837, 0x986cf4da, 0x7faffa4f, - 0xeebb1490, 0x9d54efc2, 0x75c3e18c, 0xf9ade472, 0x88df8f80, 0xaf15af88, - 0xdefe478e, 0x3a8e9a34, 0x7367bd86, 0xfefec632, 0xd257f2e9, 0x0d5f284a, - 0xd3afd1f9, 0xefc3c64a, 0x17f3b096, 0xf63a4170, 0x257aee1e, 0xe093f9a0, - 0x34c63477, 0xfbc2863b, 0xc95bc1a4, 0xfd239458, 0xbbf089c5, 0x6c337b0b, - 0x949a7eb4, 0x07f8ecd7, 0x64deab80, 0xe7e7afe7, 0x6c9f1f33, 0xbce3afd6, - 0x0a66ff4c, 0x71bce3c5, 0x537e09f8, 0x39acfd00, 0x3307b9c6, 0xbf54891e, - 0xeb8a76e1, 0xdfb3efe6, 0xc754485f, 0xf7bde1fb, 0xcec35ecd, 0xbec5f7a9, - 0xff99bee7, 0xe1e2440e, 0x29176825, 0x103bf63e, 0x0f7b0a29, 0x4d930489, - 0xe5cdedef, 0x0606ccfd, 0x1f57d09a, 0x15fde6cf, 0xfb0e791d, 0x8897df83, - 0xf087eff5, 0xccd8c3df, 0x3574d3f5, 0xed4dec50, 0x5bd4676d, 0x7759ebbf, - 0x0bd1216d, 0x890143f6, 0xed04bd80, 0xd4bb698a, 0xdc02030f, 0xd7ce33ef, - 0xcdf80b3e, 0x93ddfdef, 0xebc3027d, 0x8a7d3c93, 0xd4494eff, 0xe3079813, - 0x123c16fb, 0xca7603da, 0x6206bb3e, 0x8fe47452, 0xf8947ef8, 0xe701c53b, - 0xbc0f53fc, 0xd9e5eecf, 0xbf38143a, 0x7c5bd2b8, 0x4551c413, 0xf3033ea5, - 0x816f4ef7, 0xfa9e83fc, 0xdda3d887, 0x1f0137c5, 0x06f7f3a4, 0x01000408, - 0xe1aa080e, 0x43fd638f, 0x64654eb3, 0x2bf2cc9f, 0x873637bd, 0x3f5f2132, - 0xf208f80f, 0x7dbfb48d, 0xc021c149, 0x86e16e47, 0x423763e6, 0x037f68de, - 0x5789ffb6, 0x3b8ffe65, 0x4af60d98, 0x79a55e4f, 0x625e4c4f, 0xa960e279, - 0x239abf31, 0xd073c47f, 0x3bd807b5, 0x6607a95d, 0xd4cf3008, 0xff1033fd, - 0xbcb7d5e7, 0x878c342b, 0x04eb608f, 0xf41b978b, 0xa6e1ee30, 0x79f783d9, - 0x9d61f863, 0xc4c76cd7, 0x0fbc27dc, 0x1fd3ddf0, 0x36cbaf8f, 0xf74a9ef6, - 0xc6efd88f, 0x547b030d, 0x86b9b884, 0xa3dc2e69, 0x70c1fea7, 0x98395c12, - 0xcde35fd6, 0xb55e3a41, 0xa9cdfb3b, 0xa75f2f5a, 0x80772964, 0xf8b54e3e, - 0x3f5cd935, 0x7f8b508f, 0x372b4893, 0xf0b5c10a, 0x8f686c9e, 0x937de2ac, - 0x4728195d, 0x228eb967, 0x5f3183f5, 0xcbbfefcd, 0x476b832b, 0xc4591e81, - 0x76556ef4, 0xdfa658a0, 0x8d973d57, 0xf0670bbf, 0x2452555d, 0xf7bb9c6d, - 0x3791b75c, 0x21e4477e, 0xef09d5b5, 0x5afb18f2, 0x6437fbb5, 0xc7fd3ec1, - 0x3b46de87, 0x36624971, 0x76d359c2, 0x69df815c, 0x7ca36da9, 0xd8fbbf47, - 0xa3c763d9, 0xc887f25f, 0xbe026fa0, 0xc368d0fe, 0xd9fdddcb, 0xfd522f55, - 0xea85d3a6, 0xd3038368, 0xd5fd7a9d, 0xf09c0ae0, 0x49c9b82e, 0x1cf1e9f9, - 0xeafe055d, 0xf51eb7bc, 0x3a8ae3d8, 0xd3aff80a, 0xe066c3fb, 0x9124aae7, - 0x5f0febf3, 0x7ef8f3d6, 0xb9efcd3d, 0xbfa6edb7, 0xa160df68, 0x7ba9fed9, - 0x41fc8dc4, 0x02df92ed, 0xb66ed51f, 0xb3fd6085, 0xbef1da39, 0x1be82773, - 0xfbe65fd4, 0xa6051b99, 0x5873430f, 0xf772fa1c, 0x74be2b34, 0xfd8c7091, - 0xe99124bd, 0x84290aab, 0x5f1576fb, 0x2ffeb17a, 0xba69c71f, 0x1c77da0f, - 0xe31bd637, 0x838ef754, 0xf6fd527c, 0x5fcff461, 0xafb0dabc, 0x77ffd475, - 0x61cfc53e, 0xe874f538, 0xd0d941e7, 0xa4cfd427, 0x1ee78678, 0xf9243e79, - 0x47a97908, 0x2e6dacff, 0xf6fa04c9, 0x7eb313d6, 0xb74a25d2, 0x3e781297, - 0xc9737f74, 0x13ed38a4, 0x8c73ed2c, 0x7fb14ffc, 0x3a0f3c2b, 0xda0ef37b, - 0xbd93fa5e, 0x6df00f27, 0x4bfa59b0, 0x86dfc636, 0xb7fc19fd, 0x65fbbbc7, - 0xa5e9ef78, 0x10f140a4, 0x2068df66, 0x15245b87, 0xc0d1877f, 0x3ebe1ef3, - 0x8d797c55, 0x78bdff09, 0x9f95302f, 0xfb4cd06e, 0x2e178ba1, 0x7b3f7bc3, - 0x41563af8, 0xdb3eec42, 0x7da6b923, 0xc70fffd0, 0xb8a385d7, 0xfe4a381f, - 0x328c70c6, 0x385e81e9, 0x5fe54df2, 0x69310e17, 0xec366976, 0xa1b1ad53, - 0x0b66909f, 0x6ec07239, 0xf7ec5ffb, 0x0734201a, 0x61a899e7, 0xce57da6c, - 0x079f6039, 0x448e79c6, 0x40e3498e, 0x056d749e, 0x913f53ac, 0xe5a1afd0, - 0x8619390e, 0xfde1d56e, 0xd8952a2b, 0xb0754e5f, 0xe6f51986, 0xab876277, - 0xe5a258a4, 0xb879d5e3, 0xdd94e5ee, 0xfdf60755, 0xcfe17736, 0xbc931357, - 0x5ab27da2, 0xc7f68a58, 0x9b17c49a, 0x3d38df61, 0x0233d981, 0x58f9b179, - 0x267abc46, 0xbdf72daf, 0x31c41378, 0xaed4aeb6, 0xab6e7f06, 0x0c391c33, - 0x6e3df9eb, 0xdcaa3dfc, 0xf816e175, 0x83710abd, 0x314bd70d, 0x2b6bbc29, - 0x6078179c, 0x8bec1f84, 0x40d760ad, 0x5c6e35fb, 0x421a5bff, 0xe2af2f68, - 0xf5f6c0eb, 0xe7385493, 0x9296e8dc, 0x916bbd61, 0xb8056feb, 0x64efba5e, - 0xd03ae3b3, 0x4196fe63, 0x80cbef3c, 0x71cb4d75, 0x14f5e58c, 0x68575b19, - 0x3485c183, 0x44ffc3f2, 0x33d412ad, 0x6b0ed127, 0x04ab2f74, 0xbfd68e3b, - 0x7a78a0ec, 0x85e3993c, 0xe8f4e7d7, 0xa0cd93a5, 0xbd15c507, 0xef3a12f9, - 0x7a633f1d, 0x3fda09ea, 0xe7452bbc, 0x18778213, 0xe84947bb, 0xc1242587, - 0x74d0c76f, 0x9dfb0e74, 0xbd17aa5b, 0x3849c7e8, 0x491f635f, 0x0f7ec519, - 0x7ac3da1d, 0x83919093, 0x0cca98fb, 0xe2835ef6, 0x66fde371, 0xdd5677e3, - 0xb3a7f8c4, 0x67df2978, 0x43de5971, 0x895fae70, 0x784ee99b, 0x4f862137, - 0x0b7bcb15, 0x07cc0912, 0xcd544b7b, 0xe449bfe5, 0xd8834afb, 0xb70eadef, - 0xa32ed085, 0x35e98452, 0xd9f68a24, 0xf981d268, 0xe66de031, 0x0d2c35c2, - 0x278d8e2f, 0xbbe2c8ba, 0xc7ec1101, 0x788d5bb4, 0x44f5f04c, 0x96bfdeba, - 0xfc36e3c8, 0x66538c77, 0x7d7ee214, 0x5fab1266, 0x0fbbc815, 0x338dbcec, - 0xc69c61a6, 0xf58cefb0, 0x16dfb0d2, 0xab579872, 0xc17b5c42, 0x3a16ebb0, - 0xb6753e59, 0x8868e0fe, 0x0b53b66b, 0x2fee1b34, 0xf96af8b3, 0xb034e2e6, - 0xba1e16cb, 0x4ce4ed15, 0x8b65d995, 0x8250ce36, 0xdadee1a3, 0x8a07f43c, - 0x84484c37, 0x4ed5847d, 0x8575e27f, 0xfbe267e8, 0xc7b503b9, 0x355da6b6, - 0xab71e419, 0xca90128d, 0xeeb24bfb, 0xb17c0b1e, 0xcced0f21, 0xc6c109ad, - 0xd6efda24, 0xabfcd67f, 0x4ea7fe68, 0x8c38f0bd, 0xd5813ab3, 0xc051bbc3, - 0x12e73d9b, 0xc9bbe1b6, 0x3d6f8dfd, 0x1252f097, 0xa8ca7f7b, 0x7e536fff, - 0x80007d7c, 0x00008000, 0x00088b1f, 0x00000000, 0x7dbdff00, 0xd5947c0b, - 0x66fdf895, 0x666579be, 0xf263c992, 0xc2130922, 0x9e4e5e4b, 0x124c2280, - 0x4cb443c2, 0xe8202a10, 0xa79034f0, 0xbadc5d48, 0x30040cff, 0x5706b650, - 0x84ea2b11, 0xbbaac562, 0x351ba341, 0xb88080ea, 0xda446dd6, 0x8ffd16d2, - 0x4810154a, 0xfed2b58a, 0x39cf65dd, 0x7cccdef7, 0xb5f01993, 0x3efeb4ff, - 0xe7ddf7ee, 0xce73df79, 0x12e973bd, 0x2c614dfc, 0x5630a494, 0x51c1d8ca, - 0x618cf58c, 0x24dea98c, 0x064dcf06, 0x34e2d26f, 0xa37efac6, 0xf5e1bb67, - 0x926f6617, 0x25d8c6c3, 0x79fa2ed1, 0xa0b199aa, 0xcdb3b189, 0xc11c166e, - 0x336699d8, 0x1f966b95, 0x9fa0c698, 0xb9850e9a, 0xc55b19f2, 0x3f6336da, - 0x69923baf, 0x3d0155dc, 0xf4648e0b, 0x5bfe0977, 0xd528fcbd, 0xebc9dd5f, - 0xaa0eb2d7, 0x4f3192bf, 0xf76b3c07, 0x1cd0595a, 0x51df5fae, 0x4a1f69ac, - 0xd7bf51d2, 0x3b06fb25, 0x5bdd8c9c, 0x2abefc3d, 0x5d569f78, 0xfae1f662, - 0x13e38e58, 0x87afa8ab, 0xebe63af7, 0x77aeb188, 0x49de5c04, 0xac4e8a82, - 0x32b1d0ed, 0xe03ad6c6, 0x1ec62e9f, 0x6c7cd850, 0x15f7f6b7, 0xc2632919, - 0x9e2ad6ed, 0xf898c70c, 0xa8bc6a70, 0x88d48167, 0xc467dab2, 0x345e35f5, - 0x0ef3fbd2, 0x63075fb3, 0x3ff4c91e, 0x7fac2d70, 0x1953eb26, 0x909f53cc, - 0xcd5d8e38, 0x71258b58, 0xba673e37, 0x08a17d0c, 0x53333038, 0xf8337e71, - 0xc4ebf62b, 0x71944769, 0xed403ed8, 0xa98ed967, 0xc473400c, 0x8303735e, - 0x90b037f7, 0xce060aca, 0x28fdfa0f, 0x2359dfb2, 0xdd1be5b5, 0x09ecf2da, - 0x7e6332da, 0x9a4fd782, 0x1a4eca9b, 0x04fefdc2, 0x0311d6a6, 0x5802b72e, - 0x5eed7eb1, 0x0464e04b, 0x923beb1e, 0xaec6e535, 0x88c9c0ac, 0x1ff16a71, - 0x135ff059, 0x589d775f, 0xdf4607f7, 0x5bc00ead, 0x71190b3d, 0x46c140dd, - 0xacc658ef, 0x7c45e616, 0xf16fd81d, 0xcfe812b0, 0x00b76e66, 0xabbb1b7c, - 0xdef02595, 0x30ef876a, 0xe196273f, 0xfaf03569, 0x0e88058c, 0x39da8fe0, - 0x5bed99bd, 0xb713e415, 0xcdfedaab, 0xff00dde7, 0x4f0293dd, 0x24ac3d95, - 0x0ea3ac46, 0x5e1e91d6, 0x07eb39c7, 0x582f8865, 0xa5ec6fcf, 0xa6461748, - 0xf3d78524, 0x5cb5e1ad, 0x5dc6af0b, 0x1837a236, 0x1844bde7, 0xcea761a7, - 0xceb2846f, 0x7e4463dc, 0x3ce917b9, 0x1c72de06, 0x6f3c4c4a, 0xe0c73c43, - 0xfcaceda7, 0x1cc7e43e, 0xc7181fe4, 0x6527eeb6, 0x8f818b27, 0xfa1737aa, - 0x054dbea0, 0x547186fe, 0x08a9bff8, 0x6d3bd9c8, 0xe9d03255, 0xc3e73b29, - 0x7a2e890d, 0x0abc50ee, 0xe75d35e2, 0xd5fa47c9, 0xcc43b827, 0x66a3f1c1, - 0xcb601942, 0xf962c1ae, 0xefe81ebd, 0xcb1b9821, 0xf0098416, 0xcbc2c878, - 0xefca392f, 0x6ee308dd, 0x0de5e64a, 0xd5b9bd3f, 0x16ca093f, 0xe5439e59, - 0x416d0c87, 0xffdde03d, 0x44f5c982, 0x28f7b53e, 0x32305e58, 0x4d4c04f0, - 0x2365843f, 0x4226a65e, 0xf4b720e7, 0x9b769a2f, 0xeed05ea0, 0xa78427fb, - 0xfb39ff5c, 0x26363cf1, 0x4d7e7f66, 0xacdf797f, 0x53bf183f, 0xfbf87577, - 0x419dc4d4, 0xc2e76f3d, 0xe7a72c76, 0x9ff43f03, 0x6d89a2fe, 0x0623e285, - 0xda179b76, 0x632c5dd5, 0xd43908c1, 0xb679f023, 0x5b7241d9, 0xf943afbe, - 0xa9f9063d, 0x7d70e487, 0xfe46aa47, 0x7f5cb94a, 0x7f4d5af1, 0xc27c8e39, - 0x43dabd57, 0xe2feadf2, 0x121efa64, 0x736cf4f2, 0xf889e926, 0xc8d20ce3, - 0x1338f0f5, 0x72f8b059, 0xefa24ce3, 0xcbe61c72, 0x06bdb922, 0xa4240ce7, - 0x87bc8237, 0x750c2e71, 0x465f2525, 0x0276d99f, 0x67ac4591, 0x63341a9b, - 0x07dcdbff, 0xfc18be1c, 0xb844e520, 0x1edb51bd, 0x811b23f4, 0x4863edf4, - 0x7aacffb7, 0xd4fa91cc, 0x5038f066, 0x8af6a86f, 0x34372e23, 0x86647e4d, - 0x5169280a, 0xd97f3d39, 0xd1e881b6, 0x411f706e, 0x3aeddafc, 0xafbe1f97, - 0x483ce9b7, 0x730e2d27, 0x51bdf100, 0x7281c1b9, 0x076bf643, 0xb8f38f31, - 0x7a421b60, 0xd57ade3d, 0x0f54898b, 0xa9199266, 0xc6f7ff1f, 0x0f17c583, - 0x31bd8f1c, 0xfa0b88f1, 0x6e744b57, 0x910be00b, 0x1d0471fa, 0xdf63f744, - 0x779cc6a9, 0xff093d74, 0x8436f8b8, 0xe7fe1112, 0x8119ba6d, 0x4d2ef318, - 0x9e9bbe56, 0xdf25145a, 0x3c3b7f93, 0xd095ed88, 0x49f20a0f, 0xa32696fe, - 0x90bc2dfc, 0x3922e958, 0x73b5ee9f, 0xb6e385b1, 0x7d9a8ed8, 0xed988fa4, - 0x3ebfd913, 0xb849fd3e, 0x64aade18, 0x04601f88, 0x4ae37a86, 0x412bb070, - 0x1597e22f, 0xd3e50caa, 0xa76f3a40, 0x77d7f4f9, 0xeb11e743, 0x0edd516f, - 0x75fd6ba4, 0x99ca331e, 0xe6398ef5, 0xaa379410, 0x20f9d9ae, 0x02defa87, - 0xb7d6127b, 0x1cc8ad29, 0xc15a8f8b, 0x2df9c46e, 0xd669d64d, 0x1d669f23, - 0xf7e8dfe7, 0x9eb9925b, 0xb13fdd68, 0x9f1253c7, 0x79d2407e, 0xcb9b8f51, - 0x5856c754, 0xe7c0de9f, 0x0763896b, 0xc1e37eca, 0x0b7ecb6b, 0xa87569c9, - 0x44f68039, 0x549b78f4, 0xbe078f77, 0xf8f9826f, 0xc7c39cb1, 0x3aa254df, - 0x16d74376, 0x47330257, 0x4b3837d4, 0x6c17fe08, 0xdf0f4c69, 0xc63d2137, - 0xd3849798, 0x68efe4bc, 0xe8a2f93f, 0xc3b7f732, 0x5d0d10d9, 0xcba2c6b6, - 0x4b37a879, 0x3999fcf9, 0x9343fe72, 0x8c7c8ebe, 0x49b29ba6, 0x977c83cc, - 0x5876cf01, 0x66caa76f, 0x807d43ec, 0x9844d6b6, 0xe636cddf, 0x393e9900, - 0x32677cb5, 0xe7acb7ac, 0x3f219180, 0x1d693a74, 0xf47da275, 0x8e14a6b8, - 0x838a533f, 0x3dc7499e, 0xf8014f4f, 0xb824f676, 0x99d4f814, 0x0630fa02, - 0xbc088f7c, 0x9fc6d633, 0xf21c686a, 0xb65fac8f, 0xc3767988, 0x6b0250f3, - 0xb2bd8335, 0xc607c84f, 0x154fe7ee, 0x99c61718, 0xdde8cafd, 0xf58a2f64, - 0x80b5021f, 0x43d3d3f5, 0x77fd14e3, 0x585edbc0, 0xeade047d, 0xdbc221cd, - 0x6bdf46db, 0xe3c69f08, 0x772c74a1, 0x87933d1e, 0x70b670f8, 0x25efb5fb, - 0x6ee9006b, 0xd3d67e20, 0x0e2eeafc, 0x81e2fe62, 0x8353ab78, 0x2eeb5fa4, - 0x5877d1e6, 0x129cdfb7, 0x6c1b3efe, 0x2eb00986, 0x4270e666, 0x47c2c4f8, - 0x896be0bb, 0xa3eb500f, 0x081f02ed, 0x3ec48fa7, 0x4eef1fa7, 0x780666e3, - 0xefe66b3f, 0xdf246799, 0xfe7d0987, 0x005e4251, 0x0d1f33f7, 0x7a46ce07, - 0x91e95d50, 0xe2cea77a, 0xac3e6fb9, 0x67abbd9b, 0x5963c04f, 0xed15ada5, - 0x4f2665ab, 0xcb5dda12, 0xeb2bd3de, 0xc48409f3, 0x3c042b07, 0x5df732cf, - 0x36ff3f88, 0xc209e38b, 0x97ff769f, 0xf8bca3bf, 0xa2bf681d, 0x9346ef4b, - 0xcda56971, 0xf596fd8f, 0x876d3c54, 0xad5b2bf7, 0x2efd062e, 0x04fee29b, - 0xf765bded, 0xf21b5c59, 0xa438bf71, 0x5dfa0b3c, 0x03be60fb, 0x9d7581e5, - 0x06ecd337, 0xeb7ee093, 0x6de02b4c, 0x8964b293, 0x7dac0852, 0x1516ca7f, - 0x57feacf0, 0x281667e5, 0xc17f755f, 0x8c75f316, 0x1cb282bd, 0xd0ff59ed, - 0xfedf6899, 0xf646a712, 0x7f6fb72e, 0xca274479, 0x82a65bc5, 0xece5180a, - 0xce60d9d4, 0xb78a532b, 0xf4fc6198, 0x0ea14f14, 0x32935bc6, 0xb7f62661, - 0x7fb1bef4, 0x77df09dd, 0xa99acca4, 0x44de13e6, 0xcaccef7b, 0x926ed0a1, - 0x54b3cf2c, 0x56697f42, 0x27a7b616, 0x090fbf00, 0x77f68f8f, 0xbdfdbf67, - 0x1cd4e660, 0x53454bc0, 0xbffd0aa5, 0x96db729e, 0x36315731, 0x877281fe, - 0x983fc607, 0x15a664b2, 0x9469dff0, 0xf16d97f5, 0xcc9d58c0, 0xbe0186f7, - 0xbafef1ff, 0x9fa86699, 0x742dea96, 0xcd53fac0, 0x91996ff7, 0x65f81dfb, - 0x4fbd12a4, 0x1271482c, 0x90461cdf, 0x33ebade6, 0xf82afd72, 0x71d3873d, - 0x9424797f, 0x4ce511ed, 0x10dcee5e, 0x4e9c7e5b, 0x33b972e5, 0x8f77f621, - 0xef004b90, 0xb3e90ea0, 0x96181acb, 0xc027961f, 0xc409e64f, 0x3cb9db5f, - 0x639abe01, 0xd98e3e27, 0x5fe537df, 0xd3f53b80, 0xe8ac7aa9, 0x0d7290bf, - 0x71c56666, 0x69764cbe, 0xcf5975e4, 0xbfb79252, 0xeb7c154a, 0x5671f0e2, - 0x330ae56a, 0xb8470cf7, 0xc58b76c8, 0x4b47f33a, 0x88d052ff, 0xe2d6b9fc, - 0xacf9c0c9, 0xc19e57dd, 0xd787632e, 0xf8d72c5d, 0x98ebc24b, 0xf407ef4a, - 0x44b9fd0b, 0x5f31eeff, 0x57c95e07, 0x7d1a5780, 0xc33ad2bf, 0x3bfd69fd, - 0x7ee3fb03, 0xc57a019e, 0x1b9e7b18, 0x415eb853, 0xe422ebf8, 0x5f214ada, - 0x3d916a41, 0xabc5fe7e, 0x8fcd6f76, 0xf503771c, 0x7a7df80f, 0x412fee0a, - 0x2b1ca2be, 0xb0b33d53, 0x8a4f597e, 0xa079ed03, 0xde828db7, 0x8937a454, - 0xa694cee7, 0x76ef5a72, 0x863bb1c5, 0x3913f81d, 0x83c536af, 0x22c649f6, - 0xc4497e9f, 0x87fca4fc, 0xff453bfe, 0x1f9e9c25, 0xc5e7a7ed, 0x2fc23fc8, - 0xdf40dcc4, 0x5fce0763, 0x08ce36c1, 0x2582f5fd, 0x7091f380, 0x2ff4b6fb, - 0xb8ba87ed, 0xda912a7a, 0x260f1c65, 0x219ea0ba, 0xb9f9c5c5, 0x6bc4e3e3, - 0xe9755f51, 0xebe2e299, 0x2651b946, 0xe7bfa4e5, 0x764a8548, 0xbb2e584c, - 0x72919ec8, 0x87366833, 0xbdbfdfeb, 0x9446c667, 0x2fbe26ab, 0x1483d34f, - 0xe3cf0a2f, 0x2fae14e5, 0x2798f827, 0x24781d96, 0x08e52ed9, 0x75e1e3ad, - 0x5863ec95, 0xd7e85d9f, 0xf93f2109, 0x664c9eb3, 0xf0e13ec2, 0xb67bfa90, - 0xdcaff429, 0x47a5a64f, 0xa53b0659, 0xee105741, 0x89cfbf1f, 0x8263fba0, - 0xf3f1a20e, 0xc013e55d, 0x48708fc1, 0xc872e14d, 0xed056509, 0x17f4150b, - 0xb55cffc0, 0x3f35bdcd, 0x2e36de62, 0x1d7a9d8f, 0xe0576397, 0xfe54b48b, - 0x3b25efbd, 0x1e1873f1, 0x2ff98edc, 0x1d76f701, 0xc17dc1ab, 0x09f01d21, - 0xaf8da2d2, 0x598bfcf3, 0x29e7efd4, 0xeffeb93a, 0x1bb72e45, 0xd7ce3c61, - 0xbfd63f64, 0x3b5da83c, 0xdcdfde7f, 0x658f4e54, 0x68853dc7, 0xdaf30cc7, - 0x285fb8dc, 0xc07399eb, 0xdde1e500, 0x4b6b038a, 0xc1de1f3a, 0x4ba814f9, - 0x67ade5c0, 0xa5b5fb22, 0xbefa3a72, 0x38fc31d6, 0xcbc457a7, 0xcd3e08e2, - 0x7871b54d, 0x084cfac1, 0x472b554f, 0x9bfbf3e5, 0x0180f787, 0xf0075bd6, - 0xe12db140, 0x64b1d9d6, 0xf8f90583, 0x1f237338, 0xa258ef9f, 0xdd788b1b, - 0xebbec8c9, 0xf00f0f97, 0x147b4875, 0xe903b2e8, 0x5cd4eaf2, 0x71d86f1a, - 0x7c0c758f, 0x1376861f, 0xec3b95fa, 0x4c57dc01, 0x4dcdf54e, 0xedce7845, - 0x4a2064ab, 0xeb4dac1a, 0xfbef112d, 0x7d4177eb, 0x7e9f63a2, 0x36f3ce2c, - 0xc2bab6c6, 0xfaa981eb, 0x6f5a1fd1, 0xa02d3e04, 0xd6e11072, 0xfbf5e469, - 0xcf8a3316, 0x8cfbe834, 0xf7f41df8, 0xa3cfa22c, 0x2fc414ba, 0x6ed09bee, - 0x737bd3ae, 0x67d7dc14, 0x07a8dc98, 0xf4421f60, 0x54c2c87e, 0x26fff40b, - 0x574e513c, 0x8fd8efe9, 0x502aaaf0, 0xae242ddc, 0x60dc85da, 0xcd37dc41, - 0x7a25629e, 0x39dd5f64, 0xbff51ab4, 0xfa09e395, 0xcc7e8b31, 0xff30a2e6, - 0x2aef3afd, 0xfd48ffda, 0xa8514876, 0x8dd7439f, 0xb112ddde, 0x50fec22f, - 0xaa521ffe, 0xfa40ee73, 0xb23afb17, 0x7ac2d30f, 0x2295ed17, 0xfdde245b, - 0x3ca17e62, 0x7b48a3a4, 0x7ed3ed14, 0xb1dfd67b, 0xd9c83a65, 0x823a33f1, - 0xd152073a, 0x01ff33f3, 0xf60551d6, 0x70e005ac, 0x33972a5b, 0xfafdf287, - 0x30df9c44, 0x3abc3f58, 0xd31be09c, 0x938f0b64, 0xe90ffc2e, 0x482fee46, - 0xbfcfe04f, 0xe73b72a7, 0x1e5c6927, 0x978d21fe, 0xfb6313d3, 0xf510be2b, - 0x1f971354, 0xfcb9cb5b, 0x41b7ae8f, 0xedadfbf4, 0x668a31de, 0xef760f7f, - 0xf76e5486, 0x885fb91a, 0x0a9613c7, 0x873b06fa, 0xabb614f0, 0xda503c78, - 0xccf45fa1, 0xf372f2a3, 0xbfe8d97b, 0xe69fedbf, 0xb6f487dd, 0xf27a37f2, - 0xf1149c57, 0xbec99582, 0xbfdc64f4, 0xabf6c427, 0x75d6273c, 0x1f9199ba, - 0x1b8c53f8, 0x893dec82, 0xaf284371, 0x34e0f9da, 0x2cd5bfe4, 0xe5e0fe40, - 0x5c51373b, 0x61407970, 0x69f7052e, 0x1627ee5e, 0x47bd58f8, 0xdf4bf1af, - 0x931936ae, 0x77e984c7, 0x6e369b45, 0x58abb358, 0xf6f6fe53, 0x440b2569, - 0xfcb0a1c8, 0xa3ef4699, 0x1ef495fb, 0xd47ea76d, 0xc3f8d2ec, 0x461cee97, - 0x97f597eb, 0x77ad3731, 0x66816b59, 0xf395acde, 0x49f9bc49, 0xd4bb45ba, - 0x469e731f, 0x008ffbcd, 0xff08fefe, 0x4353d2ff, 0xa92d1e69, 0xba40ffbe, - 0xcac3cf09, 0xdabf1afc, 0xb027c724, 0x7ee16656, 0xff23a049, 0x5081ece5, - 0x6fffa72a, 0x71d1f70f, 0xfee305f6, 0xca0beebf, 0xcc397126, 0x0c3614da, - 0x6aa7e31e, 0xa0bfb4ed, 0xa7c52bbe, 0x616beb95, 0xa45f2d47, 0xd45177ad, - 0x5dea28bb, 0x6912bfc9, 0x2805299f, 0x0d7f78d7, 0xcff38f82, 0xa0ba351c, - 0x6e34f8de, 0x3d3916c7, 0x6cef5097, 0x438e24b3, 0x4b36ca7f, 0x52f5005e, - 0x38bafaff, 0x48336d1d, 0x033b8a3f, 0x5ffed6e1, 0x88a8b677, 0x0fb07dc7, - 0xfe587900, 0x8a1641e8, 0xae375390, 0x01cb3c53, 0xef2176de, 0x7d7cdcea, - 0x71a0ee75, 0x5d93f428, 0xd395e7c7, 0x23515fb1, 0x08d4e5da, 0x419a5f7f, - 0xc1cccfb3, 0x8d254e32, 0x9a9ce3cb, 0xea1432a0, 0xa3daef65, 0x875fd8a8, - 0xbb337a42, 0x41130009, 0xdc25d957, 0xa4b1b9be, 0x2636595d, 0x5d56870c, - 0xe00718f5, 0xeadd35a7, 0x8f737d46, 0x0d2437d3, 0x182279e7, 0xf8fcedc4, - 0xda2a3d13, 0x7a753fef, 0x619cd20a, 0x8ef4b838, 0xd6a7d46c, 0x6d9e7c13, - 0xae63fbfd, 0x4da22867, 0xdcddabfe, 0x23b3d19e, 0xa487db8c, 0x8c37d2af, - 0xe727bd24, 0xf4229e97, 0x3df33a45, 0xadfaa367, 0x68c9f08c, 0x861be93d, - 0x2cf6e6ef, 0x815577c7, 0xafbe0f77, 0xa8aab8ca, 0x6c17de05, 0xa14baa0b, - 0x62bbcbdd, 0x85cb83fb, 0x4c75813e, 0x75c9f5c2, 0xc82e495c, 0x7e38867a, - 0xd60fc90a, 0x1ff7b119, 0x2f7d2230, 0x216d347f, 0xa36eb7ce, 0x30949991, - 0xf4ea7ffc, 0x64f9c6ce, 0x082bb477, 0x93dfe91b, 0x1dff4ae3, 0xfcfe477e, - 0x96f928c8, 0xfe5c5fd3, 0x2cf7a75f, 0x1b67948f, 0x6927848d, 0xc7e7873f, - 0x69d5fded, 0xeabecf5c, 0xf9c12ef4, 0x276d7434, 0x3daacf7f, 0xf9631a1f, - 0xe2f9a3ab, 0x6a54704a, 0x6ea0bef8, 0xeb8039be, 0x25547f2f, 0x68dda83a, - 0xdd5938a4, 0x9fb8fb33, 0x46e61ee7, 0xb1d75139, 0xe30e594f, 0x4fb33ed6, - 0xd7011159, 0x05017541, 0x2ec233e7, 0xafcb90f9, 0x3f47ba68, 0x872dda32, - 0x9c4e5c2d, 0x15f9b72d, 0x8359eb80, 0x9deb0eaf, 0xfdbab2cd, 0xbc3c61f9, - 0x11fa6fb9, 0x3fb037cc, 0xb3e20a67, 0xd33bb755, 0x475af50c, 0x5f48dd19, - 0x36fa753f, 0x54525c23, 0x4fb6276f, 0xd7bbb34e, 0x89975b43, 0xfbbca115, - 0x1f1870ba, 0xefe32745, 0x85d3fce1, 0x91db8872, 0x813fc845, 0xa7b4bb34, - 0x361dae48, 0xc73c75f0, 0x9eff7cf8, 0xe89079ea, 0x8d0a48f8, 0x54175d9b, - 0x7f9d9fd0, 0x6b9239e6, 0x9d30ffb2, 0xe4891e79, 0xb3cf2bdf, 0x56f488c3, - 0xf950e42b, 0x8f947ba3, 0x4bfde623, 0x6e91f430, 0xba019fb2, 0xfdf7d1b4, - 0x3ea8d333, 0xbdf0b933, 0xe16aed42, 0x79088afb, 0x4311d723, 0xf5c3ecee, - 0x1cf44ed8, 0xc82772e4, 0xbe628dfd, 0x157cf8d1, 0x9a7c1fe5, 0xde99ea06, - 0x3123fd1b, 0x48787a2e, 0xe527f502, 0xbedf3440, 0xe51ce82a, 0xfe46cea5, - 0xe52bb25a, 0x22bd64fc, 0x34fec567, 0xc10f4382, 0x4a977ea1, 0x7a32a9eb, - 0xc111de87, 0xfd16bf0f, 0x03f9b81d, 0x07fdca23, 0xa25dfdfe, 0x8536fac7, - 0xedacf1e2, 0xd43ce35d, 0xf4a7fe47, 0xe2ce6768, 0xf1db0126, 0xa784bbc2, - 0x2e5c9d59, 0x53ee77d7, 0x74c2d997, 0xc0e67f9a, 0xf56748ad, 0xfb86261d, - 0xdfbfa022, 0xe9a27c20, 0xca47c254, 0xb4f878dd, 0x9472e0ce, 0x47e48df9, - 0x3e54fd85, 0xdca429fa, 0x4eaa7bfe, 0xfbf809f8, 0x1cbc690b, 0xa7df1fa6, - 0xdcb08f08, 0xe45f10b5, 0x603a299f, 0x5bb87dc6, 0x5a7f3f21, 0xe4678725, - 0xc6c7aabc, 0x54ce9b97, 0x50d437a1, 0x587b1cde, 0x7fcbf7be, 0x810bfed1, - 0xe41f786f, 0xd410d9ef, 0xd1fe72f3, 0x7277cbf8, 0xce831b7d, 0x11d71bfe, - 0x3da4dfad, 0xc9e6e920, 0x8f46aa5d, 0xea469dd8, 0x731b0ecf, 0x728ec79c, - 0x61d8cf1e, 0xc76cfae0, 0xe500737a, 0x780b9bc9, 0xa17d995e, 0x43cf8831, - 0xf875a5ba, 0x1f3650fd, 0x5ba755bf, 0x0dd6e583, 0x7842d636, 0x4b3a24f5, - 0x19127e91, 0x1e5c8f97, 0x973cf03e, 0x5b7e7567, 0xeb3fc180, 0x5397737c, - 0xe2cd39dc, 0xf333b8c6, 0xb3ce341d, 0xd72ba40f, 0x2e8dfb73, 0x83ab3f78, - 0x03c49ff3, 0x2fa253c8, 0xae120fc9, 0xb8727861, 0xf8927e4b, 0x67f4bbf8, - 0xa77cbd03, 0xda3daabc, 0x46dbdc78, 0xbe4ed5df, 0x706c3acf, 0xc7869fa1, - 0x6fd1e217, 0xb3b7baed, 0xb51d824f, 0x7a2df33a, 0xfd85be4a, 0x27bf86ac, - 0x3817bc09, 0x74afbeb9, 0x2da9ba72, 0xacbe20e9, 0xfc44d93d, 0xe5c19b6c, - 0x5684ed9a, 0xcff6331e, 0xa8dbbd62, 0x63b5955d, 0x5477e61a, 0x7038ae3d, - 0x6e4f1fbf, 0xfcf0aede, 0xbd774fb8, 0x72f98891, 0xf2b02bec, 0xe1629e31, - 0xe4eb9deb, 0x5eece272, 0x7bd13800, 0xf672f193, 0x63fa95fb, 0xc20a63c1, - 0xfac056b3, 0x139533ec, 0xec7e84ff, 0x61ee49bd, 0x9ecfe4b0, 0x3feee9b9, - 0xeecfbcc1, 0xf746e299, 0x978b5a65, 0x69cfa7e8, 0x037ee371, 0xf40cf7c4, - 0x78efae17, 0x685af123, 0xabe9fa77, 0xd76e508b, 0x799e798a, 0xe10ebf5e, - 0x7fc9e1b2, 0x6bdf8c9b, 0x09aa4a03, 0xf8fbd9c7, 0xbe63677f, 0xf2469eea, - 0xfd3cb517, 0x17f311ba, 0xfe768174, 0x03926f7e, 0xf9fe9deb, 0xef08c9f6, - 0xfa168e96, 0xede7e67e, 0xe4f03e54, 0x77f6bdbf, 0x1378e3f4, 0xccef58dd, - 0x2f09fbf3, 0xf2953e75, 0xf5d1e2db, 0xb9fb7d8e, 0x8f3d44bc, 0xcb9f307c, - 0x92d74931, 0x793f4f7e, 0xbd48c4db, 0x0ab7df21, 0x026b4e7f, 0x099f23d7, - 0xe0adadfe, 0x9ecfcef1, 0xfda7ccb5, 0x1c343181, 0x6375c5f7, 0x2ddc5d38, - 0x71d751e0, 0x46c1a187, 0xdf9fa9ed, 0x73e3df02, 0x27e7d02c, 0x64852923, - 0xd7ca25cf, 0x0faa57f9, 0xbfa026f5, 0x1f45e6e7, 0xeb1f382a, 0x2d432698, - 0xfe69f3cd, 0xf91d561d, 0x6c6d6cbd, 0x38bffb3f, 0xe02ec26d, 0x59dd907c, - 0x3922e39d, 0x8b0f7260, 0x6bb387b0, 0x27182d7c, 0xcfad7ebe, 0xbe3c07ad, - 0xb4e8ea7c, 0x727e5041, 0xf84c52a4, 0xcf5c2bd7, 0x4e346df9, 0x81c1fa3d, - 0x3e0b768f, 0xf5307749, 0xdc03921a, 0x32a5501f, 0xaa7e46d5, 0xf513923e, - 0xee0f42ad, 0x736e7e11, 0x764dde5f, 0x26bb676a, 0xed061f62, 0xf72a366c, - 0xf310fde5, 0xe7f8674a, 0x1971de93, 0xa467be69, 0xf27e603c, 0x8b7e4a7b, - 0xbca11bf6, 0x57d1fcc1, 0x285de59d, 0x3d33e51f, 0xefe4bf8e, 0x74b8fbe2, - 0x15ca174f, 0xa35537b6, 0x95c9e20f, 0xe79f3703, 0x0f95fb7a, 0x901b0e89, - 0xdf7c710e, 0x5ede8d49, 0xe815c24e, 0x890fa5f0, 0x7177970e, 0x55d0daf9, - 0xd4fdc46e, 0x69d7e10e, 0x7484f410, 0xbfe8fb84, 0x9c69933a, 0xe1a1c986, - 0x0bcea728, 0x12ff3bba, 0x3a43b7a7, 0x0e01f91d, 0xdedd1eed, 0x8fd40ca2, - 0xf0978d4a, 0xe6f800dd, 0xa3daf376, 0xd7d56768, 0x6bf23730, 0x07e0a743, - 0xbe117bb0, 0xcbd55d0d, 0x6941bfb1, 0x0ddfc933, 0x41b4c976, 0x63a86e50, - 0xd96fc8a5, 0x425e2abb, 0x7c5d60ba, 0x035d9e3f, 0x4dd22cf6, 0x9f5bbd5a, - 0xdb8f7a8f, 0x2c8fd7bd, 0x723bf6a3, 0xf2e7145d, 0xf38a3157, 0x19fb40ef, - 0x68d65df5, 0x36fb3f6e, 0x5cc5dd92, 0x6537e409, 0xd60d753e, 0x622ff06f, - 0xcd11d794, 0xb4292fc7, 0x5808680f, 0x56681f29, 0x1a7fb717, 0x9f1f38ba, - 0x4f91f093, 0xe4adcf43, 0xc4c17f8f, 0xd0fe11fc, 0xce9a5f37, 0x268becf5, - 0x359fb3d2, 0xb0c7d87b, 0xbc85b7a0, 0x6dac7097, 0xdd21d7cb, 0x09937632, - 0xcc4cb1e7, 0xf5c0cda3, 0x03d0b246, 0x3cf8db05, 0x77e174d4, 0xa789d74c, - 0xe2e79b51, 0xe17f93f0, 0xc88f189c, 0x39e85d22, 0x797eba18, 0xeea4f890, - 0x9a5fde19, 0x677853c9, 0xfb4abd04, 0x0b1e9a28, 0xbbd9b8c4, 0x4c282a0e, - 0xd1cd77b2, 0x35f5f9f0, 0xeb08d82c, 0x2e977ebc, 0xd91c6538, 0x9e490b4d, - 0x58b237af, 0xd2232af9, 0x9556fdb9, 0xbf442dea, 0x36cdd576, 0xb93fa477, - 0xb3a3c12a, 0x24571da0, 0x12ded8fd, 0x4a9d1b8c, 0x6f11bbb7, 0xd25dd2e3, - 0x5bd8d30e, 0xdcdff703, 0xcda1bc0e, 0x1ff70e3f, 0xf309f581, 0xda09ae29, - 0x0edcfc8d, 0xf7fb8f68, 0x9cfed7dd, 0xb85bdfef, 0x070402ff, 0x6f5499c9, - 0x9d8ffa09, 0x5cb5de05, 0xb1ddd93f, 0x93aaf3d6, 0xcdc0e7af, 0x3ee216b7, - 0x8dae61b1, 0x5781e1f8, 0xde9ca594, 0xbee21140, 0x83f9c7da, 0xe13c7f01, - 0x3b247a22, 0x1bc9a1aa, 0x9c8f4d88, 0xaec01a5f, 0xe81b3b42, 0x93b70d71, - 0x13f38c6d, 0xbfb94ba7, 0x6915b947, 0x8d3e4acf, 0xbf497be6, 0x35ff7cfd, - 0x81bcfdf9, 0x8079e3f3, 0x3f7bd203, 0xe9ccbf9d, 0xe07aeb7c, 0x15bef847, - 0x4225b1f8, 0x7fef47fe, 0x1fb89e70, 0x1ef6f290, 0x3a5177a7, 0x6fdda1ca, - 0xab50c66d, 0x2f0d8f94, 0x397e196f, 0x958ccbbb, 0xf0335fa1, 0x60fd246b, - 0x445ed68c, 0x09ea3f4f, 0xfed8baeb, 0x6dd2bb8f, 0x3f3fcddf, 0xaee52f30, - 0x7981d2f4, 0x73a8e929, 0xadbb6f10, 0xa58fb401, 0x3e7a291f, 0x499f044b, - 0x03fdca7c, 0xfeb021c6, 0x37ef82fd, 0x888f7a89, 0x84bec467, 0xf3a5c1f8, - 0xf679487d, 0x6c91f471, 0xb5f97df7, 0x2f5238e4, 0x8c8dd346, 0xaa7ae0a3, - 0xd7afc4c7, 0xcfec5fb6, 0x29f8e8a2, 0x800b5fc1, 0x6dde7037, 0xc417e086, - 0x19d8778f, 0x99f813e5, 0x71e31527, 0x7ce08daf, 0x386fb234, 0xfa66b7b6, - 0x92ba44be, 0x8f7c5d7e, 0x115aaa71, 0x6bddacbf, 0x7f9e4408, 0xd18337b9, - 0xb376bd38, 0x91fc0f5f, 0x87dbe99b, 0xcc15fded, 0xf33d441d, 0x2b8a168f, - 0x8a5b8181, 0x8591a6f2, 0xefce1112, 0x205efb25, 0x0cf7d5fa, 0x39e3bf47, - 0xdf0e3425, 0xdafe109f, 0xfb5fc213, 0xcf7bd77e, 0x17ad02be, 0xf16e72bf, - 0x5ece918f, 0x7d21e4b4, 0xe7f4b09c, 0xdda125bf, 0x92b9817d, 0x690e772e, - 0x55ef5991, 0x2767fc23, 0x7ffdb1ec, 0x373c0b6f, 0x532b788a, 0xb7c3ed19, - 0x19f97067, 0xe3c4bf3e, 0xb4ebefad, 0x1cf937fe, 0xdfe1c193, 0x501ce719, - 0xd7df0661, 0xfce10e74, 0x50aed7d8, 0xdd66afbc, 0x41eb3ffa, 0xb5acd42e, - 0x9f09e907, 0x71ab8ed1, 0x283a83f8, 0xb970309f, 0xcd737f04, 0x07fd6165, - 0xc849d4f5, 0xc5077e33, 0xfd0a96bf, 0xcde9acb5, 0xa15fa1bf, 0x49e66546, - 0xf2c71845, 0x9f041e1e, 0x4f2db53e, 0xf2bff144, 0xa3a67747, 0xd458ca7e, - 0xa6c1f226, 0x55fed03a, 0x2fe8373c, 0x6f672f59, 0x132764a9, 0x1ede001d, - 0x22f6f0cc, 0xe24a2f1f, 0x7745c17e, 0x08fe035a, 0xf057b879, 0x7cfd3461, - 0xcdbce710, 0x01151997, 0xaa616fec, 0xefd46ff7, 0x7234e79d, 0xfa12bced, - 0x5f4823c5, 0x4fddd877, 0x22f2eef0, 0x05d263f3, 0x0e316bfc, 0xb7b1a204, - 0xbaf867b0, 0xbee3a47c, 0x5fa1dfbc, 0xf0e4dbab, 0x91bbf0bb, 0xf176cbbe, - 0xe3f141e2, 0xd2232e40, 0x8545c347, 0xf76961e8, 0xae51c79b, 0xa221a837, - 0x1b66a593, 0xa2e1b1e1, 0xd5a9e9ca, 0xdb243670, 0xa4d7ee03, 0x6032d27a, - 0x277bfe9e, 0x093c5325, 0x17c389f8, 0xe39c452a, 0x37c332f8, 0xf7e00328, - 0x36f13590, 0x305d7fdc, 0x8f3092bb, 0xf408d1ad, 0xe7753570, 0x43d84735, - 0xa5aec72c, 0xfeb7ee83, 0x6e5af386, 0xaf5119f6, 0xd134f0af, 0x4945b179, - 0x98c752c1, 0xd24fbc48, 0xf5fd1a5f, 0xc8497ef1, 0x3c8df797, 0x9d20646f, - 0xcf6c3c73, 0x39b2f510, 0xc79fbcbf, 0xe7c39e6a, 0xbb427828, 0x728887f7, - 0x170f2891, 0x7979d2f5, 0xf797e09a, 0xd17af1c7, 0xe3152ce3, 0x99e1997c, - 0x7682708c, 0xc7d22341, 0x673a166b, 0xfe404ac4, 0x935bbca1, 0xc82c764b, - 0x770869b9, 0x4c982718, 0x67a44cf5, 0x41c81358, 0xa96f67c0, 0xb5b3e08b, - 0xe305e81c, 0x289aaf41, 0x2bf1241e, 0xcf8d1af1, 0x77ca1985, 0x181f4fcb, - 0x51985ebf, 0xcd7e303a, 0x17c250d8, 0xf38c4bd1, 0xf5f0f11f, 0x03c73b6b, - 0x0cf2ebf0, 0xb1c183d2, 0x49b37c91, 0xb5ca51c0, 0x78b413f7, 0xe39d3cfd, - 0xbbd45ea1, 0xda1f7684, 0xe23eeed1, 0x7853f7bf, 0xae02b4fd, 0xfe5da497, - 0x5f2e024f, 0x529f6ba6, 0xd1fb44cf, 0xe2f214bf, 0x47ee74cb, 0x8ddebc07, - 0x09fa95f3, 0x19304ce4, 0xebd178f8, 0x6c339226, 0xd5e51f63, 0x83ffbd40, - 0xea645af0, 0xf41535bb, 0xdec10fca, 0xbb511631, 0x0647284b, 0x48c7efec, - 0xd433b0ba, 0x0e19addb, 0xf4941f6e, 0x48d7b8f1, 0x0ca5aebe, 0x657287e4, - 0x210c63fc, 0x6bf0e40b, 0xc142bf22, 0x6214aebc, 0x07f61767, 0x8c97ff70, - 0xa3dc30d2, 0xe8213bc7, 0x450cd1e0, 0xb215bc25, 0xaddbc442, 0x5f6e7eef, - 0x139e5d0c, 0x4d9365e7, 0xe7ec76be, 0x916fddec, 0x18c27e9d, 0x8b66de1c, - 0x7c18ddf1, 0xfc2521ec, 0xf4a7b6fd, 0x98d5e37e, 0xc1f67e7f, 0x4bdd619b, - 0x1c6ef47b, 0x5f3de972, 0xed1e33bc, 0xc5031eec, 0x6fdf406b, 0x4dde7153, - 0xa13caedc, 0x67c1d2d3, 0x3df76977, 0x907a0baf, 0xdca572e7, 0x157cfa91, - 0x93797373, 0xcb1bb890, 0x3b71dd1f, 0xce5dcb9d, 0x003d87bc, 0x666bd3f7, - 0x3b7c5d92, 0xcf5e51f3, 0x39ed56b2, 0xda6d15db, 0x073bedf2, 0x3925c39c, - 0xfd102abc, 0x2ba5f85e, 0xf3fbeb63, 0x333f2e82, 0x7afdf88a, 0xfdf8cc53, - 0x09fc85ef, 0xb4fbd9c7, 0x2f57fbf1, 0x8c6fbf1f, 0xed87df8a, 0x3df8e888, - 0x6113f7ef, 0x91bf606f, 0x2acffc71, 0xa3e3af62, 0x58b7690c, 0x9f19f935, - 0x125bb00c, 0x45e37be9, 0xd8f99c4b, 0x2b67fde8, 0xd7d38f63, 0x5f368e3f, - 0xe79edc20, 0xb5fdc809, 0x8bc693a4, 0x6567a459, 0xe1c7da59, 0x3df43976, - 0xf4babcfa, 0xf8be4b6f, 0x2ce66158, 0x176d47f2, 0xf29bbc76, 0xbb463f33, - 0xba72f908, 0x4c10b5eb, 0x278fd971, 0x8487570e, 0x1d7a26f9, 0x42675f40, - 0x98d8f211, 0xfd234f69, 0x3a6e66eb, 0xfee82797, 0xe8abbbd6, 0xbdffcf7c, - 0x322332a7, 0x53f72a6e, 0x8f69460d, 0x96fa34d9, 0x65e3e945, 0x1d916f5d, - 0x70d7f606, 0x7a7f3e14, 0xc3d26ef5, 0x1d37992b, 0xd5f7bde9, 0xe56e7411, - 0x3961eadb, 0x4bfc9b9f, 0x35bf3c0c, 0x3987ec8d, 0x75373e62, 0x67503b73, - 0x1c6818f6, 0xd239730f, 0xe7cd8b69, 0x8554420b, 0xf3fd75f2, 0x631de747, - 0x15fcc493, 0xbdf00f6c, 0x52d93c4e, 0xdbce265f, 0x31eae384, 0x8990260d, - 0x6e8996cf, 0x28a73e17, 0x83cf955e, 0x6b1a79e3, 0x3afac1ca, 0xd7cf4873, - 0xc7483309, 0xa2f0fdf6, 0x37945db2, 0xeb70bdce, 0xb36f7c0a, 0x8a313c93, - 0x04cf4c79, 0x6dfc88b9, 0xb75c6666, 0x4d3c16c9, 0xf4f133f1, 0x8f88b857, - 0xf91843fd, 0x07581241, 0xd9b53f9d, 0xb171f9ce, 0xb050e60e, 0x085c716c, - 0x9ce27ee2, 0xf3c7e6c3, 0x672f20c4, 0x5f3fa265, 0xc44ad5f9, 0xee67c80b, - 0x5df78a17, 0x11f3f20d, 0x88a5de42, 0x7908b5f9, 0x8adcc597, 0xe480c7b8, - 0x95f6fddd, 0x267ee037, 0xa3f7798d, 0x71387bbc, 0x32fdc506, 0x93e68f98, - 0xc8d5433a, 0x5b57a72d, 0x46af98ce, 0xe7053bcb, 0xbed3e597, 0x9413b337, - 0xbd04a497, 0x69529799, 0xfd12361f, 0x37210631, 0x3e78598e, 0xcf3166c2, - 0x8853333b, 0x78598e6e, 0xb6b7c25e, 0x7ddadc5b, 0x3f0a437d, 0xdd3e7fbf, - 0xc0f1c66c, 0xe113b98e, 0x07cc7607, 0xdfce167e, 0x41d29c2c, 0x6f9b0279, - 0xe01bdc54, 0x6bbb66fd, 0xeba40abd, 0x7f70a99f, 0xc728ea8f, 0x3cf69c7c, - 0x44f31b87, 0xf7be451b, 0xf6a38b66, 0x9a63f219, 0xb7d63d78, 0xed96e319, - 0xac0e1d5b, 0x37d95697, 0xaafb88cd, 0x9bb1cc15, 0xaff7a0c5, 0xbe608f80, - 0xe032c73f, 0x63f41149, 0x85bae23d, 0xefbe20d6, 0xf0177fc1, 0xdc3294f2, - 0x82bff2bf, 0x773a42ee, 0xd27a3cc9, 0x85dd8d97, 0xbc60d86f, 0xe485b982, - 0xf256f7af, 0x72132fb8, 0x571cbc60, 0x61b5d9f0, 0x85efa7ba, 0x5bb43ca2, - 0x4cd37ff8, 0x80ebae3c, 0x91c4ca21, 0xc69fac43, 0xe4cdc1f9, 0x6bd3e71f, - 0xfb0ff858, 0x4ff70cab, 0xf86a6972, 0x60ef9873, 0xbbb322a8, 0x8dea0ea5, - 0x91fb8357, 0xcf15afaf, 0x543cf142, 0xe5e9237e, 0x65cd9d1e, 0x373e71d4, - 0xc3aba017, 0x94b847ab, 0x60b4b639, 0x4129d73f, 0xd8cde67a, 0x9fd382de, - 0xc94cfc23, 0x9e00c699, 0x00996b37, 0xc8bf2678, 0xffa30f9f, 0xac2fff5a, - 0xcc74f118, 0x279ef520, 0xb9ffe789, 0x0ed53d68, 0xce97593e, 0xc22e7b33, - 0xcf3f28f9, 0x8b74d0c6, 0xa997fef8, 0xd7974955, 0x300f3cbb, 0xe5cf4b25, - 0x871e0ce3, 0xa66f9c6d, 0x7146e5bc, 0x7d53030f, 0xf08c3ff9, 0xc5b8c8af, - 0x7f3606bb, 0x46fd8c5f, 0x07b7164a, 0xfdc0dce6, 0x1f228dc2, 0xcc4f7e47, - 0xbfb27ee2, 0x377b4e64, 0x1e3dec93, 0x949dfd6f, 0x48d9235f, 0xf2115f94, - 0x5f248fe5, 0x278edfca, 0x85dfb47f, 0x29e799fc, 0x40bed036, 0xef2921c8, - 0x68ef22bd, 0x1018f301, 0x1ee23d4f, 0xabe5a395, 0xccdd0e48, 0xf7fef47c, - 0x00ff3c15, 0xfd80d308, 0x6b4334dd, 0x6af3cd3f, 0x8fcf37cb, 0x3e38afb6, - 0x7c0bb8e4, 0xa473efda, 0x6b433c9d, 0x87fa2f27, 0xcf4992af, 0xfea2fc67, - 0x3e70e0d2, 0x3e546351, 0x27c88351, 0x3c2aec6a, 0x4f911694, 0xf3cdd8d4, - 0xaeba1a89, 0xedc44f94, 0xb029af29, 0xde24e31f, 0xec94d25a, 0x727f910d, - 0x8a4ff310, 0xaf6e74c2, 0x0c3cf3b0, 0xa2bca1e6, 0xce95871c, 0x8aeab45d, - 0x9adb8fc8, 0xddf8d768, 0x5577aeb7, 0xbfe93d61, 0x4843f995, 0xc3f6b137, - 0x5f7c59d9, 0x7ee143b3, 0x3302ff74, 0x059d3bed, 0xc15c4d5e, 0xd1c767a9, - 0xa66ef8af, 0x3f27d64b, 0x2f830ec9, 0x019e18ab, 0x8979d185, 0xb67af6fe, - 0x5190fc91, 0xea99ca72, 0x338038a6, 0xf5f92c69, 0x921775e7, 0x2cd9923f, - 0xb84a61ee, 0xdb7379ff, 0x69ebcc55, 0x97576eec, 0x3774c2db, 0x43ec4b36, - 0xf48accac, 0x7bd7efda, 0xbd7e44ce, 0x30b79364, 0x19d7da0b, 0x8bbfe483, - 0x1f7a57a0, 0x2ede5f4f, 0xe150c5e8, 0xe602b05d, 0xd18efbd7, 0x0a6bfb8d, - 0xcfff41cc, 0x7e4c94bf, 0x230e7549, 0x9cb1b53d, 0xf45e93cb, 0x3e3ac193, - 0xfaf7e64d, 0xa466ac6c, 0x4ca7cf5f, 0xc55e3a23, 0xe83d8702, 0x7405db47, - 0xd2cf7918, 0x8eb96d1e, 0xa9fe9075, 0x3d00667b, 0xf2947c93, 0xf4b99eb8, - 0x741b8c06, 0xa1b3db6a, 0x285c395a, 0xbcf147f4, 0xff982da9, 0xf2e3ac50, - 0x0f772d91, 0xf5fb439a, 0x2c4f8e45, 0xa17f7228, 0xebaece5c, 0x73d29fb5, - 0xa17ae7fe, 0xad1ff454, 0x3d854abf, 0x17e41937, 0x7da56fee, 0x7ca9f506, - 0xcfadd750, 0x59e785d4, 0xbb49da22, 0x890bea50, 0x8c09f2af, 0xbbb579e1, - 0x1a7c84b2, 0xbe2086c2, 0x13e27fa1, 0x29583705, 0xf71fbfd4, 0xf18ad785, - 0xa8fc1e80, 0x733afdbf, 0xb36be900, 0xd2fa44d2, 0x3c3ff68c, 0xd23e2ab7, - 0xe35eff0b, 0x4c7d23d7, 0xdd374d64, 0x9926f500, 0xb728ac7b, 0x31fe4e80, - 0x585a7e92, 0xa29f6f30, 0x7efa23a1, 0x98edf936, 0x5af52474, 0x9edcf7f0, - 0x74bcc599, 0x0fe793cf, 0xa83aeedc, 0xd8267df0, 0xeed1079f, 0x93375b7a, - 0x2c2664e8, 0x3955eb03, 0x9e9ff8b4, 0xdf472da9, 0x5ad0c50f, 0x48744328, - 0x9c540678, 0x51bdf44f, 0x98f7291e, 0xb3e5ee56, 0xf8de78af, 0x423fc396, - 0x1d7583ff, 0x0ef6891b, 0x8fc4aa58, 0x27b0f4d1, 0xb78f7beb, 0x118ac9ec, - 0x7e15e96f, 0x68586be5, 0x40ca33e5, 0x687f3b7a, 0x82333e9d, 0xbc7f252e, - 0x1379e06c, 0xae3cebca, 0xc6ccc135, 0x252e1104, 0xf928ffdc, 0xd3a41ae3, - 0x95fd3094, 0xa487f789, 0x06cc197c, 0xd75dbd23, 0x01ea0965, 0xbfa2853f, - 0x8afe906b, 0xdc89f6c2, 0x184cb477, 0x98f96740, 0x4cf60e17, 0xb495d201, - 0x8e958a4f, 0xfde73c16, 0xb6f74bfc, 0xe8237ce0, 0xc3842dea, 0x8ae80559, - 0xf4036afc, 0x147bf6ad, 0x4bfc49dd, 0x359cba7b, 0x6e677ed1, 0xc1b3d702, - 0xcf49dbea, 0xba24b882, 0xa70e737b, 0x21e62abb, 0x5a672bba, 0x6b34a97a, - 0x0974d1cb, 0x74b4ea23, 0x8bba23e7, 0x7478d7a6, 0x4ee91837, 0x2bd4dbea, - 0x48e7ddd3, 0x8fc5df77, 0x3eee9039, 0xa7c672cf, 0x937a68bb, 0xc59f6cf2, - 0x75768951, 0xfa428d63, 0xa19df8a1, 0x511e582d, 0xf6764f9f, 0xd93764be, - 0xfc4d8ddd, 0x478f497b, 0x0533798f, 0x7cf7c56b, 0x1b96256f, 0xe877c1d7, - 0xcf18f4ba, 0x0f7a19ab, 0xa1b85eff, 0xbfbc0de9, 0xdbcfd1a0, 0x337a7cbf, - 0x6c0a879d, 0xdbcbed16, 0xd8dcb12a, 0x8a7fdbca, 0x31abae71, 0x82d02dbf, - 0x96daafef, 0x6fdbe6ef, 0x114fd76e, 0x3ca7ddeb, 0x6bb506f7, 0x3f6eede3, - 0xe4604e6c, 0xfaf6e027, 0x29ceb164, 0xd33af8bb, 0x867ebe3e, 0x4563e80b, - 0xb9ec9f9f, 0x6575744f, 0xece2ef24, 0xb695cbb3, 0x474e7c1c, 0xbc47a639, - 0x43f55bbb, 0x37741c78, 0x3675710c, 0xf8c8d3f7, 0x5429e621, 0x5717d847, - 0x443b7367, 0x614f4bd6, 0xfd8d7e74, 0x72fe4ecc, 0x3e0cdf19, 0x07d414c4, - 0x976146b8, 0x4e778cc4, 0xbb22682f, 0x1960fa62, 0x4ba90ce7, 0x4bc2dc61, - 0xe58b4f9f, 0xe6cb2a47, 0x9129f3f6, 0xd7df2177, 0x4875f204, 0x4890fb17, - 0x90f0fce8, 0xdb9ed077, 0xe734cc97, 0xf3e5f6dc, 0xbcecd4f2, 0x01cd6e7f, - 0x549aeaf8, 0xe58bf7bc, 0xf2b79429, 0x4c161e83, 0xff381c4a, 0x1a0b2ae9, - 0xcf8a0f29, 0x518b657f, 0xe5c257dc, 0x3f813cda, 0xd1186936, 0xa7815cef, - 0x17a16cea, 0xca31598b, 0x6f0279a9, 0x1937343f, 0x336ebeb8, 0x798fc944, - 0x1e3f28d9, 0x6bcf6b8e, 0x97c947bf, 0x4aee311a, 0x62afc761, 0xfd3fe47d, - 0xa7f1d844, 0xfc76e61e, 0xfe41d66a, 0x719fded3, 0x961ebe3b, 0xed12f487, - 0xabddad07, 0x6877d72d, 0xdea00dcb, 0xaec6ffb1, 0x8633b928, 0x1f7ba5fb, - 0x3f432fae, 0x77cecd64, 0x235dffc8, 0x2b404ce5, 0xe740c067, 0x51a1e672, - 0xd6fabfe4, 0xd819e3f2, 0xf26995d5, 0x76c9ef4b, 0x5e77f846, 0x0d2e79e4, - 0x7a11fb8c, 0xc16f23ed, 0xd28b2c7d, 0xa572d14f, 0xe915c850, 0x5bf290ff, - 0xc6429bca, 0x77ec14f5, 0x9b60f1df, 0xe1ef3b28, 0xc4afa16c, 0x4dfa4dfe, - 0x88547da4, 0xd7d211f6, 0xba2226a8, 0xbf727eb0, 0xe847d26d, 0x662505a5, - 0x19917bc4, 0xa6e11bf8, 0xd9f58db7, 0x68f1f434, 0x83f7e5f6, 0xf451efda, - 0x0b63f723, 0x84dcfd05, 0xff181891, 0xb81f720f, 0x5ccfd38a, 0xf4843de6, - 0x9cd5fbf3, 0xf0bee47e, 0x3d03ef9b, 0xa07dc8fa, 0xdd7e4fdc, 0xdd3f60fd, - 0x863ec058, 0xe95cb1e7, 0xfdf1e017, 0x45d38546, 0x3ddf9cfd, 0xf2c2c556, - 0x733368e2, 0xb97086ab, 0x8cc9a665, 0x0316977e, 0x99cd2fdf, 0xd2d97ef5, - 0xb413f908, 0xb8401f97, 0xf9276eb1, 0xdaadeb77, 0x3d2b3671, 0xf711fd77, - 0xc95a8f55, 0x08e174af, 0xc2e59323, 0x0f9411ae, 0xc78199fe, 0x6e7ce55b, - 0xb5f7bc3f, 0xb95bd410, 0xcc6296ee, 0x0255a82f, 0xb7c1d62f, 0x77beac0f, - 0x756bbf91, 0x672f7141, 0xe427c50f, 0xbafdf1b8, 0xc6c7927e, 0xf73f5c03, - 0xdf940929, 0x4787ef0b, 0x38fee9c6, 0xdcefcb88, 0xb807df4c, 0x5b47a91e, - 0xf827f3fa, 0x1b30b413, 0xa7ce1294, 0x704de708, 0x985fcb7f, 0x13798ae7, - 0x04e2231b, 0xbe663ed0, 0xcf2179db, 0x01726147, 0xba6567cc, 0x7fd717a7, - 0x4f85c44a, 0xa9e23889, 0xfc571e44, 0xfe7d7f7b, 0x7ae20db4, 0x3b8894e8, - 0xc6d14a9e, 0x44bd649b, 0x6cd93cf1, 0x60346ef6, 0x37799ebc, 0x3d70fe82, - 0x7ca26a64, 0x5f1c4595, 0x6b252fbd, 0x1ac811ee, 0x106a3e54, 0xd399fbb4, - 0xe3041fab, 0x9ed36f2c, 0xf715ea83, 0xba0af6db, 0xa7f0b5e9, 0x506b371c, - 0xd76c28f5, 0xb3df80bb, 0x289e5fda, 0xbfea5ecb, 0xc910baf7, 0x8ff2fea3, - 0x3a9ce242, 0xf8c893f7, 0x61f8bc40, 0xfa30bc74, 0xbc74699c, 0x37e4b17f, - 0x245fef11, 0x6ee2d4e4, 0xd5b86f1e, 0x820f36cc, 0x6775b7ef, 0x26b8fc50, - 0x135c3fd1, 0xbf5bf7ef, 0xa4879e51, 0x9edcdecf, 0xcff8f8fe, 0xf5e3e222, - 0x2f5a3e22, 0x5da9d7d7, 0xcf0164df, 0x3e3e31ef, 0x60739079, 0x9f3a3c7c, - 0x33b445e2, 0xac3c610c, 0x55b87071, 0xd12aebe9, 0x39617c4f, 0x35f73ca3, - 0x416b2d6f, 0x2d9af23f, 0x615596e2, 0x380bd777, 0xd3975bc7, 0x8d2e63ab, - 0xb9813ebf, 0xe593d622, 0xc994d14b, 0x33c88f92, 0xad93541d, 0x34db9f69, - 0xf07f5344, 0xef9a51ba, 0x4d22fef9, 0x1af5a0b9, 0x6d61fd4d, 0x88f29a15, - 0xea6bd79d, 0x4921b217, 0xa23b6fe4, 0xbb125f47, 0xf347302a, 0x85def47d, - 0xb29ff69a, 0xa0931da6, 0x7b45a75e, 0x7bf3332f, 0x8594c67a, 0x76c7a9f3, - 0xc3f4d52c, 0x29504a82, 0xf633df0b, 0x79a7b899, 0x878f0f79, 0x5ab5dd5c, - 0xbead4e33, 0x1d18f08e, 0x7d622def, 0x086e37e4, 0x1b20ee28, 0xd55dff18, - 0xaeed4ed5, 0x78c8f764, 0x2241c6c8, 0xb2cd97de, 0xd3475d39, 0xc3ec8d85, - 0xe4f4bb0b, 0xc3642c7f, 0xf0449a1f, 0x6b80b032, 0x302efe20, 0xf0bb17ee, - 0x798ddd8c, 0xb5bfb745, 0xca63e68c, 0xde05d2d4, 0x5eb9181f, 0x5d2d48eb, - 0x3a5addd8, 0xa5a09a48, 0x27786883, 0xc174b47b, 0xcbbff042, 0x86753bc0, - 0xb7fe6e96, 0xf081dce0, 0x5be186b5, 0x62d3d07c, 0xbcf1b823, 0x999f6935, - 0x1d143d84, 0x4e7690d7, 0xbbb09070, 0x2e323f45, 0x93f159b1, 0x771fd55d, - 0x0bcc109c, 0xd53da3e6, 0xc95fb8c4, 0x6fe5107b, 0xbd24bf0c, 0x9497e78f, - 0xc09b9d70, 0xf32d67f5, 0x663efc92, 0x93a4fee1, 0x9fc8abd5, 0x913592b4, - 0x9cd9fddd, 0xe8efc2e9, 0xca577aa7, 0x9f901853, 0x8b29f600, 0x06aed7f0, - 0x1fef1a8b, 0xd2a7868a, 0x78ed04ad, 0x4b75986e, 0xfca3e07d, 0xedde0f15, - 0x68ff89a9, 0x51e65fed, 0xb497e522, 0x1278e587, 0xc9ae529e, 0x49ac4c71, - 0x117c899f, 0xc8d8e725, 0xd693f8e8, 0x41fd239f, 0xe3238e32, 0x9bfed14c, - 0x55b8bb08, 0xc1d2718f, 0xce782df9, 0x21e1d8b7, 0xeb29613f, 0x4fdf05b9, - 0xa8b47730, 0xb8bfe12e, 0x2ffbf58a, 0x2babeae2, 0xf26fb5c4, 0xf247a12b, - 0x65b3c607, 0xff961c7c, 0xf1a11ff1, 0x8b95c524, 0xf2f398f3, 0xd3d22708, - 0xfba6bf40, 0x8fd02bf8, 0x8a97d75e, 0x3130aaf5, 0xfdde223d, 0xf5a212a6, - 0x367990fc, 0x6fdb9e45, 0x6ed31d60, 0xe8327f21, 0xa727bc49, 0x58bbfb93, - 0xac3db457, 0x0759bf92, 0xafba412b, 0xde711165, 0x2a77f0fc, 0x659607eb, - 0xec95d21e, 0x82f1a789, 0xe0a3ca72, 0xc84c53f9, 0x8cffb941, 0xf993cfb7, - 0x4f7ef218, 0x94547799, 0x1c75f823, 0x03fd871b, 0x94e595bf, 0xf8017fa2, - 0xc7e48953, 0xfa253cfe, 0xa31f803e, 0x31f32fd6, 0xf212f6f4, 0x5c8b2d1b, - 0x8780d7ef, 0x9c7e5bb4, 0xc8e9e8c3, 0x3eb3d171, 0x3d6fc4e1, 0x47a4b9f8, - 0x68da3f93, 0xfa0d0d84, 0x79145e13, 0xbb5a1d81, 0x9d1c96fd, 0xf7df1b80, - 0xf15e095c, 0xf8f221f1, 0xaebe3e04, 0xf8f3261d, 0x0c971c24, 0x0d0afb84, - 0x8ff7fb5c, 0x115f70fd, 0x2e12ee0b, 0x7e7b4ae7, 0xdbd2f881, 0xbc23a58f, - 0x577aa617, 0xe3dcfd63, 0x5d144fa1, 0xfa555e78, 0x7b8794b3, 0xe74f4ba1, - 0xe3ae1aff, 0x25e1b072, 0xf386893d, 0xb38a26dd, 0x41bd74d6, 0x66d9e176, - 0xfc06b410, 0x72180cbd, 0x08fc65d8, 0xb78ef051, 0xd9eb924f, 0xe5f62390, - 0xef32fd62, 0x39b9d607, 0x475e6627, 0xdfb41c3f, 0xf4aa1c05, 0x1cf09263, - 0x92be7f59, 0x791797da, 0x3af45f5f, 0xfe78722a, 0xf7b329db, 0xc3efec3e, - 0xd81d9c9e, 0xfbbe955f, 0x67c23670, 0xbbe742ad, 0x79f898a6, 0x5e712cdc, - 0xc9a8426f, 0x3399e78d, 0x667df873, 0xf7a47e23, 0xfdf91c62, 0xe0a677b5, - 0xffd93439, 0xe7474508, 0xee7b1947, 0xc12c7f83, 0x3722e6f8, 0xd8bf6fde, - 0xba2fee24, 0x002c1acb, 0x91baf239, 0x186547df, 0x66e744d2, 0xe4f592fa, - 0xb3d34cd7, 0x727748a9, 0xadbcf2de, 0x01f78f7c, 0x7cb15e60, 0xafa5a53f, - 0x7bfa0d78, 0x75c83d04, 0x2beca94f, 0xe185b26e, 0xa33cf32f, 0xf82553e1, - 0x1b43ee43, 0xd05b5ef0, 0xbccde7bf, 0x6daf7d1c, 0x5874feff, 0xf6363dff, - 0x837eb8c8, 0x1e3493c5, 0x6bdc51f9, 0x278717fb, 0xa477df89, 0xbcf6a7bd, - 0xbf97b7c8, 0xdeef1253, 0x51ccff9b, 0x827b97be, 0xcb85e5e2, 0x7078ffbc, - 0x99564869, 0x739d357a, 0xdeae5ef7, 0x8fadff2b, 0x28bedfb9, 0xd3dff7be, - 0xbcec6af9, 0xceb15ec5, 0x88617e70, 0xe7f729ce, 0x7e54be2d, 0x1a477bd9, - 0x08d23ef0, 0xf6bcc838, 0xb48fbc06, 0xd0bf4638, 0xe576cb9f, 0xc4aa877b, - 0x8f301abc, 0x3df23530, 0x38f0b7a7, 0x302f2269, 0xfb7c8894, 0x9d3d2ecb, - 0x11e5ffe3, 0x31dd8cdd, 0xcb9b9de6, 0xa9ca32e1, 0x0e8d1f12, 0xe3b5fbf2, - 0x79e793d5, 0xe8d8b9e4, 0x845675f9, 0x63f9c56e, 0xf1ac729e, 0x3f7cb91c, - 0x99dde72b, 0xf0d1f1c2, 0x9bdf899a, 0xf27cf2aa, 0x4ad094ce, 0x168713e2, - 0x1e04c3cf, 0xe50faf3b, 0x99b2b9d1, 0x8f10efdc, 0xfaa7261e, 0xc8be51ca, - 0xd4caee7b, 0xc111c526, 0x87a2578f, 0x1af5dc30, 0xbb840ebc, 0x7ecbbe91, - 0x7c151f4f, 0xdc363ccb, 0xfa112dcf, 0x5a9ec96e, 0x7ee587b2, 0x3d4ef4e9, - 0x669c6fe5, 0xba72ae3c, 0xd0fda14d, 0xeb631f52, 0x7cad2e40, 0xaa3378a2, - 0xb09925ae, 0x1efe1496, 0xe9661f7f, 0xbaf8a8c6, 0xbd495fd8, 0xbe5fc72a, - 0xd7176b4d, 0x467f6db0, 0x51f4e9fb, 0xb0563f2e, 0x2b3fd226, 0x57f6d01f, - 0xa7d667b3, 0xbce8cf38, 0x8fc21180, 0xec572d37, 0x1958ca57, 0x4f358fea, - 0x9fc46e7c, 0x17c78960, 0x434ffbf8, 0x7ddff187, 0x8efe27c2, 0xc96f3e08, - 0x1720fcf5, 0xf2ef3efd, 0xf5ceaef9, 0x7f45c9cd, 0x7e7cbbc9, 0x702eea17, - 0x8d2bb33d, 0xfd8b5bf4, 0xfaff922e, 0xdffe5cc1, 0x0035f78b, 0x71264c9c, - 0x49aeba6f, 0x4df6489f, 0x43ece880, 0x7e731de7, 0x26776540, 0xd3da43f2, - 0xbf6067d3, 0x1eada7ce, 0x72d6df5c, 0x2ffa214f, 0xf3f356b6, 0x8f1366a1, - 0x397e07df, 0x538600f1, 0xaf6c7686, 0xa39d1740, 0xfd107f7b, 0x3fbaad42, - 0x98bcc61f, 0x5f3cc9d6, 0xda175d32, 0x3c62283f, 0x899035a7, 0x68e77df1, - 0x9a4e6f7e, 0xcb90bcbe, 0x36276e7f, 0xe85c5c08, 0x627f202a, 0x17fa41af, - 0x2e742c3b, 0x2eff8eab, 0xf1c628c6, 0x70eaf32f, 0xf176910e, 0xf9a666d9, - 0x1d51869d, 0x4890d04a, 0x3c50a8f7, 0x30436ea8, 0x67d416fd, 0x4f14a94f, - 0x7b4bf393, 0xe302ab3d, 0xdd8f5266, 0xbfb838a2, 0x0bfdd84d, 0x71e3fc98, - 0x9e82f9b7, 0xff7b0816, 0xf7872b16, 0xc3cee652, 0x2ccd0b76, 0x76ac0751, - 0x2947654b, 0x90d6b3ad, 0x8c85768c, 0x47b7c51f, 0x1ac9fb62, 0xe7e7617e, - 0xe1be959e, 0xf419c9d8, 0x3f865d41, 0x693c85db, 0xffcfce18, 0x83cca1b1, - 0xd786caf1, 0x30efd046, 0x3c781299, 0x1996e41c, 0x843a11ef, 0xbdd61efa, - 0xc88b15ea, 0x73880a5b, 0xd8defccd, 0x453939c6, 0x78f11e74, 0x71ffdd1f, - 0x23ca10de, 0x847906fe, 0x92bea637, 0xe01fbbfb, 0xd90debbd, 0xf941d760, - 0x789fee74, 0x25684879, 0x92991bde, 0x47978977, 0x72c13e85, 0x6cc25e4e, - 0x5685172a, 0x3e3ca1ea, 0x7197932f, 0x36040a03, 0x6cf06f35, 0xc92dda3f, - 0x87702ec2, 0xc377bce8, 0x917423cb, 0x1e7758fe, 0x84676797, 0x3e4cf93f, - 0xc20e6dbb, 0xfaec647b, 0xded27969, 0xc9f5a36e, 0x2cf6caf5, 0xffbb7633, - 0x957e7210, 0xc53da738, 0x3c2d5aca, 0x044fe7fe, 0x1eec1c3c, 0x7fcbf141, - 0xfde14dcd, 0x4f74423b, 0xfa27ec8f, 0xb8e41c77, 0x7bfe15ab, 0xf2a3e759, - 0xcb977ebc, 0xb38c2be5, 0xea19c691, 0xe79be7e1, 0xfe2214e4, 0xc0aa6f00, - 0xc9f7ca9b, 0xd07e7ced, 0x13fefe2f, 0xf46287e8, 0x0afc1ffb, 0xe787e7ea, - 0x27274d1d, 0x5aab38c5, 0x2fb6dc78, 0x69e880b9, 0xf7dc558a, 0xc75da252, - 0x9f6e3cf8, 0xc592f3ba, 0xaf091d79, 0x69c6850c, 0x09cc7011, 0xf6339f0d, - 0xaffbaf9b, 0x8eeb4bff, 0xef0797c0, 0xc5d8396d, 0x9f1e37ef, 0xf485f1c7, - 0xe076429c, 0x677f4d76, 0x9fb547d6, 0xae5f28c0, 0xda80a521, 0x6fee2bdf, - 0x61d9f795, 0xdc71fcbb, 0x57bb45be, 0xfcc1a7de, 0x1c645993, 0x8cdeffb2, - 0x70bf710e, 0x286f3aff, 0x8874eb11, 0xef223a75, 0xcfe7ec33, 0x73797d63, - 0xb8e903ed, 0xfdfdfe1f, 0xfd12298d, 0x563cf869, 0xf1d7c87f, 0x1e5572f0, - 0x1bdf2797, 0xa33ce45e, 0xe70fd9e0, 0x7849f9a8, 0xbb537f22, 0x94ba5a31, - 0xf411ccf3, 0xf3bf8039, 0xe278e5bf, 0xbbfad97e, 0x7338be79, 0xbebae969, - 0xf9875f33, 0x07ddb209, 0x34a0c078, 0x21bc27ec, 0x7327ec4f, 0xbc9c4e58, - 0x339e6f47, 0xde917fa6, 0x7b27ef47, 0xd9efe593, 0xbd1afd69, 0x397bfe4e, - 0x7efc73fe, 0xfca36b83, 0x7a8f183c, 0x176e16ce, 0xf2da2fd6, 0x037e0263, - 0x797d54fd, 0x5312bf38, 0x3bf8f3c5, 0x4af3ab5b, 0x7760ab67, 0xdc552494, - 0xa6e50f99, 0xfc93c6c7, 0xf154192e, 0xf3c83e79, 0xe04d8f35, 0x7c5747df, - 0x79cb043e, 0x8a797913, 0xf79479e7, 0x9eccb460, 0x2bb6159a, 0xd173ccee, - 0x1d4afab8, 0x42676bdd, 0x63d60623, 0xf944dd7a, 0xf1ae1280, 0x5d26259e, - 0xbff3ac53, 0x03d3f4f7, 0xc04cbf8f, 0x1fd0ba7f, 0x2105fc28, 0xe82fe355, - 0xcfe7e44d, 0x92fd5f7b, 0x9bdcd7ce, 0x079f5be7, 0x67ad1bed, 0xf287cd6f, - 0x1407eb06, 0x603c53ef, 0xc61fa087, 0x608b60e5, 0xadd9cabe, 0xd89fb45e, - 0x2559b76a, 0x18ff0ab8, 0xf007a9de, 0xa7b5e57b, 0x0f883c7e, 0x4c79c5e3, - 0xf1a07214, 0x15fdbfb5, 0x678dc4e3, 0x1b346e6c, 0x7c3f7627, 0x135fda27, - 0x1bfedfbb, 0x3cfcc3d7, 0x44f79c90, 0xfbc27ff4, 0x9a265d09, 0xabeec4ff, - 0x6bfd6056, 0x402eebdf, 0x44eeb93a, 0x42c505b0, 0x3effabef, 0x880e7348, - 0x7cd97a7d, 0x39f1b8d1, 0x013f8f09, 0x1e0893a0, 0xf8f0e73f, 0xced9f28a, - 0x0e6e8f3b, 0x7b549391, 0x78ec0ade, 0x605f3b8a, 0x7b8c6e09, 0xd1fd73c8, - 0xd5e3d57e, 0x7f783eb0, 0x20cc1f5d, 0x729e9ec2, 0x24820cd1, 0xc9672e5c, - 0x39a5729a, 0xcabf534b, 0x3ef9af91, 0xcd2af33d, 0x42ae99f7, 0xc8d6794d, - 0x37fa9a89, 0xe535cbba, 0x6a6613d9, 0xaa7b57ea, 0x60c2e535, 0xf17ea687, - 0xf7ed2e91, 0x788f4c63, 0x7eee3a28, 0x27a59f03, 0x2d9ee43d, 0x06f4d53b, - 0x85fe273e, 0xafda2383, 0x8ec5cd7c, 0xf4bdf037, 0x9f9f472b, 0x9be67e92, - 0x3180b6f5, 0x53393fb6, 0x83df082d, 0xf3f1d7a0, 0xfb25ef53, 0x937880fe, - 0xa0a6a7e7, 0x5090195f, 0x9fb9db75, 0x5c32efe2, 0x6efdc458, 0x943111c7, - 0x7f276e4f, 0xd34371e5, 0x79e47fb3, 0xf728b903, 0xaf9bebae, 0x8b94f759, - 0xcbbacd3e, 0x3c28aad9, 0x5729a1dd, 0xd4d6ee39, 0x5eb99e9f, 0x6ba67df3, - 0xb69e144b, 0xba37ca6b, 0x53c28e1f, 0x9e9e147b, 0xf4977cd2, 0x5ffc2ddd, - 0x0adfa1af, 0x3d42939e, 0xc9878895, 0x1f08faa7, 0x2ada7a13, 0x1cd74f11, - 0x957c20ef, 0x2895bd04, 0x348ecb2e, 0x20cf81bd, 0xddb0cbec, 0x7a4ce681, - 0x91766c1e, 0xf370ebff, 0x691e7a48, 0xfffbd376, 0xcf409e68, 0xe87b355f, - 0x33cd9ff9, 0xecd3d9e8, 0x734767a5, 0xae7fd507, 0xcffb8bb9, 0xddeffb52, - 0xc1bf45c8, 0x01a85d79, 0xc18ec623, 0x9e9e495b, 0xc79d084f, 0xeb7f06f2, - 0x3420a9ec, 0x901d67f0, 0x9e207f2f, 0xfb4f2e45, 0x1e0e7860, 0x19fdf8cc, - 0x43a37f22, 0x3b4429e7, 0x0fe3f47c, 0x32e6a7de, 0x37bd69b6, 0x183a7f13, - 0x132866cb, 0x90f7e9b2, 0x93cfbc1e, 0xa8b3d8c3, 0xf7bee84a, 0xb9636707, - 0xe79efc57, 0x241fc7e0, 0xc75bfc3b, 0xe2033dd9, 0xc707a3ec, 0x7b3fb388, - 0x7f4765ca, 0x46afd1cf, 0x471e11d8, 0xc3cbdf85, 0x3bf80d0a, 0xa16ae51c, - 0xf1ecf501, 0x5421e738, 0xe0c97953, 0x7bb75c52, 0x5f91e51e, 0xe1dfa06f, - 0xfdf0a39b, 0xec97acaf, 0xf7a0fae2, 0xa7ed1346, 0x2b3ce98e, 0x957a3f90, - 0xce10c7be, 0x14fe3d37, 0x7b5ea9e9, 0xafc21e5f, 0xbcbdf1fa, 0x4c7becec, - 0x0d944771, 0x8f953e1c, 0x6fdb393f, 0x33e15efb, 0x0d11d71b, 0x1d83b99f, - 0xf4115f7c, 0x201da2e4, 0x3daac7cb, 0x2c5714f5, 0x75c30cf7, 0x389af51c, - 0x81ed7aff, 0xf237e461, 0xf08bce94, 0x360cf4ff, 0xa2e7fad0, 0xe83f44de, - 0xd6207d42, 0x1f9e15ef, 0xa23dedcc, 0x2e67dc13, 0xe0bed2b0, 0xa3df8e98, - 0xeedf5d10, 0xcfa3fbe2, 0x9c87dce2, 0xdc57be28, 0x0becff54, 0x5aef5fd0, - 0xebdd750b, 0x58f6411d, 0x1740136f, 0x54f7ba68, 0xddfe39d3, 0xa12016e4, - 0xf82def38, 0x6cfef82f, 0xfc5f9df7, 0xb07fea06, 0x1d26ead6, 0xf04518e2, - 0x2f2a285b, 0xfd93354e, 0x6e4e78b4, 0x5bc5ea05, 0x56f0bc44, 0x614e9abb, - 0xe8d93543, 0xdb967e80, 0x0403370a, 0x6ab4cad9, 0x5364fe23, 0x9b1dce4d, - 0xe87ab9f1, 0x58f22376, 0x9b7d98dd, 0x07ad8cd1, 0xf9252e16, 0x19a77a17, - 0x3adb75e6, 0xe7ef8bbd, 0xdadaf9e4, 0x22f7946f, 0xc898f7e9, 0xd020024f, - 0xa5c9357e, 0x4949f668, 0x181f4e82, 0x6331e22c, 0xda4bd8d9, 0xe44ed778, - 0xdf8bb3a3, 0x1e271e19, 0xec2efda1, 0x7b8adfc7, 0x4fefa39e, 0x5c3ae391, - 0xcc75ff7c, 0xf6899408, 0x07ae42e4, 0x7cffcdc6, 0x7fac2943, 0x4743b75c, - 0xd5b70d79, 0xb87880bf, 0x68f025d0, 0x4fc85d60, 0x7c97f937, 0x4c421bf0, - 0xf0dce69a, 0xbba5f495, 0xa91951c7, 0xde424b2f, 0x397d48ca, 0x12adafa1, - 0x8fd4a2f5, 0x211ae6c1, 0x8e489b8f, 0x475e6c1e, 0x7ecdc3e5, 0x6e691e7a, - 0x8db8f215, 0x79aaffbe, 0x01c790a7, 0xd2f78f21, 0xf9e6eefb, 0xd9ad7cf4, - 0xa985cf47, 0x6e11d7be, 0xd73b8e32, 0xdcbca3ec, 0x189b0f43, 0x742ef1c6, - 0x038f289b, 0x47b1e238, 0xc94f30d2, 0xa344e744, 0xe5a295f3, 0x743d3f7c, - 0xe5b7b80e, 0xfef7e46d, 0x17b4233c, 0xa7a7c707, 0x4765cca3, 0xe0f1f4b9, - 0x8e8724f3, 0xb4765cba, 0x2e3e4fa7, 0xdd971eca, 0x0d3fe500, 0x71fd25ee, - 0x9bb2e7d4, 0xe3c9fca0, 0xdfbbfcbd, 0xf940b765, 0xfc7dc1d3, 0xd051807b, - 0x2fe0ecff, 0x33958e48, 0x47f220e5, 0x2a7f39a5, 0xd7d00ba8, 0x2f9107e5, - 0x992e67a6, 0x60b17c8a, 0x72e88bb0, 0x41fd6ba6, 0xd91acf2c, 0x1515e2ae, - 0x46e15b1e, 0x5691576c, 0xa9bb62ad, 0xc46c7739, 0x6e86d376, 0xcddb2357, - 0x236fb318, 0xb7706f96, 0x2e9f68ab, 0x1a563940, 0xe59647ee, 0x65a72977, - 0xddd5dd3e, 0xe307d25e, 0x0fa4bcba, 0xe62a5c24, 0xff426f56, 0xe2976367, - 0xa9a5dfc0, 0x27f4ab98, 0x62ee6033, 0x0a93de03, 0x3dfffaf2, 0x87ac77ae, - 0xf9623675, 0xadb72a1a, 0xedfa06ff, 0xe2f6007f, 0x8000e831, 0x00008000, - 0x00088b1f, 0x00000000, 0x3cd5ff00, 0xe5547809, 0x9dcee7b5, 0x4c92642d, - 0xe2420836, 0x96249964, 0x26b6432c, 0x0c486410, 0xf90130ee, 0x10196544, - 0x044816c2, 0x7eab17eb, 0xe0171a19, 0xd16b8d69, 0xb5c46faa, 0x61e4b6af, - 0x1d0958d4, 0x87d252aa, 0xb410553a, 0x88a47479, 0x119099f0, 0xc7d278dc, - 0xf7fce73b, 0x24cee666, 0xbefd1480, 0xff938607, 0xcfd9fbfe, 0x005ffff9, - 0xb3f85380, 0x34607f02, 0x3d2538fe, 0x0468048c, 0xd1bf67f1, 0x0395b26d, - 0x8c0734ac, 0x412fa3a0, 0x6010aba3, 0x76960eaf, 0x24a40014, 0x0b7afcc3, - 0x74b08d96, 0x5de7960b, 0x05480368, 0x20bada68, 0xda85816e, 0x6066e3bb, - 0xe21745fb, 0x52ce38af, 0xe0546e05, 0x9bd40a93, 0x4f34899c, 0x1fd24d9a, - 0x856fc7ca, 0x064a7850, 0x3d9ab7e8, 0x448004ba, 0x0dac7b93, 0xfb9bedc7, - 0x8758834e, 0x31d688af, 0xeb1ebd6c, 0x6c3200e3, 0xca1f1e56, 0x5e541982, - 0xc846ed09, 0xcff5b846, 0xda22a4fb, 0x2327c597, 0x5f434e84, 0xf9ec5f20, - 0x63fe1654, 0xe0543d06, 0x6e03e97a, 0x70d79969, 0xea566020, 0x743967f1, - 0x226670ec, 0x7ed45ede, 0x18bf046f, 0x7dfb43bf, 0xbe8de215, 0xbf697537, - 0x0f5b5403, 0x0230438d, 0xd9dfb8cb, 0x855efe12, 0x878f0dff, 0xc3c06749, - 0x10f0a1a4, 0x1af01fb5, 0xd7de8e41, 0xa66ecb0a, 0xc0bee473, 0xd1fcca9d, - 0xf7218108, 0xf445f2a7, 0xfe05dafe, 0x25ff02f5, 0x5a74e736, 0x38fcdd5f, - 0x8e005390, 0x4d79356d, 0xa9ffdc99, 0x1744293d, 0x2d837593, 0x5b5b3e9a, - 0x00de8367, 0xcdd5adb0, 0x14bad7d0, 0x3f8076f4, 0xf97336b5, 0x2e16d6ad, - 0x30f568ef, 0x8ebad9dc, 0xdb5a5fe1, 0xeb577eb9, 0xdbbf2e46, 0x6fe865ea, - 0x5fbf917d, 0x86657f3b, 0xff4d12db, 0x45cec9d5, 0x7b9e8fc4, 0x3e9913aa, - 0xc853f7b8, 0xc81a9eab, 0xc344b66f, 0x9d658301, 0x8f65c094, 0xd9e1f711, - 0xc36de316, 0x8c73fd7d, 0x19c689bb, 0xad7e09a8, 0x4a437c43, 0x30d0f180, - 0xbe9abdd2, 0x3a1c464b, 0xe4f56689, 0xeb0efe12, 0x6407bf3c, 0xd39b56d9, - 0x383e47a5, 0x17558f1a, 0x6582dc00, 0x78f3ce0f, 0xfa85abaa, 0x48c07e41, - 0x3fa29ce3, 0x097c7193, 0x3af07766, 0x0e1ca210, 0xb1e808c4, 0xd18f2c49, - 0x40ddc850, 0x60f99fba, 0x1913e9e0, 0xcb3382b6, 0xa8f870c5, 0x9e03ab93, - 0x6567a432, 0xd584c3ac, 0xa4f8127d, 0x46538412, 0xd38e00d6, 0x13d46e97, - 0x5644149c, 0x9fc3c750, 0x6322dfc9, 0x14cbf186, 0x6b94d448, 0xed35a3cd, - 0x9a99aceb, 0x5cf4befa, 0xb4d2ff1e, 0xfaed348b, 0xc59a5746, 0x232f53bc, - 0x6f7465d8, 0x0974805c, 0x9b1c9956, 0x98bdfeb0, 0x062822f8, 0xbf1b1698, - 0x317be089, 0x376a5e19, 0x14c9c0ed, 0x934e7dc0, 0x108b237d, 0xc6db9755, - 0x99edc76b, 0x76c36353, 0x6957e657, 0x25c121d7, 0x1dabdfb4, 0xa7df3453, - 0xe9ae5e57, 0x93fb32ef, 0xcef5ad08, 0xc6f7cd7a, 0x9f41af96, 0xe5b1300c, - 0x014be824, 0x343afbc6, 0xecee94e3, 0xbf1fb4d2, 0xeb12641b, 0x378e7d92, - 0x741f9609, 0x152ac4ca, 0x24df9b87, 0x3fa5f558, 0x4e01f683, 0x9f5159b0, - 0x83dc8a4b, 0x963d0247, 0xcae52927, 0x812db7a0, 0xf21270e8, 0x89bf48f5, - 0x6321c230, 0xbff2a963, 0x4c1f104e, 0x32002052, 0x16abf607, 0x3a79804b, - 0x4598d78b, 0x1be5056a, 0xc906c1f5, 0x3847a691, 0x50540e47, 0x8a0428f9, - 0x973aca08, 0x2a6bf89e, 0xb2a58f34, 0x0469dc09, 0xbf74483f, 0x2fdc7c4f, - 0xe2c4da05, 0xcfc4c982, 0x68ff3f75, 0x17ac6dde, 0x5c261c62, 0xfebaefdf, - 0xfd6b4a91, 0x91f53fbb, 0x7e216c37, 0xcd7eb26f, 0x8dcb5278, 0x7f19c72d, - 0x2d6fb96a, 0x92e177cc, 0x9f680ddb, 0xaffe3610, 0xed0a76cc, 0x53a23ada, - 0xb8c9fc23, 0x1ed420ba, 0xc418be3a, 0xbfea3177, 0x04d35a7a, 0x5ddfd7c2, - 0x6f576c4e, 0x9e087210, 0x1c4ef545, 0x29463ea7, 0xa7d44f83, 0xb2a1ed2a, - 0x6ae9cb9e, 0x6f68957d, 0x587bc757, 0x96ad1fb4, 0x522ef195, 0x9ca2cdcb, - 0xa0f7cea9, 0xe5aa1728, 0x397170ff, 0x613fb44e, 0x29ef559b, 0x53ffe908, - 0x0f18ddaa, 0xa06ec9e3, 0xc933903d, 0x1abb481e, 0xeda21f98, 0xb15eb685, - 0x237ff317, 0x44c58c7b, 0xdf63cb8f, 0x90eeb921, 0xf1bae480, 0x8bd38376, - 0xd49e7ff3, 0x12c6b451, 0xb7e7dfc2, 0x6abb7c08, 0xb6329ce3, 0xde6af95f, - 0x3923e226, 0x85c8f76e, 0x563addf8, 0x4ea77ac7, 0xe88138b6, 0xfbd0af7b, - 0xd848ff6a, 0x8686f2d0, 0xb2f5519e, 0x6cc1f3c4, 0xfaf9c1fc, 0xf4f51bef, - 0x8e59c206, 0x9370973f, 0xdcf42999, 0x95add448, 0xea36f3f8, 0x3dd23359, - 0x3a9c1b25, 0x1af29f6c, 0xf1a267ea, 0xc7d0bf41, 0x24f8c5af, 0x8f959c14, - 0x6ff6c9bd, 0x8e528ca1, 0xcf2d7bf8, 0x7c89979d, 0x9fce347a, 0xd0db7c4b, - 0x75d78db2, 0xe3cadd8d, 0x10583583, 0xcce2cf8e, 0x9e97fc28, 0x3fa5ff01, - 0x8271fe26, 0x75cfa403, 0xbeb47428, 0x78b796e5, 0xef95cbbf, 0x43325fac, - 0x472cb8ed, 0x39c68f97, 0x0e1f0832, 0x74074e85, 0x5f050ab6, 0xfabe1357, - 0x1373fb17, 0xf9f0ecb1, 0x3ed9ba47, 0x88972aec, 0x4071cdee, 0xf92a3f74, - 0x410ef68b, 0x0ed68eff, 0x5a5bcbb6, 0x84be18bb, 0x55bad073, 0x8d10dd7c, - 0xc067f9df, 0x131ffcef, 0x01f4a3bf, 0xadfb03a3, 0x4e3c07da, 0x1180ff85, - 0x2b4cf4c2, 0x27e225f1, 0xfae24ba1, 0x2120b93a, 0x138fa9a0, 0x738e52fe, - 0xcae9f13c, 0x37aabb19, 0x98792148, 0x311d0b1c, 0x0ed7cc49, 0xc41daf85, - 0x22ff2ad7, 0x11ea963f, 0xc49d6fcf, 0x37e0437e, 0xf3c0bfc4, 0x3bba78a8, - 0x881baf1a, 0xabc1a78e, 0xc607feb6, 0xc7fa276b, 0xaf8237a4, 0x653778c4, - 0x77f9e346, 0x7c555e0a, 0x7fe4536f, 0x236f3c38, 0x7f9ea73c, 0xb4cb6f3c, - 0xf891b8f1, 0x453ece1e, 0xf75d47d2, 0x7e5a7210, 0x2d3a722e, 0xdff8aadb, - 0x461677e8, 0xa26dfdd3, 0xf74359bb, 0x53c8339e, 0x4f298fcf, 0x848b7891, - 0x3ab8128d, 0x3fdfd12c, 0xdf561ccb, 0x4e3c179d, 0xf8d6ce0a, 0x75bf9367, - 0x29b3fc6b, 0xfd696118, 0xe5349bd8, 0x9aadeb3a, 0xada697f6, 0x6e5fd4d5, - 0xbfa9af5b, 0x4d01ff32, 0x63c76af9, 0xd3e67e11, 0xe77afa9a, 0x73f5346f, - 0xea6bb79b, 0x68f4b7e7, 0xfe7817ea, 0x78ab29aa, 0x1c0adadc, 0x356b6d2f, - 0x65d3f12b, 0xfe03ab0c, 0x8b83125a, 0xdfd9070f, 0xd7b7f4ac, 0xafb24bb2, - 0x32d1fd83, 0xc296ab9f, 0xcd9d8aaa, 0xb5f4126f, 0x2d78955a, 0xad5be18d, - 0x3befd636, 0xee19f35a, 0xf128756c, 0x5dc3255a, 0x4e254ead, 0xb48c3173, - 0xbb66af0b, 0x3d2164a7, 0x44bcbda6, 0xe980b807, 0xc167f87f, 0x77bc5a5e, - 0xdce28ebc, 0x8e5eca35, 0xffb37f57, 0xe3afe436, 0x950726cd, 0x311fb77b, - 0xf9a30ad8, 0x32b7ee65, 0x6cf8c338, 0x0d5fcb6e, 0x45cd67e4, 0x0863ba0f, - 0xa59a9d39, 0xf7207e63, 0xcc2f5003, 0x05218336, 0xd9ecc1f5, 0xf80da392, - 0x189207bb, 0x3f58dcfa, 0x133e0f4d, 0x7a2deb96, 0x979e299f, 0x3fa332e6, - 0x132c4b3d, 0x50f07a4c, 0x7324a43d, 0x7d0d7e9c, 0x383ca1b4, 0xbf18b865, - 0x1c3f22cf, 0xe96f5dfb, 0xbddd9030, 0xfa2fe76e, 0xb87ac36f, 0xf1ce53d3, - 0x25625c3d, 0x3e792dfd, 0x371a9dd6, 0x3520bcbc, 0x5f1850e1, 0x4e19254f, - 0xe1d1f8a5, 0x7adc5277, 0x9cf1c193, 0x05dfba2d, 0xc9a77eca, 0xc16ffb12, - 0x4dde4dd7, 0x713e4852, 0xb84d3b7f, 0x01e226cf, 0xc1b367da, 0x7e445797, - 0xb3f676f6, 0x16d72a9b, 0x2e9a9d11, 0x15313e91, 0xa69de285, 0x8fd92f96, - 0x91cfd48f, 0x90f14cf0, 0xfe656fc3, 0x93badfdb, 0x8b8d45f9, 0x5c7d5b7a, - 0x6ab80b2e, 0x39a3e3c3, 0xa64dff93, 0x4beaa7b8, 0x3c4cff11, 0x53fbdce9, - 0xd5a077dc, 0x17e52fff, 0x9a82bcd4, 0x5bcc8867, 0xde647aa8, 0x6e0975ad, - 0x2c9aefdc, 0x94f30651, 0x5ea3a674, 0xdedf5540, 0x9765159a, 0xbd3ac8ef, - 0xffd6d67e, 0x6cf9fac0, 0x4d31bff9, 0xbe48d5d8, 0x05e337df, 0xe553ad03, - 0x9ffe48ef, 0xfe707d43, 0xd7924d39, 0xf67a7a83, 0x44c37692, 0x7df9dce9, - 0x88a0e5b9, 0xc2ed238b, 0x3607b6f7, 0x2b5c9ba6, 0x92617c73, 0x1e50726f, - 0x4743a544, 0xcf3add34, 0x1fceb740, 0x76d16e93, 0x73bce0f1, 0xf1a08bb3, - 0x8acbdfcf, 0xc83e27f2, 0xa91fbd3a, 0xf781ffad, 0x636b1d6d, 0xef4472b8, - 0xea27593c, 0x01627c45, 0x80eff21d, 0x74b8e657, 0x3c7b6669, 0x195033c5, - 0xb77d278c, 0xf2065bac, 0xd4ef410f, 0x5cfe468f, 0x1f67f0a2, 0x7e243ef8, - 0x7ef7055c, 0x25980941, 0x22ae4bd5, 0x09f4b73d, 0xfc4f0843, 0x27f393af, - 0xcb7e94ab, 0xda469d2d, 0xb567f2ef, 0x1a71d4ed, 0x1fc88a5f, 0x19fa5f57, - 0x73f0ddb0, 0xa7556fde, 0x5977dfb6, 0x62872971, 0x084b1659, 0xa7d267ef, - 0x1baec947, 0x5b27cac2, 0x3f20bf39, 0x9e03e0f3, 0xc4fa21b1, 0x71f14764, - 0xf9e9f65c, 0x23ff5b58, 0xf71cb1f3, 0xf9e891ac, 0xbf78f97d, 0xeb4599dd, - 0xa0f3f556, 0xc4c379de, 0xdca0677a, 0x37a4f226, 0x9e2daefd, 0x3804e4f8, - 0x2a161d88, 0x6a85d2f9, 0x369d74be, 0xcfb93a5f, 0x49b979c7, 0x716dbd07, - 0xbd89f748, 0x55dbce1e, 0x59b776ed, 0x5dd3fcb0, 0xa3fc994e, 0x64b96ff1, - 0xdfeab75a, 0x484efea8, 0xbeb0e58f, 0xf66bbce3, 0xd53bebd9, 0x30f6aa2e, - 0x06560ed2, 0xfec96bdb, 0xe3b6f84d, 0x2be7824d, 0xf7691eaf, 0x7a138bde, - 0x57c1a8e2, 0x8cfc97be, 0xcf1c63d7, 0xaffaf441, 0xc67e16cb, 0x0302cf4c, - 0x1f091fcb, 0x450cdbca, 0x764fae6e, 0xf54d975f, 0x99d0bd8a, 0xa3b2069d, - 0x23df7275, 0xf95f12d7, 0xde1bce65, 0xbf07c77c, 0xccedb5ff, 0xeb2685f9, - 0x863ff671, 0x749a338b, 0xa2f8a6e0, 0x4a56d6a4, 0x6dc50c7e, 0xf3544794, - 0x9fed918a, 0xc8acd7b0, 0xb5573ce6, 0xd9eb49df, 0x1c33d628, 0xbe5a9abd, - 0x8731e4d0, 0xbba9bf9b, 0x4c30badc, 0x16ca5e3e, 0xdbd22ef1, 0xa21cc87a, - 0xc5f2d9f7, 0x65f8b7ff, 0x091e0c9a, 0xe4a16ced, 0x082ffe15, 0xf80e783f, - 0x2083ce19, 0xf9583743, 0x38216a7c, 0x17022e18, 0xdbbb7cc3, 0x60337c4b, - 0xbe248e08, 0xbbf57fea, 0xfe9be202, 0x57b6278b, 0x5f3bf9c1, 0x06fff48a, - 0xfe78dbc6, 0xdbbe5781, 0x7039fc43, 0xf4ace187, 0x6764eac6, 0xe451f127, - 0x53bbcb79, 0x01d73e64, 0x8b967afd, 0x03e8ab7a, 0x1b72a497, 0xe64cd8eb, - 0x1cde908b, 0x37aab4f5, 0xc2bf6017, 0xd7ac744f, 0xb5e49960, 0x80aed363, - 0x70ac458e, 0xa657a671, 0x2fa8a772, 0x95e8995c, 0x15585cb0, 0x4a6fea23, - 0xc52642f4, 0xcb960143, 0x0fac00f9, 0x8bd08017, 0xf7938237, 0x96419189, - 0x6f17fd84, 0x3e709735, 0xa4390216, 0x8e288bff, 0xb74e221a, 0x2f7908e6, - 0xbefa12ce, 0x179b46b8, 0xc95b30f9, 0x4a6bdb1b, 0xe7561072, 0x1d12f738, - 0x1bfc938b, 0x7ca32a1e, 0xa1360e90, 0x75567d7c, 0xaa779f2b, 0x35ed1afd, - 0xcdbf84bd, 0xe2bc7012, 0x9f7936e9, 0x238ce713, 0xf2cdcfc3, 0xa807b5ed, - 0x7b5a11dd, 0xc578f0f9, 0x47f71c7e, 0xd78795cb, 0x1bb14c57, 0x43f1fbe7, - 0xe5cbcf25, 0xebe679ff, 0xf80b3bfa, 0x7e43c14c, 0x7ddda372, 0x046fd79c, - 0x9ffad0b0, 0x40147114, 0x47e50673, 0xd2653c97, 0x11f19f91, 0x03c8639a, - 0xddc61bf8, 0xe31bff04, 0xc77f8267, 0x27e099f8, 0xfc133f18, 0x04cfc607, - 0x1e3b7f17, 0x8d802283, 0x4e4b4e39, 0x301ce879, 0x1c86bd72, 0xf9c1cf81, - 0x7f3c8dbb, 0xf8cddd9d, 0xebf7a41d, 0x9973a5e0, 0x0bc189cd, 0x6fc34e92, - 0xf0dfdd03, 0x7870e9f9, 0x2325cf51, 0xe853bfeb, 0x67a9d45a, 0x15d45ffb, - 0x6b086f88, 0x918e4177, 0x395f0beb, 0x1fe34f18, 0xd7e20eb5, 0xa796e129, - 0x82f944e9, 0x08332d67, 0x677675bf, 0xe51bed09, 0x51f6833c, 0x83c1f5d4, - 0x7c78cb13, 0x75a364ab, 0xb8e51f04, 0x911f6221, 0xb5f75078, 0x81bfd139, - 0x257e6ffa, 0x7a82768b, 0x10dc8407, 0xed43491f, 0xcff32d77, 0xccb05374, - 0x7e9deb8a, 0x0a1e6e4a, 0x29f675ff, 0x5477e78c, 0xc7cf537e, 0xe952fe15, - 0x1df2ae76, 0x6b901e39, 0x6ae77e84, 0xb236a5d2, 0xc9e3274b, 0xee57ac2f, - 0xe6757419, 0xf4fb47bc, 0x6ec194ec, 0xc8d63e63, 0x5f8562df, 0x6dd85854, - 0x36bd1174, 0x59ca1f77, 0xe4fa6164, 0xb3f6c62c, 0xbc9aec72, 0x89d56167, - 0xe14a1fc7, 0xea9a56f6, 0xceba783a, 0x60dfe38a, 0x6d36fede, 0x93f5ae69, - 0xcf2c44ba, 0x1076934f, 0x9ccb605c, 0xe5a3649a, 0x37fd797a, 0x41d94fe6, - 0xa3957522, 0x29b9fd9e, 0xecc264a4, 0x9639ad43, 0xcb071f0e, 0x4d64d675, - 0x31b4d2f9, 0xdb97f69a, 0x57f535b2, 0xd4d38fe6, 0xe55ef3ab, 0x2bb4d528, - 0x51660a4e, 0x60fb875c, 0x64e780b9, 0x7da25daf, 0x1c62beef, 0x3f3da796, - 0xca6e41cb, 0xda7ea566, 0xd12f5a96, 0x69f10063, 0x70ea8744, 0x1f47fae5, - 0xe222c1a2, 0x67eec686, 0xe76d3876, 0x130c3710, 0x7100ac2f, 0xdc5c3f8e, - 0xa02f1910, 0xf4907cfe, 0xd7abf167, 0xdc70db58, 0x2e2755cd, 0xef3ee1b0, - 0x8238c1cc, 0x47128dec, 0x833fc70c, 0x04d92272, 0xf0c8f4ff, 0x03fc10dc, - 0x1f850bf0, 0x3ef69c05, 0xdf0533fa, 0x4a7dbf5f, 0x07f38dfa, 0x57efc51e, - 0xafbe4460, 0x6f78e8d8, 0xdea7e50d, 0xf9ce8191, 0x03ae24e1, 0x77e81beb, - 0xb0f7c439, 0x46bbe9e8, 0x0f77f0a7, 0x94aba6b9, 0x731fdffc, 0x71aabf14, - 0xcba35dfb, 0xf370f542, 0x70f69a27, 0xa6b774bb, 0xb6a6677c, 0xbb94ef7c, - 0xe70ffbc3, 0x5c6c3597, 0x9ca37460, 0x392c3c36, 0x8be843bd, 0x28a4f5c1, - 0x097ba1fa, 0xdb43dbeb, 0x716d1997, 0xe157edd1, 0x6cb79478, 0xaadec618, - 0x193aea7a, 0x7faa879a, 0x71cf9d47, 0x08fbe77e, 0xcdf64f71, 0xc3b09af3, - 0x8db8251f, 0x2fb27ce1, 0xf47b9c47, 0x1dc0f63f, 0xee79d35f, 0xeabe22eb, - 0xa3f6144f, 0x9d33f3a8, 0x08f1610e, 0xd6455fc1, 0xd2ec8e80, 0x0f58d2c0, - 0x2d359ca0, 0x8ae8f38b, 0x7e088fc9, 0x5e4f1e68, 0x9a0f2dc7, 0xeb1fce91, - 0x3cbb1a74, 0x9616c140, 0xd9fd9efb, 0xf7e93b8c, 0xe92f7102, 0x2fb3ed7c, - 0xad7d8407, 0x1e637a11, 0xb7629ff1, 0xd3565500, 0xc768305d, 0x5e10cf48, - 0xbf6b9ca8, 0xc987fdf5, 0x7a11efcf, 0x370af283, 0xb4e05fb0, 0x1d0df368, - 0xbbf8e72c, 0xd73efc2d, 0xb78feb59, 0xf3968dda, 0xd84647a8, 0x218779b5, - 0x57fbc5f4, 0x5e9b3d22, 0xd05ef997, 0x04f6adb1, 0x911fd308, 0x28da6c78, - 0xe5ab9cb3, 0xcbe55ba3, 0x830f6cbc, 0xd185f519, 0x83a706f8, 0x55b57fe5, - 0xd27ab7cc, 0x4ec83337, 0x8bd6eeaf, 0xcdc32f4b, 0x5b064eb3, 0xb79b3cd8, - 0x5d929699, 0x603fd753, 0xf749f455, 0x0a534957, 0x843b5c04, 0xc0bf457d, - 0x417e4290, 0xecf1c4bd, 0x3551ee9e, 0x123da784, 0x3c256cf8, 0x5c6635c4, - 0x1c314cdf, 0x5e50b77d, 0xf9f2d214, 0xd71aa59e, 0xacecf1aa, 0xf27659ee, - 0x5cec3f63, 0x072907b8, 0xccd9ec93, 0x8782d74f, 0x893deefd, 0x93ca74ae, - 0x3fee534c, 0xf60c49ec, 0x67bdbf91, 0xf744ac52, 0x3bfc7019, 0x5f757c69, - 0xf4ae0c7b, 0x9297de66, 0x44fe752f, 0xf67b153e, 0x67aaa271, 0xa7dbe4eb, - 0xf7e7495c, 0xf14ac073, 0xf85974ec, 0x2147f0d5, 0x6d5eaacf, 0x6c49fc92, - 0xa633edaa, 0xa34f11db, 0xe4a97e5a, 0xf735db7d, 0xafd6cf00, 0x5fa38c1e, - 0x567f9894, 0xb1bc4439, 0x47f3faaa, 0x57f9c5ae, 0xfe4fbc61, 0xedaec2dd, - 0x917f08fb, 0x7c60fdf1, 0x7be62ff5, 0xd733e3a3, 0xcddfda32, 0x73df1c77, - 0x69c7442d, 0xea817183, 0xcb173e5f, 0x58a8d6e7, 0xfc287c85, 0xee5b647a, - 0x7f5835de, 0x66062fe4, 0xfd2737d7, 0x58ade8ea, 0x58b9f9be, 0x2491f3c6, - 0x391d90f0, 0xebcf29b2, 0x744b06c1, 0x6fb25ec1, 0xcf8e25b0, 0x327b3e69, - 0x512fb7ef, 0x76b7f27e, 0x7e4843f6, 0x7cc2e86c, 0xe88ff746, 0xb9a3cbfb, - 0xbcc5b81f, 0xca5c8a0d, 0x5fde142f, 0x242ff54d, 0xa5427e73, 0x6327e1df, - 0x7dac149c, 0x2b22be05, 0x92e7deb2, 0x5bdd10e7, 0x697ba15c, 0xf97c84bf, - 0x06f708d5, 0xc7f2f7da, 0x89c3f3ff, 0x17da9fb8, 0x1555feae, 0x07d96fae, - 0x84e340a9, 0xdfb43ae8, 0xb66b6c70, 0x3f057f90, 0xf18c5e2b, 0x27d30c1e, - 0x35123b2b, 0xd1aea6e5, 0x7a6183de, 0x729ef068, 0x04e7c4a3, 0xed5c8a8d, - 0xeddbba37, 0xfba5d794, 0x713f4ca9, 0xce84b51f, 0xf7ff08ab, 0x91ff1899, - 0x5da2f67c, 0xf3566739, 0x4e60c93c, 0x0b75b923, 0x97dc0dfc, 0x31e289b7, - 0xf1493d9f, 0x33b9823b, 0xb3f9c30a, 0x9c1bd577, 0x7b8931e7, 0x9f43318f, - 0x13da77eb, 0xf9837db9, 0x699e4d4b, 0x4d09cb55, 0x015567fe, 0xd2501fb0, - 0x89bd2b66, 0xba1487ce, 0x7aee9fdc, 0xf1def18d, 0x18bbabc0, 0xf2dc4f9f, - 0xd3bbcd31, 0x5d83f4c2, 0x11163c4a, 0xbf98356f, 0x69efe450, 0xe87e7f8d, - 0x9445bdb1, 0xcaf438ff, 0xd3ca22b8, 0x87fd942e, 0xf7c99d7e, 0x86dff69c, - 0xf7cecb70, 0xb91e2f39, 0x0c7ba8de, 0x8d43d092, 0xba648fb4, 0xc77ae3ff, - 0xf42e72ce, 0x850d81c3, 0x1f353f8c, 0xe864703d, 0xa75d5078, 0x3ebabe3a, - 0xddb57c75, 0x5f22ecdf, 0x17f46fd0, 0x415ffd91, 0xfb6130e7, 0x17f78fea, - 0xbbe85a25, 0x4913f855, 0xb7e30e58, 0x2abcf57f, 0xf06a7cf2, 0x47c9565c, - 0xfdadd3ed, 0xaff91199, 0x8321e3af, 0x7eef5c3b, 0x752a73cf, 0xdafdeabd, - 0xfd85ab7e, 0x2576939b, 0xe90e9f1f, 0x1deb0ed4, 0xb7bff23e, 0xc7e41c98, - 0x905c9a27, 0x3469f88b, 0x9afef8fa, 0xe4d12fda, 0x7991efe6, 0x234481f9, - 0x81e5bdd0, 0xf7fce554, 0x42bd602b, 0x9c16e871, 0xd756acb7, 0xd212c5bc, - 0x2cfeaa87, 0x0bdf871b, 0x3ea91ee8, 0xdf2027e4, 0xdb6b1594, 0x2da3f687, - 0xa0ae7bff, 0x6eb25963, 0x24b938c8, 0x1b65c857, 0x9e42c874, 0xa89d1d85, - 0xbf0d1de0, 0xacd7ee1c, 0x40fcf452, 0x0743d9bc, 0x8ab713bb, 0xf513ab7b, - 0x5104edbe, 0x124b400b, 0x89f4995d, 0xfab4baf1, 0x1cc86c9c, 0xd8e3cbb6, - 0xc8504f2e, 0xccd4b77d, 0xf7435bf7, 0xc132fd5c, 0xd0c8218b, 0x413d5609, - 0x4bc30324, 0x2a70c5c0, 0x0cbc3334, 0x015e19da, 0x02af0c1d, 0x89f8433f, - 0x1ed80daf, 0xff656edc, 0x3a25f2e9, 0xd765cbb2, 0xcf97ed0e, 0x3c35f052, - 0x57cb503e, 0xa63e3b9c, 0x8772f72a, 0x7cd8cbc5, 0x2f157be6, 0xec4fe226, - 0x34de0317, 0xc0209382, 0x46264ce3, 0xdd78a6ce, 0x6b7ef7c6, 0xbae5c9c1, - 0x6547c4b3, 0x1777adc0, 0xda97810c, 0x9e64f9a1, 0xb90327c2, 0xe951f8c0, - 0x8dae48f5, 0x30dd2acb, 0x7b234c50, 0xc84f4d10, 0xc59675a0, 0xa7a71cd6, - 0x5f3fb722, 0x7a8f5336, 0x66b4acb4, 0x5f90a90d, 0xe5154ee6, 0xd32f3589, - 0xf3fb7d51, 0x71728a97, 0x81c1a94d, 0xcbdae85e, 0xfa825e66, 0x27dcadd9, - 0xa011a337, 0xb672637b, 0x2b761738, 0x724dcaf7, 0x2fba5ae6, 0x580dba66, - 0x0063b8df, 0x22d7ecfc, 0xb8bc91b7, 0xb37b1c45, 0x3aafd055, 0x2e4b7dd6, - 0x2fb333d9, 0xb87486de, 0x28dd6d79, 0x18f79bb2, 0xa49ff8c5, 0x81bdc6da, - 0xc49932f8, 0xbf7556bd, 0xc189ef58, 0xadb24072, 0xad0cc969, 0x59c75d4b, - 0xe9d77bcc, 0x774fcde6, 0x023d206f, 0x15c70736, 0xbefb1463, 0x34c4cb65, - 0x1d7030f4, 0x20475e56, 0x0b4d772e, 0xee91dd56, 0x1bc6847a, 0xf87c1388, - 0x7529d108, 0x75cbe878, 0xc43b943e, 0xdfb581f7, 0xbd23eabc, 0x042e29f4, - 0xae4df9c7, 0x475a71fb, 0x51902e93, 0x45fbf48a, 0x05007a2c, 0x9096be21, - 0x0f107398, 0x1af04e6d, 0x77945e59, 0x99f9ca36, 0x8b03172a, 0x4fc43c71, - 0x8b55cb99, 0xcc5422ee, 0x60937e6e, 0x16bdbba5, 0x179e686b, 0x724d3d68, - 0xe4f881b0, 0xc607e268, 0xc76e594f, 0xf454fe0a, 0x9eb6f759, 0xa288c6db, - 0xb2e4c20b, 0xaf89db69, 0x6f7486ff, 0x5071663a, 0x3e3c90f3, 0xe79c46b6, - 0x46fa345a, 0x5d09d395, 0x9c383e26, 0xc5a2f5b8, 0x07d26ed4, 0xb7a4d9bd, - 0xda06f727, 0xe81e7dc8, 0xc8463bde, 0x7fd7ea89, 0x7d8b9d23, 0xfc8cccf9, - 0xf9104091, 0x839c5e23, 0x8af4fc73, 0xad5f0738, 0xeca93de4, 0x788b7de1, - 0x573b8d54, 0xde2dbcf6, 0x6ff07985, 0x122bbd05, 0x713e967f, 0x6fc455e3, - 0xd48bef91, 0x6949b478, 0x7bd7a2b7, 0xf227ed37, 0xc51351bd, 0xbfc345a3, - 0xa27a6a37, 0xc8d1e396, 0xb9bd46f7, 0xb14afe4a, 0xa1f8a08f, 0xb436944b, - 0x87c70b3f, 0xf709af46, 0x35c9fab6, 0xd3952b0e, 0xc7d60e2d, 0xe10e3d57, - 0x6489e1ed, 0x9e5519e6, 0xd893ad97, 0x5af156bf, 0x49c9bcfc, 0x7e7e28eb, - 0xe8cdfb14, 0xe97b8bef, 0xde913e4a, 0x837bd012, 0x2cc189cd, 0xb9ba67ba, - 0xfe41df3b, 0x9d5a1ff8, 0x68430ff0, 0x503c6a7d, 0x4b54bf27, 0x2d8e87ef, - 0x3f0b38c2, 0xa679eead, 0xd5e58ccd, 0x1055e9eb, 0x13f384a5, 0xdf2aafc8, - 0xc6978329, 0xd543ef01, 0x39153b08, 0xc0e9a537, 0x188f8616, 0x0db008db, - 0x29300f91, 0x4fcd8bf4, 0x39c7d4d2, 0x4ff4d02e, 0xd4d2cca8, 0xf788c5b7, - 0xfa71e032, 0xef422a0b, 0x3f9d1248, 0x0083f4d1, 0xbd08adfe, 0x7e27b917, - 0x4f7e4eea, 0x3ce06fe2, 0x2565f245, 0x7926f69a, 0x5dfc4cab, 0x435ea5fd, - 0xa6529fcf, 0xb956f11b, 0x9c1cfd1b, 0xb69f4267, 0x01e0263e, 0x5bb317ea, - 0x984bc9af, 0x85f2da6c, 0x629e4a79, 0xe4d58c2c, 0x2ef10629, 0x61d8fef8, - 0x0545f31d, 0xbaaafce4, 0x006cf08c, 0x6f1a2daf, 0x5df840c7, 0x1c5ac6c7, - 0x426a96f4, 0xc932cbcf, 0x8b4baa41, 0xb5b351ff, 0xd6ed1ff8, 0x52cc7be2, - 0x9bd3be2d, 0xb0bef8b5, 0x4cd78b45, 0xd96f168f, 0xda6826eb, 0x346bdbdb, - 0x578dbce5, 0xe45fda68, 0x8f29a19d, 0x4d7af17b, 0x858ec2fb, 0xaee2fa9a, - 0x957a9ae5, 0x83e386cf, 0x11d5bef1, 0xdd03a6fc, 0x74a0f869, 0xf335cfe7, - 0x9ff450fd, 0x05e8a79f, 0x2bd7fe85, 0xf8dde576, 0xb892f7c3, 0x7a158b4e, - 0x50df3070, 0xee78e06d, 0x6d725b3d, 0xc505e91c, 0x7b14b9de, 0x894f3907, - 0x1d9455b2, 0xa2bf717e, 0x36ab9f64, 0x2cf746de, 0x8a8afdc4, 0x09b5edc3, - 0x1de23ed4, 0x494af4d6, 0xf91dde73, 0x67a66b2e, 0xd1209cad, 0x3f7144bd, - 0x841ef231, 0xdeab3efa, 0x2739a319, 0x96bdee1f, 0x78c25f9a, 0x2f148c01, - 0x3efccce8, 0x721fda31, 0x5fd9946c, 0xf6ffb373, 0x79cdc967, 0xfecc6ba7, - 0xecefe20c, 0x79f5eeb1, 0x3aa3b788, 0x3dfd8d87, 0x00d6fde5, 0x2fdf8c6d, - 0x3ca4ccf5, 0xbb8600e9, 0xdfd4d794, 0xbd2663b3, 0x5be5c45b, 0xac221503, - 0xe68f3fa6, 0x71a41fb9, 0xbbd6480e, 0xbbefb14b, 0x20cf3e13, 0x73a2667b, - 0xff3e12fe, 0xfc2f387e, 0xee147bfc, 0x406df50f, 0x79f0f367, 0x8e25cfee, - 0xc1a73e53, 0x77e4c2aa, 0x4f79419d, 0xb9b6e22a, 0xb8d4be0a, 0xff328e6d, - 0x29621c01, 0x5db9f3ea, 0xacbc667f, 0xe253eb48, 0x158766bd, 0xac71bfc7, - 0x7bef84a5, 0x221d4b39, 0xb8e357de, 0xb1f7f231, 0x87ba67b3, 0x88ed22b5, - 0x97869e26, 0x57cc8792, 0x42c5e646, 0x1fe316fb, 0x76cb1f58, 0x74fac0e8, - 0xc6863fce, 0x85f9ca3f, 0xfbdacdb9, 0x3e5bf3dd, 0x02dff0d2, 0xfa9a27cf, - 0x30d04a40, 0x781ff706, 0x1bd4f475, 0xaffd7f10, 0x9e282a98, 0xe4f5ba45, - 0x0fc68795, 0x897797dc, 0xb4ce1bf0, 0x1d79cfcf, 0x5afdcabd, 0x5bfb9f75, - 0xd03971f7, 0xefb8881a, 0xbfc4d1e4, 0x09fe342a, 0x0e8fc9f2, 0x431c234a, - 0xe76673e5, 0x57a9388b, 0xabda7779, 0x55ed3bbc, 0x2af689de, 0x957b42ef, - 0xbbeaa177, 0x9c095edd, 0x8e64bf74, 0x816a7ae4, 0x0f76efc4, 0x969b3ed1, - 0x5de88b07, 0x60715363, 0xbbf3249e, 0x7df423dd, 0x45bb7788, 0x69f49592, - 0x6ef435ea, 0xcf08f0f7, 0xd9d8b251, 0x50d789f9, 0x28d870bc, 0xc5f4a3e4, - 0x7bd2666f, 0xdd53c7bd, 0x3fbf89c7, 0xf31f6495, 0x9f12ebf3, 0x6033832b, - 0xef16719c, 0x13cbbf7a, 0xf32734e7, 0x0a89b9c4, 0xbd0be647, 0x9cb04a56, - 0x2e6f72e8, 0x68dabbbf, 0x385777e2, 0x7617539f, 0x7df2221f, 0x4d1fc95c, - 0x6a1fd23e, 0x5f2127de, 0xbbd3379c, 0xca675a39, 0x6ef126fd, 0xa0cfe02e, - 0x0f747677, 0xbdf245ca, 0x1de29c1b, 0xf0a6de5e, 0xf90930f7, 0x45bd3dca, - 0xb7a779a0, 0x7ec0e7b2, 0xe5af27d2, 0x53f393b9, 0x56c7ef43, 0x7f676fc6, - 0xc6df20af, 0x797ae2f3, 0xee17a8ff, 0xc79cfa24, 0x7e56617c, 0xd7fff479, - 0xf5bc3860, 0x5a3ff62f, 0xf77a1990, 0xaddef616, 0xaf2c3f20, 0x343faea7, - 0x42e5e9ce, 0xe5a97bcd, 0x93dd8f43, 0x7486724b, 0x5948f911, 0x88633f9a, - 0x05f3d3fe, 0x774feffd, 0x97f9a04d, 0x60bc8b37, 0x6fda6f88, 0xdce898f9, - 0x3ef21963, 0x723fdabf, 0xf5b72b9f, 0x9f703e30, 0x617f68f3, 0xf08cbcfb, - 0xbfb3eea5, 0x05a3ef7b, 0xdfdf73b6, 0x6e777df7, 0x6d71811a, 0x767950d2, - 0x7e613eb4, 0x3fed4999, 0x8fedaf56, 0xb1e5390e, 0xd1de48bb, 0xe254e96f, - 0xc4cbb21e, 0xee5daa17, 0x2920e254, 0x02ed83b0, 0x71724bcd, 0xfb61e4b7, - 0xda3be6a8, 0x947fb424, 0x61af7057, 0x685f217b, 0x775f1071, 0x49f9ef22, - 0x58cef41e, 0xc44773ce, 0x758b3fd7, 0xbc7844df, 0xa335aff9, 0xf2defe28, - 0x38942b97, 0x72abd84e, 0x69cb3f85, 0x4147da7e, 0x996df302, 0x730abeb2, - 0x55c9fb33, 0x5e4591e0, 0xac93c943, 0xdff1c1df, 0x141a01ff, 0x43d0aaaf, - 0x000043d0 -}; - -static const u32 usem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x51fbff00, 0x03f0c0cf, 0x1894738a, 0x18357a18, - 0x326b3618, 0x31686830, 0x20318830, 0xaf8568e4, 0x9fa65371, 0x8181959b, - 0x81f98817, 0xd7881058, 0x6c303133, 0xff5e2260, 0xfb045111, 0xc303209e, - 0x197f2051, 0x6614ee90, 0x64055860, 0x2fe2031f, 0x1080be40, 0x100c8303, - 0x606115ff, 0xc1d20530, 0xc4036c40, 0x9bf145c7, 0x7c80827f, 0xbf2a08bc, - 0x279f8d1b, 0x25ff5f8c, 0x0ff2fc11, 0xc363c808, 0xc7e41632, 0x7a052247, - 0x29370207, 0xca8ff2a2, 0x543c3033, 0x51d06060, 0x919bf082, 0x6280ede4, - 0xec21e4c7, 0xb8c09229, 0x28b5ca07, 0x2a773762, 0x5004fe50, 0x34894bce, - 0x41d3dcf7, 0x8434afe5, 0x3ebc00d0, 0x03a8e414, 0x000003a8 -}; - -static const u32 usem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xc5547c0b, 0x3d9cf8b9, 0x926eece7, - 0x2126cddd, 0x26c2bc21, 0xb80d4401, 0x41a00c40, 0x94520f37, 0xa2a1e1a8, - 0x24786c22, 0xf622ef21, 0xddbf1f62, 0x52c488f0, 0xd4c51f1b, 0xb051768b, - 0x40368bd1, 0x5c1758d0, 0x6d8b459e, 0xd5a045e8, 0x5e40137a, 0xa540b206, - 0xcffd45b6, 0xdd9ccdf7, 0x26364e73, 0xf6ffef6a, 0x9fdbfffe, 0xcccce61d, - 0x7cdf3337, 0x9be6bdf3, 0x91be6489, 0xf21387d8, 0x256efc25, 0x108951e4, - 0x9b4e1892, 0x9fc6933c, 0xedb10994, 0x3bea247e, 0x9e0c8499, 0xd146706b, - 0x64085fa2, 0x21064b4e, 0x758d65c9, 0x793dfa46, 0xe8bc7d91, 0x9819c308, - 0xbdbae47c, 0x720c8409, 0x8266f6d3, 0x7fe92fbf, 0xc637b73f, 0x79c87491, - 0xe131a285, 0xbc9a4afa, 0x877bfa48, 0x149bbeaa, 0x48dda675, 0xfd51fbfb, - 0x9085b720, 0x4678c31f, 0x40cba942, 0x78b8e8b2, 0xfd2e6f5d, 0xaf0e3a3f, - 0x295be8cd, 0x1c1a2210, 0x242444b1, 0xa0482326, 0x679fbe9d, 0x49d7ed3c, - 0xaa36a708, 0x49e74ac8, 0x0896b4c8, 0x808972f5, 0x76cd8878, 0x78e97b25, - 0xe22e7d57, 0x220d57bc, 0x27d69da4, 0x684ed392, 0x61c4953a, 0x232dc7bd, - 0xd57e4206, 0x07123fae, 0x199b1b85, 0xdc155e24, 0x0e210f06, 0xc7afc513, - 0x8f2ae98c, 0xc4c9a79d, 0xab210d71, 0x574c0e3d, 0xfa634679, 0xdb27d0d8, - 0xf9d00673, 0xe9d8320c, 0x63834848, 0x1191dda6, 0x2dc72786, 0x0938e730, - 0xae2926c9, 0x2f5a54c4, 0x4dc840d1, 0xf342dc84, 0x19082375, 0x5084ec49, - 0xbc933dfc, 0x019dca2c, 0x45e60779, 0x7cc37103, 0x2e033263, 0xc62de291, - 0x1c95cf69, 0x1bf8efe1, 0x785fdf80, 0xc1d6152c, 0xefcc1b7d, 0xf0ece219, - 0x46dd9e02, 0x7f5a26e7, 0x5e4ceca5, 0x468ae14a, 0xad832eda, 0x1e1094bb, - 0x1fc04cdf, 0xc9cc8fed, 0x30d7acd5, 0xb4224718, 0xeb05dc73, 0x75b27164, - 0x1574095a, 0xf2e61d61, 0x77655875, 0x38fd19d9, 0x11fa2449, 0xb1fa5aed, - 0x8fe96864, 0xba9fb17e, 0xbf69e79e, 0x3bed424d, 0xbd3ce953, 0x4dce0c4b, - 0xa160dbf4, 0x0af80051, 0x80c425bc, 0x41f92afd, 0x63a05265, 0x179e1ab4, - 0xf6f7e9cb, 0xefcf730e, 0x52e2062d, 0x2a5372e8, 0xcec4777c, 0x6626e3a0, - 0x6b4cec47, 0xe987f1cf, 0xc925d924, 0x4c0eef40, 0xac47041b, 0x477ce300, - 0x9c049b24, 0xf6a4727f, 0x08edd3ff, 0x377ae1f1, 0xda5475f0, 0x3d203c51, - 0x468b1f79, 0x3450883c, 0x17e70c39, 0xad17cf1c, 0x4a434f45, 0x5868e348, - 0x875f9a5f, 0x79a663f4, 0xb09be62b, 0x3fca1edc, 0xacc9e58b, 0xba5e5d3e, - 0x55e3bd18, 0x6eda1759, 0x4291c203, 0x38445e70, 0x9bbf5096, 0x94203f30, - 0x1fd625ff, 0xb7f7eaca, 0xceed251f, 0xf9c29e0d, 0x003b2ebf, 0xd6dbc29f, - 0x2e94adc0, 0x7c106e0e, 0xec0f9a26, 0x75fe418c, 0x9f0cfd7e, 0xd767e289, - 0xea0b9338, 0x8398df9f, 0xefedbcf9, 0x5e5a24db, 0x20945db5, 0xd679d86f, - 0x5bf141d6, 0xfc7f6a63, 0xb83dfa66, 0x602f245d, 0x9f71d377, 0x48b4e29d, - 0x92f9633e, 0xdaad9628, 0xc01e6bb0, 0x91336b2d, 0xeaa70a28, 0x6f3bd2cd, - 0x03d2f9a6, 0x552a8132, 0x838cea9b, 0x4f897e69, 0x8afc8168, 0x3f601f9d, - 0x0ca4b9dd, 0xe039f7f6, 0x752f945b, 0xee93dadb, 0x7dcbdfa6, 0x7ea00a5b, - 0x09c166f9, 0x7ebe5c4b, 0xbf0087d7, 0x211e55bc, 0xcd15f852, 0xdaa1c431, - 0x17db792f, 0xade309df, 0x9426477a, 0xabb291ed, 0x1891190f, 0xe02346a4, - 0x13d36ab5, 0xe79be046, 0x1fb0073c, 0x2f559f05, 0xbb687ed3, 0x2704d7ea, - 0xc0daad4c, 0x3785cdf8, 0x68bce6a3, 0x19d57981, 0x37fb4147, 0xbd42351f, - 0xebf15f52, 0xdf180e51, 0x8c016306, 0x6306fd73, 0x566f8a89, 0x3356ff34, - 0xe94d53ae, 0xbd19dd03, 0xce39e7af, 0x397c95b7, 0xdf484015, 0x4338cf92, - 0x339e87c5, 0x57fd21c4, 0x11c48b34, 0xdf781f81, 0x8760fbe7, 0xbe03f195, - 0xc0ed4b5e, 0x75ebc21a, 0x4fd7cec9, 0x88cd660a, 0xe71ee7c0, 0xcb91a3f2, - 0x7e41278f, 0x2e69f4d0, 0xf971d63f, 0xe271e4d1, 0x933d67f7, 0x71ef5d30, - 0x67bcfa61, 0x4f3ea61a, 0xc17bd611, 0x8dd30733, 0x7f7e371e, 0x698653c9, - 0xbf16a7b3, 0x8e59e2bf, 0x178f66e9, 0x59e6bfbf, 0xa78b6983, 0x9eadd311, - 0x3d5b4c26, 0xbaf7ac3e, 0x36d319a7, 0xff7e0b4f, 0x530da7b5, 0xe98027bf, - 0x9a5f584e, 0x98ed3c06, 0xc31cf6ee, 0x03a7af74, 0x9cf7eddb, 0xc72d74c1, - 0xe49b2dbb, 0x366f1448, 0x18394117, 0x91cae85f, 0x88be3e69, 0x7ae693e5, - 0x9f348c73, 0x8a79a6e4, 0x8195c1c7, 0x0fcd131c, 0x29e565ae, 0x66b9243f, - 0xb2f14f9a, 0xaeb5b4f2, 0x4f9a28dc, 0xa3e5646b, 0xa3737bd6, 0x8f947e69, - 0x39b75f95, 0xf3431b90, 0xf2b0b5d7, 0x67927eb1, 0x01b1f9a1, 0xd07f1f96, - 0xf9a56795, 0x9f2cedf1, 0xcf37a1f5, 0x1d59f346, 0x5d4dfdac, 0x9a58bc81, - 0xcac829bf, 0xf24ab96f, 0x2e4003ed, 0xb5cf980b, 0xd1c7e4e4, 0xe59dae7c, - 0x4b16860b, 0xb7f4088e, 0x0858ee53, 0xb0867c22, 0x7e5125d1, 0xf1d8d3b3, - 0x647d1510, 0x4baaf0a1, 0x2033fca2, 0xfe504593, 0x963af0b0, 0x19648c07, - 0xbc2a3f94, 0x65bbe58d, 0x5cff9607, 0x46f2c038, 0x87ff9607, 0x7bf30870, - 0xef961765, 0xf2c4fe10, 0xff961746, 0xf981385e, 0xcb1bb2fd, 0x962e853b, - 0xfcb1ba37, 0x5753e949, 0xdf2fed3e, 0xdc2e9ee0, 0x5ddb7208, 0x6a597286, - 0x597e0649, 0x04fff9cf, 0xaf2d0640, 0x3944641f, 0xacf3f3b8, 0xd3814517, - 0x97c800f6, 0x05fa04bc, 0x485b3385, 0xc2827d04, 0x7386fb11, 0x349317cb, - 0xa2f96e70, 0x20f3814c, 0x1fea89c2, 0xdc5f9d9c, 0x17cf1da4, 0x129c0ae5, - 0x7fb5979c, 0xcbe5baf3, 0xbe78ed6c, 0xd4e054ac, 0xfeb89c20, 0x4f20278d, - 0xc809c0d4, 0xe59c0aa5, 0x7fb12708, 0x271971e3, 0x8cb8e06b, 0x7538144b, - 0xff506708, 0x378c04e0, 0xac63c76b, 0x863ce050, 0xbfd61e78, 0x534cb979, - 0x5531e3b4, 0xc29e7029, 0x0ff6a4f1, 0x16ab6ece, 0x21adbb3f, 0x3847acfc, - 0xaf37fb23, 0x3f169b5c, 0x7e10b6b9, 0x6b9c2136, 0xb76707fb, 0xdd9f8b4d, - 0x5e7e10b6, 0xe98cfc43, 0x6372bcdf, 0x8dc9f8b5, 0x0de7e10d, 0xfeb8cf1c, - 0xa26f678d, 0x137b3f16, 0x2009f843, 0x37fb1b9c, 0x2d24fc9e, 0x4293f27e, - 0xe10779f8, 0x9c1fee4c, 0xfc5a49bd, 0xe10a4dec, 0x67080fe7, 0x95e6ff4a, - 0x9f8b503f, 0xfc2181fc, 0x7270807c, 0xa94ccddc, 0xbdac70a4, 0x4c3fd9c3, - 0xc3fd9f8b, 0x8939f842, 0x3852a670, 0x29c37de9, 0xa7e2d148, 0x9f842520, - 0xb6e708f3, 0x9fd9c1fe, 0xfecfc5a2, 0xae7e1094, 0xfa3b9c20, 0xe182af37, - 0x0c14fc5a, 0x55b9f867, 0x8672871a, 0xd8274eca, 0x9a19dfe7, 0xc13212e3, - 0xd179624e, 0xf7a024ee, 0x433e8a88, 0xad225dda, 0x371cd96f, 0xd6a231fe, - 0x068d726b, 0xaa56cf4a, 0x9af5a9e5, 0x1ad149d8, 0x15ce2a3d, 0x4c27c9af, - 0x9fa9ac1b, 0x29a69458, 0x3ae7381f, 0xf720f94d, 0x487e4d78, 0xfa9a4dd9, - 0x35736ac3, 0x6fcbe1f9, 0xf54fd4d7, 0xd3e4d4ce, 0xa9afdcd7, 0x8171b23f, - 0xa69afca6, 0xb5f94d72, 0xfc9aa5be, 0xd7dfcdf5, 0xb2d31fd4, 0x437e5342, - 0xf29a63db, 0x35278171, 0x9e0709f9, 0xb1bfd4d5, 0xf94d05fd, 0x68af63c4, - 0x6c7727ca, 0x3e6fe4d5, 0xfd4d6bf3, 0x9addc129, 0xbd9fadfc, 0x439fa9ab, - 0x6fab53fe, 0xd4d03f9b, 0xa13f6a9f, 0xf24eff29, 0x553d3a27, 0xccaf1f6b, - 0x32afcc21, 0x01afd988, 0xc6f311ab, 0xa76616c1, 0x271c4b58, 0x7718fd29, - 0xa00c742f, 0x033403f4, 0xe0ce5176, 0xe83a6bb2, 0xe4ddeff7, 0xbf4ec6be, - 0xbee8cf7f, 0xbf411ec1, 0x9026f4a1, 0x061d4864, 0x8fe5f548, 0x73de8cca, - 0xd51d5c87, 0x18d7db49, 0x68e2a382, 0xe73123fe, 0xf9c7a03e, 0x83ee0306, - 0x42d49168, 0x411368bd, 0xd4d1e9bb, 0xaabd17ac, 0x1866b0fd, 0x308433d5, - 0x3bb235dc, 0xc328f519, 0x9bd03af8, 0x79d187ea, 0xd164260d, 0xbcbb718a, - 0x61fb6823, 0x8fe0c925, 0x3f991930, 0x91bfd424, 0xfd819ff6, 0x6bfe812f, - 0x94dfe97a, 0xbfd34936, 0xd34ca539, 0xfb48d9bf, 0x90f213b7, 0xbfde26e1, - 0xcb36fd19, 0xfec64c56, 0xd865294d, 0x6a46a3ff, 0x8ffba977, 0x88fff50e, - 0x31ebf681, 0xc7b9bb30, 0xd26ed3fc, 0x5ca53fce, 0x9b237f3b, 0x2e434aff, - 0xe71a3fef, 0x0e456abf, 0x394a7f9b, 0xc189bf9b, 0x0b6ff50d, 0xfa01bfe1, - 0xfd2f69ff, 0xb5b3d29b, 0xa95e1ff3, 0xf589bf9d, 0x76e194ff, 0xfb05bfde, - 0x6dc57a7f, 0x2bc3fe6c, 0xc9a37fb1, 0x31fa04ed, 0xf5ae890e, 0x50c9fed1, - 0x040d256a, 0x40fda172, 0xfd1e3a3a, 0xd21a7708, 0x8bdf1c70, 0x2576f466, - 0xf21bd29a, 0xc3b32f33, 0x5273947d, 0xd39aaabb, 0x1ce6c57a, 0x2c3df023, - 0x3164224f, 0x36a2ea1f, 0x3c9be911, 0xa48df26d, 0x26d0bde3, 0xe8bf217a, - 0xe03e29e9, 0x322635af, 0x49da08bf, 0x3fdf0024, 0x1798d9fe, 0xa7d2f3d4, - 0x53e51b8b, 0xde45fc91, 0x96ba325c, 0x1002ef8e, 0x9c7f2a81, 0x186071da, - 0x1eed487f, 0x139fed42, 0x23efeb32, 0xbe41ef6a, 0x687bda83, 0xe63a9338, - 0xdebaf357, 0x5fc7411f, 0x0b9f9444, 0x6e2f79e7, 0x624f0a29, 0x5af8f7fb, - 0x31eb07c1, 0x450c797f, 0xc53c787e, 0xbe4d04de, 0x07eac4c6, 0x2f7c136f, - 0x0dc30808, 0xe1c199f8, 0xcd2f1811, 0x36b3b1cf, 0xb1de7747, 0x7dd1b05f, - 0x5d0866b4, 0x599c308b, 0xa40f25c4, 0x565eefed, 0xa76b832c, 0x8186105d, - 0xa166b09f, 0x3768024c, 0x0649137b, 0xde3a0e27, 0xfe0cedfb, 0x527c970c, - 0x239b47ed, 0x74455d9b, 0x458a733c, 0x69acff1c, 0xed3ff2da, 0xc619718c, - 0x53cd74d2, 0x45ddcfd8, 0xe77bf2da, 0xb9f7f368, 0x572a79b5, 0x0fab9065, - 0x53bfe994, 0xdf8124b4, 0x001bf431, 0xe3907ce3, 0xd95ac1e1, 0x6a5759ab, - 0x72951b76, 0x09b88470, 0x8bdb0bce, 0x5fcfeb3d, 0x7b17cdae, 0x6b85f9b5, - 0xdd39f074, 0x7febe29c, 0xa683e81c, 0x283e81a7, 0xfa724f3e, 0x2d55f308, - 0x9a13dc7d, 0x650fa306, 0xb624a71e, 0x33d6a704, 0x18dc58fa, 0x8a1e9913, - 0x52e0f443, 0x0f4297d3, 0xfc3d38f3, 0x6943d399, 0xeeae9693, 0xc9d5be23, - 0x6b03fdb4, 0x1d3ae177, 0x3d198a11, 0x87a140fc, 0xb83d0d0e, 0xd7e83d39, - 0x87a71e6f, 0x7a308f79, 0x0767afd0, 0xa68e87a7, 0xeb4932cb, 0x1d74aeb9, - 0x0eba7934, 0xa3b775ba, 0x47ae8a1f, 0x10587a44, 0x389d379a, 0x65e42fcd, - 0xd38bd63d, 0x01a79603, 0x09e209da, 0xacf7a7db, 0x2684f94f, 0x7914da5f, - 0x36da6bfd, 0xfaa93dac, 0xf2f2d55e, 0xbb7fb55a, 0x268b79a2, 0xa6f7c4bf, - 0xd3697ea6, 0x717e4d2e, 0xfa9a3be3, 0xd21cd70b, 0x7fbd8be4, 0xbf9fd4d4, - 0xfe5353bc, 0x4d59ed60, 0x176503f9, 0xdcfbf935, 0xbfd4d37f, 0x13f08e77, - 0xa2eefe75, 0xeba89fa8, 0xa7169acf, 0x0d70cfc9, 0xec37d4d2, 0xa02ef6bc, - 0x8bef83c7, 0x4f8ff404, 0xffd1a79d, 0x7653a9f9, 0x1e939d42, 0x5383ee07, - 0x9e98d19e, 0x9f7138f1, 0xc24cf39c, 0x1edb42f4, 0x2a15c80b, 0xc8e04b47, - 0x96e574a6, 0x20d935ba, 0xdfca09d7, 0xd46f958a, 0xb2128779, 0x8a639414, - 0x2326c2ef, 0x44204c09, 0xc7c4e100, 0xe5551415, 0x37947d1d, 0xd0914151, - 0x23b0bcb3, 0x279af7f2, 0x23db878b, 0xf7847f9c, 0x7a021935, 0xe72f7752, - 0x29029524, 0x64277f52, 0xad81f205, 0x34a94f5c, 0xb9517e32, 0xb12e5075, - 0xaa303e41, 0x6bfaabf6, 0x206c9ba1, 0x66ba49d0, 0x5d36973f, 0x04f7e1af, - 0x4089cfbc, 0xdf34136f, 0xd66f9a2b, 0x25daebb4, 0x81abb8e2, 0xfdb95097, - 0x527a292a, 0xd8153e04, 0x0c6b3293, 0x14f5d38c, 0x5112dbe6, 0x34f2ec8f, - 0xc7f385af, 0x4c169e73, 0x30da78cf, 0xac09e53d, 0x93c07385, 0x1e98039e, - 0xda63b4f7, 0xe98639e1, 0x4c0e9e47, 0xc19cf43f, 0x209e4ff4, 0x9f3cc7a6, - 0x43c47a61, 0x0e70027e, 0xfe98cc7b, 0xb4c763c1, 0xe98c93dd, 0xfb0f8f05, - 0x5f5df651, 0xcb867774, 0x7f4073ed, 0xbb6ce811, 0xcd6eac78, 0xbd9d30d0, - 0xa423f2b9, 0x85cf0533, 0x0f4e264d, 0x087a1a49, 0x2377ed80, 0xe51f4bd0, - 0xc3a7324d, 0x2e47dade, 0xbfe179af, 0x7caede87, 0xd30b7a4b, 0x3d1d10d3, - 0x4f45f7a5, 0xe9e9aa1f, 0xe4cec18a, 0x1fa7a720, 0x7d6b73f3, 0x3b1251bf, - 0x77e90ca7, 0x800cdbae, 0xdcfca5aa, 0x98699084, 0x5efbc4bf, 0xa3b5c149, - 0x0d1be81e, 0xe8d2eb72, 0x73828fbf, 0xe8c74b87, 0x3ef6a7e2, 0xf49d3d3f, - 0xda17778e, 0xba3e2543, 0xc61109e8, 0x1af0cd1b, 0xc8d32065, 0x461a4278, - 0x905ce4be, 0xc4897981, 0x739f7b43, 0x3af38446, 0xc06b7542, 0x5d785f6f, - 0x1632bd69, 0xf67a9de0, 0x5e90591f, 0xf475fae1, 0x7cf5111e, 0x09d17812, - 0x25c90df8, 0xfc193393, 0x4691c1f3, 0x6409ea3b, 0xde7f16ba, 0x6bf835db, - 0xcfce5548, 0x7f11931b, 0x1a8cae23, 0xf5fc0fd4, 0xc2fbdfc5, 0xf79802e7, - 0xfb3e037f, 0xf17d8fe2, 0xbc72e245, 0xdfe746d6, 0xf8cc73bd, 0x07c01cc7, - 0xcadf1abf, 0x3c7e9c79, 0xb5f492f9, 0x493bb8e8, 0x14f6e3a1, 0x24d85b88, - 0xa5fe11da, 0x61626bd6, 0xfa70425d, 0xede14f58, 0xbd80a73f, 0x0b553e7f, - 0xef074b2f, 0x6d1781d2, 0x4d2d7760, 0x3270d85e, 0x69283ac2, 0x835d4b55, - 0xb687ad45, 0x1a97f369, 0x382d6985, 0xecec472e, 0x6a272031, 0x5edf181b, - 0x6702a98e, 0xf6097269, 0x3d39ae73, 0x3e7bd996, 0xc7360fc6, 0xe738bf21, - 0xfffac329, 0x06f4f1ec, 0x210f1947, 0x1984e4ad, 0x4b2d31f8, 0xaf7ebdef, - 0xc5fd2cf4, 0x7edde788, 0x89e80af9, 0x97dffa66, 0x09107760, 0x9adc0af3, - 0xba6bd116, 0xd66fbe01, 0x39db47f4, 0x2fe23394, 0xdf6abed3, 0x4294e448, - 0xd45e54b7, 0xe780bd83, 0xd41a4b9b, 0xcb55597a, 0x9af93577, 0xd41a47b6, - 0xfc055c7a, 0x525ff283, 0x3740482b, 0xba8c9c95, 0x811acb25, 0x8218af8e, - 0x088f804f, 0xb9955eac, 0x9fa6e8c3, 0x75b2b7ce, 0xe77c6deb, 0x8854e63c, - 0x3733283b, 0x597239e2, 0x20f9b5cb, 0xaeb7ce67, 0x5bf9024c, 0x5efa5e21, - 0xbff68451, 0x5f2e0494, 0xcf56a0e4, 0x2841f4e7, 0xe9bcd55c, 0x17c212cf, - 0x981977cd, 0xb70f465f, 0xbe91cb8d, 0xf9bd53f0, 0x8ecdc150, 0x6eaa789e, - 0x237468bb, 0xcbffa45f, 0xc149e30a, 0xd454b15f, 0x9771d126, 0xffa27737, - 0x1dec8ce2, 0xe0af83f5, 0x67e73d97, 0xa3153e49, 0xb497979a, 0x260b3f43, - 0xe3888ef1, 0x1f280fde, 0x995bfb3f, 0x57221f00, 0x742cad69, 0xc7bb70cd, - 0x61590c40, 0x6b4167bb, 0xfbe02145, 0xd1d3ebec, 0x8a445bee, 0xa40eb86c, - 0x9cec0b31, 0x7180c4f3, 0x1fc9e755, 0xeb54136c, 0xe464b1f0, 0x305ca678, - 0x1034bb89, 0xd8107bbe, 0xf539a65f, 0xf858e2ed, 0x9076292e, 0x15ca25f0, - 0x17f180b7, 0x2f77d873, 0xfd01d731, 0x634a7b52, 0x4a7b51af, 0x94f6a793, - 0x66425f26, 0x453c4126, 0xf132d3c9, 0x4d278809, 0x8ec941f9, 0xb5252be3, - 0xfd1fa0f5, 0x16e1fb9c, 0x843489d8, 0x37aa87ca, 0xa62acb9e, 0x9892e9f3, - 0x0f894bff, 0xc5654258, 0x5e5e5a20, 0x2cba33e6, 0xa277e73d, 0x943dc275, - 0x163c03f3, 0xd1bf7007, 0x886be2c7, 0xaae2ca43, 0xf3ef5a4f, 0xba2ad81f, - 0x8f506ca2, 0x9bc6577e, 0xafe7f5fa, 0x4f212f9f, 0x9bca3ce2, 0x561c6067, - 0x3e07788f, 0x7059b91f, 0x27ec22f9, 0xf1341651, 0xc332092e, 0x1ad7e29f, - 0x0f5fcbae, 0x6bdf9579, 0x1bfcaea2, 0x440197f3, 0x258a5fc3, 0x913970f7, - 0xbfc013f1, 0x7f710520, 0xc9f8637d, 0x2f5fe03d, 0x844ff8df, 0xefbb543f, - 0xff89fc29, 0xe88ff1d4, 0x48bcfe31, 0x78deabf0, 0x778875f5, 0xcfd5ff2c, - 0xb7ee846c, 0x926352b3, 0xe57bae93, 0x1736d5a6, 0x6bc91df0, 0xd6717d83, - 0x448b4e27, 0x7997df0f, 0x59711fdc, 0xc2bbf004, 0x73fc293f, 0x4ef8fcaf, - 0x6caea3b0, 0x4fe8ed92, 0x4c05366d, 0x5bab9e94, 0xb1921497, 0xf964ef98, - 0xfd022f47, 0xc7c9b4d7, 0xfe5a74d5, 0x41259fcb, 0x94a5107c, 0x48648621, - 0x549f6803, 0x00b8fc6f, 0x121a8df4, 0x6faafdc4, 0x167ffd07, 0xd8b0f28f, - 0x1cb3db18, 0xd049341d, 0x5a6afd9e, 0xb4517c7f, 0x69db7a41, 0xb2d46fe0, - 0xbe90bf44, 0x3bb7195d, 0x00eb642a, 0xc913abe4, 0x0aabe044, 0xd98f885e, - 0x7e5f2b1d, 0x1d276c66, 0xdfc6d757, 0xbe1504da, 0x52e97b14, 0xfc5fc2cb, - 0x1f3bd1da, 0xa3f740bf, 0xe455bf5a, 0xdb8da394, 0x56967e4b, 0xc41b01ca, - 0x906e5573, 0xb9fa5e9d, 0x5f17d5f2, 0xd9fc167a, 0x4739347f, 0xaf15f852, - 0x13723bee, 0x916c57cd, 0x69b21407, 0xf0a48458, 0xffd0d4fa, 0xaf0f8f96, - 0x7db6f947, 0xf618c746, 0xe1f187fd, 0xb2d8a975, 0xf4c648cb, 0xcb5e47c4, - 0x2587632e, 0x74b4fac2, 0xb7fe8016, 0x1abfe5f2, 0xdd9def81, 0xa9819029, - 0x61b9f011, 0x8087ea1f, 0xbe4f5c27, 0xd3f5a15e, 0xeba1afd5, 0xbf467202, - 0x857afa5e, 0x5c00bf9c, 0xf4a1b388, 0x21afdafd, 0x264fee0e, 0xeca1e027, - 0x306c87b5, 0x2d52d39f, 0x56e7f3a3, 0x2bbf0127, 0x7649bd93, 0xb2f7d94c, - 0xfa461fe7, 0x70f43d2b, 0xba57f312, 0x76501906, 0x3cc1077a, 0x1bbfaf17, - 0xdc4259e7, 0xcf658748, 0x9a3e4589, 0x69912a7e, 0x93ec225b, 0x9c9f7c4b, - 0x2e2e817e, 0x4569e79d, 0xe441fc2e, 0xe8bbe172, 0xcf987d0f, 0x98906a85, - 0xd6ccd4ff, 0xd06c80eb, 0xfd10d1c8, 0xe5147c6e, 0xae61b9c7, 0x56ee7081, - 0x28179613, 0x5343c447, 0x6275b207, 0x51db0772, 0xdf0793b9, 0xecbb7ea1, - 0x69ab1a8a, 0xe9467287, 0x9fef197f, 0xf41a3b8e, 0x9149d3b7, 0x46e191ed, - 0x3d500f85, 0xaa674543, 0xfff6cefd, 0xdfb606c6, 0x9beffd95, 0xffca0d31, - 0x23ed9872, 0x97720768, 0x10302b8e, 0x16cd77cb, 0x48983f90, 0xdf3ed220, - 0xae7df328, 0x0bd3d72d, 0xc424bf1d, 0xfa06e8aa, 0x4075c789, 0x34f25f79, - 0xa3e2af6d, 0xadafd035, 0x1f655c27, 0x707e7297, 0xf5c1f81e, 0xd6407e61, - 0x5e2bf627, 0xbdf652b4, 0x5fec2cf4, 0x0ebd5fba, 0x1172bfd8, 0xcd93ffcc, - 0x4fdc8e7b, 0x2d27edf7, 0xf2d5beca, 0x2dbefd55, 0xc630fadb, 0xedf7eb9f, - 0x496b4327, 0xbf4b7dc4, 0x43b7dc47, 0xf847fe3b, 0x24c782aa, 0x2aaf96a3, - 0x7c37b27c, 0x16e4f9ea, 0xd57881d9, 0x3bfa49f3, 0xd27ab24c, 0x0a8742a3, - 0x47ff95fd, 0x47e070d5, 0xe8553a21, 0x0aa74430, 0xade7ea1d, 0xfcbea3c5, - 0x522df023, 0x537a297a, 0x4a95f3c6, 0xa6038b3f, 0xc90ff6ed, 0x50b97c44, - 0xfdc691cc, 0xf3a80643, 0x45be5d3e, 0xcba5df57, 0xbbeae917, 0x4d5af975, - 0x3db6cafd, 0x10748246, 0x9713d4d0, 0x31393bff, 0xfadd1221, 0xf5a1bf98, - 0x39ee11a2, 0xd88258d4, 0xbc415e5e, 0xdc191f10, 0x51b9e221, 0x3d71c537, - 0xa73637f8, 0x8f94bcfa, 0x7e628eac, 0xd07b6e85, 0xd5d34f16, 0x4c1f2c71, - 0x1f03d634, 0xa307be54, 0xbbb1df98, 0x538b6828, 0x7e9d5bd9, 0x8778f911, - 0x0dbdf22f, 0xdd70692a, 0xd7b97a3b, 0x758f9ca1, 0x62c6db47, 0x3e29d17f, - 0xa2a9c7a0, 0xf8396525, 0x27451aa1, 0xea8bece8, 0x79c1b5ee, 0xfd3fb755, - 0xfbf439ae, 0x164477e2, 0x4975e38e, 0xd0765483, 0x975de219, 0xf05c402d, - 0x859fa45a, 0x2d17667e, 0x3f791b5a, 0x2576f394, 0xe0466596, 0x390ed4bb, - 0x51ef3eae, 0xd7ad94e0, 0xe74ff77d, 0xed11a6fb, 0xda8df2ff, 0x9fb73772, - 0xfce4647f, 0xc7191c67, 0xbfe657ed, 0xaa7b7ce1, 0x1cd77198, 0x07dd3eba, - 0xf9a26244, 0xd7117e4b, 0xc166d2e7, 0xe237fe07, 0x57fdc44d, 0xf546824d, - 0xd82e887d, 0xcef4d75f, 0xffb6bac7, 0x4007eb39, 0x307faf47, 0xda69dff6, - 0x471ffaf5, 0x37f905bd, 0x407ca68e, 0xdbcfd67a, 0x02f18519, 0x48ad3bdd, - 0xde3bddff, 0xe401f94b, 0x613934df, 0xff3bdd9c, 0xa9e8163a, 0x0ca9857b, - 0x30f760f8, 0xb95dbfe6, 0x3b63afe3, 0xc2aefe50, 0x1a366c75, 0xffc99f99, - 0xdee08f8f, 0x9d3f25c2, 0x3c17e815, 0xd7e6beae, 0xf0823e51, 0xbea59aff, - 0xe76df40f, 0x43e3cd53, 0xce64adba, 0x1c5f1856, 0x79a87f8b, 0x758bf26b, - 0xd6aaffb4, 0xb485c65d, 0xcfedef3c, 0xfd1c62c7, 0x5d37a656, 0x879e3b90, - 0xc66d87f8, 0x2994acef, 0x26c02f9e, 0x5df646a3, 0xb07935a6, 0xe5e27a8f, - 0xf5a7f473, 0x1aef1f17, 0xaffd7d99, 0xc5c10f8f, 0x67d59ff8, 0x7fde6016, - 0xf403e8fb, 0x2e909a83, 0xd27ef995, 0x4cfa8752, 0xfb3ef35f, 0xfa0e86bf, - 0xd0216f3b, 0x4d9b799f, 0xfdebdaff, 0xeb81d1b8, 0x3d07dfa2, 0xf7c77ce9, - 0xd5aaff30, 0x27ede389, 0xfd368fbd, 0x5beeb63f, 0xfadbbae9, 0xfe77f79e, - 0xfbdde7c5, 0x8f33bfba, 0xce1dbbaf, 0xfede6b53, 0x75f7c71c, 0xffe95cf9, - 0xf457ba52, 0xad4376fd, 0x6f8e933d, 0x82b4690e, 0xe25f7162, 0x03a64b25, - 0x0f2f70a2, 0x383bf8c0, 0x57608d5f, 0xbf989935, 0x581824cd, 0x82dddabc, - 0x3b4447e2, 0x5fae4eeb, 0x0cb439dc, 0x5d3b90f5, 0x827d413f, 0x39edb548, - 0xee7b7eb4, 0x6ac62742, 0xdcc7f192, 0x853d9f90, 0xe6f6b5e7, 0x12e204ef, - 0x677f7ea8, 0xa003f4ee, 0x12e5dee7, 0x29a60f51, 0xa7efbfea, 0x93efb014, - 0x7dd0f6b4, 0xdefe6d6e, 0xddfcda39, 0x843dde1c, 0x229eff8d, 0x587e07c1, - 0x8953ce53, 0x2d3597e0, 0x0a908996, 0xabb54671, 0xbbb8eec1, 0x197edb48, - 0x7f2a6728, 0xe3c537e3, 0x5c78436f, 0x3921788a, 0xed03de22, 0xdc7c8f13, - 0xf9c7b3ed, 0x489ace20, 0x7bc7864e, 0x37e89caa, 0xccb8f6e7, 0x3596cbdb, - 0x659fb0ed, 0xd8ae1d9d, 0x9be1bdd3, 0xe11cfb70, 0x2ff185a4, 0xcfb444bb, - 0xae7d9d65, 0x5dd7cbac, 0xbf1d650f, 0x073cbaed, 0x786372eb, 0x5c5a865d, - 0xccabf604, 0x8b7c87ed, 0x1687e593, 0xe8ae7611, 0x00d2fac3, 0x8466f117, - 0x9897d1e3, 0x9ce02b8b, 0x405a3ccc, 0x6b5dc87f, 0xe60f9445, 0x55c7010c, - 0xf8c64934, 0x450d8fe3, 0x85deb059, 0x7f562613, 0x09c30d9f, 0xf1c25cf8, - 0x516a425e, 0xbf57257f, 0x0b3b32fc, 0xea0825ce, 0x845c4bbf, 0xb8ed41dc, - 0x10216c92, 0x126af10d, 0x078ec6f1, 0x8e40b93f, 0xdae4fc6b, 0x496efc3c, - 0xabe9c30a, 0xe5fc6f7e, 0x17fe9d9f, 0x29c767e5, 0x3a427491, 0xd497bb12, - 0x3f7cf776, 0xa54d63c3, 0xba434be0, 0xfbeac80b, 0xb66605d3, 0x87ebfe0f, - 0xe64f9013, 0x2c4c74fc, 0xe26407f3, 0x6e1ac47d, 0x3af25c37, 0x760fc162, - 0xcfce9fc9, 0x6a6cf373, 0x87a4aabe, 0x9ffe1db8, 0xd3489710, 0x51a17cee, - 0x048b3b04, 0xcdebffd1, 0xc57bc28f, 0xcca376fa, 0x6bafbe06, 0x3f002fd1, - 0xf2afee11, 0xa6d29479, 0x75aaf1b1, 0x59c77b5b, 0x75cf6c69, 0xd571df80, - 0xc5b7ddf9, 0x80fdd82f, 0x1d5143d7, 0xe6114505, 0xafe3893b, 0xf0dff770, - 0x7f4ceafe, 0x99780caa, 0xce6a2f99, 0xee669df9, 0x264098cf, 0x770ab8c0, - 0x0c9b66df, 0x744072eb, 0x1ad57dc2, 0x3ba345ff, 0x1eb1f9c2, 0xfc1f009f, - 0x676427f0, 0xc4f3e009, 0xd808a24f, 0x73f1efd5, 0xcfb80cc9, 0x1eae8191, - 0x731df817, 0xb84fcccc, 0x74c76cce, 0x9c8e6156, 0x68cdfb48, 0x50838fb5, - 0xfebcc1b5, 0xcb03b33a, 0x4a76f087, 0xac95c1bd, 0x5ed1a75e, 0xbffe691d, - 0x79f8128b, 0x937bf399, 0x75bd7f84, 0x35a9f9cb, 0x41fa0b90, 0xd167e2be, - 0xfdc135d3, 0xe09a6971, 0xf60df903, 0x050be630, 0x53de1fd4, 0x64cfafee, - 0x7ba15672, 0xcdab9e3d, 0x1e02f7da, 0x887f78e7, 0x678287d3, 0xf1fabf05, - 0xbf29f52a, 0x9fed55ba, 0xdc6dabba, 0x54dfa06b, 0x81bb05fb, 0x3a96aa82, - 0x6b0fb08c, 0xe1909eda, 0x073ee67c, 0xa2a44b83, 0x83f8eab1, 0x0f166675, - 0xcdfc67b2, 0x2e4e80f3, 0x2c8135af, 0x1745ae24, 0xdf87c06d, 0x0f7f3833, - 0xdfde6c71, 0x57d36489, 0x3c0fabf0, 0x597cf2f6, 0xe715370d, 0x4732ab33, - 0x03da7706, 0x81e4bb95, 0x675a7a2a, 0xe572c78e, 0x074ae0fb, 0xfb420fbe, - 0x1f7871c3, 0x4fb81137, 0x8ed2d192, 0xa81f6cf7, 0x5874638d, 0x88cbb2d6, - 0x7bcd54f9, 0xfa3f4a22, 0x50bb34fd, 0x30bcaf1b, 0xe02863af, 0x5814d0a5, - 0xa7408ce6, 0x7394a393, 0x2729afca, 0xc76e945c, 0x27247ffe, 0xa2722996, - 0x95e3e303, 0xe7df02f6, 0x3031392a, 0x5a589c92, 0xeb0818e7, 0xfa4774b0, - 0x4b24d840, 0x149a99df, 0xefbc4e49, 0x47cce761, 0xeef67df9, 0xdc4e54d9, - 0xb31392a0, 0xf44e90a3, 0xf6513eed, 0x42725f49, 0xcbffb759, 0x907de6fc, - 0xf7f61113, 0x71393a17, 0xe518bf8f, 0x45b33dc4, 0x4facbdcd, 0x391394fb, - 0x5e61f749, 0xa044c676, 0x7db9f79f, 0x0bdf9473, 0x5e407e80, 0x11d94664, - 0xd1b97a6f, 0x53ff5f1b, 0xfffaf97f, 0xbe159e10, 0x3fda94be, 0x7448d4a6, - 0x979e9048, 0xbaf947de, 0xf8c8f400, 0xb907d2fa, 0x67c7539f, 0x66cf808b, - 0x6b2cf9aa, 0x7266ed5f, 0xf52da6a1, 0xfcb4b999, 0x09d946fe, 0x30fef2a2, - 0xf352cddf, 0x5ea8ccdd, 0xe3196ef8, 0x13fd97bb, 0x6dea7f50, 0xfce67f7e, - 0x11b3f296, 0x31f408ce, 0xe68c6e67, 0x7189dede, 0x06d8c9bf, 0x113de5fb, - 0xe63f79cf, 0x71c1c07a, 0x7d04c9bf, 0x9e3e49fa, 0x2f3d7c79, 0x3e794878, - 0x22de5fc5, 0x6d574fa6, 0xd57f1116, 0x57ff6cad, 0x073e0b37, 0xff8c17cd, - 0x56d79e1b, 0xb5e760ec, 0x39850674, 0x78aff5aa, 0xce1ea3af, 0x08362a09, - 0xf70cde78, 0xa59f001e, 0xce259f1c, 0x29573c0a, 0xc1fad26d, 0x2f6da21b, - 0x1e101b90, 0x78abc3fa, 0x105342fd, 0x7f0a1dcf, 0x20373829, 0xabb6d49f, - 0x59fb711a, 0x9a2a4fb0, 0x0d9ddf75, 0x3704ae78, 0xadaf41d4, 0x7b96d16a, - 0x8b17bcf8, 0x146d8c81, 0xb33df93e, 0xf778f4f3, 0xf653f1e8, 0x8873f12d, - 0x9ff327e2, 0xfe259f87, 0xf05e785d, 0xc7a2f175, 0x3f145d47, 0x324f181f, - 0x6c7e3f61, 0xf17f2170, 0xbbe22bbe, 0x189e8b4e, 0xe50f79a9, 0xef2f1ca7, - 0x83f5dc19, 0x80b55ea0, 0x6fd74af5, 0xf34497d9, 0x38c85b73, 0x6d286638, - 0x90e3cad2, 0xa0756ffc, 0xbb5b9f7c, 0xdab88045, 0x60befcc5, 0x7c09ef99, - 0xe5c1e63f, 0xfad3de54, 0xdc9bc70b, 0x287e5e70, 0x53fc882a, 0x409ddfa1, - 0xfa6f94bf, 0x0c4e38f9, 0x9ca3e60e, 0xb8ec136a, 0x4c51032f, 0x8275d16e, - 0x4cf66d77, 0x5f016bfe, 0x6a5fe617, 0x4358eb63, 0x75f60dd7, 0x5be79f81, - 0x80f83e98, 0xe73b22ff, 0xd992eff4, 0x490238fb, 0x44e77e40, 0x8f915cfb, - 0x939aee70, 0x1ddf5aa4, 0x37fe8c9d, 0xe0fc4e09, 0x36fbffa3, 0xbacbdbeb, - 0x7f4cfa2a, 0xd3c157d7, 0x1f3add4e, 0x9c2f6a8a, 0x8272e780, 0xf20bdf13, - 0xd179e1c7, 0xfef646c9, 0x1fae41cd, 0xd805f7e9, 0x78f7ea1f, 0x21c0c066, - 0x145a7a2e, 0xbf6295c6, 0x533f4c69, 0x3bfd29f3, 0x6e375f48, 0xa3b486a9, - 0x7f8e165e, 0x066edf74, 0xd04d3fb9, 0x19d149c4, 0x27ffbee1, 0xbea397c0, - 0x36493e02, 0xc8797ca3, 0x19eebece, 0x1ef02466, 0x3235e5da, 0x06bdd1d2, - 0xe06c91c7, 0x04c98f2f, 0x83e5c7f6, 0x3b9d1e37, 0xa445ca00, 0x26f7e28f, - 0xa56b8354, 0x91aac598, 0x5c9847e2, 0xfffbc13a, 0xaed79513, 0xa097786b, - 0x7ce27b07, 0xb674bf70, 0x0754d773, 0x0f325bf8, 0xcf7386ad, 0x23f67959, - 0x1b1d6047, 0xc74fbbd8, 0x9da1e4d7, 0x0577d0f6, 0xe8c767dc, 0xbb9c017a, - 0x391ea767, 0xe0f7c742, 0xb73c449a, 0xbc4aeb9c, 0xe731ce07, 0x0e9d141e, - 0x5de16f5a, 0x7f9c0b56, 0x122d1f4e, 0x0f2f0ab7, 0xeff47692, 0xeefdadcc, - 0xca4fb0dd, 0xf7843ca8, 0x87fcca9c, 0xfc840ea6, 0xd7db017a, 0xb846dd78, - 0x74ded9e7, 0xfb4998d1, 0x00f5a12f, 0x59eb35dd, 0x028d9abd, 0xe25817be, - 0x64f9027f, 0x1f0146c9, 0xfaa769c4, 0xf5c199af, 0xbed12981, 0xf9a7b69e, - 0x700f6852, 0x03ddc637, 0x743593e7, 0x527ed89c, 0x97539e1d, 0x98b476d0, - 0x2efc6fb4, 0x5eb25bc2, 0xb0af7020, 0xe3ea526c, 0x41de0093, 0x47e509d9, - 0x08dcfd77, 0xfb479ee3, 0x2fe1441b, 0x42a63b14, 0xc103f27d, 0x152eef8e, - 0xbafb8b5e, 0x623bef9b, 0x14e2cd1f, 0xefdca204, 0x2af1d493, 0xb869d125, - 0xd7964a9f, 0x3abcc3d5, 0x06a989bc, 0x468ba7a4, 0x2927e390, 0x7f54ddbe, - 0x7164613d, 0x27bc7b30, 0xfe2a1d8c, 0x1d3a32b9, 0xcb6a2fdb, 0x98b33e41, - 0x853c6114, 0x23e98ebb, 0x7ca3ab9d, 0x94eb57e0, 0x7df029ed, 0x7e136acf, - 0x932af0bf, 0x7586173b, 0xf4fb7fa0, 0xbdc0997a, 0xd3eb95c7, 0x9e3ac1d7, - 0xe13b2cde, 0x8e7c40dc, 0xbe9411c5, 0x7b64fcca, 0xa7b833d6, 0xcb7f199b, - 0x02eeee7b, 0x94a5dbe0, 0x7e70994f, 0xe2563e5a, 0xf53e4728, 0x4be3145c, - 0xe7a57e7a, 0x1b8d6553, 0x65a1cb22, 0xd0e59105, 0x37ee7ad0, 0x6b9f2c8d, - 0xbbe98588, 0xf078c9e3, 0x0d571663, 0xf404d79b, 0x70bb20fc, 0xf3781ed0, - 0xdc819fd3, 0x3be2b4ad, 0x7d92d565, 0x83e8c09d, 0xeb9fff00, 0xec29f2df, - 0x51b9b287, 0x29d90ef8, 0x47d80f58, 0x1cf0136b, 0x8c57c4bb, 0x79e25778, - 0xf4b49b4b, 0xef21f8ae, 0xa5c48b73, 0x31655f96, 0x77aaa5c4, 0x6e9447f4, - 0xdbf33f69, 0xcab01f04, 0xdcea3fa3, 0xe62670ff, 0xe5ae38ed, 0x6b583f5c, - 0xfa3eba45, 0x40d5c5c8, 0x287ef3b7, 0x89dbd010, 0xf20f5dd7, 0x7049bab0, - 0xf4b89f80, 0x297dac87, 0x3ee30f6d, 0x5f4673fa, 0xb01dce94, 0x3fd7aa0f, - 0x6feb1fb1, 0xff001c14, 0xd46286e8, 0x22bcca27, 0x9d8df2c1, 0x79504768, - 0x7b68f185, 0xec1262bc, 0x2655ea83, 0x1562b83b, 0xb3e8527a, 0x40a7bf93, - 0xb3b1cecc, 0xb4673b68, 0x9eb2f903, 0x4239c52e, 0xfd029e48, 0xbd1978d4, - 0x3b2abe75, 0x4df48b61, 0xbd1eec9f, 0xd0227f42, 0xfe98665f, 0x33cfacf6, - 0xf69e3d02, 0x91671809, 0xf40bf407, 0x9fe2b2f9, 0x1eb51621, 0xea7d17d5, - 0xfd07b0e9, 0xe958cbc1, 0xe854fa61, 0xc7874f51, 0x8c0f7225, 0x51d5a1fb, - 0xfabc8f38, 0xce59ef37, 0xcf9e19f6, 0x923fd5e5, 0x44bafb04, 0x0a407162, - 0x1624ab5e, 0x5c63d637, 0x0719d74f, 0xba7c67f5, 0x0e8acc71, 0x20f1edc9, - 0x4a3ea9b7, 0xdf9fb402, 0xe3117e6c, 0xd2bfcf2b, 0x37ea2779, 0x003a516f, - 0x92b66ffc, 0x3e21da00, 0xade547e4, 0x1369c622, 0x4b359029, 0x712bbf65, - 0xb2bf1531, 0xb7cbbe22, 0xb4857c9a, 0x27ebf97d, 0xc25c62c6, 0x7b7fa60a, - 0x39d8115f, 0x2c63b788, 0x972a3bdc, 0x5e8e7c58, 0x345df82f, 0xdebbc3b3, - 0x7a03998c, 0xdeccd09b, 0xb96f2c17, 0xfca93657, 0x65a2fbbb, 0x939e1ea5, - 0xc33ae979, 0x3e300afb, 0x4a76fbf5, 0xcbd74e5c, 0xdbcafe8c, 0xcae7d464, - 0x805cb79b, 0x63f2cd78, 0x6b77b426, 0xc11a2f9a, 0xd5fbcd9e, 0xc41decab, - 0xa7135136, 0xae3e23d7, 0x20980c59, 0x0ab5abae, 0xbe6871cf, 0x3c2df313, - 0xc66bed1e, 0x6afc556f, 0x8a5eebc7, 0xbf6d8ac2, 0x857be1b4, 0x786c9bed, - 0xabf9aa5f, 0xc47b55e3, 0xf034b5c3, 0x4e3bb878, 0x918fe413, 0xc1cee1e3, - 0x7d21283f, 0x878dad16, 0xbf8ccd23, 0x456671d1, 0xa4350f7a, 0xe9fabd77, - 0xddcf10f3, 0xe793f5b5, 0x5f95dc61, 0xe21e7e5c, 0x6882a86c, 0xe6a53d07, - 0xfe31f795, 0x1f176955, 0x97a0edc3, 0xc3f1897f, 0x7268fe17, 0x3b0bb402, - 0xfe80a74e, 0xdfcb6171, 0x782e2092, 0xe8a98ed9, 0x3db659df, 0xedbddf0f, - 0xfa059ecd, 0x7e23f5f5, 0x7b6ebf59, 0x3c60f75a, 0xeeba79d0, 0x714227c0, - 0x2c552d8e, 0xe3c1d47e, 0x8e47371b, 0xcf11ef17, 0xaeeb3ad8, 0x5b1fc029, - 0x67d09e99, 0xba61e35c, 0x63f4379e, 0xf8f3371d, 0xbe3b96d5, 0x3cf1ae32, - 0xd7ae83fc, 0x7c6d18b8, 0x8bada7e8, 0x942cf17f, 0x1af426b5, 0x07e818d7, - 0xf47894fe, 0xd95da3cf, 0xdeb08931, 0xa4f181ff, 0x0e857eb0, 0xa69fd7e0, - 0x8cf8bf80, 0x44bf441c, 0xef098770, 0x38ef966b, 0xc2e9fb8a, 0xef1843f6, - 0xf85c784d, 0xb1fa1205, 0x03ee5df8, 0x6568d9aa, 0x1d7c90f1, 0x61d25e20, - 0x2e3cefc3, 0x12b5d192, 0x9c5bd92f, 0x3498b2e4, 0x8b0b3efe, 0xf8daace7, - 0x0c3f8f01, 0x09309baf, 0x2bf3abd6, 0x3c1550e3, 0x130f01d8, 0x91c071d5, - 0x714352e3, 0x8375bac0, 0x1e3e04f5, 0xf9a5f38a, 0xe9ef10a1, 0x8a468e13, - 0x81b0bf2b, 0x905f0fc5, 0x568fdf23, 0x626b82e2, 0xd7d6fb74, 0xbee078bf, - 0xf175f1e6, 0xa1c63f34, 0x5f051ba1, 0xf323575d, 0x846327f7, 0x85b7646f, - 0x0a549bee, 0x4f2cfbfa, 0x997dc0c4, 0xbe234ed6, 0x55d8a293, 0xdc5dbe7c, - 0x8af5d6df, 0xf5a27188, 0xbf907b2d, 0x3547f9eb, 0x8fd1473f, 0x6f1f2377, - 0x1f931b75, 0x3ead5b5d, 0xb5d3850b, 0xeba44dfb, 0x189dcdea, 0x79bfbaa7, - 0x7543b19b, 0xc3f20cfe, 0xd77f1aa7, 0x22c6bb6b, 0xa2efe73f, 0xcad9fbe9, - 0x3f8d63f9, 0x9b353f72, 0xa9fa6a2f, 0xed18b6f0, 0x3bfbbe96, 0x05eeb927, - 0x99dae778, 0x45ae751e, 0xd08be69c, 0x6462cfff, 0x3237576e, 0xa395383f, - 0x959c3ef8, 0xda2707bd, 0x5b2f51a2, 0x0c749d66, 0x665d21de, 0xcc5c6235, - 0x471e3aca, 0x326723f3, 0xeb4af7ac, 0xbbc604ed, 0xb2abf01a, 0x9bbb65ef, - 0x27273e80, 0xcfaa6517, 0x1bf19461, 0x4f881807, 0xd3ad8fbd, 0x4a7d8206, - 0x1850ef24, 0x7f699dc7, 0xb62e4095, 0x9f7f987b, 0x02313d5c, 0xf64bb7be, - 0x6e14097d, 0x04e0be7b, 0xba4f6cd7, 0x7e43f067, 0x1df69706, 0x4753bc5d, - 0x69c977e7, 0x6ad13d40, 0x1569d808, 0x4f6a8d62, 0x41d70346, 0x5e12521c, - 0x8978c0a5, 0x11e63cc7, 0x46d43f70, 0xf50adaa8, 0x5de6929c, 0x9249d895, - 0x72159dee, 0x57a50478, 0xc557a70b, 0xff65675f, 0xf03b70a6, 0x0cb896fd, - 0xbbe40752, 0x7d46ead6, 0x0b9b29e2, 0xdfd23fef, 0x88938868, 0xf54ed127, - 0x5fb450bb, 0xda3b7dcd, 0xe71f26af, 0xa613e6d2, 0xc9232749, 0x8e3e049b, - 0x7882d102, 0xe06a9b88, 0x70abb2fa, 0xdc785264, 0x19c48971, 0x2c3bf280, - 0x6e808f78, 0x1e7aaf2f, 0xdc768b16, 0x3e1a7c74, 0xe1d19b11, 0x6a71b035, - 0x0389dbbe, 0xe3a747df, 0xaf1bae3d, 0x70b56f26, 0x0911277e, 0xdcc59df8, - 0x2ffe384e, 0x4abdf069, 0x224f8a2a, 0x38c2644c, 0xde2130e9, 0x83cf9625, - 0x6fa9aff6, 0xeb01ef07, 0x0c870b5f, 0xb5efabb5, 0xe0e5c0de, 0x8a514b11, - 0xac93ee85, 0xb818b5e1, 0xb82c9d9d, 0x65a04e4e, 0x9fc801fe, 0x61e796d2, - 0xc8d08a5c, 0x5ac46ae8, 0x4466fb82, 0xad55c790, 0xd53d468a, 0xa8de2664, - 0x8e3f70f1, 0xd0f1e578, 0x3f9f8f8b, 0x28185639, 0xa50d6928, 0x1fceda35, - 0xa62c35cc, 0x4502d08b, 0x8b10fe14, 0x5ff40c6b, 0x6c9dc33f, 0x1bd30718, - 0x2877bf56, 0xc16bdaee, 0x1ba86863, 0x14c0ffba, 0x2ef82164, 0xdd0ef108, - 0x51b8720f, 0x0ec653c9, 0x463406ef, 0x332ef287, 0x698df7e5, 0xdaf37f2c, - 0x7ef0f5a1, 0xe8bda74d, 0xc78c0b66, 0xcf0ebf6c, 0x9af102c3, 0x937bd5f7, - 0x4738ca2f, 0xc1e40c6f, 0x07b7c7fb, 0x23c5fbd9, 0xfc7ba1ad, 0x59378f28, - 0xed007c94, 0x43d6a28b, 0x5aaad7c8, 0x01b9610e, 0x9e1d34f2, 0x421bc810, - 0x65bf79e7, 0xb5f2414c, 0x716b5e14, 0xb1c13c32, 0xbf6632d0, 0xb8c3c1a4, - 0x61d9bdfa, 0x6e2b483c, 0x86e1e1d0, 0x858785af, 0x87a86f6b, 0x3bfa55f7, - 0x0b174a6f, 0x73d35f00, 0xdb8ef80c, 0xf41663c4, 0x145fd0bf, 0x670e23ca, - 0xbcf72f43, 0xc2853b15, 0x97d35729, 0xaba14ed2, 0x9d26e8de, 0xef63afd8, - 0xe7e96a83, 0x87ae2ddf, 0x8b32de00, 0x8896dd2b, 0x0577c7f3, 0x8b8bbba6, - 0x74c213f2, 0x09ee2c4d, 0x11feaef0, 0x5a1f82cb, 0xe9dafe54, 0x34c54b39, - 0x011fde3a, 0x3c31b823, 0xdee5c49f, 0x9e7451a8, 0xc6032e89, 0xb8b11fd5, - 0xdb3b4057, 0x6200609c, 0xf71226cb, 0xf70c4104, 0xfa8feca3, 0xaf8ecc1d, - 0x56f8362f, 0xfc60f3b0, 0xfa611dbb, 0x47d1d0e8, 0x5b47d190, 0xb547d227, - 0x47d193bf, 0x346e5d5b, 0x3b03573f, 0xc70491ba, 0x5937bac1, 0x61a40b0a, - 0x82626e94, 0xb23740f5, 0xc282b6f7, 0x3aebc428, 0xf58f5f18, 0xe652e3e1, - 0x36fadbd5, 0x71fb481e, 0x0799d806, 0xa61e780d, 0xb7a94de0, 0x46e2c2c3, - 0x7ee6cdff, 0x99a9fa11, 0x961fb1d4, 0x3f81eb6f, 0xed875c60, 0xd05dcce0, - 0xae9b36de, 0x6fdc2390, 0xf815c1e3, 0x7f23784e, 0x04963bd7, 0x7bd720bd, - 0x3fdb07c7, 0xde807c21, 0xe8f80193, 0x0af2fdc4, 0xdd9667bf, 0xce40b826, - 0xef618f0f, 0x616ebc90, 0x16bbf576, 0xaf4ca791, 0x5bb83c49, 0x7b2bfb04, - 0x27eb0195, 0x9ea19a42, 0x5f5e2aff, 0x95ddf8d2, 0x89e85575, 0x7818d272, - 0x78f9e4cf, 0xfd2d1ef7, 0xa9a4c7c4, 0x1eed29e0, 0x45a290f7, 0xee265094, - 0xc810f05d, 0x3e3f4a55, 0x7231bb4d, 0x442de014, 0x233e943f, 0x776d0fad, - 0x7c6bad88, 0x5b0be80c, 0xf1152ef6, 0xae7e8e5d, 0x47bc166b, 0xc567eb49, - 0xb4adda90, 0x4d2c567d, 0xf3c09f21, 0x087e7903, 0x743fd34b, 0x7dfa041a, - 0x9ecbf703, 0x922578e5, 0x6399bafd, 0xb8f4cf20, 0x9418e4ec, 0x85beca0b, - 0x5ce05467, 0xdbe7e25b, 0x0334c169, 0x8fb29bac, 0x6021a0a5, 0x4d2b42a5, - 0xce201872, 0xbb8f5de1, 0x7b0bce08, 0x5fb73be3, 0xea81eecb, 0xc7ce7fbf, - 0xebf58df3, 0x2fb8f4bf, 0xb7e039fe, 0xf8f1dcca, 0xbeaf9a4c, 0x69fa32f6, - 0xdf54c457, 0x68ef55fc, 0xeeffc7e8, 0x00c4dfd5, 0x333ffa1d, 0x353fbc45, - 0xf1e8cace, 0xb60e6780, 0x04efe2cb, 0x1c4a8192, 0x15ce2ab2, 0x865eb8ca, - 0xdf86994b, 0x05bacf51, 0xa7ac2059, 0xf6878a57, 0xae78a931, 0xae2eab78, - 0xbb2f3955, 0x80fcc025, 0x42beb159, 0x74faefec, 0x3e49f7f6, 0x9992fa63, - 0xa1ce0ffe, 0x3373f2a6, 0x5efb31d7, 0x09598710, 0x3f08f98d, 0x5afd1536, - 0xfefb4439, 0xaf40d641, 0xf4f28064, 0x67978454, 0x13a795d6, 0x6b915bf4, - 0x4df9c3ae, 0x0cfd2a25, 0x13a346e5, 0xd1f4f1f8, 0xf7f9fe94, 0xe1bff4cb, - 0x867f3226, 0xcdb8ceca, 0xbe515f71, 0xc4696f46, 0xfb7e8577, 0x523f38b9, - 0x2163c5fc, 0x4115173c, 0x8f1e803c, 0x95610eb9, 0xdf13d1d5, 0xf1e9fc7a, - 0x8f51e0ad, 0x9d0f9cb7, 0x9e8ef1f9, 0x23e3d1f8, 0x5be97e7c, 0x7530eb0b, - 0x4bf288b4, 0xfc4f7bc1, 0xedfaf5b0, 0x009eb4b5, 0x0df142f4, 0x30174cf8, - 0x862b27be, 0x3a6c4fd3, 0x140b37e2, 0x0f4801c0, 0x55e3d798, 0x04acc78f, - 0xd5813ede, 0x1af80fdf, 0xed00fc89, 0xb2dd6521, 0xc6f76bd2, 0xe8c4de41, - 0xa7abd14c, 0xbd50bc72, 0xbce6f51a, 0x9bfa2b44, 0x9a9eaf40, 0x5e5bc614, - 0xde571b15, 0x600bcb48, 0xfc0afe9f, 0x0608b1d1, 0x95bcc5df, 0x56e05ff0, - 0xe2ca5f3c, 0xb7df0559, 0x93d5a67e, 0xce0bfaa7, 0xdc3dfe82, 0x05655ee4, - 0x87108c7f, 0xff1479e7, 0xd7f875c7, 0xf36bb3b6, 0x0afc7c7a, 0x27b931fe, - 0xab7a14de, 0x7cfd72b3, 0xfa0a1930, 0x3337d8f2, 0x137f8163, 0xbf447c7f, - 0x4563c4c4, 0x6e9c3821, 0xe2059e91, 0xa7b77d0e, 0x763e0b7f, 0x15494a90, - 0x7253bb1f, 0xd8deb3af, 0xeb298f93, 0xc7af8535, 0x05dde214, 0x4429a67e, - 0x1ec84bfa, 0xffcf0d48, 0xb3f72b79, 0x6043210d, 0x1c585f9e, 0x79f3ff8c, - 0xd54de686, 0x9b3fe84b, 0xb66d9ff7, 0x121bfde0, 0x7842ba94, 0x93f7c34e, - 0xf0f8c6bc, 0xbd656438, 0xd3096a53, 0xfbe2e6e7, 0xe42f14d9, 0x38f098cb, - 0x090559b6, 0xe3e20fdf, 0xf66cdf38, 0xd3db9c42, 0x2b0dfb92, 0x83843df8, - 0x527e7163, 0x3fc81460, 0xb6e5f97d, 0x4e50d5bd, 0x3d6095eb, 0x910afe3e, - 0x3b821ff9, 0x5217be4c, 0xe953d77b, 0xa13946f6, 0xdc3671d0, 0xe801bd7b, - 0xb8c2283e, 0x655cfcfd, 0xcf7645e7, 0xabec45c1, 0xf6f0a7ae, 0x02f7625d, - 0x81db28f2, 0xedfa7a7a, 0x49f34e8b, 0xd3b41e70, 0xcf22abd3, 0x5bfdf81b, - 0x68bb3f45, 0xeb0fbf75, 0xe3efc0de, 0xba8e2ffa, 0x1be7d60e, 0x2d61d5d3, - 0x44f4295d, 0xf438ebe9, 0xf1f99dd3, 0xdfcb503a, 0x049cbccb, 0xe3d151f2, - 0xeb8afac3, 0x9bd7a863, 0xe6dc3f3e, 0x857eb2ee, 0x35e8af3e, 0x6423d97d, - 0xd34644af, 0xebe3ce71, 0x2edcd733, 0x41c68bb3, 0x886fd38c, 0x73cbde56, - 0x393e8344, 0x95ed21af, 0xac573866, 0x07f97e63, 0x3d8d656b, 0xbedb86ec, - 0x67bd9ed8, 0xb6b97f3b, 0xef8a23fc, 0xcef8f141, 0x868ed6ad, 0x7e1491fd, - 0xbf67b7cf, 0xc9c82f06, 0x31a32379, 0xafdf4e7e, 0x7efa7e7e, 0x7035fdf5, - 0xd8c1aafb, 0xd2a9da38, 0x1636ec4f, 0xcd697d47, 0x14f0cd93, 0x73f86f5e, - 0xd4b8879b, 0xa3ae6f7f, 0xa44e7a21, 0x781468f7, 0xc2e7be0a, 0x0fe098cb, - 0x1eff95a8, 0x6cdd9de9, 0xf413f337, 0x6088efd6, 0x8683ea3e, 0xe82203a7, - 0x048223f5, 0xa0ecf0f5, 0x6350b0cb, 0xb97b300f, 0xef003d87, 0x657cd0a4, - 0x0f662eeb, 0x5da1d4b4, 0x0aed4951, 0xe01b3b90, 0x7cc1901d, 0x27681940, - 0x885eec84, 0x7786caaf, 0x0c5db932, 0x37a5a74f, 0x1f33fab2, 0x8c35374f, - 0x9dd5bb00, 0xce932f0c, 0xa8fb5db4, 0xf557da99, 0x508a24a9, 0x76c8aafb, - 0x4ed677ed, 0xde3bdca2, 0xa4bbc025, 0x65a8ff34, 0xecedff72, 0x8fd1b699, - 0xda81bf82, 0x54d9b767, 0xfb6f6f76, 0x039b66e3, 0xfedbd9f1, 0xcd17b4e8, - 0xdf8a3804, 0xe421f282, 0xbe28fe07, 0xf442a3ff, 0x53780b17, 0xe5f6e5e8, - 0x88ced10b, 0x0a6ae6ba, 0x736593c4, 0xb8db703a, 0xc186365f, 0x706189a9, - 0x376e4a26, 0xfbbdd3f4, 0x3bf028ea, 0x04fa3bbf, 0x2b7e79da, 0xf41fdbf3, - 0xe3a91594, 0x026d6bdb, 0x10c097a7, 0xdc777fd8, 0xec0127b8, 0xc0596c95, - 0xb2fd4ef7, 0x99f1e9ef, 0xdb669fc0, 0x6629d257, 0xfde2364f, 0x60547f32, - 0x3d2ac3c8, 0x4ddfcfce, 0x3fdc5ff5, 0xdcff1d44, 0xb5abcd6e, 0xc022f831, - 0x7bdccecf, 0xde80f40c, 0xae584ee4, 0x2b9004b8, 0x24a1eae4, 0xdd6a5f3c, - 0x689f0367, 0xe0e77f17, 0xa49eeb7c, 0xdaad3405, 0xb0369ff2, 0x3e38eae3, - 0xf8ed4bce, 0x76e5535e, 0xa113df11, 0x003d26fd, 0x85d6eb7e, 0x1fdeec59, - 0xc8a6afbb, 0xef9ff1d5, 0x9cc45219, 0x4cff7889, 0x98a737d1, 0x9f183ebd, - 0x1dfd8ebf, 0xf7ba29cc, 0xefe56ec9, 0xcff5e993, 0xe2b26c67, 0xa9f8c32f, - 0x4fd67665, 0xfb2bfb6f, 0x53e204b3, 0x296cbfed, 0xb3f8c220, 0xefc24b3f, - 0x3da40fe7, 0x3df60855, 0x01239d91, 0xa2f644ac, 0xa7cfcb7e, 0xbc2f6fe8, - 0x6793be7b, 0x3cbd6ede, 0x6e2466eb, 0xd004d72a, 0x9803dcc7, 0x07c991d3, - 0xf5bbff45, 0x55dfad33, 0x722b07af, 0x6e3fd732, 0x780210d5, 0xfbc2cc77, - 0x8c240713, 0xc9ebd2f7, 0xbd058353, 0x204fc3e8, 0x4d6d6d7d, 0xfe7b018f, - 0x009f60df, 0xc65eb6dd, 0x49aa83f7, 0xc7781ee0, 0xb455baa9, 0x24fc6007, - 0x67d87af3, 0xe0a13e8a, 0x1eeaeda5, 0x7fda58f3, 0x7d8345f6, 0x76f10505, - 0x57682ff0, 0xc1fdf84f, 0xfe679004, 0x07e784a0, 0xc6f717d9, 0x45f1542c, - 0x7e0355ff, 0x6eeafb7f, 0xfc60f7ed, 0x8b6ed0f5, 0x7bcbd981, 0x063dfff7, - 0x57dbd4f8, 0x90bc212f, 0x6f53d13e, 0xcf3bfd46, 0xd1fc862a, 0x8899bd6a, - 0xde2187d9, 0x152c6a6b, 0xfaef426b, 0x6487ce70, 0xd4f49595, 0x2778422b, - 0xd0f0092e, 0xf0561f43, 0x3e33d3ac, 0x773d71b2, 0xef0f1918, 0x4d5db65e, - 0xc77bc0a8, 0x0afb18fe, 0x8f4ccf94, 0xee7bdeea, 0xfdf0e9c9, 0x9ddec8a0, - 0x7ee22ab8, 0x62b3bdda, 0xdf6a8778, 0xeb8a4e52, 0xc5d06576, 0xfad16f0b, - 0x3345f657, 0xbce4baff, 0x224f7d5e, 0xf1c7df5c, 0xcecc1815, 0xe183bce9, - 0xac6fa8bd, 0xb0f574cf, 0x4361fff7, 0x0058393d, 0xfad462e2, 0xffac234e, - 0x3e8ad9bf, 0x25a5fc67, 0x978bf806, 0xb4210ee4, 0x9268b2df, 0xac15740b, - 0x33b07623, 0x18301fb6, 0x37325d60, 0xcf5c62a5, 0x731cfc2b, 0x31a34b49, - 0x4b174555, 0x19d839f8, 0xaf129bd9, 0x9632befa, 0xfb3397f1, 0x71817fca, - 0x91347f1d, 0xd0f41191, 0xfe4cb185, 0xa77a336e, 0xc77a866f, 0x68df780d, - 0xef5ffeef, 0x97937787, 0x038c731c, 0x5894e0bf, 0x0eda0fb6, 0x710f52be, - 0x821f6dc1, 0x6672a2d4, 0xa068b163, 0x1c45befd, 0x9877afcc, 0x90d6bdfd, - 0x12b8943f, 0xc5379e60, 0xd6fdbe32, 0xdce68301, 0xbefe2dec, 0x8cb1f5ef, - 0x32c6a50f, 0x03d6dabf, 0x700b09b9, 0xc447b9ff, 0x64f01f82, 0x456c3d47, - 0xe8a80fc5, 0x6f0f936f, 0xfe863e9d, 0xc1977273, 0x38edcb0e, 0xf30882fc, - 0x24219c75, 0xf43d204e, 0xac6f0a39, 0x5d5bde1a, 0xc71d1e0c, 0x0aafd86e, - 0xfe04a9fe, 0xbfcd0671, 0x43c52ed5, 0x7f82983c, 0xff4a1e65, 0xdae2168e, - 0xe4adc160, 0xfe15fada, 0x31efe568, 0xe513b04c, 0x5d2033ef, 0x6eb9b76e, - 0x6f72c589, 0xeccfe40a, 0x36d27a63, 0x72494f2e, 0x9fc070f1, 0x79f34eb2, - 0xb7a78caa, 0xe3e7effe, 0x4bafd254, 0x0ec8afd7, 0x76cdd22f, 0xf0ee4f16, - 0x10e9cc06, 0x8e96d677, 0x154a9f7f, 0x8e3f7b97, 0xfdf68cff, 0x830eb6c2, - 0x558fee01, 0x50e210ef, 0xbea7eddd, 0xa933a21d, 0xedafe905, 0x5c7dc118, - 0xe65dfcde, 0x9f72a48f, 0xe786ebbf, 0xf87fb0eb, 0x8120fb39, 0x1bfd93a6, - 0xfc410e56, 0xafb06c06, 0xfba278c2, 0x46dad206, 0x92ebd023, 0xe52d2c65, - 0x9a4bd5e7, 0x4b3fb8dc, 0xc478b3d6, 0x4ca9b165, 0x257a733e, 0xf8c1e886, - 0x7b4dbade, 0x5c1ff08f, 0x7d6d9e7e, 0x4bf40f6a, 0x80fbebe9, 0x9eda9b8f, - 0x55c30758, 0x46ecf5e8, 0x4594e119, 0x3df3cf6b, 0xb8cfccb1, 0xf7a330fd, - 0x5ce51bc9, 0xb26c4f78, 0xbfc1d897, 0x4dc6d6fd, 0xb7eff022, 0xd9539e80, - 0x7b79073e, 0x3163df66, 0xd6f907df, 0x47e02069, 0x652466df, 0x62fb545b, - 0x343786ef, 0xb9bcb7fb, 0xebfa3a6e, 0xe005e23b, 0x55becaf3, 0xe8cdbef0, - 0xfff70dbc, 0x9ffdba9d, 0xc2b7dacf, 0x4f7ad0ba, 0xd4fffdf1, 0xe9ffba34, - 0x718db8a7, 0x66d9c002, 0xdccefc8c, 0xfe90df4b, 0xa3b57c42, 0x297d5f07, - 0x6c1ff996, 0xeaffb4e9, 0xffa12e3b, 0x4e3e3421, 0x2be54f37, 0x002a9374, - 0x0ae91bfe, 0x517c008e, 0x533d02bc, 0xccfe7a3d, 0x0795dc0c, 0xe1ff3c24, - 0x2e3c4be7, 0x6a947704, 0x99f986bf, 0x6fdd6fb2, 0xf2b238c0, 0x9e82576b, - 0x45e8509f, 0xb82b3cfa, 0x7953c787, 0x71f61676, 0x8eb07e04, 0xec8ae3e3, - 0xff7debee, 0x65cf40c1, 0xf98462d4, 0x1d82f590, 0x772945d6, 0xbdef67ac, - 0x94f0e61e, 0x2dbf87ef, 0xde3d83be, 0xf0cc3d21, 0x5c42341d, 0x931f28eb, - 0xc5c84463, 0xb70c40fd, 0xb67d860f, 0xfbafca84, 0xacebf255, 0xaa7488dc, - 0xce23e1e0, 0xb1c4aeb7, 0xc7ce3f79, 0x5d1f07e9, 0x82ff0aa2, 0x3f6c0924, - 0xe7db028b, 0xbb3fc022, 0x90dba6ef, 0x4c88efde, 0xb7b076ef, 0x47efe1e2, - 0x8cfa406d, 0x7bc7669b, 0xce494f2f, 0x7e8d38a8, 0xef74c3e4, 0xced067a6, - 0xfd85fa03, 0x97fd1bde, 0x0893fd01, 0x74a3ef74, 0x853f5aaf, 0xfc5d280e, - 0x7ca5f01d, 0x7285d3d7, 0x65e0a90e, 0x731cee9b, 0xe9e19daa, 0x8d5200ff, - 0x8000b56e, 0x00008000, 0x00088b1f, 0x00000000, 0x7dbdff00, 0xd5547c09, - 0xf37df8d5, 0x3332c966, 0xb2764c99, 0xa00c4930, 0x80490e2c, 0x084ed8b0, - 0xc3884a20, 0x93a0d752, 0x364b0900, 0x94569510, 0x8b062081, 0xb62d1518, - 0xef858320, 0x106d1b43, 0x268358a8, 0x622d1110, 0xa57fb1dc, 0x41459041, - 0xed1fa822, 0xe73bf587, 0x33337bdc, 0x6a02266f, 0xefc7e1ff, 0xdf77dee6, - 0xcf7ece5d, 0x6ec5f739, 0x843631d3, 0xae630731, 0x7d8c01e6, 0xf4bf3f8f, - 0xa12d8c97, 0xcf3773e7, 0x8224715e, 0xf0f7cfd1, 0x5e79babf, 0xc776bd50, - 0xe91c57af, 0xc5cfafe7, 0xffe0525f, 0x8967a671, 0x47f1558c, 0x89ef4cac, - 0xfbc025b5, 0x6cd69d11, 0xe266b498, 0x03846319, 0x8319789f, 0x1c636ff6, - 0x6faa3e54, 0x1f2bd3de, 0xe9cc31ca, 0x9b39a685, 0x998f1533, 0x1b3605b1, - 0x27f967ad, 0xb0dd93d3, 0xc6c646de, 0xc59bbae3, 0xd9dd727c, 0x99c68536, - 0x8f7329e0, 0x66678389, 0xa07b9e4f, 0x6607f9ff, 0x886d964f, 0x70a13ebf, - 0x4018eabe, 0x7ec48c4b, 0x0c985563, 0xc9bf9fe6, 0x326533e4, 0xc49f05b6, - 0xa3db2ac3, 0xfd329b7c, 0xccf4d9ef, 0x9633b7a5, 0x75a4cb6b, 0xb15aeac1, - 0x646858ee, 0xdfbcc197, 0x9bb59666, 0x1dd5d1e1, 0xb081e2de, 0xef462d8f, - 0x389989d4, 0x1c1af398, 0x9d629aff, 0x6a5801ed, 0x38a6cbac, 0x6992d007, - 0xcf8fb65e, 0xeced9793, 0xeea1b2cf, 0x2db9e670, 0xf8128d8c, 0xc930ad62, - 0x421c3f70, 0xd9e1c6f1, 0x20175e13, 0x1750867c, 0xd5e27e7a, 0x667d1ba8, - 0x0144f3ff, 0x78632fbf, 0xd3c1adf9, 0x1d0e66db, 0x553e6027, 0xcacc6649, - 0x5c554b3c, 0xdb6628ff, 0x773ff0e4, 0x1c2e628c, 0x57189a7f, 0x8ffacbb6, - 0x10aeafa6, 0x78869afa, 0x22e88ead, 0xd053eaba, 0xbcc07469, 0x8bdd194c, - 0xee98fac1, 0x80ac5eda, 0xbd71eaba, 0x29554800, 0xf6c7ebe0, 0xd7338d84, - 0x01d99e23, 0x0cc9cb13, 0xcdb567dd, 0xd1b6e1c0, 0xe866fa30, 0xb865e097, - 0x838bc003, 0xde3585e3, 0xdc6bf88a, 0xd7886268, 0xdc39636f, 0x68d953ac, - 0x42b7f403, 0xc6f7247f, 0x57039ea9, 0xd931bd41, 0x9e6050e8, 0xc22e8613, - 0xa0ab89fb, 0xadc3e88d, 0xbc4fbe20, 0xdf9ae23a, 0xa277bb40, 0x8bc0e58e, - 0x05b08d5b, 0xa7bfc3a4, 0x482936f9, 0x27c42da7, 0xc1b2c7f3, 0xbede7826, - 0xd5d11869, 0x052ce2ac, 0xe6ce76e9, 0xdb9f0558, 0x2a74d8c7, 0xd863eff3, - 0x13e89542, 0x16dea0f8, 0xde618f80, 0xd5e1153a, 0x6c93ce3b, 0x11ec6588, - 0x23e335db, 0x32ce81d2, 0xcc1b2459, 0x5f5043d8, 0xb46b7009, 0x4b1614bb, - 0x0a7306f5, 0x236321f1, 0x0cadae08, 0xd518d4f0, 0x6045775d, 0x7f5e2cff, - 0x86eaf1a4, 0x9ec63486, 0x22357189, 0xbb303e9e, 0x87f9c11f, 0x44a9d526, - 0x7fae82e7, 0x127ece80, 0x2c2ed4bd, 0xe0f38762, 0x0e660ef7, 0x47901ba4, - 0xf8066eb7, 0x9b3de895, 0xbd355d70, 0xc38e3e8e, 0x657cb6d5, 0x7ba184f4, - 0x21788eb9, 0x8cc7d817, 0xaeef11f0, 0x7ecdcb53, 0x66c5b3b9, 0x52ed4c17, - 0xfcfc5b26, 0x79eb7286, 0x593b9733, 0x98229a50, 0x7ec762d7, 0xac23a23e, - 0xe5fae4c7, 0xdd62cad1, 0x3e185f78, 0xeb890d7e, 0xaccf9467, 0xf2ff7fe5, - 0x1fd0a19b, 0x9f89577f, 0xc4fce35e, 0xc5a3f5e5, 0x3c22269f, 0xbdf09390, - 0xeb1cc5db, 0xeadf3a97, 0x5fb9748b, 0x3ea09b65, 0x2af464d8, 0xe66db831, - 0xf18a25b0, 0x945b0d90, 0xa820cb56, 0x2e614bff, 0x7fe9c3c0, 0xbfae54a9, - 0x133e3dd7, 0xa1d9afde, 0x7e852e73, 0xf10a2d35, 0xf337b383, 0x371d0045, - 0x31075947, 0xb770af18, 0xf68065d9, 0xc9044ad3, 0xd7009c65, 0x2feb9061, - 0x8268cae8, 0xc02df5e7, 0x5d3d507f, 0xf5c6a808, 0x6c319dea, 0x83be1f80, - 0x1fb47cde, 0x1bda00ec, 0x4f67c89d, 0x9ff1f245, 0x81f0cc8a, 0xbe528310, - 0x4a0188e7, 0x6e825961, 0x62c67af4, 0x78504f00, 0x30b51cb1, 0x3c07a5db, - 0x35e67a2b, 0x7546be00, 0x9f08aab5, 0x8e872eac, 0xe9f3fd99, 0x3bed18bb, - 0x39d0ef4b, 0xd6d5f403, 0x7aabcfbd, 0x31d0eb80, 0x942af58d, 0x6f9e3189, - 0x4623de10, 0x7b63d5d5, 0xf557b15c, 0xa57cff40, 0xe905b76e, 0x44e61aec, - 0x24f92ab9, 0xc1b593ae, 0x81ec5972, 0xda15974e, 0xb5771c47, 0xc7fd800d, - 0xe38299b8, 0x7c0dfd49, 0x0e9162c6, 0x44ca5de3, 0x3fe86718, 0x8e47c118, - 0x68ef75b3, 0xbe3ef905, 0x18e28c63, 0x6be74a10, 0x38b7e398, 0xce9f77ae, - 0x3475f889, 0x9406d733, 0x62ba7f13, 0xf64bc20c, 0xf5cb1def, 0xa78f48ca, - 0xee154408, 0x1de70627, 0xb76fa37e, 0x6c33d601, 0xd1b77796, 0xd99fb011, - 0xed4bc68c, 0x523ed2f4, 0xb10a780e, 0xd2c6b6cc, 0xb78e2338, 0x7e800db6, - 0x1fb07549, 0x78ef4f68, 0xa6b8414f, 0x882875d7, 0x777badcf, 0x3ad37ad1, - 0xf82979da, 0x176179eb, 0x5603db74, 0xdb23ed1d, 0xf2cdf5ca, 0x666f5c53, - 0xadb27ac7, 0x2c7dfe09, 0xd724f42f, 0xf66bf8c1, 0x17ef7566, 0x2895eee5, - 0x52e403e4, 0xc691ac6e, 0xe9eacbb9, 0xbdabfb8f, 0xd20f73b1, 0xdf7bf3e0, - 0xb47f12b1, 0x137e13c4, 0xf84a7df7, 0xba485c48, 0x37d9ad98, 0xb179415f, - 0xa67014a6, 0xca59c284, 0x7eb8358d, 0xf45b1fa2, 0x27cfa024, 0xd8829eed, - 0xcca57b40, 0x20159d1e, 0x8f7be497, 0x19ee662f, 0xed6190b0, 0x16595be5, - 0xb17ef7c9, 0xc27df201, 0x9122fbc0, 0x2e2c9a9e, 0x569fb617, 0xcf388dd8, - 0xfb425833, 0x975e0633, 0xe0407af0, 0x52763b33, 0x870875b6, 0xf8e80d93, - 0x4fde4899, 0x8dee8f2b, 0x83bb09d5, 0xe0eb0bd3, 0x08fb82f4, 0xc666bfb4, - 0x748c3c72, 0x9cf48a79, 0xfee2a64e, 0x76f81786, 0x1b0edd23, 0xf48dddef, - 0x9d04ce9f, 0xa274e78c, 0x63dbf7a5, 0x711d7cb9, 0xdc218bbc, 0x0ee615f3, - 0xc654ef67, 0xbe29bb72, 0x0fd13463, 0xce1943f0, 0x4eb53437, 0x66dca035, - 0x7fa809b6, 0xa0eb137e, 0xae05797e, 0x366f48dd, 0x79f89b97, 0xe9c6d9be, - 0x07d39326, 0x1c273fbc, 0x3e436d3f, 0xa3e7e01a, 0x7347a478, 0x26de3d28, - 0x011bf4e0, 0x3df1d0df, 0xf1f8e177, 0x02973a1d, 0x603b0c83, 0x3ae831f6, - 0x49e8016c, 0xf40653e4, 0xcfb40b0f, 0x9f2215b2, 0x153956a5, 0xb302ebc4, - 0xd7dc1efb, 0xf98d9472, 0x5f3acf48, 0x6c97bc3d, 0x7efe1173, 0x67689eb4, - 0x90686c11, 0x2c40f59d, 0x9557e3b7, 0xfa7ebca1, 0x53ca235b, 0xbdbfe487, - 0x01e5d1b9, 0x50c7f1f4, 0x0e123f7c, 0xa7395adf, 0x2e5fb7c5, 0x8039cb04, - 0x0f8e5ad7, 0x77c7e76e, 0x7cb9502c, 0x3d6b9608, 0x3e4423e1, 0xc1fc3c08, - 0xeb84daec, 0x4045c6cc, 0xfacd1de9, 0xfa4f7b61, 0xf358c5f8, 0x2f67b34f, - 0x8c5f8fac, 0xc7d5084d, 0xd7ae88ba, 0x75478015, 0x6150ea8b, 0xec8bf50b, - 0xfaffc42e, 0x7689c566, 0x9516eee1, 0xf2fd61e8, 0x729bd228, 0x8f6e5fbd, - 0x84aec419, 0x6b3ff052, 0x5a7d258f, 0x5fe62b1b, 0xfcc0bf06, 0xbabc6da7, - 0x3d79e6dd, 0x6fad0e50, 0xe11226f9, 0x71593fdc, 0x4abb411d, 0x85818fab, - 0x84df7814, 0xd70829bf, 0x322a0dc1, 0xad9ef5d6, 0xf6f09526, 0x8c378e2e, - 0x0a33be75, 0xa6a7f5d6, 0x7b40bad1, 0xaf8eeceb, 0xeb05dd6f, 0xfae68daf, - 0xeb9a36b9, 0xcebbd3e7, 0xbb7a41f7, 0x9274e176, 0x9ef4c37b, 0xdce5038f, - 0x730efd1b, 0x6d4acc39, 0xd4e3fb47, 0x68fbe52e, 0xa235a100, 0x0aed1e9f, - 0x06a9ca35, 0x1c4415db, 0x1f0039f5, 0x145b5f84, 0x073eafc1, 0xd6932ef8, - 0xd9d70279, 0x14b2316e, 0xfc0b3f68, 0xbae4fd88, 0xcf7ac47f, 0x9a6f5f84, - 0xa0b468ed, 0xbebfd50b, 0x1e20bc6e, 0xa2d57c60, 0x669c7da7, 0x67c44e51, - 0x10c5d1b3, 0xc283deff, 0xab78103e, 0xba773411, 0x0f01c865, 0x81fd6fec, - 0x7fbe2734, 0x48d9c77a, 0x47ed199d, 0x7d876a8f, 0x565de9a9, 0x5bbb87d4, - 0x39de5ece, 0xc19be480, 0xbb3beb0e, 0x33ddb0ef, 0xcfed47e0, 0xfd88bf6a, - 0x0dcdead5, 0xaa227681, 0x1a945259, 0xda5a523a, 0x220ca9fe, 0x0f2863fe, - 0x57cc19bd, 0x3e5efb0f, 0x54d3d050, 0xd7be40e6, 0xcdbb7be2, 0xe00f619d, - 0xb736cddb, 0xf385d703, 0x3ed2e6a4, 0xe83eb0b3, 0x0679e9cd, 0x0c6fee1d, - 0xed29bd43, 0xb44fb93d, 0xfd7323c7, 0x5ef693fb, 0xce73fef7, 0x68c7da0f, - 0x74ec83df, 0xc52c740e, 0x282d5a73, 0x03320785, 0x784adff7, 0xacfb16a9, - 0xaab7308e, 0xcdb62fb0, 0xca53b270, 0x7dd0ac83, 0xf3869e00, 0x780f387d, - 0x377fcf10, 0x4e11eb3b, 0xda1b0efa, 0x91afb0af, 0x50560fb8, 0xf8708c96, - 0x8c9aecc0, 0x2599fef2, 0xf4fae88c, 0x14f7ccb3, 0xbb4b7a6c, 0x0366e88e, - 0xffe882bb, 0x5b99dd0a, 0xebe266dd, 0x7e7ef8b1, 0xe50ea347, 0xa1cf8e6f, - 0x797ab943, 0x474eb347, 0x2f19e0f4, 0x0f5674e0, 0x54dfebeb, 0xba48fea7, - 0x2e9e1498, 0xabf6f042, 0xb849bc40, 0x30f4128d, 0x3286e10a, 0xb27f4bb9, - 0x370fc233, 0xb54b0bc0, 0x58c78e87, 0xa9c20667, 0x7d63c5ed, 0x9abc613a, - 0x8add8f97, 0xabf9a970, 0xcc618889, 0x418f2f5f, 0x30b2ffba, 0x72735dbc, - 0x0f5b9d71, 0x3dab78c4, 0x157be48b, 0xbda230eb, 0xaddd7200, 0xd2eb900f, - 0xe867db8e, 0xf7f1c628, 0x12d9510d, 0xe759f380, 0x461624b0, 0x3f72c85f, - 0x00396dda, 0xe155f47f, 0xfcc5e4f9, 0xda476e18, 0xb25afc83, 0x9678b7dc, - 0xe7a18c7b, 0x8e0df6f1, 0xb14e7f24, 0xc87a1ec6, 0xa78dedce, 0x81cf5ced, - 0x3ae17660, 0xe2c5fd4f, 0xa9d342f3, 0x0cadf7dc, 0xdb6a74e0, 0xa05e79bb, - 0xe3ac53a3, 0xdf9097f6, 0xb9d336be, 0xfbf078ae, 0x7e2c4b79, 0xfb8abcfe, - 0x2f55d852, 0x407569bc, 0xbb2de2ff, 0xf001bde3, 0xbfe98abb, 0x4ceba6ee, - 0x8fef979c, 0x20fb3be9, 0x274bd83e, 0x16501d12, 0x3c6af8bf, 0x373803a7, - 0x14ff450d, 0x633f8fe7, 0x5ddd8053, 0x3dc6b0bc, 0x1fc02f26, 0xf9922e73, - 0x0efaeb02, 0xab891e23, 0xfda999cf, 0x9e25bb76, 0xd62f4de4, 0x8f4de50b, - 0x7848baf0, 0x3c25db6a, 0x913e0df7, 0x97c5f681, 0x07c5d83d, 0xaf7ec1ec, - 0xdc7b1637, 0xf5fc7263, 0xdea77dbf, 0x5ef30ee6, 0xacff188b, 0xda127873, - 0xd6c6c57d, 0xe1f9c2cb, 0x0b5339e4, 0x57ce37a7, 0x7fb8e346, 0x1f1a6739, - 0xeddb5d6e, 0x3fe69fba, 0x0aab07d8, 0xf44b0bb0, 0xdced379e, 0x326ab05f, - 0x3f2e6bd4, 0xd9ce8e3b, 0xdc845e92, 0xdb798abb, 0xf4b57f90, 0xbefdf121, - 0x4b2a5bc4, 0x693dbc45, 0x11ba7077, 0x43f920fc, 0x396d470b, 0xe13cc8c1, - 0x75cf03ce, 0x799235c3, 0xbede1e41, 0xfe7a40c1, 0x4e1ff3cd, 0x3f7a03cd, - 0x5b60d6b6, 0x5ace530a, 0x51ed3bb7, 0x360da7f4, 0x1fa814d9, 0x865eb473, - 0x4eb95f7c, 0x1c3d2375, 0xe27b7b5b, 0x00bf2874, 0x7582adfe, 0x50306e54, - 0x770dacfb, 0xc109fb50, 0x12eb95d7, 0x7cbca3fa, 0x4481fdb3, 0xeface3c4, - 0xf11ebfee, 0xeb68c5b2, 0xaaca183f, 0x263dc526, 0x3673de00, 0xb7d50646, - 0xdc2cd8e8, 0x532bc487, 0x1dcfdd3c, 0xdc631eb0, 0x6b63c44f, 0x18d51f88, - 0x92ccedc7, 0x9aefb029, 0xbec96721, 0x8a27bddf, 0x662bc9f4, 0xd6c8ec95, - 0xb7f3ffc1, 0xf45ea12b, 0x3649de9d, 0x58f3c09e, 0xce866781, 0x8a8fa040, - 0x7a2f5e08, 0x68764f51, 0x78254591, 0x1d5c82b7, 0x65de4a43, 0x7efd0b1e, - 0x4753df21, 0xfd0e1ead, 0x1818c6c6, 0xb45fa1ea, 0xa06629ce, 0x4e797f27, - 0xc06769ff, 0x9733467e, 0x42e2ed1e, 0x5f6a0866, 0x0a7d6511, 0x4c185aed, - 0x28b0fa8f, 0xd8f9f822, 0x813daecb, 0x5b58c4f6, 0xbfa4bb70, 0xbfa0389c, - 0xb1b97efe, 0x8fe7cf7b, 0x567d804c, 0x9ec953ec, 0xde5c90be, 0x41cafb8f, - 0xda51bf7c, 0x29bdef04, 0xf9e6f3a0, 0x9052cb63, 0x86140abe, 0xe763ae7e, - 0x5ce5f3c3, 0x018c9f41, 0xf1f9fb9e, 0xbb39d13c, 0x7f6c8ebb, 0xeebcc15d, - 0xe2ffae3a, 0xcb0fd9e5, 0xf73b4eab, 0x87f5686f, 0x53fe7f96, 0xf078a3fa, - 0x0b5e19ab, 0xe585ff95, 0xfe5c2dc9, 0x5685e56a, 0x6975c85f, 0x4e7d5bd7, - 0xcf13d20d, 0xd7e27909, 0xfe7a4617, 0x6b8f9e33, 0x9e8486e2, 0x219ec18f, - 0xea877978, 0x760e5ce9, 0x6fd8edd7, 0x5711d980, 0x665a4b08, 0xb9468acb, - 0xdcf164d6, 0x97e01719, 0xa8d4dfea, 0xedd1f943, 0xfb0431af, 0xf5f9e46d, - 0xffbe389e, 0x875e38f2, 0xfb9d2bf3, 0x92794437, 0x2f6f38f5, 0x7e3033a3, - 0x85fbcb25, 0xaf7690fc, 0x9da577b4, 0x7d59ed2b, 0xb367b703, 0x7e41dd63, - 0x5fafd633, 0xed183f90, 0xef73e474, 0xe7da28ae, 0x107b8a67, 0x731569f2, - 0xa017143d, 0x7c0deb07, 0xbcf5dafd, 0x13ec2716, 0x413b26e6, 0x1d1ccfb6, - 0x8d6f9e5e, 0xc2ff53d3, 0x40ca6fc7, 0xb6b3ee3b, 0xce50339b, 0xfff1a67e, - 0x0f0fc4f6, 0x507d7e0b, 0xe15893e8, 0xf9087827, 0xedc0ea08, 0xfef02dae, - 0xe26ec58a, 0xbe2edfab, 0x1747ca91, 0x8fe7a42f, 0xfcd265c5, 0xdc77c2b6, - 0x23a700d9, 0x17d2552b, 0x3eee8d33, 0x91def0b1, 0x1bf91d08, 0xc799d70e, - 0x3b63336f, 0xcce5f3a3, 0xf26c27c7, 0x1f01f806, 0xe90c7dc3, 0x09af9f79, - 0x9d2a5ebc, 0x2b4eb356, 0x7a6eadea, 0xb7a2103d, 0xa72f11db, 0xf6226759, - 0xfa3a55ab, 0xf3a12934, 0xaf5cc83f, 0x2366bf61, 0xd37c8feb, 0x92f5c51c, - 0x029bdfb6, 0x9ed0ab7f, 0xd433f285, 0xcce4615f, 0x7b5e823b, 0xc4ef5d5b, - 0x9333bc91, 0x56eb4edd, 0x3ef44e29, 0xb4e707ce, 0xc639f10f, 0x975fd089, - 0xc775b56d, 0xc779f855, 0x185c71fd, 0xfe4f5c7f, 0xee3aed1f, 0xd570e789, - 0x296485fa, 0xc4c742fd, 0xd9c5167e, 0xe844fc82, 0x0fe70f0f, 0x48de3aba, - 0xd510dbfb, 0xa8b8c5e9, 0x3e7e66f7, 0x55e51a4f, 0x5a95dfd0, 0xfe8858dc, - 0x71c67fb0, 0xbc7da63f, 0xf1cf1927, 0x4e8d92bd, 0x2c5ce3f4, 0x76680e3f, - 0x478138f1, 0xd358eb47, 0x03ec8de1, 0xf0ec4aeb, 0x34a11a14, 0xf8d226c4, - 0x096eac49, 0x11fa0de2, 0xa3dbf230, 0x743c8a7c, 0x213c9743, 0x91a56147, - 0xaddb77c8, 0xbc3c531e, 0x5d467437, 0x53edfa3d, 0xe23c78ab, 0x6de9e284, - 0x1b8d0ecf, 0x5e3932cb, 0xbb88aff0, 0xd0346fe6, 0x3e37f2ba, 0xfcd1f146, - 0x95eb578d, 0x1f943900, 0x27fea06f, 0x9bd39d5e, 0x851f18fc, 0x880ebf8f, - 0x4662f4e7, 0x8a10e11f, 0xbfa58687, 0x313ff17e, 0xf609dcae, 0xef3cb050, - 0x20243f17, 0x0cfaa16f, 0x3c7d73c9, 0xc07f23d7, 0xd358057c, 0x7cc8661f, - 0x8fe40d85, 0xbe6c6add, 0xde51e306, 0xbc431d1a, 0x2bf9efb7, 0xcd676bc5, - 0xb6bc5070, 0xcf7dfdfb, 0x3ff6c72c, 0x118362cc, 0x87be29fe, 0x7ccff415, - 0xc9e3c91b, 0xb1326edf, 0xd9a5b025, 0x3c53376f, 0x8e954d78, 0xeed17ca1, - 0xe832661b, 0xa0db5c78, 0x47f8e02b, 0x0ef12839, 0x7c446404, 0xfc21bc48, - 0x6e3198b6, 0x5fad02fc, 0x7e80cbae, 0xc7dc04f0, 0x4e906b96, 0x15d9557a, - 0x75c817f4, 0x4c9f485d, 0xfa69ff8a, 0xc3d467e4, 0x9c5fc5b7, 0x74819e1e, - 0x5ac3d5ae, 0x7164dbfd, 0x0bbf6255, 0x4213e1e9, 0xd7894dfe, 0x7e3043c4, - 0xc76f0616, 0xf00c1c84, 0xff19df8f, 0x1fe3fc23, 0xe3091ca1, 0xc8c67f1f, - 0x9da36fe5, 0x0c2936dd, 0xe627bcbf, 0x32eeadd7, 0x6f8cfea2, 0xb3cac251, - 0xc651ab6c, 0xfae05713, 0x2b44fc64, 0xb7c0c38f, 0xde5ffb11, 0x7b0bbad4, - 0x165ec6e5, 0x15dbe68d, 0x37b9c3df, 0x046b3ccc, 0x30163b9f, 0xea3aa38a, - 0xa82bc918, 0xb093b8fb, 0x0023f295, 0xb8e04f1f, 0x9d638a17, 0x1d9215b6, - 0x8656e324, 0xf8f3e0d8, 0xcfd9789e, 0x6fc447f5, 0xe27a0f7a, 0xb05d624f, - 0x5fb067ff, 0x141602fc, 0x9971919f, 0x62af3af8, 0xc47547cc, 0x3bdadfc8, - 0xf304b3ce, 0x3386ba3f, 0x8f5053e7, 0xa215b529, 0x72cfb53c, 0x66fc61b6, - 0x9fee29f9, 0xf98f3e5f, 0x79012a96, 0xca2c9e05, 0x05bc4203, 0x0a7607fa, - 0xac53b6f9, 0x5fe4f41b, 0x5abaf9e3, 0xa4f403e2, 0x756e87c4, 0xed784aab, - 0x02a7af0a, 0x43fedaf0, 0xf919fd78, 0xe48b9df2, 0x852f0fcb, 0x9171fe6e, - 0x8c4bf374, 0x3b090c6f, 0x578867df, 0x67407ced, 0xbef88347, 0x78db3a07, - 0xf9d2f189, 0xa7a89fe6, 0x5dfae142, 0x5c28427c, 0xfaeb1657, 0x5166bc91, - 0xd57a70ce, 0x4ffe6096, 0x12d891e7, 0x1e7a5c86, 0x3b7bfac9, 0x1967888d, - 0xd5eb9107, 0xf6c88fe6, 0x0f25169a, 0xbb859fcf, 0xe039d3cf, 0xe8bfdb74, - 0x079a101c, 0x0f9de7c2, 0x39fc8de4, 0xdcd01d56, 0xa677fc0a, 0x752748c9, - 0x377e3995, 0x7bf7fd0a, 0xa0e7cc0d, 0xffd811fe, 0x5ffbc60a, 0x03bcb4d1, - 0x305757fd, 0x479c57bd, 0x1db9ef95, 0x7c7c8315, 0xf2955ec5, 0xfe66d8bf, - 0x2c458ebc, 0x4c74ff41, 0x02398e81, 0x8aeb19e0, 0x78008e62, 0x07b78dc6, - 0x7939e5d5, 0xc13798ae, 0xfde82bdd, 0x82b31ba4, 0xae78a7fa, 0x3a9e7a08, - 0x9ea8372b, 0xa822375e, 0xa385ef7f, 0xde99ea83, 0x67fa836b, 0xaa0e4c37, - 0x1cde34e7, 0xab18ffd4, 0xec147c7b, 0x5bfa3fb3, 0xebcc3f00, 0xd60cb8ea, - 0xb7ac433b, 0xa0f29aef, 0x5afd81f7, 0x53381e31, 0xcf17c990, 0x00abdf8d, - 0xff08671c, 0x39bee5ce, 0x55cfe341, 0x677e88ab, 0x048e1a36, 0xacf469fa, - 0xc02a4f6b, 0x38a7c6b9, 0xb95ea15b, 0xecf9f826, 0xbde81b1d, 0xf6e0bed9, - 0xeb839bb9, 0xd29cde83, 0xb901e79f, 0x4672bf29, 0x87dfb042, 0x9989d085, - 0xb599f4e4, 0x7aa5ffdc, 0x24e86afb, 0x27ec5f18, 0xd0438dd2, 0x9839298d, - 0xc11d226e, 0xfaf95374, 0x0708a1d6, 0xfba3fc2d, 0x0bc9e869, 0xfe007eff, - 0x7d306716, 0xfb4ee169, 0xec567583, 0x95efd850, 0x6acfb850, 0x2a797879, - 0x633b850b, 0x1fd7233e, 0x688fedc1, 0xd981fde0, 0x89ca18f3, 0xa8163bb3, - 0xe3638718, 0xecff3c79, 0xed07af8e, 0x2f898473, 0x97c484e5, 0xf80425d6, - 0xe97c647f, 0xaf19c634, 0x67111764, 0x844ffddc, 0x8f00c807, 0x0b11f301, - 0x71dd119c, 0x3c7f48c5, 0x653f2b49, 0xb9e3fa09, 0xfe2bd204, 0xbc3d6c78, - 0x03e6343d, 0xc653ae37, 0x8ebe64e5, 0x930a2bcc, 0x8497fc9f, 0xb40fcc04, - 0x75f9e347, 0x3a7cfb4b, 0x22bcc977, 0xc302f226, 0x4fa4ffd8, 0x14d7f19a, - 0x26760bb2, 0x0afebd70, 0x176dd78e, 0xa92fbc88, 0x471a7bd7, 0x2a7adfc6, - 0xc52a5d95, 0x2894bb13, 0xf46153e7, 0x3f0947ca, 0xe685bf51, 0xa8147f8f, - 0x38ee6a47, 0x0bf507bb, 0x6c63fdc0, 0x6f4058b7, 0xfdbd7e2b, 0xd12b68bb, - 0xaaebd76b, 0x9c342faf, 0xd8c47089, 0x222d8e01, 0xe445afdf, 0xd6f5c9fb, - 0xf4baa445, 0x9c1ed879, 0x8ae327ff, 0xc28dfdda, 0x3afe71fe, 0x976417bc, - 0x76e5cf2c, 0x870169db, 0x276e160d, 0x9db91318, 0x1f39ab50, 0xfb7036d5, - 0xacd7a40c, 0x8c718096, 0xdfea1689, 0x4c685cdf, 0xdf8471c4, 0x42a67965, - 0x4572c576, 0x77e47b21, 0xfcf4d1b6, 0x868509cf, 0x6fffe844, 0x6011af31, - 0x16636588, 0x93438f5f, 0xe892fe17, 0x68c252ff, 0x36898d2a, 0x5db67fe1, - 0x6a91f481, 0x5da91976, 0x8aa71f0d, 0x1afbe44e, 0xb464f229, 0x42718071, - 0xdfdfa26e, 0xe2d2edc4, 0xfe4189b1, 0xf18cf7fe, 0xd0afdfc2, 0x53942eeb, - 0xef7814bf, 0xeaefffc9, 0xf1476b67, 0xaffff5ad, 0x7ffee48c, 0xf1081f19, - 0x85c73bff, 0x1e23fff5, 0xfe7eeda2, 0x2dd893e9, 0x3e50d29f, 0xea7a30ed, - 0xb5d5fcf1, 0x6878ec1d, 0xa4ebe7ee, 0x7dc0c0b8, 0x673c4ed9, 0xbb64cf2d, - 0x4b6f482c, 0x7f3b4318, 0x696ea747, 0xe95f3c24, 0x3e7c3665, 0xbf3f2d7c, - 0x3871ae55, 0x0e529b71, 0xfdc89d5c, 0x1f380687, 0xbdf1725b, 0x27186dc9, - 0xd9953958, 0xb2350d51, 0xda2b22c6, 0xd8596b45, 0x4168e3f3, 0x770a134f, - 0x4276fe51, 0x0fb7cf17, 0x7693a7ed, 0x73e2217e, 0x2ce79758, 0x7971cf8f, - 0xcf112242, 0x5f3aeda9, 0xb27d73b8, 0xa46ae8ad, 0xf0be81af, 0xc29188e7, - 0xbb32e64f, 0x03f8e227, 0xd87cf1b7, 0x677f294a, 0xf01e98e8, 0x75e0453e, - 0xd79e5aca, 0xff7fcec1, 0x45ed2abd, 0x9433e346, 0x2d53952b, 0x5513f43e, - 0x697a64b6, 0x99c56e5d, 0xe5a2f283, 0x2bd6376d, 0xe86df3f3, 0x9dfd7097, - 0x91fb4729, 0xfcb8c9a9, 0x52a3b3d2, 0x8f1e909e, 0x64d438a7, 0xf1236f41, - 0x72409cb0, 0xc034657e, 0x92ed72bb, 0xf3d7985d, 0xc5191ffe, 0x5da80e9b, - 0x5fb07143, 0xe6167001, 0xa567a962, 0xa648b7e4, 0x718aa671, 0x7982ffbc, - 0xfef3fc23, 0xda75e5aa, 0xf30301cf, 0x9d1d0046, 0x038379de, 0x09e5eeed, - 0x93cfe411, 0xaa83da71, 0x42523ee7, 0x5c1aaefa, 0xd12d4dda, 0x9c83f436, - 0x3a61f9de, 0xb93e4dc6, 0xed05ace7, 0xbbe87fd8, 0x7c2f982c, 0x16bbd17c, - 0x93f1c017, 0x9de52a45, 0x86f42add, 0x897dfb84, 0x271fee1c, 0xdc2117ba, - 0xddfc5b6f, 0x2a3cc0d0, 0xe88130b6, 0xa54fb679, 0x9cb75c90, 0x168d1cdd, - 0xbabd774a, 0x2ea82e39, 0x89b540f5, 0xbf3b85d5, 0x69e824bc, 0x6306d376, - 0xf7e703aa, 0x38fa42ac, 0x7474e7ae, 0xe7c59b7c, 0xa7aff4cd, 0x11b069bc, - 0xb47f83ed, 0xea2b5898, 0x81877d33, 0x8abb49e7, 0x8f0ba015, 0x9d76bfc0, - 0xa68e5e7b, 0xc63e66f1, 0xcc1947e5, 0xebe010b5, 0x724d9969, 0x998fbb41, - 0x25c6389f, 0xae675c01, 0xe3fa1850, 0xc022ffb0, 0xfde1679f, 0xa5fda15f, - 0x379967dd, 0xf9480e58, 0x3cf02955, 0x79f821bd, 0x696fcb65, 0x43cc199c, - 0x27602079, 0x735f9e69, 0xd80af50c, 0x67ed4147, 0x519b66f6, 0x14496f8f, - 0x6ca1edf1, 0xfef0f7d8, 0x18ec88ae, 0x927e184f, 0x36c5c9e5, 0x17cfd622, - 0x7c795047, 0x5172a331, 0xaae3a722, 0x44efb796, 0xc766a97b, 0x738e2316, - 0x9681f1c9, 0x999bd613, 0xe896ef5f, 0x1e21af3d, 0x28252cd9, 0xe1b3504e, - 0x32ec91ac, 0xd1529f01, 0x00f08a5e, 0x1cc2dc3c, 0x503cf1ab, 0xc7f0655a, - 0x5bffe0e9, 0x60c3bf72, 0xd1da80bf, 0xb5173991, 0xb94fb95f, 0x5abcf96f, - 0xf30c7a05, 0x4583e4be, 0xd8cd1f42, 0x2f796938, 0xcefd5100, 0xfc9d1963, - 0x78f649bc, 0x516bc091, 0x8f64fdc4, 0xe3d88517, 0xb7dc3dec, 0xe64ac7a4, - 0xa5a23d24, 0xcc07493b, 0x23f7a06c, 0x4ddebd84, 0x120f2d6f, 0xcc3d245c, - 0xe4685d5c, 0xc8c79be6, 0xb26f4aed, 0xa326d7f0, 0x30e816bf, 0xba063ec8, - 0xed6baa0b, 0x9d0d2ff1, 0xb41f2819, 0xe7ccb876, 0x60e7c2d4, 0x9a5fcf22, - 0xb38d70e1, 0x8073c00d, 0x85f9397b, 0x10ca46f1, 0x3dc6dbe4, 0x6edf2377, - 0x0ff37ce4, 0x92b30f41, 0xf049113c, 0x9af4b3dc, 0xe77fc41a, 0xf2065312, - 0x8a6967b3, 0x3dfd0f1a, 0xc39214ab, 0x18a697a3, 0x97d3ce11, 0x7c871e0d, - 0x345ccb9d, 0x1638b4fe, 0x9c186ed6, 0x7947e5c4, 0x6319819d, 0xf4462908, - 0x506a9f0b, 0x9a8c2fc8, 0x6be02264, 0xf557c096, 0xa4adb78a, 0x6ff01caf, - 0xe01f5e28, 0x2aeab33f, 0xee701f09, 0x52c7cb08, 0x66b154af, 0x3b8c0a63, - 0xd11b6567, 0x82479c31, 0x95b2d7fa, 0x66eaaf84, 0xd5dd7b4d, 0xb9d83f84, - 0xb589cf11, 0xf79f823b, 0x8276124f, 0xbe913993, 0x225a773d, 0xb471af30, - 0x4ad94f80, 0x6b7286c5, 0x84b6b2fa, 0x7d3ea01b, 0xed84eaaf, 0x8587c374, - 0x1f2823fa, 0x1cdecced, 0x719c57f2, 0x9fb09238, 0x52edcac7, 0x8619ef45, - 0x3ce2d3ed, 0xd8cfd0c3, 0x618591f5, 0x73a1df7e, 0x11e4732a, 0xfca20f95, - 0x341b1b2a, 0x2fbec029, 0x3112d833, 0xf365e91e, 0xb83dc593, 0xd4f84088, - 0x7e24ac46, 0x887e45a8, 0x34c3f3f0, 0xdda17b8c, 0x7942a2f3, 0x30476c84, - 0x34709fbd, 0x9091c226, 0x9033efb9, 0x8a6f2e9c, 0xf971f3a5, 0xea2322b2, - 0xb16df2d5, 0xf9c11f64, 0x86cbbdf4, 0x6879f1fa, 0x649ede59, 0x39bcb718, - 0xe306a9d3, 0x19dcf431, 0x0d39ceb0, 0x8efe2487, 0x23bf80f4, 0x7807f0e1, - 0x4f2f6a0b, 0xe0497212, 0x238a2d8d, 0xef3a5abd, 0x58089cd5, 0x48ba99d7, - 0xe9ec93ca, 0x8c66c47c, 0xe903fca0, 0xabdf1abf, 0x7944cfdb, 0x0e57673e, - 0xf169fc21, 0xd3dffe36, 0xcbbda187, 0x68616efe, 0x66cb4d67, 0xf6864db7, - 0x6fce14db, 0x19afead3, 0xddc4768f, 0xbd9e5c49, 0xd5d07205, 0x41b7b197, - 0x0e40ba0e, 0x11f20bbe, 0x4e2fefeb, 0x8b87faa6, 0xb47e541d, 0x47951fb8, - 0xf25fbf84, 0xd102101d, 0x2e2492ed, 0xc9249717, 0x6482faf8, 0xffc66934, - 0x3a21ddfb, 0x6c67de1b, 0x9d36309b, 0xc15cebb1, 0xa9c6f7fa, 0xd3b5fac1, - 0x8c971b60, 0x0a15dbe7, 0xeee5a3d9, 0xe1fd4191, 0x7bc464dc, 0x9e5fac2b, - 0x86f49dbf, 0xe81938c3, 0xb8e2a6f1, 0x37d7fea0, 0x9fd506a4, 0xfad07248, - 0x0ecf8d26, 0xb4b9bf6a, 0xecbd507f, 0xa431919c, 0xf1014777, 0x679102cf, - 0x8e770704, 0xfbef1b17, 0xa4b0dd75, 0x5fbd60bb, 0x73d033ef, 0x5e243e2d, - 0x9951ac67, 0xbe9bc607, 0x2c1fe406, 0x74e348f1, 0x0e2fafe2, 0xb25ce858, - 0x7f6f29bc, 0x350fd401, 0xe80f2819, 0x55b8b2d0, 0x6a1daf68, 0x2832b04a, - 0x6155cb3d, 0x2c8cd8d7, 0x2d15de40, 0xa6f9425b, 0x93933e65, 0xef7697ec, - 0xc0eeb293, 0x122e2af3, 0xd53de4f9, 0xfe10aad7, 0x67df045c, 0xe15ee922, - 0xf127b071, 0x4ef4e12a, 0x0ae3aebe, 0x13f5865b, 0xb9f71f91, 0x6a71d60b, - 0x0e856362, 0xbeea15fd, 0xcf9f9204, 0xb6e90cab, 0xf2819e74, 0xafbf660c, - 0x533ac06e, 0xbe395372, 0x66a3ca55, 0x7c6898cf, 0x021405d6, 0x6d3c16fd, - 0xae01ea7a, 0xfb7d78ff, 0x8203df40, 0x8e8e913e, 0x2c5732c7, 0xf5a1562d, - 0xc276fe7e, 0x87ee7c06, 0xee106fa7, 0xfdc1bd7b, 0xefe01266, 0x20df0af3, - 0x128b6f92, 0x70b4af88, 0xf2e4623f, 0xa07c8bcb, 0x9fa6e5f8, 0x7e9296cf, - 0x26706e98, 0xe56e493a, 0x3adca0a7, 0x7640d2b2, 0xacbbd330, 0x3e8f4893, - 0xe72c744f, 0x8c77a239, 0x691df5c3, 0x5f9864c8, 0xa552be51, 0x1fd20af3, - 0xe7e3efef, 0x0f5587d4, 0xdbcc24d8, 0x525878a0, 0x3edcdd28, 0x5de5186f, - 0x596ded6a, 0xeabc097e, 0xe64bb009, 0x8179e4ec, 0x3f53bf2c, 0x3ee06075, - 0x3cf9f196, 0x4af94105, 0x1daf5955, 0x2ec8eb34, 0xc273c18c, 0xa254f789, - 0x8d5913b3, 0x9f019343, 0x86bb7527, 0x2ff505de, 0xea8f7a26, 0xda223ea1, - 0xeb842ff3, 0x0ccadd5c, 0xfaf30b25, 0x091aaf0f, 0xacfe7def, 0x2e6c49c1, - 0xcf39fcec, 0x43fdeecc, 0x1bd815f6, 0xe1ddb8bd, 0xcffbc14a, 0x1acd1d73, - 0xc7c3807b, 0x00204981, 0x056adb17, 0x7876376d, 0x3c01e588, 0x31d74f57, - 0xe079e04f, 0xb1e3c8b0, 0xa873f324, 0x24a61bb4, 0x5d333973, 0xbd9be9c7, - 0x037a70ac, 0x0f502afb, 0x173db948, 0xbf55aaf3, 0xbb72901e, 0xfe52358a, - 0xdb99238a, 0x1f15b32f, 0x9835ddd9, 0x2bfd0289, 0x56683c6c, 0xf3e4d9b5, - 0xb698d265, 0x7a60fb40, 0x73279732, 0x8e3ecf8c, 0x3ac95be4, 0xfd353ef8, - 0x2af8373e, 0xf543323a, 0xc36d854f, 0x6f8d3b32, 0xb79fa270, 0x756bf052, - 0x256be2a3, 0x51eb853b, 0x299d57e9, 0x3f56a8f4, 0x8d25e885, 0xd1a99a3e, - 0x5831acbb, 0xe97ac2cf, 0xaf5cb2de, 0x68ee9d76, 0x0e61c10b, 0x6ff50bac, - 0xa7b7c785, 0x38add684, 0xeb21a301, 0x31ee64a9, 0x780fb8b1, 0x5d08eade, - 0x215f769f, 0xd4fb15eb, 0xf9c2bbae, 0xbbe62b55, 0x04293554, 0x243eed2f, - 0x9c76b43e, 0x97854bc4, 0x45a2b7c3, 0xd67e7c21, 0xf2321f6d, 0x61ba4b6f, - 0xe02ff0cd, 0xb047497d, 0x6f9412af, 0x1e41ab95, 0xd3d28667, 0x456cd61c, - 0xad61a9ba, 0xdf9053cb, 0x1faf9b5a, 0xb5867e8e, 0xa9f9d36f, 0xa39aded4, - 0x7a50058b, 0xbf8e5773, 0x17e74fca, 0x5cfc278a, 0xe9ddc3f0, 0xe01e9fa5, - 0xeaa37335, 0xd4141c8a, 0x7a3fe44f, 0xbcb38e09, 0x63fa235e, 0xe53f0967, - 0xab59d685, 0x2e5ff7e7, 0xcf015eb8, 0x0fdd7b9f, 0x7764f727, 0x76173f85, - 0x3d1a5bdb, 0xfb81b1ff, 0xfe7ca55b, 0xff22ef5a, 0x3b0bb42e, 0xe3c6ceac, - 0x9eb91a7d, 0xbd724f9e, 0x3979e842, 0x5b35d1cf, 0x13305e29, 0xf68080ed, - 0xa56f56cf, 0xd9f1a578, 0xcbb45699, 0xbe99ae8f, 0x8f52f30a, 0xbd274d36, - 0xa97bf95f, 0x40c63df7, 0x4d68a27b, 0x907bfad9, 0x5247378e, 0xdda2b15c, - 0x2045ce23, 0x639fa167, 0x6cab970d, 0x95b39735, 0x90071fa8, 0xfd8bec7e, - 0xf4f0acee, 0x68087e45, 0xe779bd27, 0x779fcf74, 0xfe77b8c2, 0x25e9da29, - 0x755ad850, 0x5adbcf64, 0xcf563f51, 0xde20f0ff, 0xe07b01d3, 0x7b4b5ffd, - 0x0645aa00, 0xea325b4f, 0x54076121, 0x6c321bab, 0xbd083768, 0x7f801ff1, - 0xe7f87844, 0x11cbfc12, 0xdbf101fe, 0x9c381b4f, 0x7fe06ba7, 0xcbc72578, - 0x2b6ca6f2, 0x6d3f2f9e, 0xebbb26c8, 0x821ca6d3, 0x00078cff, 0x1f5fdcfe, - 0x0035776c, 0x817cf1fc, 0x96f587f0, 0xfc043bb7, 0x0dfe1c9d, 0x256cee1c, - 0xc084672f, 0x57f94bd9, 0xe4d1fe77, 0x78e23b44, 0x57d92b64, 0xaca8b7c7, - 0x932ec03e, 0xac37d176, 0xdfb449f1, 0xf767fc24, 0xf28418e9, 0xd7e1f4a7, - 0xd98788ac, 0x3150785b, 0x95ccfe04, 0xeec7f144, 0xa8edbbf9, 0xdd5f116f, - 0xe245d476, 0x19b986a9, 0xd796c7e9, 0x4239e00e, 0x45bf7171, 0xb66fbc8d, - 0x19bef823, 0xda9592e6, 0x8ce2c5d1, 0xa4f5c088, 0x79d3ef69, 0xbebdc618, - 0xd6eaf9cd, 0x5de7c4f9, 0x25b97941, 0xfe80d5ac, 0xd0acd636, 0x05eaed3d, - 0x8642d685, 0x5a3ab571, 0x09453387, 0x56aecbca, 0x564f6475, 0x447c4519, - 0x892455e4, 0xdc29497e, 0x629c902f, 0x2474f2a3, 0xda707d23, 0x7de1f462, - 0x255f382a, 0x9ddefce3, 0x41dbc226, 0x5fc0135c, 0x333f0a35, 0xb7a442a8, - 0xd3a7185b, 0x297bcc5b, 0x972707ae, 0xa71fa875, 0xc939342d, 0xa18f8dce, - 0x42cdd2f8, 0x5e62ddde, 0x313d46ee, 0x61746ccd, 0x317ae309, 0x1a30d7f9, - 0x0df987a6, 0xef748cbd, 0xf3a234b0, 0xdf123c59, 0x8ef87c96, 0x95ea5808, - 0x1fa38e60, 0xf6dd7e18, 0x5e285c7d, 0xf609f8fc, 0x8546d74b, 0x170c8bf7, - 0x2e5c5070, 0x609b3ff2, 0xc75828ec, 0x6f0714a8, 0x3fb8d877, 0xc9e02d7a, - 0xb6afc7e2, 0xfc79799d, 0xb1f30ab2, 0xbc58f7f9, 0x5d541f24, 0xc8cabd50, - 0x62794f9f, 0x34eaf143, 0x8e61dec6, 0x2ab78881, 0xee782194, 0x61f18b2f, - 0xf43aef7c, 0xd4b1db87, 0xd64cbd13, 0x978eaf33, 0x0e3b660d, 0x25e3fdc7, - 0x2abf9e02, 0x0031ad60, 0x83d7d6f7, 0xb437f3fd, 0x02fb5aea, 0xb7d3af7c, - 0xea7d21b6, 0x1b061c22, 0xaf1ee3cc, 0xa539e2e4, 0xadc5e96a, 0xa689e2b7, - 0xa0a3d5e2, 0xacf9e3ae, 0xfee6bf5d, 0x59805b89, 0xeab76e11, 0xcb9abb59, - 0x52e100e9, 0xa978776b, 0xe2853cdf, 0x202e3237, 0x86183ff1, 0x2de3c40f, - 0x4e307d62, 0x37df1583, 0x7cd7c786, 0x8ccc2f81, 0x15cfb846, 0xf257377c, - 0xbf30535b, 0x0478823d, 0x2ed0553e, 0x22ddb806, 0xe2f89eca, 0x476e14a1, - 0xcfc2943f, 0xe25cf7ef, 0x95dccc7c, 0x82797941, 0x7c4daa5f, 0x75ff397c, - 0xc5307ca2, 0xf5cbe34e, 0x8a7ebd00, 0x0240e8e3, 0x691ebd20, 0x68fb27ac, - 0xc3880b16, 0x49fbfa65, 0x77ad0eba, 0xf7dd11cb, 0x66bb1a58, 0x5f95e820, - 0x8e513a44, 0xce6c62de, 0xf68733a9, 0x52e67193, 0xefa061d6, 0x993f4903, - 0x55633fd0, 0x9535e533, 0xf41efc2a, 0x578b42e9, 0xc7e27607, 0x067bbe22, - 0xa79c46ec, 0xfca15634, 0x773169af, 0x975f2096, 0x2c7a8d5a, 0xdff1163f, - 0x8d17595b, 0x2b2d89ff, 0xdf8606e6, 0xe631504d, 0xa4f80b07, 0xadfb05d8, - 0xebc3f947, 0xe4695d2b, 0x4ff5128d, 0x665c61f7, 0x03a079ea, 0x762e1faa, - 0x5fa7bcc1, 0x91d9cf15, 0xfa7e7c62, 0xdecf413e, 0xe9de34e3, 0x53f3e4c7, - 0xf90af9fc, 0x7f5e2bfc, 0xea2f8e50, 0x2f9e6b0f, 0x827f3cd1, 0xf89f5bd7, - 0xf68bd8aa, 0xda4e68eb, 0x921423a5, 0x37214657, 0x12b6974a, 0xbb754b9c, - 0xb59a3978, 0xdc2ff2ea, 0xdb8a64ef, 0xf7809298, 0x50588fce, 0xd533ff0f, - 0x7e814c65, 0xfe79269f, 0x499ce586, 0x7288d78a, 0xe91f3df7, 0xf21e9285, - 0xae428d27, 0xa6e5ea9f, 0x831ea5f7, 0xf1c3de71, 0xbb9c752f, 0xe4f9c743, - 0x4d738cc7, 0x4738c86a, 0xfebecc7f, 0x24e1ca9c, 0x517691c7, 0xe94bba71, - 0x663afc85, 0x70bf9064, 0x18cebdee, 0xcc314bf4, 0xcfd00377, 0x919cda5d, - 0x7dcfe307, 0x0a8cc5ee, 0xbe849bb4, 0x32a739af, 0xdaa3c817, 0x5f950a73, - 0xc4647db4, 0xdb35b37b, 0xa0e38cda, 0x45942d5f, 0x12aaeb01, 0xa77d04eb, - 0xa7a01c9f, 0x4274bd8d, 0xf3cc3c6e, 0xa13b9e32, 0xd5ce7c47, 0x3dfd1f35, - 0x4a11efea, 0x97f2f8d8, 0x7b077f62, 0xee611fb8, 0x6151e5c5, 0xee34576f, - 0x390614f3, 0xfaa2fc60, 0xbf02f9f0, 0x1528eb12, 0x50fa6ffa, 0xe003844b, - 0x1e3de43c, 0x9b58af5f, 0x62fe8b99, 0x04e8f263, 0x7e8f5b82, 0x67ee2ed6, - 0xd67ee16d, 0x02c77b52, 0xbb994efc, 0xf883ec57, 0xbf09b2dd, 0x2c067c93, - 0x378eef0b, 0x89bf7ac9, 0x3f714663, 0x7ef3d618, 0xf220f99f, 0x6e28decd, - 0x361b4ecf, 0x43e50a30, 0xceb46667, 0x4facfc06, 0x4af7732a, 0xc6abf6c0, - 0xc9a17b61, 0xe08ca7d2, 0xf42e88cb, 0xb8feee49, 0xfe8fec4e, 0x35b18f11, - 0x87d806e1, 0xee950de7, 0x45067803, 0xcbc5c27b, 0xe5c5ef2f, 0x8d97bbb9, - 0x0757b1e0, 0xaff5cceb, 0x760fce43, 0x180e82fd, 0x94d2c8ef, 0x30380fc1, - 0x5d78531e, 0xfcff04af, 0xa33c92b3, 0xa23fe702, 0x68f07d63, 0x18ebb171, - 0x1d71f02e, 0xf74a06c2, 0x80b7a028, 0x31e4def3, 0xa9f541d1, 0x15cc71c5, - 0x9a9dbfe8, 0xb1bf541a, 0xffa83b34, 0x07fa33cd, 0xea689f3d, 0xb00bafc8, - 0x97b67b67, 0x5a9f04bc, 0xed0a258b, 0xbe5a4fba, 0xb416e0f9, 0x4eaa3703, - 0xef6759b4, 0x48c1f4dc, 0xf00675e8, 0x497e471b, 0x3ed1f907, 0x7a747997, - 0x7e303e97, 0x50758a74, 0xd73ca2be, 0x68dc6c5e, 0xf29dadae, 0x78ae7f09, - 0xe25ebcd1, 0x72cb9bfc, 0xa99e3f51, 0x79fc9f7b, 0xcfbe6635, 0xe21e2f53, - 0xbd442ddf, 0x357f7402, 0xe2f688be, 0xc0fc1039, 0x0e3b45ff, 0x86cd9c51, - 0xf7b44dc1, 0xf1e9e6d3, 0x942d64fe, 0x81c65fa8, 0xba018adc, 0x036368e9, - 0x48de61b7, 0xe5db85a6, 0xbf90a6e7, 0xf7146f7c, 0x8c4decfb, 0xcc48efa5, - 0xda86b86d, 0xd345ce6b, 0x1da96ff8, 0xfa2f28e3, 0x13e28505, 0x2da75313, - 0x8decfdc5, 0x1db80ef2, 0xe7f89de6, 0xdc23c7ab, 0x7bf1b66a, 0x77d51302, - 0x5941e7f2, 0xbd0d78d5, 0x7b65513f, 0x621fb015, 0xe342ddce, 0x001b444e, - 0xcb50eaea, 0x5597a803, 0x3f9f6b63, 0x5a31bca0, 0x9ed4de48, 0x26f7a48b, - 0xfdfd7114, 0x0c4f217b, 0x635d7c9d, 0xe7a24dcf, 0xbd7c2e92, 0xf7f282b2, - 0xf51b090d, 0x4321bdf8, 0xaffd42a7, 0x4a9fd73d, 0xfa37dfb9, 0x2fbe91fd, - 0x7af84860, 0xbe8de61c, 0xc8d8af11, 0xe3c8d12c, 0x62c375b3, 0xd5791858, - 0x9e39cf3d, 0xc73a6c6f, 0x3bff8ff3, 0xe417f5cd, 0x9d4592c3, 0x31178c7a, - 0xe10d8473, 0xd8305255, 0x67c01151, 0x8c9baeea, 0xeac31f88, 0xafa88db7, - 0x0516504d, 0xf916af3c, 0xdd795a58, 0xfc83e422, 0x3fd49b8e, 0xd106792c, - 0x4136ade7, 0x9e8f82a0, 0xdf2c7c16, 0x0e33a0ef, 0xf73b71e0, 0x79a6b7f3, - 0xd13942de, 0x7c6ec851, 0x4767e49e, 0x7e69c606, 0x9e03f5ae, 0x1bb21423, - 0xbeaf293b, 0xc3a1c0a4, 0xdd7bc0f8, 0xf3f3877a, 0x26d1f685, 0xca96fdf6, - 0x6fb8e216, 0x1d97f2fd, 0xedaf182e, 0xd43cbcee, 0xcfde720b, 0x0b7bf17a, - 0x1e75d6cc, 0x2fb587cf, 0xef903b47, 0x0ce1e227, 0x4d3ba2e3, 0x76816e74, - 0xbed4778a, 0xef0a7a6c, 0xe15ad5bb, 0x17f30afc, 0x8ad912bd, 0x4af6dc74, - 0xc7f51ea4, 0x9f3dbd1d, 0x5e8a7c21, 0xcf063be9, 0x9316ae8b, 0xe3fd919e, - 0xb6f24a3a, 0x485ef587, 0x4ce9697e, 0x81a7a7f2, 0xa0994bf3, 0x7fc172d3, - 0x6747c11e, 0x0f8892eb, 0x45822ecf, 0x91753c63, 0xda1b7032, 0x7d0b0e0b, - 0xe5f24e97, 0x411f3c44, 0xb1fec4fb, 0xeaa18f74, 0x1f106c5c, 0x14cb9f56, - 0xed471dfc, 0x05cadf92, 0x7d84989f, 0xb5d04331, 0x3f245bb4, 0x624f74b2, - 0x6263ec2a, 0x95bdf03d, 0xc8f9fee2, 0x31ba7e4f, 0x80be90da, 0x022b926e, - 0xedbea7f8, 0x8a768626, 0x744dde29, 0x40ca0333, 0xb766653b, 0x971b629d, - 0x592feb08, 0x7bc3a996, 0x6a79f29b, 0x7fd1a5ea, 0x27c8aa44, 0xa0e6b730, - 0x8ba86b5d, 0x9a7de274, 0x1e3cf133, 0x87057f34, 0xbb837ce3, 0xf98ced08, - 0x3fe4284f, 0xe503fb43, 0x7503d0d2, 0xcabf40c6, 0x5106e74d, 0xb9ca7d3c, - 0x2634a8cb, 0x38472e7b, 0x5ebb9d94, 0x8fd06be0, 0x710e3f8a, 0xc192bf71, - 0xc86e7267, 0x4792bf44, 0x4f1f3c45, 0x0347b667, 0x546b7de3, 0xb8c98ff2, - 0x9933f4a4, 0x804fdef0, 0xdf46fd3e, 0xa3df4198, 0x0a9dfad1, 0xb93ffeb9, - 0xbffa40d1, 0xa19dedaa, 0x79fe783a, 0xf5092ba6, 0xa7837ac9, 0x6733f708, - 0x0339efb2, 0xb83ee7d4, 0xe1dc3ad5, 0xbeb36787, 0x69f50735, 0xfd11c033, - 0xd52bcd5f, 0xf76e3ef1, 0x1a38f344, 0xcf496fa7, 0x739f3a5a, 0x73e09b2e, - 0x7a44ceb6, 0x2dd02ce8, 0x5243d00b, 0x2f3948ef, 0xeba48ff5, 0x5f973d6a, - 0xca18e6d5, 0x9debf323, 0xa442ee49, 0x1f3c7ebb, 0x9e77afd0, 0xf902355a, - 0xe53c74e0, 0x21bd4b5d, 0xc585e0f9, 0x244794c9, 0x03e492f5, 0x7ca5cf29, - 0xf52f7497, 0xfd3fe8d6, 0xc3bfd6ef, 0x3cd293af, 0x7d02a577, 0xfae7ab5d, - 0x85bd5aeb, 0xfc6c67e8, 0xcdd23d24, 0x43d1cbc5, 0x0a1e8e42, 0x3d35a392, - 0xa94581e8, 0x1c5e7e52, 0x7c11cc1f, 0xedc4de33, 0x81f39448, 0x8da6b5e3, - 0xb1f7087e, 0xd9eb953a, 0x3ddd6b9f, 0xa9d5ffc9, 0x97ff2697, 0xfc9c5ea4, - 0xfe54efff, 0xbcad0a9d, 0xa3710fc7, 0xf3bd3fbc, 0x83ea1f72, 0x03f40c83, - 0x6896c1ea, 0x0fa126c7, 0xc5445f48, 0x1f487ef8, 0xfe9ef614, 0xf5e1a9df, - 0xff6c66c1, 0xd240fab1, 0xc91be497, 0xb42f9227, 0x62f9247c, 0xbce16fc2, - 0x8b7a7888, 0xd6aa8fdf, 0x0e289b7b, 0x8c1e88e9, 0xc76dd9fc, 0xdf88536d, - 0xe084f442, 0x04bf3f1f, 0x1fc90deb, 0xff245f92, 0x98fe0b54, 0xf243f829, - 0xf9b56ec5, 0x0a9811d1, 0x08f9e690, 0x93e488e5, 0xfab5e7aa, 0x42ba47a1, - 0x199b234f, 0xae90c75f, 0xa40ca1aa, 0xfc0f532b, 0xf512f070, 0xa48bbec2, - 0xf3feafa7, 0x0f55f4f4, 0xa7e674f4, 0x1da853d0, 0x03be61fb, 0x1f3673d6, - 0x9fa66de4, 0x8dfc26de, 0x9b21fb71, 0x46f6079f, 0x35ee7df1, 0x67ff93a6, - 0xcf3cf7c2, 0x3303da57, 0xd241bf85, 0x01d81e69, 0xf8fc4369, 0xbcc0f3c7, - 0x847b938b, 0x877c5367, 0x3327cf11, 0x03b40ca1, 0x537fb27a, 0xee4d2ed3, - 0x17fe8a45, 0xb480f3c2, 0x1c6edd9f, 0xaf1e1690, 0x027ed303, 0xa262275e, - 0xb22bf92a, 0x00a35c4b, 0xba890f3f, 0xc2094fb7, 0xf902faf1, 0x2e55b2fc, - 0xd607ca3d, 0xf475ddfd, 0xcaa5bc77, 0x31fece7a, 0x8f099eb0, 0x1d1fbf32, - 0x151d8f9e, 0x511fedd3, 0x717fbf98, 0x95fed65a, 0x451be7a4, 0x9ea74ade, - 0x3d4483c7, 0x8096ea1f, 0xbea6817a, 0xeab7f796, 0x3e60593b, 0x928dd209, - 0x0eecf1cb, 0xfa601fb0, 0x2fa8b3f6, 0xff430a6c, 0x86fc6d46, 0x5ca2cf57, - 0x6c50a1db, 0xde0e1baa, 0xfa070481, 0x07d5383e, 0xc65d77ef, 0x78dbcdd8, - 0x43b5f6fd, 0x132f7956, 0x1bdc06e3, 0x2e2b3432, 0x502847ca, 0xa199597c, - 0x4d3dbef0, 0x1eb913ca, 0x0214f746, 0xaf9867de, 0x77ef2977, 0xd1674de7, - 0x4ba6adfb, 0x5186ff98, 0xac6fefe1, 0xe4c6fd10, 0xfe7d84c7, 0xe1ca9a70, - 0x3406fc2f, 0x694d343f, 0xff9f7f0e, 0x1d2fc109, 0x78213f18, 0xfe855a4e, - 0x84a30eed, 0xc2157bb7, 0x41632c7b, 0x9f98347e, 0xbad71bea, 0x7cf41a4b, - 0xbc0d2ebb, 0x77bf687e, 0x03db05a5, 0x5f069bf4, 0xf7801fa6, 0x77de61dd, - 0xfadfbf04, 0x125af843, 0xdba0bef2, 0x5d8e9259, 0xa31ef441, 0xc67d1377, - 0xb4362bc4, 0x91dc6ba3, 0xe0bcf12b, 0x12d2cfe7, 0x138c9b82, 0xb4dff084, - 0xc8033192, 0x6fcf124e, 0xebfc855b, 0xe7f775d6, 0x1ae928fc, 0x5c0136af, - 0xef07f5c9, 0xeb769cbf, 0x024ff42a, 0xaa73d05d, 0xadd603eb, 0x4d66c7e5, - 0x7f86947d, 0xfc91ff05, 0x70007d40, 0x16f941ca, 0x08e8c87f, 0x044f93a0, - 0x7c894e9c, 0xdcd18ef2, 0xe2c8ec9e, 0x3c6977e5, 0xa099f52e, 0x9e9253cb, - 0x90e002a2, 0xf43f4416, 0xf60221f7, 0x29ba704d, 0xbdf3f25e, 0xbfc0c525, - 0xfcfe761d, 0x66fed67f, 0x5fcd3795, 0xcff78ed7, 0x2096f7b5, 0xf7c7ba5c, - 0x768fda2e, 0x6e024dc4, 0x67bdaddf, 0xc08077bf, 0xbbffa273, 0xf41f40ab, - 0xa46a9e3d, 0x3e94250f, 0x2fa50d5e, 0xfa7de6af, 0xbd3d043b, 0x7950b7ff, - 0xcfbcd2e0, 0x17107bf0, 0x5bc0beff, 0xe3af06b1, 0xa31d7835, 0xbaca97a9, - 0x4afe482f, 0xe3be5cb9, 0xe312fbe1, 0xd0a9afd1, 0x3d3f2475, 0x3cf4483f, - 0x77e926d7, 0x4fd5c115, 0x47ed0fcf, 0x2cdc9dfa, 0xf491b5e9, 0xc39424cf, - 0x29f5fc23, 0xfea88728, 0xc5c60970, 0x91eafafc, 0x6fb72855, 0x1ffd9068, - 0x2f37fea5, 0xa6ade393, 0x8c8f12e7, 0xeefa463d, 0xafa97ca6, 0x3fb9271e, - 0xefbf85a7, 0xfeddff4c, 0x4687e41f, 0x6ad65c0d, 0xff4d5eea, 0x6fd017d5, - 0x2fef34cb, 0xa95f3cd2, 0xd4d1afa9, 0x2fdf821b, 0x1f10a19b, 0x38f01596, - 0xb52f96a5, 0xef4ae1f4, 0xf5ba73b6, 0xfb2662b9, 0x26af882e, 0xb5faf3d4, - 0x1a4b1be9, 0x75f501cc, 0x5f384a9b, 0xf7016cc0, 0x7ae6419f, 0x4307a055, - 0x20b3720f, 0xd9b907bd, 0xf9efab4f, 0xafe07ff3, 0x0a371429, 0xab764bb2, - 0x5536f5c1, 0x75bbdbac, 0x810182ff, 0x4be7d5f1, 0x63dd5cf0, 0x5cdbc71c, - 0x2ed02632, 0xae25cd62, 0xfeca7d80, 0x5efbbee3, 0xeb3cf9c5, 0xd1b25cfe, - 0x114f718c, 0x12f3b4df, 0xfa8aa5f4, 0x6ff856ba, 0x2f1e61c6, 0x5aa293c6, - 0x080fe673, 0xee6b27d8, 0xbb6cfb83, 0xb7dfe55b, 0x00fc07ab, 0x8398ca9c, - 0x33a750f2, 0xb6a5e517, 0xfc2cc4c5, 0xf76f782f, 0xd442eadd, 0xc61707d3, - 0x2bd35e51, 0xb17cfce9, 0xe277a63b, 0x45b7a84c, 0xb6f246df, 0x54b1feed, - 0xcb5d52ee, 0x2d8c6cbb, 0x894af75e, 0x1e7c72f9, 0x3bba7043, 0x2592a5fd, - 0xa6f7ef40, 0x8f7de83b, 0x03b896dd, 0x0c07eded, 0x0e043714, 0xe7e89278, - 0x3c60d341, 0xe92d976f, 0xf2b1714f, 0xc38d26c7, 0xf7e5a47b, 0xd25e2819, - 0x9f91b3a9, 0x58c0f3c8, 0xb19a93ca, 0xabde944c, 0xdfe57ca9, 0x7bc7ac7f, - 0x14eb5da6, 0x55cd4efa, 0x6dff375f, 0x1b2bd410, 0xc67ee9b2, 0x9474e7cb, - 0x9ae9fe17, 0x53cc3ebe, 0x47591c3e, 0x9fd0a5f9, 0x9e56bbee, 0xc92fec77, - 0x0daafec7, 0x428e3853, 0x47cfda3b, 0xe14fa857, 0xab32ce3d, 0xbbf30a25, - 0xc8c77e8f, 0x3ef473af, 0xe6ef7d13, 0xd6e7b353, 0x8f74f135, 0x767d2d09, - 0x15587154, 0xf4dac380, 0x29c925fd, 0xf8126ed8, 0x032d6fdc, 0x75d32f3e, - 0x93e90fd3, 0x5f5e588a, 0x92cdeebb, 0xa38fb04d, 0x7ca5f44f, 0xd70c84b1, - 0xd78074ba, 0x93d70ce1, 0xd9fb8a54, 0xc79bfcaf, 0x593a5f25, 0xb5f4889e, - 0xcbf5d059, 0x0313cae7, 0xc5416eff, 0xc1d13d29, 0x02c7462b, 0x5469eefa, - 0x6ce782ba, 0xf43883a0, 0xe710cf9b, 0x85e7a016, 0x57d8c35b, 0x3db9d34b, - 0x84dbf6d6, 0xba208e51, 0x29e498fe, 0xfea0379d, 0xa447fa62, 0x16988ee7, - 0x77752e62, 0x1ddb243e, 0x34327049, 0x3322fa45, 0x1aea7fd1, 0x4ff3a2e7, - 0x96c99f73, 0xfd143e00, 0xfcf2f13f, 0x3fa04fdf, 0xf13efb9e, 0x604b3ffe, - 0xaff6433c, 0x68bc5ab4, 0x58b31c5c, 0x838f88f4, 0x3147c5fa, 0x9d62ad3f, - 0xc540f481, 0x5d4584ba, 0x6e807f28, 0xdda6bfd0, 0xc0c32997, 0xc63d18fd, - 0x192f3f57, 0x5e781693, 0xbbf24139, 0x377cbe27, 0xc6c944fd, 0x65f33d01, - 0xa7cb8da5, 0xf7f8eb71, 0x58872b75, 0x7bbf74f4, 0xe89babdd, 0xc8bcf01e, - 0x5157bc5c, 0xf844ceb9, 0xbc58b4ea, 0xbef12bb6, 0x0b1f4581, 0xae74a1e5, - 0x0e19f54f, 0xca9147c2, 0x54b911f4, 0x190a3dd2, 0xf0b13c3f, 0x1d31c7d1, - 0xbbe673f3, 0xefc0187e, 0xe9d38b8c, 0xf92a6d99, 0xc4f1b51f, 0x1ab7d7ea, - 0x888fd90b, 0x4710f627, 0xe29d62ac, 0xe3e1e2bb, 0xe238da89, 0xbdc5d2bf, - 0xa238eeb3, 0x5187be81, 0x4588e229, 0x7f5a156b, 0xbdfe42e5, 0xee38a292, - 0x18b23e3f, 0xed2fa0e8, 0xc5cb6bdf, 0x7fae693c, 0x8be2992a, 0x5eaf5f80, - 0x99fc8f3b, 0x5e1ce975, 0xb03be265, 0x199d2387, 0x58afde78, 0xae704917, - 0x07f6727c, 0x7de3e44f, 0x81f189c0, 0xa09b6be7, 0xe19f180f, 0xce39683d, - 0xd0f725b1, 0xd68b6777, 0xf31939c3, 0x73d963b4, 0xde226537, 0xde303252, - 0x2e55fb29, 0xef0fbbbd, 0xd86ce707, 0x950ad977, 0xbb6b0f7f, 0xf021f489, - 0xb80b327c, 0xd9633e2f, 0xd72346eb, 0xa8792c67, 0xfe1db3b0, 0xc29f6cfb, - 0x4104fc73, 0x26b7b8ad, 0x5bef27e1, 0xf7f8e995, 0x0a754b36, 0x8902c3dd, - 0x7e97f746, 0xa3fdc191, 0xcedc1979, 0xd270cb2d, 0x55ea9e3d, 0x4cd2e726, - 0xbdf74e3e, 0x55e73875, 0x282a3aeb, 0x1317f9ae, 0x976a57f9, 0xad22ba45, - 0xf9e31f3c, 0xad779401, 0xaa3c0237, 0xfc6e5c1c, 0xad63d042, 0x94d5d263, - 0x0767ae9f, 0x5607eff0, 0xac9cb85b, 0x9bb8058e, 0x86e90139, 0x1939f7e2, - 0xb8e253e5, 0xe6028329, 0x8c3b4457, 0xc7fab0e3, 0x0d63abdd, 0xfec1a7e8, - 0x38420f97, 0x237f5dc6, 0x9559efae, 0xb4801af8, 0xbfed00aa, 0x3c3cd567, - 0xd8ad9777, 0xf0e50e3d, 0xf1832ddc, 0x7b2b0546, 0x23d25dee, 0x3bfe0573, - 0x395a3e45, 0x81bbf1d4, 0xb9706437, 0xdfb951e9, 0x2f0106e8, 0x79f20749, - 0xf7030af5, 0x47bc83e3, 0xe4bd5301, 0xdab71a43, 0x728891d2, 0x81bb7ab8, - 0x8cdf87ee, 0x973806eb, 0x751f492f, 0xdcaae800, 0x51df4310, 0x344ef2ad, - 0x51aabd62, 0xbdffbaa1, 0xd3a40c84, 0x60bd962f, 0x1c39fa45, 0xfa839ad9, - 0xa45e6ba9, 0xda29ee93, 0x8beedfb8, 0xaf743965, 0xc3ad8669, 0x9965df82, - 0x8edb20b1, 0xada0fc72, 0x0fcf88d5, 0xb0ea6736, 0x46d9b2ee, 0xbfa5dd61, - 0x885fea92, 0x41fa177c, 0x9e3852ba, 0x1b769aab, 0xdd2feff1, 0xd4e2e82b, - 0x41f6efb3, 0x4675503f, 0x2fd41f47, 0x527d0740, 0x28cfce11, 0x9a6b9fa4, - 0xa4bc1e78, 0x03a41a83, 0x8239bbe0, 0xbdb66a0e, 0x43f21770, 0x373fe20d, - 0x9e808e94, 0xf9fda9db, 0x7f18e30d, 0x44e91dbf, 0x2fa833ea, 0xce3fa033, - 0x058bebc8, 0x0c7da1fe, 0xe00ef76f, 0xf9dd75f9, 0xd07c4108, 0x66d77e13, - 0x4c3e04e8, 0x8ad77724, 0xd8ae76fd, 0x9dfc456e, 0x1ef7767a, 0x3f54b78c, - 0x11dada0f, 0x3c041f86, 0x56ff716a, 0x19d93f5a, 0xab5fb8b5, 0x74ddff7f, - 0x96b0f82f, 0xfdc9fdf1, 0xfec5ead6, 0xfef173e5, 0x2acfb13a, 0xadb5e026, - 0xc13be72f, 0xf4c7c867, 0x3fb121dd, 0xbbf83d8f, 0xfec5bbba, 0x6cc9449a, - 0x0f8456cd, 0x0fe517e2, 0x28cb8fd0, 0x397409e5, 0xe50365b5, 0xc97c4bf7, - 0xd7efbff5, 0x93fc2e2b, 0x9d8f1254, 0xb6f77c3d, 0xa1c9f045, 0x763292fb, - 0xd8befc00, 0x240d9f4c, 0xcc07d57a, 0xce46e927, 0x49a7f457, 0x61bee2d7, - 0x5f1c56fc, 0x1bd07bce, 0x0e71c7ad, 0x721fce32, 0x8b2f92fd, 0x3b5da7ea, - 0x4efd8ad8, 0x5ed1b259, 0x3f7c7811, 0xbbef46c3, 0xf7806ed0, 0xf2143b5d, - 0xe7121f5f, 0xbdf743fd, 0xe01f2d60, 0xc577f7a7, 0xe19d25ba, 0xe4c9fa0f, - 0xb9daf77a, 0x6ebb583f, 0xbae48729, 0xe1bfee8b, 0xeb976c5a, 0x2051f8c7, - 0x4a384a9d, 0xfaf7957a, 0x344b74b4, 0xdaaaf527, 0xa6d77d33, 0x9dfca21d, - 0x78ed7690, 0x2c3a3ec2, 0x9ebbcdf2, 0xe77df956, 0x41edc965, 0x33188ef7, - 0x259fea07, 0x15b6aef3, 0x49b73c62, 0x521e7ba1, 0x4acfc0af, 0x923e807d, - 0xdef0c1f6, 0x36a57f3c, 0xf10275de, 0x63bc7559, 0x44927e1c, 0x7d57a5da, - 0xa0c6aadd, 0xcf1b6aff, 0x53749383, 0xf89db275, 0x93dc5aa1, 0xeef15b2a, - 0xf74861c4, 0xce281b4f, 0x58df7653, 0xb3fbda23, 0x8a1f4d37, 0x127bc0e0, - 0x6c4fdf28, 0xe047921c, 0xebc4b661, 0xc6c4bef1, 0xbfc7af47, 0x87633a5f, - 0xc1a1df4a, 0xcb8f9071, 0x7f23c8ee, 0xcec8e1eb, 0xaed02389, 0x436ab5ff, - 0xa6e47ebb, 0xffb08b21, 0x58ef4b48, 0xc6d078fa, 0xf4bbaa38, 0xa427a431, - 0x03f32c1d, 0x90bdc5eb, 0xaf9cdeec, 0x8a97757a, 0xefac0bc8, 0xaef9f183, - 0xddf4910d, 0xa3a352a8, 0xdbe715b9, 0x8ee74499, 0x2526385a, 0x2b9ee9db, - 0x8cb369d9, 0x9725222c, 0x453023da, 0xc74375f9, 0x5e4fa81d, 0x1832c3bf, - 0xd4cb8bbf, 0xb9cb43f3, 0x90e3cd7d, 0x61dfc171, 0xeac8eb92, 0x3b57e9cd, - 0x2f7f7c9e, 0x74ec2b9e, 0x3fde919f, 0xebe9ecb1, 0xd89e1f51, 0x7dc7639c, - 0x4919db1f, 0x198e0bf7, 0x78e7bf82, 0xb4c2f7a9, 0x3de4a9f7, 0xc1defcd7, - 0xfba49cf6, 0xb9cbde0b, 0x98f2d2ec, 0x74662e4e, 0x065cfc4f, 0xe8e4fee3, - 0x7e62b6ef, 0xc9a34561, 0x8e64f786, 0x7c63fd20, 0xdf4abb6b, 0xdfbba201, - 0xdb23af80, 0x703ee8f3, 0x5ebcc7c5, 0xf0f8acd1, 0xc3fb72fe, 0xc2fe53f7, - 0xf137b04c, 0x3db7796a, 0xebe1fabd, 0x38ce0d91, 0x3bf1cb3d, 0xf3366700, - 0xef908b7c, 0x75bebc3a, 0xffe38a4f, 0xfd2cfdbf, 0x077bd313, 0xf09347df, - 0x57aae796, 0x720a2e80, 0x72fbf0fd, 0x9fb22cf1, 0x50f62e4f, 0xb4395a79, - 0xb3d2246a, 0x15ee8625, 0x51e3b4bc, 0x5373bf15, 0x79f06dbd, 0x308f1f3c, - 0x9ff7d0c7, 0x90bc5cbe, 0x17279a82, 0x8a3f89d7, 0x15f854b6, 0xb55e547c, - 0xfbde8dad, 0x0b5e4772, 0xd97debde, 0x9ac5c31c, 0x3be820ab, 0x3dbf1299, - 0xfb9657dd, 0x1cd7fcfa, 0x9fdd72cf, 0xc56e9e6f, 0x21fdb57d, 0xe23865ae, - 0x86c63a37, 0xc8a56076, 0x86ba392f, 0x23c7d9db, 0x18abfe62, 0xed7c7cf0, - 0x0efc4494, 0xa9b6ccd1, 0xc57b63d7, 0xe786c54e, 0x49cee703, 0x7dcf3c56, - 0xe2b4efa6, 0xd6cfaa3d, 0x3e57fbc8, 0x237bbbfa, 0xd829b3c6, 0x9eab447f, - 0x84293239, 0xfc32f44c, 0xcbee9ea4, 0xe4ed017e, 0x451f393f, 0x89f813fe, - 0x99927cc3, 0x4bbf722f, 0x9c57f9f7, 0x7d8a46ff, 0xcbb6f7b7, 0x17b506f8, - 0x63f6f015, 0xd096b76b, 0x68de4fdf, 0xbfbae1b0, 0xf1a068dc, 0x4db9c0e7, - 0xbe3deb07, 0xb0839f99, 0x13e8e78e, 0x6779f99b, 0xef3f334e, 0xb833cf54, - 0x60d2fdf8, 0xe80a2cba, 0xeb2ddf47, 0x7323bbe1, 0x737f7c5c, 0x7ee27f40, - 0xb1bf442f, 0x9fee99ac, 0xa93e6a5d, 0xaaff7e96, 0x74dd1791, 0x08bd13db, - 0x23ff22b8, 0x98ba4add, 0xf5c786b3, 0x0b83cded, 0x9d24fe91, 0x5803bf68, - 0x3bfc646f, 0xfa28bab2, 0xb324f7ee, 0x62fa80c3, 0x18e77c4a, 0x075f4f04, - 0x916aaf97, 0xe4f785ce, 0xec29bd58, 0x15dec477, 0xbc1a78f2, 0x7abbf74b, - 0xcff7f8db, 0x59317dc4, 0x474abe82, 0xda293e7d, 0xba038dfe, 0xf2ffae74, - 0xf5d03d3a, 0x3bf691a4, 0xd7809db2, 0x7af35ff5, 0x167b7d9e, 0x7def3fd4, - 0xec3d3af6, 0xf695d26f, 0x2fa80621, 0x75cdf259, 0xc9b9e063, 0x3bd83ae1, - 0x9b139e60, 0x7f71d292, 0xdb087ed0, 0x8e7a27a7, 0xee2b5960, 0xba569d8f, - 0xf4cc2d06, 0xa77b7ff7, 0x0e4be0e5, 0xc0d3bd7f, 0xa73bbbe8, 0x87f5cb7b, - 0xd70e9d2f, 0xa109dea9, 0xdd8ce5ed, 0x5e7cf947, 0x7e076f7e, 0x788911dc, - 0x5dd38aaf, 0xd3c7bcb9, 0xe3c7b9a0, 0xe4d5f7e4, 0x7f792afd, 0xfdff72ea, - 0x7297b5b3, 0x00ffecff, 0x4fb2f369, 0x00008000, 0x00088b1f, 0x00000000, - 0x7de5ff00, 0x5554740b, 0x55b9e896, 0x2a493eb7, 0x54842549, 0xaa84a925, - 0xc0902b7c, 0x310c7c25, 0x0403e548, 0x6a285888, 0xa205a0d4, 0x01148280, - 0x55f4741d, 0x9a7c3061, 0x179f8ee9, 0x102d4622, 0xdd787195, 0x866db1d1, - 0x3220538f, 0xb40e9afc, 0xd38ceb63, 0x68d1d01d, 0x38311b63, 0x6f360cf4, - 0x4dce7def, 0x802a56ea, 0x6f7be7be, 0xf65e97ad, 0xee739f61, 0xffb3ecf9, - 0x5f5bdf67, 0xa5eb2c19, 0x0f24c664, 0xa153ab63, 0x63595a74, 0xff7b9419, - 0x68d2cfe9, 0xac839ac6, 0xc18f2e3b, 0xd3f5a35f, 0x7ccf5051, 0x2e504bba, - 0xcd1a484b, 0x139960c6, 0x996fd062, 0x12aeb189, 0x6d3b26e8, 0x12d8c2cc, - 0x019dfe09, 0x19caf9ff, 0x956c674b, 0x44edfe15, 0xf08742b8, 0x7f466683, - 0x3f98059f, 0x1fd8c0df, 0x3925744f, 0x9d9d8cf5, 0xbb0c2e1d, 0xbc65fb18, - 0x009ce6cf, 0x8ecd1ded, 0xbec634a6, 0xd4a4c37c, 0xd09eff43, 0x60f927df, - 0xe67aa5fc, 0x6d9284ef, 0x24d8ce1f, 0xc3ea2f28, 0x61dfa053, 0x8db6f157, - 0xa9cbbcf0, 0x3f9e0c63, 0xfce70aeb, 0x82c678f5, 0x32f2932e, 0x32777ea3, - 0x9f1eeb80, 0x9dfb1c3e, 0xfe5d7d7d, 0x936eb03d, 0xec1258cc, 0x598c067b, - 0x0030780e, 0x07c32fac, 0xb40e3442, 0xbea09307, 0x0e74f5c5, 0x2f307c23, - 0x0dd8c89b, 0x06ebef8c, 0xf11fbc39, 0x196494c5, 0x6f9b37f7, 0x3283db0f, - 0x3333a38c, 0x98bbae03, 0x4d3f5875, 0x8eb19800, 0x7f60c34b, 0x3263c066, - 0x24c78096, 0xa1eaa6c6, 0xe9afac13, 0x0990fa97, 0x7884d7d6, 0x85d07014, - 0xd72c7a23, 0xc58bf8c3, 0xbc8ecbbc, 0x58c1c46b, 0xeb07fe10, 0x5de62259, - 0x3d7771dc, 0x9092cb9e, 0xc0b74ce1, 0x7ffa25f5, 0x72c79d0f, 0xf2feefd1, - 0xe29c46ad, 0x7eda1dfe, 0xafa6d9cb, 0x52fcf0f5, 0xfdc46dd6, 0x6a8ceb2e, - 0x0cf9a8ef, 0x977cbbd7, 0x99debeb6, 0xc2748698, 0x97b1b2c6, 0xe74d54f4, - 0x99f448bd, 0xca746faa, 0x66e19fb8, 0x371304c5, 0xf4479f3d, 0xb00cdec2, - 0x63ac7ec8, 0x8b4fd118, 0xb1e74f4b, 0x9cc49764, 0x7ebb18e3, 0x42731657, - 0x61aefd53, 0xc85d2654, 0x5fcffaa0, 0x57de3639, 0xd75e7032, 0xc6ab6abf, - 0x6aff5df5, 0x3aea9511, 0x4e1d049a, 0x867497d5, 0x2ce71d61, 0x9b800eb0, - 0x8162c08e, 0xd66e9a7e, 0x99e11887, 0x57bfb199, 0x596bc72c, 0x424fa5df, - 0xfd8a0e58, 0x3a24974a, 0x1f3c6484, 0x433d61ef, 0x031e627a, 0x79993bb5, - 0xa05ca5cd, 0x398ebb1b, 0x24dfe063, 0x19ce2fce, 0x81ee9ccf, 0xfc583976, - 0x87584ab3, 0x0941ae61, 0x5c737b41, 0x33e436d2, 0xe574f416, 0xe20d73c3, - 0x4e38aeb9, 0x54ee0937, 0x1d2af3cd, 0xadfa2adc, 0x18769a4b, 0xb3c1b2e9, - 0x5121e888, 0xc7acd4c9, 0x406a5fa4, 0x67d5b9fa, 0x623ba4f8, 0x585fa21c, - 0x295e0dc7, 0x7378fc84, 0x50ddb683, 0x44ad75f9, 0x8e47d425, 0xfbf6d5e7, - 0xd003d229, 0x717e103b, 0x9c0c3d24, 0xc3a3c583, 0x1224f073, 0xb9cccbbd, - 0x5be012b9, 0xee181b0e, 0xf7cf14df, 0x97310e79, 0x0f80fd86, 0x8875e260, - 0x2e4fa817, 0xc537e2d7, 0xb0e7c5a3, 0x867e2d3a, 0xb7fbb57b, 0xda6ae435, - 0x35237c33, 0xcb8b59ed, 0xbfb67034, 0xc47fd342, 0xec0d6aea, 0xf4d4ce0a, - 0xa37f5bcf, 0xbd682e06, 0xa8bfd35d, 0xbda6817d, 0xa69f7438, 0x268ed47d, - 0xf9da5c0d, 0x98ffa688, 0xda6b8f5d, 0x6a3786c7, 0x7e1dc7da, 0xe84f034a, - 0x7fe9a2da, 0x34db07cd, 0x5fba93ed, 0xdb5fb4d3, 0x9e0686f3, 0xd35bbbdc, - 0x0385ca7f, 0x1d8ab81a, 0x31aff4d3, 0x4f0356ff, 0xa6abfeb5, 0xc7fb74ff, - 0xce19f69a, 0x67da6a3f, 0xd2d1bfb9, 0x93973c6b, 0xa5ff2bd7, 0x9359ee79, - 0x5f50dfef, 0xdd954b34, 0xebf48641, 0x35ba3e24, 0x0184a74d, 0x972a83fe, - 0x1c9e1d04, 0xc1392561, 0xb78e59f2, 0x32b0e914, 0x6e7c7c8c, 0xe0f24497, - 0x28bd28ab, 0x91ebd1ff, 0x4afd9da0, 0x22765e52, 0xc45d41dd, 0x331e29fc, - 0x39d62393, 0x81aaceac, 0x9aed7b87, 0xa706b6fe, 0xe7c33da6, 0x2d67b4d6, - 0xb6703456, 0x7fd35cbf, 0x068f6ac4, 0x34eb0576, 0x7bd6f3fd, 0x6b417035, - 0x517fa683, 0x5ed34fbb, 0x69ac5a1c, 0xafc3b51f, 0x573b4b81, 0xd98ffa6b, - 0x8fb4d415, 0xb4d7af0d, 0xaadc3b8f, 0xb5742781, 0xf35ffa6b, 0x3ed34841, - 0xa6877ba9, 0x4e9edafd, 0x77b93c0d, 0x94ffa697, 0x5c0d610b, 0xfa688ec5, - 0x6a4f98d7, 0x0fd6a9e0, 0xdba7fd35, 0x67da6b4f, 0xb4d73f38, 0x2cd076ab, - 0x7adad7f7, 0xaf5d1761, 0x7cf359fc, 0x90c3dab0, 0x486f823e, 0xd613b34a, - 0x3fe102eb, 0x777ce49c, 0x28ed1e9c, 0x8c14182f, 0x41ad2901, 0x420c92fd, - 0x480ae90c, 0xe2a6358c, 0x20ac4028, 0xc15549b7, 0x4f68c9f3, 0x73aa9000, - 0x1fa0fcb9, 0xeb5ad813, 0x1bb266a7, 0xdf40971c, 0x29bfc25d, 0xa0944b83, - 0x85ebaa9f, 0x4ea166f9, 0x726f3a02, 0x582e3cf9, 0xaf9d7dcf, 0x6862cb4f, - 0x705b0427, 0x9307a01d, 0x9e6f41bb, 0x79776388, 0x378f064b, 0x89780cc3, - 0x5c48ef98, 0x32cca3ab, 0xcc33fcf4, 0xff7fa967, 0xae3e06b8, 0x8a6bfb04, - 0xa0a7ff18, 0xfbb065ee, 0x37c0035a, 0x153d8c05, 0x4cfc12b0, 0x5b704ec0, - 0x7b6549c0, 0x96e54dc0, 0x1ded4280, 0x5f827281, 0x0e087808, 0xdca8ea05, - 0xfd52f016, 0xc10340f6, 0x547c04af, 0xa62c08ee, 0x9f80b5f2, 0x560677da, - 0x40f3fc13, 0xc0ceca90, 0x237faa7a, 0x9bf04ad0, 0xdf827681, 0xdca8840a, - 0xe541d815, 0xb52740ee, 0x22ec0def, 0x9840edf8, 0x30e070e0, 0x5d0207c1, - 0x7c0c1f04, 0x40a1f040, 0x03879537, 0x0d1e543d, 0xf1fb52f4, 0x078205c0, - 0x576b4bce, 0x2e576133, 0xd2c07412, 0x2f793db8, 0x85f6523f, 0xbb462d8e, - 0x43a09177, 0x87983543, 0xcc867740, 0x2ecd6dc2, 0x13a06a3c, 0x71c9d137, - 0x96af2fb4, 0x4070d04e, 0x33560d7a, 0x5a9bd237, 0xc9e954b6, 0x90ae0cfe, - 0xbb732f42, 0x336feb88, 0xb537f553, 0x85283e37, 0x079b9ed0, 0xf811b276, - 0x9f6123e6, 0xe5c7147c, 0xc1bf39f5, 0xa35f768d, 0x66c0af14, 0xb277fe01, - 0x8c2fe03b, 0x5ed77fa4, 0x9fb456d3, 0xc235f5d4, 0xe7183a38, 0x5a2eecbf, - 0x6c3b2357, 0xbd40f5c0, 0x72fc0f47, 0xe2dbe6c6, 0x2fbeba02, 0x2234175b, - 0x85425913, 0x8cc644de, 0x48f3df76, 0xf7fce7e7, 0x17c1c21c, 0x9c429559, - 0x78537ae7, 0x7f30adf8, 0xb2bd11ef, 0x5e3439cd, 0x00ceb796, 0xf6997de1, - 0xa0773fb7, 0x17f75f1d, 0xe1cf0fbd, 0x21b12184, 0xe9dd7404, 0x3acf8892, - 0xd94d3a5d, 0x02fdf766, 0xa26df9d7, 0xa01d4eff, 0x56ebdbf2, 0xb612b2bc, - 0x20a2b8d4, 0xf055ed19, 0x5f680c0f, 0x034e61cf, 0x989b87ca, 0xea1c5de7, - 0xf823e666, 0x52a41656, 0xe176f9b6, 0x21636ebe, 0xa6157d82, 0x8afb589c, - 0x383bd75e, 0x752c70d8, 0xdd90f29a, 0xfbc70077, 0xeb43d136, 0x7a69313a, - 0x5d4bee21, 0x49c33997, 0xdeb366fd, 0xdf7d7017, 0x53fafbee, 0x9d306f29, - 0x61f488fc, 0x3fb06981, 0x3779c233, 0x38e0ef03, 0x214b0fcd, 0x3e9573a4, - 0xa74cc11a, 0x7a851ff1, 0x805e9229, 0x4b7fd04e, 0x9399cdeb, 0x4dd2f448, - 0x3e926ff2, 0xfa7b0468, 0x28542e84, 0x8c4e89e9, 0x5173ac12, 0xee49d01a, - 0xc0f0f4d0, 0xe423287a, 0x17d9d020, 0xfe9fde38, 0xe2371ae1, 0x93dbf96d, - 0x66b7889c, 0xd0079c1d, 0x9ea8f073, 0x442604ec, 0xd2dafebb, 0xb207f910, - 0xc529cca2, 0x7172e373, 0x7ead9ebf, 0x4ddc863d, 0x74f4e5c8, 0x0ba86ec2, - 0xef9cb8d1, 0x2e7d76d5, 0x2e7d473f, 0x15a6df3f, 0xc3d52d9f, 0xf81c4ffa, - 0x8d2ce8dc, 0x3fd58fb1, 0x823f2879, 0x3aef97ae, 0x7e83cd3d, 0xb92eeb17, - 0xbea07131, 0xd2abcc50, 0xe898de91, 0x5c896adb, 0xc75d3f57, 0xa75d22e7, - 0x11e75d00, 0x768a7f5d, 0x33936cf9, 0xbb2856f9, 0x28613501, 0xc95a2f7d, - 0x14c05c7f, 0x2f32172a, 0x0c808b95, 0xc1bd8e90, 0xf7888d27, 0xd52758fb, - 0x777e503f, 0xbdf5d23a, 0xd9f91f3a, 0xd517594b, 0xb5bd672f, 0xaf37b478, - 0x1daef35f, 0xeb537d56, 0x44915393, 0x7fcd0c6f, 0xdb39cb17, 0x4e834fa5, - 0x5cec93e2, 0xe4b747c0, 0xe613227f, 0xd5677dbf, 0x3f505913, 0x85cfcf5b, - 0xa2e7e31d, 0x7de891ca, 0xe0145f03, 0x78a6dff3, 0xa4fa5f68, 0x345f0d3a, - 0x123cce3e, 0xcfbbd38c, 0x8ae6da14, 0xfbf293e0, 0xf28590ff, 0x13bdee4c, - 0xdbf97bcf, 0xef3c54a6, 0xfbd718fb, 0xaf8d4792, 0x119efaa8, 0xe2cfdfbd, - 0x85f7ec15, 0xb22fefa0, 0x17f7d119, 0x658a3812, 0xcb287603, 0xf2cbd9f1, - 0x72f6f406, 0x88d1cedd, 0x95ebd027, 0x7df70e78, 0xd632d9dc, 0x9420fa85, - 0xe1887683, 0xecd29335, 0x7617e8d2, 0x8d850129, 0x7f3e219f, 0x198ee38a, - 0xfca92ebc, 0xeed19fd0, 0xd0591930, 0xce7c465c, 0x677f2226, 0x9abf891a, - 0x3879b511, 0xb7e9d78f, 0x84ff1e0c, 0xefe1ef58, 0x841d3fb8, 0xc52cbcfd, - 0x2feb879a, 0x3cc0fc53, 0x19d24724, 0x2e4773cd, 0x3e7563e7, 0xa076e966, - 0xc1347e9d, 0x8f9e3b77, 0xfd52471a, 0xcfaec3c8, 0x667cf1f2, 0xe5506c57, - 0xaec78d33, 0x84e972e3, 0xf84419c1, 0x014b9544, 0x6f2fd609, 0xa7ff286f, - 0x371d700f, 0x8c612d98, 0xc34ab077, 0x35ff7ed9, 0xdf1f4077, 0xcae3eaa0, - 0x1a8ef8a8, 0x018a61f7, 0x3ecc57d7, 0xf141f152, 0x0e4e551d, 0xb1b0bfd2, - 0x889fc42e, 0x79c7f597, 0xce3fb9fe, 0x8d79c3a3, 0xe6328e42, 0xf8237b77, - 0xae00d6d4, 0x307fc68b, 0xff8d7cb3, 0xd9c0d560, 0xffa6bb7e, 0x4d4ed588, - 0xd6e82bbb, 0x57ade7b4, 0x6b417034, 0x517fa6b9, 0x170347bb, 0xfd34ea87, - 0x6af0ed47, 0x06ced2e0, 0xbb31ff4d, 0xb1f69a7c, 0xf69ac5e1, 0x1afd8771, - 0x6ad74278, 0x3e6bff4d, 0x27da6a08, 0xb4d7af75, 0xaad3db5f, 0xb6f72781, - 0xb94ffa6b, 0x57b4d210, 0xb4d5bfb1, 0xd75f98d7, 0xf1c62fc0, 0xeb54e778, - 0x9b9e683f, 0x81afdf6e, 0xf1e7885f, 0x23ce199a, 0xf9c5e7da, 0x278b6f06, - 0x3ee5987e, 0xffdf69a9, 0x8dcdc8c8, 0x47a12fc0, 0xb67fe474, 0xc53d71d5, - 0x1d39aa1a, 0xd7bef1c4, 0xe66a1f2b, 0xbaf7d1cb, 0x7a9d8e90, 0x75f2266b, - 0x039cf97e, 0xd0ac7640, 0xc51aa2b3, 0xc9eebb9d, 0xf48e5803, 0x6c8d5ebe, - 0xf270d253, 0x7da39600, 0x1903575f, 0xca716533, 0xf996583b, 0x70d8d6c7, - 0xbce7ab89, 0xe0c4e583, 0xb3941a8a, 0xb17e2660, 0x3e7dd608, 0x846d9238, - 0xaa652575, 0xd10f5e71, 0x1d0caaed, 0xdbaaf9f1, 0x4b37142c, 0xa322d6bf, - 0xe81cdf3e, 0xec10791a, 0xd3a7f4dc, 0x69dc62d7, 0xa1f9d83d, 0xc017b022, - 0x59f2c7ee, 0xe043ebb0, 0xbb046d1c, 0x604dcb1f, 0x73fd63f7, 0x9c23f760, - 0x7ad974fe, 0xc9d56e7c, 0x6172ea7b, 0xca0f11fc, 0xd7533456, 0x0e2b7539, - 0x0fec7ac0, 0x4b28ad1a, 0xe267ae8c, 0xec8eb09c, 0x0a8eb065, 0x51078b42, - 0x3052ecfd, 0x1c39321c, 0x2becfd07, 0x1db81a74, 0x2eb045ff, 0x97cf8b58, - 0xaedee93e, 0xb6f9f630, 0x8a1937b3, 0x5d799f61, 0x014d6db7, 0xe6799738, - 0xf1d3be02, 0x93fc602c, 0x09cd8f79, 0x97860c96, 0x48ff7a14, 0x2cee4972, - 0x16b53e46, 0xeb81947d, 0x85fd50da, 0x3ce2b3a2, 0x0839cc8f, 0x787e7eeb, - 0x23e758bc, 0xaff2aa73, 0x79cf5c66, 0xef50ef94, 0x47218cef, 0xffe853fe, - 0x2f5c7993, 0xe5159fc3, 0x08938d93, 0x949d81b3, 0xf376f20c, 0xd1a7d5a4, - 0x41ad90a7, 0xbb23e509, 0x144fcf08, 0x7823c828, 0x1e44fc4a, 0x537947b2, - 0xe733e454, 0x1f3678c1, 0xf1914ed8, 0x785ac5b1, 0x19e79c33, 0x0c7ac0c3, - 0x3282e977, 0x92f0c1ec, 0x9e605157, 0x5fb0798e, 0xb51b3780, 0x8e9165fe, - 0x9f717d91, 0x378beeba, 0xdda76829, 0xf0f5c797, 0xecbb8096, 0x7ffa0313, - 0x4027d94a, 0xfd8b9947, 0xabe40f92, 0x04abd1ad, 0xd2e19fa1, 0x2237efdf, - 0x3ac5df61, 0xfd639f51, 0x27bb089a, 0xb86b8c47, 0x19bc27a4, 0x6a4abd9a, - 0xbd06fcc4, 0x618cefe4, 0xc9e69577, 0x4666b9fc, 0x1e7786ed, 0x5f309c96, - 0xba486366, 0x4bf1c687, 0xc2dbd40a, 0xb1ab3ebc, 0xf0085a53, 0x3a4e791d, - 0xac9c7507, 0x08feb0c5, 0xa0e5d93c, 0xede78564, 0xc425068f, 0x55eadd83, - 0xdae22258, 0x52bdfc4b, 0xf57db4f0, 0x864fb2c4, 0x8abdbae1, 0xa59be717, - 0xcadf9bf2, 0x2b1f3d70, 0xbd42a9bf, 0xc33d1bf6, 0x9c6f8cfb, 0x8c5a724a, - 0xa9a5a87d, 0x973ccf5b, 0x729267f1, 0x9e93f11e, 0x2ce2ddbc, 0xf17dfe00, - 0xd6c34b36, 0x47767418, 0x75b3a71e, 0xe2deaa99, 0x73d749eb, 0xeafaa93c, - 0x1fa72b1b, 0x4cad6e55, 0xce3ab0e1, 0x24f1ecca, 0x8f5a8637, 0xf98e3dad, - 0x19bbd622, 0xfde2b1e6, 0xac2b77cc, 0x21f03788, 0xcc9f34bc, 0xe7d6e9e5, - 0x4637e4dd, 0x3e20cfd3, 0x5c9bd100, 0x1dd97486, 0x31ba066a, 0x682a33cd, - 0x5bfeda2f, 0x2472848b, 0x284ab593, 0xb5d96d47, 0xe7d46587, 0x1bd8afb2, - 0x12be8ec3, 0xa9e7a83f, 0xcf8325da, 0x2abbf9cf, 0x0c0d43b2, 0xe5c9b6e9, - 0xa9f9e1b4, 0x6474da74, 0xe22faa78, 0x3a0bd73c, 0x7aad672e, 0xd60ad3e4, - 0xeb256549, 0xd63af2a2, 0x5987a54b, 0x99ab2c65, 0xf32d6542, 0xf98d3952, - 0xad63aca9, 0x9d64ce54, 0x2eb3d654, 0xa3bfc12a, 0xe4accbd2, 0x7608de87, - 0x9973960c, 0x985bca97, 0x482dca9f, 0xfef013df, 0xdbe095a1, 0xbb952759, - 0x459dff80, 0x53311f18, 0x39e417b9, 0x3c836f96, 0xf20c32c7, 0xf8c269dc, - 0x83ca9b88, 0x43ca8501, 0x0f2a7281, 0xefd43c07, 0xca8ea068, 0x952f01e3, - 0x540d0227, 0xd47c0576, 0x316054ef, 0xfc05ef95, 0x581fbe54, 0x8107e54d, - 0x12ff9520, 0x91654f58, 0xe20ae411, 0x163ddddb, 0x8f9c9afd, 0xe8271e8d, - 0x84f34fa3, 0xfdd1ebff, 0x78f1e2f7, 0x83ba3a8e, 0x94aed5b1, 0x6e6d1e90, - 0xe504279d, 0x74937746, 0x4eeb9437, 0x64d63b70, 0xd93b244b, 0x724abed6, - 0xa4bbb8c2, 0x9c027d6e, 0x0fbcdeed, 0x4f4198e7, 0x6b65ed54, 0x7f841413, - 0xe819a4ff, 0xdfc1ab70, 0x7fda15bb, 0xcebfd2f5, 0xaece8331, 0xc7f53c48, - 0xed4c38d7, 0x66b20e93, 0xf207c02b, 0x26993f4e, 0x10a075f1, 0xc7d2fe3e, - 0xe3e4d673, 0x791cb93a, 0x368e05d5, 0x5b0f19fa, 0xdb18cfc8, 0x0eac667e, - 0x2dab49e0, 0x471fe865, 0xf5b8a3f4, 0xdba2fd50, 0x563ae7d5, 0x1e2337a4, - 0xee0a7dd6, 0x65e51389, 0xcf8c58f7, 0xbbab8e45, 0xfe99f9ba, 0xf647f332, - 0x5e332e93, 0x54e79151, 0x7403ffde, 0x86df4d1e, 0xaebf1f4b, 0x3598f8a3, - 0xf6faf515, 0x7a772e14, 0xdb43e3b3, 0x53dbdd60, 0x9f21bc05, 0x610eb5f6, - 0x8dbad7d8, 0x6fc764b9, 0x1d36f38f, 0xd1bff6c1, 0x69a0db29, 0x636fbc7b, - 0x14f9c131, 0xea9759af, 0xca5ea377, 0xb1fae049, 0x9c48f1cd, 0xffff8233, - 0xe6eee422, 0xadaebeca, 0xd7ad4fe8, 0x6e7802b1, 0x1b05fadb, 0x4bce30dc, - 0x022ec09b, 0xc2f27938, 0x9ed0050d, 0x513741bb, 0xae1e642f, 0x0b4da5e3, - 0xe128d95f, 0x0b5323b8, 0x213cdc61, 0x7586733f, 0x74095d8f, 0xc6d466de, - 0x63f5fa15, 0x8597e73e, 0xd019cc30, 0x5e2239bf, 0x1ac0d5b1, 0x4166f522, - 0x35b7973e, 0x4c34bc45, 0xd33cf1e1, 0xe3d0f888, 0x11aaffb0, 0xbe93fe3c, - 0x9ff14cd6, 0x9e7fc774, 0xe9ed0e9c, 0x4d053a1d, 0x74b6d95a, 0x9efd018d, - 0xf22758db, 0x3f8956e3, 0x76e6cc1f, 0xb92c1832, 0x1efc2273, 0xf2ca37b0, - 0xf6a7e223, 0x7184a086, 0x4b11aa8c, 0xa7378c25, 0x3093ee3b, 0xe0de91fe, - 0xe8897c93, 0xfda9f927, 0x2b9f22ae, 0x6f67d61f, 0xf735e784, 0x3c0cbeb1, - 0x81b79857, 0x566409f2, 0xecdf3916, 0x27878e22, 0xb43d2064, 0x691ad7df, - 0x9af8d15d, 0x991eaee5, 0x1ce07c3f, 0xccbfdba3, 0xfdb8e7e7, 0xf9029871, - 0x1f8f1260, 0x9339789c, 0x6dd9e5ec, 0x23f41ef1, 0xb2393c4f, 0x2aa7e096, - 0x9eff683c, 0x1a62b978, 0x9a9fb396, 0x484efd49, 0x05c630ec, 0xbb753f66, - 0x7939f58c, 0xef1c2eb0, 0x71e891b4, 0x89f753f6, 0xc5a91fe7, 0xf05d72f6, - 0x2e9fd0ef, 0x012d7e6f, 0x891505e3, 0x7961646f, 0x6abdd742, 0x837fcc3f, - 0xd51afd95, 0xda4377b5, 0x3fc1d4df, 0x6b993ce6, 0x378c78c0, 0xf3ce973f, - 0xf031e626, 0xf92f077c, 0xba3b95b7, 0x8e8b01de, 0x5bd9d75d, 0x9ebad783, - 0x5883d65d, 0x34158756, 0x61ed59a3, 0xa72c41ef, 0xd16bf975, 0xa0fba9bc, - 0xdd9620f5, 0xc45e7d23, 0xedffabff, 0x055e3796, 0xab63c478, 0xe68768ac, - 0x633dde3f, 0x0d2fc51b, 0x60a1f90c, 0x8f55bf92, 0xa6f66c04, 0xf6787ca2, - 0xfa875919, 0x8d6ae4dd, 0x4f74d843, 0x4ce30eae, 0x175a53db, 0xe20bbed3, - 0x28f1e219, 0x8ba421e8, 0x2a6f1482, 0x25f013f2, 0x829dc39d, 0x7e294d3e, - 0x8bd60a6b, 0x7efe8e7b, 0xd85e1cf1, 0x4e35afdf, 0xa55279a2, 0x08cdc4a0, - 0x42ec23b4, 0x7f33b79f, 0x96c3e206, 0xf18adfe8, 0xce2a82ad, 0xd3912cff, - 0x996f7605, 0x10508f48, 0x3fd5bd3e, 0xe6c1cf0b, 0xe01bcfeb, 0xb06a0774, - 0x25c93edf, 0x367fee98, 0x39061c4b, 0x3fc2eb43, 0x5ba4e78c, 0x51cec9d2, - 0x806b6fd7, 0x0eec22f1, 0x968dc7dc, 0xba54e781, 0xf5f620db, 0xe60b2884, - 0xf5d4f1f3, 0x7ae7cc6e, 0xd4edd61d, 0x62f47ae1, 0x5d0fb03d, 0xfa227ac4, - 0xd7fafed1, 0xd23b14cd, 0x897e6305, 0x4729cc97, 0xcea17fee, 0xd71a3713, - 0x615fd6ff, 0xe509295c, 0x67f3ac08, 0x919927fb, 0xf1f7a34f, 0xfb88be42, - 0xfe8cbd80, 0xe71f4cc3, 0xbf46e6df, 0x0d94fe84, 0x43bfdc61, 0xd45c60f6, - 0x0c926966, 0x39b5fb11, 0xd99e9eb8, 0x728fdfe8, 0x82796665, 0x8b3df482, - 0x72b5ae75, 0x0f983efe, 0xfd622beb, 0x7136167f, 0xfe7c4ec0, 0xe24ef799, - 0x67583a91, 0xcfea3155, 0xbca5eec7, 0xcc8fcd89, 0xcfeb8c3c, 0x3fb93f74, - 0x7ef40615, 0x3e7dce2d, 0x77656f8f, 0x87bc9ac8, 0xc9acbf2c, 0xac58c88b, - 0xd07a076d, 0xd95d2ac0, 0xa829d5a5, 0x2509746f, 0x9da06733, 0xf923a492, - 0x9a4a720e, 0x8d1ed31b, 0x7f812ba2, 0xcdde7cf5, 0xb373a7cf, 0xb039f859, - 0x737cc55e, 0x7aacd8a2, 0x336f304e, 0xd03279b0, 0x3ead737d, 0x8f1fa124, - 0xb232f1fd, 0x26f70d97, 0xada73e0e, 0x19cce706, 0xd41fa728, 0x2aaf2959, - 0x67a0af0a, 0x94fc99fe, 0x1da8d307, 0xc53365ea, 0xabd6233d, 0xcf6b058f, - 0x3bfd4ae3, 0x0cce7858, 0x4cfae0d7, 0xa899dcc7, 0x32973367, 0xf6e8ff3a, - 0xe7b547a2, 0x78ef7e4a, 0x50b1a38c, 0xe79c07f8, 0x5af6c74c, 0xcfa3efb4, - 0x9cbba555, 0xc2f5b161, 0x2f5c0523, 0xa72824e4, 0x90aec8ea, 0x66f04ec9, - 0xfd23c3cb, 0xb9f2efa4, 0x57e5301f, 0xec43d216, 0x1f087363, 0x3f5dc255, - 0xa8738629, 0xfba1d3ee, 0x7e3ddec2, 0x5099e9e0, 0x7bf5fd4e, 0xdfa0c74d, - 0xe32cefd4, 0xeb377eb0, 0xa081819e, 0xf90361e0, 0x7cbe6b8d, 0x440315a5, - 0x414c8dcd, 0xe3ceabbd, 0x6efae028, 0x25e4218f, 0xb32c5af9, 0xd907246d, - 0xf4114bc5, 0xe89e9002, 0x6f31b787, 0x91f92b63, 0x8612fcb6, 0xaccd3c79, - 0x97d20ef3, 0xe30c8d67, 0x383637af, 0xffb0550d, 0x869d1b1b, 0x219f78f9, - 0x23b43ab3, 0xa8506a6e, 0x8546a6fe, 0xfd799bd7, 0xd50f06dc, 0xf0f46dcf, - 0x5bd40b7a, 0xd4290f30, 0x6f718015, 0x753aa4b6, 0xe8d01f78, 0x4c17ede5, - 0xfc1c7ed4, 0x8c27cc01, 0xbc910b8f, 0xf1d1ed6f, 0x7c7f237b, 0x9ab58248, - 0x3b0ecb12, 0xe8f77f11, 0xcc175014, 0x2b332d94, 0x7836cfc0, 0x7f687a43, - 0x1032858e, 0x3617bb91, 0x7ea10b79, 0xe2b643b7, 0x7b8376fe, 0xc147f98b, - 0x9de132a5, 0xbdde00fe, 0x3af741d8, 0x3efc455b, 0xf14cc4b8, 0x2875b066, - 0x6496ccde, 0xb7863b0a, 0x86b02c77, 0x39031ed0, 0x7bd8e748, 0x00764c8f, - 0x6ea3c3c8, 0xe6768bb4, 0xca9f182b, 0xb7e5aa5c, 0xaa0b85f4, 0x6646bc68, - 0xbebd3f45, 0xbcd78f91, 0xa1d21753, 0x71b9655d, 0xf341d226, 0x3fa0a60e, - 0x53c2ecfb, 0xee10c3b5, 0x3f2e1450, 0x79a172b4, 0x9c4753e1, 0xcebf1fb8, - 0x79fd405a, 0x5fd9af1c, 0x0d2f5dbd, 0xb79d33f0, 0x0c7e4073, 0x61ca3796, - 0x5e63271c, 0xc1f182b5, 0xc627d874, 0xbc8c3bf3, 0x4ca7783e, 0x0be92df7, - 0xf475b0e5, 0x0b677f00, 0x1f23a614, 0xd17c9126, 0x9dc8d7f0, 0xc179f85a, - 0x32efc0a7, 0x9db82bee, 0xd1673e51, 0x903f6d76, 0x57943a93, 0xfadaedd9, - 0xe3fa8b5b, 0x443c1a02, 0xe7e6d9e3, 0x9f7a2f72, 0xc70afb03, 0x74bed115, - 0xd7285f7c, 0x72d8bea0, 0x1b8bea80, 0x44e9c565, 0x0a79d779, 0x53b45ff7, - 0xeb806166, 0x44cd9617, 0xa4dfaa7a, 0xf5c8f0a3, 0xc2e48bac, 0xc6adf695, - 0x19f7a23b, 0xf2efbfbd, 0xa88e5cf5, 0x6613e0f6, 0x1edb07b2, 0x9ef0e8b6, - 0x78adec15, 0x55dc2b8c, 0x402c1d54, 0x1dc8407b, 0x973d25c3, 0xa216cd27, - 0x51ed8353, 0xa1fc6477, 0x13f55465, 0xd86fd405, 0x6e3c758d, 0x968efb41, - 0xe3173f63, 0xe6d6ea4d, 0x13db5de3, 0xa63f951f, 0x729bc7cd, 0x7f2a3321, - 0x7f2a2f2c, 0x7da6946c, 0x545c75aa, 0x51b5d8fe, 0x1a3563f9, 0x967b9678, - 0xcaf5ffa6, 0x86f81a4d, 0xfd343bf2, 0xd6ee78e7, 0x7754dfb4, 0x66fda6bf, - 0x7c0d4aef, 0x6b5fc36b, 0x6be6dffa, 0xb1dfb4d6, 0xf69a27f8, 0x2d49ff68, - 0xf9701577, 0x3feed9be, 0xd06c0149, 0x3df791f7, 0x28de996a, 0x7b9e46f7, - 0xa7b70252, 0xb9fdfba2, 0x8bfbd380, 0x058f9f12, 0x1c789aed, 0xf135d8f3, - 0x854570ba, 0x71c61bb9, 0x21df951a, 0x0ee262dd, 0x6bb6bfbf, 0x3ff6d9ee, - 0xbc60fd0e, 0x1b5cc4a6, 0xff8c3bea, 0x37b940fa, 0x5f747487, 0x4abf5b61, - 0x69b83d22, 0x5cab8f15, 0xaf3c5230, 0x8eac1d7f, 0xdc46fbc6, 0xeceba96b, - 0x2da47110, 0x85424718, 0xfd4199e4, 0x7ef1c656, 0xe3574d3f, 0x371a3e8e, - 0xa418dca3, 0x7e85bcfc, 0xcdc0e309, 0x7bc5663e, 0x02cb7493, 0x069bff9a, - 0x265d9925, 0xb016da2e, 0x67cc0f33, 0x635c155f, 0x527dbd84, 0xb3d4f7d0, - 0xcfddbcf0, 0x5bd31e28, 0x1853edf0, 0xe143e98f, 0x219d7408, 0xf73f3c73, - 0x5fcfeec0, 0xe6daf981, 0x5ca197a5, 0x5acf6e8d, 0x43ebf7be, 0x6e7f6997, - 0xde1f5bd9, 0x1fe7b97b, 0x25ba75d8, 0x38c87da2, 0xf3264369, 0xe001d044, - 0x80fde62c, 0xf9f5c85c, 0xc5230af2, 0xfc01aeb1, 0xbfbe0215, 0x89cff8aa, - 0x3fb9e03b, 0x44eefb39, 0x65ea1d3b, 0x847e87ac, 0x9fe53fd7, 0x9c92fca3, - 0xa3df6051, 0x9b171dfd, 0x7215c76e, 0x8d6d95ba, 0x6a0718bd, 0xd13a344a, - 0xbb32cfcf, 0x07193eca, 0x7ee06d74, 0xfeffb475, 0xddbfbf5c, 0x9177fe49, - 0x944b2718, 0x9e7f2b7a, 0x4e4c8399, 0x3114f717, 0x6a4fa1f0, 0x655e5097, - 0x8d3f942e, 0x89fd8be4, 0xa4238a46, 0xc1dc445b, 0x171358b2, 0xfb06e350, - 0x9095ef13, 0x4bc3d3ee, 0xf18f9e28, 0x5c6f1c02, 0x11d693a1, 0x32c82f1d, - 0x86bad3e7, 0xd7f59f1e, 0xe6314827, 0x1a875a89, 0x279e889f, 0xea04f684, - 0x64f16599, 0x7bef444f, 0x79556149, 0xd7e470e1, 0x51d393de, 0x90329f7e, - 0x5e8a1c3e, 0x143ccf30, 0x42b4fe31, 0xfe63dfee, 0xe63d6478, 0xe3228787, - 0xef41ccd9, 0x2a0c102b, 0x7bb18466, 0x77ce1143, 0xc277cf94, 0x1ec9d8a0, - 0xfe87b504, 0xd7217d5f, 0x9730d303, 0x19f2386d, 0x81dbcbf7, 0x12dcb1af, - 0xd67d92b0, 0xf087fc01, 0x9527010b, 0xca9b80a1, 0xda85016d, 0x09ca07b7, - 0x21e0257e, 0x8ea04778, 0x5e02d7ca, 0x6819dfaa, 0x01e7f820, 0x819d951f, - 0x46ff54c5, 0x9bf04fc0, 0xbf04d581, 0x0160f685, 0x53d7a9c6, 0x4ad03bb9, - 0xed037bed, 0x081dbf04, 0xec0e1951, 0x8103faa0, 0x060f824e, 0x287c1176, - 0x70f82610, 0x479530e0, 0x7f545d03, 0xc101f03c, 0xc93ee337, 0x15df58ae, - 0x4f8578c0, 0xf77da276, 0x15a16fac, 0x7cfb6bed, 0x79c5159d, 0x04b74fbb, - 0x8d1d1ce3, 0xef131efc, 0x040e3123, 0xed086876, 0x67fcfb39, 0xf6a54c8e, - 0x19bed4b9, 0xc4a70487, 0xafdb82b6, 0xfa91996c, 0x0a2130d9, 0xda58eb9e, - 0xdc03d218, 0xed4f185a, 0xf93215b6, 0xfce9cf6d, 0xeedc8529, 0x336df922, - 0xa541fb70, 0x5c853583, 0xe429aede, 0x161f5cf7, 0xca4a73f1, 0x9e47ad8b, - 0xa6ed542d, 0x7f7187f5, 0x3fb079f6, 0x55bcef5c, 0xb597bc66, 0x72b3a3dd, - 0xcbdf937b, 0xb8bf603a, 0xc50f587e, 0x6e7cd985, 0xade6db2f, 0xe63975a5, - 0xd6ed48df, 0xd05347a2, 0xaff76f4f, 0x6deb439a, 0xd9ae2994, 0x82903bee, - 0x89cf6cf7, 0xf0db277c, 0x64a86f78, 0x8d9e7af0, 0xe3077f5a, 0xec03837e, - 0xec63d7a5, 0x496ed303, 0xc71130cf, 0x331cd47b, 0xe829d78e, 0xfe7121d7, - 0xc4ca0f63, 0xb0302f7f, 0x2db9e0fb, 0x5105df60, 0xb6bf540e, 0xbd55e302, - 0x289dbe85, 0x8e779f37, 0x9c03203f, 0xcfc7c75a, 0x82bf255d, 0xf79c3476, - 0xbf502de7, 0x5e4dbee1, 0x4db0ea5c, 0x6ec835ce, 0xcadff3ed, 0x4397f8c0, - 0x5a8f9ed2, 0xf9f62dbe, 0xb78f8782, 0xf14c9565, 0x378adb64, 0xbcf9075d, - 0x33ff91bb, 0xc38a3e8b, 0x5cde4c30, 0x86450ea7, 0x35fc9e63, 0xff7717ce, - 0xcd423aa6, 0xdf3a8f26, 0x6aef9c58, 0xb1e234f1, 0xc62f9b5a, 0x279286ba, - 0xbf239257, 0x81ef1429, 0x942cb164, 0xb819cf23, 0xe49e0adc, 0x052524f6, - 0x8f3c1a4d, 0xe6a02f9a, 0x0be7440f, 0x29e05efc, 0xde62c4cb, 0x4fd67ee7, - 0xd73a41bf, 0xbd1b3c17, 0x92e36794, 0x35874931, 0x7a12d819, 0xde2aa7ef, - 0x3d0626ba, 0x2853e5a8, 0x1fc100c7, 0x2e713216, 0x38f8ea9b, 0x64ce3e3a, - 0x2ae082b6, 0x4318358b, 0x33e5ab5e, 0x2b7f9c62, 0x759b74e4, 0x870dcedf, - 0x1a8f7cf0, 0x8b6a3728, 0xfd01b42e, 0x3d09e084, 0x7d4cd7c9, 0x2257d6e7, - 0x4117f5d6, 0xa18c5b9f, 0x6e87bc62, 0x504af187, 0x94bf22ae, 0xd582fc50, - 0x7d5de047, 0x1d843fee, 0x75c5fcf0, 0x3cff7429, 0xda1c6d6f, 0x4ccced47, - 0xf83360f4, 0xd046c653, 0x32e90d83, 0x8b387d06, 0xfc0e348c, 0xe226aa59, - 0xcbd70cbd, 0x60972835, 0x2616fbdd, 0x99ac3e91, 0x31acdeff, 0xc9f65700, - 0x65b2cf94, 0x9cd3cf29, 0xca3aeff4, 0x31fb7913, 0xf75df7ee, 0x9fbd2d50, - 0x67ca2194, 0xb283cfd1, 0xc2533d72, 0x0b952e70, 0x99bf142d, 0x133e417c, - 0x4851a7e9, 0x17fa3c7a, 0x6d735e3c, 0x0f79acaf, 0xb68f526d, 0x8f54603f, - 0xb7464676, 0xef3edeb6, 0x6153d3cd, 0xfca5f69e, 0xbf8bf6e1, 0x7070823b, - 0x24e28e95, 0x5064fbea, 0x4df14193, 0xf9819839, 0x8ccc1b9b, 0xbe6db9e4, - 0x60f28ad9, 0xc93c7a7f, 0x2cdbf6bf, 0xcbae8764, 0x3b438a6f, 0x556f34d9, - 0x8c23960a, 0x3b18adc1, 0x2dd5e6bd, 0x9127d937, 0x55f355bc, 0xec1cac82, - 0xdc8dbb81, 0xf73e09c8, 0xe51954f4, 0x9967cf25, 0xa796eaf4, 0xadd8f983, - 0xd4e1d695, 0xf9be4cb1, 0xba76f87e, 0xbeb896b7, 0x1da11a70, 0x7ca379e0, - 0x7b4115d7, 0x3f705a46, 0x9cb66d36, 0x6b7ca469, 0xf982324c, 0xccfd0b0d, - 0x658df588, 0x573e48e6, 0xf2fbe4f9, 0x87c63c7f, 0x0e595f87, 0x2bdc695c, - 0x3e417bf1, 0xfca19be7, 0xf210d369, 0x1f8ff554, 0x8bfce029, 0xf57a4b6c, - 0x7da6318c, 0xce22abf5, 0x9e46e567, 0x61bb32a7, 0xc3dd1d5a, 0xcc65bb04, - 0xdc517be7, 0x27a7b50b, 0x7b713dd2, 0xbde30b2e, 0x8e817041, 0xf8d27bc7, - 0xb98ded7f, 0x936a1f14, 0x3cc129fc, 0xb9f097cc, 0x01dafcf0, 0x7f308947, - 0xeb970e5b, 0xe2b7e42c, 0xb38c357d, 0xe0fd7238, 0x74b505ef, 0xa61ec8cc, - 0x789e85f8, 0x888c69cf, 0x1c5c63b7, 0xcfd117e3, 0xc2d5ee4d, 0xe1682e53, - 0xc0d0662a, 0x3c2d6635, 0x3785aad5, 0x7d3b7115, 0x3f5b5dba, 0x1d85a9c3, - 0x74e307d9, 0xc2dfcf3c, 0xf049e222, 0x447e5ef7, 0x68dd681c, 0x765f3efe, - 0xcb8a52f7, 0x78f0e5b6, 0x3695638f, 0x42c591ce, 0x732fe212, 0xd63c5469, - 0x863f66bd, 0xa30bed97, 0x5efc41e3, 0xa9a1f002, 0x7c8a3147, 0x9e68eaf0, - 0xd23dde87, 0xce08bdb7, 0x5f0c60b3, 0x4d1dabc7, 0xdac53f74, 0x5caf88d3, - 0xb0695f22, 0xe88a7cbe, 0xf90f1d40, 0x7fb11822, 0xf84887e4, 0x37be51a1, - 0x8be41e70, 0x2cfea460, 0xfbd036e9, 0xa1be62ab, 0xcfe543f8, 0xa28f7172, - 0x89f4dde6, 0x9bbcd4b1, 0x705f2255, 0x4ebe5457, 0x1936a39f, 0xaebee7fd, - 0xf8b1f195, 0x682ef910, 0xe5887ce2, 0x837f9106, 0xe22c187c, 0xa6f5887c, - 0x637856ef, 0x050b8bd9, 0x63bfdc5d, 0x224f86c9, 0x73acb7f6, 0xbe5e0685, - 0x910de1eb, 0xe3f751f9, 0xbf08303f, 0xed7e519e, 0x2f9db152, 0x2bcbff4f, - 0x48cd0ccd, 0xcf2807df, 0x319c1596, 0x5ea77bf2, 0x42eb9e23, 0xcc99ff61, - 0x2fd1f2b3, 0xf2e211db, 0x37889d6c, 0x33155b34, 0x3b9981c6, 0x50c71355, - 0x4b4d11e3, 0xd854b65c, 0x7c7f7247, 0x7ca56bc1, 0x14f9e1dc, 0xf1aa48df, - 0x32c6cedc, 0x9c6453d6, 0xdd62066b, 0xc056c18e, 0xd957f9e9, 0xc0c74133, - 0xf8174dbe, 0xb0fdc97b, 0x8f2467ec, 0xea68e42e, 0xa39c44db, 0x0b2dbf9f, - 0x8b3e70aa, 0xb0fb49db, 0x1e1aff31, 0xd1c6d417, 0xe73de24c, 0x343be3c1, - 0x7e226df5, 0xb5f1e572, 0x85d33971, 0x2fc621bc, 0x1adf1a8c, 0x7181fc73, - 0xabbdf1b5, 0x714f37b8, 0x2e3a184f, 0xe9cdd236, 0xdfdd9d69, 0x83317185, - 0x06667fe0, 0xf288993a, 0xe3e9ff80, 0xc1ae7e79, 0x198f8da1, 0xfa0baf30, - 0x98b8973f, 0x3efa8ae4, 0x0599fdb5, 0x27cbca12, 0xa4e8fdf0, 0x5a24f2c1, - 0xde44d88e, 0x811cb47c, 0xd37034f9, 0x36cf5cc3, 0xe50f8a4b, 0xfe7ef473, - 0x7587f17f, 0xc8bbe389, 0x778eceae, 0x0f632e9a, 0x638205b7, 0xf175b9f1, - 0x0778c5fe, 0x918ef77e, 0xe3944f69, 0xf88ceb7b, 0x298ec56c, 0xb60f3173, - 0x13ebf04d, 0xa7a23a69, 0xb7d3dbf4, 0x29e823ea, 0xa173e8dd, 0x13ae9c3d, - 0x87f85ff9, 0xd227b471, 0x318c6db7, 0xa9d76abf, 0xd601adb0, 0x6d8e7111, - 0x9fee9ec2, 0xadcc8eef, 0xd27188fa, 0x34b1be4d, 0xa3fe7f5f, 0x87e5af98, - 0xc459b7cd, 0x6cf9d4c3, 0x67f76a77, 0x7f69fa33, 0xd487a136, 0xfee336f9, - 0x15d5f062, 0x75fe13e7, 0x69777cff, 0xf93367f7, 0xf5367f69, 0x7cea1b3b, - 0x3e6c3f2d, 0x76cfe0bb, 0x3d97def1, 0x64377f9e, 0x9a23f7a8, 0xbdccf3fb, - 0xed2f9466, 0xe850bc6a, 0xfa5173bb, 0x3be849ae, 0x6973f9f5, 0x3dff14b9, - 0x7326f877, 0xfa873d2c, 0x933b098d, 0x09933b09, 0xd9e1133b, 0x0d57a735, - 0xbbfc7a07, 0x95cf371d, 0xbecfaf41, 0x1cf8f4ff, 0xf1d9df80, 0xe832b98b, - 0x9eafd9a9, 0x1e0b337e, 0xfbdbfe29, 0xe9f4fc38, 0x5bb4073e, 0xadcccf82, - 0x18693805, 0xbaeacfd7, 0xb97779d5, 0x7cb95db9, 0x6f8f1e75, 0x3d459c82, - 0x67e39cd6, 0xcafc7f18, 0x1f349bd1, 0xeecf2ffa, 0x03105f4d, 0x7cb96a2f, - 0x1e7f2175, 0x9889c0ad, 0xaf48c6cf, 0xc7bea8dd, 0x8f7da752, 0x23692925, - 0x2c7187d9, 0x96394564, 0xfbd0f660, 0x7316d797, 0x533370bd, 0xe15fb81a, - 0x1c79102c, 0x4dcbdef4, 0x6b5c62e5, 0xfdb12fe5, 0x09e79d66, 0x79ff77f4, - 0x68e1bcd2, 0x7379ab3e, 0x3bde06a3, 0xde7dfedd, 0xb1fd9e4f, 0x64e56dc4, - 0x36998f1e, 0x7bdfc9ca, 0xa22b888b, 0x3e143c5d, 0xff73753f, 0x1e9f007e, - 0x0f54cf8e, 0x37b5a7c7, 0xff9c0d69, 0xf4de94f2, 0xc34f89c7, 0x0835f131, - 0xfbf851af, 0x7ea99b93, 0x88ed1ea0, 0xc55be12b, 0xd85f9aab, 0xc80b392c, - 0x9a19675e, 0x14c660fc, 0x1e7bac67, 0x3d48cfa4, 0x197bb46b, 0x3486a3da, - 0xeff98dc5, 0xc7d17fcd, 0x1573dbcc, 0x525ef88b, 0x367de53c, 0x1fc91927, - 0x93349fdf, 0xb659fc61, 0xd4bc234c, 0x3e51d526, 0xeb187ea6, 0x3a357f44, - 0x7c9f5d0f, 0xe909e53b, 0x4061e86d, 0xecc79fd9, 0xe95f2331, 0x5d92563f, - 0x99570048, 0x295f2e87, 0x26753d0f, 0x324f43cf, 0xd85e313a, 0x998c689e, - 0x9badfe87, 0x71fb5dfb, 0x1fb8697f, 0x886eff23, 0xe56c97d8, 0x9f58eef7, - 0xab46f500, 0x5dfc518f, 0x615bffec, 0x4dfda907, 0xf9433f56, 0x4e2a37a0, - 0xa9f45fb4, 0x77e07f5c, 0xe231dc5b, 0x0dbb5f28, 0xa3fdfcf4, 0x99cf5cac, - 0xfb3eddb9, 0x27dfb137, 0x44962b28, 0xdd3624bc, 0x3737450d, 0x9dde78ea, - 0x2d7397ca, 0x9c07ca46, 0xf7d3b16b, 0x2102e66c, 0xf446a4f6, 0xfe56eebf, - 0xd8acb53e, 0x7b7e9e91, 0xfe5f94ed, 0x00b5e196, 0x66a7db97, 0xc2bde818, - 0x28f31253, 0x5df383a9, 0xa994debd, 0xea1bccb8, 0x7645af4f, 0xc8c3182c, - 0xc1757a4e, 0x4e95ad43, 0x8aea8ff2, 0x737d9e91, 0x770fa2a6, 0x77d8c363, - 0x04f2ffb1, 0xfbd5cf2e, 0xfc09e5a5, 0x646bde7d, 0xffec6cdf, 0x4917c555, - 0x725f48d5, 0x2bae0e6f, 0x33dd3fa2, 0x5b9ff445, 0xcffa813c, 0xf5ddafe6, - 0xce3977d2, 0xc8f99da5, 0xec7ce8c7, 0xf429ecb1, 0xbde458b7, 0xe81f9086, - 0xa3d64577, 0xce22c5bf, 0x6e505a53, 0x4f218eeb, 0x3ec332d4, 0xa042e46e, - 0xb18c8cd7, 0xcff5aa54, 0xa175f47a, 0x90fce718, 0xec1fe738, 0x6ac3b4f7, - 0x3df80e27, 0x843cefe0, 0xe172f8f8, 0xb0f1f4a9, 0xbf6a07a5, 0x6ec7bf26, - 0x16ceffec, 0xb00371f9, 0x2db3bef6, 0xdf8c5bd0, 0x87886019, 0x8bf91189, - 0x25f6bf62, 0xefd0526b, 0x20f4b381, 0xbc0476dd, 0x030d6b23, 0xe42cbfcf, - 0xd2160b08, 0x2eb106f3, 0x0ceb5a47, 0x2c38bb8c, 0x6073ca3a, 0x6791aacc, - 0xa6536a73, 0xbb0ba1a6, 0x2716299c, 0xe45df7fa, 0xfbe06417, 0x7c9f180d, - 0xf78636e7, 0x9d69595f, 0xfd75da12, 0xc6f788f3, 0xe17b8957, 0xed2d5f3e, - 0xefd6c327, 0x5ff23197, 0x507382d3, 0xc33df56e, 0x92f19457, 0xc691ddb6, - 0x5dee1ff3, 0x02721f18, 0xed2d67bd, 0xb04f4fc2, 0x30f8700c, 0xa9719fa6, - 0x7282d5d9, 0x140957e6, 0xe7b7d677, 0xfbc820b3, 0x1bfbecb0, 0xf9c877c2, - 0x6c4f2e90, 0xb65b9e16, 0xb9ec9e28, 0x0675a976, 0xe8f731f9, 0xd178ac58, - 0xa7ee62ce, 0x2b628ffc, 0x4fb5cfbf, 0x1f63f4e4, 0xb8e1723f, 0x77ffe7ab, - 0x49f99e84, 0x7fde93b2, 0x4da3ed52, 0x8e47f843, 0x5f213a91, 0xf8115e84, - 0x199f3333, 0x792f45f9, 0xc774b079, 0x96bdaf6b, 0x5b53e8ce, 0x841b4748, - 0x138ea3fd, 0xc6a21f9f, 0xf243c578, 0xb87ab252, 0xedfab0be, 0x75af3841, - 0xce63e9df, 0xfba085ff, 0xd90fd935, 0xd3ad7fb1, 0xfa32c6e7, 0x9c96983d, - 0x3e78dd7b, 0xe9fb332d, 0x96baec95, 0x61dfce33, 0x28f0563e, 0x9fd837cf, - 0xefc3685d, 0x1b0e5941, 0xe265d364, 0x27d046f1, 0x19d8cbce, 0xdeaf9146, - 0x99e78072, 0xbaca58b6, 0xc5a1af30, 0x6a465692, 0x56f3c2d8, 0xcb16fed5, - 0x1607d221, 0x5adfdf85, 0xb8487f50, 0x0947c04c, 0xe110ebae, 0x5077ed43, - 0x128b5dc8, 0x5a5ef866, 0xfd4ad29c, 0x83d7b2cc, 0x34e6ca79, 0x6644f746, - 0xe217f02b, 0xccc75f35, 0xbec9f431, 0x5a4fae62, 0xaabaca4a, 0x7e327d69, - 0xd8b58eb9, 0xe7a4eccb, 0x7cf0ef11, 0xcf968673, 0x577813bf, 0xf91669c7, - 0x4eae77b4, 0xc38ed609, 0x1bf79338, 0xcb16e7a4, 0xf5107302, 0xcbf8e25a, - 0x391a678e, 0xd7fb78d4, 0x43bef18a, 0x2c4fae79, 0x0678e2b3, 0x8d15f7c6, - 0x9c62e1f7, 0x7bfbd5ff, 0x47bd2cc0, 0x581d304d, 0x7deb1ed8, 0x13f3feac, - 0xcfd1f2f7, 0xbc7960fd, 0x02871b56, 0x091eec79, 0x72565afb, 0xd53550e6, - 0x0bd3f8f0, 0xfd519fc2, 0xf6317492, 0xbf7f120b, 0x2bc5283f, 0xe10c5df4, - 0x69c7a4a7, 0x3ef030f1, 0x6f873f2d, 0xde1e781a, 0x7c4c6937, 0xd7cb4e87, - 0x38ff1cdf, 0x059f9345, 0x7131ec7c, 0xde23c63f, 0x3888f5a7, 0x6f18c21d, - 0x049d17a0, 0x89c7f7ff, 0xc33f9c1b, 0x4099acef, 0x5c60eb8e, 0xfa27e1c9, - 0x5dba3936, 0xe239efc8, 0x78d10ffb, 0x2e48c9fe, 0x7a47a5af, 0x51af785c, - 0x119bd69b, 0x7c5fdf8b, 0xee0642f8, 0xfd19c5e7, 0xdf743b79, 0xe769e2f4, - 0xcbc402e6, 0x6ffbed11, 0x474df8ea, 0x22f8a7ce, 0xe5c0a5fd, 0x3a4b2fdf, - 0xd92571b3, 0xddb80b8d, 0x7dfa7ff8, 0x73e617b3, 0xa497753b, 0x084fcf95, - 0xfc141cb9, 0xd320bb60, 0x2aee43f7, 0x3a40adf2, 0x0bac936a, 0x3ce72e50, - 0x9af2f3cc, 0xb3d55b1e, 0xb47f0628, 0xd5fdf28c, 0xbabf08c8, 0xe491bd7c, - 0x3725b35e, 0x28f772f9, 0x9fbb9f43, 0xde7a94e4, 0x79988f55, 0xdb8f8abe, - 0x7bbee9d1, 0x3a260f29, 0x7ea8653f, 0x449d23d5, 0x137f6a0f, 0xc5f28f8e, - 0x15c52372, 0x818fa1ce, 0xb72b3b71, 0x59d7a233, 0xc098c889, 0x7d0663f1, - 0x49607499, 0x106b8e1c, 0x6a0bdcfe, 0xcca1a45c, 0xde7889ec, 0xb9995b70, - 0x9a4e823a, 0x8e0fcf19, 0x2337ff1e, 0xac22fb55, 0xa80c63b1, 0x94c6317f, - 0x97ed9f26, 0xf278643b, 0x0395b4fc, 0x0ee3cc7c, 0xc5a3e743, 0x232dbe71, - 0xf30dac7b, 0x5e0ec0d2, 0x0460b0d3, 0xf64db7e2, 0x3c0368bd, 0xa2687ef4, - 0x0bdfea3c, 0x7c16ed3e, 0x05f9d43a, 0xd23001d9, 0x1d9c7b18, 0x80e297c4, - 0x2327c64e, 0xebe7345f, 0xf63142ea, 0xf3ec5c79, 0x7878f632, 0xc7b3f7e4, - 0x1afe890f, 0x6ded1c7b, 0x46fdd44f, 0xb6768c24, 0x7e3d8627, 0x05f11242, - 0xc2742791, 0x0dd5dce0, 0x39313978, 0x5697be99, 0x5defc090, 0x527fa04e, - 0xabc87e06, 0x7ed1f3a7, 0x7ff52d99, 0x43f84917, 0x47f0608c, 0x62f905fe, - 0xb6bff30e, 0xe23e2248, 0x1b7835f7, 0x73e57e9f, 0xd19236de, 0xf9c036ba, - 0xdb46fde1, 0x6233f9c5, 0x8ea467dd, 0x5037fd52, 0x13ef1165, 0x889d3c33, - 0xf741acfb, 0x72f75174, 0x9fd36d78, 0xdc1fac77, 0xed7286ff, 0x8b86d9bd, - 0x5a622e3c, 0x4b8f42c2, 0x6daa9798, 0x10cea9bf, 0xb9a82f7d, 0x6bd9bb4f, - 0x7d0f5e88, 0xd621d417, 0x1f71dd9b, 0xcd4fbfdd, 0xa644f9e6, 0x04e28c65, - 0xa66df7d1, 0x3d1e5db1, 0x8c0dcfda, 0x38e8fdec, 0x52a9e639, 0xb181b0fc, - 0x79e5122d, 0x7973df6b, 0xfe73fea6, 0x3ad6947d, 0x760ec79c, 0xd1d3da10, - 0xf7a849ef, 0x51f7ea5a, 0xdfab3c55, 0x4dbf4a8f, 0xc163eb47, 0xc6aed429, - 0xb87bf1fd, 0xf911e955, 0x7f582be4, 0x2b7f7a7f, 0x9bdf7b18, 0xcf29eadb, - 0x7fbc7320, 0xb29a186c, 0xc8784614, 0x6fc8c85a, 0xf2683c00, 0xdbd94c09, - 0x16e79f69, 0x224c3633, 0x33da683c, 0xfdd3d340, 0x7e6d42c0, 0x0353ec01, - 0x57abfb47, 0xd94d53f2, 0xf39597f9, 0x9a638a57, 0x94e4bdc4, 0x97fbe251, - 0xed14aca5, 0x9edbf4a2, 0x0738f3a1, 0x5f7181e7, 0xdd629c74, 0xf1826e3b, - 0x77fc8fd1, 0xe2cd2fc1, 0xaefd5b6e, 0xf4c8f30f, 0xce549b1e, 0xf30d2cd7, - 0x12e97bf2, 0x8a6e7c46, 0x8fcc6667, 0x1e4c2a97, 0x04c9bbc4, 0x32596c30, - 0xd4067332, 0x7b3c45eb, 0x8464c48d, 0xf3315599, 0x5dfaa3f8, 0x577d10a1, - 0xd479a868, 0x20b22bef, 0x679d4e7f, 0x2ef577d0, 0x7bf93cf3, 0x6be7e8d6, - 0xcea99e29, 0x87fe143f, 0xbfde8efa, 0x8137bcd5, 0x441d53c7, 0xf4038daf, - 0x417cf04a, 0xca3cf88f, 0x66d5bb85, 0xfa29577b, 0x4c1e670f, 0x114a3650, - 0xd2ce08fb, 0x7e03eff3, 0xd7faf1bf, 0xbc927761, 0x1897dfef, 0x8beefbef, - 0xdae422fe, 0x09597c3a, 0x191a5ef3, 0xfba431e5, 0x29973faa, 0xa0f600ff, - 0xdf111391, 0xd6f18049, 0x1fefce3d, 0x3e77e336, 0xc0e7fef0, 0x13edfe40, - 0xd1f76c16, 0xbcd43677, 0x5da3cc5c, 0x3ef0325b, 0x837df472, 0x89c611bd, - 0x99b26f98, 0x9f401305, 0x0531f4a4, 0xb9ecf3bf, 0x03a65468, 0xa07d6c7e, - 0x93bf0150, 0xa5ee8999, 0x337ead2a, 0x0ae10eff, 0xef676916, 0xefa56e97, - 0x64bf86bd, 0x3e14bf94, 0xc3ee88cf, 0x70c4c39f, 0xddf8ff2e, 0xcbe47afb, - 0x7a5d7da9, 0xfb93f3d4, 0xf67fa4fc, 0xed3d4fd9, 0x9962e7e2, 0x751f9111, - 0xcf545b1d, 0x979f8ae9, 0x5f27ea2c, 0xfdf86a30, 0x46a35eda, 0x5b17c81e, - 0x65fd46be, 0x67aa89ea, 0xe3e33fd3, 0x2dde28f9, 0x53edb5db, 0xdbd03e44, - 0xc35fdf2a, 0xbc73a1ae, 0xcf331698, 0xd5dce06e, 0x71e26e73, 0x79c7c674, - 0x9ff7946e, 0xff404d46, 0xe87147c0, 0xd82fc464, 0xdd952917, 0x58798ecc, - 0x8e994ce5, 0xf3b2bd72, 0xe487a41d, 0x3c0f3cb3, 0x5ffdfc7a, 0x7e8595be, - 0x9dc99ec3, 0xed2f6859, 0x3d15f2f9, 0xd3d5578e, 0x193eb0cb, 0x58a41e4a, - 0x10aa784c, 0xcf5033b4, 0xf59144e3, 0xe74a9eb4, 0xcfe4e565, 0x871a4e50, - 0xd933df6e, 0x87e4c2c2, 0x3da02675, 0xfe7c7cc7, 0x57cab364, 0x70972fec, - 0x9f81845e, 0x52ea54f6, 0x7b9f616a, 0x6c15919e, 0x46f3d3dc, 0xe7bfce02, - 0x7acd39ec, 0xf322fe98, 0x5afbac45, 0x2b53ee71, 0x7efec97b, 0xf92bac4a, - 0xa1c52f6c, 0x30de9553, 0xc3d4dbea, 0x37fefa7a, 0xc8bcf0b3, 0x38a14c61, - 0xfc5eba9a, 0xd73e2a6e, 0x88de7282, 0x5632b3fb, 0x287eec28, 0x55832a33, - 0xcc9a8f98, 0x6b484a76, 0x417d2b53, 0xa5e4e7a4, 0xad939e9c, 0xbf18c3fe, - 0xa3af5e4f, 0x59f24538, 0xcbf406df, 0x0565cb92, 0xf84ae4c9, 0xb7f310ec, - 0xf9d4f98a, 0xa88cf5d5, 0x7ee84bf4, 0x62e3b324, 0x132aaefe, 0xcc5abf8e, - 0x59eb14ef, 0x2c3be8c5, 0x55ad67c9, 0x83272fe8, 0x33df419d, 0x9a79e2b8, - 0xb745f335, 0x99d94f27, 0xb1e0e745, 0xe30ad91e, 0x365b64a5, 0xceb94154, - 0x32ff23a1, 0x3c5187a9, 0x9d27a93d, 0x4f527de4, 0x8a2728a1, 0x0f4269fa, - 0xd4933970, 0xaf2d50f3, 0xa4d2a16f, 0x3f8717ca, 0xda98fb8c, 0x717cb8cb, - 0x98be4978, 0x517cb8d2, 0x9556b8e9, 0x325acc2b, 0x0ff7ea1f, 0x06b5acff, - 0x73f77b9e, 0xbbe5fefe, 0xbcbe5cd9, 0xfbf725fb, 0xd3bf694d, 0x42aa5ca3, - 0x4dfa05c3, 0x33edc0bb, 0xbaab1f95, 0x48113625, 0xe7839a63, 0xc8ba1f87, - 0xd9843b9f, 0x63af00d5, 0x9529c912, 0xdd056b6e, 0x83eab3ae, 0x81fed849, - 0x3477de89, 0x98e5ce39, 0x83fe1ec1, 0x7c41f7ae, 0x33f7f8ef, 0x415def7a, - 0x437e82f5, 0x9a2e494b, 0xe4396c84, 0x3e416058, 0xae487984, 0xe918721e, - 0x3a080ebc, 0xe9af673e, 0x5b3fc308, 0x69fcdfcc, 0xc1ffd43e, 0x9340eb9e, - 0x1e973d4c, 0x885f2f41, 0xe82b3bf3, 0x7bdd29a6, 0xfc04c953, 0xcd1e62fe, - 0x0dfece7b, 0xdcb27fbd, 0xc69f1ff6, 0x3aa72efa, 0x4f7cfa8e, 0xcf19a568, - 0x1f9bd0f5, 0xabb4409f, 0x7b235fe3, 0x7ee3e4ef, 0xd0f89a33, 0x78cf3b12, - 0xadf3fc90, 0x8b7f9688, 0xc80f864a, 0x91667abf, 0xe7121e79, 0x1e4259eb, - 0xddb8554d, 0xe7e56f5e, 0x5fb25f55, 0x8b8afea6, 0xd2af55f6, 0x5ae4f28d, - 0xf29b7fe4, 0x7d4bd124, 0xbd97a73e, 0x0a0f9e82, 0x63ecce7c, 0xed97e89d, - 0x196e982f, 0xe23ef80b, 0x1cff13d2, 0x52c6bb19, 0x291dcf06, 0x024bf095, - 0xd6c97a6c, 0xcf00a9b5, 0xa7a22452, 0x1dad92fa, 0x967fd04d, 0x03a94135, - 0xb3f9e8f8, 0x0eaf3416, 0x9784bc05, 0xe3f872e9, 0x1b9e1754, 0xcaccd3c7, - 0x4ffe8cb0, 0x8cbf63bd, 0xc46df6fa, 0x2ee311ab, 0x7567c11e, 0x6a571f04, - 0x238fb82c, 0x2f2126a5, 0x5e51e33d, 0xd537cace, 0x7c75a18f, 0x1a4c6c7d, - 0x506f77be, 0xa73c95f8, 0x7e82c9ff, 0x6b27ccea, 0xccdfa053, 0xd7196692, - 0x912cd47b, 0xd7da3cfc, 0xc793f944, 0xd2ac393b, 0x74073d2d, 0x5b6fbc79, - 0x6fb61273, 0xd53e4897, 0xe21d2f2b, 0xa7d38fea, 0x0b0f7e3a, 0x3077e1b6, - 0xb7af29cf, 0xb1f53e60, 0xcccf05be, 0x7f1c3c01, 0xb8c43f53, 0xc0ad1f4d, - 0x244cdf71, 0x356d9e3a, 0x8cb1f469, 0x5e84694e, 0xd36f1ead, 0x0d4af5c0, - 0x29cfd3c5, 0x7806e592, 0xad5df3de, 0xd191397b, 0xbd77da52, 0xe14c7be8, - 0xa1cc797c, 0xd63cbe23, 0x8a9cb8f7, 0xfb4659f0, 0xde769991, 0xb21a92fa, - 0x5b29ceaf, 0x826744f5, 0x54f1d50f, 0x4f8a3e3a, 0x9ced1e23, 0x6df68fff, - 0x1dbd20b3, 0xe323bf75, 0x89675d39, 0xa1d0571a, 0x5df0dfaa, 0xda9fa471, - 0x7ef3fb51, 0x3851eb86, 0xd7946bfe, 0xd57d238f, 0xa7a2643b, 0x9afecaa3, - 0x27bf8614, 0xffecd262, 0x9ac91dfe, 0xda7597f1, 0x5db47034, 0xdbfdcfb5, - 0x0ec4cba7, 0xd847a466, 0x3ec2f947, 0xe0771fd2, 0x1768aefa, 0xf7e8eb29, - 0x45d90649, 0x8a2edcf9, 0xbe5487b6, 0xb889d66e, 0x65c78eac, 0x58dff9a3, - 0xf1eec3fa, 0x8e492ad8, 0xc65bbfbc, 0xbe9073ba, 0x8612a3e6, 0x75d01ef1, - 0x15fc23a7, 0x078b6deb, 0xccad7c39, 0xbfbf6976, 0x3f37bfca, 0x1e77d4be, - 0x367495e5, 0x6561df4c, 0x07e518ab, 0x9e786be8, 0xad665e11, 0x258bd488, - 0x8d2df1fd, 0xd84ba45d, 0xac78859b, 0xf1e46b38, 0x38e89e8f, 0x851fea97, - 0xae2bf225, 0x93ea2e52, 0xe67bb8f9, 0x7f6778f0, 0x938f3379, 0xe5fc0915, - 0x5d691a94, 0xdcf7808a, 0xb59efb16, 0x41fa54a4, 0x07dfa2f9, 0xef8029df, - 0x61e690af, 0xb1553d9e, 0xca5291d7, 0x9777b5e3, 0xa14af278, 0x15f12a2c, - 0x3d5e2296, 0x77d35f60, 0x9f643dc5, 0x33bce3a9, 0xfd16e3ca, 0xbcc96146, - 0xee8f0edc, 0x6863ed07, 0xe3d8869c, 0x7a38fb40, 0xf6ec6e7e, 0xfc39b843, - 0x30fb237d, 0x0c0643d2, 0x52f2a664, 0x16e5e32a, 0x8846aefa, 0x1e0de7fb, - 0x9146f3d2, 0x103788af, 0xf4c7fc91, 0x1cbe34f5, 0x58f7419e, 0x8325d82d, - 0x7691f9fb, 0x6a84ac94, 0x6aade322, 0xdf94a8b9, 0x1528ce73, 0x604cf3ef, - 0xa8afc813, 0xea3cfcbc, 0xc3cd43f3, 0xc85765ec, 0x63f35e7b, 0xc3fa49d3, - 0xa55f27e4, 0x4a0e607d, 0x1f39df91, 0x4a89bf6a, 0xc28a1c94, 0x5cf350d3, - 0x22dc79ed, 0xd76af6e8, 0xcc7a655d, 0x2ed1f94e, 0x056b07ce, 0xd5dbf57d, - 0xbe3f1e3f, 0xfe861f3f, 0xfefbd9ca, 0x4a7ef893, 0x37a56842, 0x145e7ec6, - 0xe531f9fb, 0xce70d3c1, 0xfba18c1b, 0x0799ded1, 0xd20263a7, 0xf1f2c77b, - 0x9eb005f0, 0x2dfcc537, 0x6feb9596, 0x1c5b4785, 0x1ef998ba, 0x7a78fe6f, - 0xd93f0da2, 0xdce395ff, 0xa7206dfb, 0xd07d1e5b, 0x7581b0ac, 0x15d96b30, - 0xe347f9ce, 0x6d5d7513, 0x625e305b, 0xf7aabd4d, 0xaf5c5a14, 0x697de024, - 0x764de7ed, 0xb4460efc, 0x43c6a03d, 0xc6a5bd54, 0xa4bb544d, 0x1fe3c1c2, - 0x7bfced33, 0x69f6153d, 0xb20fdfa4, 0xaff21aae, 0x226d3b30, 0x19fd0ab1, - 0xe4fb5add, 0x4657bf3a, 0x9eda2a3b, 0x45334da8, 0x7abd07d9, 0x1715df94, - 0xfe54fdb5, 0xc454acf8, 0x17795451, 0xcf9a4765, 0xbb40499f, 0x670bedeb, - 0x8d142e28, 0x5c2eeb9f, 0xaebd9fde, 0x83f74f5d, 0xb7ad71d1, 0xfdd2e42f, - 0x1baf11a0, 0xcccad4c1, 0x808cc43f, 0x6b7b4c97, 0x18ec1195, 0xf82983a3, - 0x58fc36dd, 0x8d0dc633, 0x7c9c7817, 0xd7fb9d84, 0x2fc18b89, 0x95335185, - 0x78c17da0, 0xef48ce7c, 0xef5d99d3, 0x09bdbd91, 0x9e2186ea, 0xa6199ec7, - 0x5307118b, 0xc08a63cf, 0xb7e66eef, 0x4d81efe3, 0xf7f78bb1, 0x59db462e, - 0xa22d3cfc, 0x2d62e27f, 0x3ce22d3e, 0x435b8327, 0xd3ec79df, 0xe7116f3e, - 0xfb1a596b, 0x63a3ec1c, 0x7aa2439f, 0xc5b6130e, 0x596c39e1, 0x758a4dbc, - 0x2f8b990e, 0x845b0e7f, 0xefd2a95f, 0xb204acb4, 0xe8a6f7af, 0x7b41fbe8, - 0xcb59c313, 0xb2fdfe31, 0xaccfde99, 0xb4367110, 0x6b9f10a4, 0x84bf97b7, - 0xa371db71, 0x7b8e74f5, 0xbcffd125, 0x60feff8e, 0x1fea78cf, 0xf883b327, - 0xfb0780bb, 0x1bbbe9aa, 0xd3bbfcd1, 0x33dd007a, 0x3db9ceb6, 0x839c016b, - 0x9980fb25, 0xcf839bfb, 0x4a3fef07, 0x7b4bbe05, 0xa654b9f8, 0xbda3d49d, - 0xec66f25e, 0x8fe351f3, 0x3a9da47b, 0xaa362b20, 0x98fc8baf, 0xeca33b91, - 0x642db3e9, 0x47c65b67, 0x39c0f7d5, 0x9f8ebdd1, 0xa1d916ec, 0x87ebaf3d, - 0x114aa738, 0x7d7f3087, 0xfb65e28a, 0x7e714efa, 0x25c6d1e9, 0xfe5df727, - 0xe7135e9c, 0xa1c453b4, 0x00e22e7e, 0x7e7fc29d, 0xf2a4e023, 0xea9b80cd, - 0x04280adf, 0x0b940aef, 0x77cfc161, 0x47cb3e56, 0x84aaaf17, 0xcf47edfb, - 0x7f7dbf73, 0xbe83a862, 0x42de74ef, 0xbda417df, 0xdbbf144d, 0x2c727c07, - 0x1fbf49ce, 0x4cdb3478, 0xa5a3b3f1, 0x8a7bfbbf, 0xd16b7cbb, 0xc70bb8f1, - 0xeb4e7ab3, 0x6f184e70, 0xee8b855d, 0x47e036a5, 0xeeffa114, 0xffbe8932, - 0x040e1b34, 0x3a5445ef, 0xf169f537, 0x65ff0f59, 0x1ddff195, 0x617f42c8, - 0xa4e88b8c, 0x2273ef42, 0x4fba373e, 0x571e5f91, 0x871beed8, 0x7af18071, - 0x14fbbe26, 0x3bac4534, 0xe0426f0e, 0x44895379, 0x0a1a73df, 0x86e5d1bf, - 0xa32fae54, 0x3475ffeb, 0xdd1b83d7, 0x773ce8db, 0x50b2ba3b, 0xf913efaf, - 0x2964b310, 0x285fbf48, 0x1cb1dd77, 0x65915bf6, 0xc011bb1f, 0x6853a32d, - 0x4f4afbfd, 0xd8f81c53, 0x21c65785, 0x76b31dfd, 0x79ce305a, 0x53dfc9cc, - 0xf9951387, 0xf29db77b, 0xa4f2312d, 0xe958f2d5, 0x95fdfa22, 0xef7cfc7f, - 0xdf7cd1da, 0x0af5524c, 0xfb815b8c, 0xdef9424d, 0xc3f902b2, 0xfc83b998, - 0xaa73e8cc, 0x88b35f70, 0xfc64f3de, 0xb6bf4f7b, 0x3f782c86, 0x0267ed1c, - 0xff426c7d, 0x3d04f778, 0x5eadaf7d, 0xe782e7e6, 0x1fa4e788, 0x997e13a3, - 0x65667c76, 0xc0fa633e, 0xde1d6079, 0xf13ad0d7, 0xadefaa3e, 0xf86292bf, - 0xc9d683b5, 0xf9589efc, 0xcdcfd1b0, 0x9a20b276, 0x1615b386, 0x709fa176, - 0x99c69f30, 0xcce3e56d, 0x9b7c7112, 0x1759ffa0, 0x81df9475, 0xcf80d6f4, - 0x7927cc95, 0x50f5cc72, 0xb7ac1d57, 0x41c6ce1e, 0x569346fe, 0x5b39090e, - 0xf745525f, 0x07dcc7bd, 0xbfbea3c6, 0xe1e574be, 0x9fc22732, 0xb74154d4, - 0xd52fa529, 0x945a5d20, 0x4c2f8a2e, 0x5d74cb76, 0x36b97d78, 0x17afd14e, - 0xb44bf4a3, 0x928fa8be, 0x54f7113b, 0xf9c4434e, 0x4b9f72cf, 0xab83a488, - 0x2f1ccbc7, 0xd67baf7e, 0x1da71e05, 0xe9f7978c, 0x7803a573, 0xd8ef3e89, - 0xa73e8978, 0xeaad3c01, 0x8c1dcbaa, 0xbf6f155f, 0x1ac9792e, 0x8d1be799, - 0xaf8a1fb7, 0x4156d1e6, 0x579e5caf, 0x3b7dbe08, 0xb771443b, 0xeff94bb7, - 0xff731d4b, 0xb3bfe296, 0x0d63a858, 0xcbe045ca, 0xe8f94239, 0x344ce423, - 0xf4f8061e, 0xbf2e283f, 0x28b7f3fb, 0x21caaa2e, 0xea25f213, 0xea1fc113, - 0x1f9099b9, 0xf02f6f91, 0x2d5e87ef, 0x457ca87f, 0x383f21eb, 0x1fcc8fa4, - 0x5fc5dffc, 0x18cd717b, 0x52167617, 0xd1cab83c, 0xac7bc7a5, 0x3dd250c9, - 0xd27f8892, 0xf5919c3a, 0x591c6e3c, 0xa12f714f, 0xa6b8d4f7, 0xbb3ebeda, - 0x5518412b, 0xc24d47a4, 0xc4fd51de, 0x64538e7d, 0x54faaa7f, 0x57fef716, - 0x08f74fab, 0xfb543a7d, 0x79bb73de, 0x43cbe7dc, 0x1c800f3d, 0xa46f9c9f, - 0x0e4cb8ef, 0xa3dfcc3f, 0xfe498470, 0x9137746f, 0x69fb0c1f, 0xe604a346, - 0xf3e64475, 0xf3bee5a9, 0xefd60a6d, 0x0af4bb95, 0x16ff07f5, 0x568603e0, - 0x0d869dfa, 0x137d738f, 0xd651f457, 0xba83dee5, 0xe6994fb3, 0x61efc24a, - 0xdf835f6f, 0x8c2a0b01, 0xb598ebbe, 0xee458bb4, 0xdc31a5f7, 0xff9c9daf, - 0x68071dd6, 0x69ea1fdd, 0x035768dd, 0x9d964f9d, 0xcfe7050e, 0xfd23dbf6, - 0xf7d97dec, 0xb7009dda, 0x086c697c, 0xa3c37ad1, 0xecf3017e, 0x078d5733, - 0x73ed8d4b, 0x0bf5181f, 0x7346c7c0, 0xa3cc04d5, 0xdbdfb6ac, 0xdae51f3e, - 0x60265bd9, 0xbcec1bfc, 0x83b7d456, 0xcdb7dff6, 0x5d3bbf8c, 0xd69f78ed, - 0xabafa231, 0x5abfbf06, 0x48f7e0ed, 0x87bed1be, 0x7b404cc6, 0x73c1ec39, - 0x0c9f344f, 0x164cdd22, 0x2f1765eb, 0xbd41fc51, 0x9e73d997, 0xf8ff47d3, - 0x8fb80f40, 0x455cbf6b, 0x7db922f7, 0xa026f9ba, 0x3c7d75d5, 0xf1db0c7f, - 0xbf58e07b, 0x001d8628, 0x4be75cf3, 0xcaebf3c6, 0xde8637ba, 0x36fbedcd, - 0xf6e783e0, 0x44bc7064, 0xc31e6fb7, 0xafb882ed, 0x9272cfde, 0x7ff5c03d, - 0xf312c0b0, 0xa9b7553b, 0x3b1ad2fa, 0x552d450f, 0x23daa579, 0x21b35f80, - 0xc69bbf02, 0x7cfdff70, 0xf103a7a9, 0x7fe77df7, 0xe50b710a, 0xf6cf52f1, - 0xae91c331, 0x97ad5f04, 0xee01c663, 0xc5a3f31c, 0x13416e2b, 0x73beabef, - 0x86e96fe9, 0x7441dba6, 0xf8e95065, 0xffe3a221, 0xe27bf48b, 0x20efd0fb, - 0x14fe7479, 0xd347c3dd, 0x03bf4ab1, 0x9be6c874, 0x79e80692, 0x7ec1ba28, - 0xe806928b, 0xfb7ea87a, 0x931fbfce, 0xe9c607de, 0xabdd2cbd, 0xd059b7f4, - 0x540f7a91, 0xfd79ce29, 0xfeec8cd7, 0xf5463da3, 0x7e35c677, 0xca3fe811, - 0x72b0aea3, 0x37b47fb9, 0x3d19fb97, 0x9a9fba66, 0xbe295ee9, 0x235d0dbb, - 0xf211adc6, 0x75dba67e, 0xeaaf3959, 0xfddf550b, 0x43777c4f, 0x00800098, - 0x00000000, 0x00088b1f, 0x00000000, 0x7dedff00, 0xc754740b, 0xeebd6095, - 0x91a93fd7, 0x16883e9e, 0xc085a092, 0xeb404616, 0x7d3d05ff, 0xa71f3210, - 0x900b18c1, 0x04e08b4c, 0x60dd491b, 0x9e3d90e2, 0x123231a1, 0x1f62cd9f, - 0xbd6678cc, 0x8c030d39, 0xc077b19d, 0x0b611c56, 0x3837e2dc, 0x71c6ec4b, - 0x3c4c9c18, 0x6c0843c2, 0xc718d36c, 0xbc4ab243, 0x0f7adef7, 0x0b756bf5, - 0xcceb43db, 0x40e75764, 0xaabd5ea9, 0xfeeb75ba, 0x7ad3d56f, 0xcecc6333, - 0x53f817d8, 0x08acbc3d, 0x65cb191a, 0xfc05f3f4, 0xebf2e2db, 0xdf632b25, - 0xb4cbeeb9, 0x2c93f943, 0x1e670adf, 0x355faf63, 0xb188acca, 0xf6e3a9ae, - 0xfa87b3ea, 0x8c08758f, 0x127b4315, 0xef768674, 0x0077c154, 0x27d1311e, - 0x7d1e9d2e, 0xfd4c9fde, 0x8795cdae, 0x9d32fab3, 0xaf7a6863, 0x59b18d3e, - 0xca0e9bf8, 0x332d9320, 0x5aedcca0, 0xcca012c7, 0x9636f92c, 0xb12e624c, - 0xf2933184, 0x6bcae99e, 0x39f015df, 0xfe831993, 0x56f595eb, 0x0d5d7f30, - 0xcccf31c0, 0x3889f1bc, 0xc9c9d37a, 0x97cd5ed0, 0xd769e30a, 0xfe9fde1d, - 0xe4f329a5, 0x572e3630, 0xfbcdf5a0, 0xf04cf98c, 0xeb6e756b, 0xe7033602, - 0xd1cc7187, 0x1e60a9c7, 0x1d01e999, 0x2adb5ee5, 0xaa6b3fe8, 0xafe5e1c9, - 0x6cdef84b, 0x3e1bdfc6, 0x4ac67ace, 0xe2d9c686, 0x54fac809, 0x4c498ec6, - 0x6f5b2fe9, 0xf8e767c1, 0xb2857ac3, 0xcd6e533e, 0xebcbc455, 0x07e1c792, - 0x860f6778, 0xcb1d6f8d, 0x55633a58, 0x8b9f699f, 0x387d6d0e, 0x58fb305c, - 0x5f4fe5fa, 0x33467cc0, 0x5d398fc7, 0x5d79f847, 0x3e90fa32, 0xeed4ae2a, - 0x4b189362, 0xfc87ec96, 0x992adcf0, 0x36053e1d, 0x7e53f633, 0x0402b8af, - 0xc29fed04, 0x738014bf, 0x5aef6e9b, 0x16ddd027, 0xa21f4c6c, 0x4c0b2597, - 0x2e96381a, 0x9bd4d449, 0xea69c79a, 0xd44f57cb, 0xdb736fec, 0x43fa9add, - 0xea6a661b, 0x354a27ae, 0xd59d55f5, 0xef56f19a, 0xff69ab9c, 0x686feed6, - 0x7f9e6bea, 0x747f5350, 0xe911caff, 0x885f1a22, 0x89e991b6, 0xd23b0579, - 0x3a4d88bf, 0x9cc5cffc, 0xf7f7a3d3, 0x7ec27f21, 0xb7af6ebd, 0xd5fe82ad, - 0xe78d3f57, 0xc5f4b4fd, 0xf90072bc, 0x17d956a3, 0x402bc798, 0xad528d7b, - 0xf445be95, 0x4536635e, 0xee951be4, 0x11560ab6, 0xda66afc7, 0x6db0aafd, - 0x7e47aebd, 0xebd01a2e, 0x3759be61, 0x2157fcb5, 0xc706fc35, 0xc7afcc67, - 0xa5cb84f5, 0x9318eeff, 0x609e397a, 0xfc017fb5, 0x8cc9acc4, 0xa3c74795, - 0x5db7a74a, 0x6f5f6337, 0xeafccadd, 0xa0582b7a, 0xda3ee90e, 0xfc3b67ba, - 0x516b927a, 0x5ebe1dd6, 0x6feffe15, 0xef815f86, 0xf323ff5f, 0xdb1013ed, - 0xe6fc88b2, 0xcfeb5ddf, 0x02402bb5, 0x7a1527bc, 0x278291a8, 0x0e908b12, - 0x83650398, 0x51f99071, 0xc133d40e, 0x9652846f, 0x38af041c, 0x3034ef68, - 0x7e71eb2a, 0xa6861071, 0x35eb45d2, 0x288dca0e, 0xa92c456f, 0xebc79cee, - 0x875e068e, 0xd52ea8f7, 0x3ee7baf2, 0xea92875e, 0x43af275e, 0x5aefaa3f, - 0xb8cef58c, 0x014489c0, 0x5825beeb, 0x5a1e0e37, 0x05ff4bca, 0xe4994a81, - 0x5de83896, 0xec7ea7a7, 0x3707af22, 0xf2d0fa71, 0xf65e3183, 0x5f19b3f9, - 0x813f3c3d, 0xfdc24dbf, 0x006fd75c, 0x828ad43c, 0xd5ef0ec3, 0x3f87320c, - 0xe4d5f715, 0xe097d990, 0x3133a033, 0x8ccf886d, 0x4ab1982c, 0x0f793e20, - 0xedcaadf1, 0xe968e3e1, 0x5af51eab, 0xfc3bec01, 0xe51931be, 0xfaa7a730, - 0x2c12e0b2, 0xd013f9f1, 0xfc327b3e, 0x1f4e1e4b, 0x32a25c2a, 0x5fb5a55f, - 0x32b6aa8f, 0x59b72618, 0x8559d117, 0xd92c9d79, 0x716dcb87, 0x2e2fe550, - 0x56e1c22f, 0x1f39ade5, 0xfb1a6cf8, 0xb9967c3a, 0xaeb36a0a, 0xd9f0abbe, - 0x933e30ba, 0x8496f7ad, 0x321019f0, 0xb7d9f0d3, 0x276e9e89, 0x83094e5f, - 0x4f182675, 0x23e80cf6, 0xc05499ca, 0x3e244243, 0xb21bfb9b, 0x97c8a21f, - 0x5817f037, 0x987e6e67, 0x5cf4519c, 0xfee7aab5, 0xdda2b3a8, 0x117a67e2, - 0xc87c70cb, 0xd2313b2c, 0xbe3cb573, 0x6bba0609, 0x90f80ea8, 0x63be810f, - 0x06dc151f, 0xcec99bcf, 0x805ab862, 0x31e2aac7, 0x71ad6e8c, 0xec909d2f, - 0xecf505bc, 0x4e6e8518, 0xdf11a766, 0xc7bd76c3, 0xb59de442, 0x01f1cbe8, - 0xc70937cd, 0xbf226673, 0xc6db40d5, 0x33fde182, 0x99f00fb1, 0x3e7cc835, - 0x08eacf78, 0x46af5808, 0xf48d9efd, 0xfe51eacf, 0xe8095f57, 0xe5a5ea25, - 0x00745b97, 0xa4013fbf, 0x517c8b57, 0x642e9c30, 0x7ee3d3e6, 0xaffdd57c, - 0x90341fb6, 0xffdb0ebc, 0xcfb0419a, 0xd5394e00, 0x1afa20e4, 0xc8cf6464, - 0x48c7c14e, 0xbc21acbe, 0xade3f6a8, 0x176826f6, 0x622e91e8, 0xf640b37b, - 0xb36ca7d0, 0xf305f381, 0x867a55fa, 0x30afcbe7, 0x34ed1139, 0x7ed4f3cb, - 0xfa23136c, 0x3c97b6a8, 0xb8476755, 0x44cc7606, 0x0abd24b8, 0xc7153f97, - 0x70e260bd, 0x7f08daf9, 0xe4fe0ad5, 0x43331d41, 0x694fbfbb, 0xff5fa30f, - 0xfcd3b720, 0x702bc44f, 0x43f0c8dd, 0x4ed007bf, 0xe5689306, 0x43ff03dd, - 0x69dcf784, 0x01df3f77, 0xf028ae5d, 0x6e856ffc, 0x5124da3f, 0xf5cd3eb9, - 0xc7a07cfd, 0x7c6e917f, 0x0fc866e2, 0xd5f74439, 0x9027cff6, 0xd9f1521e, - 0x10f48637, 0xe8f84dc2, 0xdb8344b3, 0x387510aa, 0xe5bf0abc, 0x2a57c88c, - 0x577c2a9c, 0x0bab7a7c, 0xe7b37bc6, 0xf61c135f, 0x454bf821, 0xfb847ee7, - 0x674fc1cd, 0x92ef88b8, 0x34667635, 0xfc5266f9, 0x964ca488, 0x3ea2a62b, - 0x85cc7388, 0x74cb8c75, 0x364cbad1, 0x02fd1da3, 0xf393274b, 0x82734860, - 0xf7f08ccf, 0xd2ec37a7, 0xa9d6fb43, 0xfbc13322, 0x36bcb35b, 0x09fea75a, - 0x9399eb86, 0xd60361e9, 0x6577f3e8, 0x9c11293e, 0xbf475083, 0xa2f1c6c7, - 0xf8f4689f, 0xc75fb9e0, 0xc10a1cd6, 0xee02c1cb, 0xe7cd9d8f, 0x1e17dae5, - 0x842976d9, 0xad0fda3f, 0xbdddd4d3, 0x2976dbdf, 0x106ede54, 0x3697dc44, - 0xd9db8e85, 0x5ff404c0, 0xe13b455a, 0x903743a1, 0x2c6bf586, 0xae0a7e78, - 0x008fe70f, 0x5be73fff, 0xd2ff3d62, 0x8ff650a9, 0xff69fee1, 0x0df91f24, - 0x2b1ffcea, 0x5f38ffeb, 0xa6387317, 0xb3ba1e01, 0x9f70c5bf, 0x3f7c6c6a, - 0x7a72504d, 0xf54372e6, 0x739e8677, 0x3ea55179, 0x73de3a0f, 0x1ce91d12, - 0x994c76a8, 0x7de911f6, 0x71bbd227, 0x48b5bea8, 0xf08be8d7, 0x220573fe, - 0x16c07bc1, 0xa15b3db9, 0x5c139d97, 0xdfe8d9dd, 0x6c73ab3f, 0xcbce2586, - 0xe51e3adc, 0x7adb56fd, 0xe2e653a2, 0x38c058eb, 0xf4cbcebf, 0xd1e81978, - 0x82b7fe79, 0x8dd62a42, 0xf886c2cc, 0xe70bf557, 0x01d13e89, 0xd7f2bbfd, - 0x5ddd7199, 0x1c66f5b6, 0x82d684cf, 0xea3c386e, 0xe6ec0fba, 0xf4cbcef3, - 0xb2e9e089, 0xc57bb9b9, 0xa33fa801, 0xee5e7bac, 0x6aaf6a3a, 0x09149ff4, - 0x4367e07f, 0xf568e8dd, 0x87263ce2, 0x3ac246bd, 0xb2c66c73, 0xec89784f, - 0x0dbf5513, 0x9dad4fe9, 0x91bafa72, 0x15d763e4, 0xf244cf9d, 0x07305e53, - 0xbcaf9fde, 0x7b720d6d, 0xa3bf6bbe, 0x1cf7c45f, 0xf3e3f902, 0x764dbf73, - 0x2e77359d, 0x56b3e7b7, 0x98549179, 0x3fa1f04f, 0x5bc54f31, 0x195f569e, - 0xa0b7171d, 0xd4de30fa, 0x2c59d1ea, 0x2abe90c0, 0x70f3fcc2, 0x40bb3b7d, - 0x5972d7b1, 0x2d2bda31, 0xc863df26, 0x420d960f, 0xe2a1c23a, 0x8e814575, - 0x7c8620e8, 0x942667b0, 0xb465d95d, 0xd3ccfaaf, 0x5f980417, 0x4366df17, - 0x8cdbd0be, 0xb31bc47e, 0xa80d1f8a, 0xffc24df3, 0xb7b22533, 0x2f848eb0, - 0xfc79397d, 0x86c7966e, 0xb032eceb, 0xa7f248a6, 0xfdf380b6, 0x927e5907, - 0x8ddad10f, 0x7bd2041b, 0x66377caa, 0xc237d932, 0x5c8cdb78, 0xd25f80ce, - 0x3ebf402b, 0xffa017a4, 0xf7b35a17, 0x7ba205e9, 0xadf1e519, 0x12efb152, - 0xfe1fb90b, 0xca898166, 0x547eca93, 0xc336717f, 0xaffc8235, 0x8430f2aa, - 0xc7ca94df, 0xf1f26533, 0x732f224c, 0x2e3f7195, 0x5cdc7ce2, 0x5fb97b14, - 0xfb7a339a, 0x8d7a4b1c, 0x90285287, 0x98dd79e8, 0xc52e4987, 0xa3396f12, - 0x5da33788, 0xa7073fa1, 0x73fdb513, 0xaaffde45, 0xb274e620, 0xe51472b4, - 0xa4e92c41, 0xde83cfe2, 0x79ff97cf, 0x68da47ec, 0x99a3e3ae, 0xe042d4f2, - 0x2e9cbf93, 0x96e583df, 0xbbdb23d7, 0x772f63f3, 0x72801ed3, 0x37df04f1, - 0x79b3e923, 0xfb97b185, 0x48bed14b, 0xf845f6e1, 0x3d15cbfc, 0xd2794b14, - 0x11b36504, 0xff011fd6, 0xfcc28e8f, 0xef5073cb, 0xe5817b72, 0x0fa4b99e, - 0x67e1dfb1, 0x3ec42eb2, 0x1c147b06, 0x0543b441, 0xeddd9239, 0x2d7efd8d, - 0x643f487d, 0x5c61ccaf, 0x2ff3a81f, 0x7af8e12c, 0xb0e0147a, 0x25eade00, - 0xc29baf6e, 0xbfcb50e0, 0x7dbd8c2d, 0xe043e92a, 0x1fbb0548, 0x444205cb, - 0xd0a7af7b, 0x1a7e7318, 0xe2d9780b, 0xe4918d60, 0xefd8c9c9, 0xca0d9a4b, - 0xd3cee9aa, 0x4b96d728, 0x5c60e787, 0x1ff8fbf9, 0x79d21be6, 0xc1a561be, - 0xaeff45e5, 0xbc3bb24b, 0xac478c76, 0x7ccafaa2, 0x52af43bb, 0x94dfb63e, - 0x6c05db7c, 0xe57d51d7, 0xda1f24ef, 0xd617dfc3, 0xf1c6c99d, 0xfb1deb36, - 0x959dc618, 0xe78d837c, 0x9e36ac1b, 0x3c6d109f, 0x29b560ef, 0xcf1b0779, - 0x4a6d583b, 0xf3c6c1de, 0x929b560e, 0xbcf1b077, 0xe4a6d583, 0xef3c6c1d, - 0x7929b560, 0x3bcf1b07, 0xde6a6d58, 0x1538d3c1, 0x9e3691e3, 0x78dab077, - 0xe36ac1de, 0x97980779, 0x3c6c1de7, 0xf17000ef, 0x722d83bc, 0x943ac1de, - 0xf1ff2077, 0x67a49618, 0x547f5fb8, 0x7b06cfa9, 0x786334dd, 0xe76ab55e, - 0x17182dfe, 0xfc7209ab, 0x5e783955, 0x77b414d9, 0x457e300a, 0x04dfb066, - 0x114565fe, 0xb0d5f0c3, 0x13f3c3f9, 0xbde7d9dd, 0xb0a3fa02, 0x03bc2997, - 0x18ea29e5, 0xfe7c3f7f, 0x3b577161, 0x65d6e78f, 0x3bf08b7e, 0x78482cbb, - 0x8718e7c3, 0x13f253ad, 0xffad56b5, 0xb2e67f2a, 0x995f71f9, 0xf80899d4, - 0xbb6d4590, 0x8c2ff988, 0xd7f15ebb, 0x6ab7dc61, 0x15771b50, 0xb8d41b33, - 0x844bcf3c, 0xe1df39c1, 0x6b045f1c, 0x2a7f016a, 0xc1cfe601, 0x53ae15a4, - 0xa45e7c12, 0x881bddb7, 0x453bbcbe, 0xaa6814c7, 0x9e606404, 0x6a2012a5, - 0xc654d286, 0xf24cd2ac, 0xfe9d389b, 0xf1bdd4d7, 0x030f28d9, 0x6c04467a, - 0xf9a83c23, 0xbf580485, 0x2bfc8334, 0x332aeff2, 0x3a47bffd, 0xcc82eb50, - 0x5d8238f3, 0x2f80cd62, 0x5c266ef9, 0xceab9336, 0x45eb6f90, 0x73c335e6, - 0x9b37e941, 0x2d4e2905, 0x76f28933, 0x6541ccb5, 0x695774d1, 0xcea3f011, - 0x7ae175ec, 0x0966ecaa, 0xee3d85f9, 0xf148db3c, 0x32e97ae4, 0xf60049e0, - 0x48da62f8, 0x2ec88a76, 0x451cf8ab, 0x2f1f48bb, 0xadc92278, 0x61ebd88a, - 0x0a2a83b2, 0x2dc7c919, 0x7cfcb22c, 0xcfcb84ac, 0xdf5d4b37, 0xfbd73c44, - 0x878fd516, 0xd0be8f2e, 0x6d9b794a, 0x5bc2f161, 0x6f628afd, 0x90e72447, - 0xe901b93d, 0x8f04f17a, 0x1688e10d, 0xf62a78c7, 0x1b49ecf0, 0x767baec1, - 0xd45aec14, 0x2aecb743, 0xfa9399fb, 0xb1ca3b50, 0xd0ba4f0e, 0x9092baef, - 0xc3ddaa38, 0x8d67143c, 0x6979af1c, 0x9920e214, 0xfe13bfa8, 0xea639d0b, - 0x87fb023a, 0x54bcfbe5, 0x428ef8e1, 0x634be387, 0xa0d317cf, 0x613e27d4, - 0x771b8d0b, 0x970e0459, 0xf5c0d041, 0xfdff62b9, 0x78f624a0, 0x7d72812a, - 0xf22efca9, 0xf974d561, 0x7caa5867, 0xbae1df3b, 0x2d29fc40, 0xf9024faa, - 0x767f66bc, 0x0689ea01, 0x2ae35edb, 0x52d5f780, 0x3a22fdf9, 0x5b1ff46f, - 0x1eb16e1e, 0xf7bc478f, 0xa3cb22b9, 0xc50911bb, 0x28de4fe4, 0x67e4fee2, - 0xfe288784, 0x638bafe4, 0xea7b2fbe, 0xc9fc8673, 0x5b1ffe70, 0x639de3cc, - 0x068e0147, 0xf1465728, 0xc28ca6eb, 0xbf5a8dfc, 0x443ebf6e, 0x854110ce, - 0xdc6c69e6, 0xfc1163af, 0xba35973d, 0x147b37bf, 0xf310b1d6, 0xf591b571, - 0x31c57dda, 0x7e96aff7, 0x3307ca03, 0xd0a9fd5b, 0x6f30bcc4, 0xb2be50da, - 0x0fafd5c9, 0x383f738d, 0xe537e0e1, 0xb37e7008, 0xf272e638, 0xf91e9c7c, - 0xe119bd75, 0x7e066ae9, 0x255fb08d, 0x9bffdc25, 0x9611e13b, 0x3a637688, - 0xe411f743, 0x3637cf09, 0x83637e29, 0x2a767fa2, 0x2c53d472, 0xe52ce952, - 0xe851b9f5, 0xfbcad7fa, 0xb69c4a8d, 0x2bf26251, 0xec7ff491, 0x38fce6e9, - 0x71c6e728, 0xf30def38, 0xf453dfcf, 0xd3d89ec4, 0xa00c9ecf, 0x91b5b993, - 0xf63075f1, 0x0274b174, 0xf6d4bfcc, 0xf8901cf4, 0x0d9b2fb0, 0x2e9c5f94, - 0xef0c58bf, 0x57c28b6d, 0x69782b9f, 0xb03a3e86, 0x34a05bfb, 0x9010f942, - 0xfa405481, 0x6fec55ed, 0x14308e01, 0xf1de0420, 0x3af4e7e8, 0xce7c1ee4, - 0x7fe46d5c, 0xca1bc884, 0x3999569f, 0x83a774df, 0x0efe88ff, 0x9339d333, - 0x9fcf20ae, 0xfcf26576, 0x6a3c3868, 0x456ff4fe, 0x71cf198f, 0xc4166577, - 0xebddf285, 0x6f26989b, 0xe78575dc, 0x8a4fc185, 0xc949fad3, 0x8f8527e4, - 0x74b9909f, 0x247fa85e, 0x021fdcc8, 0x5c50267f, 0xa917e43c, 0x7c98cffe, - 0x7ff15cf9, 0xcd1dfd02, 0x4947119f, 0x07308b0f, 0x74ddff3e, 0x8f10dff9, - 0x1fd3d023, 0x9fd3d0a3, 0x347fdfb0, 0x11cc627a, 0xf0cc68b7, 0x1eb2bb71, - 0x708eb5b7, 0xd321203f, 0x54ce9119, 0x9b7a02fa, 0xe8763250, 0xb4f3217d, - 0x4b136f4a, 0xbd3ebf8a, 0xf0bec05d, 0xafe1acef, 0xd149d6ec, 0x7ab59dfb, - 0xfa0f28cc, 0xf19bd732, 0x99d4c49e, 0x6bce072e, 0x006c9911, 0x3e5cbb38, - 0x007b9e33, 0x64bf2f3b, 0xcdc1bc84, 0x7e3f2e22, 0xdcffecad, 0x2aff9c09, - 0x7dbe0b96, 0x6c4d7fc0, 0x4df70197, 0x4958ff7d, 0x7b88fdec, 0x35ee4872, - 0xf7208c96, 0xe2f8565e, 0x2b5f0573, 0xe729d6da, 0xfb445899, 0xfdec5567, - 0x942b348c, 0x45d75273, 0x745be3a4, 0x2285e787, 0xe21467ac, 0xe4c7e7e0, - 0xcd4c3ce0, 0xfc406d2b, 0xf1c4563e, 0x7dfecd17, 0xb3fc146a, 0x4ad70089, - 0xfd0199f6, 0xc7ff5969, 0x11e748ac, 0x39d9158e, 0x0390069c, 0x5995df80, - 0xfc31b7ba, 0xb5a495d9, 0x67f7d487, 0x67aefe2b, 0x5267e414, 0xf1c3ce0e, - 0x4c0e7e1a, 0x3ec5cf2d, 0x88b4b01e, 0x80ffb9fb, 0x73fc0efc, 0xe358a4a8, - 0x64a8fee7, 0xb5f73f64, 0x1adc8f7f, 0xcba8e850, 0x7d9ed911, 0x40fbf621, - 0xdd60e0e7, 0xb9157cef, 0xaa6f6e11, 0xdbd89ee5, 0x7a59697b, 0xd1c3879c, - 0x24e7b4c8, 0x28dff16e, 0x8f5d2de0, 0x77e968f3, 0x5ffae325, 0x1a58c385, - 0xe78c73f3, 0xff31e867, 0x7d79f9c3, 0x94be2ba9, 0x198f36ec, 0x07d837f5, - 0xb95f6714, 0xcd1f2539, 0x6b67d82a, 0x93be96a9, 0xefa6474a, 0x403bd2e4, - 0xfc9caadf, 0x534c6117, 0xa899bca8, 0xa5699bc8, 0x29afdfb1, 0x8e48af18, - 0x632baf2c, 0x73dbe71f, 0x79744e77, 0xfb379eac, 0x4f1b4147, 0x8f25bd6e, - 0x69474e63, 0x7921faa9, 0x7087eaac, 0x5e868d3c, 0x0bd10c48, 0xcce4510d, - 0x3631c068, 0x9db51f04, 0x98afe502, 0xc0a6f98d, 0x39d89daf, 0x96c7dee4, - 0x4f138851, 0xc87f8d0f, 0xa047af60, 0xb1a5dde3, 0xbca37fcf, 0xdb7c37e9, - 0x47f9d236, 0x28c5d5a3, 0x3173623f, 0xb19fec3b, 0xf6f295b3, 0x94ad05c6, - 0x029d6687, 0xf498fde5, 0xab79f92e, 0x30a7de6c, 0x9e5c367d, 0x5e398d6c, - 0x97d8728b, 0x28c537f6, 0xf8ebcd7e, 0x37f93a4a, 0x153ca3af, 0xb347ee24, - 0xf74ecc0d, 0xb97cafa4, 0x202f58fb, 0x9a2f3012, 0x763ee8c4, 0x7ac7e1a7, - 0x051b47cc, 0xe65cfe3e, 0x974ff9e7, 0xf0a3fc77, 0x31a0e59e, 0x7f543b7f, - 0xfb4d9a51, 0xcfe569de, 0xf39bf6bb, 0x9ea5849f, 0xc19e15b6, 0xa753e1f3, - 0xec1c5327, 0x6b8f03c5, 0xbc5aecec, 0xdf7e80c7, 0x7e861e0b, 0x35d329a2, - 0x9c3b2471, 0xae927f31, 0xa89a508c, 0xfa5e7a94, 0xf86d9d05, 0xf7f73bfb, - 0xbd67e848, 0x724cc078, 0x9e81ea7f, 0xe32155f8, 0x3e719627, 0xfe3d06b6, - 0x35af0019, 0x093273d3, 0xf92b1def, 0xce799173, 0x632bc2d4, 0x0f9d00a4, - 0x6b5791df, 0x2ebba50e, 0x794cd6a9, 0x639d5ce4, 0xfceb1d8a, 0xf4fc431c, - 0x4082fdda, 0x112edd7e, 0xe19aef50, 0xec7a86ba, 0xc3eb890d, 0x496b53a9, - 0xe72a75ab, 0x2de4761e, 0xc7ef8039, 0xf1a7af4f, 0x7b64593b, 0xe5c658cc, - 0x99068bf0, 0x80f17de6, 0x55c8e748, 0x7c69debc, 0x0f30cbd6, 0xa6dea3e0, - 0xa7d87ba7, 0xe5114e8d, 0x8134e9d0, 0xdf2d82ed, 0xee8578e9, 0x0288ec99, - 0xb94a2fef, 0xa96cca9f, 0xf7a77f44, 0x748f2e77, 0xbfa55f7e, 0xa96433c9, - 0x49c0ed0c, 0xff94269e, 0x36e4b6cc, 0xdf24f17c, 0xe68743bf, 0xcffc03cf, - 0x227fc17d, 0x6b21f70e, 0xf75c78cf, 0x6a76a507, 0x1f0f45bf, 0xb0f442bd, - 0xe3efc8c5, 0x8e717578, 0x858eb003, 0xcf1101d6, 0x8352184f, 0x2a6de794, - 0x8b74f2e3, 0x81630fca, 0x7d3de01f, 0xc507bf06, 0xcea9da26, 0x84270726, - 0x559ea3de, 0x0597aca6, 0xc2f9f132, 0xd83777f8, 0xf6158c1d, 0xb08b37a6, - 0xef8985fe, 0x7a86c86e, 0x5e78ef49, 0xb3f778cf, 0xb2b1896c, 0x9f5e0cde, - 0x9367eef6, 0x9bd15ea0, 0x3095ebc9, 0x9bb078d4, 0xbd9ab37a, 0xa4be3879, - 0x0f15bf19, 0xfd7f1472, 0x45d26f52, 0x28355f8c, 0x031f87eb, 0xfbece3ce, - 0xe2ef3a47, 0x78fd5b34, 0x86c9832e, 0x3419f8b0, 0x6077dc85, 0xff2409a9, - 0xf30bfbd4, 0xf63f7f45, 0x84fd99d7, 0x2759bbdf, 0xad8073d9, 0x7e145fdd, - 0x5c2e7b79, 0xc8d96dee, 0x8c4e785c, 0xef0966b1, 0xd64c0833, 0x78e3c17d, - 0x855f9c4e, 0x187f9d47, 0xc8b5b05c, 0x3d70439f, 0x70a8e34f, 0x7937cb5d, - 0x6b7ade51, 0x0427ae59, 0xe084d74f, 0x456c180f, 0x0f1dacda, 0x1b5d3ee1, - 0x40209c13, 0x1b7cb93d, 0xb1b5dbed, 0x8e081fc1, 0xef81ba90, 0x096f5b63, - 0x289763ed, 0x9b9d21b7, 0x216ed68c, 0xb8eeb191, 0xe60c1984, 0xe5d631d9, - 0x406e7bc5, 0xd8ef7477, 0x1c74659b, 0x8beb3800, 0xc7a1f9b4, 0x83fb3a15, - 0x98e60f22, 0x01ce7976, 0x047bba5d, 0xdc70f786, 0xa88c3783, 0x5df616ff, - 0xa4be6234, 0x11a2e7a3, 0xeb03bee9, 0xf3c74e30, 0x6ff988c6, 0xbd5eb963, - 0x91e74a2f, 0x4f1c4bd6, 0x7aeeb2a7, 0xe9e0152a, 0xbdd02d58, 0x9247f5bc, - 0x7d7d60e6, 0xb192ae2b, 0xe78755e5, 0x38b4b920, 0x72c29ffb, 0x95381b25, - 0xccb4240a, 0x10f667a5, 0x4d62b93d, 0xe887b33c, 0x8a4f16c9, 0x1772bea6, - 0x280cceec, 0xfa686637, 0xeafee531, 0x83f43632, 0x949a98e7, 0xdb665c7d, - 0xeeb8c019, 0x3bc19732, 0xc2de3210, 0x3262cdbe, 0x1c11edc2, 0xcbd28d74, - 0xe0ad3fcf, 0x1c52842b, 0xf7cf1f7a, 0xefc40af4, 0xba7a6d1d, 0xcbdcd3c7, - 0x35e6aeed, 0x202ecf82, 0x0dbdf81e, 0xed40af77, 0xeba7deee, 0x1bef1193, - 0x47000f00, 0x7d84f8da, 0x9347112c, 0x4ad5dce9, 0xdf775605, 0xb38e0339, - 0xdd023be2, 0x9bbf5567, 0xb2bfc2a0, 0x91ce91a9, 0xa45e7c01, 0x4d9d754f, - 0x5ce947f6, 0x9789cad5, 0x6187a80d, 0x3406977d, 0x5bd6d4f8, 0xcafada3c, - 0xd1fada8d, 0xf29ee532, 0xf90d3634, 0x209978e9, 0xb52439e2, 0xf9d651fe, - 0xe75ef1b7, 0x0a79d16e, 0xe8cdb3e9, 0x7efa819f, 0xbaa2e8b7, 0x3bcf0eda, - 0xf89df118, 0xb1f100e1, 0xc5b9fc40, 0xf8354b20, 0x8176973d, 0xb60576e8, - 0x0f67f3ab, 0xfd754fbd, 0x554dfaf0, 0x1b9c5aee, 0x4730bbe8, 0x90ed0905, - 0x9316517a, 0x222f88f3, 0xbdf9779e, 0xa36f07c2, 0xeeb803f6, 0x7d852242, - 0x44feebba, 0xbde6179f, 0x3a56cdeb, 0x215776e7, 0xf91d81d0, 0xd6e7475e, - 0x2f79e3e6, 0x7903ef28, 0x2ef28168, 0x9226a1fd, 0x128d33ef, 0x9ce577c9, - 0xe42f2a97, 0xb6e7b517, 0x219e67e6, 0xe7beeb3b, 0xb579d276, 0xc17239c9, - 0x2d0fa8d3, 0x471dfe7c, 0x1866df04, 0x34ef23a7, 0x3271cfc9, 0x61d72f3f, - 0x2f68e453, 0xfd7551c8, 0x50e3bfb0, 0x692261ae, 0x9bcd1e41, 0x5da9566e, - 0xf8283926, 0xffe8756b, 0xdde6538e, 0x75a76d5f, 0x487a3da7, 0x316775c0, - 0xe60166ef, 0x7c3a82bb, 0x55f950ec, 0xf8b5d7ed, 0x565de80b, 0x5b63b5af, - 0x65e3d745, 0x6dbb5f30, 0x2dcfc8c0, 0x1fa88d06, 0xdef8e0ee, 0xf2c3e348, - 0x50ee7475, 0x4730fbe2, 0x7680983f, 0x39a3face, 0xf608d8e3, 0xd3acde8d, - 0x148311c8, 0xf33791a7, 0x67f2b573, 0x772b43a1, 0xa39651be, 0x4f245f69, - 0xdfdfb4d3, 0x3fa9a858, 0xbcd4ace0, 0x9d5360ff, 0xcdb26ea6, 0xb16fbcd3, - 0xe3d4d62f, 0xde6b9773, 0xa558e31f, 0xf5bd3769, 0xed0126a3, 0xc077b371, - 0x06e87805, 0x1e4b28de, 0x12d323d2, 0xe32865e0, 0x2c562d0a, 0x744df3bb, - 0x3c7bb64e, 0xec4497e8, 0x773a1dff, 0xc97c4e69, 0xdfe5035c, 0xfc5abe0b, - 0xc9a00e7e, 0x3ddbf685, 0xf0e3684f, 0x5f38abc7, 0xb94365a9, 0x280ac1eb, - 0x67b05ef3, 0x81e97bf0, 0xcc7f707b, 0x45db8c71, 0x2ec999af, 0x5376899a, - 0xb071bf88, 0x397e66ba, 0xbe427bf6, 0xf582f917, 0xbc0a6932, 0x3b08cfb7, - 0x35ee7a8b, 0xebcbf523, 0xe685d01d, 0xce597ff7, 0xceb3c1e5, 0xfc717bda, - 0xb2d03e8e, 0x7dcf4fc8, 0xaebf4468, 0x013fafa3, 0xe70cd9f5, 0xcfb44687, - 0x7a2b9e87, 0x61c60c4e, 0x0e1fe39c, 0x63de23e9, 0xa46e5edd, 0x722b4ff1, - 0x7a3be5bd, 0xf78b4f3a, 0x864a6b37, 0xe1cb73e4, 0x63ef1fa0, 0x7bf3b4b7, - 0x368e789b, 0xf9069c92, 0xbca861fc, 0xf41d367d, 0x4f1a4cc1, 0x97960fa3, - 0x3edee9f9, 0xfbcd6fc8, 0x5c34972b, 0xc8257cc5, 0x4cf3ed71, 0xb1961e7e, - 0x73fa0301, 0xed35d720, 0xfb95cb1b, 0xde58d39c, 0x2e072017, 0xdbdf2338, - 0x9f8abb7d, 0xaae0b833, 0x16787da3, 0x47e789f0, 0x3f861d9f, 0xe1dbd78e, - 0x81a465ed, 0x661bfd90, 0xff7157ff, 0x7228e5ea, 0xbfb2a2fb, 0x014084fb, - 0x33b7550a, 0x8577e88e, 0xa5ed75b9, 0xcf97dc42, 0xdebfa2b7, 0xee8123f2, - 0xffb2ffc1, 0xac3b34ad, 0x54f878df, 0x7697de1a, 0x86953a1f, 0x0cdb89f7, - 0xcf68cdf6, 0x3dd07d03, 0x3f5e8ee4, 0xa87edfc1, 0xb79f1fb0, 0x140e0af7, - 0xeb9eeec9, 0x364eb40d, 0xa3fd15b0, 0x3ae0517d, 0xabedce58, 0x2a76e5c3, - 0x13982edd, 0xc98f7ef5, 0x1e9013e7, 0x5c213e40, 0x820fc047, 0xe66dbefa, - 0xd4f648a6, 0x27df0565, 0xde1919b7, 0xfe836dfb, 0x59d38eb8, 0xbdf88da7, - 0xb0c39685, 0x71d7012e, 0x1c7881ee, 0xa181837f, 0xf7c2a19d, 0x03e05671, - 0xabfbff5c, 0x2dcf0c0d, 0x27ad596f, 0x81bfbf7c, 0x87fa27db, 0x0335bd7f, - 0x2e80cbea, 0x270f3bf1, 0x9d38df56, 0xbfbee301, 0x7569db86, 0x2f881b0f, - 0x6e13ad97, 0xa50e4bdd, 0xff6e956b, 0x70d3a146, 0xdba70dfa, 0xe6baf461, - 0xdbebd1eb, 0x90ecb7e5, 0x61f7a819, 0x438ce7ff, 0x731efa3a, 0x1a7e401c, - 0x0718613c, 0x2ada4f70, 0x63c3c039, 0xa7bef5d3, 0x9c6e50d2, 0x6df9ede0, - 0x7f2e057b, 0x7d71cbec, 0x8646dd19, 0x2a2e08f7, 0xd95176fb, 0x0a0b3b37, - 0x62cfc8f1, 0xa9ca1260, 0xf9ce256c, 0x1d35818a, 0xe452ff46, 0x8ffa67f2, - 0x87b77b6d, 0x2b7fefd0, 0xcaab74e7, 0xe64669c5, 0xf7c56c3a, 0x045f8d0f, - 0xe06cbce3, 0x282735e7, 0x09c94de3, 0x52822c36, 0xe4e5c157, 0xd438156f, - 0x3e149ffa, 0x437f2760, 0xe6685cf8, 0xd1b79ff8, 0xf8eb8cdf, 0xbd75c999, - 0x305fde1c, 0xea1b7ce1, 0x3f49eebd, 0xb9dfe3c9, 0xee1d9073, 0xa27ff056, - 0x63cf37fc, 0x3532cfee, 0x72d7f68e, 0xe90969f4, 0x68a532d9, 0x30f148dc, - 0xe66ccdf7, 0xbaba014a, 0x5aa54399, 0xaafc745f, 0x82fc8071, 0x2fc40deb, - 0xb9e9d337, 0x0553efda, 0x8e46e9ee, 0x4a97d607, 0xb6e41b7a, 0x67921658, - 0xfaa0f150, 0xfb2996e3, 0x5b1ebf69, 0xcfee28c7, 0x8f84d3d8, 0x84e76d15, - 0x41e71856, 0x02b06c83, 0x3627cfbe, 0x8534bdad, 0x626c9fb1, 0x3a0b05cc, - 0x5cccc9bb, 0x6c7d0377, 0xd81ea892, 0xbbfaa364, 0x5e54ec9b, 0xa2c738b6, - 0xa4e079fe, 0xede20a67, 0x671ed644, 0xed73cc2d, 0x41f081ac, 0xfdf4063b, - 0x376b4298, 0x0cccf4fa, 0x947a37ed, 0xf028adef, 0x8333743f, 0xfcbe40b9, - 0x8e83e702, 0x467f1bed, 0xe6b1cf72, 0x49fa037a, 0xb7176df9, 0xf1bddd62, - 0x5f680d77, 0x04fa007c, 0x7eec0ce9, 0x9e501366, 0x81da339c, 0xa66f9a0e, - 0xeb2f38d0, 0x77c80d82, 0x430263de, 0xf7a0fcfa, 0xd71c71ba, 0xe12d7457, - 0xe6744df9, 0x48ad2d9f, 0xfbb8fc22, 0x7f7c75f2, 0xf7a1748b, 0xf9effa29, - 0x87ee0243, 0x9dfda379, 0x467fec4a, 0xb7af90cf, 0xa41306d7, 0x02f87208, - 0xa3978b8c, 0x86581d70, 0xbd1937b7, 0x413cf053, 0xe1c74293, 0xfa158bed, - 0x941b4c04, 0x213229ef, 0xc1239f8d, 0x5258169f, 0x41f93262, 0xe7e038fe, - 0xabbabe96, 0x811e9622, 0xcff5a87d, 0x762187d8, 0xfc3a347c, 0x437e25b2, - 0x4329c3e6, 0x4323f475, 0x1fa07fef, 0x82fbe919, 0xe3c9aca6, 0xb9778a46, - 0x83bec007, 0xc300eafd, 0xf4829ec9, 0x4fca8d3e, 0x91d9748e, 0xc171cc7f, - 0xd82fa83d, 0x3bf23a5d, 0x7b5abdda, 0x87e141a8, 0x7a1ec506, 0x3feb42b4, - 0x5ed49f81, 0x84a4fdc1, 0x3fe34ce3, 0xff273f85, 0x057c8cc9, 0xfd834ef3, - 0xfed22579, 0xc7aed554, 0x2ed8137e, 0x740673a2, 0xbe15f48e, 0xe0a8bfce, - 0xebe5547a, 0x48d7c865, 0xaf9cbdbf, 0xa96dc7c3, 0x1c0bf9aa, 0x7b945b77, - 0xf157f710, 0x139fdaf1, 0xe7ee5f08, 0x1f4f0852, 0xb59ce7b3, 0x031f9740, - 0x2e80fb1c, 0xf19d39af, 0x9affd049, 0x6c9f19cb, 0x1d03921d, 0xbf53c5cf, - 0xa717936d, 0x19fd42b4, 0xef187ba4, 0x8a3ade93, 0x1cf43e6f, 0xbe753fe7, - 0x52cbfc0f, 0x0d8a9f90, 0xda03a341, 0x262efb33, 0x7c581da0, 0xe414fee4, - 0x6e7068c3, 0xdce054ad, 0x4bdad8f8, 0xf01e9c29, 0x455aee1c, 0xf49fb9bf, - 0x6bff111b, 0xdfa23237, 0xd97ed7fe, 0x49fc7c81, 0xfa84bc5f, 0xf1a3e3f0, - 0xd7ff945e, 0x3a7c998e, 0x6f10fc81, 0x8fb5c822, 0x91f7030d, 0x2f4479bd, - 0x3ee8ffa1, 0xc83ddbf6, 0x4cd7ee8f, 0xb5b1f968, 0x51d75d7d, 0xddf5b5ef, - 0xf2c4557b, 0x87e5d1a5, 0xd38f8df6, 0x6ffad57a, 0x28ed9937, 0xb9113f47, - 0xfbdb589c, 0x6bbfd92a, 0xc0cc6f07, 0x47c7ea38, 0xca094fff, 0x379bf735, - 0xb99e504a, 0x8251b8df, 0xc71feeed, 0x2dd9227b, 0x84f4b371, 0x665f5557, - 0xe26a27bf, 0xfa141b45, 0xd5dceec8, 0x57f00938, 0x03896e7c, 0x7b6ab6f3, - 0x139d14f1, 0x79fe2fdf, 0x21c3ca7d, 0x22033afd, 0xce8a8de5, 0x0eafc7d5, - 0xaa47cba1, 0x94ef9a0c, 0x0f38d57d, 0x2df7e2b6, 0x0275c56f, 0xec0efa3a, - 0xbfc880b6, 0xf046bb2f, 0xf601bfa1, 0xb23f784b, 0x923daea7, 0x9910f742, - 0xbd3f9ce8, 0x1c53eb08, 0x5628eddb, 0x8726a7cc, 0x02cb4bd8, 0xe809bf3a, - 0xe4cfa9a8, 0x203f7b27, 0x62baa45e, 0xfd743d47, 0x85b26337, 0xdc9a7108, - 0x1ca0e777, 0xc0d78f0f, 0x5b8418cf, 0xa7ceafb5, 0xa651f8f3, 0x042dd247, - 0x993b9ab8, 0x161d7884, 0x4b9a69d7, 0xf8f0a2f1, 0xdbb03d8e, 0x93ecfd8c, - 0xabc21275, 0x8fb8a5da, 0xc0e4113d, 0x7972565f, 0x6757f2a6, 0x3af5e780, - 0xc9e6b503, 0x69577e50, 0xcc7491ef, 0xece9780b, 0xc600ffbb, 0x1f073a17, - 0xf30e9f8c, 0x98b7be74, 0x9ae79e61, 0x829e6b54, 0x9ae706fd, 0xa21bc81f, - 0x1af9f09b, 0x345db92a, 0xd6442f64, 0x5f0aa57f, 0x2c1e968f, 0xd0f3fcac, - 0x579fe083, 0x7cff7254, 0x709f8f05, 0x7f5c3cff, 0x1d5972a8, 0xef82ad77, - 0x2af972e1, 0x47e039d9, 0x5b5e5c93, 0x32f7a769, 0x90a516fb, 0x92defd7f, - 0xf875bb14, 0x43a239f8, 0x7c379c97, 0x739ed57c, 0x6653e57b, 0x3d647bf4, - 0x897ba7f1, 0x97fcc3e0, 0x9db9ff6a, 0xeee5d902, 0xdf0f8366, 0x2c0ae153, - 0x07d8f1e1, 0x22cf8364, 0xaa89d90c, 0xddab791d, 0x6abb5021, 0x63f6aa57, - 0xbbe3c9c0, 0xfb788a4b, 0x556b8b65, 0xa75c58e5, 0x97179e85, 0x398ce7f3, - 0xf55fa14f, 0x918152e0, 0x4aec501c, 0xedc34e95, 0x72fb4fce, 0x438a4712, - 0xa7d0af3d, 0xc21367ca, 0x63d543f8, 0x7e7054cf, 0x5e3d40eb, 0xf7fc7a88, - 0x7c3cfb1a, 0x8fe3d05c, 0x463f5257, 0x2e7e8bfd, 0xebf9233a, 0xadfc6566, - 0x4e05feea, 0x59bc20d6, 0xfd19b02c, 0xf5fa68cc, 0x139d8a7b, 0xc519fdad, - 0x3f1dbc7e, 0xc8e4561f, 0xcbf3f168, 0x70f2b795, 0xf9f9a9ff, 0x8c687d96, - 0xd557bf62, 0x1ffb86bc, 0x6a04f7a7, 0x97feff90, 0xe1eee281, 0xfaa53def, - 0xecd3229f, 0xa32ca9cf, 0xf723fd0e, 0xe83f1e1a, 0x43bfb24e, 0x7a5bcc7e, - 0x05ace386, 0xb8ed107f, 0x51266f47, 0x32f686d9, 0x385e2b94, 0x1588f947, - 0x77f0b46b, 0xfb174c63, 0xf3a6cbaf, 0x9eac2d03, 0x7d2d4ce2, 0x5016d249, - 0x0f63dd0a, 0xf2be469d, 0x0fdbd01e, 0x88ffbe84, 0xc799befa, 0xfba636e1, - 0x661af728, 0xc278b40f, 0x7dad7eed, 0x8dc4a950, 0x6f09d9a2, 0x5cb85bf4, - 0x3e27a339, 0xd378c0ef, 0x7d8cc64c, 0x37b82e5c, 0x474938f2, 0xfc04e6df, - 0xd2bb6a08, 0x500c457e, 0x6bf28a1c, 0xbed5eaf0, 0x3ee8d3a7, 0x27cdac97, - 0x39ffefb5, 0xbcf0cbc9, 0x970f7252, 0xbd36ee4b, 0xa12a4792, 0x83b797ef, - 0xed0e393f, 0x1bfdbb4b, 0x8b807788, 0xc8de48f9, 0x3ecbb89a, 0xe9f4af25, - 0x3f257f99, 0x2891c574, 0x79eea479, 0x7ca48f3c, 0x1e787727, 0x0ca9f4e9, - 0x48f3edfb, 0xe8e7bd1d, 0xf2edcb1e, 0x5baaa649, 0x3b8a1c71, 0x7c79144e, - 0x209f6277, 0x626abc61, 0xe9775f1f, 0xafb238b6, 0x3ab57e1b, 0xba81e505, - 0xe22c9f4f, 0xfde4fdf8, 0x5fb06acf, 0xc944afc9, 0xe37aeb02, 0xcb3f0dfd, - 0xd9bb75e0, 0xc436fd8e, 0xc9f33fa3, 0x23c7d6af, 0x1280df7e, 0x17c7e7f7, - 0xc9f1c8c4, 0x667578a1, 0x959dc515, 0xfa08b578, 0x5c50cc70, 0x8bdfbc27, - 0x746e5c55, 0x7142bb83, 0xef3c23cd, 0x9aee9ddf, 0x9ebff547, 0x29dff8c4, - 0xfd1e2990, 0xc635d02a, 0x62c1a68d, 0x3ffd2f31, 0xe62758e3, 0xbac7ba91, - 0xf47c427e, 0xf23b3ad7, 0xfca7f411, 0x9db0f793, 0x6a8623f4, 0x0333cf31, - 0xf7405b3f, 0xdf295231, 0x8fb28f73, 0xa2cfe0e9, 0x2cd0095f, 0x34f43cc1, - 0x2333df25, 0xfe38898e, 0xfb6b830e, 0xf52fcc54, 0xc4cd8e8b, 0x3c148e04, - 0x779e196f, 0x2f9e6412, 0x6a4ff357, 0xfe5a3cde, 0x9479c049, 0xf3f056ef, - 0xf980b296, 0xc4cf3574, 0xf9293a96, 0x43cca5b5, 0x807c42f7, 0xde73afb3, - 0xcffc846b, 0xf21115c3, 0x982beb3f, 0xf3699f62, 0x5f73db8d, 0xaafd3a21, - 0x78c3c679, 0xe68ee2ae, 0x0fdcecc5, 0x28bb830d, 0xf234d3e9, 0x6ff8febb, - 0xfb67a409, 0xbc3e906e, 0x00b13416, 0x78071fc5, 0x40cfbddc, 0xe06b8671, - 0xd10d8dbf, 0xf054efb3, 0xd5f78f71, 0x04f7fd11, 0xfdf1e3ea, 0xb7cf2bdf, - 0x7ee4b7bd, 0x01bdf7b4, 0xc60b1dfe, 0x13d63fb8, 0x6ed18b10, 0xf2fb83b9, - 0xf5846564, 0x7eb8e399, 0x52a3e70a, 0xab4aff85, 0xdeeb9e38, 0x7b987ee7, - 0x48afcf03, 0x7b705c8a, 0x74fd5e78, 0xc6a09a56, 0xca45c7d3, 0x92091cbf, - 0x447968de, 0x7cc9efa0, 0x33cbfcd9, 0xf1f391e9, 0x462f7a2b, 0x3634bfce, - 0x168cfc90, 0x638f0ecf, 0xff2a9dff, 0x7638f3a6, 0xeb44957a, 0xd7e4f64e, - 0xeb43638c, 0xb0fb83bf, 0x7d845674, 0x6fe383b8, 0xf1db1d9c, 0x3b63caeb, - 0x1e3113fe, 0xc78c7b7f, 0x6c7961ff, 0x8abaebf3, 0xdbffc2d8, 0x1fdfc318, - 0x57fffe09, 0xe78407cf, 0x0bcfc3ff, 0x30039f84, 0x17b0f5bd, 0x9d84badb, - 0xefc33f41, 0x24d6bf8d, 0x93141c80, 0xce7dd3f6, 0x1f3ce505, 0xecdeadb6, - 0x9d0c2bdb, 0xf5f1501b, 0x23f73568, 0x5eebbca5, 0x04d45efc, 0x829f5039, - 0xfe72b2f1, 0x59ae4377, 0x898c5e78, 0xc9e63a52, 0xc5f4cde0, 0x5b749760, - 0x5359e722, 0xe9a2f195, 0x35d58391, 0xe315678b, 0x7c8a3d1f, 0x4a87ff0e, - 0xe5ea521c, 0x6899e9f7, 0xf34c5f4f, 0x1ed1d3da, 0x9fc93c4a, 0xbc99f827, - 0x67b2e097, 0xdc7fe62f, 0x7be11b20, 0x26ffc946, 0x1b2bbbcf, 0x60c9d2e3, - 0xf05e6217, 0x920fcc69, 0x7bd12b3f, 0x66977cea, 0x19ea3f71, 0x9f301303, - 0xcfca9deb, 0xdf9eb139, 0xe6a6fd91, 0xfc1acef5, 0xca055a97, 0xfc23b5eb, - 0xf3f9d53f, 0x442b65f6, 0xebcdf80c, 0xf8df2891, 0xe5dff976, 0x9e1e68ba, - 0xe24c7be7, 0xbf409caf, 0xec78e019, 0xefd12168, 0xffe5e38a, 0xc7fe8cd4, - 0x3cf09164, 0xe254afcc, 0x78941705, 0x502f1a87, 0xacff5bf3, 0xc03e49c4, - 0x03940bf8, 0x72810f18, 0x9ddd2cfb, 0x67db4fd6, 0x67ffe045, 0xf21f1e04, - 0x87c794fe, 0x9c8e8d0a, 0x7f94f3d0, 0x63ef8b35, 0x2fe79fab, 0x0fcf78d4, - 0x7e14f595, 0xefc7ef4f, 0x9d6e15a1, 0x5f3d446e, 0x0e2b35b8, 0x4fb219cb, - 0x5ef80697, 0x4eb0fab6, 0x7448bfdd, 0xe75957b4, 0xca4133b6, 0x961abdef, - 0x8b34bff7, 0xa968679f, 0x097bfbe6, 0xd418a0ff, 0x6e229b1f, 0xb131f341, - 0xca47d24a, 0x5f80b52b, 0x76b6708c, 0x7c55b873, 0x75edf8b7, 0x53c5cf38, - 0x1658adc1, 0xa3aec9ac, 0xf5db7bb8, 0xb9bf68ad, 0xae9c6f07, 0xd19978a6, - 0x43c4fe8e, 0xdbb8da03, 0xfe3cd513, 0xe01a2afe, 0x457bb788, 0xef0b8ff2, - 0x927e8915, 0xbfe42c5b, 0xde981b26, 0xdc45f58a, 0x4c682a2e, 0x5b3ac3ad, - 0x60f64492, 0xd27b19c1, 0x714379c3, 0x377be4b0, 0xdd3c458c, 0xc6aacf2e, - 0xe45b2ed3, 0x5f9fb8e3, 0x7edacf35, 0x6f3a3df6, 0xc54baeaa, 0x8d2f9a8b, - 0xcf556796, 0x3f1bb83d, 0x70d39cd3, 0x8c06c18b, 0xbd1e163f, 0x5fce5468, - 0xa1ecb64a, 0x91e16c3c, 0x557f94eb, 0xcf6eadf3, 0xa1abb275, 0xf7fb119f, - 0xd7f9e26c, 0x2c0e00d7, 0xb2dd617b, 0xdba1ef09, 0x7583eca8, 0x9b63f3e3, - 0x6ff4a972, 0x7c795072, 0xf8951953, 0x64f4c999, 0xa75edbcc, 0x59d5edbc, - 0x524dcec3, 0xe8b76f5e, 0x15f108fc, 0x7aa3f792, 0x1f4fde78, 0xee35e3c7, - 0xbefa0633, 0x99acfba1, 0x5f4d77e4, 0x0ff444eb, 0x9ae73f3e, 0x60777088, - 0x2e842dde, 0x961d913e, 0x9d83f424, 0xdbe60b0e, 0x1aaffb0a, 0x874c3cf1, - 0x3c623018, 0xc0cf200c, 0x9eee8b23, 0x6fdcfceb, 0xf1058d5f, 0x58fcdb7b, - 0x8fcfffef, 0x58fc957d, 0x273f3577, 0x0291caad, 0x8bde4ea7, 0xf2d919e5, - 0xd89c8870, 0x94f9e4e6, 0x1127936d, 0x4e76ee1f, 0x321d5a4a, 0x8f23675e, - 0x3bdf245f, 0xfcfa12d9, 0x1f3cd597, 0x67302c96, 0x33567924, 0xc7ddebfb, - 0xd76e411b, 0x3ffbb244, 0xe5d029f9, 0x238ba04c, 0x90389edf, 0x343f19c7, - 0x71adb71e, 0x2831c4f5, 0xd8982e9f, 0xd3af1e14, 0x5858e3c4, 0x5c5a2e5e, - 0x4ea3456e, 0xa179d0b6, 0xdbd404e0, 0x2633f1e1, 0xbd702706, 0xbde0672e, - 0x83319814, 0xf961b195, 0xdf305fb9, 0xfbc327cf, 0xa4751acb, 0x5d3cd42f, - 0x36c8a341, 0x6c167d01, 0x3f28f834, 0xa45e28d7, 0xec6fc576, 0x90320a94, - 0x6b383fce, 0x16ae3094, 0x34731f1e, 0x049eefee, 0x026d1dfd, 0x5dba0bdd, - 0x073d4f1e, 0x3fdbd2de, 0xf96de307, 0x3d77576c, 0xac9fcff4, 0xf4fcf093, - 0x3f1e7cf0, 0xd8a05dff, 0x3671e139, 0x4bb433a4, 0x1bf0e3c2, 0x38d83a15, - 0xd7adeb9b, 0x1d537f14, 0x4e17ed47, 0xcd9d3f3f, 0xb8b46df5, 0xbc6551fe, - 0x6d82c6ce, 0x177f7193, 0x93ea18e8, 0xf35ac6ce, 0x76f190e4, 0xdbe7e6cc, - 0x60fcc19e, 0x907e686a, 0xf3c301e7, 0x2b9caa82, 0x037dffec, 0xc8377be2, - 0x6e63d46b, 0x141fcf1b, 0x8339ab1e, 0x4e086372, 0xc377b7ae, 0xbec8079e, - 0xbe312473, 0x457bfa2e, 0xc502a3de, 0x7c160ae7, 0xea1e3c76, 0xf74499cc, - 0x2767dcb0, 0x3ca2b16f, 0xe316205a, 0x53b71ebd, 0xc26795b8, 0xeffdd27c, - 0xbcefa1ac, 0x7f903e16, 0x81e5f70e, 0x0f9d0366, 0xfddef554, 0xf03534ef, - 0xc64fbdf6, 0xe0ae7b61, 0x79f1d8b0, 0x763f7d23, 0xfa7e4bfe, 0x110b58bb, - 0x81e7903a, 0xe44497b3, 0xd716cb9b, 0x151f23df, 0x4cf2522e, 0x3f4f5ccd, - 0xc0c8b7d0, 0xead3cec8, 0x9f5913cd, 0x46e83c53, 0x8fe5215f, 0x43fcf052, - 0x29be90de, 0x6c7a0a3c, 0x63d39dcc, 0x112d9d3f, 0x1e82673e, 0x17927843, - 0xf87d3cf1, 0xf650effe, 0x8a5e9a3f, 0xff518726, 0xde63fbf0, 0x5c36c10c, - 0xee31db8f, 0x3af68a53, 0xd3a2e394, 0x71661fdf, 0x628a4eba, 0xa149fdcf, - 0xa7e7a8df, 0xcf27477a, 0x7fd987f4, 0xd563791e, 0x4df352ff, 0xa0f6bfaa, - 0x65ab0f62, 0xbbfe5293, 0x72a037ef, 0x21bf788d, 0x86fdf239, 0x68090e87, - 0x1bf7a8a7, 0xcd59194e, 0x4f3c54e1, 0xf277dcab, 0xe93b222d, 0x62fcdfd4, - 0x78a98beb, 0x509049df, 0x3a1fb51d, 0x1dbe7a47, 0xa7b223ec, 0xe3cb7efa, - 0xf9f887ad, 0xc8def6f0, 0xaddbdddf, 0x32f5dfd8, 0xaed1b923, 0xe86db79c, - 0xb744f251, 0x8b8f96e2, 0xb74b71a1, 0x3d56303d, 0x7f23ebc7, 0x8cc71b4f, - 0x60ecb716, 0xdbb73a41, 0xa07046b1, 0x39ddb87e, 0x79ca5ddc, 0x4c71a8dd, - 0xb973e479, 0xb94c71e1, 0xb9c79b5a, 0xf7c4966f, 0x680825db, 0xce759aef, - 0x7fb73a36, 0x9d22904c, 0xcd5a5ef3, 0x257cf4e5, 0xc8d0720f, 0x8560e3e9, - 0xf06ff740, 0xfbee1e1e, 0x1efc63c1, 0x7e02c1ce, 0x7bcd470f, 0xa66bf7a8, - 0xe83de50e, 0x2f7a9dfe, 0xc367bd47, 0x5ae08f98, 0x7d1c5cf4, 0xe1876bc7, - 0xbddb8d90, 0x1a3f7e5e, 0x43e61065, 0x8913cc4d, 0x6bab6b5f, 0xef7a6ac4, - 0x8f4fdb8e, 0x7bf04754, 0xe91f8a7d, 0x2fea8eae, 0xfad6afac, 0xf70f540b, - 0xde54ee17, 0xecd98be3, 0x87fbfb4e, 0x9e8f1c63, 0xf1b63b32, 0xfb48ecc4, - 0xfda2c5b6, 0x5e5aaf1e, 0xb0dfe456, 0xbb0dc5ef, 0x7af5c92f, 0xa7ff60b7, - 0x1ba7ca4a, 0xcaae9f28, 0x7c31eed5, 0xe3291ffc, 0x294065a9, 0xd77ca3bb, - 0xbc4a97f9, 0x7b944bac, 0x2f69ee10, 0xd397e368, 0x97e3690f, 0x35937b33, - 0x78ff7cf5, 0x6785fbcd, 0x8bda6926, 0xda68f703, 0x68142f4b, 0x1503e5ea, - 0xaf2bf79a, 0xb3ea6ad4, 0x65f8da82, 0x61c5cdf5, 0xb47d38f7, 0xdca01abe, - 0xe6757ed0, 0xcbde6a6f, 0x575da358, 0xaebb4796, 0xebb51b89, 0xf6cdc752, - 0xd397d76a, 0x325f5dad, 0xbef2e3e6, 0x7f2e3e7e, 0xc7c95db6, 0xdfb058e5, - 0x2d938d33, 0xf7a9b768, 0xfef7d5a9, 0x5866372f, 0x007f40df, 0x00000000 -}; - -static const u32 csem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0xe4b3ff00, 0x51f86066, 0xb97bc10f, 0x726e1818, - 0x0143f821, 0xd08667cf, 0x0c0c2c6a, 0xc6cc401a, 0xcec0c0c4, 0x717ebc44, - 0x1d7b044e, 0x4cc30307, 0x31c8de20, 0x481afef0, 0x7e879d7c, 0x42f3a976, - 0x81c15968, 0x570837f7, 0xb430310a, 0xc430330a, 0x0cf84088, 0x55f2a8a2, - 0xa9b60842, 0x39766524, 0x0003f502, 0x3471cc24, 0x00000380 -}; - -static const u32 csem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd554780b, 0x733ef0b5, 0x7993331e, - 0x0f20f264, 0x0084f102, 0x021842a2, 0x27088784, 0x01a8c421, 0x54bc8083, - 0x48433c26, 0xbfa81132, 0x2677bd6d, 0xb5ad1104, 0xbc1b6951, 0x14101de8, - 0xd1a07515, 0x40e81c06, 0xdbdab114, 0xd5a8f8a8, 0x40445076, 0x8bcbc248, - 0xaf7fd52d, 0xe649cfb5, 0xd4484c9c, 0xffffbff6, 0xdbf3f1fd, 0xd9cfb3ec, - 0xdaf5ed7b, 0xf6bdad6b, 0x9a32c11e, 0xe4224e24, 0x65a3f85b, 0xf4842784, - 0x0adb2ce9, 0x64918fda, 0x8b2ffc42, 0x108e36f2, 0xf08e77ee, 0xbc8451a4, - 0x980b99b5, 0xcfbc3d69, 0x9fad0846, 0x603d34de, 0xff6422ce, 0xef02b308, - 0x8f9ade9f, 0xbd2fc9f5, 0x7b6814e7, 0x00bc4bd5, 0x13bed375, 0x109d88ce, - 0xa1e5b9af, 0xf6f3e96b, 0x85b27897, 0x93fc450e, 0x9085244d, 0xfec21663, - 0x52fab22e, 0x6d56ab2b, 0xf4077fde, 0x2664de5b, 0xd54fda56, 0xaed365ee, - 0x8765f5a5, 0x54af0244, 0xfa95ab6d, 0x00f2fad2, 0x9afa8417, 0x71c67f7d, - 0x79480ada, 0x27212870, 0x5f22167d, 0x96ceeb49, 0x79f45994, 0x11676045, - 0x83b15fbc, 0xfbe89b73, 0x7ff69b15, 0x3457fd0c, 0xda79038a, 0x36ed8aff, - 0x63610f22, 0x1e604b7f, 0xbc01a64b, 0xc4886f55, 0x97e5eb4c, 0x70044956, - 0xa54bd424, 0x61ff180e, 0x38c07649, 0x0d1c7087, 0xd0cf559f, 0xd577e871, - 0x986e702f, 0x7889b55a, 0xddd69e00, 0xda4f39d6, 0xd2b55e61, 0xf77ef860, - 0xb7bc127d, 0xb2f6502c, 0x36f80655, 0xe700454b, 0xd2d2cda6, 0xadfd9da1, - 0x0ea6fed8, 0xd90d63ae, 0x76a89ea9, 0x47d27963, 0xacee6c88, 0x04a21057, - 0x407700ed, 0xf3ac3e9a, 0x812e79f9, 0x3fd0d190, 0x674b644f, 0xc83094ff, - 0xe8f7fe07, 0xf60f813f, 0xb2db023a, 0xd2b5e93a, 0x772dff45, 0x4bacebd2, - 0x9ed09fa5, 0x56bfdd17, 0xa074043e, 0x5cfbd4f0, 0x4be23e58, 0x4f8372c3, - 0xcafdbc46, 0x06cb0437, 0x3f9f1b9f, 0xe58b1be6, 0xe5829f26, 0x2c62be13, - 0x7c52be03, 0x0e6f8b6f, 0x1e7d5b96, 0xaf94fe7c, 0xbeedcb1c, 0xacfe7c1a, - 0x772c6eef, 0xfcf8fcf8, 0x2c7adf05, 0x2c7abe83, 0xb01af977, 0xf005f46c, - 0xdb7d97bd, 0x05f26cb1, 0x5f1ef9f1, 0x5f219613, 0x407dcb18, 0x7d865a5f, - 0xf01e582d, 0xabe5887d, 0x777e08be, 0xcb1c77d0, 0x3bbc5507, 0x817c9027, - 0x10a9cde2, 0x92171517, 0x8be4a258, 0xca589eb4, 0xf9b729ea, 0x4f5a25f3, - 0xc53ad0f1, 0x70cadf63, 0xfbd699be, 0xccf6b0d6, 0x8581487b, 0xacfd33d6, - 0x4a83c07d, 0x07d69581, 0xc1f6b3d4, 0x7105fc9b, 0xc0383eb4, 0x11deafda, - 0xfad1b02e, 0x9ed641d5, 0xed932213, 0x66139eb4, 0x94b7dcf5, 0xcf5a0ec9, - 0xbcf5616d, 0x9d93fd8f, 0x61179eb4, 0x153f8fdf, 0xeb4f1c9e, 0xfb59dbe3, - 0xd0a44bc4, 0x0913eb45, 0x7b02f587, 0xad02617e, 0xbd58b817, 0x20995fa8, - 0x7dbfe0c7, 0xa1116462, 0x7fddb0bc, 0xd3a422b3, 0x455914ba, 0xfe9f14dc, - 0x8b0f5839, 0xbfb43164, 0x84532fe5, 0x912eb471, 0x17fed0d5, 0x1fb6057f, - 0x6f6c6510, 0xf6c2aff7, 0xed8c9203, 0xb07bdaa6, 0x60a8aafe, 0xbded727b, - 0x92abfef8, 0x6b83ed82, 0x41fac21f, 0x63ed83d1, 0xef8d7f6b, 0xd83c941f, - 0x80dac8fe, 0xffeb4852, 0x00b679c1, 0x9e71d75f, 0xfc0d9272, 0xa52b4c1a, - 0x238ebafc, 0x1e3e4073, 0xf2a6a600, 0x525d2eb0, 0xfbedbf40, 0x3c93de47, - 0x3276f2a7, 0xf53e97d4, 0xf3f61640, 0xd223f61c, 0xfb9ef87e, 0x58cdf899, - 0xbf133f5d, 0x69fad729, 0xaceaf784, 0xdf67ebbd, 0xf0f5e337, 0xf5a1537c, - 0x71fb17b3, 0x135e6ef4, 0x87a09dbf, 0xad4adbe7, 0x4fd8839f, 0x09e0ef42, - 0xfd74638b, 0x5a65c584, 0x7ec47f3f, 0x1e0ef4fa, 0xeba71a45, 0x6b969147, - 0xfd887cfd, 0x9faef7a4, 0x1ead74b0, 0xd685691e, 0xa7ec11cf, 0xa5e6ef7f, - 0xc3d3af98, 0xfad2ae63, 0xcf748939, 0x073f5dea, 0x1cfc7a1c, 0xe7e07470, - 0xa833c21c, 0x702af377, 0xe053f1ea, 0x25cfc0ec, 0xdeaae7ec, 0xa9c073f5, - 0x6701cfc7, 0x0e447e07, 0x77ac35e6, 0xd7882af3, 0xbe20a7e3, 0x0e4e3f03, - 0x3bd119e0, 0xa3ed5e78, 0x7dabcfc7, 0x8a93f03a, 0x1dee8cf0, 0x7a29853c, - 0x74a614fc, 0x784647e0, 0x9faef5c6, 0xf8f45357, 0x03a53579, 0x3f61573f, - 0x5e6ef5d7, 0xfc7aa985, 0xe076a614, 0xc9fb1727, 0x78476cf7, 0xd1c7ed08, - 0xfb073f7d, 0xb073f1eb, 0xae7e077f, 0xd0a67ec5, 0xee7bb27e, 0x8f5328a7, - 0x0ecca29f, 0x9e2214fc, 0x3f5de86f, 0xf8f53307, 0x81d99839, 0xcfd8a99f, - 0xabcdded4, 0x7e3d0ae8, 0xf860ae8a, 0xc08c2499, 0x9dae8675, 0x727e9e6e, - 0x857cbf7d, 0x2ef3efa3, 0x6e5de756, 0xaf0f7602, 0x45a433d9, 0xf6fbe9e1, - 0x0fb9091d, 0xa6bb6890, 0x8fc076e0, 0xd1795a83, 0xd8fc4d76, 0x951d9d38, - 0xeaea24a0, 0x757dc549, 0x1d29f7ef, 0x9d4f6ba0, 0x3daeb573, 0xabab93dd, - 0xd78f9467, 0xa6bfdfbd, 0xe2bf5740, 0xef751bee, 0xd16ff967, 0xcfd7b3d5, - 0xa83fbdd3, 0xfdaea17e, 0x5d0a86ca, 0x958155fb, 0xdb35faba, 0x7f7ba27f, - 0xae8d7058, 0x03d3787d, 0xe111f6ba, 0x91f57447, 0xbdd31e87, 0x8b65ba3f, - 0x87cc7dae, 0xc7daeacf, 0xeae97645, 0xa3df1ed7, 0xf6baff7b, 0xa4faba03, - 0xbdd7bf8b, 0xd5de4f9f, 0x3f96dbdb, 0xe29fdeeb, 0x7ed74cfa, 0x0697da7d, - 0x3aeed53b, 0xe75a8d76, 0xfa08ae41, 0x0974fe25, 0x43b0d5ed, 0xd7d4bac2, - 0xc714fcce, 0xe528f952, 0x22c0e91f, 0x92f91939, 0x21bb51fe, 0x95f96fbf, - 0xaefcfa11, 0x5d2b9ef1, 0x925df9f4, 0x862bb867, 0x8df9437d, 0xca506923, - 0xed8d2826, 0xdf8c89f7, 0x0d2e320b, 0xf7bf423e, 0x2707da9a, 0x3e70fad0, - 0xf1f2083f, 0xbb426732, 0x35278e3a, 0x999c5ef0, 0x5f74dfa0, 0xfe93de56, - 0xdf587928, 0x5c19da9f, 0x45ebbf67, 0x51da1a4f, 0xc1f89fb5, 0x9fd759ce, - 0x212fabce, 0x849f70af, 0xf7e903fd, 0x79a697fd, 0x89667f68, 0xe3d119fa, - 0xa1fc744b, 0xe4187e38, 0x3f8c20e1, 0xe6f8ebba, 0xe3756301, 0x75cb325b, - 0x3a245be3, 0xdf908bbe, 0x8eae7ed7, 0x9e30894f, 0xcfb93790, 0x66737c71, - 0x9f7f8e39, 0xe8aefd44, 0xc63ae3f1, 0xbff9816f, 0x07fcdddf, 0x3fcfd78c, - 0x7f3f42b3, 0xa3ffcd89, 0xf8ead3da, 0x3fff3871, 0xfcd9a773, 0xfcd82b33, - 0x8edfaccd, 0xf81d9df1, 0xc7f8c08f, 0x9cdf19ba, 0xff3f413d, 0xf3f52a2b, - 0x4ff1b337, 0xc7505ed6, 0x5ff8e3b7, 0xfcd81772, 0xf1c4a8af, 0x0dc7b325, - 0xc46523fc, 0xf8e804d5, 0x7c551fa4, 0x742ec0a9, 0x2487281c, 0x6421a152, - 0xe100371b, 0xf18e2bb8, 0x947157db, 0xf99f50df, 0x500939f1, 0xfd4799cd, - 0x57d79546, 0x4097c8ec, 0xf53b61ef, 0xa0a896b7, 0x91e26e2e, 0x7306c9bf, - 0xb7851060, 0x43f789b5, 0xeb86f17d, 0xbd5fa002, 0x14a0b266, 0x184813be, - 0xcbfe7f9e, 0xe7a25b61, 0xd4972c65, 0x5122c78b, 0x07e1d6f2, 0x35219016, - 0xc029be14, 0xeb3ba304, 0x0e3f529f, 0xa98fe31c, 0xffa843df, 0xc6c899f3, - 0xf7f50bfb, 0xfea11ea0, 0xa4ce3a1e, 0xdda3bf16, 0xf0a34e1d, 0x7ff0aa97, - 0xfd79302a, 0xe02e36f4, 0xd5f9f2a7, 0x7fa0478f, 0x1b6ee0bd, 0x1c277a45, - 0x5d24fe65, 0x0fcbce9d, 0x6ddf6a74, 0x10e16c0e, 0x6be032bf, 0x21268a3a, - 0x5067d68b, 0xffbe775c, 0x07a9bec1, 0xb7212739, 0xa54c4512, 0x9abedfef, - 0xe3a2efeb, 0xb9cc52ce, 0x32521d6c, 0x24d7284c, 0x909634c3, 0x88471a5b, - 0x5d3207b4, 0x448d3f11, 0x58a33b8d, 0xaa559f5f, 0x8a8ab7af, 0xb570a268, - 0x66c8e74e, 0x39ecefda, 0x9c6d76fa, 0x4644a681, 0x52bc7567, 0xfa74938a, - 0xb9943668, 0x7485d8f0, 0xdf62e39e, 0x1778f06a, 0x7e8c2489, 0x010fbfbc, - 0xf193faba, 0x362e79bd, 0x73bc236f, 0x4a528b44, 0x8ca739e7, 0x1b7f000f, - 0x9f68ffe1, 0xd0e5314d, 0x22a3fd72, 0x8f9d7531, 0x1eb9fe11, 0x22827ce3, - 0xcbf3f3ac, 0xdf19cf8d, 0xffe9531c, 0x2d07f029, 0xa0fe00bf, 0xf9551ff0, - 0x32af53a3, 0x3d9af0fe, 0xda1f80d3, 0xe904f237, 0xadcbf2aa, 0xa92cbf2a, - 0x2105f3d7, 0xb8e8111e, 0xfb970e6c, 0xcc1f1440, 0x5960f956, 0x6e6f9e83, - 0x3d317e27, 0x6ee65d06, 0x9a6f7cd8, 0x9f7e75dc, 0xff337ca8, 0x9f88fdc1, - 0x7464f3ae, 0xd3a543ba, 0xf6fa35ed, 0xdeba555b, 0x4e75d2ae, 0x51afc3c3, - 0xc9e641f5, 0xdde41101, 0x9e8d53fb, 0x3d3d1d11, 0x708d3d2a, 0xf3d2a1de, - 0x7a331f8e, 0xa88de11a, 0x9c348cf4, 0xae80c913, 0x5be11af0, 0xf9977770, - 0xccab5c60, 0xde9e9b1f, 0x4755fca6, 0x05579ea3, 0x3475586f, 0x6c56ce4a, - 0x2fabae9f, 0xbdd5cc0f, 0x4ca1acbf, 0x7ea4bed7, 0xd17daeb9, 0xf5753bfa, - 0x758fff32, 0xbbb82fef, 0x7b7ed756, 0xf6bafdcd, 0xeb0fe5f9, 0x1b3d73ea, - 0x9ecfef75, 0x3ed759b3, 0x5d19f4ab, 0x9de28cfb, 0x6574faba, 0xd37deeb7, - 0x066eabbe, 0x3deb7cfe, 0x713d809e, 0xc605fdc1, 0x45b82f33, 0xd473bc37, - 0x1f5f2327, 0xf2c10df3, 0x7c8dcfb8, 0x1637d27f, 0x66a6d6cb, 0x7413ac3b, - 0x124a5c5d, 0xcd326908, 0x0fdf5dab, 0xeb8269d6, 0xa9e4c869, 0xb37ad3f5, - 0x28794649, 0x78489069, 0x2c1c2124, 0xed1c2a36, 0xa47b547c, 0xaa06f687, - 0xb6ba93f8, 0x3f624497, 0x76523ef7, 0x7765f005, 0xcbfd03eb, 0x4da7bb00, - 0xed8debb5, 0x8d291c95, 0x1ac84e7e, 0x626ac384, 0xc4a54776, 0x5772bfe4, - 0x4271017a, 0xe6b83c3d, 0x2905e372, 0x9f02a793, 0x78e4eb64, 0x3a35c359, - 0x9a204efd, 0x6df807dc, 0x8af9eea4, 0xbeead7ed, 0x479fb53b, 0x5741abb8, - 0xb165838c, 0xe81333f4, 0xe67370e1, 0xa700618c, 0x4deb1472, 0x3c2ed07d, - 0x755e2be5, 0xafd01074, 0xbee3cb14, 0xf31e5839, 0xea3cb079, 0x53f2c72b, - 0x11960d5f, 0xfe58dddf, 0xf2c7e7c5, 0x2c7adf63, 0x63d5f23f, 0x01afa1f9, - 0x017df7cb, 0xb6fb0f2c, 0x2f8ef963, 0xaf8b6588, 0x9f56cb09, 0x7726a582, - 0x71ddf13d, 0x093e1d75, 0xcf8317fc, 0xed7f3aa4, 0x7c9d09fa, 0x87dfc716, - 0xb9e1a67c, 0xf2acc1a4, 0x1f8e8a43, 0x4397c012, 0xbda1eb3e, 0xb0f95441, - 0xb763efbb, 0x6bfcb77b, 0x0fea6df8, 0x7e4eb7e4, 0x53f030ca, 0x34fc4f76, - 0xa7e28f8c, 0xb31726a9, 0xfa7e547b, 0x8623cc19, 0x8c0f315f, 0xf6513e90, - 0x826f929a, 0xbaa56c75, 0x601f420f, 0x763aacfd, 0x05b77d1d, 0x10c0baed, - 0x0ece3758, 0xd860dbf9, 0x21fb3847, 0xf7567e25, 0x49f233f3, 0xd05778f7, - 0xa01a59bf, 0xdaea4f44, 0x78638d6e, 0x31489ab5, 0xfddaeba1, 0x2f729e83, - 0x81758a1c, 0x01f7c224, 0x8c4774f7, 0x0cada97e, 0xaf09edf8, 0x72af8e75, - 0x8f63bfa0, 0xca0f3dfd, 0x2f6626a9, 0x68f335c7, 0x93f093b7, 0xc76fc06e, - 0xa77664ba, 0x7dbdbc41, 0xbb42e490, 0xe3d64c81, 0xc3a05fcf, 0x4714fddf, - 0xd6eeb82d, 0x06fe21a7, 0xbd38357e, 0x49ebf817, 0xcf84f7bf, 0x7fef3085, - 0xd27b3e01, 0x45e93d8f, 0x342fc8a2, 0xedb7f9d1, 0x80fb961b, 0x1e5ee30c, - 0x9afedadf, 0x7e5f9e11, 0x4b6e3e47, 0x25b8f8d1, 0xa41f8093, 0xc6d9cbca, - 0x2e81e32b, 0x40f4fd1d, 0x9f77ee4f, 0x7eff8264, 0xdfdf4b3a, 0xe2fec67d, - 0xa70dc225, 0x89243ae3, 0x92bf53c4, 0xd1e36cf7, 0xfc47719f, 0x67d83710, - 0xe0c9d773, 0xaffc9e37, 0xeb3d0cb0, 0x0f670be3, 0x3f04e93d, 0x5f1a656c, - 0x1d063473, 0x982ab2b5, 0xf68f6355, 0xf5f49a57, 0x715cf5b3, 0xc725e710, - 0xeb061ccf, 0xa8e6ab8c, 0x0d3f7a08, 0x959fad4b, 0x738e1269, 0x3c767b72, - 0x4c02fff3, 0x4048ec9f, 0x67d2737d, 0xd9fff7c1, 0x8fd774f0, 0x8d210f06, - 0xe80b33e4, 0xdd96da73, 0xcaddfbfd, 0x825e7083, 0x890929f8, 0x69bf815f, - 0x3b7fffa5, 0xb015fa00, 0x0debf5ae, 0x70f37ef2, 0x3743be78, 0xd64efd1e, - 0xbbe18cf6, 0x204ee5ee, 0xa7be34c7, 0xbaabfbf4, 0xbb62bdbf, 0xc76f46b5, - 0xdeeae826, 0x9d1af4a6, 0x00ff0b5d, 0x1386bdc3, 0x54ab0960, 0xb04db0d9, - 0xda7e07af, 0xf049c103, 0x5ef6385f, 0x79222595, 0x16971464, 0x6385d3e0, - 0x6797fe35, 0xa9ea99ff, 0x048a6f13, 0xa25c8ce4, 0xaea9e550, 0x899bf220, - 0x917d6898, 0xc6c2f6fa, 0x6eb02515, 0x26f9789d, 0x931643f4, 0xc7f82752, - 0x0f3ea4e5, 0x89a7b5e2, 0xf3e418a9, 0x39c77934, 0xad1e4a32, 0x2e9d8482, - 0xe3b7af5a, 0xabaf7fa9, 0xd7d06b2f, 0x525b9297, 0xe97edf60, 0x38049106, - 0xf6fa1bd0, 0xf61779af, 0xacd48cbb, 0x57fb7583, 0xa16bbc6a, 0x5419088b, - 0xf6fd556f, 0x0a32bcf1, 0x71604b87, 0x7a1f6d16, 0x7ff32279, 0x2406662a, - 0x59ffbe85, 0xa95bc8e3, 0x07dfa206, 0xbc7ec1d6, 0x6f713a7f, 0xf7e95d23, - 0xc237e15d, 0x5d03d9ab, 0x3855c3f6, 0x4a73b792, 0xcb1e8620, 0x67263814, - 0x102bbeaa, 0xc7b8ba5c, 0x7bfd4334, 0xd13253f3, 0xde1ed3f1, 0x668c2793, - 0xc0fc03fc, 0xe792ed09, 0xd69ff487, 0x7f82ffa5, 0x68fdff6a, 0xfeba79ff, - 0xfb53fda7, 0xfe05d81f, 0xaffab179, 0x2ff3edfa, 0xa93ea9fb, 0x4e97f178, - 0x13c9d742, 0x9b8a7d42, 0xdb72b5d2, 0x96854ebd, 0x13bf05c7, 0x8044f5f8, - 0xef458e2f, 0x154e0587, 0x41cec542, 0x49fe0ddc, 0xecf93ffb, 0xf11e30cf, - 0x85d136d5, 0xe6edb4f1, 0x61ca99b0, 0x12f2e375, 0x23f58392, 0x19df7eac, - 0x7a4dea1e, 0xfa78abfe, 0x1f902997, 0x8d453942, 0x9ed1852f, 0x79fadead, - 0x5e4fac11, 0x64728ed2, 0xbfc60efc, 0xaffa8898, 0xdaef8a4c, 0x38c4e14e, - 0x8bc55781, 0x6767f1b7, 0x37942778, 0x82fa017c, 0xc7e8227a, 0x572bbf1b, - 0x8235d4ed, 0x8d98f923, 0x190c7bfe, 0xc3517a03, 0x3b30090b, 0x5f99eeb5, - 0x70a11ce7, 0xa6fada9d, 0x97c28b93, 0x83674f26, 0x8f73fe8b, 0x6ddebddc, - 0x6d16f2a5, 0x96eb690f, 0xd7daa4dc, 0x8a565621, 0xf3e42761, 0xdd166e54, - 0xf2b8fa7e, 0x7a9f27f9, 0x7f99e20c, 0xd107bb32, 0xff3c57fe, 0x69e3fbda, - 0x314ec57d, 0xc34d84b9, 0xd274a5ce, 0xbfff4bc7, 0x1e93b73b, 0x4d79bf15, - 0xe7b18792, 0xd27624f7, 0xfdcec565, 0x15d61912, 0xfb83931f, 0x063d88a5, - 0x8a47827d, 0x7ba85ec0, 0x8825bfe6, 0xc7d89e33, 0x18acd491, 0x1afcdcf8, - 0x278003da, 0xaf4aa7a4, 0xde19fa0e, 0x80ba52f7, 0xcbd236de, 0x5522def8, - 0x90bf40bf, 0xfbf94167, 0x07903d85, 0x0dd991f5, 0x617f2878, 0xf3e61395, - 0xf8c35085, 0x537bf1fc, 0x8b959f40, 0x961714fe, 0x13f979ec, 0x5bfe423f, - 0x528ff6f6, 0x9444be30, 0x45ae1374, 0xe79874fe, 0x70b34d92, 0x07894b9e, - 0x71fcb0f9, 0xcb4034be, 0xde29020b, 0xac4e4319, 0x2f939322, 0xd2e250b6, - 0xfe017e79, 0x77efe824, 0xb436c0f8, 0xa024efbb, 0xcea47e0f, 0x580c5a85, - 0xf46160bf, 0x2ebaabfa, 0xa33eb010, 0x7deb77f9, 0x93a7402d, 0xd85495fd, - 0xc112f177, 0xfb83e2af, 0xbfcbf696, 0xd195253d, 0x9e42c889, 0xf75d1dfa, - 0x7873c327, 0xac5445bf, 0xc8efba39, 0xe39d59b7, 0xa7c756af, 0x7ac1c770, - 0x6c4a45fd, 0xd44f35fb, 0xb75d00f4, 0x4a2cf8a3, 0x6ffc99de, 0xbbc99fbd, - 0xe981ff26, 0xfe7ed0c5, 0xf8239330, 0x0a43d60e, 0xdb153857, 0x50e4cff7, - 0x3a3f503f, 0x156f9c96, 0xb7d73955, 0xc285f91b, 0x51f1702f, 0x24e3037c, - 0xdf701d22, 0xfa06e965, 0xf51e947d, 0xaeceb8c2, 0xbc726afd, 0x455bf34c, - 0x9b203ebd, 0xdee81e98, 0x9e23f2ae, 0x53c0c52a, 0x52fc818f, 0x20cbf579, - 0xcc2962bf, 0xcd1dcbff, 0x72a3cfef, 0x935065fb, 0x355ebd5b, 0xaef96dca, - 0xdc9624d1, 0x9377697e, 0x9f4b7298, 0x7b5b94c7, 0xfff9f904, 0xf0d55eb4, - 0x78f00c38, 0x351e274d, 0x3e1dd93d, 0x90f27a8d, 0x8d5e2320, 0x1dfe927a, - 0xf95d7926, 0x8d43e351, 0xab9e2aff, 0x51f402ba, 0x7c6a9f07, 0x1aa7c1d8, - 0xef89761f, 0x6c68f0ea, 0x34fb00bf, 0x96f9ae14, 0x528ed38d, 0x4ed2d257, - 0x7f26df70, 0xaafb8f26, 0xe584f396, 0xf3111081, 0xd5303f43, 0x753b068c, - 0x3d6fdfe2, 0x7785177d, 0x2c8bf13e, 0x445ea02f, 0xb7d2ffbb, 0xf3a04edf, - 0x79e2a799, 0x54fb453e, 0x0239974a, 0x70a38e17, 0x3f8815ce, 0xb7e2113e, - 0x0a34f91c, 0xfae5f98e, 0x4c4dfc3a, 0xa7a7ece9, 0x9fabbff7, 0xb7cb7df2, - 0x1d3f5d29, 0x50bbc844, 0x10bc388a, 0x81d357cd, 0xde7f14ae, 0x00605c51, - 0x5088a9ea, 0xbd77e51a, 0xf3fb3220, 0xa319c2ed, 0x9fc9bec1, 0xf19e2c3d, - 0x7bf460fb, 0x3b3eaabd, 0x41e397eb, 0x650d9fcf, 0xf67b7fa3, 0xac4722d0, - 0x9566d0bc, 0xf7535ecf, 0x5cecda5d, 0xbff94f3d, 0x7da3b48d, 0xc95bb7e3, - 0x82fb18b6, 0x5f4d451b, 0x7fa374ab, 0x8e7f1d3c, 0xe97387ca, 0x51b9f1a7, - 0xf5399b74, 0x4aece084, 0x34fbf807, 0xa1fb0fca, 0x06be05f8, 0x235b36fc, - 0xe231a545, 0xf8a9cf79, 0x6be0789b, 0x0c2dcfcc, 0xc7800be5, 0x8baf3b42, - 0xc9a93c83, 0x143250eb, 0x60789ae0, 0x5347cff9, 0xe21ef63e, 0xeb8f90dd, - 0x3c919d0d, 0x2361fc31, 0xb07fa13e, 0x2e888f33, 0x627bd7c4, 0xebc012e9, - 0x04acb37b, 0x95df35f6, 0xe0b155dc, 0xf5b3332c, 0xbd292e66, 0xbffb8a30, - 0xb3f9bf0f, 0x8a02e11d, 0x9676b38f, 0xff95ddf7, 0x759fdc98, 0x0e5a8171, - 0xf56790f8, 0x71002e64, 0xf9e222b4, 0xe50e04f9, 0xfeb4527d, 0xfe9a6fca, - 0x54f5e43c, 0x89973887, 0x110b57b6, 0xdbd8f809, 0xfb0053b4, 0x289926fd, - 0x6a108f18, 0x8a8ccd86, 0x05111d7b, 0xdff357c4, 0xf80edde6, 0x4cd3373d, - 0xe8652e00, 0x01d82719, 0x512342e7, 0xd79bba0e, 0x5a647c1f, 0x10fd08a1, - 0x3f230fe4, 0x74db2514, 0x499359f5, 0xdba5373f, 0x95647344, 0xeafd063b, - 0xbd67c624, 0xff966fd6, 0x04dbf4cf, 0x5f18dfaa, 0xedfad18b, 0x7df18926, - 0x8d4b7e94, 0xd656dfa5, 0x17c0a9ca, 0xa766f72b, 0xbe575d02, 0x2c4fa4b1, - 0x8fbaf6fd, 0xa86ff7f9, 0xfd6de679, 0x1e1b7ea8, 0x51fadfa5, 0xae2316fd, - 0xa5ea5a3b, 0xcffcb37e, 0xa0ebdfc8, 0xb7cc62df, 0xa69fc558, 0xb5438adf, - 0xfb8adfa8, 0xa97cbaf1, 0xfa4f5249, 0xb397ecad, 0x6dba2eb0, 0xf007f831, - 0x0dedfa0a, 0x38c1cf55, 0x5dfee7a0, 0x3d277d72, 0x3d5bd557, 0x67843ff7, - 0xecadcf4d, 0xd33da1cf, 0x9e990f95, 0xf4c5995b, 0x4cbdcadc, 0xc41cadcf, - 0xbf519cf4, 0x6fd17415, 0x21eafbec, 0x23f47bf4, 0x1b7d7eb3, 0x23992f6d, - 0xfdf42dba, 0x9f3b5912, 0x5a3a3351, 0xd4bbfddf, 0x9f73be8d, 0x3d2e73c1, - 0x823fbbe9, 0x7a841bbe, 0x91c8206c, 0x1c6e3f91, 0xd3e5d368, 0xb1f5f7bd, - 0x79045ee7, 0xfe8f03f9, 0xe62607f7, 0xfafbed27, 0xbb9048d8, 0xaa1e00f7, - 0xf9519eef, 0x47e7d5af, 0x28793a7d, 0x7baaf793, 0x1baafe18, 0xd5df3639, - 0x7586407c, 0xd1176fe0, 0x2f7dbe8f, 0x9b67a3f3, 0xc0d8fa5b, 0x225fffcf, - 0x2bfd25ca, 0x87e28b29, 0x302b1739, 0xce2bb9ee, 0xccfc05b9, 0x80b10239, - 0xd0e0bb1d, 0x7ec0278d, 0x3d71705d, 0xe00bbdda, 0xc8e92279, 0xa1db98fb, - 0xebf6f527, 0xaf9da6bc, 0xf9ae9065, 0x8ccd1310, 0x7157132e, 0x5d59cd81, - 0x5da823f3, 0xc62df986, 0xabdf893c, 0x47cd9ff3, 0x8fe45f10, 0xe5f8cc7c, - 0x72788def, 0xad54bc33, 0xaa78f5e6, 0x89e262e1, 0x2ca4ba52, 0xb72f13a5, - 0x975914bf, 0x39cbed01, 0xf38cb7f4, 0x9c66f0d6, 0xcd4786bf, 0xbea059bf, - 0x24743f3f, 0x86889e66, 0x22f92ee7, 0xf80dde1a, 0x33d34b78, 0x206190d7, - 0x3c981f97, 0x7c0d1f3f, 0x178a7bf4, 0x73ade70a, 0x2bcee907, 0x65e2a3bd, - 0x6148e7aa, 0x24780c8a, 0xf367c035, 0x96be77ca, 0xb377e742, 0x210b9592, - 0x937f59f5, 0x688f103c, 0x1ea3b6b6, 0x9470f8d4, 0x5985c999, 0xf5ef2bd5, - 0x7ae21575, 0x50b9c4d3, 0x3d06c2be, 0x7999e6a7, 0xd7f261ef, 0xbaf7fdcc, - 0x6788518c, 0x91482e58, 0x5d015eb6, 0x86a73fe8, 0x40bc5d18, 0x69cffa17, - 0xe020fda4, 0x73993abd, 0xa6fde187, 0x3f02f79d, 0xcfa56ebd, 0x39cbce41, - 0x0e8616f7, 0x65ca7a7b, 0xc58858f9, 0xc8cc18c7, 0x173f5ceb, 0x5d897bc0, - 0xe68993ed, 0x8e00f796, 0x366e5489, 0xfd00c3c3, 0x46fe8a2f, 0x07c8c5fb, - 0x7503e53d, 0x2ab9efc7, 0x3a075f9e, 0xeddf01d8, 0xde43d812, 0xb47f5b30, - 0x1720af76, 0x3a34de22, 0x65f5d134, 0x2983a314, 0xd66f9e06, 0xbd9e2aea, - 0xef844e21, 0x6ffea06f, 0x7ebb0712, 0xf8d41f5f, 0xc5772cdd, 0xd215c413, - 0xe806f4a3, 0xcd7de8b7, 0x11b7a6ea, 0xa6ae375f, 0x15dc99e6, 0x407d1a5f, - 0x6f0e5e0f, 0xd34fcadd, 0x61799891, 0x467e55df, 0xb3f2f599, 0xe6fedacf, - 0xedab8870, 0x90af50e5, 0x7e2e8250, 0xecccd330, 0x07ab6696, 0x0dfdbcf9, - 0xee45bdd1, 0xa8a67faa, 0x257f0174, 0x64e27cfa, 0x4de80898, 0xa67c9597, - 0xe3007bcd, 0xe0f5e8b7, 0xe907ab75, 0x33ff5dd7, 0xedfecccc, 0xead31ece, - 0x9078c3d7, 0xc7eb28d7, 0x5a47ae33, 0x79a7a95c, 0xbf71d479, 0x71b4bcef, - 0x84beebbe, 0x3c60b497, 0xd89fdb4e, 0x89767bc3, 0x73163f60, 0x0a107dba, - 0xfe6fee39, 0x59bffa13, 0xff7ddd1a, 0x530a3f10, 0xe3bebf3c, 0x9f638c49, - 0x34c8f67e, 0xaf159f90, 0xe542c4f0, 0x838775af, 0x889e5984, 0x45427604, - 0x5dfb8f23, 0xcde70844, 0xa833b288, 0xf1f0c327, 0x5ef503a2, 0xa0732ec5, - 0xf15f7e84, 0x103967f2, 0xc35d6b7f, 0x59ff9ff4, 0x91fd1f95, 0xa807c81c, - 0xbcfed810, 0xa88f3e91, 0xb76a79fc, 0x6fe80e6d, 0xc73b3b6e, 0x2d9c115b, - 0x0ce2a39a, 0x16459bf7, 0xc36ddee7, 0x33ff6c3c, 0x0331e61c, 0x48e7d17c, - 0x53d0fcb5, 0x5cbd30cf, 0xe00624d1, 0xf6c5703c, 0x1710ad9d, 0x8cd0f8af, - 0xfb77abf6, 0xd3ec0919, 0xcf3e2fc9, 0xf1371bce, 0x976878ba, 0x3e76e438, - 0x59f8866c, 0x01ea1563, 0xf5823f5a, 0xfbf71aa0, 0x15b2718e, 0xd97dee2f, - 0xe2b8514f, 0xf13b4f37, 0x36cb705c, 0xb723c627, 0xa05f7e5f, 0x7831dc4b, - 0x9c771abf, 0xf5c105fa, 0xf1dc7621, 0x2127caa4, 0x48ee3eb3, 0x3c6127b6, - 0x5799c292, 0xd17e231a, 0x5fcfffc1, 0xcdf60278, 0xf2faed4e, 0xf2bb8009, - 0xfc4f739b, 0x2a93e294, 0xdbac1720, 0xc3df67de, 0xbbed067d, 0xd27d55f7, - 0xb8d3ccfa, 0x27fad34f, 0x6b7a1bb3, 0x2645fbdd, 0xeeb453ec, 0xe2053afc, - 0x4ef7abb8, 0xf56d7f41, 0x4953934b, 0x2b407f0c, 0xbd037f81, 0xd23227d8, - 0x39b1b9ad, 0x4d3ce013, 0x77eb0ee9, 0x58393c47, 0xb2f4e2c5, 0x11de471a, - 0x4bae5f7b, 0xc671b8dc, 0x3ac1d7cd, 0x65ba28de, 0xf1f88bd2, 0xe1cf4a61, - 0x0ee3a0bd, 0x38209f75, 0xe3f1b2f5, 0x4a0ff0d3, 0x7d660baf, 0xe342fe1c, - 0x0c7cff92, 0xba931ada, 0x7b871f8d, 0xdf6d3f81, 0x2159bf6f, 0x5da39016, - 0x1edc61cf, 0x0f7d47e8, 0x85fcfad2, 0x1cbb884c, 0xc0efdb17, 0x66bdebfc, - 0xd8aaa3cc, 0x53ca01fb, 0xe36f4beb, 0xf7511abe, 0xc7495adf, 0x5127db1f, - 0x56ef3a7d, 0xab3b8b07, 0xb4b88074, 0x6ae7c4ec, 0xb5f199fc, 0x2eee9716, - 0x32d63d1e, 0xabbfed80, 0x5b5591fb, 0x43112cff, 0x0b1b9fbc, 0xd9723af4, - 0x0f0d547d, 0x98c3c02e, 0xd896fde8, 0xfd8efff1, 0x80dd0316, 0x758f609e, - 0x7ad0a7ec, 0x07ab883f, 0xed620fb8, 0x666eb5df, 0x62ad34fb, 0x6d45bcec, - 0xc5a465ff, 0xe812efb0, 0x4f4bbedd, 0x78aef8f3, 0xb42706ca, 0x9d7c574f, - 0xbf5b14ba, 0xd4e16adf, 0xe7be037b, 0x67257ebe, 0x05981bcc, 0x78d5597c, - 0x4a7b0244, 0xf9b4df5b, 0xe7fd529e, 0x78f2cf53, 0xb05d644e, 0x51bbf519, - 0x1613547f, 0x5bc23437, 0xab7a616e, 0x1fad89ba, 0x023976a7, 0xa9cfda76, - 0xaf91bb03, 0x911c77ab, 0x83bfb4fc, 0x45237fdb, 0x60acf2a2, 0xc14408fd, - 0xfd85ea7f, 0x897f6c39, 0x71c6ebf9, 0xf1c752ee, 0xe38f6286, 0x374671dd, - 0x507f0ace, 0x2e7ee762, 0x4149de3f, 0x9dfd0d99, 0xe409116c, 0xf20c9ffd, - 0xe31881c5, 0x5a88b5cf, 0x0fc98b3c, 0x1cf1475d, 0xbb9d83a6, 0xb42513e4, - 0xc63b57bb, 0xfde7087e, 0x19243b57, 0xb57517e2, 0xeeb52f2c, 0x4069dcdf, - 0x5b84baef, 0xdeae3f71, 0xb2575f80, 0x1ae21f2b, 0x51d2c2ae, 0xbd46aec0, - 0x7498a093, 0x1476aff0, 0xce14caa7, 0x469daab5, 0x0b9e3704, 0xc5459de5, - 0x65de1f30, 0xec635972, 0x52f6883b, 0x8bc289e2, 0xe39fd2e8, 0xca469724, - 0x7f968fd0, 0x39696953, 0x052e8d88, 0xb1858c53, 0x99fcddec, 0xdb779c2e, - 0x507fd50e, 0x614aec88, 0x8eb06479, 0xcf8aedb4, 0x43f1c321, 0xb47e50a2, - 0x1db9cfa9, 0x5e83f7fb, 0x4a24eb5a, 0x8a339502, 0x86cf9955, 0x2c23acf3, - 0xe9f0365c, 0x857aff99, 0xf10d6bf6, 0xd9b457e8, 0x25527cb5, 0x46cce401, - 0x41bcc41e, 0x936fe560, 0xe634e13a, 0x25781213, 0x298d3eea, 0xa1fd1dbc, - 0x7c589bb3, 0xff572780, 0xcf8b027a, 0xafc00091, 0x542b2fae, 0xe212cf38, - 0x3bfbc30e, 0x580f181c, 0x9422c6f6, 0x3443a01f, 0xf58a92be, 0xac1b5ee7, - 0x67f01cce, 0xbf555a36, 0xc0b4afc6, 0x6ac59b39, 0xf54a7dbf, 0x18a962e7, - 0x975e41fa, 0xe5faf2a8, 0x9843a2d2, 0x8a59e68f, 0x8e753e7a, 0x31acdcfe, - 0xaa204b4f, 0xfe601c9f, 0xadbc9773, 0xb708cda6, 0xc56b7f31, 0xc35d7d76, - 0x37a027e3, 0x127402af, 0x80e2e5fb, 0x3237e23d, 0x4613d7f8, 0x9afc777d, - 0xb5f8f4d3, 0xdafc7aca, 0xa7f11886, 0xadc3afc7, 0x97e697c7, 0xf8df8776, - 0xc873fab1, 0x8afc2aff, 0x548ed556, 0x4aff4af1, 0x654c292d, 0x42e9dc03, - 0x28c2e518, 0x30f61947, 0x9feeff07, 0xafc5a81c, 0xefd40edc, 0xb87cea69, - 0x1b3becc5, 0xf00f11c8, 0xe08e51ba, 0x79e82024, 0x75d8f91b, 0xfac40acc, - 0x4d7b7c8c, 0x355cf4f7, 0x0b23d5fd, 0x809b57e9, 0x3f23877f, 0x89bef3b0, - 0x05975024, 0xc176ea72, 0x59f41dfa, 0xb8458bdc, 0x17b885f7, 0x5efb820f, - 0xa43e585c, 0x0db4abe6, 0x306e7825, 0x029f3e18, 0xdca1e9fa, 0xf7a069f6, - 0x29484bbc, 0xc51fc1e8, 0x0f03f3b1, 0x38bf65a8, 0x85abd549, 0xef824c6f, - 0xe70ca243, 0xdb42dbd5, 0xdea0832c, 0x2a3de3c4, 0xabfa84de, 0x90d6fc60, - 0x6c5ae0c8, 0x38820c09, 0xc7115ec8, 0x013c5d6d, 0xd87665cf, 0x2f96216f, - 0xccfa16d2, 0x9f4a28b9, 0x7a3d36b7, 0x36b9c415, 0xa9e7629a, 0x7e9ab14c, - 0xec1bfad8, 0xc537b792, 0x1eeaf2ca, 0x51e7401a, 0xbaacfd3d, 0xb879330e, - 0xabf3a556, 0xf9c46f4b, 0x64e214bf, 0xf88a4758, 0x461a6edb, 0x3dee39e7, - 0xb0cf8d41, 0xf528e578, 0x2fd03afd, 0xdfeb5fa8, 0xddc3e9e5, 0xe7020547, - 0x2cd546f4, 0x15eb7f45, 0xca73e527, 0x704a7917, 0x616df024, 0xcdef0128, - 0xd04c7ef1, 0x22dd1fae, 0x4f33f8e8, 0x22f3575d, 0x44c05e54, 0x3edf50f9, - 0xec18222e, 0xfc0f00a0, 0xfd71ed75, 0xd55685f3, 0x149272ee, 0x970df3e0, - 0x5ef20e78, 0x7b89dadb, 0x6dbb850d, 0xa3845f71, 0xfa9c3ced, 0xbe25e5a5, - 0xbf7ad638, 0x62f8caca, 0x9d7044a3, 0x8ed4b8d9, 0x4b03c5f1, 0xf580ae2b, - 0x7b1fabfd, 0x8e7588ae, 0xc53f4a3c, 0x252c7cb3, 0xfe058c9e, 0xbc31cb5e, - 0xc697a7d7, 0xf8d7f7c8, 0x8d6fe359, 0xc697d3af, 0x35e56279, 0x7665637e, - 0x21d2c15a, 0xdafe049c, 0xe38f0e3e, 0x5cf1aeb6, 0x9f8ddcf6, 0x7800c9ac, - 0xd0e74dbc, 0x3884b6ee, 0xb1bd9625, 0xfec4eac1, 0x6bf8d75b, 0x2eef8f21, - 0x27a09c2a, 0x0377efbb, 0x813f5bfa, 0x677c2ca0, 0x73c32fa9, 0x642c4bbc, - 0x85bbc40b, 0x1c5bf4fa, 0x6f93ffc0, 0x7de14758, 0xeb84d4ac, 0x8dd146eb, - 0x08abfbf0, 0x1a83f8c1, 0x8d37edcf, 0xcf3e8e6c, 0xff3584fc, 0xc7a52b59, - 0xd21756b3, 0xe6e3c925, 0x3ff77e00, 0xf209dbfe, 0x8cd176dd, 0xfaabec74, - 0xaf77da43, 0x36dd9959, 0x0ad94e33, 0x64f293df, 0xc7b71394, 0x123c5ee9, - 0x78a04dee, 0x4ea3928f, 0xbbf1f9fa, 0x71d50f44, 0xbb449e14, 0x2892f909, - 0xc5d2ec8a, 0x4728fd29, 0x30905c9a, 0x4d8f2047, 0x885cabd3, 0x1ca83b0b, - 0xc3d8b28c, 0x962477e0, 0x105379d3, 0xfac2c4ac, 0x754e116b, 0x3cc6cb9c, - 0x7997ca79, 0x608a3870, 0x71121448, 0xdf4d7fa1, 0x6d7a7a6a, 0x59794102, - 0xa810b0fb, 0x126cfda3, 0xaf885622, 0x01722964, 0x0a251aa4, 0xef179e32, - 0xff304e5f, 0x78fd96d2, 0x42dd8742, 0x37c47e85, 0xfb5882fc, 0x869c7c79, - 0x401fcf2f, 0x6a1ce46f, 0x8de6003f, 0x73c6cadb, 0x3b4166bf, 0xa87f43bd, - 0xba9158f6, 0xdcfb8efe, 0xc209f2c4, 0x3ef44893, 0x687f519b, 0xebb8c9f6, - 0xbf606b22, 0x189fdc68, 0x055bb49c, 0xcead1bbe, 0xa89f43b7, 0x1098e6eb, - 0xfbf427d5, 0x66c8d0dc, 0xf72b07b8, 0x5dc72663, 0x3f21c9f4, 0xbefbf80f, - 0x17c8c47a, 0x2e54c223, 0x32a1f6d5, 0xeae1a7dc, 0x19fb43a8, 0x9e49de83, - 0xed152a3e, 0x8cdf955c, 0xdbe4d678, 0x77b9f728, 0x0ccd9bbb, 0x1a47e62e, - 0x275c21c6, 0xe836721c, 0xb078b7a5, 0x29f2dbf7, 0xbf5c281e, 0xf4a3f902, - 0xb81f384b, 0x21bfe601, 0xe415bd74, 0x27af7be4, 0x5475fa21, 0xbcd3f69e, - 0x0fae3e27, 0xc04e27ae, 0xf3fef543, 0x46127aea, 0x01c8777a, 0x78e89395, - 0x46ffc689, 0xa3e4d77e, 0xc8de2e0e, 0x047673c6, 0x0b9e59d6, 0x663065e2, - 0x7805c9b2, 0x3aedecd5, 0xfe25bed5, 0x56ffb474, 0x1eba88bb, 0x4f800665, - 0x5ecd44ea, 0xe3a25b77, 0x051dab53, 0x4fdb97a9, 0xfea45ef5, 0x1b39d459, - 0xfe8ed0af, 0x84a2f79b, 0xfe37bfcf, 0x7914289a, 0x898dfc3a, 0x7f15dd1b, - 0xb08471f1, 0x9ffec2fb, 0x230cdf9f, 0x7727dc7f, 0xe25aefce, 0xf5422579, - 0xf5aade47, 0x3f193675, 0xd7969c39, 0xfb682f55, 0x01e9dd9f, 0xa98fbca3, - 0x70c66fac, 0xeef20f4b, 0x25f8a9b5, 0xb3e80664, 0xb76a61f1, 0xff957564, - 0xbcfceaf3, 0xb6f78636, 0x8307db5b, 0x3de7ad3c, 0x2f687135, 0xb0264c46, - 0xb413762b, 0x8ffbdc7b, 0x5bde513a, 0x4feb7492, 0x8fc0bb57, 0xa7d9a9f2, - 0x7c6a5d9a, 0x552ec3af, 0x3e2d1bd7, 0x795135ca, 0x193cf0a1, 0x1c03f1e7, - 0xbfe62e75, 0xd05701c2, 0x3d584f63, 0x365fc075, 0xd838973a, 0xce12192f, - 0xb096f162, 0x93bb3e4e, 0xde419b47, 0xb03f1482, 0xfae9f9fe, 0x1eeb8837, - 0x0971b19e, 0x85aa5e0c, 0x97e9bec0, 0xd560d847, 0xfbc7f304, 0x6bfbb0e5, - 0xfbb2e5fa, 0x31c73732, 0xa18b65fb, 0xfa5ac27c, 0x144bcc18, 0xfb9cdf88, - 0x5006e1fd, 0x64f90e21, 0xf800d29c, 0x382b14b0, 0x71170c8f, 0x19de9473, - 0xbc839042, 0x994ac489, 0xd247f163, 0xfb48ffb9, 0xf39128cb, 0x06323f81, - 0x9a373c12, 0x9e7d8a11, 0xf13895e8, 0x8debd987, 0xbcc1ce5d, 0x41cfcaa2, - 0xa937ce89, 0xe9839d84, 0xf050fb88, 0x8eadbf01, 0xadb2715b, 0xab3ed817, - 0xd9e1813f, 0xc101bfe8, 0x5a825e60, 0x822257bf, 0x2bfd1135, 0xdfaff03f, - 0xcaff4164, 0xd041dc46, 0xb1c41fb7, 0xce3aecf8, 0xbfea1ebd, 0x702dda10, - 0x37268fcf, 0x343c3c9a, 0x40b716e1, 0x775e755f, 0x5f7c0736, 0x00ef172a, - 0x9c275b9e, 0x6716bc1d, 0xf8c99ed2, 0xf975e14e, 0x9afd1af6, 0xacfd1d44, - 0xd6895710, 0x08690ef3, 0x5cadedd8, 0xaafc1b9c, 0x831ce5d6, 0xe7a8b397, - 0x3cdd0411, 0x1fcc6cd3, 0xe7f55369, 0x90b2e3df, 0x84f5b51f, 0xc63d6fce, - 0xe8f30d7f, 0x386a8738, 0x973c6a77, 0x11dd969a, 0x7cc74a07, 0xee0952dc, - 0x43672332, 0xbce3b436, 0x124cf6ce, 0x6a64bce3, 0x5cf31ac4, 0xbc5256b0, - 0x4b780d7d, 0x40126b15, 0xcedea71f, 0x1f1188f4, 0xc47f9c6d, 0xfb47d841, - 0x1f331883, 0xd2d32b45, 0x4c584a6e, 0xbf4b4fdf, 0x79ed4b01, 0x19885d83, - 0x71b24c57, 0x64dcec3f, 0xfc18b103, 0xed1b24cd, 0x9de7b4ef, 0xff1415f7, - 0x37bb8c76, 0x37bc31c4, 0x37bc31c4, 0xe53e1a48, 0xcebf9078, 0xf7975bba, - 0x4967c1b4, 0xd10f2010, 0xb9f28e9f, 0xdde8c5c4, 0xf682bef9, 0xdca21f4d, - 0xc4941730, 0x436c9106, 0x21f167be, 0xafc87ced, 0x4024cf7c, 0x96db94be, - 0x16fbfaa5, 0x0604df46, 0x530df9f7, 0xb214dc70, 0xe2983ac6, 0xc9a96979, - 0xd3a3710d, 0xc2723f0b, 0x1985e991, 0x0f20792d, 0x1b8f79a7, 0x984a97e6, - 0x8e6cb85f, 0x2ed30814, 0xc2a81b93, 0x01ba7462, 0x4ccb3bf7, 0xc7aef331, - 0xe9fed8d8, 0x961738d1, 0x90d36969, 0x92f59d4e, 0x8c4bf004, 0x35e54a7c, - 0xcea8f17d, 0x6f94cc73, 0x790c5b14, 0x1349136b, 0x185beb87, 0xb1ac95f1, - 0x35b7aab3, 0x39064979, 0x52ab7d84, 0x3a3547aa, 0x4d5f500f, 0xfe28b8c1, - 0xbfd7a171, 0x79c37f06, 0x45ea015d, 0x10c88e4d, 0xa0ade7a6, 0xa1e2a377, - 0xe83f7b6d, 0x9f8efb0f, 0x0739dbfc, 0x55fd3bec, 0x9e807768, 0xbbcf7e3d, - 0xf4c7380e, 0x2e2c3dc9, 0x4fc18772, 0xfa63645b, 0x74ad8f7f, 0x8177e01e, - 0x9e791fef, 0x77257e28, 0xe593fdb3, 0xde70de01, 0x506f7f5d, 0x70c93055, - 0xf11f908f, 0x1fdea55a, 0x46c7a466, 0x2cb78b1b, 0xca59b1df, 0x4f7c6190, - 0x5c7f8c25, 0x378f43f5, 0xd1dfd03a, 0x63b859e0, 0xd9be0484, 0x7566435f, - 0x6445bdff, 0x025287eb, 0x151e67fb, 0x0f38466f, 0x2f6af7aa, 0x8fcb25f9, - 0xdd63a329, 0x27b0f54d, 0x187bcec4, 0x13e4b1e7, 0x129528b9, 0x1cfdc96f, - 0xfef0ddfa, 0xf33d743d, 0xee1f7ddc, 0xd9e719b3, 0x051f5ef5, 0x2a65b3fd, - 0x6de78dbd, 0x3ed88597, 0x41e262f8, 0xfe72ecf9, 0xc5cec436, 0x678de318, - 0x00db650f, 0xa9b0bf0f, 0x323cc4f1, 0xef6dce06, 0xfe20343a, 0x9f56f772, - 0x828bef52, 0x3ca1bb7b, 0xce5823ee, 0xe2902303, 0xf6f432bf, 0xd55fc05d, - 0x3ef13b4d, 0x8faaefb4, 0x9c2742aa, 0xe9ad4b90, 0x6e876a25, 0x8b20f903, - 0x5a7d9d39, 0xc49cf9bd, 0x9f866afc, 0xb7e7d4db, 0x20723e01, 0xd9fe5bdf, - 0xdbef4a04, 0xd1f3c52a, 0x6f3da5f7, 0xf7c3efd3, 0x3cdabe76, 0xed6b79b5, - 0x9c5e6a55, 0x0e4d3bf1, 0xb97ca9e6, 0x75f4eb78, 0xea8a297d, 0xa9917ef6, - 0xf3c3939e, 0x2d9f1a42, 0xe945a523, 0xa349f831, 0x84df076f, 0xd3f38e7e, - 0xbeb8bae8, 0x3f83c54c, 0x4c4fdd4d, 0x91957883, 0xa73a7a8f, 0x32462add, - 0x7c8dbe41, 0x7dcddad2, 0xb31b2128, 0x4acb162f, 0xa8cfc411, 0x15cebbf9, - 0x171cdf65, 0x14fe0fea, 0xe32b6ee4, 0x083d0efb, 0xf7e8314e, 0xff5c4537, - 0x54e43a57, 0xe90fffb8, 0x13f20e37, 0x4f787ecc, 0x4f98e71b, 0x808a0651, - 0x4f2c62ff, 0x81954afa, 0x97db3a83, 0x04e73c6e, 0x086dbbfb, 0xab51b8c1, - 0x69ef0f43, 0xe37a8f1b, 0x4a8f4ab4, 0x3f9be5a1, 0xdadace83, 0xc7177982, - 0xa771a92e, 0x58e2e64b, 0x39d8b4f3, 0x7778bddd, 0xf9a872a8, 0xfa540b35, - 0xfb6211dd, 0x4d370be9, 0xc9747a47, 0xa1fd54bf, 0xf50e46b2, 0x4b3e918e, - 0x3e63d7dc, 0x3e40a2da, 0x5e85df7e, 0xbba441e4, 0xda776e91, 0x371eec5d, - 0x7b8246a1, 0xe26d8eed, 0x8571ff70, 0x73ff7b10, 0x9df4ddb6, 0x479c63e6, - 0xdb2ff077, 0x2faebb5a, 0x908ff981, 0xf08dcf80, 0x425ff36b, 0xd4a7a614, - 0x2f3776f9, 0xf2c49912, 0x7f75d434, 0x815b9c39, 0x790793fd, 0xc6adcf96, - 0x35f834a1, 0x28f38d78, 0x7cf12be2, 0x8f035b41, 0xf877d979, 0x77067dd9, - 0xfd70e5ac, 0x9a4e8eed, 0x7bf6d15e, 0x30ca9baa, 0xfb43cb6f, 0xedb63b01, - 0x29f6c263, 0xcf7873d6, 0x0cf4b75b, 0xeea57cb1, 0xa30849e8, 0x374a62db, - 0xdebb3ff0, 0x0caf909f, 0x0a27de8c, 0x8c0ca0dc, 0x4122b7de, 0xb15957cc, - 0xf9eeba7d, 0x8e35768d, 0x9ef5eaa5, 0x24d48fe4, 0x696f8cc4, 0x9fc9a6f2, - 0xda778f26, 0x0a6f6665, 0x59198381, 0xd1879f80, 0x7afaa1bf, 0x3df99d9e, - 0xafa5cd0f, 0xa73c6f54, 0x3258a7db, 0x096bd196, 0xbbcf825f, 0x0f14bbd3, - 0xd8bdbd3a, 0xf8c3cfae, 0xe6d1f3a1, 0x3689c9a1, 0x189ca33f, 0x43d237bf, - 0xe919ef8b, 0xc007a462, 0x5bc67e09, 0x35816d7b, 0x38b7ce14, 0xaf7fb706, - 0x4d6ee115, 0xb9c0ac9b, 0xf9f4eacd, 0x3e01fe58, 0xb0fb074c, 0x768eceb4, - 0x8d87eaae, 0x225c5dea, 0x5ecbb557, 0xd9232ab2, 0x24d2a7b9, 0xb58993e0, - 0x17161991, 0x583e8f21, 0xa4f7045c, 0x32387c4e, 0xbff14203, 0x5646f07e, - 0xd77916df, 0xfcfb86e2, 0x690a8a4b, 0x2fd071fd, 0x95fa2fa0, 0x6efbe0db, - 0xf973c4eb, 0x1fdeccba, 0xcf9d2e65, 0xed66b1ee, 0xb33ed495, 0xf2aef5d0, - 0x4157e0f0, 0x4a5b2b7e, 0x542e218a, 0xba781109, 0xce2955de, 0xad872db0, - 0x7be9e3fb, 0x4f3cd91f, 0x76ee21d9, 0x8bae2d71, 0x94058795, 0xc588722f, - 0x573a0567, 0x6d6efd2b, 0x2993b51c, 0x5a26d77e, 0xd317e0dc, 0x97f07ee7, - 0xb22a26d7, 0xa35cf51c, 0x70077c1f, 0x7cb135ac, 0x0c6ffd82, 0xc65c8f8e, - 0x23efd82e, 0x34cfe025, 0x1a582cfb, 0x1725f3db, 0x37c8e79e, 0xb18978b1, - 0x76bb6dfd, 0x00ce49ae, 0x243ea8be, 0x1fc3fca1, 0x84559fd8, 0x613549c9, - 0x0eaad0e7, 0x53773c13, 0xcf08a87d, 0x84b9c0dd, 0xe07a754f, 0xa6ee735f, - 0x9e18af93, 0x44ae040a, 0xd0b71a88, 0xf9d5d56e, 0x9810d354, 0xdce3e10f, - 0xcf846e70, 0xa2ecd530, 0xa0afe7f3, 0xe087c525, 0xff70f372, 0x89e4fd4c, - 0x559fdc3c, 0x2d79aa27, 0xbe3e7626, 0xe557dd63, 0x39fb2b4f, 0xdd028f4a, - 0x25b1ff4f, 0x53f6c6cf, 0xe6d6afd0, 0x8429c75b, 0x35ed7f03, 0x7219e782, - 0xe0334993, 0xb19446cf, 0x47166fc0, 0x6c97caa2, 0x65fe9b3f, 0x9b36e940, - 0x7e53237e, 0x9fc1faff, 0xe3bbff22, 0x68b2ab4d, 0x59f8739d, 0x2e74c33d, - 0xef30b28b, 0x6bf565a8, 0xd006e74c, 0xc358e8ba, 0x4af1b0ea, 0xa3b33e17, - 0x143fc8ae, 0xba3171c6, 0x01ae50ee, 0x2c4c16fe, 0x901c23ae, 0xcb477f70, - 0x794b5957, 0xe2d1f806, 0x5d747a60, 0x3673c16d, 0x28179b88, 0xec4fe432, - 0xfa41ef51, 0x5786a5be, 0x7f4266de, 0x7fc04a09, 0x53e183bc, 0x54690ba3, - 0x5e3c81ae, 0x81ae5412, 0x0e7ebd7d, 0x7e83a24f, 0x96adf23f, 0x1bcfa089, - 0x0f28f9df, 0x82bf73ef, 0x2df233f5, 0xf9d243ea, 0xff6dfe9c, 0xe4fbd1cd, - 0xa9f91cfd, 0x03251df0, 0xec9cafda, 0x3951b722, 0x2c8853ac, 0xad9f8365, - 0x091b2ff7, 0xd91f4fd3, 0xa070af4a, 0x3ae3093e, 0x67bb13f6, 0x7e8dd400, - 0xec496933, 0x949dde55, 0x17ee3773, 0x7d346625, 0x85d610b8, 0x4a7bb1df, - 0xfcc14538, 0xee3b17d3, 0x9718236b, 0x373891b2, 0x9b898dc4, 0xd453f9a4, - 0xf1899af8, 0x945e7255, 0x87ceacff, 0x79085f7e, 0x2c6c63f2, 0x8fce81bf, - 0x823afd07, 0x848e58c8, 0xa0365938, 0x3df583d8, 0x4fe1f824, 0x588fff69, - 0xb2ca7c59, 0x8fe2e89d, 0xb7160e65, 0xe2c9c079, 0xf062718f, 0xe22bb016, - 0xd81710ce, 0x4b8f6d15, 0x0bcfee02, 0xdf709bae, 0xe309a0ee, 0x018b4fdc, - 0xb517ec17, 0x5bc8255f, 0x6d7f6748, 0x7eb5dd2a, 0xabe4911f, 0x0bf7ee20, - 0x9d3fab27, 0xbb8f304f, 0x801484fd, 0x0cc4dcfd, 0x3c744d4b, 0xd9839e69, - 0x1573bfbb, 0x043a04cc, 0x1811c6f7, 0x38becc7f, 0xb9e3d013, 0xe056b91d, - 0x4701178b, 0x66890f14, 0x5fd09dd7, 0x6f0a39e2, 0xf9673e16, 0x223c82fd, - 0xfc77e29e, 0xee19768d, 0x1ada7ad1, 0x56f311bc, 0xbde1379f, 0xee4a2fc1, - 0xf17f50e9, 0x3d02ecac, 0x305674fc, 0xbcf3e70e, 0x62f3e709, 0x2bd5fb5c, - 0x0c0fdc29, 0xc12ef161, 0xcfd00446, 0xbe40a982, 0xae5f3e93, 0xafa6b1f2, - 0xd11c8137, 0xc11c23fa, 0x29820c73, 0xcb48e51f, 0x276b6a27, 0x67d44f98, - 0xfc0f0b66, 0x8b5d371c, 0x8879853b, 0x25284d17, 0xb04dcf68, 0x05ce788b, - 0xbce199f2, 0x0f5544db, 0xb2b8fc4f, 0xbb07e584, 0x9ebdc30f, 0x7ef576cd, - 0x739f7530, 0xd727ca92, 0xa16f0891, 0x245dd7ed, 0x4d27886e, 0x8fdfa8ba, - 0x5f60ca78, 0x57fb514e, 0xf0855dda, 0xede89f38, 0x450d29bf, 0x2c3d6027, - 0xfc008a20, 0x6862d934, 0x09d23b07, 0x9febf0f7, 0xfd50e03f, 0x19924cdc, - 0xeda6c79d, 0x87e14d43, 0xb5fb446e, 0x5e037258, 0x0f95da76, 0xdfc03f20, - 0xc5cb9222, 0xb1f29f25, 0x1721c37c, 0x2cae046d, 0x8769fca4, 0x50dd5cf9, - 0x79d2b7ef, 0xf5903d5f, 0xfa087c0f, 0x93c7cae5, 0x8fdf4093, 0x95a5e957, - 0x7f01df1a, 0x7f19e2b9, 0xca7786b9, 0x2c8ed3e7, 0x37934f7c, 0x67e83be0, - 0x1f98188f, 0xf29bbf6b, 0xafc0d3eb, 0xfd04ed3b, 0x5ba59fb8, 0x699c80e6, - 0x7caab4e3, 0xd5d72c6d, 0xbf0fdcae, 0xc0bfe4fb, 0xbec28dd6, 0x75e8a517, - 0x83024fbf, 0xcfd72bd7, 0x68790698, 0xccf31176, 0x5173d452, 0x1e92fcd1, - 0xdf1a2fc5, 0x9c59dab5, 0xc99fe348, 0xe1e5dfbb, 0x840be4f9, 0x8748b2b8, - 0xcff1a2bf, 0xf7187f44, 0xe6122781, 0x67f9189f, 0x93fc3757, 0x40165e7f, - 0x9fe1756f, 0xba7f8c43, 0x0fda1be3, 0xe4616bde, 0xaa1c779f, 0xff2dddbd, - 0xfcf3c25c, 0xbe4ef7ab, 0x93657eec, 0x6a9f9f4f, 0x62d9c72c, 0x54bb2fe7, - 0xea96efbc, 0xbd01ca6f, 0xcec4d531, 0xe32409ef, 0xeeef0a16, 0xfcdeed38, - 0xefa86c9a, 0xda1e9814, 0x1ea33219, 0x78f769da, 0x669b7e30, 0x0557e761, - 0x23ce044f, 0xe45afbb8, 0xd921dfe8, 0x587660ee, 0xfb8f0c50, 0x37f1ec02, - 0x9d8c1f18, 0x2a43cb9a, 0xa662fa5a, 0x971d4617, 0xcfefc336, 0xbfccea3d, - 0x06967c00, 0x79dfa3b8, 0xcf784a8f, 0x0951f552, 0xf76fe3f5, 0xf1045dbd, - 0x79cf2d51, 0x8bb79ecc, 0xfbc2860a, 0xa1fedf8c, 0x8ead65ea, 0x5f404047, - 0x1fddee1a, 0x4b1e71d7, 0x297e6f7f, 0x674e51f0, 0xf93ef1bb, 0x3fdb1c60, - 0x11644d99, 0xb4719886, 0xdeb85ef4, 0xfcaf78cc, 0xff3b30ec, 0x27b0f336, - 0x2af2bdf6, 0x37ef187f, 0x8a77f6a7, 0xe7efec13, 0x6841f65a, 0xdd6cc884, - 0xd7354a0e, 0x26a33f30, 0x9349f81b, 0xf8a3fc43, 0x44327e0b, 0xb706bbf7, - 0xd07ff3a9, 0xa9fbb02d, 0x4bee1222, 0xefb09cfe, 0x363aea82, 0x40f4c9ca, - 0xe617eaee, 0xcb239c03, 0xcba06695, 0xd7162eb3, 0x5b0905f9, 0x6e6e81b2, - 0x8253f701, 0x0bf93ca2, 0x223df3ae, 0xd3b10e94, 0xe27d3df6, 0x8ff8c246, - 0x9c633d3a, 0xed099f60, 0x31bbe087, 0x824773e3, 0x588fb71e, 0x9aeb049b, - 0xab853706, 0x13bd9b78, 0x81ae0d0e, 0x8f97c64e, 0x00c6cb3a, 0xd03be01e, - 0x8e474d4b, 0x8d7be059, 0xcf7b821f, 0xe2883e30, 0x4e83e00b, 0x4016e0be, - 0xa283c35d, 0xfdb7cfae, 0x8b42f88b, 0x17c8f46b, 0x7e70b710, 0x0b98be2f, - 0x05f23578, 0xce3ce7b5, 0x505cf618, 0xc6937962, 0xe7b13fe7, 0x896efbe3, - 0xd913de60, 0x6bbf6567, 0x7dc049e8, 0xd8b8df90, 0x1c9f6d98, 0x28a6a4cb, - 0x7664e559, 0x2a3bf6bd, 0xda1cc223, 0xa2a8239f, 0xbced0db8, 0xdd27a87e, - 0x31c8fe2a, 0x46fb838e, 0x033e3731, 0x1270d0ec, 0xcc236bd8, 0x87906125, - 0x1989b65d, 0xdae63f60, 0xfcc36426, 0xfab21e5f, 0x5ed2584d, 0x9bfe5bee, - 0x7da772ad, 0x66c3e9a5, 0xfc6d5bb5, 0x4c7f2a35, 0x2779d852, 0x70d1ebd0, - 0x9003eb68, 0xc2e0e009, 0xdadf4db3, 0x22878f50, 0x00936f14, 0xfd878a0e, - 0xfb04691c, 0x24a4df21, 0xb03b064f, 0x3800584f, 0x9d7ef6db, 0x92cef109, - 0x021febd0, 0x3eda25bc, 0x0fbf5bac, 0x35b7b46b, 0x3ff3487b, 0xf3497b34, - 0x82aec17b, 0x1fd532f6, 0xbed99971, 0x05b084d8, 0xe47853ef, 0xa2957cac, - 0xe740b3ca, 0xe3cea251, 0x7082d266, 0x4ca9f769, 0x7251f153, 0x39abfa88, - 0x54c84ed0, 0xeaa9878a, 0xdd532a7d, 0x6e22fbfa, 0x3efb1b1e, 0x9e9fad15, - 0x1bae37de, 0xa3f61ad7, 0xc879687e, 0xf94feec7, 0xc3f98fbd, 0x7ef007e3, - 0xb1dfd601, 0x09feec59, 0x21c3c317, 0x763af629, 0xf1eb9551, 0x9c0e48a6, - 0xe7bfdec7, 0x1e6eb8ef, 0xf7f7f3d8, 0x771c8ec1, 0x97902042, 0xa8c4fe3b, - 0x180fcc78, 0x695f232b, 0x6f3f7afd, 0x9cf611b4, 0xccdeff44, 0x728f0a41, - 0xc167c025, 0x8f5395f2, 0x9dfd0a3c, 0xe8902a3f, 0x92451f73, 0xe5c42067, - 0x1ddfd48b, 0x7b31c83a, 0xa83f6b4a, 0x11c7defe, 0x21216f95, 0xc567bb43, - 0xa9e7451c, 0x1a1ffdea, 0x2f1ea75d, 0x74e4213e, 0xfdfc0fa5, 0x5a10e233, - 0xaa9ce1fc, 0x9ff3490f, 0xf5ce7cf0, 0x600a778d, 0xc69f5fbf, 0xdc6a2513, - 0xe9ea641b, 0x4e21c547, 0x6ff60d3a, 0x4e8f33f3, 0xb7e5bc83, 0xf4814c78, - 0x99be7686, 0x3e16f503, 0x462abde6, 0xba1f5efc, 0x9955ef13, 0xa3e4cf1b, - 0x5fc7f1a7, 0x3864f94d, 0x3b309dd0, 0x4bdd8f30, 0x81efa462, 0x1491ff3d, - 0xbe3dda19, 0x91bfa3bb, 0x2a9caf0e, 0x9eac7dc0, 0xdbe461e8, 0xfe9e747d, - 0x5377e12b, 0xbf8fc42d, 0xfac2ea9b, 0xac34beab, 0xddeafc6b, 0xd81264fb, - 0x4e9f1a79, 0x337c6249, 0x49a3f76e, 0x2f49dec4, 0xc586de23, 0xc97ffe33, - 0xee25d9aa, 0xa3e8d359, 0x843ae977, 0x2d27ea8c, 0xaa563790, 0x70fb3ac2, - 0x4425da11, 0x5c62cf3d, 0xb7f366df, 0xda75014d, 0xccfeefd3, 0xf57acb94, - 0x6fc5397b, 0x0eb00bd5, 0x99ab0916, 0x78ed531e, 0x9d231e0d, 0x08a523df, - 0x19f0777f, 0xe708c0f9, 0xf6f91d4b, 0xda07ae0a, 0x18cce0ef, 0xc6262598, - 0x8f868798, 0xc7ae8499, 0x8f5fbdd9, 0xdbd78c6f, 0x178ee7ef, 0xdad011fe, - 0xe919bc9d, 0xf4d76c66, 0x900c1147, 0xec1fa58b, 0x29f1b993, 0x8ba2df48, - 0x3ae85112, 0xcfe9fa43, 0x2b9293f5, 0xb956df91, 0xf8eeb3d8, 0x4f22faad, - 0xf93b233c, 0xd87a6c4e, 0x5bb77c06, 0x1c41b7a8, 0xf4fb3af5, 0xc2bd103a, - 0xe2660bcf, 0x131115fd, 0x94dad081, 0x886699d0, 0x243f7833, 0x20a1be78, - 0xf0327fb4, 0x0b42abe9, 0xe76d59fa, 0xca387909, 0xd50a6cee, 0x6b2ec0d9, - 0xf3e7664a, 0x5d10260e, 0x78c5f4fe, 0x8e9a6fa6, 0xc4a69d9e, 0x62ee1f68, - 0x28833cfc, 0x9ff439c9, 0x7f29eb45, 0xc7dc1f80, 0x42927181, 0x325afdce, - 0x39732dd8, 0xf6da23f4, 0x992d798e, 0x7b7adbc2, 0x2999ea02, 0xe9ddf74d, - 0xfe0884a2, 0x6f3e2463, 0xfef0e32f, 0x8dd92284, 0x59c5a2f5, 0xf98df7e8, - 0x09466926, 0xa220dfb4, 0xaf8533df, 0x755e2014, 0xabc38d3a, 0x9170f63c, - 0x623df85a, 0x0e3674ff, 0xc093f971, 0x24a77d3f, 0x66fe0469, 0x07d5ac9e, - 0x122eefe1, 0xfab6ff83, 0xcdfb73a5, 0x2cf57db4, 0xa78df30e, 0x3f8832b8, - 0xd68a7f8a, 0x5baf384b, 0xc005a942, 0xf58a33d7, 0xaac31ee7, 0xd4ab393d, - 0xfbd10246, 0xe50b9cf9, 0xfdb5a0fa, 0xf11dfc56, 0xf98122bd, 0xa37e7269, - 0xe7b3efca, 0x9bbee924, 0xa9dd984e, 0xaa4dd5c9, 0xfaa8ddfc, 0x193d73cd, - 0x094bf1ba, 0x40fe87b3, 0x64810bda, 0x7ed8b8f7, 0x96f6b4f4, 0x25e1f3c3, - 0xd068dfbe, 0x310d3787, 0xe57cbdf8, 0x348be45a, 0xc8f78dce, 0x37edf5b8, - 0x8dd7d58f, 0x0fd46bf2, 0x8f8b20b3, 0x3427aaef, 0x2f6b307d, 0x683c422f, - 0x33c53e56, 0xbb7ac5da, 0x317d27bd, 0x7d1bae26, 0x17be4971, 0xfa2e90cc, - 0xefe2e3e2, 0x4b7e2fa5, 0x54b196dd, 0x578edfae, 0xa4fecdd7, 0x298de83f, - 0x81478efc, 0xbae8da8f, 0x47c18e69, 0xc5a3bada, 0x1ca88a01, 0xc5381ea3, - 0x5ca663f6, 0x91fe274c, 0x0e80719d, 0x12ed423d, 0xa97b0c77, 0xe51b3e35, - 0x68ef43ab, 0x2eca257a, 0xb87ef311, 0xda85325d, 0xc02e52a3, 0x2be10fd7, - 0x2925ef52, 0x882b8482, 0xc19da61f, 0xa0579038, 0xcfae2cfe, 0x817f224f, - 0x3b12e3fe, 0xaf68c3e5, 0x0ae87168, 0xe94f6697, 0x1e23a5f9, 0xc3dd9339, - 0x1149f1aa, 0x7fe413e0, 0x04fb8f26, 0x7fd41bff, 0x8000b303, 0x00008000, - 0x00088b1f, 0x00000000, 0x7cc5ff00, 0x55547809, 0xf579f096, 0x55492d5e, - 0x146caa92, 0xb612f08b, 0x84582484, 0x5916ec80, 0xa014a358, 0x8168cb80, - 0x9a126b0b, 0x69ee9c71, 0x0242a6ff, 0x83b74343, 0xe8cedad2, 0x3ad857f4, - 0x08b41a83, 0xd09d0301, 0x584c5015, 0xf82e0834, 0x1a6d1ad9, 0x84490ed1, - 0xbfbb46d6, 0x739cffcf, 0x2aaa4bef, 0xffff4d85, 0xb49fdf3f, 0xdeefb97d, - 0x67b9ef77, 0x979ee73f, 0xb3559bdb, 0xf6e008ad, 0x14078a99, 0x77f1d000, - 0xe042c022, 0xadacc37f, 0xc78ef016, 0x69fcd7be, 0xe7f80d87, 0x9c2ffc3b, - 0xa42cfc90, 0x900bcf50, 0xce54b009, 0x7d57fc5f, 0x3c5e3d33, 0x52fe7a27, - 0x92b9fd98, 0xf81b700c, 0xf71c30cd, 0xff8ec5f3, 0xc7154bec, 0x7e8b2e97, - 0x4a4ce99e, 0xff8790bf, 0xbe230118, 0xd4ca0153, 0x22b79dba, 0x5527ddbc, - 0x334c558f, 0x390ffed1, 0x350ffec5, 0x7c800c97, 0x1674df80, 0x3db1f8a7, - 0x1c2111b6, 0xd1bad00d, 0xec71edc6, 0xefc5f107, 0x3c66e7e8, 0x21fc059f, - 0x52b4b607, 0x4801b721, 0xc4ed1805, 0xff602745, 0x0d3f9e2a, 0xc02486c7, - 0x5c2473ef, 0xe7af00d9, 0xf104e798, 0x5eb8c3bd, 0xe30dd700, 0xf75c01fa, - 0xf72746c8, 0xe6e8db5f, 0x442e0dfe, 0xfac0066a, 0x37af2714, 0x8776f72f, - 0xe35bdf1f, 0x50e7e6cc, 0xf844da3e, 0x7b2fe036, 0x1004086a, 0xac77afdf, - 0x807494d0, 0xb1e2b72a, 0x01d1f566, 0x8e58e34f, 0xbe25cbf3, 0x102ab72b, - 0x1fe5e7c4, 0xc4072bae, 0xee33575f, 0x2aa9f887, 0xfc368355, 0x63d34967, - 0x0cdf453b, 0xdefa08d6, 0x33028e22, 0x86cd16b5, 0x28f02cfb, 0xf1f7151e, - 0x6ff78936, 0x1d412af5, 0x278b79ff, 0x63871e9a, 0xae58bee8, 0x0ffe80b3, - 0x47305bdf, 0x9d718609, 0xdfa29305, 0xd6757c5b, 0xfed8cae7, 0xe898b47c, - 0xbf3fb63e, 0xb7744edc, 0xc1863fe3, 0x95fba230, 0x8d6fa58b, 0xc5ba3e85, - 0x8e74b1b6, 0x9d16bf1d, 0x673a27ef, 0xc6ce9b5c, 0xce8b7ffb, 0x904e110f, - 0x1bf470be, 0x30049e8b, 0x1a07e9bb, 0x55f679d1, 0x32add78d, 0x861433ce, - 0xd4fe79d2, 0xb76ff859, 0xaafcdf42, 0xfe2d2fa6, 0xe79f6b82, 0x22bfed6f, - 0x69fde745, 0xdf7e6f5f, 0x8034f3be, 0xf9ce78c1, 0x8df8d139, 0xbd2c6ba5, - 0x62f7ca16, 0xe635b5e9, 0xa05d061c, 0x60689913, 0x555fbc1c, 0xd16b8e19, - 0x162e97ad, 0x7e4f08ff, 0x5f8071ff, 0xd6fab9f3, 0x76827493, 0xe02057cd, - 0x03c84732, 0x052075f2, 0x0ade5be9, 0xec0444e1, 0x3e738b96, 0x28f5a8d7, - 0x39c469f0, 0x8353e7e8, 0xfadf6ace, 0xb2075765, 0x96fb19fc, 0x14b01069, - 0x972173d2, 0xd255f0b1, 0x7e69233a, 0xcb68f980, 0x10b2d32e, 0x05ba639e, - 0x9b51f5ee, 0x4e03da28, 0x9d1a07a1, 0xfbb75e26, 0x6e099b2b, 0xf0e57804, - 0xf8406280, 0x09e7563c, 0x33218bd2, 0xc945fbf0, 0x9cdfcf3a, 0xdc048104, - 0x9b76b41f, 0x2b44f90f, 0x3941c806, 0x825906d3, 0x9d64b835, 0xdc91f616, - 0xa8347b75, 0xd1bbb946, 0xe048ef78, 0x6c92402e, 0xa99474fe, 0x0fde8b26, - 0x79c54fb7, 0xfa6a1537, 0xb2e29c36, 0xf1a03fea, 0x93ab66ae, 0xf83eebde, - 0x5a662dcf, 0x20f02be7, 0x335af084, 0x4f8e1532, 0xa4839873, 0x93d4ca37, - 0xddfb09aa, 0x8fa4003d, 0x970b2da6, 0x3a6dd200, 0xb138d7b4, 0x8c74429d, - 0xd0bfbf43, 0xde843379, 0x9a74881a, 0x4334e921, 0x6692abea, 0x4946f595, - 0xac841a92, 0xb374fd3e, 0x408cd1a4, 0xee0a497b, 0x3c53433b, 0xf9bfd835, - 0x8fc516aa, 0xba3e932f, 0x951f4fb1, 0x3dbdf5c9, 0x019686ba, 0xff344266, - 0x3d0a3596, 0x798b6254, 0xbe0fed2e, 0xe6557cc9, 0x429f1e8c, 0xfbf913ba, - 0x825e8c62, 0xa653fb18, 0x03b935fe, 0xc58af0f1, 0x8454defb, 0x19b4e7bb, - 0x70e7c59e, 0xfb933b11, 0xc631a7e3, 0x07b6c51e, 0x757a270f, 0xe215eb84, - 0x07f50723, 0xd7b1f579, 0xa3b63f9e, 0xf18e98a7, 0x0d22dd4a, 0xcf2d99b2, - 0xf0fb33ba, 0x92bf0fde, 0xad78b10e, 0xdbde7a97, 0x8e8d7ce8, 0xad8f0fdb, - 0x979ed8b3, 0x48d749fc, 0xf8bdfdf5, 0x95e5e434, 0xe25e890b, 0x0c2e57ff, - 0x4afdb2f2, 0x0c3e59d2, 0xfe783879, 0x51e92272, 0x21aea7c4, 0x6cb8f49f, - 0x9f99679e, 0x06841c85, 0xc36e0a8e, 0xc12485fe, 0xf624aff7, 0xbc23cf1c, - 0x3cf262df, 0xeb68db4b, 0x202a2f87, 0xd175b9fd, 0xe2803379, 0x2887e505, - 0x84ee8a4f, 0xa00db1bb, 0x05ff113c, 0x72482152, 0xd0108662, 0x785e35be, - 0xd319da9a, 0xfbc214f4, 0xddb35c65, 0x29e9eb41, 0xd7f0f7c4, 0x057d132b, - 0xbf5ff1fd, 0xee1a7c11, 0xe6d1b0d3, 0x1c2f50d3, 0x7ee4e8d8, 0xb73746e3, - 0xdcea3687, 0xfc913a6e, 0xaa1ff243, 0x169f16bc, 0xa5e657a1, 0x0330fd0a, - 0x35c10ef5, 0x00609403, 0x23c66f79, 0x7288f2c0, 0x10a4dc10, 0x393cf0bd, - 0xfa44f87d, 0xe888ee5c, 0x3b56ad43, 0x82a59321, 0x67985ee9, 0x09d1f7e2, - 0xd59f3e08, 0x3fd23e7f, 0xfc8cbfaa, 0xefc38416, 0xb0b996f2, 0xb37c390d, - 0x7adf885d, 0x4bd1e965, 0xf4b9fdc0, 0x43b95ebc, 0x8feb84bd, 0x1f84cf0f, - 0x8f18bda2, 0xe2bc2184, 0xff045dcf, 0x100b1684, 0xb2b0d07d, 0xf21a167c, - 0x5ca2b5f9, 0x8448fdc0, 0xef8c1bbe, 0xc4c3cb59, 0x23a0074f, 0x645ef08d, - 0x7e49d9f3, 0x3f04b997, 0xdddb9578, 0x3937ae0a, 0x0951e2c3, 0xf1bee1b4, - 0x2d7f11eb, 0xce21b819, 0x1cc9696f, 0xb713e7a2, 0xc93ef1bd, 0x08e6d7b7, - 0xcc986cab, 0xf6111d9d, 0xe33c007c, 0x74927f24, 0x476877dc, 0x0e4e3f5a, - 0x6abb9eb0, 0x6b5e9209, 0x09ec933d, 0xafd33ee3, 0xacbfd8da, 0x6e5117a7, - 0x8f26270f, 0x42133d65, 0x63f2430d, 0x6d98e713, 0x3c23aff6, 0x7a3e65a0, - 0xedfbdf0a, 0xafd20065, 0x543fdbd3, 0x312d0fc9, 0x40e80ee5, 0xa32a8f38, - 0xf27da853, 0x6e7ce4e3, 0x127724cf, 0xec9b0e7e, 0xcefbed3a, 0x0474bd46, - 0x8da9cbf2, 0xf9023a50, 0x368dade3, 0x746f4f6e, 0xa3667b72, 0x38a3db9b, - 0x3af3fc4e, 0xbd7f138e, 0x6fd4e381, 0x4f6a71c3, 0x7ad43ae0, 0x489872df, - 0xe5bc677e, 0xbc2da8d0, 0xfadb892b, 0x742c933b, 0x50c9c38e, 0xfc4fec67, - 0x370c4e14, 0x2ee50780, 0xdb53fdd5, 0xad3f680d, 0x1c6502fe, 0xf754d4c0, - 0xae3a6d5c, 0x8fe87b3b, 0x19f1c2be, 0x6a7ec3a9, 0x3b6f7843, 0x893868e3, - 0xf5c7d2fd, 0x3f883a9f, 0x92a2244f, 0xb7643c24, 0xc7365179, 0xc418d293, - 0x24c2f768, 0xfd19a7ec, 0xc8a5b9ec, 0x3a4a4b0a, 0xb005c0f2, 0x73e1b1f3, - 0x25df886d, 0x513fff76, 0x9b6812df, 0xfa9d3a53, 0xbc927010, 0xcb20e62b, - 0x7d2510fb, 0xadbfda11, 0xd4c4ff0e, 0xabc07f08, 0xf48d21fc, 0x02af44c3, - 0x77a674ae, 0xf7d2a470, 0xd5b798dc, 0x15313651, 0x2ed7f7f9, 0xc269f995, - 0x741bc534, 0x635f97f4, 0x7af384de, 0xe26fd129, 0xd4b559c5, 0xe2e3982e, - 0x4dd96fbe, 0xa5ff24b5, 0x5fbd6b8e, 0x5c87efc2, 0xc547d666, 0x638bce1a, - 0xe3798d17, 0xffc8c991, 0x0c4b69ee, 0x7d7c4b3e, 0x84935fd6, 0x567732fd, - 0x34752aa1, 0x6bb5df70, 0xbf978d1b, 0xe572c0de, 0x59e8f249, 0xa5ed8ac4, - 0xd33e3869, 0x24c278a1, 0xa93ed32a, 0xa771a34d, 0xcdb421e2, 0x553b8ef4, - 0x5423e344, 0x9fea4ccf, 0xd89d4bd5, 0x4e66d19e, 0x66f384bd, 0x6c78a4e7, - 0xf099def8, 0xff10ae8f, 0xf249ccce, 0x1714e824, 0xa4ae9f04, 0xa9eac7be, - 0x8f1ce9d6, 0x3ad32495, 0x6131e2ba, 0x92d6febf, 0x147045ff, 0x514052fb, - 0x91a5dc68, 0xc7e4fb1f, 0xe275293f, 0x0aa1fabc, 0x099cfc90, 0xe091fee7, - 0xa89ad99f, 0xf5402027, 0xbd296716, 0x9c516f57, 0x2befb89b, 0x5181f9a1, - 0x5c79fd66, 0x769de4f7, 0x6fe507b6, 0x745fb3e5, 0x6cc1cef2, 0x9adfca17, - 0x49ed4c56, 0xcbdbf093, 0xc39f2adf, 0x930826e3, 0xebbf2952, 0x1dbdf81f, - 0x4d293f25, 0x0c4ff5c7, 0x416eb173, 0x116a953a, 0x83e70d7a, 0x55dfef42, - 0x945bf3c1, 0x8f3a3f01, 0xa7e4aff3, 0xff715a14, 0x5109e959, 0x710ce7f3, - 0x8de7f545, 0x45aa5818, 0xfcf2b1d8, 0xadfea8ac, 0x88e94a45, 0x69bef988, - 0x45fd5109, 0x11d2aea5, 0x2b6ff311, 0x5fd5181f, 0x54565b72, 0xb269a67f, - 0xa11b1fd0, 0x7dc854bc, 0x9bfb2979, 0x0a87acd9, 0x1bee629d, 0x8e3f7e38, - 0x7f09b617, 0xfe85d0aa, 0xb4a5d214, 0x80fd88ad, 0xc68f7c36, 0x8f52ec8b, - 0x3ddda005, 0xfc80ec91, 0xf62fe209, 0x6677658b, 0x6305fa3b, 0xb768ae89, - 0x752fe023, 0xfaf1db44, 0xcc27e144, 0x0bad7f01, 0x75a739e9, 0x6557fb1e, - 0x6145d5e9, 0xbf467c20, 0x2a370b1f, 0x13779dd1, 0xac6ab61f, 0x890ce737, - 0xd4adafd9, 0xf48c7ec1, 0xb7c8e6ef, 0xe0217d8c, 0xc6ff276d, 0xffb18738, - 0x4733ceb5, 0xe17ec69d, 0xacd73adf, 0xa9a5859c, 0xcf5fe171, 0x9c2c4cfe, - 0x4f32a979, 0xfb15fe81, 0xeca9ad85, 0x7a4fe22f, 0xf0c13f3c, 0xcf51ca7f, - 0x9cf522b9, 0x585f4943, 0x673d6d70, 0xff2d7bac, 0x78d758cf, 0xde54ea1f, - 0xf7bf78df, 0x7fc4aeb9, 0x27e71bbe, 0xae9e79c5, 0x5cfe7fc4, 0x9a19fcf4, - 0x7940e35e, 0x278a0e3e, 0xa93f7840, 0x959ae46b, 0x52d6f59c, 0x5fa1f65b, - 0xf670b723, 0xb52d40f9, 0x27833b53, 0xb9fe78ad, 0xf94eaa39, 0xea2fc307, - 0x0aa56717, 0x55f8e47f, 0x78e3aedd, 0x53b7407d, 0x88ff51dc, 0xaaf8a76e, - 0x28730bde, 0x370ef48e, 0xc438a7ad, 0xf62d879b, 0xfa154def, 0xdf7c857e, - 0xfea90f68, 0x857f0415, 0xf251e3ad, 0xe9bf2a49, 0x1c5f10b1, 0xbf2f7f27, - 0x5c77bfbf, 0xbf683a0b, 0x1d048fe3, 0x7e7d08be, 0x22defebd, 0xe20ca662, - 0xa917c553, 0x096c4a4f, 0x51fd48be, 0xf54574e6, 0x83ff93c7, 0x0f76cdef, - 0xae6f7a8c, 0x0f35159e, 0xf21cd8fd, 0x902c6a87, 0x353e91a3, 0xcfc87a25, - 0xefe3c58b, 0x0e3df9e5, 0x6051b927, 0x7f55d74e, 0x29e4fb1c, 0x7d8bf811, - 0xc4553dbe, 0x9ec88373, 0x52273ae3, 0x556b6e75, 0xd0e6709f, 0x887e267f, - 0xbaac63ed, 0x95c3d68c, 0x1e77c4dd, 0xba0ae9bb, 0xe3d2f0e0, 0x686ae7f3, - 0x4de33dff, 0xfb1c38ff, 0x215f1ec7, 0xfb4d53fa, 0xfadfb1b2, 0x7fa27df8, - 0xd9bc69a3, 0xb819ec83, 0xf9296e7f, 0x7fbee90b, 0x9b75fa27, 0xd4155b1d, - 0xa8099503, 0x4cd5b0d7, 0xf7a6140a, 0x2ddbc7c5, 0xc0915f68, 0x175e6cc8, - 0x156ec0d2, 0xc26574f1, 0x13d920d0, 0x13abd8ad, 0x0c132ade, 0x9264777a, - 0x09da879d, 0xdd9d7151, 0xfbe1ef82, 0x0bff3665, 0xc9c26f82, 0x87a5ea3a, - 0x200d960e, 0xea9138fe, 0xede43c64, 0x7d26ea9b, 0x21edf085, 0x01fffefb, - 0xf078e6be, 0x3ec59ad5, 0x2579f59d, 0x86f38f64, 0x3e947921, 0x3a6a15fa, - 0x21084f3f, 0xeebfb0ef, 0xb1fe5375, 0x90f165c6, 0xf2427eff, 0x35b6f5ef, - 0xdaa18f32, 0x29a91f05, 0xb17bf5a6, 0xcff25b7d, 0x6a2fb919, 0x910ba1be, - 0x33d9c03f, 0xe8815174, 0x6aa87f13, 0xe1f90f61, 0xe490ff3d, 0x83f9f8a1, - 0x183f8144, 0x8fd1f3d2, 0x777bf9f1, 0xf1b679e7, 0x65a78173, 0x0e9aecc1, - 0x06b38fec, 0xe3fca06f, 0x47ff34a1, 0xad3b8784, 0x87cc91c1, 0xb449f58e, - 0x8e05e28f, 0x0ff88c53, 0x32dd3ce3, 0x705c7fbc, 0x46c1fded, 0x64e96576, - 0x7f637781, 0xe88db1c4, 0xf124def1, 0xe10780dc, 0x303e26e8, 0x0785eae0, - 0x8f393886, 0xd4ff2200, 0x2e8be325, 0xa7ec8f5a, 0xdc7910ea, 0xff38983f, - 0x8ac24552, 0x4de77dfd, 0x791a0f1c, 0xfb1022e0, 0x49b53e4d, 0xf803e065, - 0x96a2513b, 0xcb5c695e, 0x7684fdf1, 0xf6fe262d, 0x2a9d3db2, 0xd5a9bfdf, - 0xf6a0e25f, 0x5379e8fd, 0x093f1c65, 0x59c52a82, 0xc6623b93, 0x467fe71b, - 0x18bd4feb, 0x4d293cfd, 0x3041c3da, 0xb24f3228, 0x974dc641, 0x10a7664f, - 0x2b186b1f, 0x8b0f48a8, 0xd4a4c2ae, 0xb0d33d3e, 0x4959e711, 0x2db8da9f, - 0x8fbceb38, 0x88dc69f6, 0xf49a3f0c, 0x435b9baa, 0xc2ce0aee, 0x623630bd, - 0x0617291f, 0x2fbf2f1e, 0x23ae38f0, 0xb0d397e7, 0x43356e6f, 0xc3c3ef50, - 0x0c2f8914, 0xbbfe38df, 0xf6c1d17c, 0x62db626b, 0xead9e495, 0x711e8136, - 0x113d04be, 0x6c7d08f4, 0xea8d49cf, 0xb59e92ab, 0xca7ed109, 0x924fb978, - 0x7ad45067, 0xd062bf86, 0xacea50f3, 0xc663f256, 0xdfb1563b, 0x3b293292, - 0x93a2fd6a, 0x042ef8d1, 0x63e2979f, 0x71c087cf, 0x5ab3c4c0, 0x29327f94, - 0x63f983bc, 0xcfd187d2, 0xee8f9ca7, 0xfcc9a697, 0xaedd2c56, 0xfb184f85, - 0x7fe969cb, 0xde5d3e3f, 0xcda67c68, 0x8667c689, 0x039f1a2f, 0x6be34596, - 0x1f1a3fa0, 0x898d5783, 0x7d61bf1a, 0xd87f5461, 0xcd44a70f, 0x198342cf, - 0x75be1fd9, 0x91fcd45e, 0xf545163b, 0x67753f47, 0xe0dcfcd4, 0xbcf1a88a, - 0x2efe6bdd, 0x368417fa, 0x3427cd44, 0xfe87be9b, 0x4bfe3637, 0x53ff7ed4, - 0xa18daff4, 0xe7d256ff, 0xa85e8813, 0xecfb0b37, 0xa425b919, 0x6f4d5d3f, - 0x9b79437c, 0xf9ceb140, 0xf03cc0aa, 0x2fd8e0d4, 0x7a429f54, 0xdaa2306e, - 0xd6a37a84, 0x1ec8ab04, 0x71326a3c, 0xf390d31e, 0x3f84d317, 0xc89a62f2, - 0x7b78197b, 0xd922ed1a, 0x43ea5541, 0x248efa73, 0x935453f2, 0xfec9da09, - 0x1fd61e69, 0xbe101ce7, 0x0755f719, 0x4ac5e701, 0x982d2792, 0xbea8fc88, - 0xa9fc72a9, 0x8e83f20e, 0xe4e6a4f6, 0x9f8453ce, 0x4e9b0e2b, 0xfaa6ab7c, - 0xf0df6403, 0xa1e7a19c, 0xdef39fbf, 0xf1495846, 0xe65fd196, 0xe699bf5e, - 0xe67bbb2f, 0x7b7f8a48, 0xacaddf9f, 0x43a08d2c, 0xc51739e4, 0xa40eabf1, - 0xd867fb09, 0xdc7ec313, 0x3a6bd569, 0x538c3ed0, 0xbb407d85, 0xf10d2071, - 0x88f281f1, 0x0169f859, 0xed1f9d33, 0xb827df2a, 0x80df21d0, 0xdd9f4a6d, - 0xe643bfd2, 0xda3b20fa, 0x00937d6f, 0xf74438a3, 0x1de33df0, 0x955dfe86, - 0xecbbf8cb, 0xf97f9e88, 0xaf02e1fe, 0x90f620f7, 0xe22ce70e, 0x17fc063c, - 0x42fe5ea5, 0xd24ee5ea, 0xebf911c7, 0x2676bb55, 0x2e7e7f91, 0xc6e3f847, - 0x3a49dff3, 0xe54d2eff, 0x9dddaff3, 0x047cfeb0, 0xae422ade, 0xe3557ea8, - 0xf991f5c0, 0x39c6b5cd, 0xe7468afc, 0xa8e52758, 0xf923b5a2, 0xfe7f604e, - 0xb75c34c3, 0x7b95d772, 0xa6fbd00e, 0x67614c9e, 0xd2dfbc03, 0x82e380f7, - 0x28817fa5, 0xcd33b6bf, 0xa67570cc, 0x09613889, 0xbbe44e36, 0xb803e825, - 0xda637da8, 0x7c3fe22c, 0xbfb0561e, 0xa4cc15a0, 0xb3fa16bf, 0x33f484cc, - 0x3f6779e0, 0x69cfed1e, 0x1b73ef3a, 0xfb7ef8f8, 0x922a7bdd, 0xd6340fd8, - 0x8141d633, 0x3def3f20, 0x499cc057, 0x0ae99f79, 0x9fb817fb, 0xeefb9e8d, - 0xec99bc1e, 0xbbdfb1b0, 0x0ef4bfe0, 0xf022c5f2, 0xfac6baf0, 0x1134d740, - 0x4b03f97a, 0x44ed1d2f, 0xa66d0dbf, 0x3685e530, 0xbdf2b39c, 0xcf75774a, - 0x9c230fcb, 0x66f9af1f, 0x7f7082bf, 0xbfe7bcb4, 0x3bf3e00e, 0x4741529e, - 0xfdd9f1be, 0xbc447a5a, 0x2bfeee79, 0xafe86f2c, 0x2924ff3c, 0x1eac97a5, - 0xd60f9392, 0x322a34bc, 0x9f4e485e, 0xf74e9099, 0xe2d2933b, 0xc6c46fde, - 0x3f886ba5, 0xf6757e59, 0x5cbe0d4b, 0xc372f92d, 0xf9f9a30b, 0xf3dea486, - 0x2af3fe88, 0x3436c1e7, 0xf1af395b, 0x3587e48e, 0x31337e2f, 0x8f57cf32, - 0xa95ba97c, 0xf74b7275, 0x09fa3aa6, 0x1e5e4efb, 0xeaab71cb, 0x1e73a2cf, - 0x3269fabe, 0xf9bdf7f5, 0x6e079f2d, 0xbbf83ebb, 0x78917911, 0x79ea4aae, - 0xc54af497, 0xf94eab01, 0xb90392ac, 0x7ec2ee27, 0x1fea2b65, 0x5725cf3c, - 0x29a7b1c7, 0x00a83b1e, 0xc32ab7e5, 0x2be4ac09, 0xe520941b, 0xee34d6c3, - 0xfb1832dd, 0x1616ea6b, 0x2556bb11, 0x59567d0b, 0xb13704af, 0xe9873e1f, - 0xa365285c, 0xbfee50e4, 0xd778e3e5, 0x85feb171, 0x3cf6b08d, 0xf55d9dc6, - 0x38205e5f, 0x395a35d6, 0x292176cf, 0xfb8c196c, 0x84abda5e, 0xdc9f7a02, - 0x1c44b976, 0x98f42ab6, 0xf55df685, 0xe411c2dc, 0x381d7636, 0xb93d216d, - 0x59b1e1aa, 0x309179f2, 0x8b9641ff, 0x9595bbb5, 0xd5ac7991, 0xa4420ee8, - 0x02f842fd, 0x40eafb13, 0x2cfa494e, 0x435e1a6b, 0xb6bd42e8, 0xf58569ff, - 0x97e242da, 0xf9ef0e0f, 0xdf686fdd, 0x923dff83, 0x7d745ff1, 0x805f07f8, - 0xb94a8bfd, 0x633c5c0f, 0xb2b2f8a1, 0xde217cc1, 0xba6352fd, 0xcfda1eef, - 0xfd638f88, 0x10162dee, 0x10d93ff7, 0x82ec9e7c, 0x1cb2c7a3, 0x9a57f9e1, - 0xce68f080, 0xec0acb1e, 0xc8ce48db, 0xc11db85e, 0xbef57178, 0x84f18d74, - 0x78fac4b1, 0x3921a0f7, 0x5877a25e, 0xe9579f28, 0x5f10b4ee, 0x173f8657, - 0x9f8dfff7, 0x89c6f2cc, 0x574e5fb7, 0x273f33a4, 0x6437de4a, 0x30b9618c, - 0x90c3daf7, 0x60bee58d, 0xa9d90f45, 0x3b91070d, 0xbfb7a214, 0xec0ee087, - 0x7ce9d04f, 0x9f3e0725, 0xcfb111d8, 0xf47ca51f, 0xf95e59e6, 0xf099ac64, - 0xb193efb9, 0xf3df525a, 0xaac74cae, 0x97997978, 0xdedd85d3, 0x18bbec9c, - 0x9e09072d, 0xd95bee30, 0x147be764, 0x2d2d8394, 0x70729145, 0xc45daac7, - 0x07aa4de7, 0x1b2a0225, 0x79abfa17, 0xc887927e, 0x0cce36a3, 0x4eaa1f10, - 0xfc27f31f, 0x289bf715, 0xff508fef, 0x3ff74dcd, 0x39ac724d, 0x1e646560, - 0xf1d4d2a4, 0xe88516ab, 0xa26bc3ba, 0xf5810afd, 0x75f0ea96, 0x94553c70, - 0x7bdc53a9, 0x202cc274, 0x59bcfd3c, 0x39afbce1, 0x8b35bfd5, 0xe55c7be8, - 0x2fa396f9, 0xbbbee804, 0x11141c6b, 0x7f79c67c, 0x2a0c2e3e, 0x00b9b3ae, - 0xe6edb43c, 0xc4dd4b83, 0x38cf3fbf, 0xdd867ec6, 0x2bd20213, 0x503fe835, - 0x1f9ec7de, 0x093ad30a, 0x1522be39, 0xee9359f7, 0x58b4be64, 0x27ca1efd, - 0x36fb203d, 0xe08ab7cd, 0x8a27a5b3, 0xf5c87bf8, 0x48baf9e5, 0x6f74cdfe, - 0x4b7ce7e9, 0x69f05997, 0x71c00dd7, 0x4cfcd722, 0xe32f21a6, 0xb83b06cd, - 0xd6546aad, 0x44d7da46, 0x79e8dbf0, 0x1ea5c1d7, 0x2d9cdf82, 0x91333df9, - 0xff7622e5, 0xa99f888f, 0x62b4c0ce, 0x99e1166b, 0x9ff7a6f0, 0x7be4a1f7, - 0xf9a01f03, 0x115e4873, 0xfcbc6f54, 0xf8bd3f92, 0x7375d12c, 0x95c72faa, - 0xc2bcd7cf, 0xc6277629, 0xff9c3b95, 0x31b7c901, 0x89f095bf, 0xfcd16fef, - 0x51efc236, 0xc5b35f89, 0xfe593ba7, 0xdfed3a7d, 0xf141be7b, 0x3c8df7cf, - 0xff6c96df, 0xcfef9ef7, 0x54e67cf2, 0x2f5a37e4, 0x399e7819, 0xfe201839, - 0xa2824dab, 0xa8f8f84d, 0xe49b966b, 0x6f91cb6e, 0xd7bc9286, 0x40dc7926, - 0x9be6b179, 0x6fdc9196, 0xf3277419, 0xe42f17ff, 0xfb11aa16, 0x7f17a724, - 0x2f3be745, 0xe2c5b1cf, 0x7c73a1cf, 0x9c69cf2c, 0xefba496b, 0xf911e92f, - 0x7e921826, 0xd7b3fc5d, 0x7194d7b8, 0x61da479e, 0x8f38f38c, 0x5c890dd8, - 0xfa57b67f, 0x98f81ae1, 0xd1e0ec7f, 0xc2f2bfd9, 0xa92baa09, 0x36c13169, - 0xb5253e3a, 0x92fdee22, 0x0c119355, 0xb2186d7a, 0x8d3435d3, 0x39d89f3b, - 0x3ee116af, 0xf8550108, 0x0cf9d169, 0x255e2af0, 0xdaf18f32, 0x63cbeb9a, - 0x21afe33c, 0x63cd8d79, 0x969b0e4c, 0x23ae525b, 0xbcdaf19f, 0xd18cf9b8, - 0x5171d119, 0xc0ce8641, 0x7f047285, 0x4189c286, 0xf1833791, 0x26eabf94, - 0x9fe3855b, 0xde5999e3, 0x9b1cae95, 0x13e0ed0b, 0x3adb6c4f, 0x8470e50d, - 0x6bf503c0, 0xf1f5c988, 0xe6f507ec, 0xc31b5e47, 0x3dea387e, 0x4e02f395, - 0x1d0c4b09, 0x137fd08b, 0x2a27a541, 0xf63e12bf, 0xdbf1326d, 0x2dfd549e, - 0x9b4f4fa2, 0x092875ca, 0x15c5875a, 0x900eee47, 0xe076807f, 0x3e84339f, - 0x7b8a35b7, 0x65ee9b4b, 0x74e0993d, 0xe423538e, 0xd8432f24, 0x1f638aa5, - 0x2ca0b50c, 0x4c9d325d, 0xd7f5c7ce, 0xa64fafed, 0x73dade34, 0xd2a44f6f, - 0xff353b9f, 0xff3c0c82, 0x51aeca17, 0xb75bf236, 0x7e12c706, 0xae6ce142, - 0x20d02ccf, 0x87f615a0, 0x3c29eaa7, 0x9504ba14, 0x5b71a54f, 0x257e34d0, - 0x58555ff1, 0x30f6979c, 0x6dcc8aa3, 0xd5dfb854, 0xeb4a9358, 0x79b6fd55, - 0x97afe910, 0xf39f8432, 0xf13cd5e2, 0xcd1a06be, 0x25c33fbf, 0xa2682a99, - 0x324be37c, 0x5575d94f, 0xfec679e5, 0x55338d05, 0x7e41f227, 0xce11c778, - 0x7559368b, 0x73c26fa2, 0x94d1f020, 0xd5687ec0, 0x7640d9e1, 0x1e05dbaf, - 0x24f7c705, 0xfc447cf6, 0xd56cd3d0, 0xc1373ee9, 0x715203b9, 0x1eb23dfd, - 0xb619172c, 0xdcf7d1de, 0xe9a12fd8, 0x24439497, 0xe57be0be, 0x4c076d04, - 0x3be24477, 0xc959d849, 0xc3127b57, 0xe967ba26, 0x59efdf41, 0x4e0fab86, - 0x380d7de0, 0xec0ed973, 0xf85cf4b1, 0xe5c33a71, 0x05c83e24, 0x8d342701, - 0x26af49d6, 0x8e7cbd38, 0x09eea704, 0xaae1fd28, 0x208e8b1a, 0xa4a3cfca, - 0xc9f4a6cc, 0x5f625577, 0xb0b286df, 0xfca41b27, 0x9d2b6eb7, 0x8547d916, - 0xfdefa933, 0xf8e278ff, 0x9c21dab6, 0x48a80bff, 0x49b63b7f, 0x214e74a9, - 0xde122857, 0x0781428c, 0xdbb40baa, 0x7cef78c4, 0x2a4773e4, 0xe79e7fdb, - 0xf3ed3ab1, 0xf85e58b2, 0x0ff0d17e, 0x17c2521f, 0x76d2466e, 0xc94be63e, - 0x9a7573c7, 0x875c3c8e, 0x3cb8fef3, 0xfd8c2a34, 0x79ffab16, 0x3f57cfe2, - 0x80bdb15c, 0xb31eeff4, 0x4ff49ca7, 0xf671e047, 0xeb345fcb, 0x0ee422db, - 0x7264f486, 0x3ecc61dd, 0x3d36e755, 0xf776fe4e, 0xfba74541, 0xcf736ef4, - 0xb2bb8250, 0xd50b33e9, 0xfc1d5663, 0xb2ebfd84, 0xda5eff4c, 0x3563526f, - 0x864dcfd7, 0x873f5c1d, 0x20eb917a, 0x4fa16e43, 0xf51d9f2e, 0x1d04756c, - 0x06f293de, 0x6461fe3d, 0xbca49abf, 0x1c38a61e, 0x772dfddb, 0xf7f5a70c, - 0xf180fccb, 0x191c355e, 0x04df784c, 0x3c6b71af, 0x5c6a0eef, 0xaef79cbf, - 0xc46f5eed, 0xfe52d3fc, 0x56fdcb4f, 0x20dffa67, 0x7cb6d778, 0xc2d2a16a, - 0xa1a1f3aa, 0x3486f714, 0x4719c53d, 0x6fcaf48f, 0x69553c8c, 0x5f9a163d, - 0xaf581175, 0x536bbd20, 0xbd2f7e90, 0x396638db, 0x348fdf3e, 0x8b3b2149, - 0xe3d92af1, 0x60df66fd, 0xcefd5f9a, 0x8f4963d7, 0xf020241d, 0xaf375f7f, - 0x4378461d, 0x244e2ffe, 0xac0bdb39, 0xcd390cd7, 0xf7c53927, 0x8bff89f3, - 0x7acb9fa8, 0x7da58f79, 0x7ee5cb1e, 0x225c9013, 0x203cb3ff, 0xdfc93bff, - 0x3ca277cb, 0x59a3fbf0, 0x9bb4f7ce, 0xa337ecbc, 0xfdc91f5e, 0xdfd4c5e2, - 0x64ea5ed3, 0x843aa739, 0xf0d79242, 0x04275e11, 0x45f2d740, 0xfd22f80a, - 0x648cbcff, 0xf1242f71, 0xd8433939, 0x9e8e5083, 0xd873c1e2, 0x3e4a3555, - 0xe8a5ec22, 0x9a5a7b4b, 0xbf6d97f9, 0x26524698, 0xda5384ed, 0xd678ff49, - 0x6d28fffb, 0xa7d786d5, 0x73c3a82c, 0xf2a5386e, 0xf71961f8, 0x1c9f2585, - 0xb21af991, 0xa89a7a1b, 0x13e7a61f, 0xe5f54fb0, 0x4bebbd13, 0x9a4d1cc8, - 0xb528e3b3, 0x12a17c53, 0x2da6db72, 0x166a3f6b, 0xfc479e62, 0x6e6470d7, - 0x75e3d51e, 0x0242b39f, 0x6df0d882, 0x222f47cf, 0x8c3e1e1e, 0xa7638ff8, - 0x7fcc38f0, 0x060d7fe8, 0x6ef1ff77, 0x4091ea45, 0xc7e27cd2, 0xafb506ae, - 0x2254808f, 0xfddf5363, 0x007b7da4, 0x677fe76d, 0x2267077a, 0xf00ccf3e, - 0xfa7ddb73, 0xcb124cdb, 0x5c4567fd, 0xe6f160df, 0x6434ff11, 0x871ba863, - 0x2299ad4f, 0x856453ef, 0x379cf7b8, 0x18390a67, 0x0aed8015, 0x33aaebc7, - 0xd4bf7488, 0xe82d7aa0, 0xc0845d2f, 0x6fa4a992, 0x01f75e64, 0xfc5e3f90, - 0x283cfa45, 0xdf900fbb, 0xc1eb7682, 0x11d6c45f, 0x316fd978, 0xeb0058f2, - 0x2b5fc44d, 0x0ff8149b, 0x67aac5c4, 0x93afe7a2, 0x1babf275, 0x8c1b1d77, - 0x5cf35d74, 0x2df938cc, 0xe211ff7c, 0x5d5d7878, 0xcdc33d74, 0x197fd299, - 0x7fc9c30e, 0x3d62be41, 0xd5a0d661, 0x60ac7c8a, 0xf6224314, 0x0be04992, - 0x67cb2bf5, 0x8a6f61be, 0xb9ea5e85, 0x94a75c04, 0x94743bbb, 0xd4a681ea, - 0x8f687965, 0x9f189a29, 0xee2598d2, 0x4aa0b4a7, 0xbc930c75, 0x77ec59fe, - 0xa967bc07, 0xd49564de, 0x5fc4e097, 0xd3c8fbca, 0xddfe92af, 0x9d6c60ea, - 0x9553c0a8, 0x8219379c, 0xcaefb435, 0x69dea2dd, 0xf9e8eeed, 0xeb4f1255, - 0x8c7d3a9e, 0xa11585d2, 0xa7897198, 0x3a98c6aa, 0xdc38b116, 0xadef299f, - 0xf5fb7d64, 0xd1fc5bd6, 0xb78dfc2c, 0xf8c63ae5, 0xef914ce6, 0x1063c4ad, - 0xd505d77d, 0x2ad1f120, 0xfc2c9025, 0xc72c705e, 0xb067ddf3, 0xbdcfac81, - 0x3ee9e25f, 0x7e7c3fc9, 0x19e2bf7c, 0xfdc57df1, 0x7f868b3f, 0x832cf80d, - 0x0d83f9f1, 0xde50b03f, 0x56df9631, 0xffd999d5, 0x13f1235d, 0x7a6b5fcb, - 0x858767f9, 0x7f2c5bec, 0x6b95fa55, 0xf6fc2fc0, 0x0df85bff, 0xcb91af3a, - 0x398735ac, 0x09f6b53f, 0xabf943c5, 0xf7ab9d6b, 0x7f7cf23c, 0x359eb9ef, - 0xc6063de8, 0xa4e7bd30, 0x63bd175d, 0x96bdedfd, 0xe726bcde, 0x66b72f05, - 0xe0dd3e73, 0x6675d8ab, 0xf67dbf49, 0xbd7fc253, 0x276258d4, 0xa4fba3ff, - 0x9ce8a3c9, 0xc02e4caf, 0x566f8ff3, 0xee91fc81, 0x033be1a6, 0xa9e17f08, - 0x5f94c5a2, 0xed0a7f1f, 0xb707dd13, 0x0257fd16, 0xd27b07df, 0xb667ee48, - 0xbdfb488d, 0xfb61d783, 0x70b27dde, 0xe9e93967, 0xb445a593, 0x54e382ae, - 0xed285e9f, 0x42c9f554, 0xbd84477b, 0xc8a64dfa, 0xff716fcf, 0x1b8a51fe, - 0x7b35ef66, 0xdb323f28, 0x8094dfec, 0xa0be15f0, 0xb771aa78, 0x9e47ed63, - 0xbe5175a4, 0xf38acd28, 0x8d08e9fe, 0x1851ed57, 0xb2a6eefe, 0x3f643dbc, - 0xec87aa83, 0x7dd37762, 0x1f920ff9, 0xfe40fcd4, 0x1dfb117d, 0x66fa154b, - 0xb6660df6, 0xec839dd7, 0xbca72ebf, 0xeb1777a8, 0xfb43ce8d, 0xc37dfc2c, - 0x78dc051e, 0xa3ee63ce, 0x3a1e132f, 0x50b69c0f, 0x70d25010, 0x4711d2da, - 0x25ed1b7f, 0x9cc2f30c, 0xe161ddaf, 0x7ffdcdfa, 0x2b79d0b0, 0xf384fb9f, - 0x7e286b6f, 0x19ef3f20, 0x3a77bf95, 0x85aafcda, 0x4eb2b4f8, 0x91590181, - 0x271e66e3, 0xcffd4afd, 0x369e84ea, 0xe4857ff8, 0x0dff8377, 0xf5215879, - 0xe35b7dda, 0xffa1bbf3, 0x96ef041e, 0x03deb841, 0x0eb9cb75, 0xd11d81e9, - 0xfc5257f3, 0x17cd237a, 0xa9f2befc, 0xbdd5f1e8, 0xfd601e7c, 0xbf47ab1f, - 0x2e7ff433, 0x5f9f12e4, 0xa618af0e, 0x7d7d3ca1, 0x8830cd7a, 0x293caf93, - 0x6ec306fd, 0xd89b0e5f, 0xebcec5ee, 0x2162bc6a, 0xfad55b7b, 0x6773f627, - 0xf4c97d35, 0xe16a6f28, 0xc05bd97a, 0x79f08ebf, 0x49dd934b, 0x877976fe, - 0x9af303d0, 0x42a0c1ac, 0xa25aa1e3, 0xf161f773, 0x90e049bd, 0x4816fec2, - 0xe252b8bd, 0xe3c4a575, 0x06e38c4a, 0x8c8c7d53, 0xbc652be3, 0xd7673abe, - 0xa9292a31, 0xdaebe394, 0x1e13268e, 0x5bd081e7, 0x6f4242f3, 0xec31f419, - 0x40beac50, 0xd10f770b, 0x95936d77, 0x4be7d6eb, 0x0ebf35bd, 0x5fd296f5, - 0xb40f747f, 0x7ef1fc8b, 0xddac7701, 0x9e886cad, 0xfc201aef, 0x7fd2cbd8, - 0x4d101c2e, 0xb01ef297, 0x9e7f7e53, 0xfc827aae, 0xfb46bb56, 0x7e458eb7, - 0xf55bf5c3, 0xeaf129e1, 0x4df68cb5, 0xfd181719, 0xc3679405, 0x0ee721f9, - 0xffdc6447, 0x7f84039f, 0x1ab266b3, 0xc446ba20, 0xb30a0b49, 0x7349c6e2, - 0x8637f409, 0x71b3f7dc, 0x77927191, 0xb7e228d7, 0x2cef757f, 0xaaa6baa7, - 0xba2fa13a, 0x29bae126, 0xfb03f7e4, 0xd67555d1, 0x5533c520, 0x7dfc2fc8, - 0xc909f11a, 0x46529363, 0xc671827c, 0x42feb4ed, 0xf3c4eaba, 0xfb446c2f, - 0x2c2fcb8e, 0xabf992fd, 0x3738846d, 0xbc406de2, 0x3788c3b8, 0xbf0aaf2a, - 0xa95e78d6, 0x51dc7075, 0xb5ea24d9, 0x337c8e1b, 0xede10b34, 0xd0f3fe6e, - 0x3e4f54e5, 0x86e7d840, 0x54a7d0e2, 0x1ef5f457, 0xb5ff5c5b, 0xb52bff57, - 0xe6950f2c, 0x6bf64c8e, 0x791fa20e, 0xb7d1ea13, 0xa538e0bf, 0xbdc248e1, - 0x5aebcf94, 0xfce61fe1, 0xc3553a1e, 0x3783f626, 0xe4b72d41, 0x8dfa451f, - 0x4ea29d2b, 0x3f6941e9, 0xf208ffa9, 0x773883f5, 0xf97f6146, 0x8549f437, - 0x10d5ebe4, 0xe95532d8, 0xa42a07af, 0xdfcdacdc, 0xf6ae85b5, 0x0aa7fd63, - 0x31184f29, 0xf58cbdb0, 0x8633fe9f, 0x4edfab5f, 0xbbb8ff64, 0xae52754d, - 0xabfbf119, 0x6227e441, 0x271d905c, 0xe485fb5f, 0x7f794ecf, 0x65493d5c, - 0x8b2699fc, 0x10b7f0d6, 0xdd37cc8f, 0xb2411da7, 0x5f87796f, 0x583e26cd, - 0xdefa3bbb, 0xe7e8e889, 0xc8a0b1ba, 0x7cec8547, 0xbf8c6517, 0x31d5f874, - 0x6fd56fc4, 0xd04a3b7f, 0x96519be7, 0x67c36bf4, 0xe2228ab4, 0xe2229366, - 0x475afde6, 0x556bc532, 0x645f5507, 0xef41bf3d, 0x813ca597, 0xf503f226, - 0xabe67403, 0x1fc126ea, 0xe2d166a6, 0x7e444bfe, 0xf7fbccc8, 0xbe462f1b, - 0x067b1ef9, 0x40f21704, 0xf987b995, 0x89b4eaaf, 0x7d3aa9e1, 0xc4447339, - 0x775a017b, 0xeabfe900, 0xc4fac075, 0xe76fa40e, 0xd891f7d3, 0x027eff9f, - 0xb2c761fb, 0xfb8b97b7, 0x7f48152f, 0x9af6fc3d, 0x60f691d1, 0x2f7100e2, - 0x3707840e, 0x10bf3f79, 0x6c3c4bfb, 0xbf324582, 0xaf79f820, 0x2e309b8c, - 0x9c40737b, 0xfd7aecb8, 0x2b66eae9, 0xeab9fe50, 0x19d72b03, 0x92bcdd7d, - 0xeab87ee3, 0x06fa4d1f, 0xa91bfefc, 0xcaf0f87d, 0xebfcf4d1, 0xe46fabc3, - 0x29b2a97c, 0x2011cf2a, 0x5fe4dcf8, 0x5deef57d, 0x69b67fe4, 0xb6149fec, - 0xee977d9d, 0x9835f769, 0x8ad1dbf9, 0x067613fd, 0x2aafc892, 0x11df4f9c, - 0x98d56bed, 0x32dfd0ff, 0xfb3b2bfc, 0xd88aa757, 0x7c75c2bf, 0x4e8b6e41, - 0xa7bad394, 0x9a688b8a, 0xd7a4e382, 0xe57f93c6, 0x0cb7f3e8, 0xf8933e78, - 0xe0496eec, 0xd9028bbc, 0x4460cf82, 0x1aebdc14, 0x64ff675e, 0xf51aa35d, - 0xdef188fd, 0x7b88065f, 0x3e0cef87, 0xe65e290b, 0x5da2bda3, 0x932fb8d7, - 0x1cd6b1ce, 0xaea93e62, 0x3df18b33, 0x07ba05a2, 0x411fc09a, 0x273f0807, - 0x65d211e8, 0x8438259e, 0xbdbdfafc, 0x2eb28af7, 0xf5ea2824, 0xf3875a6a, - 0x5b974c77, 0xb3c7a5f7, 0x9ee92743, 0xe3be1d07, 0x8a1e2259, 0x5badff1d, - 0x9f8e41e4, 0xf8f1fa13, 0x78e8ff4c, 0xc500327a, 0x48a05f22, 0xef8835fa, - 0x35e763ed, 0xfe787ad3, 0xc70243dd, 0xf73b8f89, 0x63fdf026, 0x75e44ba7, - 0x34dbea4b, 0x6d661efa, 0xec813283, 0xf79cdad2, 0xec197bf8, 0x5c9e9117, - 0xf7c83e1b, 0x7b7515af, 0xc0e37967, 0xec2dddb1, 0x9df93cc3, 0x7cf8ec72, - 0x3c067e39, 0xdb9e3219, 0x673ef74e, 0xf14ecdca, 0xeef89bdd, 0xd7a956f5, - 0x6662df17, 0xe80cea3f, 0x227f7166, 0x481639ee, 0xd4ab7dbd, 0x63dfb1f7, - 0x76fdfa1b, 0x67c2ceb9, 0x73dd3360, 0x7d9f7ec4, 0x170ff4bb, 0xefd79781, - 0xf4bd5df7, 0xfeff6313, 0xea5b8942, 0x8a3051f5, 0xed087af4, 0xe45bd70d, - 0x9eddb026, 0xae32305f, 0xa9df41df, 0x753bf2eb, 0x57fa0d6a, 0xf6c7bee7, - 0xb9cb78f0, 0x86fbf997, 0x1d900973, 0xcfad9ee7, 0xe47a1a1e, 0x79774136, - 0x14e151ef, 0xbff41a30, 0x645a1184, 0xffa0cd7e, 0xff0e9283, 0x394575c7, - 0x63e645a0, 0x07fea90e, 0x475419dd, 0x38fec9dd, 0x21ed809e, 0x3ca86b9e, - 0x846b50d7, 0x7034bb9d, 0xee3e5c79, 0x406a5f3b, 0x6e7493d8, 0xecad725b, - 0x14845637, 0x22b0eefe, 0x9b7fa20c, 0x51caf9c2, 0xbf5c2d0d, 0xf154a4b1, - 0x3c5a8578, 0x7c19f04b, 0xfc26c0b4, 0x7a5f8303, 0x88f925f1, 0xb85fc9c6, - 0xb10bfa55, 0xda1a34fc, 0x4bfad167, 0xea878abd, 0x47c9af36, 0x4ebdc6cb, - 0xf8b5eee1, 0x4cd2f908, 0x9f96317a, 0x1ffb735e, 0xb775fc25, 0x80525e5f, - 0xfdcf1feb, 0x4ff1286c, 0xe8e435e5, 0xddbf4945, 0xae71c08e, 0x7597a963, - 0x8db9f504, 0x5697841d, 0xd3b2bf60, 0x8365bed5, 0x8eb9b7f0, 0xc09c22a0, - 0x4d15a5f5, 0xad6efe76, 0x713aa1a2, 0x26e3e90c, 0x7ec763d5, 0x52e9c379, - 0x179423ca, 0x2a973a89, 0xabbba8bb, 0xbbba8bb2, 0xe7fee9b9, 0xeff813dc, - 0x11d74403, 0xb57e3a58, 0x3ef87be1, 0x9335df56, 0x7fe1370f, 0x4b350f4e, - 0xbb686cfc, 0xc4863992, 0x887fdd34, 0xfd7eeee0, 0x8a7d0b45, 0xd5e63551, - 0xd6825459, 0xde79d6ec, 0xb52d752d, 0xe0365694, 0x429dbbb7, 0x43839aef, - 0xbfcd6fd8, 0xea9b7abe, 0x258c6f83, 0xd2d5d5fb, 0xc112d636, 0x501b9def, - 0x63a1c76f, 0x1ca49835, 0xca2adc6b, 0x0947e922, 0x3e6aaeb9, 0x8bf9499a, - 0x7ce7924e, 0x1e49df6a, 0xdec56d81, 0xc923c933, 0x5a2fd99f, 0x4d4bbd63, - 0xad03cf2a, 0x49edd463, 0x666df091, 0xc4852ef8, 0xa31d003a, 0x8e441716, - 0xd6bffcd7, 0x3e851707, 0x07d288e8, 0x16429e06, 0x0388efe0, 0xa75cad87, - 0xae3ff740, 0x036a3a08, 0xc26efd05, 0x76e48a60, 0x0f7bdd32, 0x834f9727, - 0x41afa9bb, 0xfba54b58, 0xea2ab0e9, 0xbeb086fb, 0xbff7289f, 0x50b70b49, - 0x7964f03d, 0xda053a5f, 0xe80cde79, 0x4e0bd6e1, 0x18ba0efe, 0xb24edc3c, - 0x5a53e785, 0xe2143f2b, 0x99c27bef, 0x4d82eb9a, 0x871d6f7e, 0xd3787dde, - 0x0f8182e0, 0x44d5ee95, 0x79ec533d, 0xfc28186e, 0x42bc9bbc, 0x414b910f, - 0x2093c0f5, 0xd3f9f7c4, 0xebde43a1, 0x54c73fc7, 0x1ee90b8c, 0x31ba3a6f, - 0x208f8c89, 0xe7469fcf, 0xa79de351, 0x19933e63, 0x9f049d4a, 0x7d34ce12, - 0x73febf67, 0x28355374, 0xebefbde5, 0x5171fae9, 0xa7a83ddf, 0xa9f78de9, - 0x7af1597e, 0x43d9beb9, 0xfc538ddf, 0x7b3ad613, 0xc03659f5, 0x722b8198, - 0xfbe84e06, 0xc0fc046e, 0xdfb12475, 0x277c448d, 0xfe231702, 0xe751922e, - 0x48b83bbb, 0x65913aa7, 0x7bfe36e9, 0xa1b6853b, 0x79af29e3, 0x339fcd28, - 0x7dea8330, 0x62f246eb, 0xfb02705a, 0xecbf92b9, 0x78449de0, 0xf7c6bc50, - 0xd37cc02b, 0x320bf7fb, 0xb227bf81, 0x3e77c55b, 0x6d1f91db, 0x3a052ca9, - 0x23c35fd5, 0xd3f93a25, 0x0f365c5b, 0x256c477d, 0x707dedb8, 0x1d44d8d7, - 0xd44d8d48, 0x72f51879, 0xb1ad78b1, 0x8f4e7919, 0x98f1fd8d, 0x627e90ef, - 0x7842dff3, 0x98a9287a, 0xde530eff, 0x5cdcd32b, 0x7fbf250f, 0xf03049aa, - 0xe7e36c50, 0xec94f57d, 0x3d52d667, 0x9359c237, 0x78ff5c01, 0x0a546934, - 0xb4d565d5, 0x9aee7a89, 0x77eb008c, 0x7d615fb3, 0xd25ad35f, 0xb2e2f64a, - 0xdd75c2c3, 0x07512e35, 0xd080c81f, 0x3d347af3, 0xa0f419a6, 0x8f594bfb, - 0x5c65d064, 0x7bd0943a, 0x91dec2e3, 0xdb429384, 0xfdd037cb, 0x7470b8c2, - 0x69d2197d, 0xf7a9d135, 0xc9cd1e3b, 0x7d061ef5, 0xd9987190, 0x06ee929d, - 0xdfc69cbd, 0x516af023, 0xa0c08f7f, 0x4144f6e3, 0xe055332f, 0x7577e70c, - 0x4e96375a, 0x14e11bff, 0x4bb0bac1, 0x00004bb0 -}; - -static const u32 xsem_int_table_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x93cbff00, 0x51f86065, 0xd2f9c08f, 0xbcde0c0c, - 0xc4b462a8, 0x0c0c5c0c, 0x0e5c4041, 0x7b401ac4, 0xdbe9016f, 0xcdce1c40, - 0xc40110c0, 0x1ff881fb, 0x6207ff10, 0x04d6200d, 0x79405fe2, 0x5b1ba845, - 0xda181898, 0x8803b880, 0x875880bb, 0x97418191, 0x93fb7891, 0xde181984, - 0x7af82389, 0xcd0c0c12, 0xfff3f452, 0x5631c360, 0x29efb5f4, 0x174e3ed0, - 0x19c73f04, 0x505c2498, 0xe0bb70d5, 0x4d078337, 0xcf8d179e, 0x9e7f4787, - 0x5cbf2a21, 0x4d3f950b, 0x23e18187, 0x2d0a9a92, 0xc7416efc, 0x0c0c468a, - 0xabc4464a, 0xca8c60df, 0xd081300f, 0xb1adf900, 0x0003a809, 0x00000000 -}; - -static const u32 xsem_pram_data_e1h[] = { - 0x00088b1f, 0x00000000, 0x7de5ff00, 0xd5547c09, 0xf37df0f5, 0x66499996, - 0x0d909326, 0x8a027108, 0x081380a8, 0xc3b44069, 0x8e22a222, 0x260dc55b, - 0x1037d902, 0xfdaff0fd, 0x2d361032, 0x4682d0d6, 0xa0c0748b, 0x0d0482c1, - 0x00e02418, 0xd52ff82e, 0x5b7bbfd8, 0x16c34a0c, 0x7e1b8092, 0xce7fe5b5, - 0xef25f7b9, 0x6d80264d, 0xfdfb5fbf, 0xe6f169bf, 0x5ddf7bbc, 0x3dcf76ce, - 0x14fbdcf7, 0xf89628db, 0xe0cec663, 0x2cabd20f, 0xdd51b18c, 0xa0db6ce9, - 0x74fa87a1, 0x6559ffe7, 0x4287ead3, 0x6ed0ab1e, 0x9cfdd61e, 0x7e5485b1, - 0x386b8c40, 0xf4d31cbb, 0x8f0e1b10, 0x9616c96d, 0x6e7dd8cc, 0x0901bf46, - 0x912974be, 0x5615ceb1, 0x780cbaf7, 0x085c7aae, 0x20c8f7df, 0xf7c25077, - 0x1652c93c, 0xbaa23fe4, 0xbecc01d7, 0x6cb3233f, 0xe0da66c6, 0xc3fc0f6f, - 0x7cbea07a, 0x63106cac, 0x059969ea, 0x77ea7fa0, 0x3403a512, 0x00efc336, - 0x6c2df978, 0xfeeed0dc, 0xecfd13b9, 0xe8b78073, 0x5b7e89f9, 0x097f90c0, - 0xecffa893, 0x5faa4afb, 0xf2f16f6f, 0x073e6c5b, 0x8d941636, 0x7f963bcf, - 0x8be7c2e9, 0x7aa16e9b, 0xd82c5318, 0xc8b772cf, 0x635cfc4f, 0xbbfaee96, - 0x76a214f1, 0x04d3d874, 0x3188feed, 0xb6bfb5e9, 0xd543c032, 0x0563d556, - 0xaad84cbc, 0x700c7f86, 0x84295ae9, 0x9d9765b0, 0xfb4bc031, 0x9d870e6a, - 0x9fcb0f9a, 0xaa1805a8, 0xff36b728, 0xdbc40afc, 0xa3ad9956, 0xf784fc66, - 0x3bc71b56, 0x9e70e46b, 0x6ba5839d, 0xf7c74f77, 0xccad1a0b, 0x6e95f50e, - 0x057a9fcf, 0x54fbf9c0, 0xd74a4586, 0x01fad02f, 0xea92185c, 0xcf18ee11, - 0x36e0fda8, 0xca1eb439, 0x939ab877, 0x1ff1836f, 0xcf31b4ab, 0x676fd0c5, - 0x80adf273, 0x96d0a287, 0xd15ef849, 0x2c8bc946, 0xfaeb6134, 0x7bc2fb37, - 0xaf241ba5, 0x5c52f015, 0x433ccb17, 0xc0ce1f78, 0x3906d6bf, 0x9fc863fc, - 0x1964e30b, 0x49ead748, 0x57f6c64c, 0x37671e68, 0x0e558e9e, 0x376b1e61, - 0xda01ba5c, 0x5ecaf781, 0xc438bc94, 0x200b0b32, 0xb76fb65f, 0x81d67b4f, - 0x0da05be3, 0x96b8e276, 0x3f2e586a, 0xeecdbb94, 0xd5adfec1, 0xd17e4126, - 0x9e5ab5ea, 0x75c5fe81, 0xcd8f3197, 0x419aafd0, 0x88fe4629, 0x9b018f4c, - 0xc453fb18, 0xf91eaf98, 0x37690944, 0x9fa2e419, 0x2ef44f14, 0xf54d93ae, - 0x4b192603, 0x007eff82, 0x82be027f, 0x57849d3b, 0x05736e9d, 0x3b74e91f, - 0x2987e425, 0xfac6d99d, 0x48e7f4f5, 0x754fe807, 0x5fd29ba5, 0xba52a654, - 0xf443d2b2, 0x07f10279, 0x6fd172e9, 0x4e3658d7, 0x3e5d7681, 0x4b3146e6, - 0xa71be298, 0xe7e09c02, 0x01ddf270, 0xf19673c9, 0x6a13e9eb, 0x72651720, - 0x53e49b15, 0x05ac02fa, 0xb42f30e6, 0x9be8dcaf, 0xd7b19a38, 0x1c71e059, - 0x502922ff, 0xac657480, 0x740fd53e, 0x1e812259, 0xc52d7c01, 0x961e0241, - 0x067e05f4, 0x4f713d3a, 0x24b2b3f6, 0x70889ac6, 0x668f73de, 0x54353d50, - 0x0cf50a8f, 0xc93d773a, 0xf54c73d3, 0xd02f4f24, 0xf54b59eb, 0x9eafcfd8, - 0x318fa627, 0x917a67f7, 0x580bcf5e, 0xfcf3916e, 0x633c95c6, 0x333fb9ac, - 0x949ea84a, 0x002cbdbb, 0x7f9d65e5, 0x864fb358, 0xf8c6c77c, 0x23328f11, - 0x86df8d1f, 0xaa4139f5, 0x97147c8c, 0xa7926313, 0x09825f78, 0x9fb933ee, - 0x7f927ca9, 0x653f29a0, 0x7c11a5da, 0x5eb770e9, 0x54e86026, 0xfea35e38, - 0xd234fd6a, 0xd9fae33b, 0x9fa07e08, 0x03cef483, 0xbb170263, 0x57d8dfa1, - 0x407ff406, 0x8eee5c0b, 0x2e3037c2, 0xea62a589, 0x991a60b1, 0x78e554bf, - 0xfbffdf1b, 0xfde107c1, 0xe0e74b72, 0x4bff8078, 0x8e21f71a, 0x4ca88ffb, - 0x32316e81, 0x3172c0ab, 0x6ffa4656, 0xb3f64669, 0x975e0341, 0x917e000d, - 0xa65debba, 0x1f915206, 0x4115825b, 0x3025cfe4, 0x8c7eb041, 0xe115641d, - 0xfef085e0, 0xc454bc80, 0xfd0355bf, 0x835f6c61, 0xfb5287f6, 0x5b7ed8ad, - 0x075bed2f, 0xb7da98e6, 0xda9817a5, 0x3ed069b7, 0x706747c8, 0xf01f68be, - 0x93b18637, 0x6fb53e6c, 0xf6a02f4d, 0xc0ac6a97, 0x574c7ed4, 0xbb60dffb, - 0x49fb63df, 0x703fc651, 0xe9fc798c, 0x6bf1e645, 0x416cfc7c, 0x431fb450, - 0x20a497e3, 0x117a7f1f, 0xd795bf1f, 0xabbed5db, 0x049aff0b, 0x5ea43aed, - 0xac683fc6, 0x9417fc79, 0xe56fc798, 0x2c17bbed, 0xa83bed13, 0x196978fd, - 0x2505ff1f, 0x0d66bed4, 0xb48f9178, 0x211531fe, 0x40d34f9c, 0x07485280, - 0x921d28fa, 0x93e818c0, 0x8481b2df, 0x38620787, 0x03137ddf, 0xd6e8e6fc, - 0x12042ca7, 0x9970f308, 0x8de2e9e0, 0x3f3e34e3, 0x9f5e6907, 0xab3aba2d, - 0x8cf9a651, 0x2e86b4ad, 0x37b6fe82, 0x678441ca, 0x2432bcad, 0x760a7cd3, - 0xb0a7be02, 0xf3ff3e30, 0x8ceb61aa, 0x674c8ae3, 0x2dadab57, 0xd2eab906, - 0x90d9e3ef, 0x055fe80a, 0x6ea8c132, 0x34f415b8, 0x39fc3d03, 0x0f4c63e8, - 0x392edcab, 0x5d9c7a04, 0x059b946c, 0xb2092edc, 0xff4087f7, 0xdffa227f, - 0xb77c70aa, 0x884293ce, 0xcc566fff, 0xcd9f50d1, 0xa4058eae, 0x5ca3f777, - 0xbb73a9d0, 0x14f64435, 0x9f88074c, 0x191449db, 0x1baed3fb, 0x305c94de, - 0x31f4d63f, 0x0b3777bd, 0xf2854e2d, 0x0ee79733, 0xeff8c370, 0x211d669a, - 0x7cc4fce3, 0xc7242dfd, 0x8725bfac, 0x2b0d69b1, 0xdc00fed4, 0xbcfd4d3e, - 0x1dfef0c5, 0x577c3301, 0x576e1981, 0xed05aa43, 0xad894299, 0xa9ef7a85, - 0xedebe730, 0x3812964c, 0x3f7b455d, 0x85f41c01, 0x3a60f747, 0x89bb1f02, - 0xfcddd3ae, 0xe53fbd5d, 0x4c2ca90f, 0x124b71f3, 0x5127fa23, 0x8f9b80b9, - 0xd3bfb23b, 0x0fcf9b55, 0xa0fe99fd, 0xec8cf84c, 0x58aecb7f, 0xd9ec059f, - 0x552f9a96, 0xf1c8c164, 0xc67ff644, 0xb8f1c8fc, 0x721f9c35, 0x39cf9183, - 0x53f2449f, 0x5fb8e379, 0x53f0321e, 0xbfb5fd69, 0xaf78643c, 0x1326eeb8, - 0xc3ba185c, 0x26bf3e54, 0xbb3f94d7, 0x3f94d0ba, 0x131cd973, 0xd07c1b9c, - 0xfcc67e54, 0x7bfca605, 0xe5311e2a, 0xc2b055df, 0x7811df04, 0xf6fe54ca, - 0xf94d6b69, 0xdc975d96, 0xf5547288, 0xde70cc81, 0xfad1daf8, 0xbf37b473, - 0xa45e2876, 0x57b011c7, 0x818e0e50, 0x7b6982bd, 0xabb248e3, 0x31e60f41, - 0x4b56a130, 0xc6cb83fb, 0xa4665ea2, 0xefd2433f, 0xc634c183, 0x843c979e, - 0x6346b93f, 0x89616061, 0x71f17425, 0x6fc86ca7, 0x0d7e4739, 0x9ec8fa08, - 0xf44b72f9, 0x72ebe5e7, 0xd3bd402f, 0x5f803e9b, 0x3ae79c7f, 0x99103d84, - 0xbf31225f, 0x7ebeb9f1, 0x7ae25cba, 0x53ac44be, 0x3bea5e4a, 0x0e10b99e, - 0x5b38ae0f, 0x5480f57b, 0xfd6893d4, 0x803f2127, 0x51e81814, 0x24c8375c, - 0x65bb6ddf, 0xea1957ea, 0x99abd004, 0x4257bfcc, 0x9bde133d, 0xec30cb7e, - 0xd475ef87, 0x8931acfb, 0xcab6f5e6, 0xa43cbfc9, 0x94fc7d22, 0x469ca91e, - 0x80656b69, 0x059543d2, 0x595e7e94, 0xe54b6941, 0x540f4a7c, 0x63fd2906, - 0x3f4a32e5, 0xf4a6acad, 0x4a1acae3, 0x510cac3f, 0xa3e95eda, 0x2e879754, - 0xf617ebfd, 0xc0b758b0, 0x8b0f6e03, 0xb2822cb1, 0xdee724cd, 0x53f39454, - 0xa3066f8e, 0x63ea7fbd, 0xde8ca260, 0x6fc915f1, 0x47d1d3bd, 0x085e4af6, - 0xcf4fa798, 0xa70c7b7c, 0x26c2dd93, 0x8f47d033, 0xf79cf45c, 0x2b04a1de, - 0xa9c032c8, 0x519c9bde, 0x0fb985ea, 0x3a2e75e9, 0x70e75f31, 0x3eb7675c, - 0xac6c97fd, 0x206972f7, 0xcaf7879f, 0xf0b30f34, 0xd7a45eb3, 0xf49bc50f, - 0x5bd29fda, 0x2e89dca0, 0x33a735fc, 0x6e48e748, 0x8354ffaa, 0xc7882995, - 0x2e10d8a6, 0x7bed4f8d, 0x38f285d6, 0x3eae5537, 0x7c77b234, 0x5467d695, - 0x29e30c3b, 0xa7c3346f, 0xdcc9a5aa, 0xbb89e07f, 0x95f21875, 0x45d0fabb, - 0x4a54ff48, 0xa6e67af5, 0xb1ced46a, 0x7c7141ba, 0x79f10efe, 0xf13c6370, - 0xa93bac2b, 0x3fbb3ffc, 0xf7a3d5bd, 0xf606b187, 0x01f50d85, 0xf73a0de4, - 0xdd07a8fa, 0x3f34af95, 0xfd49abd2, 0x1885ed06, 0x206677f8, 0xac10abd6, - 0x2f5e5bd7, 0xe397ad07, 0xf6a68df3, 0xbe8f3de0, 0x7af7c7a6, 0xb5855be7, - 0x7d04e3ea, 0xe7f0a575, 0xabd9d714, 0xbc4af3cd, 0xec6f2e09, 0x679a6d5b, - 0x7f900ff0, 0xc8292156, 0x9b82253f, 0x32c7143a, 0x6a97fa09, 0xe5bd50f1, - 0x6a572f12, 0x1e02d16b, 0xb466c762, 0xd1cdee33, 0xfb73cff9, 0x1fdf401f, - 0x1ecaadfd, 0xd7e17cc5, 0xb06cf551, 0xe7e82d6f, 0x0dbdd011, 0xef5053c5, - 0x3d76dd1d, 0x98b327d9, 0xa48b85df, 0x8d9d5602, 0x6609ce76, 0x7ffc8c99, - 0x35defd82, 0xc8deb0d2, 0x9fd468b7, 0xf3cccb99, 0x2667d82c, 0x0cc6bf38, - 0x939bb1e7, 0x56f3df91, 0xa0b730aa, 0x6ff39a5c, 0xbe49b8b7, 0x12c559f2, - 0x3f08ef5a, 0xa66ebdd8, 0x2fb907f4, 0xec99e57d, 0x87e8a1dc, 0xf75bfae0, - 0x7026140f, 0x3128a53b, 0xff20f9a4, 0x3f91868b, 0xfbe182b9, 0xa7a825a1, - 0x5de64e82, 0xefd27acf, 0xb23ff687, 0xd27cfabf, 0xfa214fc3, 0xbe49d721, - 0xda759450, 0xd84916c3, 0x974a415b, 0x76eb718b, 0x5c044d6b, 0x47d7011b, - 0xbf377fc0, 0xbf133225, 0x35025aa5, 0x5fce2496, 0x4a482f68, 0x47f816a7, - 0x51ed4fea, 0xb53fed7f, 0x3fa834fe, 0xfd7f54db, 0x0bfeb53f, 0x29bff47b, - 0xafa5fd5a, 0x0416da6c, 0x79b4537d, 0x3cc18b95, 0x4ea95474, 0x4bdd02f6, - 0x21762fd6, 0x82511c1f, 0xa3e7e42e, 0x34727921, 0x22d2f87e, 0xe7cca2fc, - 0x855d7090, 0xc7fd427f, 0x54d9f85e, 0x59bee7b4, 0xbd69baaf, 0x5b0d6754, - 0x1acb4e41, 0xdfa0a70a, 0x1c83e017, 0x46527a5e, 0x9fccd1b8, 0x4aafcf45, - 0x701eff46, 0x844f588a, 0xab2a5ec9, 0x9c24f3fd, 0x2759ca87, 0x7be459c9, - 0x04e9fed8, 0x5ab98fd2, 0xe87ccf5c, 0xe5f9d927, 0x0de52f02, 0xbb293b3f, - 0x30f6bd30, 0x4cb013ea, 0x7c8f0ec8, 0x41d840af, 0xc4ce2c87, 0xb1425856, - 0xa11fb11f, 0xc2f1d4de, 0xaa0edc42, 0xf0e4f0da, 0xb6afd083, 0x24badfda, - 0x7974be03, 0xf33f553b, 0x7a7aafd7, 0x62edcbd7, 0x5efdd7bd, 0x34f3de88, - 0x89adfb0a, 0xd86a25a7, 0xc971f685, 0x841bd55a, 0x9e9b25c7, 0x5c69ee7d, - 0xf5627eaf, 0x17f5045e, 0xc3e37a6f, 0x6f170031, 0xf0a71351, 0xe4a43861, - 0xc394fa6e, 0xba23f9bf, 0xf2f451e9, 0x18679a1b, 0x4270fe7f, 0xb78a5d37, - 0xb0d8d6ec, 0x5098f89e, 0x716b5bbf, 0xfd4fa144, 0x676849c1, 0x56f86d55, - 0xd1e575c3, 0xc94b125d, 0xb5cf8288, 0x80bd906f, 0x0a7a2278, 0x2fd1757a, - 0xd0397ca2, 0x247af505, 0xbdcb22bd, 0x1465fa81, 0x93fd17af, 0xbe2fdfc0, - 0x4fec7e8a, 0x43c45ead, 0xb9f78bc1, 0x95873c70, 0xcfe7ce0a, 0x3f464e2c, - 0x4c1a817d, 0x9fca5376, 0x9fb9ac17, 0xbdff2ff8, 0xfaf993fb, 0x42d7d7d0, - 0x2fb05573, 0xeaf6738e, 0x799c68db, 0x587c402c, 0x0fec8cf0, 0xc2b5fa41, - 0x22896f26, 0x9732c527, 0x80ebc393, 0xc3ce30b8, 0xbf414eb8, 0xd0e5efee, - 0xcc8ff27a, 0xee0fa861, 0x6cf1fdd7, 0x8b5fc12e, 0xb27184fd, 0xdae75f45, - 0xbb5bfc4c, 0x74e919b4, 0x052f806c, 0x4ce56afd, 0x487c0a09, 0xf95ea067, - 0x3853abbd, 0xc947989d, 0x5d81ef16, 0x639f0130, 0x67d566f9, 0x8f7a6e1f, - 0x6ee8c99d, 0x1f689e7f, 0xf3831dfa, 0x5664e1f9, 0x7c651f50, 0x07aeb235, - 0xf0375e60, 0xb9de4199, 0xc23ed7fc, 0xff975de5, 0x31934dd0, 0xb9f7abff, - 0x387be11c, 0xc2bf425f, 0xfbbf9429, 0x83f48956, 0xc9a38595, 0xe42aad79, - 0xc91f9cdc, 0x457fd02f, 0x0df0338a, 0x744093b6, 0xde5abf20, 0xa8df784a, - 0x575db157, 0x39757acf, 0x20fa17ce, 0x707d064f, 0x603eb759, 0xe81eb9ab, - 0xf20aeedd, 0x7a1a9bf5, 0x5f9469ee, 0x07a0d790, 0xe3f557e5, 0xdc6f8ff8, - 0x209de1fb, 0x75ebc7b7, 0xd5eb35b9, 0x782db948, 0x7c84bd69, 0xc7b7291a, - 0x894ac00b, 0x3cf0b726, 0xb416dcaa, 0xaaf44bfc, 0x65c7c78e, 0xf5d55eb3, - 0x8cf86f64, 0xca9793d4, 0x127aa89e, 0xecb3ef7e, 0xf3a8fc9e, 0x457fcea1, - 0x80bd29bf, 0x9f3a09fc, 0xc5d87cea, 0xf61f3aa7, 0xf098cff0, 0x3b7f9918, - 0xc10c04f2, 0x7f255dbf, 0xdf134962, 0xdef7838f, 0xf8459fec, 0xc734d1f2, - 0x9fecdfaa, 0x11438468, 0x79447d70, 0x8fec045f, 0x80881f28, 0x4be54c2b, - 0x8c6af71a, 0x2a6c20f8, 0x2bff9d67, 0x759445f6, 0x950f3eac, 0x82d49c37, - 0x9d691fc8, 0x753fea1a, 0xe8a89821, 0x9329dc3f, 0x7003b0ff, 0xe9da04bc, - 0x0a1198d8, 0x6c591e82, 0x0ecdebe7, 0x012ba777, 0x1cf1c5d2, 0x96d24cee, - 0x9fd41ea0, 0x1fb9da77, 0xe9dfc3a4, 0x31f8378a, 0xa4c9360e, 0x6c425bc7, - 0x093f3472, 0xdf8434cc, 0x3e5bd616, 0xe0768ff7, 0x87b633be, 0xcf40cefb, - 0xfa4765ab, 0x56bf5c7c, 0x23605ecb, 0xedc16b36, 0x77a1742e, 0x71ba0d34, - 0xfd9f3c1a, 0x6db7ccb6, 0xafa53e82, 0x8471dd61, 0x2b189f05, 0x72de7ee1, - 0x4d999fe2, 0x6b321d7c, 0x28797479, 0x39e5ef12, 0x77a869e6, 0xb9f0fd61, - 0xd7ac0fd1, 0xe23ab053, 0x42f5d379, 0x3d69aa6e, 0xce6b5458, 0xd4f5880f, - 0xc9feba37, 0x7fa49964, 0xeb84a170, 0xafb7a17a, 0x38de8796, 0xb1d3e80d, - 0xbfb8664f, 0x2649aa7a, 0xc8da9cfa, 0x305953f7, 0x8cafe489, 0xd4be9275, - 0xf286d6f1, 0x7aef7175, 0x9feb6dac, 0x3e421fb2, 0xe187f6da, 0x6db482bf, - 0x778327db, 0x47cafc20, 0x3d607fe9, 0x65d84fcb, 0xc7733f27, 0x7ff1272e, - 0xa5dfcec7, 0x76f0843f, 0x3af7f92b, 0x1c3b7d76, 0xa163b1f9, 0x60f500b5, - 0x7ebe00c7, 0xedf9daaa, 0x7f9a16f0, 0x331d1117, 0x7de88d14, 0x072fe9aa, - 0x54e02e30, 0xed0a8c13, 0x24b15d8b, 0xdaafe55f, 0xb1d11fc9, 0x80ecdbf3, - 0x9e379fe3, 0xd3ffb132, 0x5ed364e1, 0x73c5fec2, 0x8ef979bf, 0xc02ecfd1, - 0xdd86f1fd, 0x9fc84cda, 0x875fdaf0, 0x78ed7ea3, 0xed4ddb89, 0xdc1acb6a, - 0x48ba18df, 0xbd02a85e, 0xfac851da, 0xd16fb631, 0x4728f1c4, 0x57f2f13d, - 0x2f9cb3f2, 0x7c28263e, 0x8feffb3d, 0xf5c7c90f, 0x9364339f, 0x1ddfdc70, - 0x89ea03f8, 0x4be2565d, 0xebc7bc7d, 0x733d9017, 0xfbdf71ae, 0x52dc6e3f, - 0xbdc67cf8, 0xff9cdfe0, 0xfa878aad, 0x3d072917, 0x03e77cf9, 0x7a726f04, - 0xc9e7bfa9, 0xa7ff6bef, 0xa025fdd1, 0xe3dcebbb, 0x4b3fff0e, 0x0ba7b7f7, - 0x3e31bbba, 0xbfb5fca0, 0xa87eff52, 0x37f96b9e, 0xe36f7ba7, 0xb7fdedd7, - 0x33f79e2c, 0x5664fca1, 0xe2c340ed, 0x6f3dd2da, 0x5bee4267, 0xb1e37b69, - 0xf623e3bf, 0x5e34f47b, 0xf1b6fee5, 0xed03efb8, 0xac4978b2, 0xab3af917, - 0xfa2fb0bf, 0x3b23cbcf, 0x63da7fa4, 0xc5304f64, 0x2bf712b3, 0xe99f4adf, - 0x360bd8a5, 0xc200e3e2, 0x6c052bee, 0x4afe6f5e, 0x4adc3e62, 0xfd7e9fed, - 0xd373b43e, 0x83b264d2, 0xf7fb2521, 0xfe64d775, 0xad3344bc, 0x98f5ae87, - 0x129347d7, 0x89a8ebcd, 0x19abbea2, 0x0ed5ffef, 0x3c021429, 0xcbf01f8c, - 0x8ea7f444, 0x126548bf, 0x605893c0, 0x263bae11, 0x9df5cc3a, 0x836c7dc0, - 0xc5eff1bf, 0x3c2ec4e3, 0x47e95c0e, 0xc9900e3c, 0x3c4e7aaf, 0x6f09bf62, - 0xc78c2199, 0xe3978a61, 0x4bd4a131, 0x1eb16a7e, 0x1da26ec7, 0x349638a3, - 0xb82b3ca3, 0xa078e69e, 0x9ebeb875, 0x4cdf0dee, 0xd115cfac, 0x257f8ea4, - 0xcdd9f64d, 0x5cfad1f5, 0xa50fcba7, 0x7fc74e87, 0xaac92e94, 0x8e692e99, - 0xebca0a39, 0x8c3f5c64, 0x1c99f2c4, 0xb42a0b4e, 0x0fd624df, 0x28e678d7, - 0xa4278041, 0xaf482a65, 0x22f6db7c, 0x79b51f8c, 0xc5c7ea25, 0x1f9a166d, - 0xe112596c, 0x428d487d, 0xf7167bf0, 0xd4f7a428, 0xfe395e2b, 0xbb3f4320, - 0xba06e34f, 0x7c97ef9f, 0xd8cce67f, 0xf0c7f46c, 0xde7fc61f, 0x59b7eb00, - 0x063859ab, 0x615b34f0, 0xf404b8c1, 0x73ec4b93, 0x0cdc9f93, 0xe4aaefe3, - 0x55ce7aee, 0xf2bd37be, 0x015f4ecf, 0x45f9f63d, 0x94c76d8c, 0xc6288a6f, - 0x9a8ff6f5, 0xf7cabe38, 0x1e40d0b3, 0x0dfb2187, 0xab2f8afb, 0xcaf33fdc, - 0x891a5f1f, 0x1d71dceb, 0x7eb8e343, 0xa971e2cd, 0x8a70bd62, 0x0ebce279, - 0xe283afd4, 0x9f74bf68, 0xe7168cec, 0xbfac41b8, 0x28f1837f, 0xb2d47690, - 0x57d7196a, 0xbefc93ac, 0x5b1b5ac1, 0x661e251f, 0x7e116a8d, 0xf8374122, - 0x7fb8d9c9, 0x0d9fdbc3, 0xe919c6af, 0xa8e536d6, 0x1d27bc32, 0x61b9f7f0, - 0xc51feaff, 0x11f7ae2f, 0x2dec1bbf, 0xf451fc93, 0xdfc0bd47, 0x91df3dd4, - 0xa6d2f49f, 0xdfe416b5, 0xa62d6b4b, 0x553ad8fd, 0xb04631f8, 0xa9afd811, - 0x2cceec7b, 0xd93ecba4, 0xe5a5f18b, 0x40b5274d, 0x48c47d94, 0xe8fd627c, - 0xdd556f7f, 0xb50eeed4, 0x75e2267e, 0xc31b09c7, 0xad76f575, 0x3f5a38ba, - 0x7ef2b4ef, 0xf7f566ce, 0xf7f8cf0d, 0x0eb8efc3, 0xae3c7847, 0xf0996b3f, - 0x1ff24483, 0x553e3e23, 0xbf3842c7, 0xf5157ae2, 0x8c8da9c2, 0xc94077e6, - 0x06feb863, 0xd1b1ff79, 0xe37173af, 0x5da0df96, 0xb924d650, 0x4ca24b71, - 0x8fd0d169, 0x2f18de5b, 0xe99c3ce3, 0xdd6fe3d1, 0xc8356ec3, 0x10aaab45, - 0xd98ef6be, 0xfbb61771, 0xd0c69b65, 0xdebdf14e, 0xfc79c2e9, 0x2491a6cb, - 0xeb8dbd07, 0x34564ae5, 0x841ce311, 0x87e48c3e, 0x4c631ba1, 0xa07215f0, - 0x54d7ca1f, 0x6f3ccb6b, 0xd32dfa14, 0x788fb124, 0xf42dfa9e, 0x7b7e99ff, - 0x016fd75f, 0x23906fd9, 0x419bc0bf, 0xd344a5bf, 0x4f25736f, 0xee7de20a, - 0x482941ce, 0xab6fb9d7, 0xdbf4d149, 0x2fbe4aa6, 0x4dc459ba, 0x7e803477, - 0xdfa0dcbb, 0x45bf401a, 0xa3191f89, 0x73fa7ee9, 0xbfd0b7e8, 0xa136fe46, - 0xde328b7e, 0x74fe041b, 0xe9bc36fd, 0xe1b7e920, 0x3c53160d, 0xf84d44f0, - 0x6fd57a9b, 0x68add252, 0xbd53ef1f, 0x67f851b1, 0x37c7b093, 0x6c46388b, - 0x955cf507, 0x5cf4c3f6, 0xb9eaf9de, 0x759e117f, 0x2b77373d, 0x9ee8b8a3, - 0xdcf5c87c, 0xe7a0eddc, 0xae47e424, 0x64eee6e7, 0xa1172fdc, 0xd0f486df, - 0x97ca8c6f, 0xe5fbf985, 0xde4f198d, 0xf08df50d, 0x941b5ea9, 0xefadd11f, - 0x5df51946, 0xbe8bd695, 0xfa7e77db, 0x77d0ab6e, 0xa206c7a0, 0x0fe48d7e, - 0xde39936f, 0xc3e8c77c, 0x79465f1b, 0xfb4c9df9, 0xf859ef92, 0xa33bd1fe, - 0x7f21670f, 0xf3fa2a7d, 0xd9e9c6a2, 0xfaa4195e, 0xc7cebc27, 0xfb91ba57, - 0xb81acbcb, 0x2b56587d, 0xe7f03c87, 0x69df31a4, 0x9dc2ffd8, 0xf8014b12, - 0x13f56b26, 0x9febb40e, 0x1f589957, 0xf034c94d, 0x629cacc3, 0xd957fbf2, - 0xfcf0eb5d, 0xd9852cd1, 0xec5fbfd0, 0xed147498, 0xbe1ce2e0, 0x9e2c501f, - 0xb3b071eb, 0x4464f4bb, 0x9ce3483c, 0x9eb3fb37, 0xad531671, 0x9f53ae9c, - 0xb7184295, 0x22ee33da, 0xb8a17a44, 0x5dfcfcce, 0xc9377f21, 0xf62f842d, - 0xee351cae, 0x85d72f43, 0x4f027da7, 0x9e131780, 0x3c545242, 0x64a7a501, - 0xa5e37726, 0x4b2d77f0, 0xf0a05f70, 0x91f68929, 0xe3adc723, 0x3afc722d, - 0x773f751e, 0xbf2fa8b1, 0x6b9d2d69, 0x8e8bc48a, 0x747c48e7, 0x1f023de1, - 0x7e5d69ef, 0xd71891ed, 0x7a437c04, 0x809ff826, 0x3fc76817, 0xf9d322ee, - 0x5e048f9b, 0x9b8f5646, 0x370fe180, 0xe43a1c61, 0x79ccd5e7, 0x63e02fb3, - 0x119ec7d4, 0x315e9d38, 0x7dc01ac6, 0x4ef60dda, 0x1f3a83d2, 0x3e72b30e, - 0xd95e84d4, 0x3c62afd1, 0x251bf3ad, 0xe521da37, 0xb5e13b61, 0x0ed1f81c, - 0xf53ef645, 0x578124cd, 0x6aaf9d37, 0xd013f314, 0x26eb82c1, 0xf10abe7d, - 0x9b2358f3, 0xebca5d38, 0x58b25d38, 0x94c7ed27, 0x30de48d5, 0x71aca78c, - 0xeba1c50e, 0x0e7e19fa, 0xf0a29d23, 0x7f8d12af, 0xb39b3a19, 0x62cde7bb, - 0xb5aa6e51, 0xe7dc43fa, 0xb1f20a99, 0xfe10d896, 0x3efe1677, 0x2450fc57, - 0x78132ebd, 0x757884db, 0xb93afe20, 0x8efe15fd, 0xf9e969ce, 0x84d04ae5, - 0x9f4f09d7, 0x53b7fce6, 0xac5fa0f2, 0xcfc86f0b, 0xc74a3f90, 0xd233f21b, - 0x465729a1, 0xddf00f38, 0x78e7a327, 0x28d4bf71, 0x0f3b85f7, 0x919ffaf2, - 0xb8ca2cbc, 0xff7f307f, 0x4deebe40, 0xc55987de, 0xf7f0413a, 0xfdcef63b, - 0x77bf9123, 0xd12fdc4a, 0xf7da6f14, 0xd7cac1bc, 0x20ec1b4d, 0xf6dfb807, - 0xe75deab6, 0xae1fa9e9, 0xc03972b2, 0xe0c784f5, 0x0704baf7, 0x75a6f182, - 0xa4178a36, 0xf6e40c7e, 0x6f5f51aa, 0x5ba4b3b2, 0x7faf7ab3, 0x37bfa88a, - 0x8787497b, 0x47a87b61, 0x21bda11b, 0xce45eddd, 0xe0ffba17, 0x43bae35c, - 0x3bdfcff0, 0x1f9dbd2e, 0xce554f1a, 0x4c5f699a, 0xb54aab8f, 0xd1515e04, - 0x992c9bbe, 0xe7a0b7e2, 0x70ffce82, 0xa36ab7fd, 0xa59faf7a, 0xd08ec8da, - 0x2d5ecbcf, 0xf010583b, 0x254fa5f6, 0xe32b0179, 0x7f38b183, 0x1079878c, - 0x8ff72f92, 0xca6ee8fa, 0xed9f6997, 0x29f5dfc6, 0x1bc87dc5, 0xbb1d0c79, - 0xfb225331, 0x6cac3de1, 0x36e1da34, 0x268ab3e6, 0x47e73f21, 0xd73c21f1, - 0x3d5b5992, 0x3d7203c1, 0x85542ea2, 0x674277a9, 0xaf483be2, 0x7a433271, - 0x4cfafb35, 0xbef7f9c0, 0xdc4cb33f, 0x813b078a, 0x8fb119ea, 0x31b96125, - 0xce5a24be, 0xeaf86e8c, 0x7fa05bfd, 0x5ecbf7a3, 0x69bb940f, 0x7281c3af, - 0x85b56436, 0x19780c05, 0xe85542c3, 0xc87d1a77, 0x83ea0b77, 0xf07bb002, - 0xd341497c, 0xc2172ada, 0xbf7a25ab, 0xe498183c, 0xaa6dfe82, 0x32e93939, - 0x0e500bd4, 0xcd5f29ab, 0x4ad795cb, 0xce710c5e, 0xf1415a6b, 0x12b57948, - 0x14dc601d, 0xd78d9892, 0xbd41b21b, 0xfbc3569b, 0xc17f3859, 0xed6f58fb, - 0x416ff7c9, 0xa4fd03bd, 0xfdf237f7, 0xcf783cfa, 0x3b527283, 0x5c2bea87, - 0x073c312d, 0xcf91b053, 0x55fb054f, 0xec37e62f, 0xdde68a7e, 0xdf5ed029, - 0xc28f9c0c, 0xd13ce913, 0xe74dc948, 0x80be1f38, 0x0e0756f4, 0xa5f05f18, - 0x4909f8f3, 0xa3fd62c0, 0x6dfd7fdb, 0x9e535cfc, 0x07d68177, 0x272779ea, - 0xfc42c329, 0xe1f69274, 0x03be010f, 0x79379c56, 0x9cdecb3c, 0xc316b42f, - 0x1b6398fc, 0x6acfef44, 0x1e71471c, 0xe29f99b3, 0xe68ea63c, 0x57bbe776, - 0xefe843da, 0x4ced577b, 0xaf7be7c3, 0xf6f3d2b4, 0xb70f5c4d, 0xbf21680f, - 0x2ad5e1fb, 0x552ff3c3, 0x13d265ab, 0x74aa3787, 0x867e576e, 0x6fe437c7, - 0xdec876e2, 0xc3debcd5, 0x9b7edc75, 0x936dccf0, 0x5fce1e70, 0xeaf9cfcf, - 0x875f5a7a, 0x4d0bb9e6, 0x9ea45bf3, 0xa970f5d5, 0xf54147c0, 0x8f4fda5a, - 0xfaa5bbd4, 0x6fa1187c, 0x9d9f714b, 0x24c3d3f6, 0x91f5a547, 0x6e8e65f1, - 0x43f20dbf, 0xefe23bf8, 0xc32afdb2, 0x45f48d75, 0x678a24db, 0xf21ef9c3, - 0x3e493747, 0xf8287b8c, 0x7b221ad8, 0xe33b943c, 0xf99e703f, 0xc8f0cac4, - 0x03d22b48, 0xb58e54f4, 0x84bf8ff3, 0xb3df47e7, 0xf010e461, 0x5fe12e4f, - 0x5ace138f, 0xb27ee3cf, 0x8c995bde, 0xc4d98de7, 0xf207a43e, 0x3016646b, - 0x92a38de8, 0xf93b96ef, 0xfb46e0fc, 0x966ba747, 0xf3879d56, 0xeb8d916c, - 0x957acf47, 0x0bc78bce, 0x3e0bd618, 0xb70a77b4, 0x0cd648af, 0x73b850fc, - 0x0ea83245, 0xcbc444b6, 0xe6738954, 0xa76f1a85, 0x5ee49770, 0xaf47686b, - 0xdb57af47, 0xb41bdfce, 0xd5bda793, 0xa3fd885f, 0xa1ad7e71, 0xa7ac88de, - 0xd4bdfb47, 0xa75ff393, 0xffb9e257, 0x0a65779c, 0x62f9cf76, 0x3ee320ca, - 0x7eea9e8f, 0x2df7ece6, 0x5fc067cc, 0x98631fce, 0x86ef40cf, 0x40ff2051, - 0xb91a1bbf, 0xea30d73d, 0x459a56a0, 0xbde51bb0, 0xcba3f84c, 0xbbfdf226, - 0x16f7cc86, 0xc94ffca1, 0x581f8892, 0x49f5a030, 0x83cdfb24, 0x59f900fb, - 0x787cfdfc, 0xe1b2e51f, 0xa0a72e29, 0x4fa83c2f, 0x98af56ca, 0x256be544, - 0xb0dfd60f, 0x92ec9736, 0x51991c82, 0xb241ed7e, 0x0f1a0a93, 0x833ca226, - 0x7b44aefc, 0xd5ac6ca0, 0x9758ea8d, 0xdfce5d4b, 0x9961e715, 0xcf0c3dcd, - 0x5876e077, 0xf796f934, 0x72b76133, 0xe1cf2cb9, 0x26eefb72, 0x3e784715, - 0xad724e72, 0x728cb1cb, 0xc72dd59c, 0xd04f577b, 0x870fae50, 0x99a38a24, - 0xe5007a80, 0xe71e837c, 0xf3d8edc4, 0xd973f395, 0xbf20a599, 0x72ea5f38, - 0xa475cbae, 0x2d2b373c, 0xee3f62b7, 0xe34ed2bb, 0xf6d57098, 0xfae3ef0f, - 0x275ff68a, 0x3260f55c, 0x853cc7ea, 0x78e979c7, 0x5c78552d, 0xad7e8f60, - 0x3df5a05c, 0xf445fe9f, 0xd9ab33e3, 0x8b6f125f, 0xb5eff1e7, 0xb9fdf12a, - 0x9c87b3e4, 0x9e7ca79d, 0x4b9d5caf, 0xe5f6f53e, 0xe27ae69d, 0xf5476991, - 0xf01dafac, 0xbe3c0618, 0x8a59f1b5, 0xc2f13e0f, 0x8748a9c1, 0xe7c01de2, - 0x9d1b5fc8, 0x4e7a8c2c, 0x55bcd109, 0x39d320d4, 0xb384a603, 0xe51a716f, - 0x1575c798, 0x3f12766f, 0x0d64bd15, 0x8bf7814d, 0x9c317db6, 0x76166ae2, - 0xf05adc52, 0x072f6105, 0x1ca3865b, 0xbe3c2914, 0xfc2f522c, 0xe7edc6da, - 0xd3b1edb6, 0x1d527c70, 0xa8a2dfbf, 0x6ad576fe, 0xc278a7d8, 0x50bb52a6, - 0x8379f68e, 0xfe78c7c0, 0xbc67fb17, 0x2b8f4157, 0xf5c0db6b, 0x1aa35144, - 0x8a327bc2, 0x63b4b6ea, 0xc7d171bc, 0x957ff256, 0xf3a49dd7, 0x6f361314, - 0x794aff22, 0x8fda6ca3, 0x59df11eb, 0x18ad8727, 0x4a50d897, 0x1f0090fb, - 0xc45eb824, 0xf8c0fe53, 0x3bcde2c3, 0x850105b7, 0xef3f2fc5, 0xac72fd42, - 0xf10bbd79, 0x359ef50e, 0x3c47bade, 0x2223fd67, 0xc386f39e, 0x2f4b6f74, - 0xf0c79cf1, 0xb794100f, 0x4e78e66d, 0xec87d756, 0xb667e84b, 0x47feca3f, - 0xe9be7d97, 0x1e7835eb, 0xe3a5eda1, 0x25dfb06b, 0x0d72fb7f, 0x5db189c6, - 0xcaf79a76, 0xe280f85f, 0xbef7f5b7, 0xc87f09b0, 0xfe29e786, 0xab13fdbd, - 0xdf6b6b17, 0xe31d3879, 0x7cb7db06, 0xccfe8c97, 0x26af3b79, 0xadbcef7f, - 0x94585213, 0x914f4379, 0x11e7437f, 0xb7491f7f, 0x297b0dbd, 0xd004ed9e, - 0x5760f51d, 0x297d6e9c, 0x88f67f8f, 0xd18ddcf8, 0x88f43bcf, 0xe5b86dc7, - 0xff512bc6, 0xf27b7037, 0xefb9719c, 0x3f2f3d03, 0x146e3a0f, 0x37f5d7f1, - 0xf72e359c, 0xf401fe04, 0x74cdd8b2, 0xf661bafc, 0xbcc69faf, 0xc6bd3e86, - 0x03cf86e5, 0x8a79fa7f, 0xa73e6c77, 0xa5e8e51d, 0x343c50df, 0x078a6fd2, - 0xd3afa3e7, 0x11ca3cf1, 0xce3a73b5, 0xad3b9d3f, 0xd14fdf74, 0x9e488fce, - 0x47beb7da, 0xce266a7e, 0xaeb3b435, 0x973f8f1f, 0x9d6b78c4, 0xd0579e3c, - 0x3d7de301, 0xe22e7a2e, 0xeb5f397a, 0xc5bdbef1, 0x1f6d5ef9, 0xe00fee28, - 0xb5a5c8f1, 0xb3f1107f, 0x729374dd, 0xcf075e90, 0xe3ad471a, 0x72f42dc1, - 0xf47b1c77, 0x38aeeab8, 0x21ba08f6, 0xea9e713d, 0x3807538a, 0x49f9046d, - 0x2e768a3e, 0x8f2d7da2, 0xa3576f7f, 0xe3d6379f, 0xf4117dda, 0x9bdbc7d6, - 0x7b72e8bc, 0x50fc71ae, 0x4266d13c, 0xb57c4f52, 0xbf5d1f7d, 0x7f4bb4cf, - 0xebbefad7, 0x148954bc, 0x5eeb1e79, 0x86d2cbe4, 0xeccfe483, 0xf18b7f5a, - 0x7bff09b6, 0xc5320bdb, 0xdfa92f39, 0x523dfa4b, 0xbde1947f, 0x7bfa512d, - 0xe7d85dbf, 0x68fe7c8d, 0x7219c97b, 0x7b6d3d40, 0x975f13b6, 0x71483c6d, - 0xbdd66fd6, 0xe218b5ac, 0x08fe7027, 0xf6d3c619, 0xa4e1eee2, 0x30fdc5cf, - 0x8954ed91, 0xa29bca76, 0xf1be53b7, 0xe29da9a4, 0x76e6bd60, 0x63bdbb9c, - 0xac76ef8a, 0xb73358ef, 0xcbd58f13, 0xf6d14393, 0xd8aaec69, 0x29e6afef, - 0x0f74a3cc, 0x7bdf938e, 0xc862bb23, 0xcce79cee, 0x112e38f9, 0xbae28d53, - 0x388816aa, 0x537a9fb0, 0xce55de91, 0x77f618eb, 0xe0d7e231, 0x01dd51ff, - 0x9aaaf686, 0xbf42cfea, 0xd1dea443, 0x642c2d12, 0xe73cf7a0, 0xed0f14e4, - 0x90d3848b, 0x0f32079e, 0x67ef58ab, 0xcfabfe11, 0x0524b614, 0x5059f7fa, - 0x7a802ef2, 0x0c5ff7d9, 0xd67b3bf0, 0x8781c3af, 0xa9bf9365, 0x0079dacc, - 0x35ec2bd7, 0xc847ed3b, 0x7f74ecbb, 0x3b1af948, 0xd6ef778d, 0xbb239f6f, - 0xc656d7fb, 0x556087f7, 0xb996f783, 0xb7871d79, 0x2fe6bb7e, 0xcbe35768, - 0x1afe7ed0, 0x89eb8f28, 0xfeb4b18d, 0x8e2978e9, 0x7fcb51ee, 0xa8a9a1ed, - 0x3963f2d7, 0x4e6fe63f, 0x7d415509, 0x6e1c49ad, 0xee8034dd, 0xc97e28ab, - 0x7ba5f149, 0x8652beb7, 0xe6fb54f3, 0x60330c58, 0xfb09afed, 0x7ee237ff, - 0x63d51aad, 0x642f338c, 0x2e78c78a, 0x536118a8, 0x3f23135c, 0xfa11c906, - 0xe8e31ab1, 0xc5d8113c, 0xa84e7aa6, 0x89780f9d, 0xf8fd838f, 0x3f70aa39, - 0xe59107d4, 0x76fdfcf4, 0xdcbd8e7e, 0xba39ef0a, 0x9d6b97cb, 0xeeae1c79, - 0x3349f5c7, 0xe744ff95, 0xb3df9173, 0x23fe5e5e, 0x7aaedebd, 0xe265fbf8, - 0xfe489b7e, 0x57a5d43d, 0xb4717afe, 0xf4a25bfb, 0x2fdf9e9f, 0xed05a0b1, - 0xba762d96, 0x67ef0bb7, 0xdb0e73c0, 0x55ffbe34, 0xfdd30ae2, 0x3e843b39, - 0xd309892e, 0x44fd3e7d, 0xc23cb03f, 0x22f2d6cc, 0x15f4bdd2, 0xb3f8c33b, - 0x3e9cd7d2, 0xb6e977a4, 0x957f5b6f, 0xb18bf185, 0x7d2bd7e4, 0x1f117fed, - 0xd3c35a94, 0x2dbcfee9, 0xe7f78656, 0x3b796db5, 0x4db5e51d, 0x9c27a70d, - 0xb4af5f65, 0x57be6ade, 0x58e38c40, 0xbc42e865, 0xaf3f4177, 0x9e8bd45b, - 0xdb8632b9, 0x9f18f6d7, 0xdde48635, 0xb1d44f7c, 0xc641c6ca, 0x9e45fbf3, - 0x7fb17ae8, 0x9d8ffa8c, 0x38f47743, 0x263fdaf7, 0xe699ed09, 0x96407464, - 0xfa8e3d81, 0xe4eea8bc, 0x7c1ff430, 0x6fdfa316, 0xf9c389e0, 0x73ad33e8, - 0xcfbfea18, 0x19873bd2, 0x952399e7, 0x92a28f36, 0x8ed2875f, 0xfaf327b5, - 0xb5378c31, 0xf7a68b4f, 0x12c4c586, 0x8e1e8afe, 0x7a8e7a8d, 0xabe70c4c, - 0x531f6834, 0x43e5176c, 0x2d33f76f, 0x31b87a44, 0x49ebc3c6, 0xbcf8690b, - 0x20fb6eb8, 0x950a1e23, 0x72072a6a, 0x642cf84a, 0x832cb52b, 0x2bdbd6fe, - 0x28f0ef9c, 0xf2813f74, 0x55f8ba7f, 0x3933a6ee, 0x518e3191, 0x5c6614e0, - 0xe7eb33f2, 0x6fd51448, 0xcc69fc43, 0x646456ef, 0xf7926a95, 0xa94f5618, - 0x7e2ecc03, 0x43055a5f, 0xec44793d, 0x0c1fa3ef, 0x3d7c6ed3, 0x383f7a48, - 0x328bb180, 0x4f09bef0, 0xbf80db9c, 0x3eb3706b, 0x2b69e309, 0x5317d718, - 0x488f68dc, 0x033b00c1, 0x595554fc, 0x03df8837, 0x2f187cc2, 0xf42c2649, - 0xf37ee5cf, 0x8083b43b, 0x843df94f, 0x1550b157, 0x86c318a0, 0x9e3aefc9, - 0x96f3fbf1, 0xeb8ccc7d, 0x0741128f, 0x7a4ddc16, 0x7fbac1cc, 0x5aa3009d, - 0x155b7d45, 0xdc1cb7f7, 0x59b8739f, 0x58c3ed18, 0x42c70b07, 0x1caa18ea, - 0x2bbfca33, 0x5f03600b, 0xf39ac7ba, 0xf402e523, 0xf5bb445a, 0xf7a83f84, - 0xbf7a88ab, 0xabf7a88a, 0xe3abd5b3, 0x2836dca9, 0x58a5ef03, 0xf02f595c, - 0x09b3dbc6, 0x867e01bc, 0xcc7f3de0, 0xfb15e312, 0x18d784e6, 0x962b1bd1, - 0x8e6eba07, 0xfa7e20c9, 0x4eaedc59, 0x8966978c, 0xc3d70c35, 0xbefd248b, - 0x1877e64f, 0x1b6e63de, 0xa223e1c9, 0xcf02cd9d, 0x55bf748b, 0xb276f28f, - 0xb7947abf, 0x263e56f7, 0x6f67797a, 0xde8d89fd, 0xea5ef89f, 0x5a8d8eaf, - 0x4bd50fff, 0xf47daf65, 0x76efee0e, 0xa03727e9, 0x6e676cde, 0x1a54fd46, - 0x16b7fadf, 0x4cedc27a, 0xde999a5b, 0xc0dfc831, 0x9a17316f, 0x49f2479f, - 0xf472fe14, 0x29df7185, 0x61f3bbda, 0xe74d5e7e, 0xbe315c83, 0x9f7cb589, - 0xdc79eefc, 0x46cb078f, 0x25dfe61f, 0xe1aeeff2, 0x0fdde3f6, 0x1b0fb4cb, - 0xc1d5bf79, 0xe1efcdff, 0x801f07b8, 0x5f33ddbc, 0xa233850a, 0xdec5dbdd, - 0x677a878f, 0xde44fe88, 0x9e601583, 0x68e4cb49, 0xbe7160f7, 0x45e1cfd4, - 0x8b317fde, 0x66fdc5f9, 0x3159e7e6, 0x22dbe26e, 0x0f55a425, 0x82c79eed, - 0xd1ef802b, 0xc7be04fe, 0x9c592ffd, 0x8d2e66c7, 0x9adfd7c7, 0xa77fd260, - 0x70e27886, 0x8baf66be, 0x7cfe6ee7, 0x149eb5ee, 0xe54579e3, 0x1ee9ac74, - 0x9bd52aa0, 0x3d4dfa8a, 0x80f33d7d, 0x07a76a1c, 0x1f218f31, 0x7e1256ec, - 0x3d24f30c, 0x5084aa95, 0x3f6e2a2f, 0x37bb47cb, 0x5eb3f39e, 0xaebc4b5e, - 0x177ccecb, 0xe6461dfe, 0x5dcfff81, 0xdff3a1e1, 0xa7fc3957, 0x5d95fe71, - 0xa380de39, 0xb7043f27, 0xe15771f2, 0x8e7a33b8, 0x7af34aa7, 0x0ebedec9, - 0xcbf245e6, 0x3fd86d79, 0xc8f9ead9, 0xadfbfd83, 0xd30fd0ca, 0x23de3f13, - 0x153fc821, 0x24714fea, 0xc194dc72, 0xbc72fed8, 0xfff4146f, 0xe8bf7132, - 0x52264aa2, 0x08b7571e, 0x34a51fef, 0x913ea447, 0x8f72a64e, 0x974a7b8a, - 0xd5297a54, 0x56f36bf1, 0xb6983dd3, 0x36fb790b, 0xa25fa0b7, 0x402fe045, - 0xb52d97f6, 0xed1df682, 0xde308aee, 0x60d2c727, 0xb961c1de, 0x9abf09ab, - 0x13bf919b, 0x456c13ca, 0x66b55218, 0x7149d10a, 0xc87cb057, 0x0604754f, - 0xe37da2c7, 0x6987df31, 0xd6711d4d, 0xf8bb31fb, 0xfbc7136d, 0xb7e71263, - 0xa63fbc48, 0x6e307b36, 0xbb6bb1e2, 0xbc22abee, 0xe38872c3, 0x7ef93ffd, - 0x37bc4f6e, 0xc0699b4f, 0x327b33bb, 0x0267fde1, 0x5e054bcf, 0xaa1d04ab, - 0xc4ab3e04, 0xe255afbd, 0x812adcde, 0x3bc42adf, 0x7b888fa4, 0x3d23177b, - 0xef119520, 0xa1d6bfc0, 0x7b432641, 0x520f0f7c, 0xb75be087, 0xb2a4fc85, - 0xbc43efc3, 0xde39135b, 0x03a00e6d, 0xdde035f1, 0xc241f983, 0x78e0eaa7, - 0x0e9cf286, 0xef105602, 0xa739f123, 0xb6fde007, 0x87d424d8, 0xd6784c63, - 0x1f9fc712, 0xf3e29fde, 0xf390a25b, 0x6a25fc48, 0x5d605efc, 0x8fb37bbe, - 0x765c44ab, 0x1197b895, 0xcd7688f1, 0xbb0fc02a, 0x3f93e398, 0x2f60221f, - 0xfd6249a5, 0xc074055f, 0x3d8527fc, 0x74c67884, 0xb75f2c67, 0x762a5a24, - 0x04a788ab, 0x4b0fdf7e, 0x6cb4b20c, 0xf18043c6, 0x1e641a97, 0xe1fdf584, - 0xc8ff335a, 0x7ee2256e, 0xc893cf49, 0x56df2b6f, 0x2f7fb82d, 0x74debfcf, - 0xe69e5bae, 0xfe10f78b, 0x35da1203, 0xb872133f, 0xfa85f902, 0x8bc3d7c7, - 0x152c1f05, 0x223f06f7, 0x2131e7f8, 0x7ceb8fcf, 0x48e7e5e3, 0xf1e64f96, - 0x1699898e, 0x9862bf71, 0xe309e319, 0x834cf5bd, 0xc6dad17e, 0x9fdd2943, - 0x92b63ec9, 0x650ec6dc, 0xf8afe43e, 0xf10c1f8f, 0x7dfd70fb, 0xd78a1ed1, - 0xeb1dbfef, 0x0e83bf89, 0x711587b4, 0xd7cca4cf, 0xef51cd93, 0xeef2ad8d, - 0xa65fa1b1, 0xbeecfeb7, 0x73f11b69, 0x1e44e5de, 0xbfe027d6, 0x8ec03663, - 0xc157581a, 0xc81bd62f, 0xa57a8c5e, 0xebfc49c6, 0x1be7fe80, 0x17b624f8, - 0xc754ceff, 0x5f501bb5, 0x240680bc, 0x6a2fc130, 0xcf11d906, 0xfa0f7380, - 0xfea956b1, 0xac2f38be, 0x8fee8f8a, 0xdf2c65fb, 0x5d657087, 0xac2bf26a, - 0x9ef47d54, 0xef59ac7b, 0x44f314ac, 0x9cb344c2, 0x4fc2f3e8, 0x39577d45, - 0x5fb13b02, 0x9227a7c9, 0x1cde273c, 0x52a89e7d, 0xf7de20b5, 0xcb8c3551, - 0xe3573077, 0xfd0f73f6, 0xe49f68c3, 0x3af06054, 0x7ce983f4, 0x7d7190b6, - 0xaedc6417, 0x04f5c7d4, 0xe715bdf2, 0x3ff13703, 0xcb0807ce, 0xdefc6a17, - 0xe42dbbe3, 0xe4225887, 0x672151ed, 0xfd7c85cb, 0x8acbe51c, 0x297b58f7, - 0xab9085fd, 0x90872895, 0xe0cd8f1e, 0x3fb8bcf6, 0x2ccf5f4c, 0xfba08db4, - 0x161cab22, 0x4f94179a, 0xae0721ac, 0x768f760f, 0x7647ffa3, 0x4e03b966, - 0xfba2cfcc, 0x2cf8a5dc, 0x37cdf237, 0x9c1759ce, 0xc8161e2d, 0x2b16f74f, - 0xea4bf72a, 0x8957c8f7, 0xf75408fb, 0xd5fd0ccd, 0xd856264f, 0x9635de29, - 0xe4d787c7, 0x81de1366, 0x86b19d1e, 0xb4ca5a75, 0xfbeebaeb, 0xec9feac3, - 0xef835ee5, 0x6960de85, 0x41a17641, 0xfb88d44f, 0xc8279924, 0xc5f41886, - 0x31268bc2, 0xd4f5eff4, 0xcde8bd13, 0x2e6f5cf5, 0x4deba292, 0xf5d78edd, - 0xd17ea466, 0x4c17c5d3, 0x54bf9d36, 0x7a465e1d, 0x3f744867, 0xcac3b242, - 0xd7992ff7, 0x33d19b9b, 0xec95f01f, 0xed0be030, 0xf16fdd21, 0x89e328e3, - 0xae4793d4, 0x00d7e7d3, 0x4b343bdd, 0xfa393cf3, 0x79abf3ac, 0xfd3fc85e, - 0x794fcd08, 0x5a5347a7, 0xd92d7350, 0x69770c23, 0x1c2ef70c, 0x0bbf7d5e, - 0x46b87be9, 0x56af9fec, 0x74bf1843, 0x197166b8, 0x0f76d5c1, 0x2fdc66d2, - 0x3de1741e, 0xc8d6b34d, 0x247e9fb4, 0xf14e9826, 0x399fdf9f, 0x63e21b23, - 0x9a5dac16, 0x6b38fc8e, 0x373a52dd, 0x37c1247b, 0x59806fd8, 0x79ec8796, - 0xbcc6fefd, 0xb43ead67, 0xdbe37bc7, 0xfdd1d5bc, 0x27f8553d, 0x779853ae, - 0x7643ae08, 0x8674c6bb, 0xfc8e0f81, 0x82eb4ec2, 0x8ed82d2a, 0x58bad570, - 0x2555837c, 0x280fbf44, 0x0fb571d5, 0xf0ea94e9, 0x73298b5d, 0x4f7ed024, - 0xdbc472ef, 0x3b5f456f, 0x2d3ebbee, 0x3a0245ee, 0xbbf264dd, 0x56d77df2, - 0xb66347e1, 0x4463f25e, 0x7c97a7be, 0x62938f17, 0x7ff9e8ee, 0x6869ffb7, - 0x315df58f, 0xe6b4bf8e, 0xe84f92f8, 0xa11f7989, 0xcf8bc450, 0x5a1b175a, - 0x66ce4518, 0xb3c7f389, 0xce997ec4, 0xebd7858f, 0xe3e739f6, 0x5e973e48, - 0xfaf884b8, 0xcd2a7dcb, 0xafc0656b, 0x17a5efa8, 0x507dd346, 0xe2bb9e0b, - 0xfc0b8c71, 0xf94cbf6a, 0xc4eda725, 0xf53fedc7, 0xce8239d2, 0x9df4a9df, - 0x5df6af88, 0xda01e74d, 0x3ad3fdc5, 0x7c9cd29e, 0xc1c6bc3d, 0xe9de50f5, - 0x743c919f, 0xa66857f1, 0x779e7286, 0x5e5ce7fa, 0x31d9fef0, 0xdeebec38, - 0xe0a1771c, 0x2cd7806b, 0x2169349f, 0xc2df9bd4, 0x0d8d8ae5, 0x7b1f9196, - 0xd1f7ac6d, 0xc6bff228, 0xb5f931e1, 0xf3965bf2, 0x4caec0f7, 0xcc99c434, - 0xc87bdf12, 0x65efcd3f, 0x4b20ee65, 0xfa127945, 0xcc0e5bb0, 0xdbb772f7, - 0xd3d4e3cd, 0x79c6bb17, 0xd6fd6985, 0xe8abce3d, 0x53b09e79, 0x13465bf2, - 0x5f9e3ddc, 0x9e368e8d, 0xa58c71ee, 0xd1f1edf2, 0xb450ffdb, 0xc0595adf, - 0x8b4fa07c, 0x79bffdc4, 0xd434fba1, 0xe3ab791f, 0xb8c32413, 0x4d8a6bf2, - 0x35794ff1, 0x5fdf74b9, 0xed5ceafe, 0x76bc835e, 0x36cd85d1, 0x4743e5d1, - 0xd532e880, 0x40e3dfe1, 0xf0a17cb9, 0x583d4f81, 0x11d3a72f, 0x82bc382d, - 0xae7ddbf4, 0x3ea7e768, 0x8d53a48c, 0x1fac13a0, 0xd2740cb2, 0x7ef913e9, - 0x07d2faeb, 0x8bfdc53e, 0x45edf8a7, 0x08b1ebbd, 0xc74465fa, 0xf383a75f, - 0x0fd82b6b, 0xdfc2f381, 0xbbf8a665, 0xe827f15e, 0x7f47e3ad, 0x51dff60e, - 0x944efb94, 0x1f5851cd, 0xe17387e7, 0xc17dbbad, 0x8fa2e30f, 0xf3a9c527, - 0x04167cc3, 0x71aa3e01, 0xf1f7a3fb, 0xb682c43c, 0x974f18f3, 0xf1362e9c, - 0x01738a43, 0xff415397, 0x211e7ba3, 0xc50d6ebe, 0xbd19ed7a, 0xd9c5278f, - 0x185c1f0b, 0xffb34364, 0x11c1f1ef, 0x29f837cd, 0xde60479c, 0xf0bd79c2, - 0x1b86c7f9, 0x18ea97fb, 0x79c4e697, 0xf6fcfaa9, 0xbde383b7, 0x1e1d70fb, - 0xab7b275c, 0x8e254860, 0xbf7c60c0, 0x37f4f5c8, 0x145bdfe8, 0x68f0c4ff, - 0xcae2f476, 0xdfa0977d, 0x99b2aab5, 0xc5d85552, 0x0ce2ed0c, 0x688f5dfe, - 0x2b5e05f7, 0xcae2ebf4, 0xb5b7ee66, 0x70db9905, 0x323b00cf, 0x8ad8fc92, - 0x69cf6cc3, 0x7e8dc06a, 0x83dc4d73, 0x65812aa0, 0x67e85919, 0x1a0ccc4a, - 0x938d77f0, 0x4f2cd7ef, 0xfdc6e3dd, 0x8fd42b10, 0x9a5b33fe, 0x77e4ca72, - 0xe5995d7b, 0xd7e93a04, 0x7ab0c744, 0x1f91249f, 0x1f8454f2, 0x1fa994f2, - 0x7da6cd89, 0x28bc488a, 0x281dfe36, 0xb3ff0985, 0x9dfe87c0, 0x3e6ea5a4, - 0x8fc295ce, 0xaffa04fd, 0x363b022f, 0xc1f645d6, 0x7c2c0b92, 0xe853687d, - 0x3c6b2bbe, 0xf1c5af2f, 0xff71d871, 0x59f5c643, 0xde276098, 0xd5d32610, - 0xf1c2128b, 0xdc2123cc, 0xe0978587, 0x5c63a37a, 0xfcf803cb, 0xd7207b79, - 0xa6ff7809, 0x0901f36f, 0x81fc33f7, 0x35cf118b, 0x03d33072, 0x772d7fe5, - 0x74b96266, 0x8138fac8, 0x39e017a7, 0x9f618087, 0xdcd7df94, 0xe13dcb0d, - 0x112be60b, 0x5fdf86fb, 0xc7b7cc6c, 0x1fb02af8, 0x4acbdf91, 0xfda242fc, - 0x074cfc41, 0x34fdff9f, 0xf2772f3f, 0x07f10575, 0x6e3ed7f2, 0x3c529d3f, - 0x87efb871, 0xb4dd79d8, 0xbcf363ef, 0x114f686e, 0xe05ad8eb, 0x4fb0c557, - 0xb3e2a177, 0x545d3f20, 0xfd8dcf0d, 0x2727628d, 0xf2dae838, 0xdebd76a8, - 0x83af3c3f, 0x4f4f94f8, 0x92247b22, 0xed74762f, 0x69eff027, 0x9e33a1dd, - 0xf1c388b2, 0xfad1ff4c, 0xfdae93ee, 0x761c45aa, 0x5efca873, 0x69fe3fbe, - 0x99c51c6e, 0xa3b8fdea, 0xda336969, 0xf53477c5, 0xbcf8899d, 0x3fe2e0a3, - 0xed43ba63, 0xfa8b13dc, 0xce897ee2, 0xc1f9dd97, 0xa42c6aeb, 0x475fdf5b, - 0x2f3c1ff7, 0xeb3a71e4, 0x01fe9154, 0x7ef8d6e6, 0x47df8857, 0xae02bcc5, - 0x715fd157, 0xdb743877, 0xf3dd000d, 0x3406e87a, 0xebefa6f7, 0x43d5037c, - 0x893ddea0, 0xf7f494f6, 0x726fbd1a, 0x35d7bf98, 0xe346c57e, 0x8daf1ee9, - 0x0f8fafc6, 0xeff84a7a, 0xf7b88fc2, 0xf8c7c74d, 0x77dc7c99, 0x1d75dec4, - 0xe03acb3b, 0x3fb0db0e, 0xde3e78f3, 0x7cfc489f, 0x1fa05985, 0xf6fa745f, - 0xe33e3f20, 0xbd45edf4, 0x4ceb6257, 0xbc920657, 0xcbcf85bc, 0xc905c0e4, - 0x0313fe30, 0x21271702, 0x9cfb9a1e, 0xc07fbd97, 0x80fbf9ce, 0x81f7f39d, - 0x5baf9d0c, 0xecd7c89c, 0x538d2274, 0x92c77eff, 0xbb1f87ad, 0xc4fbf81d, - 0xbb3efcdb, 0xe373d952, 0x9697e443, 0x3e2e3199, 0xfc203d32, 0x7c5d2d0c, - 0x433bc7c8, 0xa332f2e1, 0xc1ce9621, 0x9b2f98cc, 0x319fdbee, 0x32c3c79f, - 0xadf879a5, 0x22c275a6, 0xb3d2d711, 0x4483f41e, 0xfe7333d6, 0x6517ba04, - 0x471ee69b, 0x9c35917e, 0xf44e66cf, 0x608e78c9, 0xf68932cc, 0xf21f47f1, - 0x3c00b634, 0x45ef1433, 0xe0f99d31, 0xfbc20d7f, 0xb99aca51, 0x9e45347f, - 0x4853f993, 0xf3e1ed57, 0x1073c23d, 0xc79f0e4f, 0x69cfd861, 0xdd322b53, - 0x38f7cfc8, 0x7207a87c, 0x827df56f, 0x22fdd574, 0x0afbbcfa, 0x171801d8, - 0x27b77b9a, 0xb724f907, 0xd4a3eede, 0xd01894c6, 0xb30ab96b, 0x31a29a61, - 0x0c698ec5, 0xbd9a61b3, 0x354fd850, 0xe0fd9137, 0x786bf1ca, 0xd36e79bf, - 0xfbe35ff3, 0xb7784af9, 0xdcabe064, 0xa3bfb7a6, 0x3f3e7673, 0x565efdc5, - 0x9fd699a7, 0xf0cdeac3, 0x38668de5, 0x47866c33, 0x65c333ee, 0x67683638, - 0xe11ef88c, 0x86569d9e, 0xde2b2bdf, 0xf438a56c, 0xa0ae7157, 0xe93b5e78, - 0x4dc509c5, 0x712718d9, 0x05a745fc, 0xfe3b95fd, 0x59c532fa, 0x658a6e74, - 0xfbb86718, 0x831618d3, 0xed9bbc71, 0x18bf30eb, 0xd9fe8768, 0xb5f6cde2, - 0xedb34f18, 0x434f9d52, 0xedb50f14, 0x4bbcfc6f, 0x086b06e7, 0x6f8e2ee3, - 0xe445fe7f, 0xfa1be3cb, 0xaaf61d93, 0x7d60b414, 0xdd3847c1, 0x3ebd08c7, - 0xe2f5e846, 0xfc7af33a, 0xaf6e970a, 0xfce287ba, 0xe3812637, 0x2fb2b5bb, - 0x2577c587, 0x8c6dfb74, 0x40dd67b0, 0x7687cfcf, 0xd08879d3, 0x7ba179cf, - 0x6bd11f35, 0xb3ea0c41, 0x0cdaa38e, 0x5c5d4bf4, 0xcea3c663, 0xcc8497df, - 0x24ba27cf, 0xcf0ce7a1, 0xc55e3033, 0xe71524b3, 0xdfa367ef, 0x8bbd7f53, - 0xbc2f19db, 0x20f2e9a0, 0x992a7b8b, 0xb2ae70c7, 0x79b3ef5b, 0x089e31fd, - 0xfbb035e9, 0xbb447179, 0x2eb1fd7a, 0xda5fcf2e, 0x448279f8, 0x95638781, - 0xe86ec8fb, 0x7d2b23b2, 0x380689be, 0x727766af, 0x776fe12e, 0xf986bdf2, - 0xdec364aa, 0x4e30bbe4, 0x8f414eae, 0xe3b92b36, 0x498f9fb9, 0x3d72e7c4, - 0x11f313f6, 0x6ff56d8f, 0xd81cb0b8, 0x718c23d9, 0x5735f967, 0xe41a26fb, - 0xb9f287fe, 0x3712b74e, 0x392bcbc7, 0x9cf093cd, 0xff0d7148, 0xfd71618e, - 0x80dcb76d, 0xcfcd5ef8, 0xcc2b67d3, 0x963c832f, 0xfaedb96c, 0xfcbcf061, - 0xec5e5199, 0x2b71540f, 0x78de2f3e, 0x3d15ce92, 0x8efee16a, 0x0504fa48, - 0x13fa3d9f, 0x39ea0147, 0xcb75efa8, 0x9f7f7a08, 0x239bec05, 0xdcef83e3, - 0xb38e4505, 0xa06f0ffa, 0x9f3330f8, 0x684bdf02, 0x97ae75bf, 0xe9e8ebbc, - 0xd19becc2, 0xa02df754, 0x8fc87978, 0x0c297eba, 0xa489eb99, 0x6fc16aef, - 0xe4621bf0, 0x7d72c893, 0xdce904a6, 0xd07cc974, 0x43ff0693, 0x8a6aa1c9, - 0x076c8dcf, 0xc1985823, 0xe181da0e, 0x9b972875, 0xfc169c78, 0x88b65b24, - 0x61c41f63, 0xf915c7ba, 0xf8a21811, 0x83d13652, 0x4d99bd78, 0x37d754c6, - 0xc3f5396d, 0x52abfcb1, 0xa2bf73cb, 0xe7249cfa, 0xdd30ee6d, 0x9c4fdb6f, - 0x70f36f47, 0x8feeff58, 0x64d45f9e, 0xe3aeb8a7, 0xbfd23427, 0x149e300b, - 0xb768bfcb, 0x3d68c058, 0x78cfa5be, 0xab6e538c, 0x1fa5f7e7, 0x5e33efab, - 0x1ebccb3b, 0xf9f44fa9, 0x39fe20f6, 0xbe7afd1a, 0x83ce1726, 0x771c788b, - 0xcc8a9f4a, 0xd274288a, 0x2ad44bdf, 0xd3fd7132, 0xbbc38f79, 0xcc14f08e, - 0x9fefc850, 0x5c9a7e4a, 0xe83a9fe1, 0x02edbff6, 0xaca139ba, 0xec25fe0f, - 0xdfa1d793, 0xfbd90bf3, 0xf7507b80, 0xacacfd3e, 0xa3df9d00, 0xfb40f40f, - 0x56161533, 0xe266df80, 0x609c353c, 0xae674f9a, 0x719e2896, 0x78f372d6, - 0xe36ebef0, 0xaac05afc, 0x5622dea9, 0x6ac1694f, 0xce217e73, 0x273c2e47, - 0x8a76e3c7, 0xfaf9cd6a, 0x8d92c0b9, 0xf0d1ac67, 0xc7d335f6, 0xc702fbe7, - 0xa36cdd27, 0x2ab7ddfe, 0x6977ef8e, 0x6df387cc, 0xe9272ae7, 0xa01662ff, - 0xe629dc7e, 0x7307f2fd, 0xed20b37d, 0x37d33f98, 0xcb9e0fab, 0x2d23f3e7, - 0xf99e4919, 0x13c57ebd, 0xbf007859, 0xbce187cf, 0x8524dc5b, 0x036c2187, - 0x9fc11d51, 0x3826bde3, 0x3679e37e, 0x6e38fc7d, 0x3ef673e3, 0x9e116fa7, - 0xb8f9929b, 0x0225f98d, 0xad1b251f, 0x98d17f26, 0x79d0528d, 0x6aaf9e39, - 0x1acaf7a1, 0xf54d58ce, 0xec1d798a, 0xba076601, 0x2b58298d, 0x755660e3, - 0x25d0f1e9, 0x1ccbced1, 0x755c7810, 0x945f5e5b, 0xbed1c7db, 0x9d1027ed, - 0xf84a7a43, 0x06d858a3, 0xec8cc5ed, 0x7b3f2982, 0xe2938721, 0x26a6bd1e, - 0x4a2fbe8d, 0x653361fb, 0x0e789bff, 0xd03e32b3, 0x99da0e37, 0x2ba5f169, - 0xc1bebf24, 0xcf9d6fe4, 0x88e4f0f1, 0xa22a4b8a, 0x3a75b7ac, 0x53d5213f, - 0x3b70409c, 0x599da79f, 0x20c06a9d, 0xb8e32317, 0xd3db8cbe, 0x3a8fe742, - 0xfe744ab7, 0x20e929f9, 0xea7e0f9d, 0xff430f5a, 0x09d02a40, 0x1253eff5, - 0xfcf7845b, 0x34dc3565, 0x73a40de7, 0xe3178c56, 0xc61b4a0f, 0x1a0ea5c9, - 0x62e3b73f, 0xbee2d62b, 0x218cca54, 0x61df9023, 0x866e33dc, 0x3ce3a3e7, - 0x075f5ed4, 0xc2ea7ba7, 0xa1dcc660, 0xce7fbed8, 0xc38f281b, 0x7cbce862, - 0x99cae00a, 0xb432e940, 0xe65952cf, 0x5333b46e, 0xa04678a7, 0x8b957f4f, - 0x916493b7, 0xf684dc67, 0x270e08e3, 0xd6f92c3c, 0xa0ae1311, 0xfcac5276, - 0x1cf87a93, 0xfa1b4ded, 0x7a061c27, 0xc4c8a84f, 0xf10653f6, 0xa70b5134, - 0xbbfb3d61, 0x75a01ee8, 0x23373cc8, 0xbbef3d7d, 0x2eb82971, 0x0b06dfdc, - 0xfb63d075, 0x97fdf4d3, 0xfbec83b0, 0xf2f0870b, 0x97994ec2, 0x24e7cfc9, - 0x15f6eba6, 0xfaa1d72f, 0x5ea246e2, 0xf9db8f7d, 0xe47c395f, 0xeb42bf07, - 0xa0803ce5, 0x58e9f953, 0x0bcc3216, 0x21bed3e5, 0xb4fcb3fb, 0xef1cf4cb, - 0x95c63509, 0xa1ec1497, 0xb2943bef, 0x509f3a66, 0x838e6f5a, 0x7a2622bf, - 0x979f3abb, 0x3059969f, 0xf99abb6a, 0x2c3ee9f9, 0xb95a27d8, 0xd3f3f364, - 0xfc6e1992, 0xe8539456, 0x7169cb39, 0x0a71fae1, 0x67a847ce, 0x7aa09642, - 0xda5d3779, 0x79a62ddd, 0xe1c3dda8, 0xa8bfb10e, 0xb7f5ebe7, 0x39c4d34f, - 0x7bcf7e3d, 0x2028255b, 0x4dd3cfc0, 0x5ddfc927, 0xf09bb4d2, 0x3745f3a3, - 0xd059629e, 0xaae4a780, 0x6405b0e6, 0xfdb8e9fc, 0x025e874b, 0xcba3d924, - 0x7d4b3bf3, 0xbf1f2163, 0xef90616b, 0x792eacd8, 0xcab37527, 0xf0fd0b22, - 0x6389d2ee, 0xdf2f308d, 0x35f37efd, 0xb2b78113, 0x6bf7f286, 0x6b7bdee3, - 0x7506c621, 0x4ce83b9d, 0xb00d3bf7, 0x0076022d, 0xbb00cc3c, 0x2313f223, - 0xe02353f2, 0xcdbe5e34, 0xbd974e19, 0xfb8e6d8c, 0xf4051ae0, 0xf0df5b5c, - 0x6479bc74, 0xd747d579, 0x4b8ef7e0, 0x7bf7f8b3, 0xaf249acb, 0x65a3d064, - 0xe4871e5e, 0x3368b6f0, 0x9a1e2287, 0x507d44df, 0x71b928d2, 0xdfa8e0fd, - 0xdf182612, 0xabde18f3, 0x92d3ebe7, 0x5ef483fa, 0xb10ff5af, 0x3a3f3c90, - 0x772a73e4, 0x362dfdae, 0xaf3dfcc5, 0x52bbf6de, 0x50b7812d, 0xc7f7eadf, - 0xa8f96db7, 0x20aa7bfb, 0x7d7ded7f, 0x469f497b, 0xc72f5b9c, 0xe5ba38fe, - 0xa3e3c745, 0x7dd14e43, 0xd6187fba, 0x079a01f4, 0x2e4ef3b1, 0xff75abc0, - 0x14787a54, 0x27785fda, 0x4f1fce2f, 0x704ba148, 0x059a7a5e, 0xef76c12e, - 0x3768bd29, 0x80ec6a7e, 0x5e0cf2da, 0xdc4df309, 0x01ffc249, 0xfc00cb67, - 0xc7e9dd64, 0xa4e1c2ff, 0xe609ba16, 0xafefeab6, 0x1ecdefc1, 0xc032d018, - 0x8ff7f002, 0xe0993a5f, 0x419e5a8b, 0x04eac2f8, 0x196b0f0e, 0x03fbc320, - 0x23267d83, 0xa3bbd6fd, 0xa109fdcb, 0xc5fef46f, 0x891df60e, 0x84aafb43, - 0x2c783bcf, 0x757a06da, 0x4db1d17a, 0xd31f01eb, 0xf49623ff, 0x5bb6fadd, - 0x1e13f3ae, 0x6f8c7e82, 0xa6f8114c, 0xbbf49179, 0x5f44f642, 0xba130b9c, - 0x6f4ce9e9, 0x71bcd0f6, 0xb416c569, 0x0fa6521f, 0x55e379a5, 0xee27ef97, - 0xe9e9dd51, 0xc4fe9e24, 0x5bfae6ed, 0x46bc50b6, 0xb24e43ca, 0xdf171eab, - 0x23b90067, 0xba0870fe, 0x3c7cdc58, 0x73190dff, 0x80001bd1, 0x00008000, - 0x00088b1f, 0x00000000, 0x7dddff00, 0xc594780d, 0xbbbcf0b5, 0x26effeef, - 0xb24d9bbb, 0xf379f909, 0x71100843, 0xa9189313, 0x18884dd6, 0x220bb531, - 0x49716b62, 0xc93049f8, 0x2d16ad46, 0x544859bd, 0x46d10882, 0xe1b80a04, - 0xfd2b6202, 0x1a8c4582, 0xf68882e8, 0x72dfbd2b, 0xbd3fadeb, 0x8a7e1bd7, - 0xb4564288, 0xeb6dea5c, 0x2666739d, 0x5c9377d9, 0x9f7b7aa8, 0xbe8f8be7, - 0xcef33bce, 0xfe73399c, 0xb3339ce6, 0x9086bb1a, 0x258e4264, 0x4ec730dc, - 0xe631df9f, 0x224c9d15, 0xf433bba4, 0xc84b499c, 0xc421127b, 0x09f04845, - 0x0e7b6853, 0xd1eddf21, 0xb4897504, 0x734de1de, 0x44b2d116, 0xc345bd7c, - 0xd57fbde5, 0xd2b3e5de, 0xd32d3172, 0x9912abe7, 0xbd33f58b, 0xfe5a0e69, - 0xa7aefe02, 0x9f561ee5, 0x58ad25ae, 0x7fbec39f, 0xe5dc84aa, 0x76d4cfa3, - 0x7d296e3a, 0xb5b89dae, 0x916b8e9d, 0x0bca1789, 0x5d6c16e7, 0x736a614e, - 0x897842cc, 0x51269bd7, 0xe6364ef8, 0x76d1566a, 0xc8afa7bf, 0x515c8435, - 0x97b0cde0, 0xff40f9d1, 0x44d21c74, 0x3c369527, 0x37981cfe, 0x7ad7afad, - 0xcf3a64b3, 0x39fe1ddb, 0xe35ebed0, 0xd0b4429d, 0x77c0b789, 0x8823b405, - 0x3b76399f, 0x40f227b6, 0xffffbc19, 0xb8954f08, 0x4f115fee, 0x7534ef77, - 0xf8242c9d, 0xb7fd05f7, 0x2aa1d7b9, 0xbad2fa07, 0xcb871a4e, 0xd0ffc377, - 0x24ad4871, 0x2c3a1493, 0x8d6e22ab, 0xbfe836ff, 0x7a07e979, 0x513781a2, - 0xf02ff43d, 0xeb0a4ebe, 0x82fce952, 0x76cf24fb, 0xb2cfdec2, 0xe8959211, - 0x21e613bf, 0xc3f79ee0, 0xd17f34e6, 0x3f2c7cf0, 0x76e6a978, 0xe4b79c5a, - 0xf4edaecc, 0x590f79fb, 0xdb865108, 0x9d711ed3, 0xb8cf7fdf, 0x9f495c9a, - 0x86b0defa, 0x19fdebe2, 0xb69cb3c4, 0x1a435f7b, 0x73efff00, 0x743f95bc, - 0x853211f7, 0xb5d95f90, 0xd0499df8, 0xbddbe483, 0x53b7e288, 0xd0234122, - 0xd23d4cc3, 0xd28860c3, 0xfeb095c3, 0xfbe87d74, 0x872707ee, 0x067d7482, - 0x619100c9, 0xbec4153e, 0xbfa9895d, 0x29eb00a3, 0xb44d049d, 0x0e68da3e, - 0x5e80956d, 0x50a5a028, 0x5feb093f, 0x07fad895, 0x38e230ef, 0x1d1933dd, - 0x433a3776, 0xb6001cc1, 0xc6de008b, 0x7694a3a2, 0x64487482, 0xb69994ef, - 0xe36c7c61, 0x3a52c172, 0xb4dbe2f0, 0xe4dab23f, 0xb01f4f19, 0xbb943284, - 0x4a3c7152, 0xbe91ab0f, 0xfd470664, 0xab42d38f, 0x394f5c70, 0x36a3cbac, - 0x1f787cef, 0x014591fd, 0xc89937f8, 0x7d09634a, 0xe8c3a44a, 0xe1c0eba4, - 0x134f5d21, 0x60bb83a0, 0x7f878a00, 0x536f386f, 0xd89ffbe8, 0x08038425, - 0x484e58cd, 0x75f5611d, 0xa4c72ccb, 0x86d4f029, 0xddf4090d, 0x03bc1bca, - 0xd972be82, 0xf3fb48d3, 0xeb22ba73, 0x83c036a3, 0x804bbe1f, 0x29b73ffe, - 0xefd32856, 0xd3f2c0a7, 0xbf870bef, 0x7df039ff, 0xe0c7c019, 0x65166d27, - 0x1f8c34bb, 0x80b9fcf1, 0x6f69ebaf, 0x9c6278ec, 0xd98f7ef8, 0xf007ffbd, - 0x4e1ef145, 0xb45e0174, 0xf0f1aeb8, 0xc7d1f4ba, 0x5e7eb44d, 0x82b1d69b, - 0xd4bfd3e2, 0xf015f386, 0xbd1a95de, 0xec8de48e, 0xa5a594ff, 0x2ff9865c, - 0x964f7465, 0x62e22819, 0x2e1fa2f1, 0x485dd253, 0xd23587a2, 0xf0e5ef28, - 0x517f8001, 0xf8f7cc77, 0x621abfdf, 0x21be09db, 0x3f07148a, 0x92452ba7, - 0x12fcdd61, 0x3ebd375b, 0x56e40f3a, 0x9f02dc3c, 0x8de5c6ff, 0x7c788ba0, - 0xbbe01bff, 0x5dbe246c, 0xe84c81fa, 0x80d4bfd7, 0x9fef8a78, 0xf77e1090, - 0x4d0489b4, 0x4bd6ee94, 0xfaebd212, 0x90212d07, 0xe8a6839b, 0x6067c00e, - 0xdeb88dff, 0x0acd1ae7, 0xea364da1, 0xf705bf19, 0x171f18db, 0xdc80140c, - 0xece7473b, 0xee73eba5, 0xa09eda37, 0xa4208024, 0xadda37e5, 0x5ee7ff40, - 0xb3f589be, 0x5a10a2dc, 0xe986000e, 0x7fe081b8, 0x578a11b6, 0xc7119669, - 0x0a57b13f, 0x8fbea019, 0x5e4639e2, 0x36ffa39e, 0x8dcb0c94, 0x3800a841, - 0x07082cfa, 0x8e23699d, 0x59335df7, 0xd16fc745, 0xad0d5e48, 0x2932596f, - 0x31e0ced4, 0x16d5cac6, 0x4a90e90d, 0x45bff986, 0xdee0bc73, 0xa7275622, - 0x60ac7970, 0x851243bb, 0x3ab8c9b3, 0x05fa05a2, 0x4bf5a03e, 0x78673ea0, - 0x7f565a1d, 0x479817f4, 0x7d351ecb, 0x9eaf3d34, 0xba5892c7, 0x17a619ca, - 0x17c3294b, 0xf1a126a9, 0x2f1b5e14, 0x21226a5b, 0xe963e02d, 0x2ae27234, - 0xc0e0f4da, 0x5b23a074, 0xa3a92f69, 0xe269c0cf, 0xa7b8510d, 0x36bcf7f6, - 0xd477b68e, 0xba613244, 0xcdbfa581, 0xf0d5793b, 0xaf380b3a, 0x4b427fe9, - 0x7e1e38ac, 0xeef14147, 0x89bb62b6, 0x7d88aeb3, 0x92efc0ae, 0x0f2f4c35, - 0x1fe02bc0, 0x75cde999, 0xfd526f5c, 0x617af28a, 0xafd404d7, 0xce40ffa0, - 0xf4c0953d, 0x903dc831, 0xaa8e6d33, 0x9e741cab, 0x14d56766, 0xc71b1947, - 0x27e98367, 0xa788fea1, 0x243d78eb, 0xb5e6a5da, 0xc75ab716, 0x0cf9476e, - 0x90dd16f1, 0x2c88e4c8, 0xafd17961, 0x10ab3d75, 0xe6e9193e, 0x2839cdde, - 0x97481b97, 0x89bce81e, 0xc740f484, 0x98248c8b, 0x1162e940, 0x9f48966d, - 0x881bd78b, 0x8d7eb312, 0x89b97521, 0x49bb85cb, 0x7bbfbf04, 0x357d5c67, - 0x7d68db09, 0x2d8491b3, 0xd755ecf0, 0x8e7d50b7, 0x85f7d67c, 0xe93df621, - 0x8bbdf366, 0x3aa3bbaf, 0x79d3f5a4, 0xdd51306f, 0x5d0684ea, 0x97533eb8, - 0x267ae0f5, 0x1e737896, 0x2bf2bd06, 0xa52b679d, 0xf5f03fdb, 0x6639f812, - 0xbc00aaaf, 0x9c1ab59b, 0x0361f47f, 0xd524e7e2, 0x6bfeb0e3, 0x59aee41d, - 0x8dae79f4, 0x8075f378, 0x2cd67b26, 0xaf3c48db, 0x00d4c57a, 0xd0e0d374, - 0xd32ae8a8, 0xf972c3a1, 0xe5ff8e0a, 0x1cd6d096, 0xa014f744, 0xa15cf2a7, - 0x9994c957, 0x474c7cb4, 0x6e5a3bed, 0x43f56399, 0x4f60037f, 0x0efdf2d0, - 0x77eecf26, 0x453d71e8, 0xd057cc59, 0xfb071d0d, 0x9ec55f33, 0x43658e02, - 0x74609fed, 0xbaf0f5c3, 0xea0f7346, 0xd5fa21e1, 0x22dfa410, 0xfaf01e9f, - 0xf32b970a, 0xf8a16ec1, 0x1412857e, 0x2f608fc8, 0x3e295fb3, 0xe5a52de6, - 0x79174e57, 0x67402956, 0xf2bcde4c, 0x4159331d, 0xccf37c87, 0x27fb1f4f, - 0xb4fe7f5a, 0xfad0315e, 0x746b4005, 0x88915efd, 0xbe0bc617, 0xbe810868, - 0x7b33d26c, 0x15ff69b4, 0xfbd19ecc, 0x71842c37, 0xc079d05e, 0x084a69de, - 0xeb03b73d, 0xa2943cd3, 0x863aabc9, 0x16cbe0cf, 0xf439bdf6, 0xa0bb9fb3, - 0xa413d53e, 0xff26a3ed, 0x74d75846, 0x7a889283, 0xc25ad7f9, 0x381709c6, - 0x878f5e28, 0x9c7ddd98, 0x4e304956, 0xa1fb0dbf, 0x90b69a7c, 0x33a273f6, - 0xe543e715, 0x2759da2f, 0x82b618d6, 0x34375dfc, 0x8fed84ae, 0xd3d37ceb, - 0x8bf8f968, 0xb4e59ec5, 0x0fa7d06a, 0x073d29eb, 0xafbb32d6, 0x016ca35e, - 0x16fd90fc, 0x8f58879c, 0xb5c59ac0, 0xb2581f50, 0x8f9016ec, 0xc839f163, - 0x3723127b, 0x166891cf, 0x86c6d3f0, 0xe830dedc, 0x1e89fe95, 0x4dc4af54, - 0x8dd29f17, 0xa93db59d, 0xee8df863, 0x5f3d21d3, 0x1740ff6e, 0x43d33972, - 0xca804e30, 0x0ff82265, 0x594c72e5, 0xad995a3b, 0x5495e063, 0xeba9df6e, - 0x47fc1253, 0x9e5a5d60, 0x97f78ffc, 0x145e302a, 0x4ae922e5, 0xa93cbe46, - 0xba03cef3, 0xf5875475, 0xfd7a3175, 0x99d983a4, 0x076e06f5, 0x963eb092, - 0x797d450f, 0xc5ee9a95, 0x7fa704f3, 0xf7c9845b, 0xce1af591, 0x401ab71f, - 0x20654d8f, 0x23d06c93, 0xc15fe856, 0x0e9ea7fe, 0x3969ebeb, 0xbf58597b, - 0x4f813f88, 0x46c3be28, 0x1b93ef3a, 0x29bf8c6c, 0x459fa01a, 0xe5f50415, - 0x63b52d22, 0xd2bde04b, 0xe5d74037, 0xa40e8bd4, 0x8a67f22f, 0xf9ef8a15, - 0x5033b784, 0xb1ca97bb, 0x30a43a97, 0xafe60bec, 0xe5356c37, 0xb57b5f00, - 0xcdcf5836, 0xf9b1ca12, 0x1b05951d, 0x9ec97968, 0x13fd702b, 0x2e5d182a, - 0x2f503909, 0xb1f2e54e, 0xa3d210de, 0x8933fe1d, 0xf6883ec0, 0x1374f68f, - 0x64ad28fd, 0xae401e24, 0x1421e8ab, 0xd1f6a653, 0x57265ed4, 0x24e79509, - 0xf2126ec6, 0x8938e41e, 0xf4d503b3, 0x88fa1411, 0xa4a23dc9, 0x7213dc82, - 0x97dd98f9, 0x3e3b44e8, 0x97d6153f, 0x9b9327ae, 0x6bc425bb, 0x7d456933, - 0xd0c0f422, 0x9c8f5cb8, 0xbe9906d2, 0xcf813c32, 0xae0e677c, 0x8bd212eb, - 0x95e844fa, 0xdf20e8b1, 0x88fbe1a9, 0xbc60e9d1, 0x9afec153, 0x75f0934e, - 0x65a6bc74, 0x853cdc24, 0x50536d3d, 0x693d323f, 0x9e127a64, 0x97d0cbe6, - 0x5e31faf1, 0xc1ebc61f, 0x77d33d54, 0x3d859d62, 0xd98d3a93, 0x85975301, - 0xfc08a4b4, 0x94eade35, 0x26bb61e4, 0xa8d18ef0, 0x1f65095c, 0x9ef905c9, - 0x2a62f950, 0xc4c80fad, 0xa1657c0b, 0xefa1e978, 0xb7fb7337, 0xd7cd9527, - 0xabf467ad, 0xd8a47d93, 0xc112eb0a, 0x99346f7d, 0x051e81d8, 0xe8db373e, - 0x1df02577, 0xefa1b7e3, 0x1cc3a48d, 0x2bd57df3, 0x173fd426, 0x0c85b65e, - 0xb3f88f68, 0x94bfb41d, 0x4ed01bdf, 0x0d8af73d, 0xae39e9f5, 0xefc25d0f, - 0x7e611e40, 0x41aebe16, 0x008e3552, 0xc6334bed, 0xf6140881, 0xd983b359, - 0x21ed2359, 0x99139f5e, 0x80cae8c3, 0x8e0bcdfb, 0x4ca00781, 0x7fa021e1, - 0x7e32716e, 0x5699ec0f, 0x3efa43fc, 0x187ab3e0, 0x40c5fdf6, 0xf7ed06af, - 0x7d2918e7, 0x8b2ed74d, 0xd1e7483e, 0x83b5699c, 0xfeceab7e, 0x41dddfd7, - 0xd1ee1fcb, 0xf3ac0311, 0x497369f6, 0xb7f2d8ee, 0x3e3ba431, 0x772fc310, - 0x9b9754ef, 0x40e5d57b, 0xbf7cba9f, 0x653ae6d3, 0xf9e1d941, 0xc1b5d282, - 0x87ba7ad0, 0xd5786bc2, 0x8668fa80, 0x1390ffd3, 0x7a26ade4, 0xc86cf018, - 0xf80a78fe, 0x9ffd023b, 0x5034f048, 0x31148a36, 0x5f5f03fc, 0xb6cfcd30, - 0x61b7828f, 0x06a311fc, 0x75ad4cf1, 0x173944f6, 0xd2e27ce0, 0x403c3f7b, - 0x9668bfe7, 0xdf02bed9, 0xcacb6b78, 0x18449ec1, 0x4dfd6049, 0x8bbec21f, - 0xf5846bb6, 0xb693353f, 0xac3570a3, 0x89b0fa67, 0x6f801244, 0x69dda85b, - 0x1bfc4ba4, 0x77776fce, 0xf4c3cb44, 0x359dbb7f, 0xf94e0113, 0xe80fb22f, - 0x37e851e3, 0xeade4ec6, 0x4bfc7264, 0x463299fb, 0x02b699f8, 0x038d9afe, - 0xfe3a4afa, 0x0cf97ff5, 0xa5e2fde5, 0x823ee1af, 0xb33e63ce, 0xc80a4dab, - 0x1e0fc5a7, 0xdf62f7c0, 0x8ad32a76, 0x36d7b6fb, 0xa1d95818, 0xcda9f2c7, - 0xb8b95f6c, 0x3cc10a57, 0x931759a5, 0x6c2f412a, 0x640dd9d6, 0xf1e35e24, - 0xb7a6c1f8, 0xf5efc013, 0xf61d2201, 0xc7b3127b, 0xb809adec, 0x135a507f, - 0xac0cbec0, 0x9043f1bf, 0x6b378b8f, 0x902f603d, 0xcff4367d, 0xc37cde2c, - 0xe85685c4, 0x4aa4d3e7, 0xb96d13f0, 0xd0543c01, 0x7e6217ce, 0xf4f5c89e, - 0x6ae5bcbd, 0xd0f1f805, 0x62ff0666, 0xd0077187, 0xd17ff5d1, 0x1ac97f22, - 0xb93b07e2, 0x089def5b, 0xda6cad7c, 0xe7d61d3e, 0x1ae99983, 0x224bbf6c, - 0x638bc076, 0x5fbc0a69, 0xe03ec92c, 0x8df586e3, 0x4f76b1b5, 0xc7f9939d, - 0xa597b32a, 0xaf91580c, 0x6d3e80e6, 0x08f94cde, 0xdef59fc6, 0x0d70eeef, - 0x6b3495f3, 0xa1532dfd, 0x1e7567ff, 0x7b21bbe0, 0x90b7d366, 0x4c2fe0be, - 0xe398b5f1, 0x99f2abeb, 0xa4f822c1, 0xeae400b5, 0x05ad15e2, 0x8cec51f6, - 0x44d93e21, 0x213272f9, 0xf9129da7, 0x1993fc02, 0x63bed54e, 0xb59a7dac, - 0xc67a8350, 0xedde21e8, 0xb74a99f4, 0xb71fb0c9, 0x6f58c925, 0x7d23d24b, - 0x77ba7fcb, 0xbce86fe7, 0x2ffa749e, 0x26ccbe80, 0x6bd062de, 0x455ed44a, - 0x35405acd, 0x136461da, 0xcc89afb3, 0x92eb85fc, 0x31558ec9, 0x125373fb, - 0x39504fdb, 0x73f405f1, 0x1f3fddee, 0x64b6fc06, 0xec053c7d, 0xcfc5c085, - 0xb35fe0f4, 0xdf284bf6, 0x011f1ead, 0xcff409ba, 0x868a0b24, 0xc3c072e5, - 0xbcfc46f4, 0x98e924e6, 0xb145751c, 0x82974a9f, 0x41076ee5, 0xd4b8da7a, - 0x46fef68c, 0x4004c857, 0x2b7cadff, 0xee46a7ec, 0xfb6e340f, 0x740b5785, - 0xe3ec921e, 0xfe30aca1, 0x17986c18, 0x3e71d2d2, 0xc41796dc, 0x8f4a9ef2, - 0xb759d696, 0x5ccae3fd, 0xce9f53c0, 0x9eaded03, 0xdf980481, 0x244edb87, - 0xb61afcc0, 0x0dde7169, 0x16524fa1, 0x09cb0d16, 0x905fc69d, 0x5d827604, - 0x42f8c2b2, 0xedb87c5e, 0x560594d3, 0x7d403fe6, 0x5e3a3a5a, 0xc9cacecc, - 0xdff5fdf0, 0x6672eb64, 0x72042197, 0xf9898cf0, 0x33bb45f7, 0xaeffa636, - 0xcdfe124b, 0x3fd02cde, 0xa2796543, 0xf7c4e406, 0x2efe6ced, 0xf0166f7d, - 0xba9247e5, 0xb52b259f, 0x52e54424, 0x84894ae3, 0xf33fcca8, 0x20594bdc, - 0xfedc3fff, 0x0c5d5652, 0x89dff17c, 0x6a498de7, 0xaff09a7f, 0x0ce1f4ba, - 0x63ceaf18, 0x31cc7e60, 0x3da2abfc, 0xa4fccf59, 0x816b9483, 0x8377c50e, - 0xd82f660d, 0x18c483bb, 0x5d5b9702, 0x7ad7f73f, 0xd82ef9bd, 0xe3ef88d7, - 0xf40d5ffa, 0xfa92e144, 0x5827f424, 0x9f28a28a, 0x77fcb4bf, 0x918cf5d1, - 0x8d9d74ff, 0xc6cd4eb0, 0x0471e1e8, 0x780f43e9, 0x6558b7d3, 0xed2957d0, - 0xf7a2be8c, 0xe59f706b, 0x814c2732, 0xdd3e80b8, 0x76f9056d, 0x43b9817d, - 0xb3ef0893, 0x333ed042, 0x0bbf10bd, 0x0ffa3156, 0xc3f410a6, 0x095691a5, - 0xe676b4fd, 0x20a8cfe7, 0xf8b455f6, 0xe76624b3, 0xbd6789b8, 0x5fd70f36, - 0xc70738c2, 0x400fd08b, 0xcf2f2047, 0x23a44648, 0x7b425fa9, 0x9de9ab54, - 0x458efd07, 0xbac52b57, 0x2a1aba72, 0xeae89dff, 0x23c74149, 0x20afcae8, - 0xa38db95d, 0x23f715d3, 0x127b765f, 0x36bec1f4, 0x2d6be395, 0xfbd13f97, - 0x2eafc28d, 0x796b7cc1, 0x6b46b57f, 0xc47a0b58, 0xd638fba3, 0xda89bc3f, - 0x4a7fb0c5, 0x3e9ebb03, 0x57cfb5c7, 0x6448dd70, 0x9608fc00, 0x2fa88dab, - 0x7244d31f, 0x9d498ec0, 0xe81bbad4, 0x515e7523, 0x0bee3b49, 0x17a01c33, - 0x7fa2d740, 0x1f34e974, 0x1c5823b3, 0x8f533a28, 0x07969cfb, 0x8ecc7d2b, - 0x097e41a8, 0xa02936ac, 0xe7f5a707, 0x08fa072c, 0x031e232c, 0x86cf71d2, - 0x9dcfe045, 0xac80f56d, 0xb225f113, 0x9d77cd52, 0x05538b12, 0x0f18226f, - 0x0d338e1b, 0xe821f96c, 0xf422c6ff, 0x8ff90c9b, 0x8dea09f3, 0xd6438dcb, - 0xde2136ad, 0xd068fc45, 0x25741146, 0x3fb191fa, 0x7a646892, 0x407ca468, - 0x054a73ff, 0xa1eb7f11, 0x3cca2e9c, 0x5ff823de, 0x456ca3c4, 0xc8b01cbe, - 0xbf399c2b, 0x049c4332, 0xb36c77fc, 0x00fd8416, 0x19598dfa, 0x694fcadd, - 0x50e92028, 0xaaab9ffb, 0xbcca6233, 0xc1f7d0fd, 0x5f573755, 0xa877fa8b, - 0x7aa6c01e, 0x26bd9459, 0xc355e205, 0x83b532f5, 0xff127d8d, 0x1be6e2be, - 0x941eaaa8, 0xee7ff8c4, 0xd11f82f4, 0xc5e35444, 0xf5c727c2, 0x5bfda3af, - 0x383ede15, 0xefe826ee, 0x7e5112a9, 0xe14bd3a0, 0xf753ab5b, 0xdfe52887, - 0xf78c4143, 0xaf0e537f, 0x6c319d5a, 0xe17b501f, 0xc36549cf, 0xefa3c276, - 0x495d76d5, 0x3fd8b2c7, 0x15fe83d5, 0x92e03efa, 0xe7890ed0, 0xf49704d7, - 0x656becd5, 0xe09d7d84, 0x74f5f662, 0x2fba4960, 0x581df941, 0xdf6023e6, - 0xe9c4bb52, 0xe3e4bb42, 0xfd680753, 0x1f9f59b9, 0xbb40a71e, 0xbec1e67b, - 0x4651702a, 0xa9d81bf9, 0x6f94490d, 0xaeccfd8c, 0xe31cfaa6, 0x967e8205, - 0x38fd39d8, 0x97fc0482, 0x32a4fbdd, 0x5a4277a0, 0x6ba36eb3, 0x379703f9, - 0xfbe1c713, 0x9779f8cd, 0x205f98bb, 0xa1b55850, 0x26dffa00, 0x5617b011, - 0x594f1e15, 0x63a9fb80, 0xbe630b29, 0x0a7bec6b, 0x53b8d9f1, 0xcb1e2a37, - 0x7804e1a9, 0x45f9796c, 0x338dc82f, 0x42650921, 0x04ea1c83, 0x41a1b6bb, - 0x29211603, 0x03bfcd0d, 0xf5731fe3, 0x5f9d3c64, 0x8177d706, 0xa706b79d, - 0xbfe9bcc2, 0xd1b57d12, 0xc4e508b7, 0x2b46b9c6, 0xeb0a91c6, 0xd83c41ee, - 0xc3c05ecd, 0x34aac2aa, 0xe665a718, 0x4dc63b74, 0xf5073da8, 0x077e0f2d, - 0xae0245fd, 0x1aba7d55, 0xa9ca77b0, 0x0a0bf75d, 0x4673a677, 0xf5f2878d, - 0xe2eeed38, 0x5710acfb, 0xff8e5d1f, 0x174664bf, 0xf82f921d, 0x8ff452ed, - 0x677f5892, 0x1fb31f76, 0x55e9716f, 0x5c5bf1fe, 0x36bdaecc, 0xe4069918, - 0xb01e5fb2, 0x201d5d80, 0x5f604fde, 0x65567c4d, 0x9313ae3b, 0x0536ae5f, - 0xd74666fd, 0x425763c0, 0xee32b5fd, 0xf03c8867, 0x5cf71863, 0x8ab3cba7, - 0xf2803e70, 0x90214583, 0xfe5cfbc7, 0x96fac2ef, 0xdcf57b73, 0x831637cb, - 0x5fd8517f, 0x5099cf9d, 0x94da766f, 0x4e406b27, 0x796649fe, 0x6468c603, - 0xc967ed1a, 0xb71c4ee7, 0x84ea14d3, 0x68f60ff5, 0xeac9beb1, 0xdbf4045f, - 0x29faeb78, 0x0d608798, 0xd51e8015, 0xd008bab9, 0xa0bedd31, 0xf2e8c51f, - 0x4f238811, 0x2597ce0b, 0x767117d0, 0x63f034cd, 0x85c5bee1, 0xce2adc7e, - 0x1529e31f, 0x2b22329c, 0x34917c74, 0xf9bce76c, 0xbc32d9e7, 0xc68ff614, - 0xd5eefcc8, 0xec04cd73, 0xf448f25c, 0xf8fc06b0, 0x7b0108ae, 0xc257b9b8, - 0x5f0b9a71, 0xe5fec3d0, 0xdfc65eee, 0xa0dfbe01, 0x78c2cbf8, 0xedc2cb94, - 0x67460e81, 0x1c787224, 0xb679f9e0, 0x76d0849e, 0x42577e31, 0xc0793396, - 0xf8f3d3fb, 0x37f73343, 0xf5884d51, 0xcec25cab, 0x5b8ea158, 0x49d771f0, - 0xf016af11, 0xfca92c5a, 0xc3d9e2e4, 0x183c4fbf, 0x1bfc0e9d, 0x7e05f4a5, - 0xccd20da7, 0xf3a75e7b, 0xc93650db, 0x9b98a603, 0x04b69392, 0xa45253de, - 0xfbed2f78, 0x0dd03a64, 0xafc821a9, 0xda957d2d, 0xeb8b2b66, 0xa58c5e60, - 0x53ea07b5, 0xfd442aef, 0x5993710c, 0x1cb3fdf4, 0xe65669af, 0x08af73c7, - 0x341c40e6, 0x9eefa0f1, 0x2bfc61d7, 0x4d87e8cc, 0x73636ba5, 0xf82573e2, - 0xf8a4dcbd, 0x7767e800, 0xf00252ad, 0xc41f7888, 0x0d16670b, 0x3d38e3e7, - 0x7d2b7792, 0x983976ee, 0x6a40cedf, 0x1f785e00, 0x1fc70eb2, 0xe3079fc1, - 0x9e0f7c42, 0x32c2d2e7, 0xc0c9fffa, 0xefb8ed96, 0x483e6037, 0xef1bdf6d, - 0x35adfe80, 0xc78c5e92, 0xd52dd9c6, 0x02beb789, 0xf6783ff4, 0x018796d4, - 0x7af6dbae, 0xce25ef30, 0x9bfeb91e, 0xb33f3ecc, 0x3f00a2dd, 0x9b72e56c, - 0x27c88fda, 0x3f6c5dc1, 0x1e476f19, 0x27f7a975, 0xddafe543, 0x05f0648e, - 0x0b3cb3b7, 0x7c03df21, 0x70d837ff, 0xd7f4013e, 0x13c10dbf, 0x8db20f97, - 0x8ff483e7, 0xe6f20f9e, 0xe8104b0e, 0x09af7ce1, 0x8f3292fd, 0x45b59d7b, - 0x7524001f, 0x01cf0e38, 0x72581b79, 0xca1ae7e6, 0x8b0f727f, 0x8f12c923, - 0x4b4afd33, 0x6bcc5c58, 0x808bff07, 0x774c765b, 0x3e408b7b, 0x713779b2, - 0xb39351bf, 0x2ef16140, 0x94d43796, 0x7b002e10, 0x87ae55ea, 0x5e2ccc9a, - 0x87d0e835, 0x26a35d61, 0x185d1fff, 0x93df62d7, 0xd8941a5f, 0x884f56b8, - 0x0a2775d9, 0x9d3d6135, 0x07d80f67, 0x59ab6eb0, 0x9f286b7c, 0xc7a1bf60, - 0x5890e2c0, 0x41ccec1e, 0xe22f5939, 0x3f99fb56, 0xa7c79eae, 0xf45acc4e, - 0x745ca40c, 0xb035ad48, 0xaab0bb3f, 0x0fe8fd12, 0x9f13393c, 0x7ed52bf5, - 0xa7e045ff, 0x238e1bcf, 0x1d7bff0b, 0xbd99e8f1, 0xd447ec3c, 0x5945fb50, - 0xbe815729, 0x15f621cc, 0x2095ff20, 0xe9abad5d, 0xc13e83b3, 0x12349768, - 0xa77239d8, 0xfbeb0ccb, 0xf5068768, 0xe343b054, 0xcf027685, 0x8fccc939, - 0xf3324d74, 0x0aa5d06b, 0xd9e238c1, 0x0771e3a1, 0xa272dfde, 0x2353c309, - 0x76a3e7b1, 0x7d3466b9, 0xd0ebfa2d, 0x4fc11ab5, 0xa0d4cd17, 0xde82fbdf, - 0xc6fd173b, 0x790202ce, 0xd6b61d54, 0x1eac3595, 0x2982e779, 0xebfac3ea, - 0x12486664, 0x33f209c5, 0xcbe79935, 0x616de1c5, 0x1f1cba97, 0xa90c698f, - 0x3fc4f5cb, 0xc58f2d21, 0xa7df620f, 0x75f93326, 0xc70e5561, 0xe3f307b7, - 0x6797fcc4, 0x3269bc30, 0xb33733d9, 0x41d02e6a, 0x7397c42e, 0xabfcc9e0, - 0x7f082674, 0x092e75ee, 0xde0e23e9, 0x80da300e, 0x3c593abe, 0x3f856ff4, - 0xe4caee1e, 0xbc1fae14, 0xd65f886e, 0x8f18f5db, 0x493f5cbe, 0x0e5ab25d, - 0xfebf950d, 0x27db2cfd, 0x9e796a75, 0x50e51d8d, 0xe5cd9d9d, 0x11d9e484, - 0x6a56f786, 0x3a3cc02f, 0x3f6025b5, 0x8ad5bb4c, 0x6fd968f3, 0xf3703f42, - 0xd02c81b2, 0x03552de3, 0x89b71005, 0x2b402fc7, 0xdb45f90b, 0xfee8b9d5, - 0xd884ec03, 0x4b5f3c76, 0xfef5671d, 0xf60cb920, 0xbf762739, 0xb76afa01, - 0xfd15f509, 0xf00603bf, 0x839cbcb3, 0x3687ccf6, 0x0bb41b7f, 0x9e5bc398, - 0x85bb01cd, 0xfdcd4dd9, 0x0bb01e86, 0xe2623aeb, 0xd59ff07c, 0x591fb8ea, - 0x3bff44e9, 0x6fbf56e9, 0xddf714d8, 0x17603888, 0xbd3af3ae, 0x3bf0227f, - 0x7f983bd5, 0x8351b670, 0x5af50379, 0xb79022cf, 0x7b6a4d67, 0xad8dacfc, - 0x75a196d7, 0xb5bda0f6, 0xf675cc65, 0xd73ac014, 0xb63f886b, 0x6758669f, - 0x7c4dbeba, 0x78becf9d, 0xf3ac0175, 0x2eafbbc7, 0xa75e7580, 0xdf02f2eb, - 0x5bfc39b4, 0x27bf6993, 0x3da1f06f, 0x2f58f225, 0x24f71e97, 0x432bfdab, - 0xff21ffe5, 0x30fa58ca, 0x5a87043c, 0x4af4ba1f, 0x3a83c806, 0xd5bfe1a3, - 0xaa37f08b, 0x4068cf1f, 0x3ffec77f, 0x0766ba7f, 0x2d7e81c8, 0xbfa223da, - 0x0f3fb2fd, 0xeffda1ec, 0x69413db8, 0xb91bfeec, 0x246dd85f, 0x88abf041, - 0x27b0807d, 0x5bf1e5e3, 0x251f3e7c, 0xbb006f7b, 0x8dfacbe6, 0x633bf81b, - 0xe76653e8, 0xcc3c936e, 0x7e8bdc6f, 0xf37d96e4, 0x3e27e0ed, 0xe37e621d, - 0xd18b1796, 0x7a18dc6f, 0x65790c2d, 0xc3b25fa4, 0xdb71a3fe, 0x07c804b1, - 0xba5cfb10, 0x8c933daf, 0xefdea8f4, 0x489d0e9e, 0x0a01fc80, 0x71e82577, - 0x07aa2b8b, 0xfba16fba, 0x6c23c83d, 0xa187a391, 0xc11716df, 0x3ed2973c, - 0xc44ffef5, 0xf4fa3779, 0xf6377728, 0xd790214b, 0x4e7f7a29, 0x9235e806, - 0x2078c761, 0xc98bb3e7, 0xb294d4de, 0xf7baf8d8, 0xe1e4e4f3, 0x0d81b07c, - 0x03bf4889, 0x83b5e23a, 0xe360db3c, 0xf9464cf2, 0x8e4dc7f6, 0x630fcb10, - 0x6218ffed, 0xc8a34276, 0x5849930b, 0x68b5eba6, 0x585df7b6, 0xe1f7906f, - 0x5b1f7938, 0xbbfb7116, 0x52f51849, 0xca181933, 0x176d8b0f, 0x7887d71f, - 0xd21faab8, 0x1f80ac5a, 0x07ab4eec, 0xb8f881e0, 0xf6c83eba, 0x961f94eb, - 0xafd30c96, 0xbf410758, 0x1d0fdc2d, 0x08fe3868, 0x4fa06fd0, 0xd77d83b2, - 0xdbf461e4, 0x905bf744, 0xefcf1b47, 0x379d57a4, 0x97ff163a, 0xd1f5a8a6, - 0xe4eff950, 0x453ebd5f, 0xfe62f7cd, 0x343f6fc2, 0xf1897ecf, 0xe2bcdc65, - 0xfef1a9f7, 0xbccfb176, 0x2738795c, 0x870f2d45, 0x79677fca, 0x2eb43758, - 0x1d50f2f1, 0xe59bf8cf, 0x5c70ffe1, 0x4f7d99e3, 0x03bec027, 0xa7d878ec, - 0x63aedcac, 0xfd1413f9, 0xe9e2f1b1, 0xc597ab5a, 0x5ea2b54f, 0xa657871d, - 0xe33c38f3, 0xd45ed7eb, 0xf335bae2, 0x3ef37138, 0x369a079b, 0x9c631758, - 0xba7e3e36, 0x0e9eec84, 0x471f154b, 0xce7e026d, 0x753c74bb, 0x8f8b0a75, - 0x20725852, 0x6f3e216f, 0xa7eb35eb, 0x7598fe49, 0x1ba22aaf, 0xdbe85182, - 0x33890728, 0x14c6fde6, 0xc6bf5766, 0x7adc8bf3, 0xad608e76, 0xfd85e2cd, - 0xf2c35b8c, 0xf2e07e9f, 0x18bc826d, 0xfaf1c2a3, 0x4344edf2, 0xae8cf2f1, - 0xb04ae517, 0x3901ead9, 0xa237fc28, 0x5e3c8bff, 0x3ffad971, 0xfcf7de8e, - 0x3c7bd30f, 0xf18bf67e, 0xddb8d6fe, 0x151b8a7a, 0xe3a4105f, 0xca5f1023, - 0x63bf4919, 0x1d1633f5, 0x1df14d1f, 0xfe766149, 0xb857cc14, 0x2963394c, - 0x3f009e8d, 0x5063d911, 0x7e09afc0, 0xab8fd412, 0xaa3e78d3, 0xe6267ca7, - 0x2573b369, 0x58ce1ce2, 0x4307e476, 0xc8ecc3eb, 0x9f5cc60f, 0xde47672f, - 0x087df0ee, 0xd2b27674, 0x1e01e78b, 0x61f851b5, 0x619cf87f, 0xe22e73d4, - 0xfca5c63c, 0xd1c45f2d, 0x4bff17d5, 0x3a92d472, 0x75f95d96, 0x13cfd1cb, - 0x763a7fc0, 0xff9e413f, 0x45bc4119, 0x6b6449f7, 0x103b5f8c, 0x197bf961, - 0xfef15e1c, 0xa1bef83f, 0x999bd521, 0xfc7fdf4a, 0x1248d1ae, 0x652e9ea9, - 0x67c5b172, 0x4b42b8c5, 0x697fcb2f, 0x8e504659, 0xb4df80b7, 0x3389fc08, - 0x4f7dd809, 0x2013fd3a, 0xf7d1ee8f, 0x226d41ac, 0x1167dbf8, 0xbdcef3b0, - 0x9c33cacb, 0x6798c9fe, 0xe3006cb7, 0xceb3dd18, 0xf9561e60, 0x523e9f17, - 0xa2f08a53, 0x5065c13f, 0x3db9679f, 0xf133c995, 0x6f843d9c, 0x3ff3fa2f, - 0xdaf9606e, 0x0ed79701, 0x0fe1097e, 0x8c1128b7, 0x61ecb42b, 0x96b95bc6, - 0x30fc87cd, 0x65a9e903, 0xf831654f, 0xa9af494d, 0xf2ddec18, 0xdf715bdf, - 0xe983f1f7, 0xcfb12798, 0x7c02afe5, 0x37434ad8, 0x4d9a7d81, 0xf7bb01c7, - 0x1537dde3, 0xfe42dc03, 0x39bf03ad, 0x4d9d7f1d, 0x462717ed, 0x64bf7796, - 0x33ee2647, 0x5afeac9b, 0x133aff98, 0x9db82383, 0xfee14f9f, 0x17fe78f2, - 0xd5aa9f7c, 0xdfa938e0, 0x5c9c6235, 0x3a7585c8, 0x0de637e2, 0x9e1293cb, - 0xf1701867, 0x99fec73c, 0x97854f2c, 0xbe752ead, 0x37c947e7, 0x253c0094, - 0x8b57f2a9, 0xe4475967, 0xb2a4940b, 0x5cea9678, 0xb322e5a2, 0x7aed73a7, - 0x4adb27a4, 0x9454e2c2, 0xbfaec09e, 0x06991a36, 0xbbf2bce7, 0x9e02d7c3, - 0x20d45ff7, 0x4799e49e, 0x28933e30, 0x56f2f1b1, 0x004e740f, 0xadfd8c7f, - 0x954960eb, 0xa0157b2e, 0xefa749f4, 0xffe45481, 0xaf1842d6, 0x2c745fea, - 0x059f72bf, 0x59dd0cfd, 0x795f984d, 0xea833dee, 0x33fc4e7c, 0x3e605648, - 0x6fdf6e65, 0xdb604e31, 0x279a8d23, 0x15aa44fb, 0x1825a6f9, 0x36398e99, - 0xce50bad7, 0x1f7efbca, 0xee43bb04, 0x91024194, 0x03579d0e, 0xcb82d3e7, - 0xc7f5fa09, 0xb035db77, 0x3f3cd95e, 0x7fff7066, 0xbee3f14e, 0x4205c445, - 0x3749bf2c, 0xc7ec08f0, 0xdf03e5e4, 0xec7ac20c, 0xc05a6871, 0xb68baa7f, - 0x9f65dfa0, 0xd9acfd05, 0xbe2b797d, 0x2bd9cb41, 0x1b0718ed, 0x6ceee57c, - 0xf3a7e7cc, 0x3cca3f1c, 0xf9654a1f, 0x8b3ef248, 0xfc99f406, 0xa8c0f104, - 0x0aa523b2, 0x968a7ee1, 0x07df3f69, 0x8e1e4a7a, 0x0a3f829b, 0xaa4354f4, - 0xcdd0077f, 0xa5a4b9d0, 0x892e7666, 0x2db5a79f, 0x9c176f7d, 0xfdc2d9f7, - 0x4ff707b9, 0xbffe859e, 0x7582594e, 0xf960e0b8, 0xb2a42f95, 0xfc48e278, - 0xd63cc41f, 0x65bf7ddc, 0x02e28d7a, 0x8c7597fa, 0x574ee45e, 0x5f19f80f, - 0xde63f049, 0x611d75ee, 0xeccdc62d, 0xa35c7f27, 0xd677ecc4, 0xb2d33d33, - 0xe3cfed93, 0xd29737f7, 0x921ebf2f, 0x0cbf4c33, 0x764eff95, 0xf4e2efcb, - 0x6fbcdfca, 0x5efdea21, 0xbf12fdbc, 0x8f611bbf, 0x9637f5c7, 0x50f2231d, - 0x61c786aa, 0xd84db4f6, 0x9e554149, 0x9f95954e, 0xfbaa343b, 0x47649f5f, - 0x3b79107a, 0x72caed29, 0xfe8fdbc8, 0x4edfa088, 0x3c8915e4, 0xcb1560a2, - 0x8c6a09f7, 0x4dd12e78, 0x687f30ba, 0x124b091c, 0xf006d7fa, 0xe42a6dfc, - 0x4fefd111, 0xff62e6a4, 0xa567899b, 0x22a6e516, 0xc826fc01, 0xb802493f, - 0xc1161b43, 0x7159b778, 0x9fe4133c, 0x033ee124, 0xc7dd39f9, 0x35a756f2, - 0x3a43b8b0, 0x4e50cfd5, 0x697467cf, 0x3cc7ab9a, 0x22579156, 0x5e044ff2, - 0xd3be38aa, 0x01ca2c27, 0x54f228b9, 0xe53d99d6, 0x39c11760, 0x1cbf3868, - 0xbcf3346c, 0x776fd613, 0x4f9e2e63, 0x2979b2fe, 0xf91678f1, 0x7f44fa29, - 0xe46cbba6, 0x37416739, 0x7089eb31, 0xecc7dc6d, 0x3d06aafc, 0x71b063ce, - 0x072bfa06, 0xec04351b, 0x037eaa81, 0xf1b8c3a3, 0x93d5ce36, 0x872bf430, - 0x054f204c, 0xceca5c3d, 0x085beba5, 0x6d83e0fe, 0x524ef33b, 0xd6d43fde, - 0x9341cf8b, 0x12bdabd4, 0x03cea1cf, 0xb48df5c9, 0x1af95afc, 0x6689b7c8, - 0x6a849449, 0x96faafd3, 0x60c4f54c, 0x287df472, 0x7be1bedf, 0xba3e3cac, - 0x9beda245, 0xed623ed3, 0xa9d33681, 0xefff5ed8, 0x57eb41b5, 0x267f7fd0, - 0x351cf9f1, 0xebf464ee, 0x3f41123c, 0xa57fd712, 0xadba3e4c, 0xdc9fb47a, - 0x54951f3c, 0x8854fcf3, 0x7b72d0f8, 0xefc6315a, 0x13d944ad, 0x030cfa81, - 0xe30827b3, 0xccf1f687, 0xf4e46d6f, 0xbf843240, 0xf208206a, 0x81c73dae, - 0xe7c90fdf, 0xf310863d, 0x8ff1b19b, 0x9e0578be, 0xb679124b, 0x6733d884, - 0x36f9815f, 0x135af2aa, 0xdb29a73f, 0x7bbce133, 0xc1db8ebb, 0xe6c47cbc, - 0x04f3885f, 0xddf6a4be, 0x507e1bd1, 0x7674fc04, 0x41f30fef, 0xa7a8ddce, - 0xe45184fb, 0x933a595a, 0xeb3a836b, 0xb77e894a, 0x016fe6c6, 0x32c77c3a, - 0x311c3a6f, 0xa9549b9a, 0xc1bc0077, 0xd780b4e7, 0x8e274e64, 0x473e0cd9, - 0x3c824fb5, 0x1b1376d4, 0x7b2fd937, 0x7f845cf1, 0x851b74b6, 0xf2625dbb, - 0x88947e9b, 0x92a15576, 0x26c87108, 0xcb55ee7e, 0xcb9688e5, 0x1b6e7f91, - 0xc1a997c8, 0x13ef4d78, 0x7fe7b05a, 0xbfe2e3cb, 0x9f9f51cd, 0xb83371e8, - 0x569673c5, 0xcfe802b9, 0x523aaba5, 0xab40e94b, 0xfd7084f7, 0x37186d32, - 0x772b603e, 0xa5efd00f, 0x42951fec, 0xe67b773e, 0xbe214a8f, 0xdc7a75a7, - 0x8f7298be, 0x357fd19b, 0x59bc03b4, 0xefc14b5a, 0x97f5b5fb, 0xfa2bfb48, - 0xf50dfdf2, 0x35706063, 0x7059a319, 0x9359fe6e, 0xffac3b7f, 0x30c7f985, - 0xfa40fc2e, 0xaf21f7d1, 0xd18ea8e3, 0xe793305d, 0x69ee93e3, 0x0eee9409, - 0x5e7839e7, 0x1ebf8b0a, 0xa8fcc09e, 0xfcb17e54, 0xe61289d1, 0x66ced621, - 0x266f62e7, 0xfa018e91, 0x68593a3d, 0x1c8af4fd, 0x796b7fb4, 0x77f4c89e, - 0x7eb0097c, 0xca8f6fd3, 0xb2c7f720, 0xeb746ee7, 0x3e188194, 0x975149be, - 0x97542e6f, 0x9751e5bf, 0x97f15dbf, 0x9365b109, 0xe8107bd9, 0xdf8955f5, - 0xb10d7147, 0xa4ba7f23, 0x935dd820, 0xe7e74a5f, 0xe53e5989, 0xf17ef94f, - 0xf5820aa5, 0x5b8d3b29, 0xfdcf508d, 0x3f5e5aef, 0xd98c4dd9, 0xea07c44e, - 0xf3c4a8e9, 0x93185d32, 0xb1ef7b22, 0x6d343f33, 0xecfda7ab, 0x1f20af9d, - 0xe43558a7, 0xa5ebc09b, 0x04c3b446, 0x289bb45f, 0x963c537d, 0x819a338f, - 0x9e75dbde, 0xd697d0f5, 0x2f40506c, 0xb1182657, 0xc83fed6f, 0x9b96d7a8, - 0xcb4ec40c, 0x63371f07, 0x3e265cb9, 0x20a123c8, 0x51e786ce, 0x0ad4279d, - 0x60eda5f3, 0x160eedbe, 0xeb96d757, 0x7ed3cf51, 0x3e0f5d71, 0x9c1109a1, - 0xf98ca57f, 0xc1661ca6, 0x7c247477, 0x6be734ff, 0x518486ad, 0x7bb3a58e, - 0xfed10e39, 0xbf83dfa1, 0xdfa0f6d2, 0x13b950ae, 0x271bcfea, 0xc0a8b9e0, - 0x592f79d0, 0xda15c003, 0x67e87cb9, 0x3f04f2e7, 0xa542f90b, 0x852bbe5e, - 0xf8149030, 0x053b050f, 0xfb8204ec, 0xccb71100, 0xd97a8a34, 0x0da6fd0b, - 0xe0e767b5, 0x56997852, 0x60253585, 0x27f1bca7, 0xe4b1c3a0, 0x931a6145, - 0xe429e213, 0xc3c316c5, 0x19af6a47, 0xef0a3d6d, 0x9b0cf2c7, 0x84c7ad9d, - 0xad4be00c, 0xe8064279, 0x478776cd, 0x0b94c5f1, 0xae6a76e9, 0xdb45f013, - 0x35adf2d1, 0x18e5f2c7, 0xc69854fd, 0xe76d00e4, 0x1ef0a24d, 0xc0192934, - 0xdb8ca3bf, 0x7cb5c6cc, 0xe9bae3bd, 0x41ddb4b8, 0xb6971d1b, 0x843266db, - 0x8da30935, 0x78c0a15f, 0xa2971a97, 0x833f911d, 0x93a503af, 0x0ec1f820, - 0xaf4834da, 0xf2be7833, 0x1e3664c1, 0xffe75429, 0xf8e99be4, 0xcea65f98, - 0xda51b9f7, 0xfa7a01d4, 0x56c25369, 0x3837cfa0, 0xfcb61cdd, 0x69d83e43, - 0x382bcc6f, 0x71267284, 0xd1100779, 0xf28bd20c, 0x0bc1c846, 0xa1cac769, - 0x8de1e54c, 0x0fde7469, 0x079d1ee4, 0x3c721f9d, 0xa5f68f9d, 0x56935bd9, - 0x417e1236, 0xa06e029f, 0x218be053, 0x5f838d3a, 0xa5b91bd0, 0x37251317, - 0x9e173b53, 0xa425eec2, 0x2bc5e595, 0xa3f3c399, 0xd8dd3e44, 0x18d1e6ca, - 0x746fb844, 0xe6f318fc, 0xffe718ee, 0xf735c01e, 0xbef04fca, 0x3f9ee222, - 0x1477f601, 0xc96979de, 0xc6f07bff, 0xca97f9db, 0xcf8b1f0f, 0xacd2f8c5, - 0x1e1f989d, 0x7cc56d98, 0x3f3c69f1, 0xc1a0d036, 0x0fdd00b8, 0x85a23ee2, - 0x97204318, 0x5cbb72a7, 0x45785b9c, 0xe0d6fe62, 0x7d45068b, 0xde7c513f, - 0xe97982b8, 0xbf2c65c1, 0x6f7ec87c, 0x1f7ed056, 0x9cfc73d2, 0x93317744, - 0x28f7dded, 0xe689fbea, 0x44fdf513, 0x7121ed0b, 0x32948a6f, 0xdddfbf9c, - 0xbbfe9043, 0x9f58b96d, 0x88fa65ae, 0xa3e9837c, 0xbaa21cee, 0x399d691f, - 0x94f31134, 0x46c15e78, 0x6ff83fc8, 0x9a7e0bf2, 0xc2fca926, 0xc9afe543, - 0xf0e6dc2f, 0x5b3a02ef, 0x92cde458, 0xebd63d28, 0xd2987f99, 0x8108a6eb, - 0x7cd6c574, 0x44dda7d8, 0xe4d2df5a, 0x02febd21, 0xa53275e9, 0xbd153cd7, - 0x15fc61ee, 0xe82d2144, 0x0b4e8875, 0xfd00f3e3, 0x6edc60fb, 0x5befef47, - 0x6fd35f60, 0x683cb0f0, 0x2f19d796, 0x59e0621f, 0x5c783320, 0xf3c22d5a, - 0x0f13f43a, 0x4df0e5cf, 0x12a69d2c, 0xf1631fc6, 0x824caa4f, 0xfe6192b6, - 0x6ffd9931, 0x7c43b8c1, 0xcfdb08f4, 0x6b5b808e, 0x739a7a45, 0x057f8b07, - 0x802ecc2c, 0x1d1a5838, 0x7f1f267f, 0xdaafa74e, 0x4a66ed01, 0xfa610f0c, - 0x167f850f, 0xdfd99faf, 0xb370798c, 0x63c775aa, 0x2f2120ed, 0x2e6ddc45, - 0x7dab7f6f, 0xd2f20ea6, 0xe3aad767, 0x64ef735d, 0xb339b6f1, 0x25ccfdd5, - 0x7cc13fab, 0x03aad24d, 0x53bdcdfc, 0xda49ff5d, 0x026c9c50, 0x710ec9c4, - 0xe520d03f, 0xd7a3e013, 0xba6f1793, 0x84f9d287, 0x8095149f, 0x9486f0df, - 0xd04f6dc6, 0x271bb3f2, 0x94f5f961, 0x28ff7eef, 0xc0296fd4, 0xe25c3572, - 0xe056fb04, 0x8567ca43, 0xc8cc77e5, 0xc27d0049, 0xe087bdfb, 0xdfd9b77b, - 0x73b6933d, 0x3cc5c94f, 0xd7ee6ad6, 0xeac85c18, 0xc6d2be6f, 0x52ef9552, - 0x6d5c5fd0, 0x1d35f766, 0x04bb7e29, 0x73abaaf2, 0xd5e4b979, 0x243e5049, - 0x3af7827d, 0xcab66b9c, 0xe92d0eb0, 0xb93ecfcc, 0xa44f0a50, 0xf276a978, - 0xbcd99bfe, 0x4b9e4b6a, 0xaea93e07, 0xf64cfd62, 0x41e67654, 0x2c79cd3b, - 0x26374b9f, 0xbf05fe00, 0x957df0e5, 0x5c7d2bb0, 0x3de4bc4e, 0xfb4491d6, - 0x0f2519f5, 0x7157d14c, 0x664bdd8c, 0x7d03e765, 0xfc191cde, 0x2cbcd3f4, - 0xb8cab6ef, 0xe1e40d3c, 0x297d7e2d, 0x2c6ecbcc, 0x1179043e, 0x65951589, - 0x246da798, 0xfe94beb8, 0x3f03a7c7, 0x5649fd5e, 0x559d1002, 0xbe82ff4d, - 0xafba0a66, 0xe537d356, 0x65e9c9db, 0x2adf9697, 0xd30d36fa, 0x3ef658f7, - 0xe102ab85, 0xaf5a86fa, 0xc7138d0d, 0x8ee3f19f, 0x2fe03725, 0xc30efe56, - 0x987c8bd7, 0x798dd901, 0x825da7c0, 0x38026f4f, 0x9e089af4, 0x3c96ca8f, - 0x7180f093, 0x7a88c785, 0x055f8e2f, 0x33e0997c, 0x1709192f, 0x6ec2c9fc, - 0xf02e7f65, 0x7af064a3, 0x38979dfa, 0xe3a2e187, 0x7a0e91df, 0xcf0611fc, - 0xc995a966, 0x112fbe19, 0x311697fe, 0x7cf53edf, 0x1eeccdcb, 0xcbf83703, - 0x3c527630, 0xcbee0869, 0x9f310758, 0xb3e7d700, 0x9e9b3e8d, 0x4736edce, - 0xedcfd23d, 0x283aa354, 0xff74c25e, 0xd41e700f, 0x7ec1f704, 0x62f1216f, - 0x47d29cfc, 0x6ec63d20, 0xe3c6f012, 0xb90c65a9, 0x789f3f1a, 0x5baf0cfc, - 0xe29e0d24, 0x7cd0e1fc, 0xf19e732f, 0xaf4b8af6, 0xb93a5bf6, 0xec39d17f, - 0xfa842c4f, 0xa0f6625a, 0xe123d13f, 0xda96af7e, 0x6ba7201f, 0x71fa086b, - 0xfa0d569c, 0x321d8513, 0xff5c9f16, 0x6ab7264d, 0xf73f089b, 0x4f17e6c8, - 0xe064a98f, 0x1ad6787e, 0x800b0d95, 0xaaac1bff, 0x56b50673, 0x4e788f16, - 0x503211c8, 0xa87f7a06, 0x0fef423c, 0x8a1c8194, 0xf6ae7fbf, 0x3b7bf322, - 0xacf84a2f, 0x032b1cf5, 0x19acefbd, 0x56790328, 0x14fef767, 0x13dc55d6, - 0xbdcf8f19, 0x97911ae9, 0x1a745972, 0x0e2247cf, 0x7fe6c47a, 0x3fc63d39, - 0xa08a5675, 0xcbb5759f, 0xcfe7e7ce, 0xd8767a01, 0xefc12a73, 0xaad8db34, - 0xd138bb03, 0xce903fe1, 0x5f17e8e4, 0x9a17e6c0, 0x56de3c52, 0x66587fed, - 0xee1e22c3, 0x81b878e5, 0x9bf3d9eb, 0xa90fb8b4, 0x0d3e16f6, 0x9bc0a0a1, - 0xbe42123a, 0x147ea2f5, 0xa79dc6f7, 0xda185506, 0x7d436f3f, 0xf557f8bb, - 0xb09b2718, 0x1894435e, 0x6431397d, 0x327fdd56, 0x5553a779, 0x5d37a2be, - 0xbecafed5, 0x717d555c, 0xfeaa9278, 0x544b37aa, 0x54c8b2e5, 0xdfabfb55, - 0xaf9552a9, 0x6aa19819, 0x3df403bf, 0x4e37e3c5, 0xffbd52cf, 0x37f4e368, - 0x5d7d3e21, 0xefaa3bf4, 0x043f704f, 0x85237a09, 0x040bfe74, 0x53ac5ebd, - 0x9acd4f7d, 0x7c0e54b0, 0xac16fecf, 0x95f77966, 0xfdb16314, 0xdb52ec2d, - 0x28903713, 0x84b62be6, 0x40984f24, 0xbeba9dde, 0xf107afb1, 0x0f7ba97a, - 0x6be6b826, 0xc69754c0, 0x22633b51, 0x0d5c8220, 0xf1638379, 0xbfd6a5fb, - 0xa97fe480, 0xd5b837f5, 0xd4526feb, 0x54296feb, 0xa3cdbfaf, 0x0ac4ff5e, - 0xbc3bfaf5, 0xaa4ff5ea, 0xb27faf51, 0xa9febd4f, 0x9febd573, 0xffaf57e6, - 0xbaf506b8, 0xd7aab667, 0x7aa97b3b, 0x4b82735d, 0x74f1f554, 0xc849e820, - 0xf795bccf, 0xa453dbaa, 0x42e86268, 0x5f02d9d0, 0x8d63e603, 0x35487aef, - 0x4c7d3c5e, 0xf48f3c20, 0xe547d22b, 0x727f6e38, 0xa97aa0ba, 0xda325c6a, - 0x73c03719, 0xff6e04ee, 0x33b746fb, 0xd58afc84, 0xe6fbb1eb, 0x08dae4b1, - 0xd1f7c57d, 0xd82bea63, 0xf7869b47, 0xefd163d1, 0x59ea84bb, 0xfa357c1c, - 0x33b0eecf, 0x999a0e38, 0x5429ff3d, 0xd1db435d, 0xde141536, 0x743e6177, - 0x93cd77fc, 0x1df20fd1, 0x7183abd2, 0x7c1124ef, 0x7c5123ce, 0x755d89fa, - 0xf10165be, 0x645fb9e9, 0xc9a9e009, 0x7a0e5038, 0xa3fcc2ff, 0xee7c63ef, - 0xdd65d248, 0xe21c7207, 0x3909e33f, 0x49c9e5c5, 0xf2d10388, 0x27f71339, - 0x8ae2897a, 0xee29e7c1, 0x269bacf7, 0x5a259ea1, 0xd5b1e633, 0x9ea12edd, - 0xf60ffbaa, 0xf4c71f6c, 0x52e788da, 0x6e2ed781, 0xa13b301f, 0x62dd0e0f, - 0xadf890fc, 0xec7a8f68, 0x3fb4deb0, 0x47f98716, 0xdbb17f76, 0x25dce0c8, - 0x89c2b911, 0xdd7106c7, 0x7ce1fd61, 0xe0c8db9b, 0x4623a5db, 0xe264efc0, - 0x31f0fb47, 0xd63c8a99, 0xefd624ef, 0x17f05cd1, 0x7e6fcd9a, 0xa9f21aab, - 0xf472e0e5, 0xa88f7fdf, 0xb677f7fd, 0xffbfe84a, 0x3e9b851e, 0x1b8f76dd, - 0xef28b2f4, 0x1e21b802, 0xfbe8ed00, 0x04ab7754, 0xadafb1fe, 0xb10f3dbf, - 0xbfb25f76, 0x83087ea1, 0x3d60fe0b, 0x83367f85, 0xd281b7d2, 0x11efb6cb, - 0xfbc61ff4, 0xa969c76b, 0x31fc8106, 0xc097bb1d, 0xfb67af2d, 0xbb1ec3e2, - 0x7444cfca, 0x7a47380e, 0xf20e7b29, 0x9cc54fbe, 0x3474a0d3, 0x1fbafdea, - 0xa47cb065, 0x44c8b6f6, 0xe39e4b88, 0xdb87d771, 0x56b2c4de, 0x265e60f6, - 0x88e5f7dc, 0xa2ef5ef9, 0x4e7231f5, 0x63efd2b6, 0xeace8de4, 0x1e6bcbc3, - 0xbc608b69, 0x25efc753, 0x5ee3347b, 0xbfc63fbb, 0x6e38cef2, 0xc4831927, - 0x69b8429e, 0x4f4eff4f, 0x5a3f4023, 0x762a7cbb, 0xd3706d1f, 0xeef562fe, - 0x1b1264c5, 0xf6d9587f, 0x88fdc20e, 0x6743f7e4, 0x36127c86, 0x641b7c51, - 0xdf4d0338, 0xe511b86f, 0xaf76deaf, 0x1aa1ee07, 0xb7067f0b, 0x7e56217c, - 0xdf8e387e, 0xe7e5c5cf, 0xc9d16d93, 0xdb7b4e30, 0x5d6f0a80, 0xfdf1176d, - 0xc452369a, 0x7ac43fea, 0xf4828d4d, 0x42d28a73, 0xf27ae204, 0xc1fc0d80, - 0x10263ed4, 0x8db9d67f, 0xb8306f18, 0xa2e4bc18, 0x9e63e90b, 0x3e00c19d, - 0x1f4a4cbf, 0xe1d52fef, 0x4cbefafe, 0xefbfb62b, 0x780fe337, 0x29eadf29, - 0xc37fb41a, 0x61c7867c, 0xf973d3f8, 0x0fbf6449, 0x5d3e80e4, 0xd38538c6, - 0xf1d70b3e, 0xf027f6cb, 0xcc1137ae, 0x5a67d647, 0x5cb85ed1, 0x6a19dd38, - 0x8fe3c7bc, 0xffe509e2, 0xf74f1c7d, 0x93fcc83d, 0xf04fddf7, 0x4a59053c, - 0xe987caff, 0x87971c6a, 0xcf87c4a9, 0x082a36ae, 0x465eb00d, 0xed409fe2, - 0x8d8bd211, 0x82a7e04d, 0x80ecaf7a, 0xaa2788d4, 0xb9e1335d, 0x1764e2a6, - 0x6bdae3b0, 0x13c08b3f, 0x2f801162, 0xc109037b, 0xab98bc55, 0xf877c740, - 0xd7813959, 0xe565cc27, 0xe89f5e44, 0xef4ce563, 0x0035520b, 0xcb471716, - 0xca6f3ab4, 0x80bc7907, 0xfcf173b0, 0x84cd8d7e, 0x73ab0bcb, 0xdfd43566, - 0x8b9cf049, 0xaf09ffa8, 0x5f1eb34f, 0x637a0799, 0x0dfbfab6, 0xd6a90f1c, - 0x30d35de3, 0x17aea6de, 0xeb64acf1, 0xfbf137f9, 0x53fd7522, 0xf59b7bfc, - 0xd41a647c, 0x7fc7abe7, 0xac5bd79c, 0xca8def2c, 0x037f767e, 0xd78c7faf, - 0xc61ea09b, 0x5af5642f, 0x6f09df71, 0x18e1c9d7, 0x431e33e2, 0xbf33260c, - 0x233696f2, 0xbf3c57f2, 0x73f707dd, 0x9bf30d95, 0xf519297d, 0x32fb86de, - 0x5049dc98, 0x51debc06, 0x77a8a2e4, 0x37cc65da, 0x48f5bad0, 0x972b064f, - 0x871f9c27, 0xead489e4, 0xe4c64461, 0x9ae8a5f4, 0x9005f012, 0x0ff4596b, - 0xfbe33ae8, 0x918fe21a, 0x664de973, 0x83e58fe2, 0x39554e05, 0x5574cee5, - 0x5cecd77b, 0x74b5bd55, 0xcc9eaa92, 0xdc9f2276, 0x5ccbe9cb, 0x17aaa254, - 0x6d9065f7, 0xb59d9dbc, 0x554fe5d3, 0xa85f3bb5, 0x9f8d0224, 0xa3dc49ba, - 0x7c8231e6, 0x9b96d7b8, 0xb3f8fc0a, 0x4e440ab6, 0xf627e53b, 0x1ba7f3b4, - 0x54fa598c, 0xcb10b978, 0x7e583bcf, 0x879b7b7f, 0x9e087395, 0xab6f6faf, - 0xca2ef2c1, 0x69fcf09f, 0xdb9f179b, 0xcfa15969, 0x2bfda47f, 0xda1e9fb4, - 0xa19f943f, 0x3373c3fd, 0x3f9e1fed, 0xfd43fda1, 0x942fda06, 0xc170a69f, - 0x0fda29f3, 0xed31ffbc, 0xb44fca1f, 0xb6bcb0f9, 0x1f962e6d, 0xf3e3f36f, - 0x7c06b6b1, 0x8ad6d9df, 0x96db47e5, 0xb6e1f3e2, 0xdbdb3e20, 0x2f7d6256, - 0xf9e793a7, 0x2be7dc79, 0xf103bdd9, 0x219fdfeb, 0x9d2fbb61, 0x154a539f, - 0x3f2ab97a, 0xfc033fa7, 0xfceabd02, 0xc21fc054, 0x8c786261, 0x0668e387, - 0x91270fb3, 0x930b72c8, 0x1f07181f, 0x6159e7df, 0xae35fca1, 0x4e7bad95, - 0xd3eb145f, 0x4778d81a, 0x5c409db9, 0xce519241, 0xbb439b8e, 0xcaa45273, - 0xd007f2c2, 0x14dc430f, 0x5aece53f, 0x21e64672, 0x5725c00d, 0x331e3d50, - 0x397c21af, 0xb7809c18, 0x57fde0d1, 0x696d378e, 0xa75fbb2f, 0x6c0c2ba6, - 0xe2b6f666, 0xb9c63afd, 0x9f4cb0be, 0xef1f9f2e, 0x717498e9, 0x5224dd3a, - 0x9bf176f9, 0x8ccfa144, 0x31fef526, 0x6a89417d, 0xb8bda67f, 0xd1572886, - 0xfbd48b7e, 0xbdfe733c, 0x198cefaa, 0xf5eaa90f, 0xfaaa15ae, 0x1e73bbba, - 0xc73e0371, 0x6199b8b1, 0x210272f5, 0x4fdd85e4, 0x4ce65c20, 0x92738f36, - 0x605f7ec2, 0x133dff37, 0xd6797fbe, 0x5c65f1ce, 0x09f2fb8d, 0x482c560e, - 0x0f406a0c, 0x448bfc7d, 0x9e3b7f94, 0x7e9fa0d1, 0x40690922, 0xe6a64cde, - 0x015fd424, 0xf16b8c37, 0x942d26aa, 0x85a2898b, 0x8a2455f2, 0x7fba3afb, - 0xf5d264d1, 0x9ffad16b, 0xd9f2d131, 0x2cb3ff4c, 0xfa8c30bf, 0x67af80ba, - 0xadc7d881, 0xdcfde397, 0x37f44cc6, 0x7625cfa9, 0x874bfdf0, 0x970df989, - 0xc153ca3b, 0x46373e0e, 0x7dcda83e, 0x14058de2, 0x63b4b6df, 0x1fef14f8, - 0x9ea33457, 0x94cbcfd7, 0xf75e5abe, 0xd44faa7a, 0xf307937c, 0xcffa5b38, - 0x6b76e029, 0xff228fc9, 0x3c84e874, 0x9e411253, 0x893d970d, 0x3b1e6624, - 0x93c9deda, 0x11fa2151, 0x375f326f, 0x4ff95f31, 0x4bc87695, 0xd179e02c, - 0xf2d2db3b, 0x7f0fc7ab, 0x5074e3ef, 0xa0352248, 0x348b0b5f, 0xe074109e, - 0x31fcabb5, 0x2f2efca6, 0x4b930b9c, 0xf2c40788, 0xf785d244, 0xd57fc829, - 0x7c9a3e62, 0x50a21af0, 0x0d6ad8fb, 0x70d16093, 0x75fb84bf, 0xfce5cfbe, - 0x9c6af667, 0xec259c8f, 0x74e80f26, 0x1bd599f2, 0xacfc3a01, 0xf4d8c75b, - 0xd0bebab8, 0x2def504a, 0x1487d42a, 0xebcbee09, 0xe5407bc2, 0xc8c9122d, - 0xb9a63801, 0xdf7e83e7, 0xb63a416b, 0x9fc72fac, 0xe359b830, 0x0efc40af, - 0xc2357b28, 0x9aeda2e8, 0x82b7eb27, 0xf001393d, 0xdcbc0562, 0x430d5f91, - 0x1e2217e7, 0x2f79f217, 0xc8e8f3e4, 0x833fc21c, 0x70bc7887, 0x6ea2ef1f, - 0xcf528fe1, 0xaad2f1f3, 0xa2bdc36f, 0xff2d11ed, 0x3e352299, 0x5322e957, - 0x70c34be6, 0x66173851, 0xb8015c82, 0xd80f82af, 0x919f9afc, 0x941cc6c8, - 0x6f68356b, 0x3f306994, 0x9b2e9e3d, 0x8fdc9932, 0x7dd9d866, 0x4853eee4, - 0x93e5c3cf, 0xc2482c6f, 0x5bb333fd, 0x8fcb326c, 0x58957af4, 0xe12af7bf, - 0x72e7e45f, 0xa1de1ccc, 0xb127057b, 0x892b60bc, 0xb4bc87ac, 0x2bf5f6b1, - 0xdc707332, 0xb53d7de1, 0xa53f205d, 0x5c7988cc, 0xa13e44ab, 0x69995472, - 0x57384f63, 0xfa74e465, 0xf79d4da8, 0x6fcf9db3, 0x418f5f3b, 0xf27bc8a3, - 0x9cc716d6, 0xafeba9f3, 0x88963f47, 0xff720ed3, 0x1d59a0e1, 0xa4e46d57, - 0xaba87830, 0xc1f10cca, 0x6da7162e, 0xdd99bfec, 0xc7efbb6b, 0xed302f78, - 0xa87a0153, 0x57ebede7, 0x0b58fdaa, 0x5f91fa77, 0xf164fde3, 0x398a317e, - 0xe31fec3d, 0x335b62fd, 0x43c27ef9, 0x7b0e218a, 0x61de7562, 0x7277ec33, - 0x1f0f9e08, 0xef017da7, 0x81bba6dd, 0x974fb82e, 0xa3fbb114, 0x54ffd7e2, - 0xb2f11e96, 0x78efac53, 0x3ba5da2b, 0xd81c98cb, 0x2dfce079, 0x2b3f69e3, - 0xf9d52473, 0x3a399580, 0x29b7a75c, 0x97b3c37d, 0xeed19a90, 0xa9943b29, - 0xef726af9, 0xc1eff55a, 0x1c0df734, 0xff2828b6, 0x1fba035e, 0x4279fc3c, - 0x1451f211, 0x08c4bf7f, 0xc19930c2, 0x76b3e70d, 0x17993e6b, 0x676f0f4b, - 0x36ff58ca, 0x0d2f8ba7, 0xae1ab557, 0xa56f45b3, 0xfd7060cc, 0xb9c6e40e, - 0x5894f1f0, 0xb5c0467b, 0x03df8c7b, 0xe2abf0f8, 0x1fad42a9, 0xfa74f062, - 0x6ed3c3bf, 0xfcf0e8fd, 0xb3f3c395, 0x9b5eec43, 0x515ff591, 0xe1ab759f, - 0x647cfb3d, 0x0a49880e, 0x7f115fef, 0x182993ee, 0xebf8e613, 0x59f4e52d, - 0x078fe5ca, 0xc09150cf, 0x1e63577b, 0x924caf66, 0xbe5ca16a, 0x2cf77f00, - 0x02c3ef93, 0xbf9e3f1a, 0x4619ef21, 0x64d77f95, 0x9ddeba31, 0x878a8d2e, - 0xcf362cd2, 0xb2ea4703, 0xd8f1bfc1, 0x7202063b, 0xbfcf3361, 0x6bdecc7e, - 0x05a67b84, 0x425ca11e, 0x747d019f, 0xc7bc2811, 0x2a333f4a, 0xd3c651d6, - 0xc6d6f1b0, 0x4f188df1, 0x1564a73c, 0x3a557b32, 0x387385a4, 0x0b7daf6b, - 0x5b5b7fef, 0xfdeca32a, 0x1d5ff8d2, 0x5bf0ff87, 0x7a30b729, 0xe1459299, - 0x90fe916b, 0x0e5a6df0, 0x2a7fd148, 0xbd157c82, 0xa01fe71f, 0x4691ec78, - 0x8b2d29e2, 0x9f988bd1, 0xdb80bf98, 0x5c02dd76, 0x06bbdb07, 0xbca51a54, - 0x8917d0bd, 0xbcc1ff5c, 0x2b5c5f50, 0x654c73b3, 0xdafbae32, 0xee78a98a, - 0x17cf376c, 0x1fa35e89, 0x164477f5, 0x763dbc70, 0xb811b7f1, 0xafd83947, - 0x883ffbc3, 0x15bee03c, 0x8dff1fee, 0x5389f78c, 0xfb81aa7a, 0x391c0ecc, - 0xebfb009f, 0x843a59f9, 0x87973e7b, 0x35b51783, 0xc8ec1e78, 0x0c6d7667, - 0x6965d7fd, 0x89127db9, 0x35af39c0, 0x8b3cec25, 0xd603db95, 0x001b2723, - 0x43c56b7e, 0xde862906, 0x10196566, 0x68fa35ae, 0x17f6878a, 0x6125a7d8, - 0x7bc1ffe6, 0xb3ce8719, 0x5a1e19da, 0xbda10f4a, 0xf767ed60, 0x2965d635, - 0xb852ce4c, 0xe6f7d2f7, 0xebd99f89, 0x8e94bea1, 0xbdfc3b97, 0xd3d6cecd, - 0x4beec65c, 0x3fed7b5a, 0xc83ee1db, 0x471df844, 0x79f2efd8, 0x7292b80a, - 0x48dfbc35, 0xcbf81724, 0x5abe632e, 0x235ef86f, 0x2f82fbd8, 0x62d5cade, - 0x39f947bb, 0x0a2b4789, 0x4cae7043, 0xdb35b1d0, 0xcc1640ff, 0x0bc5f28f, - 0x7c44ef68, 0xf63f10d3, 0xdf33c862, 0x32e64525, 0x076f443b, 0x68d42c3e, - 0xe116fc54, 0x549e26eb, 0x73dda3fd, 0xa15da73f, 0x46423bf7, 0xfe4de702, - 0x22667178, 0x191da7d8, 0x1af3dec2, 0x259b5f01, 0x8c0e625f, 0xdc5a2ff3, - 0x72381e0f, 0xedc601bc, 0xbe02f3a0, 0xeb75f87d, 0x3a53b06a, 0x53e45eec, - 0xd0ecbe31, 0xfd60f5f0, 0xdf7bd6ec, 0xd4647f04, 0x3acdeec1, 0x11867538, - 0xd3b69fe8, 0xa07f3f40, 0x04f0f7fb, 0xfd1aa7e8, 0xb3ed0b06, 0x8b77c3a6, - 0xb011ff88, 0x6b75176f, 0x3c83f755, 0xc2c5e5cc, 0x8e12168b, 0xac2c2fd9, - 0x6b9e0ef8, 0x0131785c, 0xcfcc3fdf, 0xcfcc3fed, 0xf8e2edbd, 0x5f3f9978, - 0xfb8afacf, 0xde9c4f6f, 0x8eddfe4a, 0xbbf7c63a, 0xa59afd60, 0xfaa83d01, - 0xc73f5335, 0x687f64f3, 0x21b093b3, 0xf311de06, 0x98e1224c, 0x5dda8771, - 0x52709134, 0xfa32faec, 0x15af9e1d, 0xe6d0ffeb, 0xdd8e3c46, 0x1e1538ff, - 0x53cffb87, 0xff6471e1, 0x87ff5805, 0xf44bc2b6, 0xfe8c793f, 0x0ff05473, - 0xef8f9bf7, 0x7bac1dcf, 0xeef942d6, 0xc6c57860, 0xf7e14b57, 0x7bf80cf7, - 0xb7afa41b, 0xeeb9cf0a, 0xfa0e7822, 0x7a7ffd81, 0x1f52f21f, 0xc0f7aad8, - 0xe8ba8318, 0x7a28cf3c, 0x83d89f26, 0x789cef70, 0x87959dbe, 0xdeff1ceb, - 0x90ec8728, 0x942c6a67, 0x8ce7a0ed, 0x015a1224, 0x235297fb, 0xdf1139ca, - 0x34fefd12, 0xb392ab53, 0x46a17ee2, 0x68d87f9e, 0x26aff161, 0xac2cffab, - 0x574d12ff, 0x1f68cfcb, 0xf03b0ba7, 0x0e213b7c, 0xf888d7dc, 0xc5fb0c8e, - 0xf97d703c, 0x9b0b9c08, 0x0cffe397, 0x1509fbbe, 0xd1ef102b, 0x0fcdb15e, - 0xf38f79f9, 0xa6e3e47d, 0x2313db88, 0xf2d9753f, 0xba1bb357, 0xecb7e8e2, - 0x8cc23b77, 0x40d9757e, 0xcfc8dabf, 0x7ce072eb, 0x67bf00e3, 0xb9fb414e, - 0xde30f4ae, 0xfc275947, 0xf3e32b02, 0x601d3256, 0x54788b4f, 0x8217e402, - 0xdd86b0dd, 0x616f5853, 0x275ffae5, 0xba17b9e1, 0x8114b21f, 0x65add99c, - 0x071e22fe, 0x1e61cf3b, 0x02c9ae34, 0x7cf20efc, 0xaffdf397, 0xe7a7bde1, - 0x3a478e57, 0x0fe5ffa8, 0xddc31ef1, 0x0d9f4ce9, 0x3ea1b3ee, 0xca7837ab, - 0xddcd5ee1, 0xed6ecce9, 0x2509c395, 0xa3ec7631, 0xa7285519, 0x5e395e3f, - 0x19271b13, 0xc2e4cd9f, 0x94ffe11a, 0xce70e5a3, 0xf0d2e3ea, 0xdd3ea13f, - 0x1bdfc263, 0x53fdecd3, 0xbabfde39, 0x63bf80c6, 0xe277b551, 0x5fb0b9ba, - 0x1f31904c, 0x84d7b35b, 0xc55d9cf0, 0x6f8383ee, 0xef35ee41, 0xcbbf871d, - 0x62896f56, 0xd9b364de, 0xc1f10053, 0xc0dfbdfa, 0xf1389fdf, 0x902cc4f8, - 0x9593c783, 0xfb6fbc2c, 0x3a748a71, 0x26fbe3ef, 0x579df7b0, 0xdb6ab9e3, - 0x347f8b1a, 0x4bd088ff, 0xedcdf7f1, 0xd73e2f4e, 0x6899f807, 0x5e1c80f4, - 0x675fe438, 0xbfd607f7, 0x24a59d19, 0xf306ffa0, 0xa7edea17, 0xeb1df7f0, - 0x49dd8fbb, 0x42e93e30, 0xbcfb15fa, 0xb9eb71f8, 0x8faddafe, 0xd5df83ce, - 0xf8e76fab, 0x59f7bfe7, 0xdfc629af, 0x5ff8149b, 0xf31f7713, 0xc5de38f7, - 0x1911c4f3, 0x76a4b9ef, 0x8ff81645, 0x2037ec4e, 0x33589dbd, 0x1057ef19, - 0x5853d5e3, 0x8f4f94ed, 0xb029953b, 0x15b20bbe, 0xb676ff36, 0xe9ef157f, - 0xbdf811f8, 0x2d3ee8ce, 0xda0dafe6, 0xc71009a3, 0x7944ed14, 0x5afd3e68, - 0xddb7bdfc, 0xdd7007e9, 0xa0115d29, 0x6d2fcd2b, 0xbf03b7a8, 0xf71bbf64, - 0x82092971, 0x8ef8349f, 0x077bf701, 0x9ed019f7, 0x9d977c1e, 0xef711fcf, - 0x059a359f, 0x7e06dcf7, 0xdae50e39, 0x0b746660, 0x784dbfb3, 0x51e0e4cf, - 0x5e3cd5ff, 0xd1efc69c, 0xefbb034c, 0x18533ec2, 0xc4fa3eec, 0x6c9043b8, - 0xfdfbe373, 0x882fbc16, 0x24f9d93e, 0x7f1b8f69, 0xf1748937, 0xfdf823ef, - 0x09fe5903, 0xc81fa720, 0xe15bfda3, 0xeed893fb, 0x4affae42, 0x9211598c, - 0xc74bc7ce, 0xd9fd337e, 0xccfa5ef8, 0xa80f7ecd, 0xb047d78b, 0x5ff0603e, - 0xbdf8f38d, 0x328cf48d, 0x5f7aafcf, 0x49d97de4, 0x6e028eb8, 0x23b4678a, - 0x93d2f1e3, 0x029ff6cd, 0x3974f11f, 0x80979eb4, 0x7832fc0f, 0xb63ec0bf, - 0xea26ab8e, 0x9ce93c99, 0xde32f68c, 0x27931430, 0x07df7cb8, 0x3a839748, - 0x97a0d3ef, 0x847547a2, 0x2d48c3dd, 0x5457f003, 0x16f576b0, 0x7010f7e6, - 0x07e7e19c, 0x1e593b1a, 0x3ee799e1, 0x856f9ac8, 0xa81ff3f3, 0xff0bcfce, - 0x0124ed21, 0x8f5633fc, 0xc4575092, 0xc22d76ec, 0x6e8f7ec5, 0xdfc14e8d, - 0x3e3e0c0b, 0x2712fd11, 0xbc5ecaf4, 0x15d57607, 0x6d27a01a, 0x4fbf9731, - 0xfb8979b0, 0x6d3dc4dd, 0xc81978f1, 0x99b2fa66, 0x3b82eff8, 0x25138ffe, - 0xf14b0785, 0xff744abe, 0x52cd206b, 0x7e589af6, 0x9185ea3b, 0x2fea42f7, - 0xff827bf1, 0xb053e5bb, 0x9f806556, 0xd5e80260, 0x7fb676d3, 0x40225bc4, - 0x3cd96bbf, 0xb803e03b, 0x4ef882ff, 0x5bc45e83, 0x4e1e2825, 0x9e3eac4b, - 0x1bbc84ce, 0x1ba00f81, 0xa3be17e8, 0x9d9e7f7d, 0x763ff6c3, 0x17943f27, - 0xaa5e43d4, 0x490157d0, 0x0f7dc0d6, 0x024a1d27, 0xcec9e5d0, 0xc872e73c, - 0x292871f7, 0xe076f6b1, 0x0e7bc110, 0x73ff3814, 0x922efc35, 0x05f80a77, - 0xfed53b77, 0x5e787888, 0xfd401ca8, 0xc6985ff3, 0x800053c5, 0x00008000, - 0x00088b1f, 0x00000000, 0x7db5ff00, 0xd554780b, 0x733effb5, 0x79332666, - 0x84841e4e, 0xe4249840, 0x09308401, 0x0741410f, 0x68151048, 0x85280978, - 0x42100793, 0x17b6881e, 0x240cdb5b, 0x41b45a20, 0x768bd151, 0xb4544140, - 0x03414141, 0x58a50077, 0x56d56351, 0x880dcb6d, 0xa8311fbc, 0xadadff97, - 0xfb5bf5ff, 0x90ce649c, 0xf9b7b5a8, 0x67d9d83e, 0x7b5ad7bf, 0x3bdaf5ed, - 0x3f437cdf, 0x756109d7, 0x10f4422b, 0x116dce22, 0xa3109862, 0x42f382dc, - 0x11c885d8, 0xca8df3fc, 0x5c3adb89, 0x8df88588, 0xdaf9aaaa, 0x2bc89eb5, - 0x1f5c2deb, 0x774675e3, 0xb5f1bdf1, 0x28f250ff, 0x084c21b3, 0x5d3dfe87, - 0x1e310f88, 0x90ea7b8d, 0x460ca7dd, 0x09ac2e1a, 0x75ac5442, 0xa51a45fa, - 0xbacc4e6f, 0x4285e653, 0x5c6cc775, 0xe34ad899, 0xca2a6f96, 0x1fb29112, - 0xd0aaf341, 0xea9e55e7, 0x0a8752cd, 0xeaa8f6d1, 0xebf684da, 0x6a8f9e55, - 0xa51eb8f3, 0xdbd627ef, 0x9fa9cb5c, 0x273e7d0a, 0xc5d16b7a, 0x0ab794b9, - 0xf280bdab, 0x45da2d56, 0x54782efd, 0xb177f62d, 0x81f7aa3e, 0xf80ba0b5, - 0x3a894d60, 0x1ea8327c, 0xe39469d6, 0x7268f7bf, 0xc2fcd157, 0x63cc77e9, - 0xd1f7e2a3, 0xd1f44efc, 0xfc7f21e6, 0x82b13093, 0x45daeaf2, 0x2bdceed1, - 0xa1c27de1, 0x01727b45, 0x031eb95f, 0x18e3a19e, 0x7808bcf0, 0xbabd20c6, - 0xabf04bc5, 0xa0f5487d, 0x4be6bece, 0x98df80d1, 0xae47453d, 0x61b5f7c1, - 0xecda8c22, 0xcefe9c3b, 0x8b8f34ad, 0x3d4155ab, 0x193dd28a, 0xdbc68289, - 0x2e7cf96e, 0x4dbf73e0, 0xd2917acc, 0x47a7b7d2, 0x46fd285b, 0x21f51fa7, - 0x6a352709, 0xae7cf47a, 0x98b93edf, 0x9edcc7f2, 0x7aa082c4, 0x2ce9d63f, - 0x6b655f14, 0x718d16ff, 0x78d8d62a, 0x2e5e065d, 0xbf341d62, 0xfe118d8b, - 0x8b9704e5, 0x5fb8dbbd, 0xbf464f03, 0x4183c015, 0xa56f544f, 0xe38fa5db, - 0x114717b3, 0xe1b4d35c, 0x64e82e9e, 0x2e3483c1, 0xe51f5bfa, 0xff7de675, - 0x74780d71, 0x25969be0, 0x8f03fc0c, 0xbc6da44f, 0xde59be97, 0x93d10ab3, - 0x7d78d0e0, 0xcbdf42aa, 0x850984f6, 0xda532bfa, 0x9c09288e, 0xac14fb77, - 0x8c3cf17f, 0x9871f657, 0xf7c7e505, 0xf3c79f5e, 0xc12bc10a, 0x7a2bb529, - 0x96d698bf, 0xdf8209ea, 0x736d3ec5, 0x7d06be79, 0xe79bce74, 0x4c37bb51, - 0x4c5c5f60, 0x76467c23, 0xf801b1c2, 0x5df5c619, 0x6f6fa676, 0xb1d7e01e, - 0x7ac8575e, 0xfdeb215d, 0x0b7d3040, 0x29ebc68f, 0x82cc24ff, 0xdc0fe5ef, - 0x71a6e594, 0x8e3bdf8e, 0xce3c75d7, 0x75fd879b, 0xcffa953c, 0xe59d72bd, - 0x733ad00f, 0x8d9d65bf, 0xb757c64e, 0x7b6b8ceb, 0x3acb7c42, 0x6874ea37, - 0xab33f3ac, 0xfa8ada3b, 0x9cb155bb, 0x14fb6a8a, 0xcc8d7fdf, 0xd0d056bb, - 0x0f4936b5, 0xfc236bb5, 0x6685d7c0, 0x6e7f04db, 0xf1a01f27, 0x583d27be, - 0x8f8e1e98, 0x023c3f75, 0xea9f75f4, 0x9701b9f2, 0x9cfcef21, 0x57efc7f2, - 0xb1f9025d, 0x0fc47e12, 0xc70fe02c, 0x73278b53, 0xb5cdaf7e, 0xb4f9fa82, - 0x047f6ff1, 0x63dc5cfd, 0x5f5e0b73, 0x90b3fdf1, 0xaf82f9a7, 0xc66e5c11, - 0xebce54b8, 0xd619ef57, 0xe8f17288, 0xbba65760, 0x0214be0b, 0xaa358ae7, - 0x01d21f69, 0x3ed5e3c1, 0x3ac6e290, 0x8713380c, 0xa83a9acd, 0x4fc81e13, - 0x9709d41f, 0x9ad0bb5a, 0xfb12fbf8, 0xfc414194, 0x9749f00c, 0x3cff44e7, - 0xa2d2c7c9, 0xc873f683, 0x8ff942fc, 0xff48cf51, 0xcc57c1d2, 0x705178fc, - 0x1950e09e, 0xc21c5f92, 0xca42aa37, 0xb7ca43ab, 0xf99cfaf7, 0x13f8e840, - 0x31bee4d3, 0xc3aa58e0, 0x9145bb71, 0xc53ee47c, 0x2d7e89bf, 0x4bedbab5, - 0x8e2ffe69, 0x4fd0f311, 0xae385599, 0xced97de5, 0x8ab52beb, 0x7c02b086, - 0x633d70f7, 0x435fd4dd, 0xc3e51c58, 0x7aa21f25, 0x7941ec13, 0xf31adf83, - 0xf0934f09, 0x5bc5d230, 0x83c78d9d, 0x14dd59e0, 0xeed7ca6b, 0xee3c6e4a, - 0xc62fcce8, 0x6ff4c92f, 0x387ead22, 0xaa7f22e0, 0x8c1eb577, 0xb249fa20, - 0xd469e168, 0xff83c5ef, 0x66eb9d1b, 0x262f0fbc, 0xe9a816fc, 0xf5a61d2f, - 0x3d56edb6, 0x9befd09b, 0x5f11fcf2, 0x1b787a5f, 0x9bd9af7d, 0x7775ee21, - 0x8e143fae, 0x8a5d7717, 0x17efa74e, 0x05c3d90e, 0xcda501c9, 0xd1ed63f1, - 0x84babfbc, 0xbb875bbb, 0x6b05dfd1, 0xa094f46b, 0x6b44177a, 0x7a20d4f4, - 0xa975dd29, 0xfc31e44e, 0x1f106a7c, 0x8f4f74ff, 0x2f7d2ab1, 0xb1af7dfb, - 0xe9c74a16, 0x736fdefd, 0xe686b93f, 0xe61ddbed, 0xbef34cd9, 0x0b2ce6f0, - 0xb3785fda, 0xea7f4f42, 0x4fb3f4e5, 0xb47e3153, 0x31bbd245, 0x293488de, - 0x8e59954f, 0xfc1a313e, 0x699ed5ff, 0xe59d69f5, 0x2c829665, 0xad9b79e0, - 0x7de62e6d, 0x95ab1141, 0xc67eceb8, 0xfdb9b9a5, 0x9f27dd85, 0xf4f87f00, - 0x60053efe, 0x6776172b, 0x7e5469e7, 0x5921e3e1, 0xc2f7ea2e, 0xf01ec97d, - 0xf7366d85, 0xeede994f, 0xdf60f289, 0x9c61fd1b, 0xf77fe825, 0xa435c355, - 0x52f9cb1f, 0xe3934f3e, 0xce8294fa, 0xee2da37e, 0xbf028f5f, 0xb3cdbdf8, - 0x7fa59299, 0x8b19e8cf, 0x773f61f5, 0xd5b28781, 0xe26dc261, 0xde782b27, - 0x8763c2a5, 0x1172841c, 0xa2e55f44, 0x6fcfbf98, 0x405f7f34, 0x17df027c, - 0xaf7f37ae, 0x5aab8d10, 0xfc8b7d69, 0xf682efe6, 0xfb112f8f, 0xe269f8da, - 0xd6f17ef3, 0xf54cc26f, 0x0fe74f84, 0xa5c7e60e, 0xc7c11fb4, 0xfefc579e, - 0x3defc015, 0x7433af2a, 0xd2d3cb5d, 0x448f1d78, 0x6b6e63fc, 0x598f5e10, - 0xe0893584, 0x1c2ecc7a, 0x47e80549, 0xbeab9c08, 0xcdfe613d, 0xfedee4d4, - 0x3296a55f, 0xe0b24bdf, 0x05c3b83c, 0xedfd47ce, 0x7e8a9939, 0x791756ca, - 0x77e6835b, 0xe47de6d1, 0xdf5790e7, 0xf54d7e23, 0x37f58d8e, 0x1d79a58e, - 0xd4f557bb, 0x33af3177, 0xe3f99f24, 0x28f71e09, 0xf2843fc2, 0x2d4c9ccf, - 0xde9cbc21, 0x34b5327c, 0x3115fe98, 0x8d1e982b, 0xebc26694, 0xf489ac82, - 0xeb05ad18, 0x89d7ad09, 0x0d7cf35f, 0xb1553a78, 0x787a2ba4, 0xe54f7414, - 0x05577f39, 0x3d9acee4, 0x33e83f36, 0x0f17e362, 0x6cfa0adf, 0xda40b9b6, - 0x2f547bb5, 0x5bb174e4, 0x1ce267f5, 0xba34fe6b, 0xeecce712, 0x68352e21, - 0x170e74dd, 0xb0b97ce3, 0x596252eb, 0x1933f72e, 0x9eed44f2, 0xdfa03c87, - 0x5cf1e6ee, 0xf1affa9a, 0xff99af3f, 0x20fdcf9d, 0x81f046f1, 0xc0b2278d, - 0x3e0f89df, 0x99fd8697, 0x791db5f5, 0x83875a21, 0x2c7e68fe, 0x7ff45fbf, - 0xa3a5f2c5, 0xbbfaf559, 0x349ec3c0, 0x07ffc33b, 0xcd026fcf, 0x7e73b12f, - 0xe03d9f34, 0x6b3cc6cb, 0x9c766ddc, 0xd11d17b3, 0xb4a7e079, 0x89f989a0, - 0x06e4f9fa, 0x289b2d7f, 0xee16bf88, 0x09c2bf9e, 0xf151a179, 0x6f280f40, - 0x2adcf956, 0xddfaa0df, 0xecc29784, 0x213bf6bb, 0xe5443e9f, 0x3abc74d4, - 0xa8b38fea, 0x54fbc2fe, 0xf8dbefce, 0x80da3fd3, 0x11360dd7, 0x47863c06, - 0x63c7d26f, 0x3e916879, 0x37cd45bf, 0xb7a0569d, 0x013d51ec, 0xe51cdfb4, - 0xd5b2f7c1, 0xf4c163b6, 0x50bf1f35, 0x2bd7f37f, 0xf81a40fe, 0xc2fcb984, - 0x27ce9f30, 0x5c6fbe42, 0x027f7535, 0x89eb2b52, 0x72e6fc8b, 0xf34ebcfc, - 0xdf7fd5a9, 0x17a6b99a, 0x29c173f0, 0xabf60b44, 0x1df595b5, 0x054d6811, - 0xfeec2f1e, 0xac78152c, 0xb27ff57d, 0xebf81744, 0x51cd4fd8, 0x84222709, - 0xc6e74b38, 0xfdd01637, 0x5dc5c9a5, 0x8fb17fd4, 0x6d5b17dc, 0x63905ebe, - 0x8afc6ff7, 0xddc5c1f9, 0x17575f5a, 0x5fb9dbf4, 0x124b4e7d, 0x205380d2, - 0xbae4da1d, 0xe484fb11, 0x1f417bc1, 0xdd4d569b, 0x6be77944, 0xa2424836, - 0xf7923336, 0xfcc7f60b, 0x7d8d7ea0, 0x017c15b2, 0x1fc930e9, 0xe523ec5e, - 0xbcbad584, 0xfb5f75b0, 0xe62ecce4, 0x26cd3ab3, 0x923edbcf, 0x2b4dcc6f, - 0x9c874f0e, 0x0345f161, 0x75ebc21f, 0x157c1027, 0x97eabe9d, 0x3df0512d, - 0xda723449, 0xfa71345b, 0x245a10b8, 0x0b8f0bea, 0x4fa21670, 0x7bc7e02c, - 0x31abd79e, 0x8e89fcdf, 0xd06af03b, 0xf8562f83, 0xeaefd337, 0x63508746, - 0x46b5ed20, 0xa0d451a3, 0x4beebfa9, 0x540fb6e5, 0x3ed49fd6, 0x2e3d3e06, - 0xc8cbf7e0, 0xf8c131e9, 0x74b877db, 0xdeabfa02, 0xf52e7a49, 0x4d877e77, - 0x5957a004, 0x3d50bf69, 0xec2fe1db, 0xcd4be069, 0x5cbc808a, 0xaf7c794b, - 0xfaf5651d, 0x9792e083, 0x9a91e12e, 0xbb70c59e, 0x9a1ef560, 0x9573fa08, - 0xdbd721da, 0xc04f970e, 0x2a4b6379, 0xfb5e63b5, 0xa4758f0e, 0x56b16f01, - 0x9aab37de, 0x5c5b718d, 0xf62a3fe8, 0x436f9e03, 0x534445ae, 0xc28f86bb, - 0x874c0cfc, 0x3a6143e4, 0x85021b5c, 0xf817770e, 0x14c289f1, 0x77ca8231, - 0xcf3013a8, 0x1752aef3, 0x958b68f0, 0x9b308776, 0x9af40277, 0x78b8d8b0, - 0x7a446fcc, 0xabffcf06, 0xcf3c25d8, 0x80bc48af, 0x7af241be, 0xbd0df231, - 0x7d8655cb, 0x8fbc23e3, 0xfc721d6b, 0x9f2a3da8, 0x43a462a3, 0xbbefdbe7, - 0xc89c68ca, 0xd024dabe, 0xa89f3183, 0xf00baf61, 0x858b1ce7, 0x3786b3e5, - 0x2f80d722, 0xd21be518, 0xf819bd25, 0x75609958, 0xae3c7f81, 0x574ae7d3, - 0x6820a3b1, 0x161eb69d, 0x0ec55e1d, 0xbdbb69c0, 0x97ce10f8, 0x738efa36, - 0x54d27f73, 0xaa14f407, 0x273f4167, 0x64c768ea, 0x0ee9dfa3, 0x424177c0, - 0x5bb478e9, 0xc2ac9628, 0x5eb85b7e, 0x3e208115, 0xe39360db, 0x211cb82e, - 0xc73a4302, 0xe3f8405d, 0xf9a397f6, 0xd653837b, 0xfb92886b, 0x2974cee7, - 0xd3d4ae2f, 0x83fa7ab5, 0xccc7baf9, 0xfec7cfd7, 0xe4a94b71, 0x53a677ef, - 0xeb4ad5bf, 0xab268878, 0x80edda92, 0x973a89ef, 0xcd058408, 0xc6758af7, - 0x38d0408b, 0x3b2ef51d, 0x183e2045, 0x47c66e1f, 0xb9237ae7, 0x125d44fc, - 0xfefbb1c3, 0xec704c53, 0x04c33fec, 0xcffb2bc7, 0x7513f2e2, 0xffd1df39, - 0x4ffa6ec0, 0xb3bfcd33, 0x5dfc7edf, 0x82fad2ec, 0x22eddcbf, 0xd374c07e, - 0xbb2676ca, 0x7606fda2, 0x9871f12f, 0x95f7dc80, 0x0576cb53, 0xe96d87f1, - 0x0b9f5d76, 0xfadf80a4, 0x6b4e3ac4, 0x8f1a5d77, 0x0be26ef6, 0xcbd0e76c, - 0xcf1b456b, 0xfa02fc13, 0xbab648bd, 0x96977cb9, 0x98c8bd0d, 0xf33c8747, - 0x859f48bb, 0x9ed841f6, 0x1f6347bf, 0x4db6b45f, 0xa9aa7d86, 0xde088d59, - 0xfdf407d7, 0x17cfb631, 0xd5d7b079, 0xbdf11da0, 0x9c5dee9f, 0x84d4f80d, - 0xde61e5b5, 0x2dfef7fb, 0x57c8e70f, 0xc5f7167b, 0x9f54adf7, 0x5b7b0fe5, - 0xbfa8278d, 0xb3e5c27e, 0x9b4ce88c, 0xfa1ffdf5, 0xfa9eeb7d, 0x36c7985e, - 0x2e483dd8, 0x56f659ac, 0xb078f1c6, 0xe083ef21, 0x16f8825f, 0xa6bb43eb, - 0xdf2063a9, 0x0f32487d, 0x96ee87e5, 0x3ed0c372, 0x83496fc2, 0x2ce1f7dc, - 0x619a89f0, 0xe1541776, 0x9616fcf0, 0x3987c3b7, 0x9f9f385c, 0xebc193ed, - 0xc84e43b3, 0x78a2fb40, 0xf154e7a6, 0x1b6dc9af, 0xe04ff642, 0x68db350f, - 0x75b56abc, 0xf78538f2, 0xa9f031d1, 0x78bfb79a, 0x135fd747, 0x8c5a9f81, - 0x5f78f04b, 0x432127ef, 0x9a7a893b, 0xabbef5a3, 0x9b8cdea8, 0x1fa15393, - 0x99fae895, 0x19404898, 0x1068fcc9, 0x9e5720ec, 0x7a0f52db, 0xc034d14d, - 0xf0ec97c1, 0x981afce0, 0x71c91c22, 0xf4fed0d8, 0x57ee34a9, 0x2ec316e9, - 0x03de60aa, 0xdf3d35f4, 0x2c6969ab, 0x38fe939f, 0x3b3fd1d0, 0xfbc325ae, - 0xa30bf077, 0xdf3787fe, 0xe2eb483a, 0x79e430dc, 0x36e9bdbb, 0x3aadb3cc, - 0x9847f592, 0xc9eed0f3, 0x2a02c39b, 0xc8b68aec, 0x3fe7d0d5, 0xb07b988a, - 0xfee3c107, 0x83222d28, 0x799acdda, 0x95e42ac3, 0xa5eef1fd, 0xd692e7a0, - 0xd3e7c0e1, 0x83262d4e, 0x6872afc6, 0x8969137d, 0xd968fbe7, 0x8be43831, - 0x449e25e3, 0x2ee2a0f1, 0x53e72fe7, 0x0ff1c8a2, 0xe8496947, 0xf2d2c4a7, - 0x66f855c4, 0x837b616d, 0xfdc1e868, 0x8a8bb79c, 0x037fe4ae, 0x75f4470e, - 0x6b89b3ec, 0xf6fad32f, 0xd4f18dad, 0xefcb7cd3, 0x96b7399e, 0xe296f9d2, - 0x9a6a80c4, 0x55d61677, 0x9be92be5, 0x79f3f24c, 0x65ef3e9b, 0xaeadbcfa, - 0x1cfde0ac, 0x437aef3a, 0xc285f95e, 0x50ff20fa, 0xac5f15fe, 0x87ca5eff, - 0x307d2e59, 0x20d6e70d, 0x3649db0b, 0x22ded384, 0x7d5df23d, 0xbed38f9e, - 0xf7f1c473, 0x149ef8d5, 0x3d27db2e, 0x7ec3f16c, 0x37763c50, 0x9ac9e9e3, - 0x634a8f48, 0x1db70895, 0xf0995072, 0xd9fc5cb2, 0x69edbf98, 0x661575a5, - 0x6e01d768, 0xa92de2f3, 0xb43cf01f, 0x6f205381, 0xf8eb928d, 0xd7937916, - 0x6cb85531, 0x3589942c, 0x531fc816, 0xf329725d, 0xa63fb915, 0xe30daf09, - 0xd71a10cd, 0xbb05c3fb, 0x1fc4fa17, 0xbcd10ba0, 0x7f1f0a67, 0x9cfc2d9f, - 0x5c022ade, 0x95a2c7ff, 0x89bc06f3, 0x4825e63e, 0x53d938fa, 0x8cdff865, - 0x9117bf79, 0xad1967d7, 0xd923ca63, 0xad5fac99, 0xf9f0c1eb, 0xd14f79ae, - 0xeff686e9, 0xfd83f43c, 0x99fa9d3b, 0xfec8637a, 0xe061ec2d, 0xf6dbf333, - 0x877b4b51, 0x4c9914fe, 0x475eb870, 0xc5def5e9, 0xa9153fac, 0xf847c291, - 0xfaa51969, 0xf21c7721, 0xa0484f2e, 0xb9fddc75, 0xb77e83d4, 0x843dbc5c, - 0x46377fca, 0xd2dcf515, 0x64d4f2cb, 0xbdc99fbd, 0x9d869fc7, 0x2408b0f5, - 0x17b9a50c, 0x8f5ed65d, 0x564ef9a1, 0x52c435b7, 0xa4de84f9, 0xbdf104c7, - 0x5bb6121b, 0xd8ddd7a1, 0x627dfccf, 0x99df59ae, 0xc0551a24, 0x7350f279, - 0x0f807dbd, 0x0c8ad7d1, 0x0188b7a9, 0xdfee8062, 0x47fbb963, 0x13ed1f7a, - 0x0be1d92f, 0xbb433579, 0x3a5c7007, 0x18b9b3e9, 0x7ae55857, 0xd951de6a, - 0xe48c779e, 0xdf9d2f2c, 0x84e8ebc7, 0x08f29308, 0x6e48a7f2, 0xcea67a40, - 0x3a39e9cd, 0xa17e51e7, 0x67eb23ce, 0x7d803f14, 0x73faba56, 0xb772f02b, - 0x6ef9c253, 0x761faa67, 0xc6a68ab5, 0xe55e98f1, 0x4883a6ae, 0xe3c503cb, - 0x382ecc71, 0xd220e4b4, 0xb6f43bbb, 0x5fdd0e25, 0x5dbff3c0, 0xa3dbd3a7, - 0x8834dea6, 0xbbedc9f6, 0xf6ebdfa5, 0x4da7533e, 0xc6de404a, 0xa8e8eef9, - 0x3422b2fa, 0xa8cf22da, 0xb758cdde, 0xc1e8f9b7, 0xc9e75a78, 0xff3c11ba, - 0x9e5e75d3, 0x09bad9ff, 0xa33dfe9c, 0x27ae39f8, 0x6c79673e, 0xd6a3b6d2, - 0xe45faa14, 0xb7d8bc55, 0xdf857ad7, 0xdeb1744f, 0xf581cf26, 0x1f600e74, - 0xf534198f, 0xe9303bf1, 0xda276d0c, 0x5171b8cf, 0x3c99c611, 0x7a8ac4a2, - 0x2216bf33, 0x4e93ad3e, 0x8dee8bbf, 0xf8eb57f5, 0x6157bf3b, 0x1bdf9e78, - 0xdf6cf0cb, 0xf9031191, 0x8ccee960, 0x6f89489e, 0x046f7a1a, 0xd97ed7e0, - 0xff6df3c2, 0x8ef59c28, 0x774bf6d0, 0x7a89ec0e, 0x22df0967, 0xfb3cde48, - 0x83b87ffc, 0x71b395cf, 0x027d5f4d, 0xc957f6fe, 0x39b248df, 0x5ff818f1, - 0xd01e5eef, 0xce5d05cb, 0x02233d26, 0x6e8d5fe7, 0x427f0457, 0xb4b86cfe, - 0x217f0ee7, 0x17f62c65, 0x9c1373c6, 0xb9191cc3, 0x7f7087c7, 0xfd467e47, - 0x9258fcbd, 0xb9effa07, 0x63a48fed, 0xf34dadfc, 0xfa8c793f, 0xf8b7ef3f, - 0x9d4e746c, 0x5e174d17, 0x2a7e1f05, 0x777bed92, 0x9c2f342b, 0x717b9bc3, - 0x86b1473e, 0x2c39c32f, 0x73cfbcfc, 0x1975b714, 0x17aaadf1, 0x7a05ed1f, - 0x30608d7c, 0x5b5fca82, 0xed7cc11b, 0xc8e79b35, 0xb8f7f432, 0xfbe9efec, - 0x0bb63cef, 0x05d57de9, 0x65fa5277, 0xa1e31c46, 0x034581fc, 0x79ce9ed0, - 0x3dfd4c91, 0x80128af7, 0xbad06abf, 0x69922b7d, 0x1c37837e, 0x34a2f4b5, - 0x1ea529ff, 0x373ec0e9, 0xf9fd821e, 0x6e6e196f, 0x9a5b643f, 0xd96d829a, - 0x75c9ffcb, 0xe59bfe7c, 0x9f75dc82, 0x3a25ed8f, 0x4a0183e5, 0x348d99d3, - 0x8fd4b0d7, 0x6386340a, 0x6767af23, 0x6ff7b4f3, 0x49075815, 0x8977981e, - 0x91e7c3dd, 0x7811b7df, 0x78e5af3e, 0xf62bbf58, 0x3b7a0a3d, 0x707a25af, - 0xfa4cbd3e, 0x7fa8d5fc, 0x7cebcac4, 0xa2f7a9e5, 0x2189df61, 0xbf09d93d, - 0x78db7e48, 0xe3eeafd4, 0xf587f016, 0x09fae279, 0x8ecd4f80, 0x9fb91b9d, - 0xfa07872a, 0x4bcec56e, 0x2f205307, 0x993c20de, 0x321dc7a0, 0xaf42abff, - 0x56a5a547, 0xe652fc6c, 0x5f398a5b, 0xfc27da4c, 0xca4ca2fe, 0xe7e88f49, - 0x63cd68a0, 0xee24c97e, 0xafd7c4ee, 0xebe518a8, 0xb0c97cd3, 0x27e71b6f, - 0xfda97b9d, 0xb2ec65b0, 0x5bd8cb7d, 0xdf2e1953, 0xebb3dcf3, 0xdfd197e7, - 0x73e17623, 0xdf303f52, 0xc1be9ec0, 0xcdebcf2e, 0x2f4067c4, 0xe34d79c6, - 0xed93f5e6, 0x29afe0bd, 0x076832aa, 0x91e523c1, 0xbe379630, 0x62b3f8ef, - 0x6df9f156, 0xe1b55bc8, 0xd9f22f92, 0x885fed41, 0x37eeaed2, 0x7932760c, - 0x3bab0bde, 0xe3c8f217, 0xfa6bde51, 0x96d5bcb1, 0x39d0358a, 0x53e61d7a, - 0x95fc92a3, 0x457f2411, 0x73af7dc6, 0x2de51034, 0x5beffb42, 0xcd046c7f, - 0xf1290633, 0x86a468ef, 0x485a45de, 0x7d39fc97, 0xf3f8135b, 0x3f926143, - 0xbe610d47, 0x7433ac64, 0x07c4039c, 0x6f3be234, 0x11a339d0, 0x3917183f, - 0x7d78cac6, 0x907552dd, 0x3922e5ce, 0x1ada0802, 0xdef3943b, 0x61638228, - 0x2eb42aa4, 0x252347f4, 0x3ac7cdbc, 0x984427c7, 0xc42515ea, 0xbf8fb1da, - 0x1d55faef, 0x3cb86a4f, 0x8370d4bf, 0x7413babf, 0xfac87dbf, 0x776f7ae5, - 0x3abe630e, 0xeb7ef956, 0xdf15b22e, 0x8b8f3c09, 0x7373e7cc, 0x2394e45c, - 0xd475e09a, 0x7ae87be1, 0x1c25d743, 0xfa8e4fdf, 0x167c2289, 0xedcfc7ec, - 0xb66b776c, 0x5bf73eb5, 0xa2f36b82, 0x47ec0f5c, 0x70bed32f, 0xb54e9f80, - 0x0cdb9cb3, 0x37ea92d9, 0x5c7170f7, 0xdfba6bcb, 0x6f5b37dc, 0xbe7c14ef, - 0xc5eecf34, 0x615ef47e, 0x48ec1034, 0xd26fd2f5, 0x16f25b6c, 0xe5e6ebce, - 0x819a1e29, 0x69efc150, 0x97e47ccb, 0x095ebcfc, 0x817f0adc, 0x40bb73ef, - 0xfeb175fd, 0x5f94e9d5, 0x9e0c8bf7, 0x8fa447cf, 0x8abc62d7, 0xeb5be670, - 0x71c9bd62, 0xff979f04, 0xb279f2a1, 0x91f29f2e, 0x6ed9d7cc, 0x378a6eb3, - 0x04ad7e19, 0x36eb6f1d, 0xb05ef2ca, 0x4d3ca293, 0x26c4ffb6, 0xd7a2dfeb, - 0xfbf1d04b, 0xb4a74eb1, 0x683f99ff, 0xa0ac2393, 0x95fb77ff, 0x46fbc6be, - 0x17e19378, 0x933cac7a, 0x54b7986d, 0xf4c690de, 0x66d3dba4, 0xe8dcfce9, - 0xc31c0d17, 0x9fcb4f21, 0x3b37f3d9, 0x2a33df41, 0x1f21479c, 0x22b1547e, - 0x0cfd7a0a, 0x21840d4d, 0x917a6abe, 0x4bae43b7, 0x395eb8c7, 0x1fa1b96e, - 0xdf00ca06, 0x710e6dbd, 0x81ffcb2f, 0x96fac121, 0xfa45e781, 0x1a6eadbe, - 0x7eb060f3, 0xfe27695d, 0x72e51833, 0x6a45573f, 0xd57d07bf, 0xc1e1baee, - 0x54fbbd60, 0xbc7943f9, 0xcf71f4ef, 0x3c1f79d5, 0x6f39099e, 0xb8c6a702, - 0xf011fa1d, 0xd5f6fd49, 0xefda73cf, 0xdaf00b3e, 0x92fa94e4, 0x85e3edb5, - 0x359faf94, 0x09f7cf80, 0xd85e1d53, 0x8477daf5, 0xadaf61f9, 0xc5ee159f, - 0x44f7eaba, 0x985761f9, 0xd21befa7, 0x6fbbf8bb, 0xade98dbb, 0x667feeca, - 0xdaabb50b, 0x89e99fdb, 0x96ed95e8, 0x642357be, 0x6d37b479, 0xf79450e5, - 0xcd79fa64, 0xf2e18ee6, 0xe5c15537, 0x58ac81e1, 0x539b7782, 0x1375853b, - 0xbcfdb2bd, 0x1fbf2eca, 0xfa12e9d1, 0x96fffb25, 0x42bf7144, 0x8f3f6bcf, - 0x584f7d67, 0x91f3c9bd, 0xaf207dbf, 0x7dcbb347, 0x7ea46a21, 0xe725c478, - 0x9e39a475, 0x8f4185f7, 0xdcb78a47, 0xef809593, 0xfcd2af24, 0x0d4cb2fe, - 0xd06e1fc0, 0xf2f5329f, 0xbb5157db, 0xd9555f4f, 0xd7e7336f, 0xfbe30f8b, - 0x13d5159c, 0x6bbcad39, 0xf5cb9f32, 0xa2eea71f, 0xa7a984f2, 0xe06bbfd8, - 0xd9954e7f, 0xe9989a9f, 0xdf813355, 0x83f6ff5c, 0xd9e1ff54, 0xaf001627, - 0x473533c3, 0xf6dbec26, 0x4cff97d6, 0xfe5d6df3, 0x36a3d627, 0xf8116b44, - 0xd3f7717e, 0xc566bf5c, 0x7e802cff, 0x74956350, 0xb5db9c63, 0x91bf3d3a, - 0xffa2c5a9, 0x63bf15aa, 0xb722223d, 0xbbd7f245, 0x3a3f1fbe, 0x65f9bcd3, - 0x0e2dda85, 0x54e1ae6f, 0xfce1e7f5, 0xa204ab3b, 0x2b860c95, 0x5ce775eb, - 0x47e06881, 0x72b948b3, 0xbf10d6f1, 0xa8925031, 0xdda88bdb, 0x8f5526e2, - 0x41dbf457, 0x17f5a1a7, 0xf7ae77d3, 0x8a57bf3d, 0x763df926, 0x30d7fdd7, - 0xfe0045fe, 0x64cf33ae, 0x9c3d026e, 0x5674f9df, 0x34369fb0, 0x72be72bd, - 0x7df4e7fd, 0xd8be8e73, 0xc2db6f40, 0x0b85f64c, 0xf4eb24cf, 0xc2e9e926, - 0xe7ecd933, 0xd9f7d44e, 0x0967c505, 0x085fbb47, 0x9e10678e, 0x971ce1a6, - 0x0e1a6de3, 0x9d61fbb9, 0x6f8e2e2f, 0x67be0e1a, 0x68e141f0, 0x41bb63ca, - 0xf41e534e, 0x8a7f8364, 0xfe2ca6e2, 0x42ca6fee, 0xd22d97fb, 0xa7cc630e, - 0x8e14b9f2, 0xf0b5a27b, 0x6e7caefe, 0x8de426e0, 0x929dea71, 0x253bd4ef, - 0xb75d097f, 0xe8ed2996, 0x1ee64fa4, 0x3ea4b3a7, 0x5c82f496, 0xde6593e4, - 0x370bf329, 0x6fe1d894, 0xbcc9b7af, 0xfd897d6b, 0x35f7e618, 0x4fc4b569, - 0xc5bf7473, 0xdda97f02, 0xfafefb0b, 0x3f1ce1e5, 0xcf3edb31, 0x7af6694b, - 0x035c69bb, 0xe6fdfd0f, 0xf9f48bef, 0x0b890df4, 0xedb6a5ea, 0xf639c30b, - 0x8e32e8a4, 0xb4a64960, 0x6cfb3ee3, 0xaa917c47, 0x6dc2dbeb, 0xea5ba1d0, - 0x8fd78c1b, 0xef5e06ed, 0x2ff9a148, 0x5ea5e3d6, 0xfab848b6, 0xe37c959e, - 0x052d7ce5, 0xc005d5e7, 0x2c5ce71d, 0xef2173e5, 0x7919bc49, 0xf0a15f03, - 0x82f1f15d, 0x9f95d814, 0xc7f694c8, 0x8f2c7c50, 0xe513de1a, 0xd4cf5c06, - 0xdc00ca1d, 0xa89d758d, 0x68e97af3, 0xafbfb4eb, 0x8c6877cf, 0x30477c8f, - 0x1d6fd77d, 0x20248872, 0xd5ab6e71, 0x5bd42583, 0xbf43f7fd, 0x36aadfa8, - 0x3b9704f9, 0x91739780, 0xbd41dffb, 0x0b621b05, 0xed180fa0, 0xf22fae17, - 0x7bcd0796, 0x5e3356e0, 0xf3993506, 0xf3997783, 0x0d06715b, 0xe5dbe7fb, - 0x21f9cc07, 0x93f9cc87, 0x3371dc1f, 0xea854fb6, 0xbe855fbb, 0x87f1e7f3, - 0x7a9f4e70, 0xe06895f9, 0xcb5ff16b, 0x0b8f420f, 0x3c21678d, 0x7c73d02a, - 0x97a6145b, 0xba5ae22b, 0xdc4643e1, 0x30627606, 0xdf0a54dd, 0x95da6b41, - 0xa68acff5, 0x6744bd9b, 0xcfdecb55, 0xecb37a90, 0x5ad36477, 0xd0cee43b, - 0x3be3bb71, 0xc6ebd222, 0x21192a3e, 0x365eaecb, 0xfe8a7c4e, 0x1e37bcd6, - 0x2bf258f4, 0x929be585, 0x075fb297, 0x3edd1cdd, 0x6f4e46fb, 0x30f0c09e, - 0x9b0b92ec, 0xe5144095, 0x8744235d, 0x8bf11f7f, 0xf1210da5, 0xe2426b9f, - 0xcb99d682, 0xf7daee17, 0x504710ff, 0xe38278e1, 0x678cae2e, 0x5e801ff4, - 0xb04a7959, 0xa9f2aa7d, 0xe5ccc26f, 0xf5f35d72, 0xade71875, 0xf1cb5df0, - 0xaacb577b, 0xa3fe38e2, 0x4ba8e973, 0xcb73853b, 0x5eaf7738, 0xf29551b7, - 0xfd84b7bc, 0x8e7691c8, 0x8876ac8b, 0xebcd0440, 0xebdd9450, 0xd697efa2, - 0xb2bcb147, 0xe85ce480, 0x270a948b, 0x627a4dc7, 0xbbc4eed0, 0xd565cb2a, - 0xd51e12f1, 0xb0fc51bf, 0xa8c3571d, 0x3293fc8b, 0xd80448bf, 0xf23a0bbe, - 0xf803ad06, 0x468bce0b, 0x59565fa9, 0x9f00fb03, 0xab68738e, 0xad155eb9, - 0xc838a3f3, 0x35efe67b, 0xd7eb8da2, 0x2c26faee, 0x3d907bf8, 0x435ef59a, - 0xf97556ff, 0x3865fd4a, 0x20744fcb, 0x6cbe8384, 0xeebedcba, 0x6823921e, - 0x7b0d2b7d, 0xdf295af8, 0x9e51b2dd, 0x679f2463, 0xd6eb4e01, 0xef867c92, - 0xce206fa4, 0xf70a2c44, 0xea5ef94b, 0x6766eb0b, 0xf2f45cb1, 0x400a5e3f, - 0x487b691f, 0xbad2bb61, 0xbaefd97c, 0x3973fafb, 0xe3c2a7f8, 0xb61cb184, - 0xde518a6e, 0x4f91f587, 0xc864c530, 0x1ef7faf9, 0x4bdefe6e, 0x3ec166f5, - 0xb2741e22, 0xfb90c47d, 0x2ebeb90d, 0x1ac9cb56, 0x75feb9d6, 0xf0516db1, - 0xf88a89bb, 0x6cb725ef, 0x36e3cfd6, 0x2afc3f5a, 0x83e295c7, 0xf5198ff0, - 0x73c96646, 0xef58f865, 0xfb1ebd16, 0x532dca5f, 0xe68ebdee, 0xc5b0fe55, - 0x81a17b0d, 0x66f5e107, 0xd7c70e01, 0x77400b3a, 0x7b4ac7c3, 0xc97c91d9, - 0x0a8623e7, 0xab1a378e, 0xcb363bf7, 0xc2934a62, 0x9fa91e89, 0x1ed245e3, - 0x98b4351f, 0x132496ed, 0x6e2aebcc, 0x4fdeb265, 0xf7f8bdb9, 0x4f98bba3, - 0x4a145d07, 0x6df8fbf9, 0x2f3926ca, 0x0e27c72f, 0xf6c9c07f, 0x39fae3ce, - 0xe881e064, 0x0fcb1868, 0x0d8b5f3a, 0xa0b59ba1, 0xa0879c07, 0x6e982507, - 0x8b7174cc, 0xee2be122, 0xbaf7f293, 0xe8379958, 0xf13ff482, 0x229ba0bf, - 0x4eeff0c1, 0xdbd6340f, 0x74481e9d, 0xd07408b0, 0x0e842f51, 0xec3fd584, - 0xa542fcdb, 0x2b876223, 0xab148284, 0x17ce21f0, 0xebc32467, 0xb11fab1e, - 0x12adbd78, 0x92ac7d2f, 0xf1b4e8ee, 0x7d701785, 0x4b7de22f, 0xbc285c1e, - 0x4524bf54, 0x1fad7db0, 0x713155c9, 0x45204edc, 0xbb0a8e58, 0x5f68a513, - 0x2ffb2312, 0xfe3829e9, 0x5af3fa8e, 0x36e674e2, 0xc15efe1c, 0x47da0572, - 0x9f7b7017, 0x5af7b645, 0x219bed29, 0x95b698f5, 0x5cbf1c61, 0x2c9f7772, - 0xb1c4c9d0, 0xa2393a66, 0xde9195d3, 0x8dd6ed94, 0xf0249e75, 0xfe86d283, - 0x3bd4de7c, 0x0277ab8b, 0xb047cf9f, 0xeab259fc, 0x618693c7, 0x7bc42f7e, - 0x9333c280, 0xa83fb3b7, 0x4ff661b4, 0xb4be843e, 0x2bdfc9d5, 0x59f5b5b2, - 0xf715ff90, 0xa1f49ddc, 0x7b01c674, 0x9ad7b512, 0x957f9ca6, 0xedbec9d2, - 0x989e40ef, 0xfae55d3c, 0x3fb48593, 0xce39068b, 0xd6e7df24, 0xd26fea24, - 0x69c38528, 0xa95d3a8e, 0xa40fc1b7, 0x2ca9f7e3, 0xe47f9745, 0x5592813d, - 0x73d2b27d, 0xc9213fe1, 0xfd390bb8, 0x18fea353, 0xa5e40365, 0xfee4e3be, - 0x1fa3ea33, 0x4b3a7bf4, 0xd5bf55ca, 0x09e462e1, 0x7cbf5cae, 0x8cd1d875, - 0x40b6a468, 0xfde9a536, 0x7584bec7, 0xe3174c4e, 0x77ee03d7, 0xcf1362aa, - 0xf984adb7, 0x1b965442, 0x4291abf4, 0xd6e3facd, 0x8f27ccfe, 0x7a3b698e, - 0x6e8fe537, 0x8ced241e, 0xbe617dba, 0x707cb04b, 0x77e48c74, 0x98239b6d, - 0x5ab88ffe, 0x3da4e2a3, 0x650ded8e, 0xb67c493a, 0xf87efeac, 0xed22cbb9, - 0xcc7e7147, 0xc71a687f, 0x53ad9427, 0x07b86103, 0x6f6cc6b0, 0xded48aa8, - 0xb5087ec6, 0x07da841b, 0xa3a03340, 0xd30a35f2, 0x8f7adf61, 0x9cf9993d, - 0xcafac2e2, 0x70fd0323, 0x9c7b940e, 0x857cc71c, 0x826be0fd, 0xb9d870fb, - 0xb5890705, 0x009f6b67, 0x258d254e, 0xe446efac, 0xfabfcc6a, 0xec1704aa, - 0x26fe9d17, 0xbe0b5ec2, 0xc64d6d64, 0x9655fcbe, 0x3130f19b, 0xc91595ce, - 0xfbe4ed74, 0xae6d4711, 0xe8efcc2c, 0xe705a74a, 0x9215c4ed, 0x39df69be, - 0x1ee18f70, 0x3f0708ab, 0xfb259ad8, 0x5adcb39d, 0xbdf291bc, 0x151ac21d, - 0x67cafa07, 0x5fd85efa, 0x75e62dfb, 0x046217ea, 0x35b289e4, 0x74bce56b, - 0x96d610fa, 0xe71a78c2, 0x02b4e6d4, 0xe43a01d8, 0xdb63fedb, 0xba0ec701, - 0x3d30ae98, 0xc10e7ad0, 0xbfde9c8e, 0xe9ca32f4, 0xcbd03efb, 0x7e81b1c4, - 0x522f1b88, 0xb6be38ab, 0xe078493d, 0x6d176c77, 0x93b48f2c, 0x67be023c, - 0x9f8319f0, 0x1d785d10, 0xdef89d89, 0x22534752, 0xceb5be1e, 0x75b3e9c1, - 0x7825612e, 0xe24bab6f, 0x6e750bfc, 0x72ea9b4e, 0x758bfbf8, 0xa8efce1e, - 0x97f9c11b, 0xdf9cbceb, 0xd3813755, 0xf98aeb57, 0x08afc1bb, 0x0c97cc3e, - 0x27f063be, 0x3e0cbe83, 0x73574a15, 0x17b8cc09, 0x1f99ed41, 0xeb107c1a, - 0xf27414b0, 0xe9cf0327, 0x092fb14a, 0xceb450fc, 0x5228ff06, 0x0aff3dcf, - 0x22bdb9c1, 0xed22ed92, 0xf6c1f242, 0x079f0748, 0x0bb176a9, 0xdbfa89f6, - 0x0eef47bc, 0xad6f873a, 0x88358450, 0xc4bc7f8e, 0x7441ac29, 0xac596f3c, - 0xd9673f29, 0xa4f46ffb, 0xd18ddffe, 0x1e69b372, 0xe2797e47, 0xf7d13ff1, - 0x4cf2fcdf, 0xf34ef026, 0xc608fcd8, 0x9f5c2bbd, 0xd79cab47, 0x9796765d, - 0x7d4b86fa, 0xd4b86fab, 0x08e3f0b7, 0xa23dcf8a, 0x2d24a3e3, 0xb1a79df6, - 0x9baeec6f, 0xb44ec047, 0xfa4bde52, 0xf2a3f804, 0x2bf8e8bf, 0x70c6165d, - 0xf7d06d2d, 0x36dc706b, 0xb258f5c1, 0xf14ef960, 0xd7bf010a, 0x03d85fb1, - 0x63882b24, 0x40afc38a, 0x6be52276, 0xab98ec0e, 0xe411f77f, 0x21d96576, - 0x4735b396, 0x087fc724, 0x705ced9f, 0x83b2ca7f, 0xf6b44f5c, 0x466fc536, - 0xc1daf50c, 0xc0e34037, 0x7ece695f, 0x1a2efd81, 0x547fbe15, 0x5f2f7fae, - 0xa2e298ad, 0xf2ab6467, 0x959645de, 0x4259f3d3, 0xf91a473f, 0x96e832bc, - 0x61c708f8, 0xdbe63796, 0xe7f10417, 0x597bfd52, 0xa714c58e, 0x9d967f79, - 0xcd8f39fb, 0x9bdefd49, 0xcf9f6e93, 0xf7cdcffc, 0xa5fa8c05, 0x60ab0539, - 0x835d2e4f, 0xf6cea6a8, 0x7d56d925, 0x7fa92e5e, 0x8b5ce839, 0x2ea2f8e2, - 0x9e4307cf, 0x475f8539, 0xef59fcf2, 0xb9e17caa, 0xac8fe017, 0x9f1873fc, - 0x75839553, 0x7fae4afb, 0x839634f8, 0x70ca91bc, 0xff12e1c8, 0x35fdcf85, - 0xb55d711a, 0x97bda43b, 0x6b48a3d2, 0xfb60aaee, 0xf6878d5e, 0xadf81c49, - 0xfaffefd9, 0xfbe67f0b, 0x14b0849d, 0xe3986e3d, 0x7c766ad4, 0xb06bf1ca, - 0x7286f9c7, 0x1d5f1c7f, 0xf956beda, 0x4257f59a, 0x68a7c32c, 0x3c8997cf, - 0x12979d8f, 0xf76ae7c1, 0x2aec4cac, 0x1fb4288e, 0xb0c1ce23, 0x358ad5ff, - 0x59cfc39f, 0x9384d77b, 0xff65de92, 0xca1eeda1, 0x31384a8e, 0xeec62050, - 0x5893b62a, 0x2c9fc705, 0xed38edd5, 0x63f64cfe, 0xd7772777, 0x2446a7ae, - 0xdd5bb592, 0xbeb38831, 0xae84c428, 0xb649f4f0, 0xd3cf6b94, 0xfb3f823e, - 0xe59536e2, 0xa2db8bca, 0x6cd43f78, 0xe220f07b, 0x529e6b04, 0x2d58edd8, - 0xafce385a, 0x1c2a8766, 0xec1de7c1, 0xcfddf147, 0x5173f173, 0x8b5f404b, - 0x66ef149a, 0xc3bb4f9a, 0x6823d31d, 0xbe80af3e, 0x87173488, 0xff470d35, - 0x079ffcc6, 0x37920b7f, 0xc83f3517, 0xef548df1, 0xbf37cb02, 0x3c38e08d, - 0xc1dec93a, 0x186ecf3c, 0x45f5fec2, 0x586bdb4d, 0xe116d83e, 0x8ce9e982, - 0xe40f7ccd, 0x81de3e80, 0x9c8f296c, 0x67d1edd5, 0x1f59505f, 0x2fb13cc2, - 0xb871e8cf, 0xf537bb46, 0x4b666f76, 0x5b26a7f9, 0xfea34fee, 0xd1a3a6a2, - 0xc9fea8fd, 0xfa73ef5d, 0x166fbebe, 0x3df0b645, 0x223b93cf, 0xc9e09ef8, - 0xfe39ff1d, 0x7cef1a35, 0x250498d3, 0xc89d9f68, 0xba7dc9b6, 0xf32fc641, - 0x13d61725, 0x673d789a, 0xac28a5b7, 0xa4de032f, 0xf1dd9fb7, 0x3643df12, - 0x1c1febe4, 0xb14b382f, 0x18a3dc86, 0x8d72083d, 0xd7bf55a3, 0x63dba6d1, - 0xaffa6ffe, 0x5927bfd1, 0xe471f58a, 0xc4610d3d, 0xbd64b86f, 0x27b73522, - 0xc1dcddf6, 0x97b899ee, 0x7192de2d, 0xfbb7a297, 0x737fe811, 0xbb678ddf, - 0xbb9b52cb, 0x1c5ff227, 0xe0958526, 0xce887733, 0x875a9257, 0x347bbec1, - 0x8615ca4d, 0xb56aad3f, 0xbf04bc22, 0x3e67445e, 0xd0aafde4, 0x49c90760, - 0x563d7c67, 0x71daf161, 0x99d9463e, 0x3bb7ea2e, 0x75bec137, 0xec7c2ec4, - 0x29d17b7f, 0xd2e927fd, 0xf618f20f, 0x7155a517, 0xd878ac81, 0xa9ba74f1, - 0x41e54a9a, 0x29b553f4, 0xea390590, 0x2bda5d9c, 0xa9fd0e51, 0xabd640aa, - 0xfd14e9d7, 0x69a3dfa0, 0xf72c0bae, 0xd0128cee, 0x44af2c3f, 0xd3c8bb49, - 0x41614dce, 0x1cbf76e7, 0xc777118b, 0x66df4afe, 0x0bcc3f39, 0x7b22fcf2, - 0x5de41663, 0xd145dc63, 0x39de3c8d, 0xe145bc7d, 0xa39fd28d, 0x3ea211c7, - 0xec136f8f, 0x267b6a77, 0x33e6e58c, 0x632f2dc9, 0xf4cf33fc, 0xa387b8e7, - 0xbb05fe69, 0xf1c9dcb8, 0x86cf95e7, 0xd3df3005, 0x5db144cf, 0xca4db4eb, - 0x12a3a763, 0x143b1e59, 0xf65cf0f5, 0xa6153d63, 0x5a742ec0, 0x9424f611, - 0xf2c1ee6f, 0x32dd6540, 0x1254d7f6, 0x4b1c817b, 0x7fc804e9, 0x67f737a7, - 0x37e9d17b, 0x415cbe55, 0xbbe357df, 0xfee71a26, 0x0880f58c, 0x799e23b6, - 0x83fd6ff6, 0x5a463bfd, 0x3ed994f9, 0x5183d066, 0xf923945e, 0xd48e5160, - 0x71c86e53, 0xd11d5a71, 0xaf3a70f4, 0xc207f253, 0xb481eb03, 0xef61131f, - 0x3bb4d23f, 0x9c048951, 0x09ff5903, 0xfa956fb8, 0x366d99d6, 0xbe5553f6, - 0x3b65e512, 0xf157ddd4, 0x554ac97d, 0x1695e3ca, 0xf950df79, 0xffb656e5, - 0x2ce33fd4, 0xde083c00, 0x6db6dfac, 0xe471f556, 0xf4b7a7b8, 0x808d7e91, - 0x10797f9e, 0xc62635fb, 0x59537989, 0x0790dace, 0x2a7a5eb8, 0x69fee382, - 0x34e22f1c, 0x73f67f2a, 0x0598cf09, 0xc1d027ac, 0x4ab9fccd, 0x77d5cfe7, - 0xfb83135f, 0x955de210, 0xb25c79ef, 0xff827a7a, 0xd1ebc286, 0xbf3f9d1c, - 0x83f338fc, 0x8837da2a, 0xfbac5b0f, 0xab3f1713, 0x78b95cb0, 0x308f35d5, - 0x26c77ddf, 0x5ce22f70, 0xc1d183d3, 0x91cfa8f8, 0xbdb3b0fc, 0xa62feb87, - 0x5bfdb2fa, 0x2d9f3cd1, 0x13e60f36, 0xddefc78a, 0x07f559fe, 0x226cafb5, - 0xcaef22f9, 0x2d125ff5, 0xf833fd3f, 0xfb2736cb, 0x7cff0951, 0xadacea3f, - 0x7fd60169, 0xf32779f6, 0x72b1b39d, 0xf3a49fdf, 0xf98d97d4, 0xb66bf4dc, - 0x9a61fccb, 0xd0b439c0, 0x98d7ee6f, 0x9b1cead7, 0x4f78b7a4, 0xd544fc0c, - 0x47f40f84, 0xb711f9f8, 0xedc6d77f, 0x40b3d743, 0x4fb1d76f, 0xba608f9f, - 0xe24bdb39, 0xd90bece5, 0x8d1d9e7c, 0xf34ef495, 0x74de854d, 0xb8a65636, - 0xa87a0499, 0x387a4974, 0xed89a63b, 0xed956702, 0xc9b51e9c, 0x74cb9576, - 0x5fd13b7f, 0xb407e812, 0x63aabb09, 0x19e40b4d, 0x05e1f9f0, 0x4f70069c, - 0x0e8ed43b, 0xd7f9c53a, 0xe333efaa, 0xebf6051d, 0x89a79fb0, 0xba6bc7ef, - 0xedb5593c, 0xf0257f4a, 0x614db554, 0x197fda7f, 0x13acd0fd, 0xd1003f0c, - 0xc29f62e5, 0x6e2c22ef, 0xfb116db8, 0xbdac96d3, 0xac6f7415, 0x6f7eb163, - 0xf2a2a8fc, 0x693a8e7c, 0x395ee4ff, 0xdfdf019e, 0xef1d28e7, 0xf38cb875, - 0x3bf0f68b, 0x47496e39, 0xfea46d94, 0x35941aaa, 0xa19a4e3c, 0x19f5cae7, - 0xd8b02270, 0xaa3be761, 0x6eeed3df, 0xbb3cc6fd, 0x9d31cf9b, 0x934d1fcf, - 0xdedb93f7, 0x2fccf796, 0x26243d7d, 0x41e45bee, 0xf46061be, 0xd063b887, - 0x22f3f520, 0x35f61cf8, 0xcf34ebec, 0xff660dac, 0xe653ce4e, 0xe66d80fc, - 0x730eee7c, 0x9cd9af3e, 0xce6ebcf7, 0x0ee309ff, 0xf41384eb, 0x4235c46f, - 0xfd0a46ff, 0xf5261ddb, 0x7fa1e46f, 0x8dfe8523, 0x91bfd0ef, 0x3c8dfe87, - 0xa1e46ff4, 0xfe85237f, 0xfeeeef8d, 0xba554e12, 0xe07814bd, 0x4eddbab8, - 0xf7813e23, 0x89d9c5cb, 0x558547cc, 0x1717a5ea, 0xd8fcb2e5, 0xe29a6f61, - 0x11937b60, 0xad18958f, 0x1c47f785, 0x2ab2d280, 0xb1db8d39, 0x55f6ba1d, - 0x2aae8769, 0xeec24670, 0xe4f2bad1, 0xa73d882a, 0xd418b4a3, 0xdb6b68bf, - 0x2f56f802, 0xff7ec03b, 0x77eee5d6, 0x63f893af, 0x5f118bfb, 0x0f738255, - 0x25f49b7c, 0x71ee7719, 0x4353db04, 0x4d6244fd, 0xd3f21e50, 0xd43e733a, - 0xe6be042f, 0x46abed35, 0x6c6fc7c6, 0xfbe0c96d, 0xe0e33e9f, 0xea9f69fb, - 0xcb313bf6, 0x2198f2c1, 0x1bce23cf, 0x9f7a5970, 0x95e709b2, 0xc31c7fa7, - 0xa650fdb9, 0x68617ee9, 0x0879765a, 0xf91df3cb, 0xe3058a35, 0xbe5f4f94, - 0xcd6af58f, 0xedd2e7cb, 0xd7b2dcfa, 0xeef34c5b, 0xd1370fef, 0x71adc0d1, - 0x5ecc7e21, 0x7783faa6, 0x31f887a5, 0xa7ca9807, 0xbe6219ad, 0x8d7c5f8f, - 0xbdafbca9, 0xa1cf6e23, 0xfce4b9fb, 0xa5ceb25c, 0x6f5e02c8, 0xc554bd68, - 0x6ff827f3, 0x4e52dbc5, 0xc673a72d, 0x2bbfaf1b, 0x9d7f0052, 0x57e03277, - 0x858b64d1, 0x3f4cad9d, 0xf332c487, 0x15615cb9, 0x275c573e, 0x84b855dd, - 0x7fda9637, 0x654c6d69, 0x47e5fa3a, 0x68812aa9, 0x3c9680d1, 0xde8bafe8, - 0xe838727c, 0x98dd5aaa, 0x3bf2a2ea, 0x5c16ff14, 0xb7133f20, 0x9524713d, - 0x495aa927, 0xaa73c27f, 0x1cff702d, 0x19edd1f0, 0x7ca4ef02, 0x68a5e6ba, - 0xe9d41f8e, 0x0ae6d52f, 0x6c6c1d07, 0x814f5954, 0xeb8d4cfd, 0x8d8d93a4, - 0x6bd0e1f1, 0x3e28c62a, 0x5c06c7c8, 0x8508fa0c, 0xefefc907, 0x97bd69ba, - 0x94f7c90e, 0x752e758c, 0x41a2fac9, 0x07de37b6, 0x5c7bd630, 0x372b47d7, - 0x3b7591be, 0x7fd73f7d, 0x7e1b9e5f, 0xbc5dbadc, 0x6d96c5ee, 0x7d29925b, - 0x85dda1c7, 0x7b7d2d75, 0x1a48f45c, 0x326dcbe7, 0x75b3fdae, 0x23e13e4f, - 0xe3777a7e, 0x0fe87693, 0x9dbf5695, 0x6679cddf, 0x0ef11da3, 0xc8dd6fd7, - 0x2d6c17df, 0x71807b61, 0x1194eecf, 0xa3c3ad97, 0xc1b2ac62, 0xde3ceb45, - 0x1585ca5f, 0xa69e32e1, 0x46f51d48, 0x55b5d602, 0xa6bac7c9, 0xe3b76f17, - 0xf58781fd, 0xa6fba17a, 0xa2b4f0fd, 0x357bb01e, 0xd4c71c29, 0x11993edd, - 0x64fbcfe8, 0x4e34e5da, 0xc81e5fa7, 0x8287de7a, 0x239c2fb4, 0xf5fa21b9, - 0xf5da5561, 0x4ef9559a, 0x30903d98, 0x5ec2f20d, 0x35456ef9, 0x0a23439d, - 0x710bb7a0, 0xa3c5a535, 0xd79d1354, 0xf6984616, 0xb4112cc1, 0x9bbfa8af, - 0x7e532f45, 0x530cc4fa, 0x07d399fd, 0x0b9df886, 0x7f99cb3a, 0x8f7a6d5d, - 0x9f2efaa6, 0xc7bb615b, 0x4a77f358, 0xbb3a62ef, 0x5abed4d1, 0x47bd354c, - 0xf7a9e8b3, 0x6544ce18, 0x54e1c476, 0x6658f7e8, 0xeff54769, 0x169dfcad, - 0x7dafda62, 0x927f3c33, 0xfd8da5e7, 0x7d3d8609, 0xe8cf7e16, 0xef0cbcea, - 0xbc451788, 0x9a1dec30, 0x61691e59, 0x3c48553d, 0xa8f6eb54, 0x8f691cea, - 0xd8b5f6aa, 0xf04d8f11, 0x4810a6b7, 0xb6151a6a, 0x477d5237, 0xdfcc9c4a, - 0xcc3bef85, 0xdfd052f7, 0x521f9465, 0x42bfb04b, 0xdd686bcb, 0x606a1738, - 0xd83b6247, 0x076c9384, 0xfbd1c633, 0xf434e837, 0xfed0807d, 0x33700c06, - 0xbadcaeff, 0x822f60fd, 0xd8e2b4cf, 0x549dc47c, 0x95b14d35, 0x6f495ee4, - 0x54bfff06, 0x7ebf6161, 0x4c03e1fb, 0x5615ed6f, 0xff4b8c8f, 0x78d4b876, - 0x9435dda5, 0xbad0170e, 0xb05e7fe0, 0x15f8f143, 0xe9f00f59, 0x810cfa05, - 0x70174a4f, 0x01d5e033, 0x7e7290bf, 0xe2286e3f, 0x0a7be426, 0x1425c057, - 0x0b38fa9e, 0x2772c134, 0xf3cfcbcd, 0x8c57e90a, 0xb78fdd08, 0xb0ffd9db, - 0xe52e1141, 0xf531e1bb, 0xf4e3b4b2, 0x6feb90cd, 0x2078a9db, 0xd97cdfbf, - 0xe83bdfca, 0xd9c658a7, 0xde689f4f, 0x54f41daf, 0x8ccff72c, 0xeedc89cb, - 0xdf5745df, 0xff864f45, 0xdd7e3426, 0x19e647b8, 0x1ab7dfa0, 0xf37d8626, - 0x1be1c44f, 0xe77741f2, 0xe439c74c, 0x9910f1d2, 0xbcf9e5de, 0xe39d2a34, - 0xbedd35cc, 0x4d69f068, 0x5b8c676f, 0x78eee542, 0x7e6f7bd0, 0x43557167, - 0xfbf06a46, 0x1b4ada37, 0x975381db, 0xe25a73c7, 0x7ce22574, 0xdf2e5929, - 0x4f763969, 0x29f844cf, 0x25b4ad8e, 0x8faea44c, 0x553439dd, 0x88be420c, - 0x86d74fd3, 0xcfb60acd, 0x032de91b, 0x9c61f9e4, 0x872de7ef, 0x3f6167a3, - 0x8d19dcae, 0x2bc5a190, 0xa2ee1fdf, 0xa2d9be73, 0xfec01a2d, 0xce7c8de0, - 0x3cc6d70b, 0x390ce7d8, 0x516572a3, 0x5503c84f, 0x04f038ff, 0xb96d01e4, - 0xea72112d, 0x81540fe9, 0xe73a1ad0, 0xe538be58, 0x6a7df494, 0xabdf0473, - 0x2f08a53c, 0xd48b51fc, 0xd32e797d, 0x337cdb79, 0xd2708fc6, 0xae30c3b8, - 0xc6124b7f, 0x30b2f8f5, 0x333cb6ae, 0x8bbb2ba6, 0x97aed691, 0xc316dff2, - 0xa3dbacce, 0x0f23f721, 0x4b645fb9, 0xc8791fb9, 0xf72148fd, 0xfc0d7be3, - 0xd71bf00e, 0x6f43e5b7, 0x39158df5, 0x8e1cf84b, 0x7f5c81cc, 0x01ee12bb, - 0xf15dba3f, 0x8478e4f4, 0xf9e5620f, 0x2357821b, 0xb246dd1d, 0x5edd1059, - 0x8221d977, 0x88c6ebe3, 0x9c7e5358, 0xbf54d923, 0x2a6695c8, 0xbfa93ebf, - 0x7706fca9, 0x537f29be, 0xfd5348ce, 0xa6319e49, 0xdc468ffc, 0xc53faa60, - 0x9f94c53b, 0xa9b66136, 0x12e28cfe, 0x59ccf953, 0xb3e54c8b, 0xf94cdbb5, - 0x34ee2b5b, 0x92f1ffd5, 0xaf72a6e5, 0x0e715970, 0x231f4336, 0x3e85efb8, - 0x6fede946, 0xe3064667, 0x4b38d475, 0x350cef97, 0x56fa900d, 0x39f7ae74, - 0x09ee25d0, 0xe8fb0e81, 0xe2f680f7, 0xbf06199c, 0xfa914065, 0xe8324b70, - 0x685eb426, 0xfd88a8f9, 0x6594f097, 0x9f6ee7ff, 0x313e2561, 0x43fdaaea, - 0xfb7f2832, 0x5619e6c0, 0xaea32fe2, 0x3a52ffd9, 0xdcf17fe5, 0xf07cb237, - 0x57284bfe, 0xfccbf772, 0xc822c134, 0x9bce06af, 0x8c75a3e1, 0x8d7d2eba, - 0xba53da47, 0x5235538c, 0x9d7101c0, 0x00d20380, 0xfdd227d1, 0x5f489f44, - 0xb72cfa27, 0xe8907109, 0xd221e913, 0xf7fdf14b, 0x3d2297a4, 0xd2297a4c, - 0x452f4877, 0x297a42da, 0xcdd43fd2, 0x3a83f4e2, 0xb1fddb8d, 0x8fd382ae, - 0xf7f096ea, 0x7196ea4f, 0x1f3a97fa, 0x8064ff7f, 0xb0087f61, 0x8bf0c69d, - 0x091fc0d5, 0xdb2ede7b, 0xb1bf60b9, 0xabe795e2, 0x5facc7e1, 0xb0235a22, - 0xb1ad5b4f, 0xfe9d1c27, 0xadf9eec9, 0x92089c55, 0xdee19ccb, 0xf8f006cf, - 0xb7cc5dbd, 0xc447eff5, 0x84053eb4, 0xb5d34fa7, 0x3307e0b3, 0xc656ca0a, - 0xeeb8ff10, 0xd03625eb, 0xae9687cb, 0xd5efa3ef, 0x03a7dbf9, 0xf7e86dbd, - 0xa65dfd5a, 0xae321d6b, 0x6b6b5af0, 0xbfdbdb3d, 0x03c46e14, 0xefec33ed, - 0x5ef958f7, 0xe085f2b1, 0xc104e8fc, 0x5b2ffaf9, 0x5af10e38, 0xcf892797, - 0xc46f3d1d, 0xfdf87505, 0xef1413f1, 0x8de1f863, 0x2fc29f78, 0x3e41c75a, - 0x77691d18, 0x0dc48587, 0x2fbedfc0, 0xbcc68fea, 0xc3277df8, 0x97d4ffbf, - 0xf2f78022, 0xb5fe3f0c, 0xd834968e, 0xe1df4615, 0x33c704f0, 0xe57afe19, - 0xe715168b, 0x64af1189, 0x3bcc638c, 0x15fd4aca, 0x5d23c674, 0x47ca6aeb, - 0x757d465c, 0x93d7f724, 0x49dde3be, 0xb955e7aa, 0xec3e535d, 0x22aba3c7, - 0x8ce9423d, 0xafa9e813, 0x3af1ea9b, 0x38d0bf0b, 0x1eb4624e, 0x1c7e8127, - 0x01df9cb2, 0x48109d1c, 0xa39ffbc6, 0xb03dd897, 0xb88e3e83, 0xb8ce82b3, - 0x088fd405, 0x2798c7da, 0x15f7edfa, 0xbcf217cd, 0x9df0cbd7, 0x29f492e6, - 0x3f5e7adc, 0x2c6385af, 0x3d54bbdb, 0xfae61c5f, 0xcfd1046b, 0x90da19ad, - 0x1fdfd481, 0x7ccc8c94, 0x7a3217d6, 0x094fdf60, 0x0bb04779, 0xf03119fa, - 0xbc7e84ff, 0x05bdef12, 0xe942e1db, 0x418fc0c8, 0xbbde064f, 0x0e832ba3, - 0x18d0e282, 0x65711def, 0xf4a17f7a, 0x199d1dd6, 0x43ad75f4, 0x8cf001d2, - 0xae8320f8, 0xf89a2f94, 0x2ae8eb1e, 0x067f9f07, 0xc5d2855d, 0xe9257495, - 0x0e27feb4, 0xba4aefee, 0xc007a4ea, 0x55d387e5, 0xf8f38a8b, 0x79a7a59f, - 0xee3c626d, 0x765c97ff, 0xabda441f, 0x7c17b69f, 0x198c4ca6, 0x2e13120f, - 0x62ec1075, 0xba32f5a1, 0x7f4a17a9, 0xbc6eeda1, 0x6e465da2, 0xfa71bb70, - 0xaeda1959, 0x047aed12, 0x71c21bb7, 0xf7e96f11, 0x1a72de08, 0x999e2d71, - 0xb90e5390, 0x2f2df26d, 0x27cc8de1, 0xf3a719ba, 0x096243f3, 0xee24bf9f, - 0x854f40fa, 0xcb8d693a, 0x42fac85d, 0x71d76461, 0xedea3705, 0xdc5d7fc7, - 0x4f8cf980, 0x37e3cb30, 0xf5fcf2ea, 0x0ffb91a2, 0xc6e1477d, 0xce59ebdc, - 0x61477d0f, 0xfe3d40f3, 0x81a44d20, 0x8f0a17df, 0x0efe9f9c, 0xcfbea146, - 0xc9ba7453, 0x5462ab70, 0x6a9bee1c, 0xaf321c56, 0x3c8c1de3, 0xfce3eb8c, - 0xe9cfc20d, 0xfdc0224d, 0x0903a24c, 0x61091ff9, 0xc85fef93, 0xaa35bafb, - 0x5790dff6, 0x4fba7b8d, 0xb057b53b, 0x4c440fcf, 0x4a77839e, 0xd7190dc6, - 0x17f6ed0f, 0xdbce59ba, 0xb960c8ef, 0x16d2fb13, 0xde27c9d7, 0x5fba73a4, - 0x8a37bca6, 0xfb46f714, 0x3bfa79d1, 0xbf91c73a, 0x40b96731, 0x736ef1bb, - 0xfed193bc, 0x6138d726, 0x9cfeef8d, 0x776f29bc, 0xdecdd86f, 0x042ecd8a, - 0xbd8adf7e, 0x7deb10aa, 0x45a7b62b, 0x4e7661a6, 0xafd2bd07, 0xa0d8b92b, - 0xc6f1cefb, 0xc1dd78f3, 0x286b80d9, 0xff380d3c, 0xeb1eb800, 0x077bae0a, - 0xaa379608, 0xad5f2423, 0xd57c908e, 0x58757380, 0x9ede7dc7, 0x5527f1c1, - 0xf9af090e, 0x5611aecb, 0x2c17f512, 0x93f9c91b, 0xb807c275, 0x6092c69f, - 0xf7b10f10, 0xce58eb09, 0x9ddcef1b, 0xe8bdf87d, 0x2ae79a24, 0x983ff687, - 0x4082b9df, 0xe2844916, 0xbe7a86e4, 0x05fe7f8f, 0xaa7d03d5, 0xf1af754a, - 0x96facec0, 0x7d71ef2a, 0xfe15207d, 0xd754f158, 0x0e55e8f1, 0x9f435f09, - 0x98afd21c, 0x5fb1adf7, 0x80befe85, 0x0ef55f21, 0xc6dcf193, 0xe4eef73d, - 0x92e1e1ad, 0x930ef5af, 0xebc0d8fc, 0xee7ebb06, 0x89c33f53, 0x3afca68f, - 0x98abf59c, 0x2e4c6f58, 0xc28583ec, 0x76189fa4, 0xf904f695, 0x22b5ca7e, - 0x945191eb, 0x13643c2f, 0x076f2a7e, 0x92794043, 0x1fb6b3f4, 0xef82a4ba, - 0xfc294517, 0x6f71863e, 0x22c92c29, 0xc27c41dc, 0xbd370ee9, 0x13911b4b, - 0x7947ca67, 0xc7ea997a, 0x9537488c, 0x98077ac7, 0x1427e3ca, 0x8a3df298, - 0xefd536af, 0x29ac6b39, 0x68ddac9f, 0x31529faa, 0xf83794d5, 0x24fc8a58, - 0xc5b92cfa, 0xb2efbed4, 0x34fd5352, 0x5ca9a55f, 0x319b3bc5, 0x25b7ab40, - 0x81cf1127, 0xd58c9fca, 0xe3de434b, 0xf0cb08b5, 0xfe6b77ce, 0xcbde5a33, - 0x80b91099, 0x6cc9afdf, 0x9e7999fc, 0x2c6b44ea, 0xcdbbd7a5, 0xc928b17c, - 0xb9171f9c, 0x71df814f, 0x9fcccb9c, 0x4d589653, 0xeae51ff9, 0xe44f34fc, - 0xbbe3ddb1, 0x300daff0, 0x4e143fe1, 0x7efc0f44, 0xef9d3b68, 0xcdebcc3e, - 0x070f7e32, 0x75e0937e, 0x0c126fc0, 0x824df807, 0x049bf0f3, 0x24df87d7, - 0x937e1cb8, 0x8721f2e0, 0xd61ff8cc, 0x55ffc662, 0x6ff1991f, 0x787765d0, - 0xa66ad91a, 0x9a29a10f, 0xba782df2, 0x7e9994e6, 0x1d73f142, 0x09b15b89, - 0x09e287c0, 0xbe387fb8, 0x8be08656, 0x37f7c3f0, 0x31477bdb, 0xd7d71e7e, - 0x20606d75, 0x3a2e97df, 0x6fbc0aa4, 0x71f3ac63, 0x6d3fdcfd, 0x89731ad5, - 0x5dcefccf, 0x763e0490, 0xdb7e909d, 0x4f1655f1, 0x207fba80, 0x29d99c64, - 0x3fa843da, 0xaa52fe2b, 0x26d2741d, 0x0e7bcfdf, 0x95d8797c, 0x123eb2f1, - 0xf6bef84f, 0x27be54cf, 0xa8d2c475, 0x8eaf8f80, 0x9f009ed1, 0x84bb9799, - 0x8a249bd7, 0x5c402fb7, 0xa5857fd4, 0xafb73f22, 0x722dc7bc, 0x89fef95b, - 0xa6e727c1, 0x2da9b8c8, 0xdd7fbab9, 0x9ea7e323, 0x777295c9, 0x71c5c794, - 0xf2b925de, 0x8ba90d7e, 0x010773a9, 0xd99d873e, 0x0b3acf80, 0x8ad9ebbf, - 0x9d09e47b, 0x0f21c8f7, 0xa3ecfe43, 0x1ff57fcb, 0x47581c3b, 0x3a617af6, - 0x1dfbfb7f, 0x81e2f8a6, 0xfca65d5b, 0x5324a6a0, 0xdcbbc1fd, 0x40fcf2a6, - 0xc87ca98e, 0x3f298f21, 0xa98465ac, 0x791f55fe, 0xad91f94d, 0xaff54c13, - 0xca6c5539, 0x47b688a7, 0x8abedf01, 0xcd1c53b4, 0xb9fa974d, 0xe4dc705b, - 0xe563bbdc, 0x7edd5f7d, 0x46fbc861, 0xd3a6b9dc, 0xd11ea875, 0xe8e52ed7, - 0xf52164fa, 0x1fae8746, 0xa13eb30a, 0x1de371e9, 0xe67c58f7, 0x5e2371b8, - 0xd0ef43bc, 0x7b8e8af5, 0xe2f19d34, 0xf178e0de, 0xbf5d61b9, 0xc75e7d1f, - 0xfbfce87b, 0xeb7ae5da, 0xbdf3b4ef, 0xa15e631d, 0x96c949f3, 0xd1d9bb74, - 0xbfaabdf5, 0x46fb4ae5, 0x25f1666b, 0x3613fdd0, 0x6dff2b4f, 0xf3c62b84, - 0xb75e22b4, 0xcf7617fe, 0x8f77f70a, 0x5cb07737, 0x658b1ccf, 0x8e5c94de, - 0xddfd338b, 0x92418884, 0x7583adbe, 0x78c84afb, 0xdc646373, 0xbbb1889a, - 0x8fddbf41, 0x6499e127, 0xff7c0d17, 0xf167bf4b, 0xf74d35e3, 0xbd8e68a1, - 0xce3f7f51, 0x4c3d036f, 0x59f24b1c, 0x5b13c93e, 0x49143d7a, 0xcb13ca72, - 0x8a9f6cac, 0x3757fe7b, 0xde75fafb, 0xfa4be99f, 0xb203e810, 0x07a8f40e, - 0xb72954f2, 0x2beb920c, 0xb8eebf52, 0x187ec0e7, 0x43f3f421, 0x174fbc70, - 0x6874c6f4, 0x75dfe3ac, 0xdba0c1ef, 0xfa193850, 0x3be3d0af, 0xd2f319fb, - 0x07ec67e1, 0xfdc67e03, 0xb66df713, 0x7c914de2, 0xe202658f, 0x6dfc0ce5, - 0xc6f693c9, 0x503c3a05, 0xbba8fc0f, 0x6e6a457a, 0xedf7ec0c, 0xeae31dc2, - 0xea3b0e82, 0x62e09bff, 0xfbbbbfc0, 0x87f1dd6d, 0x5df0be50, 0xa3baddf7, - 0xdef67fd3, 0x909f105b, 0x5e3a4bf1, 0x1c2cfdfc, 0x94777017, 0x323f3f79, - 0x9189f248, 0xe4fdf483, 0xccd6fd23, 0x0ffc042f, 0x9d552bf5, 0xbcf3c85f, - 0xdf98ad24, 0x8af9c6af, 0x37f35bfb, 0x8847f94a, 0x87abc4e2, 0xe36f8fc2, - 0x7ad7cbfb, 0x4a6ddb05, 0xde3f151b, 0x75f12af9, 0x9fb30fad, 0x0772cdcf, - 0x26c83bbf, 0x46576a4d, 0x5da5f6ed, 0xc2facef9, 0x60eef948, 0x0beafbe8, - 0x2f19bd75, 0x86df606a, 0x19eebdfa, 0x3cb1fba4, 0x9cf2c3c2, 0xa150d71e, - 0x37a0e9d7, 0x0e6f7cbf, 0x31f6327a, 0x671f1ca5, 0x3f0dcdc0, 0x3cce90d4, - 0x073c37c1, 0xb58379e7, 0x0ec5f8cb, 0xab7e1af8, 0x61ecbf0e, 0x1a1127be, - 0x77ce718f, 0x3f2bba20, 0xeb1fe198, 0xf8741f6e, 0xefc3bec7, 0x89691ed6, - 0x69f1dfc6, 0x67df26df, 0xfd5bf4e9, 0x22cbb865, 0xf03153fd, 0xfdeab53f, - 0x5d798d89, 0x96d50fdd, 0x9438e4ef, 0x73b68b66, 0x2cefad10, 0x7b778ff5, - 0x9fdc89ef, 0x26117788, 0x2ba976ea, 0xcdcbadd7, 0x8fe914a3, 0xef8ca9f6, - 0x5ef209f6, 0x8151f13d, 0x4fc4677d, 0x0481114c, 0x4a1f86a4, 0xe1923d5b, - 0x4aa1f86f, 0x9e792302, 0xda17ea33, 0xeb68e4f0, 0x851577a3, 0x53fd3bbb, - 0x5c647dad, 0xaa7e7754, 0xb9f39769, 0xaf97e9bf, 0x183e7ee1, 0xb6e52694, - 0x036efb86, 0x2ad80d9d, 0xab67586c, 0x4bbfebad, 0xabf3a851, 0x3d9ae812, - 0x96ade282, 0x962fbc2b, 0xbf88c22a, 0xe46f3e62, 0xf9ea352f, 0x7dbf9922, - 0xeab7cca5, 0xd16da7ef, 0x275820ed, 0x7a07ac52, 0x4edd36f9, 0xc5207582, - 0x7c1df03a, 0x35f0790d, 0x90d7c1e4, 0x0a435f07, 0xa5ef86be, 0x761538a2, - 0x0ad3f85b, 0xfc07f683, 0x72418569, 0xc169fc13, 0x82d3f879, 0x169fc3eb, - 0x5a7f0e5c, 0x69fc3970, 0xd3f879c1, 0x9fc3eb82, 0x3f879c16, 0xfc3eb82d, - 0xf879c169, 0xc3eb82d3, 0x0e5c169f, 0x39705a7f, 0x79c169fc, 0xeb82d3f8, - 0x5c169fc3, 0x62996f3e, 0xd3cdb7f2, 0x5b287fdf, 0x51f4cf1f, 0x9b1c5198, - 0xeffdf847, 0xc4fc7f88, 0x373c0e96, 0x2edd022f, 0x48f70ead, 0x904e373c, - 0x8908b778, 0x8cd9b6e7, 0x32ecbbe7, 0xb4e3245f, 0x7e07e943, 0xf49b42ab, - 0xdf85215b, 0x56fc290a, 0x2ab7e148, 0x2b7e94cc, 0xe15bf0a4, 0x4856fc3b, - 0x0a42b7e1, 0xf85215bf, 0x6fc290ad, 0x2b7e1485, 0x0adf83b4, 0xf856fc29, - 0x5215bf0e, 0xfdf0adf8, 0xfe03cd08, 0x905e632b, 0xf499fbf3, 0x9343a252, - 0xe532ea5e, 0xd707e721, 0x5c1f9c87, 0xb83f390e, 0x707e721c, 0x707e721e, - 0xc1f9c87d, 0xdc8349f9, 0xef20bfbc, 0xbc83b707, 0xd41f9c1f, 0xb6037be8, - 0x2e1b49ab, 0x35b48ebc, 0x7142794a, 0x2f353109, 0x8bfc2673, 0x35254ead, - 0x6d8423d6, 0x859980f9, 0x38f4d794, 0x66d13cc7, 0xae39be01, 0x05a6f080, - 0x0f65c704, 0x5cc97ffa, 0xf9b3f86e, 0xbf9ef087, 0x50deb043, 0x35afdfa3, - 0x4b847bda, 0xefd46a45, 0x2f5d77cc, 0x1ea37c74, 0x79a0cbf3, 0x8f996290, - 0xbbfc9378, 0xaf700b22, 0x91458b60, 0x642bb8f1, 0x5d28743c, 0xe793caad, - 0xf6cb16fb, 0x5388e1fd, 0xb83c5129, 0x156591ef, 0x80056c87, 0x7e0292d3, - 0x562f2af7, 0xab92d75f, 0xcc658711, 0x124bb0db, 0x867be09f, 0xbd84daa3, - 0xfd19c69c, 0xefe3b085, 0x4bb44c73, 0xa0ed0279, 0x29f40e6f, 0xf4414dde, - 0x9e4f2cbd, 0xb6ef9a7b, 0xfbe9cbab, 0xae4b6dc0, 0x89c5fdc6, 0xd3ddb2e1, - 0x386689bf, 0xf8506e4e, 0x6da8ce9e, 0xc9fb8bc2, 0x3a7e75cb, 0x5ecb9b70, - 0xf8bae3ce, 0x6fd1a3de, 0xbe5486c9, 0x5a2259a7, 0x450f710b, 0x3df8550c, - 0xb46e037c, 0xbeb1d7be, 0xb02ada2c, 0xfbe0ff2f, 0x7e2e244f, 0xa34ffb9f, - 0x2116c687, 0xcb3450ae, 0x0d2742f7, 0x83d9592d, 0xe5f9a5e6, 0xbfa3a17b, - 0xe706f258, 0x85ef929f, 0xe70cf932, 0x9879f1f9, 0xfdf853ed, 0x8dbec995, - 0xee370496, 0x25b72f65, 0xe136fea2, 0xf5055881, 0x8d8af708, 0x168ae575, - 0xbd01538b, 0x41f10388, 0x639c47f4, 0xdf25e83a, 0x59f7e363, 0x365d58a6, - 0xce431bf0, 0xb1c97129, 0x3151d48b, 0x4432cf7c, 0xd0d4b84e, 0x7e62e383, - 0x3b4e9c78, 0xba5fe7df, 0x8572c9d3, 0xbe615eb6, 0xc65f3e79, 0xf6dd56bb, - 0x7a4b70e1, 0x99ce9c67, 0xbc16ff34, 0x7d267b03, 0x8508f47b, 0x79bd88e5, - 0x0da3d704, 0xcd3df12f, 0xf06f9592, 0x0d4b943d, 0xfbcb450f, 0x52ffd26c, - 0xb0cdc3ae, 0xf1d7cd3b, 0x69c7ae53, 0xef93ab1d, 0xcc39d33a, 0x6a5caeef, - 0x119cb1b0, 0xf21a2f2a, 0x911ef1a7, 0xc23fae10, 0x60d153ce, 0x0bc03be3, - 0x4aac94d7, 0x91ca5712, 0x7339758b, 0xe38d8351, 0xf7f42ab2, 0x6eff42d4, - 0x1e3d62cf, 0xf356f16b, 0x42f24ff7, 0x7de350e4, 0xc94ebd4d, 0xb06607db, - 0xc6c4b43c, 0xcb39cdfe, 0xb6247ca5, 0x93ee3f0b, 0xce3e59cc, 0xe666f782, - 0x947af4ec, 0x5de9e82e, 0xd89a4e5d, 0x4ff864ea, 0xfcc11cb9, 0x14e5ea65, - 0x397cdfce, 0x9799d399, 0xee2adc65, 0x5a6e8122, 0x073be48b, 0xd1f2ebef, - 0xc6b1c40c, 0xc9eb3e43, 0xf44eddf4, 0x74f2218d, 0xabc035be, 0x3878801c, - 0x44ada6d1, 0x8dc4ec9c, 0x4d83ef82, 0xfd451c82, 0x155c82cf, 0x5691fd8f, - 0x2661f7c4, 0x68bf7c28, 0xf4dbd0d2, 0x43fb40fd, 0xf7e13f30, 0x29c2b457, - 0xcd39c47e, 0x805bb6d2, 0x685f637f, 0x5efca3be, 0x629f24ea, 0x9a923bc7, - 0x741b6fae, 0xe63fba1f, 0xb276e846, 0xeb076948, 0xb26193b0, 0xb7c92478, - 0xd3e4266a, 0xf66db0b9, 0x608109d2, 0xcb2b951f, 0xd576fc7b, 0x419206cc, - 0xc9fb55ff, 0xde458b1c, 0x9039233f, 0x96880bef, 0x2f949ea2, 0x4014a359, - 0xf5e6323f, 0x38ec67b9, 0x3a4eb0cf, 0xa7d8ed28, 0xd2e51ef2, 0x7e4d327b, - 0x8cb4d09b, 0x34fd8de0, 0x27f5a637, 0xf468610a, 0x1c2de160, 0x85ebf781, - 0x005428f1, 0xe8b798f1, 0x3bc1eaf9, 0x973ab4ff, 0x91f9c4e1, 0xa6687dbf, - 0xe05ff22f, 0x6b147393, 0x4b1bdff0, 0x0d5768b2, 0x50f7c1ee, 0x11bf03c7, - 0x9efc6db9, 0x4bb64a44, 0x7b10a9f2, 0x8960f54b, 0x4bbb50c7, 0x773cae59, - 0x7a9dd584, 0xdc7bfb2b, 0xd634b76c, 0xbe66cc7d, 0xf3a46be7, 0x5ee7eb07, - 0x9ee7bfdd, 0xf916c3ca, 0x1663c2fe, 0x8857f6ff, 0xd0f72f5e, 0x8fbd6066, - 0xe79ede21, 0x8cfaf1af, 0xf83a4cf7, 0x896efe95, 0x96474f41, 0x2afbe25d, - 0xb77691a5, 0xe54f441a, 0x0fbe15ab, 0xde4cba5a, 0x2b56d6e7, 0x6e845df2, - 0x99bf58ec, 0x9efcbffd, 0x117e6fd5, 0xf8750b2e, 0xbcb7b1ce, 0x84eb48e1, - 0x3d979fef, 0x347c9360, 0x0efb8990, 0xf2712cb7, 0x7b9fd9bb, 0x0f06ab8a, - 0x8c3c9e03, 0xe5d871a7, 0x8c4b7f54, 0x4bdf04b6, 0xd841cb45, 0xfcfee71d, - 0xba8f7e6d, 0xdf8d39b6, 0x95d92cbf, 0xd9ef0abf, 0x7ed1ee7c, 0x4497f582, - 0x4790ecba, 0xf9621a6a, 0x53db9e7c, 0xda2bcfbf, 0xe067cfd8, 0xd2c1bee7, - 0xbe7d778e, 0xaea2e71c, 0x6cc01157, 0xbaf54c53, 0xf61a63b6, 0x4b3b50d1, - 0xdf21bbe8, 0xdd815765, 0x5f641ec4, 0xb632ec35, 0x71b3639c, 0x77b1cfae, - 0xf73ef7fd, 0xf437f3ea, 0x7a1df9da, 0x9ef8ee6d, 0x2ad7ff90, 0xcbd3d82e, - 0x7133dd23, 0x90fca1bf, 0x62b4910d, 0xbe5b9c62, 0x7c8f731f, 0x8ef4a63f, - 0x7367e67c, 0xdc029380, 0xfbc9193b, 0xe94fdcb8, 0xfbf7ee90, 0xf40f6bad, - 0x0a7a0dd9, 0x821df978, 0x1ed79772, 0x951f2417, 0x77a62a35, 0x0bfc8c24, - 0x97c95583, 0xfc00dd48, 0x9a477c7e, 0xcd396f1d, 0xf1093121, 0x27417b99, - 0x51db3ac3, 0x993f8e3d, 0xca0e2e98, 0xfe14bdf7, 0x2f18e4bb, 0x955beff8, - 0xc3df9a36, 0xdf2cfaa0, 0xc51c1aed, 0x68b895fd, 0x5d4869dd, 0x03824f3c, - 0x3eeda9c3, 0xe3cdcfea, 0x02ca3e30, 0x07ec1b7e, 0x42f71073, 0x7e5c5bf9, - 0x6d29c61b, 0x68d4ef90, 0xda38e46b, 0x20fb58ea, 0x975607c8, 0x5cb04fbd, - 0xbddf20d8, 0xddffa39e, 0xcb2f9a11, 0x2704e5cd, 0xee33b3dc, 0xabc286dd, - 0x797f9f44, 0xce59ac63, 0x036b5c6c, 0xf377667e, 0xdd39c65e, 0x30da5d0e, - 0x2837df86, 0xbef97ab7, 0xfbc3a68a, 0xf79cdbb3, 0x7b325fc2, 0x34b623dd, - 0xb065ffca, 0xe9cf6b94, 0x7a6271fb, 0xa9df9320, 0xf1c9cdba, 0x8d5db3e3, - 0x780edebc, 0x81f0443f, 0x662ae2dc, 0xf89d1378, 0xbe596f10, 0xcedf8cce, - 0x77c944f9, 0xf095d7fc, 0xd5605bfe, 0x79e0aeec, 0x8997dfac, 0xb4d9a1f8, - 0x970ef1ef, 0x1f7c6970, 0x3343c4f6, 0x6205eff9, 0xe6cf1c9e, 0xbbc78f71, - 0x4c374453, 0x18fd06d7, 0xf18df3f7, 0xb4ab1eac, 0x6bbe7bc7, 0x420f7a9f, - 0x7c27af4e, 0xddd00fc3, 0x02e3b53e, 0x2f6b8d26, 0x5e07ef97, 0xfdf4efc1, - 0x6a01fffa, 0x00d36c91, 0x0000d36c, 0x00088b1f, 0x00000000, 0x7dedff00, - 0x65555c7b, 0xd6bbf0ba, 0xc0d857da, 0x51b08b66, 0x62020dc0, 0x10106d11, - 0x80a17515, 0x636a735b, 0x8dc42937, 0x910150b7, 0xf39fa8ac, 0xa96f0db1, - 0x962a2695, 0x8da6b675, 0xb2707595, 0xd99b1b46, 0x0f5d9a6a, 0x39d38d3a, - 0x32cdb653, 0x34d209bb, 0x99d37d9f, 0xde79e7be, 0x0daf60b5, 0xf9a675a4, - 0x3efcefce, 0x7df5e3fc, 0xee7d7bd7, 0x765ef3cf, 0xb24c6322, 0x98783631, - 0x8c81b183, 0x45931819, 0x77a13fc8, 0x6302edfb, 0xbeac7195, 0x28d2132d, - 0x0b6bff56, 0xdfe3df63, 0xa2749ef8, 0x8f2c6453, 0x5da0dbb1, 0x10af7c1b, - 0xd6ccabd9, 0x29d33df3, 0x148af7d0, 0xd41dd336, 0x7ec3fb1e, 0x13efd5e3, - 0x338b69fc, 0xe3abea7b, 0xbb78d856, 0x9a7ed0a9, 0xdd8beb05, 0x3ea81bf5, - 0x26e9b3cf, 0x3632c591, 0x87ff04db, 0x7b4894a5, 0x32e6c456, 0x7057b0d6, - 0xe1a8a11a, 0x18b18941, 0xf08b9f48, 0xbec664b1, 0x3bcdf868, 0xcfbd40b7, - 0x64af6f37, 0x35e67b43, 0x398a3fc7, 0xf7363046, 0x0c733652, 0xa5de6c60, - 0x0f569431, 0x073864f3, 0xf8dbd506, 0xc607ba5c, 0xfb2dadbf, 0x5a307fdc, - 0x30e59fb7, 0xbf73fef6, 0xe868e3fd, 0xde9f3197, 0x3acf4d7d, 0xa13ead66, - 0xc304b2af, 0x4d73af8d, 0x83155746, 0x18b6ce79, 0xcd14121c, 0x64c55e5e, - 0x33b32798, 0x13e41a67, 0x422bcc75, 0x16fd6cbf, 0xf3eb04d9, 0xb557fe30, - 0x5da9905c, 0x824fbe63, 0x7a860cf5, 0xdf5e1cc6, 0x58f7f00c, 0x4884670c, - 0x912de8a8, 0xcdbc1903, 0xf83d29f7, 0x21a90c1d, 0x89ef07a7, 0x5ecc1d0a, - 0x7b6d0657, 0x330305f0, 0x65eb0f96, 0xfceaae1c, 0xbff32aa7, 0xfb20bd6d, - 0x4e0ddea0, 0x2757cf07, 0x7ac1e61b, 0x364face7, 0x5cb486cc, 0x473e5ef9, - 0x2f8dde5b, 0xccaf8aab, 0x4f587695, 0x57c71b57, 0xe13d3ad7, 0x2f4f6bab, - 0xa931257c, 0x00771e67, 0x8e00d8be, 0xe382362f, 0x57c0530b, 0xa82f33a5, - 0x7c70bfde, 0xedfe7ecd, 0xd0765e0f, 0xceffa8fa, 0x1dbe8d07, 0xb6acffd0, - 0xf2b784bd, 0xc9f41bd5, 0x99ceaf50, 0xdb51704c, 0xb6cfaecf, 0x6de78032, - 0x1debb7ab, 0xe8eefc16, 0x9521ee93, 0x413f1059, 0x6790099e, 0x3bbc40ba, - 0x397ea7a2, 0x9c617ba4, 0x91cd8b25, 0x719edaec, 0x3cf428b6, 0x86da3ebb, - 0xafaecde3, 0x7165887a, 0xf66777fa, 0x66b3bfe6, 0xa0b317ce, 0xb3cfe43f, - 0xe424ce45, 0xd4510a8b, 0x3e9a9bf0, 0x79837884, 0x35e0063d, 0xdbc3fe23, - 0x0c38469e, 0x6ce6145e, 0xa9a94f86, 0x8b8e1f01, 0x36f38cf4, 0x826bcc88, - 0x8135a97a, 0x548f388b, 0x876c28a0, 0x528d8469, 0x1df90b16, 0x4802ed30, - 0xee9e2453, 0xc3f5f273, 0x677e3f77, 0x5c3c8131, 0xa1cf4abf, 0x3b606af4, - 0xfe00a757, 0xd9cc310d, 0x4fa1e8ec, 0x3e951fb5, 0x6fedfa55, 0x70ae7b7d, - 0x3993677d, 0x3386593c, 0x56e304c9, 0xb9cc3c3e, 0x3afcb846, 0x0f00610d, - 0x817ad05b, 0x7d6c0b58, 0x903537ac, 0x0fcd7657, 0x24a5b7ad, 0x86f58fb6, - 0x93e553ae, 0xc3ce2639, 0x015127c0, 0xfad77798, 0xf10c51a1, 0xca2f302d, - 0xcd8bb39d, 0x5d5bce22, 0x504d53d7, 0xbbb6e619, 0x33e944c9, 0xc368c04d, - 0x764d3e00, 0xe4df3fca, 0x29adb4a0, 0x9ddbca83, 0x633f9a36, 0x80698881, - 0x85308aa7, 0x8f3cfdff, 0xe54165e5, 0xee9c6d53, 0x11035b4e, 0xfd3920b6, - 0x0d79bd71, 0x0efa428b, 0xccfc883c, 0x5db2871a, 0xf5e9d430, 0x4cc42367, - 0x3f3e4fa4, 0x7d12ddb5, 0x163fc927, 0x02ec7061, 0x24b19b96, 0xe02374fb, - 0x38f2ee6b, 0x9b129027, 0xe49438d1, 0xb46f0cc2, 0x7eb00093, 0xcc78430b, - 0xf860e453, 0x2395aa92, 0xb26b7eb1, 0xe6718055, 0x5ae79c5a, 0xced5fda9, - 0x4b7bf1fb, 0x93252199, 0x9026caaa, 0x72287763, 0xdcc0896c, 0xa07787c8, - 0x12fe449c, 0xfea2a50f, 0xf055a3b9, 0x56cf291b, 0x21d7000b, 0x78d2eecd, - 0x055b1394, 0xbb6c0ee7, 0xa9a9e40d, 0x0d769e47, 0x7a817f73, 0xf4077d81, - 0x255ffd07, 0x5d710220, 0xca1c726d, 0x75824df1, 0xb979c317, 0x059f080d, - 0x6e9c9d0a, 0xc8e11339, 0xa3eb81ec, 0x65105ff8, 0x288b23cc, 0x3d141b6f, - 0x79406486, 0x310e4e45, 0xca41f870, 0x3a3f11da, 0xa0e909a7, 0xc51292cb, - 0x886f28fa, 0xf2c38948, 0xc912ad39, 0xaa9e9545, 0x7c2835d5, 0xa3be1733, - 0x2a912bde, 0x56be9162, 0x74a44cb6, 0xcd9286ce, 0x24e3a05e, 0x9a3b1dc1, - 0xb867a3d6, 0x13b5399e, 0x55bc47af, 0x9b4630ef, 0x7a496f00, 0x104e526f, - 0xbed9ce3f, 0xbb41892a, 0xd3cddbf3, 0x5b17fe51, 0xa1a38acb, 0xd16dbcfd, - 0x1e9052d9, 0x7ae6ca49, 0xc4ed4164, 0xacf00638, 0x2791fbf9, 0xe78fa0ac, - 0xe8569f42, 0x70b69bff, 0xd4aa179f, 0x924fed34, 0x31dee780, 0xa1b3e279, - 0xe0f142fe, 0x1f50a32d, 0xe2a7be08, 0xce23bea9, 0x503c87da, 0x0fc073d3, - 0xdaf7a00e, 0xf51ef5ff, 0xd6f895f3, 0xbed0e5f5, 0x4885f6a6, 0xa6e167ec, - 0xa15be43f, 0x49e8a0fc, 0x173ffec3, 0x45653fb6, 0x9edd6c02, 0xee7c7a85, - 0x4f28b4a6, 0xf917f21f, 0xbd51f100, 0xaaf8205f, 0x517c33e5, 0xc7bb8406, - 0x4c560ccf, 0xf480ccad, 0x8d625e7e, 0xf6a80f68, 0x323e5a8c, 0xf3adcb9b, - 0x9093eb51, 0xb53fe64e, 0xccf50925, 0x5f3c1167, 0x6fadd4f1, 0xecf2dca0, - 0xaf101a34, 0x38331d1e, 0x41799f51, 0x551d22bf, 0x93c6ff03, 0x04ae61dd, - 0x0eca2a7a, 0x6fceb827, 0x51fa411d, 0xa77c179d, 0xcc74cff2, 0xd218f385, - 0x748d99dc, 0x7f9d67ff, 0xcff3e22e, 0x17a766f5, 0xf5cd99f1, 0x4bd79fdb, - 0x05ee58a5, 0xe47b4186, 0x885febcf, 0xd8f4b548, 0xfbd2256f, 0xd67684b2, - 0xea36428b, 0x76ccf0ed, 0x1bb22cc3, 0x9d59d118, 0xc359d395, 0xe0e97d01, - 0xa8c7b218, 0x37e746a4, 0x05af85f4, 0x9dd5bd8a, 0x80d7b7df, 0x87b3527c, - 0x6d3511db, 0x508ec867, 0x855a92ed, 0x39ee179f, 0xda857643, 0x871f6eae, - 0x5e3eed4b, 0xc801955e, 0x80e5cd1d, 0x0aba4200, 0xfbf905f1, 0xd3d7f5fe, - 0x7bf26997, 0xb5df7f29, 0x750f2e56, 0xb7a8499d, 0x349c64d6, 0x976bfe20, - 0x5e42fd2b, 0xbcde341f, 0x2f0481ec, 0xc16a1f2c, 0xfd8d0ef6, 0x9a2fbb50, - 0xc36bfbda, 0x97bea356, 0x4c3a2ceb, 0xa42d6b9b, 0x8bd5b7ff, 0x9c5cba19, - 0xed13985c, 0x916183b9, 0x07472859, 0x06653c2e, 0x3b6a0248, 0xbe50888f, - 0x2f73ca3a, 0x031c67d2, 0x6f5090ae, 0x5fb405f8, 0x74f95e3b, 0x6e3ff604, - 0x066be048, 0xbf0bd753, 0xf20c5e9b, 0x2d981964, 0x06671f64, 0x0f1d2046, - 0xf4e5cc3c, 0x1ab67ae3, 0xb9d31bf5, 0xf72834d9, 0x3c42dca3, 0xdbe61b7f, - 0x1dffff05, 0xfec60ff3, 0x143fc999, 0xd0a4bddb, 0x5968dba7, 0xaebcc02d, - 0x8359ea1e, 0xd041be4b, 0x222d935f, 0xac34a40e, 0xdfe7a1d7, 0x82757b55, - 0xc113a722, 0xc8bb408e, 0x416ec830, 0xf3366e3a, 0xccb209f5, 0xf71e611a, - 0x8d9e1e67, 0xa76d7a7a, 0x9d611989, 0xc8c33a13, 0xe41c4d7e, 0x6cd6bd22, - 0x2dbd224e, 0x02ac7438, 0x14ce1fea, 0xcfac3afd, 0xcfac3e4c, 0xae76214c, - 0x9db19668, 0x6fb5f070, 0x960fbe51, 0x82891e2e, 0x47be0df5, 0x9d433670, - 0x8f73aeca, 0x15a41bff, 0xfdec7697, 0x2dff4857, 0xe113b3ca, 0x75cbba7a, - 0x5ba803c6, 0x39336d6b, 0xc160deb9, 0xef7838eb, 0xb13691b7, 0x9d1d7e67, - 0x4dfb9ee7, 0x2726a62e, 0x07099fea, 0xa11fd225, 0xc3b0e9f3, 0x3d5287c4, - 0x2c3b3bb2, 0xb0104fa2, 0x70f791fe, 0x164c137e, 0xbaf684bf, 0xb065ff49, - 0xc48e617e, 0x935773e8, 0x83df614a, 0x938b1091, 0xd1747d47, 0x38eb7642, - 0x3a550f85, 0xdb9b2b7b, 0x72296f8f, 0x73338555, 0xaf582cc8, 0xd66cf0a8, - 0x1022faab, 0xf87b32ce, 0xaf529176, 0x932892eb, 0xf46d5e1d, 0xebb2e831, - 0x33d250e0, 0x3fd9c9fd, 0xf601dda0, 0xf954f2c4, 0x5327845d, 0x0acdeef4, - 0x2dfd54fc, 0xacdffd29, 0x8b66f1c0, 0x5376e1c8, 0x7a14dc08, 0x1e97a50a, - 0xdb41887a, 0xeccf1ba3, 0x51a3f6be, 0x6bdf84c9, 0xfd78e61e, 0xedfaf090, - 0xcd802b5b, 0x4dbfa0d8, 0x0cfefc21, 0xb98bf578, 0xedaf023f, 0x9bf578a1, - 0x375e2187, 0xa0676489, 0xa376881d, 0xb5c0e507, 0x60f6e794, 0x51392306, - 0xd7398529, 0x8077e324, 0x87c91643, 0x541f28a3, 0x15c430b9, 0xe9f506b8, - 0x71e57069, 0x8db1017e, 0x10a4e797, 0xf6b0245d, 0xbc072c78, 0x277da1e7, - 0x7e668699, 0xe5b7720c, 0xdfdedf01, 0x82cd3f40, 0x983ceb6f, 0x8b66f78f, - 0x0eb7ed13, 0xc3d5e89f, 0x59a25a3c, 0xbf187ed6, 0x4e55fe65, 0x4533962f, - 0xf8374c6e, 0xef837ed0, 0xbdf88d49, 0xe97f7f9c, 0x441f67ef, 0x8d33acfb, - 0xb25abad1, 0x67da3a59, 0xf419652d, 0xdcaab7fd, 0xb7823079, 0xddf4e32f, - 0x43e6df32, 0xa3e8f43d, 0x27a8e1be, 0xf1cbb65a, 0x510d4836, 0x981cf89e, - 0xd38920ff, 0x94324b7d, 0x7059ba43, 0x7ec5cf97, 0x0df3e1ae, 0xff3d8794, - 0x4e657414, 0xe506d105, 0x76231ba7, 0xe9555ca0, 0x2e30f074, 0xcf7887df, - 0x7938456c, 0x7a8cb027, 0x8543ffe8, 0x0bf854de, 0x008d36c0, 0x3c1098f7, - 0xa31774a8, 0xca585fc0, 0x413bcfe9, 0xf31d4f59, 0x0091bfa1, 0x38070953, - 0xf0c11a57, 0xd5967483, 0x6ff38d93, 0x91f80c5e, 0x0f1c1d70, 0xdd5645a7, - 0x155f07d6, 0x0df128e6, 0xa6f90218, 0xa9be7192, 0x7a42ba44, 0x0aba046c, - 0x481647a2, 0xae173e88, 0x83ca15d0, 0x1cb8f708, 0xc257e758, 0xf0b1f21f, - 0xa694ffad, 0xa4ce35f7, 0x1e2f2e1c, 0x734a7b33, 0xd04def48, 0x656f9dd8, - 0xfa889a7f, 0xafbdf4e5, 0x149a6025, 0xeb8c9ee5, 0xd7fe5cd8, 0x1fff1452, - 0xb8f407c6, 0xffcb0f8e, 0x2dda224f, 0x235f4b95, 0x79d2bffa, 0x37989996, - 0x5d1ee01c, 0x00fd382c, 0x462d79bf, 0x16f824e7, 0x0c755c57, 0x6ad659e1, - 0x56911874, 0x1c8d62d8, 0x408f2b3b, 0xda1d8a37, 0x39ba246a, 0xf4894bf7, - 0x8b92b9c1, 0x0f800eaf, 0x4e0856e7, 0x32d657ac, 0x3790256c, 0xa816292b, - 0xa057995e, 0x1ca9657a, 0x051a275f, 0xaf4037a2, 0xde283b25, 0x8ef5a731, - 0x13df88a9, 0xa40f5fc5, 0x187ac1f8, 0x2e63e547, 0x959e48de, 0x56abf529, - 0xbb47911b, 0xacb597bf, 0x3ffc88ba, 0xde521bd3, 0xec53e93a, 0x5b51acb7, - 0x8235c6ee, 0x4e57771d, 0x07ca0c44, 0xefce64e6, 0x40f24811, 0x93fa0ff2, - 0x447140bb, 0xc20f30cf, 0x61bc89c3, 0x99eba47a, 0xdba05708, 0xdd7ca5e8, - 0xbe0aa733, 0x99ceb049, 0x1f67ce16, 0xfbbe0996, 0x09ff3e05, 0x5065ef40, - 0x5d740b1e, 0x38e4c316, 0xe626dd48, 0x2e79c70f, 0xca09f61d, 0xd438d3db, - 0x8fefaa28, 0xf75ca1b4, 0xb78911e8, 0xe5a52f32, 0xede947cc, 0x98f34fcc, - 0x74933ac1, 0xfc93af90, 0xf38e312b, 0x0367b32b, 0x8b5fd7d2, 0xe0169c4e, - 0x4239ddfb, 0x439428de, 0xdd68038d, 0x701f5b97, 0x067680a5, 0x5fac41aa, - 0x147ee396, 0x4ccab3fb, 0x74ab718f, 0x995a8e95, 0x17d61537, 0x9be2debb, - 0x6b8beb04, 0xf5c21cf5, 0x38374fa6, 0x1383ef10, 0x74133af8, 0x543f9fdc, - 0x81a3606e, 0x183f360e, 0xdb3a43e6, 0xda2035bc, 0x03e6fea1, 0x97cc0180, - 0xf0bc14af, 0x4e61eadd, 0x7559d38c, 0xfeed111e, 0x188f56a2, 0xe1a7e208, - 0x394441b2, 0x23d3be91, 0x5ab49ea2, 0x353d53d7, 0x4fd4ac5f, 0x59067937, - 0x4e9e4ec9, 0xa15c33f4, 0xd49fb51f, 0x045f8356, 0x4ac917b8, 0x57b7997d, - 0x9e8a61fb, 0x3961db56, 0xab7a67d2, 0x453f4fa3, 0x3f505b4d, 0x08f88f83, - 0x7bd205c6, 0xfd711fca, 0x1bf084da, 0x36abf378, 0x2103374c, 0x9d1c71f8, - 0x79e34cc7, 0x15d33cf8, 0xbfbf87da, 0x63e38f7f, 0xb9bbf01e, 0xe422fef5, - 0x1f00cda3, 0x9de6f3c4, 0xcfd4ccb3, 0x799a59f4, 0xf286a931, 0x4b070825, - 0xa23c75ef, 0xd53d2fcc, 0xbd695a23, 0xe76843ce, 0xe28ccba5, 0x763f6a01, - 0xf405741d, 0x857a776a, 0x90cbcc7a, 0x47b8945a, 0x4eb38e3a, 0x5d31ff40, - 0x6b4957c1, 0xf63361fd, 0x5f1466e3, 0xfe85cf4c, 0x8426fea1, 0xfc37a183, - 0x5e99e742, 0x4273e7cc, 0xf18edfa9, 0xe76c7494, 0x74431158, 0xd5d7e7c5, - 0x1c6214ea, 0xa08fb197, 0x7e90c9fd, 0x0cb8c29e, 0x7e4ecfa4, 0xb42e4a6d, - 0x97d1fe7f, 0x52d0b476, 0x0fb33e0e, 0xf5ab56e5, 0x9c709be6, 0xff9f2283, - 0x5de2724d, 0x206ddf98, 0x53be9a3d, 0x7944db4e, 0xebfd1393, 0x55df56ae, - 0x2cbd422f, 0xeb64c618, 0x0a138f3d, 0x3a15da9c, 0xcb793938, 0x53ef5c20, - 0x582c7745, 0x5f87ed02, 0x3b8d38f7, 0x94fcca7c, 0x9b0fc816, 0x30abcbf8, - 0xc78e5f7f, 0xfee4023c, 0xde5fd2b0, 0x6ae50fb6, 0x821cfce9, 0x4576c597, - 0xda39a9f2, 0xbf02f5e3, 0x52dc4737, 0xd2b8fc8e, 0x24487066, 0xfa19eb77, - 0x7711cd59, 0xe5bfb1db, 0x4c26f9d1, 0x36bfd60d, 0x6e3c9ca1, 0x1e2131c9, - 0x18132d9a, 0x0aaceb96, 0x4f1bbe9e, 0x885240fa, 0x73847772, 0xe5744cba, - 0x0c272864, 0xbcad0609, 0x2f7971d6, 0xb43e1dd9, 0xf5acba9f, 0x60cc8148, - 0x7ca05409, 0x69795493, 0x3c717a71, 0xa3b4e2c9, 0x9142b4bf, 0xaf862c37, - 0xf73960d3, 0x5eaf389f, 0x962e63fd, 0x867f4b50, 0x4128ccb0, 0x9bda3ff9, - 0x573e10c6, 0xbbc58353, 0x6844f518, 0x70205d7f, 0x4fa38e50, 0x7e337647, - 0x5eddee48, 0x7a341bb2, 0x7a5e5ba4, 0xf221f5a2, 0x7a811e52, 0x792058a2, - 0x0ceb61e9, 0x0c12feb8, 0x3c5c00b2, 0x545eb8db, 0xce267bf9, 0x49e5f005, - 0x5e5c9165, 0x2673e4e9, 0xd1efc60e, 0x452a5cae, 0x5e021e22, 0xc3e9e0c9, - 0x9378f79f, 0x9d1e507f, 0xa987fa41, 0x21fe9007, 0x0fe144fd, 0x6f078a8f, - 0x50a3f5d9, 0xd912cb5f, 0x85cb9503, 0xe2cfb436, 0x6947d1bc, 0x2edcc5be, - 0xa6bf9768, 0x892a1cf5, 0x7979444b, 0xc799d962, 0xbebd41ef, 0xfff49c29, - 0x5667a5a4, 0xa66e3c60, 0x211a7057, 0x7d1a59ef, 0x6f987bf7, 0x905d3a34, - 0x81f0ab3f, 0x914597fb, 0xb8084f68, 0x759e8cce, 0x83321656, 0xf139e29b, - 0x3b409633, 0x34e0a34f, 0xa1e07a3b, 0xef527ac7, 0x37bc05f5, 0xfad0fe46, - 0xa8d7bc3f, 0x3e7759c8, 0xc6a2d9ca, 0x700a87e4, 0x7cf5eb5d, 0xd7d18d9e, - 0x3927de53, 0x1cb97639, 0x3fd8a99e, 0x57b3a59e, 0xc0f7c3c6, 0xcef9416a, - 0xc8a956f1, 0x88e340e5, 0x0d3f1863, 0x3e48172c, 0xa252bc79, 0x5ccdda1f, - 0xef784d9e, 0x5d900a28, 0xb43de5d8, 0x722b5a92, 0x3674a3de, 0x94588c17, - 0xe3dfa76f, 0xfe479ffe, 0x9bb62563, 0x83b5a2d3, 0x0cfd0226, 0x67bcb840, - 0xf1e9fd26, 0xefbad196, 0xea6945f0, 0xd38ead55, 0x8bab3de4, 0xe7b0c7ae, - 0x52277bac, 0x3992af3c, 0x2ade9122, 0xc1376e65, 0xe61b259f, 0x4f9d5733, - 0x2ac7b731, 0xa27ec18b, 0xb07b5aef, 0x3389fec7, 0x78a8df20, 0x3a13f154, - 0x19765eef, 0xacd076e3, 0xdd7ada75, 0x16301076, 0xe5caba8a, 0x32bf76da, - 0xb9459fbb, 0xe038dee8, 0xaeabf21b, 0x80821e50, 0x266e7f21, 0xa61f71e3, - 0xced543e8, 0x517a592f, 0x6668728f, 0xc23d45e3, 0x1fd2e673, 0x385fa7e6, - 0xa1bef3b5, 0x3ebb4a20, 0xbf934e39, 0x534435d1, 0x30f766ff, 0xa75bf7cd, - 0x5ef9ab5f, 0xc9a919ee, 0x5e3d5edf, 0xfd467f53, 0x7a1cad24, 0xa3d69a37, - 0x79bfa7e2, 0xa3e8a5bf, 0x12ec4277, 0xe23a9d35, 0xbf91133f, 0xe4672c3f, - 0x33787cbf, 0x1d31f8d3, 0xe7822423, 0xf93d5c80, 0xc8e5f731, 0xbf208fef, - 0xa1f44fc9, 0x7343f3c2, 0xa228c9a1, 0x7ee4627f, 0x725fa879, 0x5e503990, - 0xfdb1d4ce, 0xff8f5442, 0x9cf30e67, 0xe3bafec7, 0xf10f4b0d, 0x1f884378, - 0xff78a573, 0xbfcc0670, 0x4d79790f, 0x16c3f72e, 0xffaf36ee, 0xb58e0838, - 0xfc9ad16d, 0xebf1fda2, 0x3bd60e3f, 0xae1d044b, 0x93e146b3, 0x7da0165a, - 0xa0e8bb52, 0x40c4eafe, 0x583be62c, 0xf4b46c67, 0x0a8b838f, 0x258f800f, - 0xa9de2837, 0x193fc3fa, 0x9e0a453e, 0x1a70b4cb, 0x90e3cb93, 0x29108f5f, - 0xc7239cdd, 0xf103fee7, 0xf49eb41c, 0xdc7fbcdc, 0xc847227a, 0x9f9f0859, - 0xe3dfaf1b, 0x17940f1e, 0x7f0b908e, 0xfe4cb826, 0x47a5c247, 0xd82f47cf, - 0x72a3fa0d, 0xfdfb819d, 0xbf5c33de, 0xfefd7237, 0xf68fb47c, 0x44f39b87, - 0xed070ee7, 0xe93ed297, 0x618d7ba1, 0x59df1819, 0x797d23a1, 0x8190997a, - 0x2126c2fe, 0x0f36fc8c, 0xc81648ab, 0xc878b9be, 0xaa31fd48, 0x3afded07, - 0x0551f390, 0xe4096b3e, 0x71e5ccdf, 0x716e35b1, 0xf5038a4a, 0x1eac1ff6, - 0xe27a8b8a, 0xfd9e1e11, 0x696be130, 0x2bee45df, 0x6bd0127e, 0x8512d1e5, - 0xd5cc5f8f, 0x2e1f3ad1, 0x949db914, 0x1f70ba2a, 0xa9d81563, 0x96065768, - 0x915f28eb, 0x6d59e9c7, 0x9d0a1ff7, 0x14dd94c7, 0xda88f386, 0x7d7dba24, - 0x2e51fb8c, 0x793d0f8f, 0xb3ed1857, 0x68742a01, 0xd6bddbef, 0xaf582e69, - 0x8d96d0bd, 0xdcdadfb6, 0x4d6fea68, 0xcf159746, 0x748cfca1, 0xfe8eca78, - 0x8cfac0a0, 0xe655cd33, 0x580feeab, 0xe936fe94, 0x9da2bf41, 0x1e289822, - 0xf91af161, 0xb16715f9, 0x1ccade26, 0xa76e0b02, 0xf428f3d6, 0x1b42c76a, - 0xeff697e1, 0x5db178d5, 0x1ba417a1, 0xcf4abbc4, 0x8983fda1, 0xe9cc8dec, - 0x15d9f389, 0xe51a8e52, 0x8f748dd9, 0x1f90eafd, 0x07fe5cbc, 0xe3c4be6e, - 0xded7de2c, 0xe18879c3, 0x0c9c525f, 0x5fce4aec, 0xbee2434b, 0x024f913f, - 0x40cf0e66, 0xde1e5684, 0xdac9d0ab, 0x48de827f, 0x3ebc02ba, 0x8fe5cb9c, - 0x36fdc0ab, 0xb2c73bca, 0xfba230d4, 0x96270b1f, 0x51384560, 0x3872ba5e, - 0x1f3df379, 0xcc749e10, 0x7f71b46f, 0x72e1f90b, 0x31c2a47c, 0xbe9e6449, - 0x3c88f2f4, 0xca1bfbe5, 0x6ab7ae7e, 0x61d90fc8, 0x02c57728, 0xcc2cd2c6, - 0xffb6bc61, 0x8f9c0e7a, 0x396ae885, 0x96aee5d2, 0xcfe43094, 0xcabc6564, - 0x0ca7d29b, 0x205fa077, 0x040ed018, 0xe3c0c3bf, 0x574edc3f, 0xb94f7ae5, - 0x72c47ed6, 0x1f8f664f, 0xeaf7daa6, 0x82973c77, 0x59f3aae3, 0xfd61d8a5, - 0x125577cd, 0xdca2724b, 0x808f765a, 0x5ab1dcf0, 0x717df8d4, 0x0325615e, - 0x7fce3e3f, 0x8efd13af, 0xcdafb038, 0xf575cf28, 0x5e083382, 0x0a817b81, - 0xf8871338, 0xe24fe02b, 0x8967bd3a, 0x57c7425e, 0x85abb1d7, 0x5de71b8f, - 0x9f90c82c, 0xa02f5154, 0x9956b7df, 0xa3055c7f, 0x3e9969ef, 0x9e21e301, - 0xe38a5616, 0x03335655, 0x332af5c6, 0xf2865399, 0x7443c6ca, 0x02b9edde, - 0x206f2539, 0x4f3a4fc9, 0xa4f02ae3, 0x4d1d01e7, 0x7643284d, 0x864bb867, - 0x167f89f1, 0x4cb5a71d, 0x59efa2f0, 0x843ce2d4, 0x11d001fe, 0x2d3c7dc5, - 0xe75f1a01, 0x5d7271e5, 0x80e9c18b, 0x658d4875, 0x5521ffb4, 0xd4329c1b, - 0xdf29b63b, 0x2d95f18f, 0x0ddfdc8d, 0xd67493f5, 0xd1c3d7fa, 0x9910ab5f, - 0x790a0144, 0x5659fa2a, 0x30562e85, 0xf7ee3b77, 0x41fe1933, 0xdca548bb, - 0x2a6f3d5a, 0xd0e52266, 0x13dc8378, 0x6b9e409f, 0xd3b240dc, 0x678daa94, - 0xc92b2d48, 0x7d6233af, 0x890faca8, 0xa5d54877, 0xac971714, 0xf35bf2da, - 0x8e086222, 0x9e1e3c59, 0x8d88ef73, 0x727cc2b7, 0x1fe3797f, 0x41873d30, - 0xfe5b8033, 0x4c073bb2, 0xac16ff87, 0xa62378d8, 0xe8cebc4f, 0xe08fc19c, - 0xfa8c6657, 0xe8fafcf1, 0xb2abf295, 0xb9d00f26, 0xd27dafc2, 0x094f1abf, - 0xfe954fe5, 0x4d4ef943, 0x7f865ed7, 0x120526d7, 0xdf4f0f91, 0xdb03323b, - 0x73de3657, 0x5f88c7c8, 0x77d00705, 0x117177a5, 0x5660ba23, 0x5e5bd097, - 0x490b3784, 0x1f37bfec, 0x3b7c863f, 0x13e7effe, 0x95df087f, 0x63ce8c09, - 0xf649fd81, 0xdfaa9a9c, 0x3eb9f223, 0x246790bd, 0xc1464ebc, 0x053bac0a, - 0xc7bee0da, 0x2b4e6078, 0xf02e7fa4, 0x4de38b3c, 0xef9e3c81, 0x6b40fd7b, - 0x4b37ae0c, 0xa78ef5c7, 0x76e68edb, 0xa8ffb748, 0x06590fd8, 0xdced0536, - 0x771126c0, 0xc0e0596e, 0xe2d63be7, 0xc9b96bbe, 0xcaeb0699, 0xf448dfba, - 0xf68a0484, 0xa7689651, 0xb6aee5b8, 0x9f69cb8f, 0xd2c0d1b1, 0x0ee06e28, - 0x006473c3, 0x4caab0cf, 0xacc357b2, 0x857aaf68, 0x1e88aaa4, 0x22f5087b, - 0xef2cb40a, 0x30ac53ad, 0xb042aefe, 0xec7b3347, 0x59fed51c, 0xeb4c9f9c, - 0x6820ed57, 0x8fddb0c7, 0x0b4aa7e5, 0x19bb224b, 0xf7fb83e6, 0x90264cb6, - 0xff5213ed, 0xd92332f4, 0x7baf76af, 0x5bb470ca, 0xa0e6a797, 0x9ae30add, - 0xfd7f6e24, 0xbb67ca3b, 0x285ef94e, 0x49b9e0e6, 0x05801f75, 0x8718d174, - 0xfeaaed53, 0xe763a5e7, 0x9505b954, 0x9f2f9b7f, 0x59ff7ec1, 0x5563dd72, - 0x634d4de8, 0xe9e079f8, 0xcf8dbd0a, 0x9e9a5337, 0x73dbb3ff, 0xfe93aea7, - 0x39feeb79, 0x9ffae1d7, 0xffd88eb1, 0x3cd8f821, 0x3ac67ff9, 0x4ff2996e, - 0x5f37875c, 0x43cfc86e, 0xe746d679, 0x7e2eec88, 0xdee41c2e, 0xcb9cbc3d, - 0x09938b39, 0x74ffc764, 0xfd84d779, 0x1c1f419d, 0x7778a1cf, 0x67183a08, - 0x88a1a588, 0x8ca5cdec, 0x2c8681f6, 0x4340fbe5, 0x224d3a96, 0x6e1603da, - 0xec520e27, 0xb94b41ce, 0x9ca719dd, 0x118b882b, 0x3fd4327d, 0xca5bcbf6, - 0xbee0c6e7, 0xd5ec9190, 0xf5dd36e6, 0x5e53d416, 0x868fce89, 0xd2d289da, - 0x5f9c4a95, 0xf6aa9f6b, 0x79e31a68, 0xb4b3b2fd, 0xa3daa74f, 0xb4f29443, - 0x603f7ca5, 0x1ed68b48, 0xdad6ab8d, 0x1082fa8f, 0xbaa9733b, 0xeb49d07f, - 0xe9d72dd3, 0xa87ffcf1, 0xb07b89dd, 0xab0714a8, 0xfeb4067a, 0xf630d74d, - 0xf9f77e74, 0x1fdc1c8c, 0xd05ab99a, 0xcf5539e8, 0x7e282402, 0x43e3e2a4, - 0x3f8873d4, 0x5fb534f7, 0xaf3e6fd2, 0x2e4c7048, 0x539cd74f, 0x1e7eec62, - 0x3a73712f, 0x11eaf5fa, 0xddaed16b, 0x37c6eeb7, 0xfd697d31, 0x04e5e19d, - 0x6f54f5af, 0xebc6cb7f, 0x7650ff30, 0xe6123dbb, 0x53a8d0f5, 0xefd009ef, - 0x85e33c6a, 0x2978b3eb, 0x9e14b68f, 0x7ab3d08b, 0xa4dbdfda, 0x0d9f4c0f, - 0x45122be5, 0x23be911c, 0x1832981d, 0x59309f9d, 0x35f57e78, 0x30e3ee8c, - 0x1a9f5ce5, 0xd73d0987, 0xc7c3cab7, 0xc4f00559, 0x18963573, 0x39a91f7e, - 0x08e9fee1, 0x818766ef, 0x8b3939e1, 0x624fee72, 0xa82aaed5, 0xbf7edc77, - 0x0bee167d, 0x7e881867, 0x26ce98a4, 0x9ed993c4, 0x71c2af63, 0xcd35e242, - 0x2037e929, 0xfbb5bc59, 0x20679ef0, 0xc9cf7b7d, 0x2a9d312f, 0xf3c3efb5, - 0x88465225, 0xbf6bd29f, 0x9bdc1198, 0x4a5f3387, 0x6e3b9632, 0x754e9110, - 0x869a6feb, 0x50c154fe, 0x4f581ae7, 0x1bf30258, 0xbd611e60, 0x7b7989f6, - 0xce9c20a9, 0xf59648d5, 0xdfd80d15, 0x7fba08a8, 0xae03bec0, 0x4df3a7cb, - 0x80f657f4, 0x0e3a47a8, 0xc38ff653, 0x1fed7b32, 0x30c2fcd3, 0x3b59e14d, - 0x7a15c3e4, 0xca7b635f, 0x6b77fb87, 0x106e5213, 0x69f53d1d, 0xbbd6195f, - 0xab1bbbf2, 0x26fd5f68, 0x9fcf1593, 0xcafb2985, 0xa574e3a1, 0x43675b3a, - 0x6418b46a, 0x55f11673, 0xe0725f0f, 0xe68353d8, 0x9cfaf501, 0x736e3aa7, - 0xda83c71e, 0x64c2d19f, 0xf74323b4, 0x81fb43ad, 0x56be7079, 0x31fda9ea, - 0x01e746d6, 0x518b8874, 0xa7abb57d, 0xe9df0db9, 0xff1fbb24, 0xcc82e382, - 0x35fc431a, 0xcedb55ac, 0x0dcfca9c, 0x2a18f4a8, 0xfdd0a52f, 0x6f7ad4f7, - 0x9f81e138, 0x1fad0827, 0xf6d0d70a, 0x5833b7f0, 0xe160ddde, 0xa95d88fb, - 0xac22b99d, 0x473da57b, 0xbf5a7f33, 0xef7fd3d0, 0xbe6d3cfd, 0xb9f6364c, - 0x7d07943e, 0x4e8277cd, 0x6c596fbb, 0x8d2fb6d1, 0x25777ed1, 0x4592f368, - 0x6d91dfe9, 0x8e1af3a2, 0xf79e137c, 0x18d8f953, 0x8af7efe2, 0x2efa2adf, - 0x1e74c991, 0x79de9375, 0xe3c4e50e, 0x01d24033, 0xf82c3c7d, 0x552e58cc, - 0x0f515bb4, 0x93d3adc6, 0xaefc7a9c, 0xbde0ce5b, 0x6ba016a0, 0xf771e584, - 0xc56e9b47, 0xf148b17c, 0x70fb9b0d, 0xcb51d239, 0x37bf5f77, 0x3a9fcf1b, - 0x5bce740d, 0x75b1b73d, 0x1e2b61ac, 0x94cb8a0b, 0xfdf069cd, 0x84e62aa1, - 0x6323b099, 0xfc712363, 0x15a2d12d, 0xd1f3ddf5, 0x718efff5, 0x8c19e694, - 0xe14219f6, 0x46d23757, 0x756e3672, 0x5bf780b6, 0x5f9b1e1e, 0x06317289, - 0xaf9465fc, 0xc57dca90, 0xf015c717, 0xc5b6c0f8, 0xbe23c52f, 0xdb0f5837, - 0xa2159e69, 0x52d8a713, 0x8b7fe5c1, 0x7b3ed185, 0x3752a8f3, 0x72ec4d1e, - 0x8b3c0ec9, 0x41dee2d8, 0x2d595ef3, 0x9cacd972, 0xc8580197, 0xbe9c3951, - 0xfd4a360c, 0xb3346e98, 0x972839f8, 0x7ce8c292, 0x81f67f50, 0x57cb84b4, - 0xe9cc6f6c, 0x1143debf, 0x5cc8f18d, 0x9fe467cb, 0x6dfd0b9f, 0xf299b19d, - 0x538d3caa, 0xdfbbbbe8, 0x1bba3d10, 0x36724bf0, 0x9e2ce41a, 0x878e63c7, - 0xf575b789, 0x3a20b4c2, 0x7c8055d5, 0x2ee7e2cd, 0xbebb7e30, 0x87e334a8, - 0x9b9d4cfc, 0x5518e5cb, 0x97ebbb1e, 0xda05dc61, 0x635f51fb, 0x0fce783f, - 0xb7d71952, 0x443fa851, 0x830cf37e, 0xe839ef03, 0x430e402a, 0x56825d7b, - 0xc9181c4f, 0xc1fb35f1, 0xa09eccbb, 0x728c4d38, 0xbea3661e, 0xeb069cde, - 0x744338d9, 0x6c78076e, 0xfa1068a9, 0x55c4c78a, 0x0d997e70, 0xde6fd1f5, - 0x1b139152, 0x8c669ebc, 0x36d0c073, 0xdb9f0fd7, 0xbfc885d3, 0xbc79235d, - 0x1cdd67bd, 0x3f4071be, 0x479a87a8, 0x6ae6ae97, 0x557241da, 0x6d6de567, - 0x073a7aae, 0xcfc155d9, 0xf813ad5d, 0xc4a4827e, 0xf28b9bcb, 0x4bf4bf49, - 0x492b152f, 0x57e2849f, 0xe5fd3f9d, 0x9911e907, 0x8719f1f1, 0x4cceb49b, - 0xda07e1fa, 0x4af9743b, 0x1e0bd47d, 0x62ba7f6d, 0xf8e33651, 0xaf105fa8, - 0x7bc5e63a, 0x95fda193, 0x3a16fc2a, 0xe069c91f, 0x8d9db1ed, 0xdbf48bf8, - 0xc8e00169, 0xa1ce82e9, 0x3c38f7b3, 0x7c3a24b7, 0x2e01f86b, 0xae7487d2, - 0x78f7a52b, 0x658e098f, 0x7de8efb8, 0xe7f3a25d, 0xcd4f7aa1, 0xb13070ab, - 0x3e9ce736, 0x0f9c4dec, 0xa76935ea, 0x01fa89d7, 0xed8a97d0, 0x094b2a36, - 0x5cd4b3bb, 0xd7ade8e0, 0xab6d5cba, 0x937282af, 0x03f69983, 0x99534c3c, - 0x79c0307f, 0x1ccf33ed, 0x3df58abf, 0xf803ae0e, 0xe6bce099, 0xe63347f9, - 0xedf37b40, 0xb9b426ad, 0xf5a1cf43, 0x76a4ef6e, 0x4cab4b71, 0x23c519d3, - 0x86b95465, 0xafd90b08, 0xe48674cc, 0xc6c934b3, 0x3d10a7ed, 0x50f80eb9, - 0x644af08f, 0x38d0af04, 0x49f8e871, 0xdefcc905, 0x1a52e2e4, 0xa7454377, - 0x5d90e31e, 0x4ec57aae, 0xefa9f4f2, 0x7bb1fb42, 0xff23a73a, 0xc81a1577, - 0xc1f87e1e, 0xcf119349, 0xc51265de, 0x7bd17ad1, 0x233dbac8, 0x1cae9cf5, - 0x7f28cd8b, 0xdbb9ccb7, 0xfec3e8ec, 0x8b3152d8, 0x965a2fce, 0xa5633b70, - 0x88e481bd, 0xe7b942a5, 0x71cbd8a2, 0xa213bfaa, 0x3754b727, 0x9bdef198, - 0x8590de7a, 0xed97dbd8, 0xbbbd1fbf, 0xf18bf961, 0x2aee4fa8, 0x79c78869, - 0x4ff0896f, 0xd5df1377, 0xf2029f93, 0xf1e51e38, 0x920e91a2, 0x7ff2dd2f, - 0x0e3b39c6, 0x5569181e, 0x43db8af8, 0x417fe25f, 0x928d66bf, 0x1c6014a7, - 0x8e44b52d, 0x74bc6076, 0x00d3bbdf, 0x7abd93ae, 0xfb8d63f2, 0x2fc1f481, - 0x49382632, 0x681e9e5f, 0xac9d22b0, 0x8f46fc6a, 0xe2ce6bf7, 0x7fe855e9, - 0x87b70255, 0x9818c556, 0xa1f342df, 0x2e754f45, 0xf5a7a866, 0x0137dc09, - 0x798fc5bf, 0xfd102316, 0xbaf18e4c, 0x298700ad, 0x30bbbe31, 0xd7ac4aad, - 0x129c60d9, 0xf080b447, 0xc563a29d, 0x9daf1e06, 0x115cf385, 0x59c511f3, - 0xd1c5a727, 0xc5a3547d, 0xc9fbc3ad, 0xf6d5677a, 0x8bce8cb5, 0xb015bc51, - 0x8ce1f74a, 0xb6bdc718, 0xeeab8e27, 0xdcf1a913, 0x04290575, 0xffc1212f, - 0xcb23e22d, 0x1ef1101a, 0x403e987e, 0x46aaf8f6, 0xcd41f913, 0x91da3b09, - 0xf823323d, 0x3e7aa43e, 0xb163e017, 0x0c567c02, 0x95d69bbc, 0x17bb1494, - 0x91faa5e7, 0x50af20f1, 0xcc2565de, 0x4beb8a9b, 0x4aedc37a, 0x0cc67a86, - 0x1660365d, 0xa2b9eae0, 0xc61eac78, 0xd8583c21, 0xabfb4c38, 0x40d122bf, - 0xf2d0d8f1, 0x5c780b27, 0x21050b32, 0x135eebae, 0x755dcfdd, 0xaaf7bee0, - 0x301e7e50, 0x6767c939, 0xffbc1481, 0x66771dde, 0xaeddff7c, 0xdbb5bf9c, - 0xa63f740d, 0xf8ccbe3b, 0xe71abcbe, 0xd9e51a88, 0x31f2788c, 0xc7f421c7, - 0x8f71abfe, 0x4fca461b, 0x6dac7f60, 0x63c515c0, 0x68eac6c2, 0x8529279f, - 0x05f78279, 0x5feb2956, 0x7a870dd5, 0x75f5ea3b, 0xf6079428, 0x378d870f, - 0x2226bbe7, 0x88ec46dd, 0x47dafd47, 0x171343bc, 0x79287bc1, 0xfa6204b1, - 0x9c79aa93, 0x3cea6624, 0x5348778a, 0x0ad93ef9, 0xdcfc6016, 0x7c84c0a0, - 0xfd4beaba, 0xe887700d, 0x927accd7, 0x90ae9193, 0x7f2f48b8, 0x6576e645, - 0xa2dbdc88, 0x02f1f9f0, 0xcf91ee25, 0x93e7bff2, 0x5228bb25, 0x1889f7d9, - 0xe8724295, 0xd90a5711, 0x411cc443, 0x9d9cbef0, 0x87b15073, 0x8f9ca77e, - 0x83e72bf7, 0x83e72b0f, 0x0b77c55f, 0x863f90c0, 0x7a4016ef, 0xe549c9bc, - 0x2815346f, 0x6fe399ca, 0x4892ee45, 0xf9941fb2, 0xadf994e9, 0x25734eb0, - 0x6d567e03, 0x5879d3d3, 0xe984c263, 0xaf32cf68, 0xdb119edc, 0x7587ef73, - 0x9efcbfc2, 0x095da773, 0x3a4f3a1e, 0x3ff7cac7, 0x542d7c55, 0xb612afea, - 0xc75f9019, 0x36e16a76, 0xc6a452fe, 0xda622cae, 0x4d1397f3, 0x4bf53443, - 0x97f3daac, 0x6ad7ec93, 0x68764fbe, 0x975e5fcf, 0x1f643e31, 0x0b574b56, - 0x806e8013, 0x7d33aa4e, 0xd685ff34, 0xcd7b8a52, 0x74c7b90d, 0x3f36ab47, - 0x2fcda7df, 0xabcdaddc, 0x46c3c9e7, 0x9230f429, 0xf131fc8d, 0x0cf7e44e, - 0x0107ef85, 0x3ab36fbf, 0xcfda1199, 0xf8bf7816, 0x1b00c61e, 0x76c94bed, - 0xe3ac238c, 0x5cb09ff7, 0xc3bdcbc7, 0xbe7af695, 0xdb8ec56f, 0x4b1dbee8, - 0x06ede1cc, 0xfc7eeff0, 0x72f1a48e, 0xfe87af0e, 0xa21bd612, 0xe5c353f4, - 0xfe459c93, 0x33ec9b82, 0x62b36b23, 0xc2fe016a, 0xe9399a34, 0xab0c759e, - 0x9075bf27, 0x51327f72, 0x43bca4e8, 0x3e6186b0, 0xf0a67045, 0xe48f85f8, - 0xfe4950c3, 0x89f12a75, 0xf447745b, 0xb90d97e6, 0xaaf007ba, 0x910286f8, - 0x5623e2e4, 0xd8f9ef46, 0xbf13f75c, 0xb016c36e, 0x8f6b336e, 0xf87a1549, - 0x61bcede7, 0x5c135fc4, 0xb52fda0e, 0x780b2415, 0x8588a52e, 0x4536cb9c, - 0xc4a3e869, 0x5f42171a, 0x4be84243, 0x9d7f7f4b, 0x3945d5ec, 0xe842ce90, - 0xe5be2ff0, 0xaf182c51, 0x05fa8f4c, 0x7689d58f, 0xca9e054a, 0x754f9602, - 0xee319b46, 0x73d18b67, 0x3fd8a579, 0xab9f4aa5, 0xb2eb59e4, 0x566bfbe1, - 0xf6e649d1, 0xf13d2dba, 0x96df1825, 0xea35f600, 0x5c919963, 0x1fd3b07d, - 0x7fd43576, 0x65fffc04, 0xeb1bfd0c, 0x65efbc64, 0x5f10e4b5, 0x7949623f, - 0xd05ef300, 0x437f58e8, 0xe5aff731, 0xef826ce8, 0x05bea151, 0xc23da5ef, - 0xc1a94cf2, 0xfebc2df5, 0x5164597a, 0x31189f90, 0x9dbfea82, 0xcef86667, - 0xd9a07781, 0x63ec7187, 0xdd77acf2, 0x7b7feb41, 0xaf07d714, 0xa8f11c19, - 0x7c991e0f, 0xd287a677, 0x685f8d74, 0xbee4104b, 0x8f8517ce, 0x92bd7236, - 0x78c7e25b, 0x34c2747c, 0xfd039957, 0xe90bb71d, 0xf112e742, 0xfd375be8, - 0xa87e2b44, 0x0fc106e4, 0x5d749b4b, 0xe3ff430e, 0x35770b11, 0xd59e291e, - 0x02f98652, 0xd903ee91, 0xd9ebe25c, 0x7e02aeb8, 0xe54af0fe, 0x181ea871, - 0xbfdb9a32, 0x3c448693, 0xdffa1430, 0xb15a2450, 0x2b7a0dff, 0x4ef1e7dd, - 0x1757e466, 0xe097eabb, 0x11096dbc, 0xda6fcf0c, 0xbe781a0a, 0x00ccc0d8, - 0xbd6b934f, 0x4a69f117, 0xf6c08cf5, 0x7a7e0747, 0x5b19ed1c, 0x703a4882, - 0xaef9cba2, 0x2817eb1b, 0x79e29df1, 0x9b3c70eb, 0x599ab445, 0xb9541c0f, - 0xcbc99ebe, 0x0ab2ffc9, 0x0accdef4, 0xce0d436b, 0x708491e7, 0xae6df3b2, - 0x79e20b06, 0xd13d40c3, 0x7f224941, 0xc2556a57, 0xffcc0ab4, 0x7191a062, - 0x1f2ff3be, 0x5381fe8a, 0x5b3575a0, 0xc75e681a, 0xc139892e, 0xa9a896ef, - 0xcf85a1d9, 0xf8f146ef, 0xf1e30990, 0xf5b79f80, 0x8b9a9ccc, 0x78a7a3f4, - 0x6b7c7f53, 0x7ece5d73, 0x2afe61fb, 0x110b0394, 0xc29785be, 0xfa404f98, - 0xfe61293d, 0x5b017f77, 0x60d9d680, 0x6e41fec1, 0xbfa2fabb, 0x7e9cd188, - 0x4b0e0b9b, 0xd7824ef8, 0x341f1021, 0x444e4e5b, 0xb528783e, 0xa1e8e88c, - 0x899a8f82, 0xfcf3862f, 0xeef779db, 0x137a3c41, 0xe77f69c3, 0x315982a1, - 0x60bef4c1, 0x32f44894, 0x4e616fee, 0x9463e23f, 0x91fbf881, 0x8c56c708, - 0xccf3794f, 0x824bbf64, 0x986cd975, 0x2862c4e7, 0x5da2fe87, 0x7ef13e62, - 0x0b8f0575, 0xd57e302b, 0xf8843b65, 0x31664a90, 0x3949ae7e, 0xef9114f7, - 0xb435435c, 0x25956ffa, 0xd8cfde97, 0x4270d092, 0xbb20b6d9, 0x5722906a, - 0x45889406, 0x5906df28, 0xeb655db8, 0xbb940594, 0xaa47fba1, 0xed29d7be, - 0xa65b328c, 0x371b54a3, 0x7d7015d2, 0xe97f6a1b, 0xc35edc2c, 0xae8fbc3f, - 0x893f35cf, 0x317438e7, 0x197f7ada, 0x0a739ca5, 0x3a54afb1, 0x7ae560df, - 0xd1ae4362, 0xa1bd7487, 0x2a59db98, 0x47f2ab1f, 0x872abf85, 0xef7e7bd4, - 0x5195f628, 0x87365e4e, 0xe599eae4, 0xd4076f78, 0xc317739e, 0xfa56897b, - 0x1f72aefe, 0x6f6294f1, 0x5bd8a7bd, 0x5bd8a1ff, 0x05bda3ef, 0x835186f9, - 0x1437bf08, 0x08dd762e, 0x20901af3, 0x3a14df11, 0xedc44c4e, 0x271971af, - 0x61d97d2c, 0x0ea2d111, 0x348f05e3, 0x36497bf2, 0x1598ed97, 0x95cf59f1, - 0x766b2cf9, 0xbcbb3469, 0x7ae3f27c, 0xe43ed1d2, 0xb9557beb, 0x994c794f, - 0xfe6571ff, 0x57f3286f, 0x43498fed, 0xbca132be, 0xefaf10df, 0xfc297e47, - 0xb9d0a729, 0xb57950a8, 0xe908c401, 0xfc9122eb, 0xe778209f, 0x25bde46a, - 0x4ef5f720, 0x1e68c959, 0x7660dbbf, 0x7c462c57, 0xa714664e, 0x27aae89d, - 0xb90365b9, 0xf8b37245, 0xca6ceb5c, 0xe5833847, 0x6381519e, 0x8e5acbb1, - 0x4638be72, 0x24571f4f, 0x5bbdd0a4, 0x1d0efed5, 0x0cf072f7, 0x82a66795, - 0xf3e25ef5, 0x6c7247ff, 0x8ee3e32c, 0xfd3a24bd, 0x4f1cde5c, 0x91237926, - 0x5fed0a7c, 0x636f3795, 0xbe2064cc, 0xfba1644f, 0x610a7700, 0x9de7844e, - 0x3f307c28, 0xff7dd197, 0x673d8ac1, 0x01d1de57, 0xceb8a14e, 0xf5b04ed8, - 0xfc7af883, 0x1bf75325, 0x8f8edc6c, 0x9a27e4d6, 0x4bf535e2, 0xef9ac9ac, - 0x35c3ec93, 0xb23b27df, 0x32ebf935, 0xffea6946, 0xc9a459c2, 0x593050df, - 0x2e4cbf53, 0x6665e4d3, 0x0e4877a5, 0xfa1eed36, 0xa7fd1eb1, 0xa71fa1b6, - 0xa14f86f5, 0x0e0bf0f1, 0xa3b5e160, 0x00e8678b, 0x87518546, 0xfc864cef, - 0x6793d1c6, 0x0aef80e8, 0x3afe1f07, 0xd3685819, 0x7f3c29e8, 0x53afe1f5, - 0xf465bf20, 0x863f3c75, 0x3adcf091, 0x2f0cea7a, 0xea1c59e0, 0xd0347479, - 0xea972df1, 0xf83da28f, 0xe6d365c7, 0x4ef84b26, 0x06625940, 0x8a6ce7cc, - 0x7efc61e7, 0x15acec73, 0xfc761178, 0x8f74f577, 0x79a337ed, 0xfc8b8ebb, - 0x8b8e8d5d, 0xbb0d1dfc, 0x53f6f1c8, 0xcbbef553, 0x7e9a0e04, 0x64115fdf, - 0xfd05af7e, 0xdc6939cd, 0xfd14c4df, 0xdfd14c4d, 0xcdfd14c4, 0x6fee7a39, - 0x26fe8a62, 0x89bfa396, 0x324d5be9, 0xb934efa5, 0x726f6d28, 0xbf7dda53, - 0x6ae729e0, 0xef380a3d, 0x985b8b4f, 0x1117e4c3, 0x4ae7a14e, 0x4f9df43a, - 0x45ca7ed0, 0x12fbc0e6, 0x394e2287, 0x39acbf70, 0x2e7444cf, 0x4c3bb674, - 0x9730bdf0, 0xb62f9be7, 0x617e503b, 0x8e9eed1e, 0x946cb6e8, 0x16b5cdbf, - 0x35bbee27, 0x23c7f45f, 0x1bd6149f, 0x714cdee8, 0xe9c52767, 0xbdfc2d0a, - 0xc7114384, 0x91e3288e, 0x9179da5c, 0x277c45f9, 0xb0eedcc7, 0x3f60e32a, - 0xea326e30, 0x3025c2b7, 0xbf5bf52e, 0xb0a9fa98, 0x842b8f74, 0xe1fa6b8c, - 0x410a2771, 0x3176a6e3, 0xc701177a, 0xf5c66875, 0xfc3f744b, 0x78c25fa2, - 0xd3b44761, 0x354d718e, 0x21df8c5f, 0xdfcf45bf, 0xf8742c5f, 0xb893d425, - 0x5bef89bd, 0x33d881c6, 0x1f0d79d3, 0x47a865c9, 0x5d9db971, 0x9a179d7c, - 0x9f900bfc, 0x6077958a, 0x7ba58cc0, 0x730c4c9b, 0x9128bea2, 0x38363bbe, - 0xe339df17, 0x1b15a0ef, 0x1f90dbdd, 0xde5c74eb, 0xdf3318b0, 0xcfb5d057, - 0x3bd415ff, 0xec983b19, 0x4bfb0495, 0xb404752c, 0x44cae45f, 0x5b24e3bb, - 0x7568724f, 0x8f7fe794, 0x31be7a06, 0xf4505eb3, 0x7763f527, 0xfdc0ef85, - 0x86578e88, 0x4d1f21e5, 0x645e3a33, 0x1f7fbfc0, 0x3cfc44dd, 0x8791ca2d, - 0x7dfdac2f, 0x8f9e0af4, 0x3788bc73, 0x69acad83, 0x8ffc7146, 0xf1452f3f, - 0xa79a740d, 0x7fb43a0a, 0x765373d4, 0x063613d1, 0xfaeb54e0, 0xd7e7c0ca, - 0x7078c069, 0xc10718d4, 0x4661e06f, 0x273a98e7, 0xe076f847, 0xfa80df7e, - 0xb2878c6c, 0xd61e474c, 0xd277d24b, 0xef8ef27d, 0xa827fdf8, 0x50537919, - 0x8389fefc, 0xf8afab92, 0xdc31c9e3, 0x6a945d4e, 0xa8788759, 0x944c9bb3, - 0xe748bc1e, 0x9dce9982, 0xd96bf18a, 0xa97bf7d0, 0xfae18eaf, 0x41a57921, - 0x74410231, 0x30e594c2, 0x0cbde6a6, 0xbbf6d0f4, 0x8bdfbac3, 0x43327003, - 0xdef3c89a, 0xeb178f1d, 0xac65f534, 0xe31dfddf, 0xbda7acf4, 0x8fcddbfc, - 0xc6554f2f, 0xc7997a43, 0xd50c7fc8, 0x6d0b6b3b, 0x843f3bea, 0xcc63c7e7, - 0x523de9db, 0x14877949, 0x4e315aea, 0x3de8ce11, 0x37bfc1ae, 0x9e819afb, - 0x3d399a76, 0xdd3c8aa7, 0xeafaf229, 0xbbeaa53b, 0x7a14cf6b, 0xa3cc2b6e, - 0x8fd4fc7e, 0xdf1b37b4, 0x6d6788cb, 0x6efabe34, 0x012f5a94, 0x2b0920f4, - 0xe23a675d, 0xfb1250ab, 0x63e7e784, 0x1d20e68a, 0xb2f2685c, 0xcdf4824f, - 0xc6c8f085, 0x49d5fc60, 0x3f5af7da, 0xda81331f, 0x1b6beda9, 0x284fb227, - 0x3a27e978, 0x69154daa, 0x624ebd1f, 0x9c3be2af, 0xa80d5920, 0xa776d597, - 0x78e2de40, 0xc5fc82ef, 0xbb903df4, 0x3ed1e89f, 0xfbe94e9d, 0x3f2a1e4d, - 0x694d54dd, 0xca9ea9a0, 0xa46a6a3f, 0x23db96f4, 0x167f9172, 0x3ec65fed, - 0xdaf7a209, 0x1027bd36, 0xd4553f94, 0x51ad1d37, 0x7254e8e8, 0x1c9fdfdf, - 0x53bbedc3, 0x3b3e38e3, 0xf7c0dec0, 0x972e80da, 0xdbfd6d5b, 0xfdca1d1d, - 0xf9e3a3ae, 0x3c4765fe, 0xc31f2fcf, 0x64596efd, 0xe8fed8ad, 0x3fef0378, - 0xefc6ac45, 0x7bf78db2, 0x77a45d2a, 0xb1357ea4, 0x5831fee8, 0x73ca163f, - 0xaea7f27a, 0x41e5dfe2, 0xaf9d5cbc, 0x42b6fdfa, 0x61eefaab, 0x8fcf7f3a, - 0x7a02f7df, 0xfad5fea7, 0x3e702663, 0x4befad0c, 0x43c9e7e5, 0xc2a9f1e1, - 0x6817c4b7, 0x241f2367, 0x9d45f107, 0xa542f883, 0xd6fe9543, 0xa7387216, - 0x0f3a151a, 0x07eee7e7, 0x76842ea3, 0xb4cce383, 0xbbe3208f, 0x9d9eb0cb, - 0xa12fc282, 0x63bca0fc, 0xca83f2ac, 0x0fbd2a07, 0xefe33e06, 0x8c75f334, - 0x5f79fa95, 0x7b475958, 0x845dc46c, 0x2b7a83d7, 0x12b1adea, 0xb0792f7f, - 0xedcef5d8, 0x11b19fc8, 0x96918c0e, 0xf7d4b2ac, 0xfe3ec725, 0x9543c2af, - 0xa3c0fd0b, 0xca0c1c17, 0x123fc3bb, 0x50e7240e, 0xf6fd238e, 0x8c4eb721, - 0x177629b1, 0xc7cfdfa7, 0x1d226fc8, 0x1d660875, 0x30e87bde, 0xf05f7df7, - 0x0ebe78e8, 0x16d68e95, 0xe3074a32, 0x96f6873a, 0xba7aea7b, 0x230779d7, - 0xc61a97f9, 0xacf143cb, 0xfe482bae, 0xa979c19d, 0xec0c64f0, 0xa127e81f, - 0xe8ef42c6, 0xe0e856dd, 0xd3f036fc, 0x67ac0dca, 0x3e8a35fd, 0xf8944c7b, - 0x7e8ac87b, 0xa4172ee9, 0x1a996599, 0xcf4743bd, 0xefe15f3a, 0x5645fb8a, - 0xa372ef8d, 0x171c1d6f, 0xe5c8521f, 0x3cf4d743, 0x2f13f711, 0xf742d5fc, - 0xea0c2f8b, 0xcef68d3c, 0x533d5685, 0x2a9b23de, 0x8b9dde80, 0xf90c133e, - 0xf39ef2a5, 0x0ef7e8e7, 0x176d7a83, 0xb5bda34f, 0x4cc4ab68, 0xeb609e78, - 0x3d20b737, 0x4f457bcd, 0x5b9a99e7, 0x7a471e37, 0xc04fb73c, 0x85d96fe7, - 0x31c5027d, 0x7c225b6b, 0x0a5fa866, 0xc77fac79, 0xe3c7c96e, 0x39c5328b, - 0x3ef1946a, 0xa0a5d731, 0xeb713e5d, 0xfb843a5d, 0x8b02edbc, 0xb48f7e83, - 0xdf0c79de, 0x8db7391d, 0x366b2fdf, 0xf9c0ee47, 0x0ceb4a97, 0xc17ca083, - 0x635e5e76, 0xf70cfd29, 0xcd3c1743, 0x60b3fe28, 0x8ff9046f, 0x1ff45af3, - 0x8eec8205, 0xfcda6dea, 0x4066d67c, 0x53b0583a, 0x07b35e5b, 0x79f241f2, - 0x2f12a150, 0x29b2ce19, 0xe3c2d25e, 0xef7caa07, 0xb97b5f6d, 0xde506d1c, - 0x897f66ff, 0x5f0ff7a5, 0x23e926f9, 0x2997cf0b, 0xff9033f9, 0x178e1bea, - 0xca752e15, 0xb3c55fd8, 0x675836dc, 0x2b662bdd, 0x0775edfa, 0x79e246ce, - 0x016145b0, 0xbd99177a, 0xded1592c, 0xe4bf607b, 0x1ed6f845, 0xfb893f34, - 0x9e2f7598, 0xa13c6030, 0xb262df74, 0xef312657, 0xfd9bf44a, 0x89dac8a2, - 0x7de9da8e, 0xce77265f, 0x1c2e7ec3, 0x0ed15b30, 0x4ff97ba8, 0xfcc76ec7, - 0xa7dd028b, 0x201890bc, 0x55b7993a, 0x0c437ba2, 0x1efcb42d, 0xaf10913a, - 0x28b6e788, 0x0ee58f7a, 0x19e23bc4, 0x4648eef0, 0xd071e13a, 0xf44b4f79, - 0xd9b5b9bd, 0xf9cff580, 0xbc557e38, 0x094b4a97, 0xe71e0bcf, 0x75b89cf8, - 0xa430e6d7, 0x64f5a783, 0x76811f8f, 0x0d3b7883, 0xe15e181d, 0xc5d85ffd, - 0xd37791cf, 0x376301c1, 0x2f3ce01d, 0xa7c00747, 0x472ff7a4, 0x97e89d07, - 0xddffbf92, 0x0ed0c7b9, 0x87e7e08f, 0xd51b77d5, 0x2e071a77, 0xdf14753c, - 0xbfb34ae7, 0xa5777640, 0xc5da8bed, 0x9d09de8c, 0x4be78853, 0x02bdbf26, - 0xca7277d1, 0x2f14d9b3, 0x6d7607d5, 0x744378c1, 0x3ac7c538, 0xe1b6cb92, - 0xb6c598fb, 0xc2f6936f, 0xcefd163a, 0xeb11e748, 0x3fc67e15, 0xbea2073c, - 0xa7780c4b, 0x07b519f3, 0xc65cfc8d, 0xe1fbed3e, 0xce9cf11d, 0x959d0c4b, - 0x804fd18b, 0x411c70fe, 0xc2e9fee6, 0x451dfc83, 0xa85c9fd5, 0x47b8a7be, - 0x60836efb, 0x3dea9b7d, 0x70429850, 0xd6371a18, 0x73797681, 0x0d84f339, - 0xc17d21fd, 0x5c7ca9df, 0xb5fa8bf1, 0x1bd1fb27, 0xbcc91daa, 0x15daf721, - 0x014775b9, 0xbbd1e39f, 0x7be1d0df, 0xf93b1d8c, 0x3fcc3bef, 0x062af208, - 0x1af519f7, 0xd4a753b9, 0x0fe914ff, 0x5bde76e0, 0x052892ff, 0x8bf797cb, - 0xa79a9fb1, 0x48753f79, 0xf5571457, 0xfe830e6f, 0x33d36cbe, 0x4c0597e4, - 0x23fb3791, 0x4bd46e28, 0xbedcecbe, 0x50f7cd12, 0x76085aba, 0x94222e26, - 0x69f6eabe, 0xa85d3deb, 0x670e7bec, 0xfff9e0d7, 0x90e031af, 0xba5f23d7, - 0x8e67e9df, 0x6eefe428, 0xef68287d, 0x056b0fef, 0x77ea0f96, 0x63c4cfb8, - 0xeafe4aa4, 0xfe4d56dd, 0xa6bb369a, 0x1dfbb5fe, 0xfed9ef9a, 0x11f7cd0c, - 0x7c9a9dc7, 0xa6817b5e, 0x64f7c8fe, 0xc0547e4d, 0xe63fa9a5, 0xef935bbc, - 0xf4f584ca, 0xe9a8cf61, 0xa9a0bb24, 0xd661d93f, 0x465d7ff4, 0x65df26b4, - 0xd8a3e051, 0xfbfdaa99, 0xff6e42a7, 0x7c2aa686, 0x8ed4e17f, 0x37edfaa3, - 0x2bc76814, 0x5de3b593, 0x1df05e29, 0xff9e9d41, 0xf8a6027e, 0x34ba09fb, - 0x9809fbfe, 0xc04fdfc7, 0x013f7f14, 0xe4dd7fcb, 0xa6befca4, 0x04bfca02, - 0xf7e6097e, 0xe9829f83, 0x609fe0cb, 0x77e0e5f9, 0xb8f7194c, 0xca1bee32, - 0x4e153fb8, 0xbdfd296f, 0xef87f4a3, 0x3df4ea0d, 0x795d6bdf, 0xe3e025e2, - 0x7467db22, 0x086e595f, 0xa31c6294, 0xe18975f3, 0xf1e667f9, 0x418a6f1d, - 0xa18036fd, 0x9ddcc49d, 0x6e3ee26f, 0xad438bdd, 0x81efae78, 0x07787ffd, - 0x27d85fbf, 0xf0e6bc51, 0xd891b3fe, 0xc29797cf, 0xe90a30e9, 0x7cd7c845, - 0x0d7e502b, 0x6773c77c, 0xca4af793, 0xa46d67bb, 0x554cbeef, 0x2fba3ef3, - 0xd7b3deed, 0xb85a7880, 0x7f7d2f7b, 0xf35af81d, 0xcd76f77d, 0x87d62b77, - 0x47cea174, 0xf7cf8571, 0xa9f9fdab, 0x7f2a4d7e, 0xddf3fe3f, 0x418e5647, - 0x6ab7bc7d, 0x17b5c600, 0x3b1139ee, 0xf1f007fb, 0x66cf4bd5, 0x3da81ea2, - 0xd1e72920, 0x07b57f78, 0xcf9e4af4, 0x6f7526bf, 0x63379e29, 0xb3ba047b, - 0x4f5b25f4, 0xee16c4e7, 0x728355df, 0xedc66176, 0xb57f8a7a, 0x83bc4a49, - 0x6350d3bf, 0x6baedc65, 0xdf123afb, 0xdb7dffa9, 0x1ef1ebd1, 0x23c1c774, - 0xc74c5ef4, 0x4fe3493e, 0xf1cb1d8d, 0xf72c763b, 0x77dcbeff, 0x09cf1224, - 0x8476d03e, 0xa7e75dc3, 0xf2561ff5, 0xbc12901d, 0xfeb44bf7, 0xcd2497f9, - 0xc0b801ef, 0xcdfba171, 0x7022d3fb, 0xf8db275d, 0x7d40d378, 0xd56a7950, - 0x1bff9c1c, 0xe53cf2f6, 0xddfa327d, 0xaeab8ea1, 0x767285db, 0xe7d49b61, - 0xd839f779, 0x98efcc2f, 0xebe9d39e, 0x1b1c2fa9, 0xc37f7004, 0x749b2035, - 0x62af5284, 0xa59bd72c, 0xea2a4f06, 0x47169391, 0xfdf9d204, 0x8811a1ae, - 0x6298c3df, 0xba49ebb9, 0x1f60be07, 0xb5a4ef1f, 0xeee9123d, 0x5211bee4, - 0x2dcbfef0, 0xe9ba7aca, 0x5e6f1bbb, 0x6fb553c2, 0xe9fb05bb, 0x9f2f1fc1, - 0xf54ad636, 0xb89df0df, 0x93aced05, 0xc0ddfc19, 0xfe460663, 0xdc3dc2f5, - 0x70793e4e, 0xfbe0f6f0, 0x7c14d359, 0x7df06474, 0xf5fb0bf5, 0x77dbbd4a, - 0x3d3d4d31, 0xed4ed7c7, 0x33beac7c, 0x5e7da10f, 0x6744b8f3, 0xf5f46a1d, - 0x4ffeb8b1, 0x57e769b7, 0x46b9c0ad, 0x0d8d8fef, 0x039ad7a2, 0x21637cdd, - 0xf2a03f3a, 0xa9f08389, 0x8664f1e2, 0xe765e7c4, 0xecd5f8ef, 0xdd7445dd, - 0xe3c4be3b, 0x31ef83b7, 0x74be2939, 0xb55a7f19, 0x2dfc821b, 0xbd23bdfa, - 0x989e686b, 0x9c1f63d2, 0x1a1f942e, 0x987e879b, 0x93ccfc9b, 0x185bec0c, - 0xebed16b3, 0x891dfa28, 0xd76e38cd, 0xffbd3d3e, 0xb03a6b5f, 0xef23df00, - 0xc0a30272, 0xe9b6bbbc, 0x4667dfbb, 0x629e773b, 0xf0ea7ee7, 0x7fa04be4, - 0xb489976b, 0x923d9abe, 0x5c17cf0f, 0x57dee450, 0x406f937b, 0x2e39ad7a, - 0x9a3fd159, 0x70fc96d8, 0x77e92e61, 0xdaeb57b2, 0xb75c9db8, 0x58bb205b, - 0x156a43b5, 0x629ce43b, 0xd65b9f07, 0x57e3edc9, 0xea11b604, 0x7b030dad, - 0x9b5de604, 0xdaec8539, 0xcadd695a, 0x473c0ec1, 0xe61bb5a5, 0xe7443c1f, - 0xd1cec0ae, 0xaddc2f94, 0x69b6d7cd, 0xf8bfaaf3, 0x3b6ed8d2, 0x37fa3863, - 0x1c615225, 0x0a9bc3f2, 0xe77f555e, 0xf49c6bce, 0xe80f27fb, 0xb8d4531c, - 0xd16bc204, 0xc7cc2f2b, 0xc26afb79, 0x347fe49c, 0xdae096fe, 0xd7ee17f1, - 0x1bdee074, 0xf0e333f2, 0xe9cfd8ed, 0xf05e917c, 0x2cbaefe1, 0xfd815d42, - 0x32df0499, 0xbb7b3b8c, 0x293e4922, 0xca1a08e7, 0x632affb9, 0xb2a6180c, - 0xe7f72c7e, 0x38eaf543, 0x0e8a405d, 0xb1811392, 0xd8af5429, 0xde57cfc0, - 0xfd24e119, 0xedc4c436, 0x6e2621f5, 0x75d10faf, 0x85dfa32e, 0x7df02418, - 0x6997ac8e, 0x9d6d60ff, 0x0417f685, 0xe10e957b, 0x955076b1, 0x887de90e, - 0xfd032db5, 0x8c5f353a, 0xec7b33df, 0x478b5283, 0x8cece387, 0x047d9417, - 0x74cb4fae, 0x90747d56, 0x996c657e, 0x3dea7e66, 0x7e7d9fcc, 0xa59f9856, - 0xef807e67, 0x75ff6c28, 0x86ec93ae, 0xf7f532a4, 0x2e49ea1a, 0x12fcf0a8, - 0x7018bde8, 0x816c7745, 0x1db66a6e, 0x96b2ff22, 0x76c4afb5, 0x1d7c91a5, - 0xbefe06a5, 0x4f186951, 0xfcb8e375, 0xa5d2512a, 0xc3f6b4e3, 0x7eb27191, - 0xc63ba41c, 0xf2e34db9, 0x79953f68, 0x6f0d7d61, 0x43d677f3, 0x13943ee5, - 0x7c0d7d3d, 0x466ff288, 0xd54d60bd, 0xbf9c69d8, 0x6ea2f116, 0xf6f85a3e, - 0xea27c493, 0xc66acc39, 0xa3667bf9, 0xc41a9ad9, 0xdf908b17, 0xc377ded0, - 0x138c7cbf, 0xeb6abff0, 0xe9973a7c, 0xa2b58c69, 0xfa48b75f, 0x7e25f692, - 0xda2ddf2c, 0xcdfbcdaf, 0x11fdfe9c, 0x1949f902, 0x0de3bae3, 0x0a498fc4, - 0x08f76c7f, 0xfb600e74, 0xcf1e3a77, 0x7e2810ab, 0x36143377, 0x624994da, - 0xba22eabd, 0xe333724f, 0x4b596347, 0x3dbbf28c, 0x796fb431, 0x9beeb293, - 0x2843fe75, 0xdbea8e57, 0x749e3192, 0xc4e4d6b4, 0x1b59cbfe, 0xc15a6fbd, - 0x153d29da, 0x9fa2f75e, 0x2226f73a, 0x63c9fddd, 0xf6d678a4, 0x50223be5, - 0xe5b167be, 0x044fdc56, 0xb7c6ec50, 0x73b3fb01, 0xd51df742, 0x2f60c4fb, - 0x027d21c7, 0x1d2127fe, 0xd8dc079c, 0x5fb77a73, 0x2317c7f8, 0x2c5f7f11, - 0x5b96e179, 0x9d5ffa19, 0xa82d47e4, 0x5df7465f, 0x33da9c81, 0xaaf07bf2, - 0x5bc55de2, 0xf01d5e37, 0xb0af182f, 0x938404a6, 0xc91965f4, 0xe8917fa5, - 0xf0e5d69c, 0xbc7dc2aa, 0x0e3b9f82, 0x8a15f970, 0xb70f156f, 0x43f5bbe2, - 0x236eef49, 0xc923313c, 0xb87a50cb, 0x3080be1c, 0xc4d93ce9, 0xa1f92318, - 0x4f2e4583, 0x2813cf07, 0xf33b795e, 0xf48012bc, 0xf5f7f096, 0xc70adefc, - 0xb782855b, 0x2fdf313f, 0x71ff9232, 0xce323b78, 0x606e34dd, 0xe50dbe6f, - 0xb2f8fed3, 0x37fce1c6, 0x18fa5f55, 0x3f0863f2, 0x376bf087, 0x2ff09d1e, - 0xc69e8f08, 0x6ecbe248, 0xae7b4b7c, 0x7fe22f4c, 0x5fb58e30, 0xaf93f9f0, - 0x46055f80, 0xf8f8bfbf, 0x54dead38, 0xa5c2a6f1, 0x07e0b8bf, 0x2ad47fcc, - 0xe70abed0, 0x748dbbe3, 0x57dd43ff, 0x5e4ff751, 0x5cf5c719, 0xd801fa68, - 0xb55fb84b, 0x40e4e326, 0x194f33b4, 0xfef87ed4, 0xdacb07ef, 0xb6f7f113, - 0xe9e2283e, 0xddff0329, 0x872f350f, 0x07e4b8f1, 0xc22f46f1, 0xf86103e9, - 0x1f33d404, 0xcf5cf708, 0x070671f3, 0x26e3cbe6, 0x53903de0, 0x798e357a, - 0xf07f12bf, 0x8f9479f1, 0x027aa62c, 0x074a5dff, 0xf61ddefe, 0x1736082b, - 0xbb83e7cc, 0x9d7de8d2, 0x718d7dee, 0x467f0edc, 0xdc774759, 0xe2815eff, - 0x355133fe, 0x84c4fee1, 0x877c2e2d, 0x437df4f3, 0xb4df69b3, 0xea3e3b41, - 0x978a64fd, 0xfee7e06e, 0xabea752e, 0xb75bf482, 0xc8be2dbe, 0xd1e4e7cb, - 0xbfa88cef, 0x86db2747, 0xc7dcff73, 0xd550df7f, 0x5fc75d67, 0x73c704b0, - 0xdfe2533f, 0x0fe1f9dd, 0xc3eb0526, 0x4dad4f43, 0x0daa7ec7, 0x05a72cde, - 0xb1ee877f, 0xaa5bb424, 0x4e955a9f, 0x0f53f4f6, 0x545fa3a4, 0xba6d63bd, - 0x0f70f94c, 0xbe3a65f9, 0x1b9e2fee, 0xd4f3e745, 0xdccaf6fe, 0x1d30a8af, - 0x3dbd412a, 0x56afeae5, 0xda41fee0, 0xffc5027d, 0x15f6b066, 0x332b67a8, - 0x16b15f38, 0xe87fc913, 0x776bf68f, 0x4ec5ff0d, 0x646f0794, 0x81cfd59c, - 0x203e127a, 0xd5df1035, 0xdfa3adf2, 0x7fcd5c09, 0x7ea7b027, 0x56ffed22, - 0x9de8172d, 0xfcf519ab, 0xf1a4f377, 0x59c704d1, 0xd18fb3ab, 0x794b57fb, - 0x6fa314f9, 0x67ec49df, 0x3fdf818b, 0xe094ee64, 0xb29270fb, 0x9d73385f, - 0xca717bf2, 0x639b6938, 0x53af07b7, 0x591df652, 0xdf2477ea, 0x32f0506e, - 0x5789e975, 0x54efd0ed, 0x1e3cc7bd, 0xe9b3bfbe, 0x619faa5c, 0x3a33f41c, - 0xf066985f, 0xd71f3a3c, 0x7148c3bd, 0xc1acdcd2, 0xcfd41c52, 0x11b45259, - 0xab4b99d3, 0x728f9d1e, 0xcd94d5b8, 0xf9f2358f, 0x114e0835, 0xed91f4e5, - 0xb842ceb7, 0x7fc4df9d, 0xfb61abff, 0xc2ddfa30, 0xafdee4fe, 0xf9eff89a, - 0xa264dd3d, 0x2b26d9f4, 0xcfeba3c3, 0xff29d935, 0x4a0e4daf, 0xcd3cf4d9, - 0xd7f4d8ef, 0xe14b88df, 0xb973bbf4, 0x3bf4cdab, 0x39460d88, 0x2bc03c75, - 0x1ddaaaed, 0xc2eb280f, 0xbdb2b8f7, 0x0e1113c9, 0x3e2c0fb9, 0x75b3a686, - 0x7d97df3c, 0x24eae4f3, 0x2c77d614, 0x7cc4f33d, 0x78fb7ef8, 0x270835f7, - 0x148bb6d3, 0x607238a7, 0xbbc22555, 0xaf91877a, 0xf9f7594f, 0x8f71e94d, - 0x75f97c62, 0x160dc53d, 0xc4f33b6d, 0x877f0c03, 0x9821b177, 0xbd74afde, - 0x7ee78f57, 0xaaf8e5e6, 0x78fc383f, 0x449b5abe, 0xf803b3fc, 0xf3a7f32a, - 0xcba5a2d5, 0xc6cb7e08, 0xb8426fbb, 0x937bd79d, 0x0fce9f90, 0xee744b1f, - 0xf820457d, 0xdbbc72ab, 0xbfe056af, 0x575b6c50, 0xc723dc98, 0x04b961bf, - 0x3e0743df, 0xf9fb474d, 0x3fe5fd9b, 0x6097eeb8, 0x1861fedd, 0x1a5133af, - 0xe0df3dfa, 0xf584ea19, 0x3ef3f7e5, 0x6af1d2e8, 0x539f9ffc, 0x36213fc0, - 0xe6219df8, 0xd4f9828d, 0x61fc141c, 0x26cfa859, 0xbf43a67d, 0x8fcffc11, - 0x198ce734, 0x9f4828fb, 0xcbdf37f7, 0x4fd875a5, 0x1ddc8f5a, 0xfcc89ef9, - 0x547b7a41, 0x83f98c20, 0x73f6edc6, 0xfb40cca0, 0x1724f14e, 0x2e786f10, - 0xe181c2ec, 0x99ff303b, 0xc2f1e381, 0xf14f604b, 0xf2931078, 0xd9f9d67b, - 0x50b22f81, 0xb7ae86ce, 0x882fe5ee, 0xaff66a3e, 0xfad028ba, 0xcba67f27, - 0x0ffafcba, 0x1645f53d, 0x7d33efe2, 0xb6fd1f20, 0x1640860b, 0xb7eea1e2, - 0x58ff9e5c, 0xf3e5a838, 0xf7e81b57, 0x1304eb3a, 0xf48949d1, 0x2e1fc525, - 0x87f1e71c, 0x924f03ba, 0xc83aed3c, 0xc48b40e3, 0x8c38d2f6, 0x399fd49b, - 0xcbacf286, 0xe831fdce, 0x2b71de9f, 0x41e8aa1c, 0xde12675d, 0x4dd83bf7, - 0x3c8fdc0f, 0x0c3bfc8f, 0xf3a369fb, 0x9c2b2cbd, 0x39f15da1, 0x7c30f3f2, - 0x257930bf, 0xdf79f9d2, 0x8f941cc0, 0xadfd666f, 0xbf86e28e, 0xb27ba70f, - 0xe6926db5, 0x3af7799c, 0x703f127c, 0x29fb54c4, 0xe7c1c99c, 0x1b8e0cb9, - 0x837e6ec8, 0xba2e13ef, 0x7b13f38a, 0xed53f399, 0x7b0643f2, 0x15bb7f50, - 0xc8ed527e, 0x1bffbf29, 0x85b3e5f1, 0xd504fd32, 0xffc7a54f, 0x4cf7fe9f, - 0x33412fff, 0x800063ec, 0x00008000, 0x00088b1f, 0x00000000, 0x5aa5ff00, - 0x5554700d, 0xbdef3e96, 0xdd2749fe, 0x12421349, 0x42068408, 0x03621a88, - 0xc4d67281, 0x206efce9, 0x6b01bb33, 0x8d08c42d, 0x749d2422, 0x6aece882, - 0x021a6eb9, 0x367564ac, 0x1d47598c, 0x809f9b47, 0x9476ec28, 0x0da0c040, - 0x6ba2cb0a, 0x3a26aa45, 0xab545b55, 0xa6e00eac, 0xd63b8223, 0x3be7b8e2, - 0x1dddb5ef, 0xa6ed4fe2, 0xee7dba8a, 0x9ee7b9cf, 0xce77ce7b, 0x52b48f3d, - 0x6a22ca22, 0x2a08cdcf, 0x6ea6ff0a, 0x6d4445a2, 0xf67f2429, 0xaf1f4541, - 0x7dbc64d3, 0x58c9a340, 0xce08eb93, 0x4754419e, 0x459a26dd, 0x654284b4, - 0x29bf71a4, 0x795bcbf2, 0x6d0dfebc, 0x61931741, 0xb06aad1b, 0x7aa6d513, - 0x1314360b, 0xaacaab0d, 0x0bcc6286, 0x4b9d2e95, 0x7efe0df4, 0x879b744a, - 0x2a224f99, 0xf60f14d3, 0x169c9d1b, 0x8b5dc9dc, 0x491bfb97, 0xeaa7984d, - 0x534f98f3, 0xa3827c08, 0xd81d4b25, 0x9964b468, 0x8eef3e23, 0x07d6d237, - 0xd2a14e31, 0xf9f6123b, 0x68858f4b, 0xcb17d121, 0x650faa17, 0xdaae79f2, - 0x51337403, 0x29ed768d, 0x70ddf785, 0x05564ccc, 0xafbc67fc, 0x670239f2, - 0xfa65ea34, 0x790a4752, 0x4bceccac, 0x1bcf0f1e, 0xd8293b99, 0x3f6fe7c5, - 0xe78990a0, 0xeeb11db5, 0x6d79e14c, 0x9bb648e6, 0xf036ddf7, 0xdb878b3b, - 0x2cf7fef6, 0xcf58b9ae, 0x9e433647, 0x6dfa1514, 0x174ff277, 0xce607f91, - 0x3f3177fb, 0xf44d69ff, 0x67bd37ed, 0x05d7d621, 0x5afd8f9e, 0x82d5f60e, - 0x56f0a56e, 0x3cfdda27, 0x9bbf48af, 0xe5dff86f, 0xb386575c, 0xf8be7e38, - 0xa7a25d39, 0x69f8bd18, 0xd602f73e, 0x43eb468b, 0x21ee5976, 0x6e717b96, - 0x252e8ece, 0x5fae9d71, 0x4b69768f, 0x9d15cb0e, 0x6615b8a9, 0x6c0d4d15, - 0x851f4276, 0x1797b38a, 0xb97f5f47, 0x9bf42d74, 0x9dbd2c12, 0x90b517cf, - 0xc7e2c7dc, 0x04b49bb6, 0x6a0f1679, 0x3443dc1e, 0xc90e9a95, 0xe2a77bbd, - 0x61bca83e, 0xd61267a9, 0x2b7bbe8d, 0x7955196f, 0x73fafdbd, 0x7975ca04, - 0xc9a9b0ce, 0xd7721b7d, 0x80ede5e7, 0xc400d9fe, 0xfaa94e8e, 0xc7951efe, - 0xbfd7c7e7, 0x46a79c68, 0xf089ce2b, 0x9dc506f8, 0x9f671ce3, 0xf587bb58, - 0xe9ef86be, 0xb46fbe45, 0x6938752f, 0xfda26ccd, 0xff42b91d, 0xda4b8773, - 0xf4914750, 0x16e1d2bf, 0x2dc760fa, 0xf0ea1f42, 0x51d03d08, 0x8ed1ed27, - 0x033fe906, 0x708cff51, 0xe2ec20a0, 0x4a6d7c14, 0x1cce1e9c, 0x9e494f43, - 0x24a99c3f, 0x991453d3, 0x3cb870ff, 0xa5fa6018, 0x939ca732, 0xc0d1ca8d, - 0x4b4e68fa, 0xb40ca12f, 0x674a41f9, 0x037bb1bb, 0x3ffbb61e, 0x43daedd4, - 0x4bcfc533, 0xf33aaf30, 0xdbf846ce, 0x692b2ce5, 0x1ec3cfac, 0xde63dfef, - 0x0555d3e9, 0x683fd1db, 0xfef95b73, 0x94dc5787, 0xff47bd01, 0xb78d234d, - 0xb05a28ae, 0x0ae994b9, 0xcc7622bb, 0xc86e6efc, 0x4fc6bb66, 0xb83553e6, - 0xe3a4d4ba, 0x02b67384, 0xc1aeb7fd, 0xdb261b3e, 0xfc795816, 0x57f7b94a, - 0xf7a627d8, 0x0aeb29da, 0xd98bd0bc, 0xf3cabef5, 0xa66eff02, 0x80f79e5e, - 0xdf649dc3, 0x822bcb47, 0x45c59bb0, 0x07cf36b3, 0xd9ba767f, 0xf5bb3fbc, - 0x51e7c87e, 0xc14e94d3, 0xb8099731, 0xf3fdc410, 0x452e953e, 0x716c30ec, - 0x7f993299, 0x2b22b538, 0x194eebc0, 0xb8da7df7, 0x7dc633ef, 0xd5fdc3bf, - 0xfdcbbedc, 0x1fb88768, 0x9e988aed, 0xd085a34d, 0x0da7f05f, 0xef44792f, - 0xa3a0f9a3, 0x3b0e5a66, 0xd33f025c, 0x81bf27f1, 0x5ca278e5, 0x036ee397, - 0x6b6e867f, 0x85d7d3e8, 0x858b4f84, 0x4bffb0bc, 0x9f609f58, 0xf5f175b1, - 0x9bb2ed24, 0xe7c29029, 0x20b6c3a0, 0x895344f4, 0x0ecb5f80, 0x692e08e7, - 0xcf8ab329, 0x017a644f, 0xabd29e09, 0xae5e7d56, 0x85fc216b, 0x8cfb2475, - 0x9980d504, 0x399fc4ed, 0xf2c99854, 0x167e188e, 0x49fd0fa3, 0xcff6fc13, - 0xd7db9a67, 0xfe7cfd14, 0x13854365, 0xa9b15eb0, 0x4eff33b0, 0xe1acfc7d, - 0x0699fe87, 0x943ce33f, 0x7dc7ca12, 0xce1d8f44, 0x2ee987bf, 0x1ead787b, - 0x8285c207, 0x5c2e14df, 0x42549c06, 0xd44dc8e7, 0xaf7dfc77, 0x47d027e9, - 0xfdd079e8, 0xd3af7fc7, 0x6739df4a, 0x50a4f8e2, 0xfd04e2be, 0x3df74181, - 0x409dc13f, 0x87395f9b, 0xdfa6cb71, 0x3327ab7b, 0xa783586e, 0xff37603b, - 0xed97dba2, 0xd027ff40, 0x2b11cb5b, 0x0f2b2ec1, 0x0af67ff4, 0x3bf4b78f, - 0xa8fb80dc, 0xbbe88667, 0xc7dec8f3, 0x7d236f61, 0xae87f166, 0xfe7bbffd, - 0x25679911, 0x35bd5b98, 0xcfbc4a54, 0xe37fe3d1, 0xb49f6135, 0x6fd015d0, - 0x39179c57, 0xfeea27ea, 0xa9f1543d, 0xf5bd0037, 0xc46bf81f, 0x0a0cfab5, - 0x65e96ec0, 0xe46647be, 0x6a86f57b, 0xc771e12a, 0x6ff04ad0, 0x86eac97b, - 0xcd5efa9d, 0x5f1f84a9, 0xfb14ccf3, 0x3bb1be6b, 0x3d57711f, 0x23cf6fba, - 0x23679859, 0xc99edbc8, 0xf57ac476, 0xdd163b69, 0x6bb7f72f, 0xf7206fcf, - 0x64ed1b3e, 0x03cccd3e, 0x99ef35fb, 0xd1f00c1d, 0xe3fafb5e, 0x1a87b895, - 0xe83db9ed, 0xa6dbb2bf, 0x2d670f42, 0xf8728c9e, 0xbbb359e1, 0xba0ceb17, - 0x2ea27879, 0x56a45a4f, 0x3bab2fee, 0x37d7711f, 0x80bfe1f1, 0xf75af5dc, - 0x3ce2cff3, 0x3884ad7b, 0xeb1f6171, 0xe85dd78d, 0x2dc7cf35, 0x9873ec8f, - 0x94972f60, 0x82cf95ee, 0xef3eaf7f, 0xf45bad92, 0x439de819, 0x11e78fd8, - 0x6525f2e2, 0x85ff527b, 0x5e25bdde, 0x97c5dfd6, 0x09bd8bea, 0x17f31bf6, - 0x526b6edf, 0x6024147c, 0xbf19f25c, 0x3b2019c9, 0x8366dfc7, 0x99e878bc, - 0xbe296791, 0x737ee2fe, 0x6a3ac2d8, 0x94e6d2b6, 0xf83fb8cc, 0x0ebcfef2, - 0x3ba9f3e7, 0x34c7910a, 0x84ac882f, 0x51b05c5f, 0x7bcf2e4a, 0xbe5f88db, - 0x2a971b83, 0x4f2ddf25, 0xc7ee854d, 0x38f57357, 0x16c07576, 0x1ddf280c, - 0x83a3fe8f, 0x8eccef9c, 0x67af77d3, 0x7e71297e, 0xad425b6f, 0x2db7de6e, - 0x738fc753, 0xe33f7f3c, 0xcfb19558, 0xe79287aa, 0x299152df, 0x8966d3f6, - 0xc60e2214, 0x88ac2ff8, 0x10a45ae1, 0x5d763578, 0xe013d23d, 0xe08acbc8, - 0xf2a0ef88, 0xa86e96a1, 0x4fae3b34, 0xa8204a5f, 0x0f7f8c95, 0x7b8c8bb9, - 0x55ef5e60, 0xdbe57ee8, 0x98d8f36f, 0x246a4b4f, 0xab53791d, 0x7c8e9223, - 0x46a8e468, 0xcbeb8d3b, 0x199ff18a, 0x4649afdf, 0xf6643fb8, 0x8fdbc6d8, - 0x6f3c438f, 0x2ab37e1d, 0xfdd0a93e, 0x4d2069a6, 0x646723f6, 0xe9b6ec11, - 0x3875e4b9, 0x1fc133a7, 0x65760647, 0x8fe2137b, 0xaa3b90cf, 0x137e287c, - 0x7ca3fafd, 0xa54f81d8, 0xf6ab0acd, 0x65b1af22, 0x3a294d0a, 0xe5b1b01d, - 0xa7b4befb, 0x5e2e7ec2, 0x1e3f156d, 0x73822251, 0x0aae27b9, 0x23988c3e, - 0xca8e7382, 0x18fc11ff, 0x09591099, 0xb4adcadc, 0xc9f196af, 0x1e2e9591, - 0xa0c2b2ff, 0x03e491a7, 0x57322785, 0xb5ea4f03, 0x3711b7d1, 0x09d99769, - 0x7be9893f, 0xa227a19d, 0x783b86c7, 0xb3410ffc, 0x4e61f10b, 0x0be462a5, - 0xb5f9f896, 0x908d3fb8, 0xf841c0eb, 0xdddd9367, 0xfdc1a32b, 0xbc1f20af, - 0xe5dddb33, 0x326f5eba, 0xcacae587, 0xee2d6afc, 0xfbdd3b29, 0xdfcc158f, - 0x07c91c5f, 0x4bb5b1ce, 0xdd7b6a1c, 0x47fb13ba, 0x807ba3cd, 0xde1c175f, - 0x9f582b27, 0xada196ad, 0x67d22ca5, 0xa429c8e6, 0x6f604bf8, 0xbdba2382, - 0xb2ef148d, 0x561e9f08, 0x9767eb2a, 0x4b940f71, 0xa1f603b4, 0xe6fcf7e8, - 0x00efabc0, 0x6686466f, 0xf58f4e09, 0x4f030ba7, 0x3e3703a6, 0x981ef8e0, - 0x60ffef13, 0xfa0b5ef5, 0xc3b8bf97, 0x9ef6e112, 0xbbe7c9cd, 0x0cf6ed7c, - 0x9e3d0bf8, 0xec7b0fd0, 0xeac7a649, 0x4e197605, 0xe88083f2, 0x29c79cfd, - 0x0e54b7f2, 0xdf0f41b5, 0xd698cbd2, 0x6313e812, 0xa9f331e8, 0xce1fcf41, - 0xb6f84879, 0x430f0b4e, 0xcc07236f, 0xe4ef7c04, 0x7f7426b8, 0x1aef105a, - 0xadc700f5, 0x216e3d2c, 0x0fa4b45e, 0x8cbdc4ad, 0x989d5bf4, 0xa7c8e9bf, - 0xdb3f38f9, 0xdbce3e63, 0x3670e472, 0xf78dcec1, 0x6cc7c704, 0x1ff4b78c, - 0x24bbc6c9, 0x86aadfd6, 0x4717210a, 0x47e012b8, 0x85afdfac, 0x8b7f210b, - 0xf1825432, 0xf996e428, 0x49a06b4c, 0xe8aad1ce, 0x34474f7e, 0xf7b1f9c1, - 0x6e8551f6, 0x250f8caf, 0x1d3707c8, 0xb11254bd, 0xd9a0f1c7, 0xe81395c0, - 0xdffdd62f, 0x09c0c8b9, 0xbf0cda5e, 0xbc27071f, 0xf5a3dc31, 0xae7dc816, - 0xb63b9742, 0x3bcaf85e, 0x6de32023, 0x992a5daf, 0xc6758c59, 0xa3c04a3c, - 0x017c7159, 0x0e0ae40e, 0xf367326c, 0x2bcf7cb9, 0xd25e4eee, 0x96b1b8dc, - 0xd33ad3a7, 0x6bd0b5fd, 0x5de40513, 0xb1ae5637, 0x8570f476, 0x553ebf7e, - 0xf6fb8f7f, 0x964ec128, 0x7d6322eb, 0x9bc17cee, 0x5d67f030, 0xf85ac6f5, - 0x7e597ddf, 0xf9bbe24b, 0xedaff887, 0xadd7a649, 0x339b58df, 0x1efb9f8e, - 0x126a7eda, 0xd9afcf5d, 0xdb36a3bb, 0x4c7f7d75, 0x98b68bee, 0x49e6959c, - 0xbe58fa89, 0xb71276b1, 0xaffe52eb, 0x7dcfd0fa, 0x8c3588f1, 0xb5facbb8, - 0xfdb7fce0, 0x0925bd71, 0x5f807fb7, 0x9d6b0533, 0xfe5bbe33, 0x12ab6db1, - 0x4f80561e, 0xe2bd5fec, 0x0937ec67, 0x18aa6dfb, 0x5a68a753, 0x37791d3d, - 0x4f4f5779, 0x6d8c53ac, 0xa8a72819, 0x49bd88b7, 0xd2b87ecb, 0x623e8e3d, - 0xd4ae6ff3, 0x864d9f64, 0x6fa94f1d, 0x1e15e679, 0x53ccb97f, 0x557ec956, - 0xbf92a9ae, 0xa6a7dd8f, 0x860fcf52, 0x80bf1db2, 0xcd07453d, 0xb949f84e, - 0x4f33eba6, 0xfc2efcbd, 0xe1db2f31, 0x357e64ea, 0xbcfa6955, 0xea273663, - 0x5f63d140, 0xffe07be5, 0xa5cbec5b, 0xd3b262ce, 0x953f1e64, 0x3df0573b, - 0xc6c7cfb6, 0x7aa5693e, 0x645ed3be, 0x533afefe, 0x3adbe3b1, 0xc51be493, - 0x12d9c169, 0xf890bf87, 0xe85c1d16, 0xf7c05cd4, 0xd6fe1da0, 0x677ff5fe, - 0x0c8f0e23, 0x0bba67fe, 0xd3ed75b8, 0xb6cfd874, 0x81d38f81, 0x6606270f, - 0x1d9ed039, 0x1fd03972, 0x16b8fbad, 0x368cbaf3, 0x8b30675e, 0xf636b19c, - 0x13d58e7e, 0xcdd1de12, 0x73af6bd0, 0x614b2fdb, 0x82dda9ef, 0xce8efc63, - 0xd788fc44, 0xe3395c19, 0xeb1265d5, 0xf5b3050c, 0xd45a033a, 0x7acc0a19, - 0xea34019d, 0x6751680c, 0x0cea3f40, 0x006751a0, 0x68033a8d, 0xa2d019d4, - 0x2bfe80ce, 0xbcb16ba8, 0x50de4e51, 0xecd1aadf, 0xf40fff82, 0xf5e4416a, - 0x74d31c0f, 0xc412877a, 0xfbc67f7d, 0xaf460e23, 0x28b075e8, 0xe77953c7, - 0xfbcb341f, 0x5eda1a20, 0xd6f71337, 0x5571b9af, 0xd9371117, 0xa3cddb14, - 0x6a1f5127, 0x1bdc53ef, 0x2e5fe85d, 0x5c1b6c72, 0xfa237ef8, 0xd56ecd7b, - 0x9abafb85, 0x6f97fa8d, 0x58ea57b0, 0x2cc739d5, 0x15fbcf72, 0xeffde1ca, - 0x64efeab0, 0x2cbdc6bf, 0x9545b0f7, 0x1d6fda3c, 0xcb4bf792, 0x4d738a8b, - 0x7eda1e42, 0x1382e7cb, 0x9df4b69d, 0xb21fd790, 0xc524d739, 0x7de48f57, - 0xc174fc7e, 0x45433c8d, 0xa7d5af4c, 0x7b5edf90, 0xf9213801, 0xb47e4248, - 0x33fcd9d6, 0x5da467e4, 0x7efce133, 0x644ee87e, 0x6d3dd6f9, 0xb09228fe, - 0x9930737f, 0x6df60df6, 0x99c823cd, 0x034a8fdc, 0x943fb2e2, 0x74aa1fdc, - 0xc6927d64, 0x3cd1e63f, 0xff755be4, 0x3f40e6b4, 0xdbb977ef, 0x61caf92a, - 0x2570f78f, 0xb349f1fb, 0x272fea47, 0xbde4d98f, 0x9cfb7e75, 0x8d4bfaa4, - 0x1fea5536, 0xc48acc1b, 0xdee52bf1, 0xaacbb063, 0xeea57bba, 0x10eb9552, - 0xe1d98e7f, 0x3786f2d1, 0x5cc377c0, 0x6abfd497, 0xe10bf4ac, 0xf72f7ec7, - 0x7f16683c, 0x8254e9ab, 0xc9abd32a, 0xad7f816d, 0x3d8a7562, 0x298fed99, - 0x78ab0fec, 0xbb04c6af, 0x915db0da, 0x100a42bc, 0x8695e7ac, 0xfe0d573e, - 0xfb0a57eb, 0x3d56bdcb, 0x5553ce0f, 0xc5d79fe1, 0xdfe78b71, 0xfc0b5e47, - 0x55c71d66, 0x5f671cb4, 0x37bf708f, 0x9ebe6a6d, 0xc072bbe7, 0x3319f57f, - 0x726a4f01, 0x95e85e7e, 0xfced5f78, 0x095bef84, 0x737da5df, 0xa8e1f7d3, - 0xc8493e89, 0x759a4f6b, 0xca7d61fc, 0xec14eb7b, 0x5e3eea55, 0x3474cf69, - 0x8ca2bb49, 0x340bffc4, 0xe02f6f3d, 0x4a6672bb, 0xeb0fa2dd, 0x6eedda6b, - 0x0b863fe8, 0xbefc8dbb, 0xe796e540, 0x5bd54eed, 0xdc29d30b, 0xca5b8d3f, - 0xe7617e14, 0x5c71d47c, 0x3d4f3fc2, 0x7d05c0bb, 0x4377697c, 0xc739351f, - 0x31dde1e6, 0x72ffe0cb, 0xdc55c359, 0x029d2797, 0x438f9fd8, 0x5adfacdd, - 0x5d41481c, 0x50d1e43d, 0x38a63f27, 0x1ebfaef1, 0x716fb74f, 0x140acfc2, - 0xb5b7ea27, 0xd935dda9, 0xe676bfcc, 0x9cf0370c, 0x61ea55f1, 0x76eadc23, - 0x53506b70, 0x6ca6b5f4, 0xff0df3d4, 0x54a6f729, 0xd7f78a4d, 0x1d147e1b, - 0xf11d22fc, 0x6dd447f5, 0x807f8377, 0x835eee6c, 0xfea0ec3f, 0xbf5269a6, - 0xe5d1d98d, 0x613b39fd, 0xf4ab5347, 0xef8d8d75, 0x0c4f9199, 0xc1cde6dd, - 0x7cd72bfe, 0xce5b25be, 0x8cbd7e39, 0xb8033771, 0x165eb63b, 0x463df1c3, - 0x6b781dfd, 0x26baea32, 0x326baea3, 0xa326baea, 0xea326bae, 0xaea326ba, - 0xbaea326b, 0x6baea326, 0x26baea32, 0x97ae13a9, 0x878eddf6, 0x08ea1da4, - 0xbc4278c8, 0xc7eab9b8, 0x55175dd5, 0xa577538d, 0xc4865714, 0xbd7bf65d, - 0xcea63dde, 0x26aefeca, 0xe0d57bf8, 0x431e7b84, 0x7163d25e, 0x6b5438b3, - 0x603c16f1, 0x54f07c17, 0x8d6f5b8d, 0xf52ecfe9, 0x9b64cbd9, 0x2ca87b8f, - 0x5152659a, 0x23ee34c7, 0xdf84ef56, 0x1bf09ce0, 0xd31bf0b4, 0xfcdfb8ec, - 0x5daec2d6, 0x0109e7aa, 0x726c13c9, 0x32375bbf, 0x2f7d30ae, 0xe5709339, - 0xc2b831b3, 0x90159a0f, 0x95a0ed63, 0x233f74ba, 0x37254ff8, 0x0e3f9c7f, - 0x9c7484ce, 0xda1a9699, 0xb5a67d87, 0x1791baa5, 0x9d8bbfb3, 0x88a6dc9d, - 0x06a1afbf, 0xbc1c77d9, 0x7c9e4749, 0x73d1c4ef, 0xf7f9e1bf, 0xf25d83fe, - 0xd793ad9d, 0xe0fffa2e, 0xae954d4d, 0x84775f8f, 0x9659e77d, 0x43b654ea, - 0x16d5578e, 0xb8ba922a, 0x50fe2a9a, 0x58ae3da3, 0xd377a380, 0xb577dc3c, - 0xc839e1b5, 0x2efec399, 0xa32cdfef, 0x6a1a6bbe, 0xd9f4cbde, 0xbe373cec, - 0x3dcd4dab, 0x800b0544, 0xb0c57547, 0xadd4b3ab, 0x1963dd60, 0xbf83bfde, - 0xa7cc5edc, 0x96fee356, 0xb3b69753, 0xce63ee4b, 0x32fbdc42, 0xf51fabab, - 0x9e6f2d86, 0xb2c27a90, 0xd442d70c, 0x79bcb61b, 0x5c73a75a, 0xe51b8afd, - 0xabab13b2, 0x66f8827f, 0x109f3eeb, 0x09a1fd67, 0xc0fb7449, 0x09f3eee4, - 0x3f05ae71, 0x3f4e9df8, 0xafb84c53, 0x5c944356, 0xf21dbbd5, 0x4bfeebf9, - 0xa8d3cf7f, 0xaaa7c9c4, 0x749c5c74, 0xe7b0c282, 0xf90ec5d1, 0x713397fe, - 0xdbd43cfd, 0x10b5d8a8, 0xfdaf38f3, 0xe2f8ec35, 0xc1a79ead, 0x7738cf27, - 0x3579f10e, 0x0d90c758, 0xbbe319ed, 0xdbd529e4, 0x3d36b688, 0x357e9260, - 0x6df68a58, 0xfa20f435, 0x81762fd9, 0xf393ed4f, 0x3a622c6e, 0xb79a1acf, - 0xe9788ede, 0x73fe8dd9, 0xec5e9e65, 0xdfeeb637, 0xe58f9c69, 0xc37987d9, - 0xf9e4aa85, 0x6dea37c3, 0x55c22ecc, 0x371d0e3a, 0x93aca8fc, 0x58e7fbe4, - 0xa55e39fb, 0xfdf9781a, 0x47bcb372, 0x7e4c4f20, 0x0a5d5eea, 0xa3de5879, - 0x61afbc86, 0x5299ec9c, 0x7b6ef98f, 0xc77ec80d, 0x7c653b0d, 0xe3af396c, - 0xa685b4a3, 0x0de404e0, 0x4e0d1e53, 0x7653bc80, 0xdc5cda8c, 0xb51810be, - 0xe1787f21, 0xe86d476f, 0x7543c17f, 0x56bfe1e3, 0xc2df09ad, 0x3f5951b2, - 0x921af79d, 0x04e8c277, 0x4d856fe4, 0x6c02596f, 0xe69e73b7, 0xb7f2937d, - 0xd3638922, 0xfe9a5b0d, 0x87b04aa8, 0xe490cfe9, 0x259d54ab, 0xdd14bee3, - 0x3e8f7dff, 0x6e8ec2a8, 0x09dcb208, 0x69e737f6, 0x1248e5d3, 0x6bacb0df, - 0xf3837031, 0x3f71a4b5, 0x3cbe4733, 0xe423c0c5, 0x378c8d8f, 0xbeb7a6fe, - 0x79c8be42, 0x8c7e18dc, 0x261c314d, 0xebef5dc4, 0x20fc1711, 0xbbdade79, - 0xf78ad91e, 0x76e3536d, 0xd78fbc8b, 0xdb456df4, 0x259efada, 0x4cbf2487, - 0x65f9cf9a, 0x9c9d7d12, 0x7b68e463, 0x39adf3f0, 0x76cbece3, 0x0ed12d70, - 0x37439a4e, 0xd27abde0, 0x480eea9f, 0x0fdd091c, 0x6ad9d97c, 0xecae2377, - 0xd8a555fa, 0xa9f5b7d7, 0xfaa98f32, 0xa751d947, 0x52540fcc, 0x87e6fc11, - 0xe1e011da, 0x0c3c24ec, 0x8972dd48, 0xddae7043, 0xadb60778, 0x123e4a71, - 0x5336ebf3, 0x98adc3e8, 0xef90e597, 0x45b70c11, 0x6f7c2ca6, 0x4aeee29a, - 0x2ece2bc8, 0x9d041599, 0x830a19dd, 0x15cfe8ef, 0xd5c8ea37, 0xd6ae3a69, - 0x7bad0da8, 0x352dfc79, 0x5bf1b82c, 0x6ff307e0, 0x7697acb7, 0xb14cd945, - 0x290a5cdb, 0x7067fffa, 0x3d7bc42d, 0x67ad3df6, 0x20efb05b, 0xf04afbde, - 0x8fa8b599, 0xe45d95fe, 0x80d50689, 0x33d3cf99, 0x7bb70481, 0xb8942cee, - 0xc686a513, 0x2cff91fb, 0x6a3a954f, 0x13d704cf, 0xd3da6ef8, 0xf5e4a37c, - 0xc7a4fe87, 0x29a5d1fb, 0x3d71e46e, 0x711b5cf3, 0x5d479eae, 0xa29afe32, - 0xa13c0bf3, 0xa967a7eb, 0xe69ece7e, 0xc59f794c, 0x8767a1ee, 0xbfbe3267, - 0xe5bc3259, 0x1803a8d5, 0x667b1fdf, 0x4fb73f70, 0xde770d29, 0x75733e07, - 0xb9945779, 0xde4edee4, 0x7b13e379, 0xf1867d74, 0x897dac1d, 0xfefde923, - 0xcb80febf, 0x002220b3, 0x00000000 -}; - -#endif /*__BNX2X_INIT_VALUES_H__*/ -- cgit v1.2.3 From 56ed4351c2604c221a82276f51e5dfd467921bf3 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Mon, 27 Apr 2009 03:28:25 -0700 Subject: bnx2x: driver version 1.48.105-1 Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index cdc80e0820cd..a669bb7eb00c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -56,8 +56,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.48.105" -#define DRV_MODULE_RELDATE "2009/03/02" +#define DRV_MODULE_VERSION "1.48.105-1" +#define DRV_MODULE_RELDATE "2009/04/22" #define BNX2X_BC_VER 0x040200 #include -- cgit v1.2.3 From edbd9e30306067c3a45c035eb95a6f49daaa2337 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 27 Apr 2009 05:44:29 -0700 Subject: gro: Fix handling of headers that extend over the tail The skb_gro_* code fails to handle the case where a header starts in the linear area but ends in the frags area. Since the goal of skb_gro_* is to optimise the case of completely non-linear packets, we can simply bail out if we have anything in the linear area. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- net/core/dev.c | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 31167451d08d..c9ef41916071 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1137,7 +1137,7 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb) static inline void *skb_gro_mac_header(struct sk_buff *skb) { - return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) : + return skb_headlen(skb) ? skb_mac_header(skb) : page_address(skb_shinfo(skb)->frags[0].page) + skb_shinfo(skb)->frags[0].page_offset; } diff --git a/net/core/dev.c b/net/core/dev.c index e48c08af76ad..6785b067ad50 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2378,18 +2378,13 @@ void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) unsigned int offset = skb_gro_offset(skb); hlen += offset; - if (hlen <= skb_headlen(skb)) - return skb->data + offset; - - if (unlikely(!skb_shinfo(skb)->nr_frags || - skb_shinfo(skb)->frags[0].size <= - hlen - skb_headlen(skb) || + if (unlikely(skb_headlen(skb) || + skb_shinfo(skb)->frags[0].size < hlen || PageHighMem(skb_shinfo(skb)->frags[0].page))) return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; return page_address(skb_shinfo(skb)->frags[0].page) + - skb_shinfo(skb)->frags[0].page_offset + - offset - skb_headlen(skb); + skb_shinfo(skb)->frags[0].page_offset + offset; } EXPORT_SYMBOL(skb_gro_header); -- cgit v1.2.3 From 36e7b1b8dac1a785abca3a121b6b0b79f1a8d7df Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 27 Apr 2009 05:44:45 -0700 Subject: gro: Fix COMPLETE checksum handling On a brand new GRO skb, we cannot call ip_hdr since the header may lie in the non-linear area. This patch adds the helper skb_gro_network_header to handle this. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 7 +++++++ net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c9ef41916071..fe20d171acf1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1142,6 +1142,13 @@ static inline void *skb_gro_mac_header(struct sk_buff *skb) skb_shinfo(skb)->frags[0].page_offset; } +static inline void *skb_gro_network_header(struct sk_buff *skb) +{ + return skb_headlen(skb) ? skb_network_header(skb) : + page_address(skb_shinfo(skb)->frags[0].page) + + skb_shinfo(skb)->frags[0].page_offset + skb_network_offset(skb); +} + static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5d427f86b414..bda74e8aed7e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2343,7 +2343,7 @@ void tcp4_proc_exit(void) struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct iphdr *iph = ip_hdr(skb); + struct iphdr *iph = skb_gro_network_header(skb); switch (skb->ip_summed) { case CHECKSUM_COMPLETE: diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4b5aa1854260..d9dd94b6bf66 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -943,7 +943,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct ipv6hdr *iph = ipv6_hdr(skb); + struct ipv6hdr *iph = skb_gro_network_header(skb); switch (skb->ip_summed) { case CHECKSUM_COMPLETE: -- cgit v1.2.3 From 52fbc1007eb071c40a367462476eee695b412578 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Mon, 27 Apr 2009 19:42:03 +0000 Subject: atl1c: disable L1/L0s when link detected Disable L1/L0s when link detected. We enable L1/L0s when link connected before, but there is some hareware error on some platform. So just diable this feature when link connected. This feature is about power saving. Signed-off-by: Jie Yang Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c_main.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index deb7b53167ee..8b17278c4a58 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -220,11 +220,11 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) /* link down */ if (netif_carrier_ok(netdev)) { hw->hibernate = true; - atl1c_set_aspm(hw, false); if (atl1c_stop_mac(hw) != 0) if (netif_msg_hw(adapter)) dev_warn(&pdev->dev, "stop mac failed\n"); + atl1c_set_aspm(hw, false); } netif_carrier_off(netdev); } else { @@ -240,10 +240,10 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) adapter->link_duplex != duplex) { adapter->link_speed = speed; adapter->link_duplex = duplex; + atl1c_set_aspm(hw, true); atl1c_enable_tx_ctrl(hw); atl1c_enable_rx_ctrl(hw); atl1c_setup_mac_ctrl(adapter); - atl1c_set_aspm(hw, true); if (netif_msg_link(adapter)) dev_info(&pdev->dev, "%s: %s NIC Link is Up<%d Mbps %s>\n", @@ -1242,9 +1242,7 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - pm_ctrl_data &= PM_CTRL_SERDES_PD_EX_L1; - pm_ctrl_data |= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; - pm_ctrl_data |= ~PM_CTRL_SERDES_L1_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << PM_CTRL_L1_ENTRY_TIMER_SHIFT); @@ -1254,19 +1252,11 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; - if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) { - pm_ctrl_data |= AT_ASPM_L1_TIMER << - PM_CTRL_L1_ENTRY_TIMER_SHIFT; - pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; - } else - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - - if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; - else - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - + pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; + pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; } else { + pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; -- cgit v1.2.3 From 833cc67c7722e35863c6aaee9df56b442ef957ae Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 27 Apr 2009 21:32:16 +0000 Subject: smsc911x: add fifo byteswap support V2 This is V2 of the smsc911x fifo byteswap patch. The smsc911x hardware supports both big and little and endian hardware configurations, and the linux smsc911x driver currently detects word order. For correct operation on big endian platforms lacking swapped byte lanes the following patch is needed. Only fifo data is swapped, register data does not require any swapping. Signed-off-by: Magnus Damm Acked-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 13 +++++++++++++ include/linux/smsc911x.h | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index eb7db032a780..5113b26fc2d9 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include "smsc911x.h" @@ -175,6 +176,12 @@ static inline void smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, unsigned int wordcount) { + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { + while (wordcount--) + smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++)); + return; + } + if (pdata->config.flags & SMSC911X_USE_32BIT) { writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount); return; @@ -194,6 +201,12 @@ static inline void smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, unsigned int wordcount) { + if (pdata->config.flags & SMSC911X_SWAP_FIFO) { + while (wordcount--) + *buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO)); + return; + } + if (pdata->config.flags & SMSC911X_USE_32BIT) { readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount); return; diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index b32725075d71..5241e4fb4eca 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -47,4 +47,14 @@ struct smsc911x_platform_config { #define SMSC911X_FORCE_EXTERNAL_PHY (BIT(3)) #define SMSC911X_SAVE_MAC_ADDRESS (BIT(4)) +/* + * SMSC911X_SWAP_FIFO: + * Enables software byte swap for fifo data. Should only be used as a + * "last resort" in the case of big endian mode on boards with incorrectly + * routed data bus to older devices such as LAN9118. Newer devices such as + * LAN9221 can handle this in hardware, there are registers to control + * this swapping but the driver doesn't currently use them. + */ +#define SMSC911X_SWAP_FIFO (BIT(5)) + #endif /* __LINUX_SMSC911X_H__ */ -- cgit v1.2.3 From 3935358ebcb8320965478c0e8ee070e1d65851c8 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 27 Apr 2009 22:34:54 +0000 Subject: igb: reconfigure mailbox timeout logic This change updates the timeout logic so that it is not possible to have a sucessful check for message and still return an error if countdown = 0. Signed-off-by: Alexander Duyck Reported-by: Juha Leppanen Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_mbx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c index 840782fb5736..ed9058eca45c 100644 --- a/drivers/net/igb/e1000_mbx.c +++ b/drivers/net/igb/e1000_mbx.c @@ -140,13 +140,13 @@ static s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; - if (!mbx->ops.check_for_msg) + if (!countdown || !mbx->ops.check_for_msg) goto out; while (mbx->ops.check_for_msg(hw, mbx_id)) { + countdown--; if (!countdown) break; - countdown--; udelay(mbx->usec_delay); } out: @@ -165,13 +165,13 @@ static s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; - if (!mbx->ops.check_for_ack) + if (!countdown || !mbx->ops.check_for_ack) goto out; while (mbx->ops.check_for_ack(hw, mbx_id)) { + countdown--; if (!countdown) break; - countdown--; udelay(mbx->usec_delay); } out: -- cgit v1.2.3 From 2844f7975837d47fe7f20aa96c1df3bcecf91935 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 27 Apr 2009 22:35:14 +0000 Subject: igb: make rxcsum configuration seperate from multiqueue The igb driver was being incorrectly setup to only allow disabling receive checksum if multiqueue was disabled. This change corrects that so that RXCSUM is configured regardless of queue configuration. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_defines.h | 2 +- drivers/net/igb/igb_main.c | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index ad2d319d0f8b..65acbbaca2d5 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -289,8 +289,8 @@ #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 /* Receive Checksum Control */ +#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ #define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ab846ec65204..4ecf4dfce9bd 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2236,29 +2236,21 @@ static void igb_configure_rx(struct igb_adapter *adapter) mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX | E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); - wr32(E1000_MRQC, mrqc); - - /* Multiqueue and raw packet checksumming are mutually - * exclusive. Note that this not the same as TCP/IP - * checksumming, which works fine. */ - rxcsum = rd32(E1000_RXCSUM); - rxcsum |= E1000_RXCSUM_PCSD; - wr32(E1000_RXCSUM, rxcsum); - } else { + } else if (adapter->vfs_allocated_count) { /* Enable multi-queue for sr-iov */ - if (adapter->vfs_allocated_count) - wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ); - /* Enable Receive Checksum Offload for TCP and UDP */ - rxcsum = rd32(E1000_RXCSUM); - if (adapter->rx_csum) - rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE; - else - rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE); - - wr32(E1000_RXCSUM, rxcsum); + wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ); } + /* Enable Receive Checksum Offload for TCP and UDP */ + rxcsum = rd32(E1000_RXCSUM); + /* Disable raw packet checksumming */ + rxcsum |= E1000_RXCSUM_PCSD; + /* Don't need to set TUOFL or IPOFL, they default to 1 */ + if (!adapter->rx_csum) + rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL); + wr32(E1000_RXCSUM, rxcsum); + /* Set the default pool for the PF's first queue */ igb_configure_vt_default_pool(adapter); -- cgit v1.2.3 From 182ff8dfdb63e66ca81e4d3a4c746f8d578e5687 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 27 Apr 2009 22:35:33 +0000 Subject: igb/ixgbe: remove unecessary checks for CHECKSUM_UNNECESSARY Both of these drivers do a check to verify ip_summed is set to CHECKSUM_UNNECESSARY prior to passing the packet to GRO. GRO itself already does such a check so it is redundant and can be removed as this will likely cause out of order issues when receiving a packet that didn't pass checksum validation. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 20 ++++++-------------- drivers/net/ixgbe/ixgbe_main.c | 17 +++++------------ 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 4ecf4dfce9bd..f7f861215242 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4430,20 +4430,12 @@ static void igb_receive_skb(struct igb_ring *ring, u8 status, bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP)); skb_record_rx_queue(skb, ring->queue_index); - if (skb->ip_summed == CHECKSUM_UNNECESSARY) { - if (vlan_extracted) - vlan_gro_receive(&ring->napi, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.upper.vlan), - skb); - else - napi_gro_receive(&ring->napi, skb); - } else { - if (vlan_extracted) - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->wb.upper.vlan)); - else - netif_receive_skb(skb); - } + if (vlan_extracted) + vlan_gro_receive(&ring->napi, adapter->vlgrp, + le16_to_cpu(rx_desc->wb.upper.vlan), + skb); + else + napi_gro_receive(&ring->napi, skb); } static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c45e4e7999ea..42b803d5cfd3 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -459,23 +459,16 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]); - if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag != 0)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); else napi_gro_receive(napi, skb); } else { - if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { - if (adapter->vlgrp && is_vlan && (tag != 0)) - vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag); - else - netif_receive_skb(skb); - } else { - if (adapter->vlgrp && is_vlan && (tag != 0)) - vlan_hwaccel_rx(skb, adapter->vlgrp, tag); - else - netif_rx(skb); - } + if (adapter->vlgrp && is_vlan && (tag != 0)) + vlan_hwaccel_rx(skb, adapter->vlgrp, tag); + else + netif_rx(skb); } } -- cgit v1.2.3 From 8dc92f7e2ecfd93f5c57da78594a7a5482e2c15e Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 27 Apr 2009 22:35:52 +0000 Subject: sctp: add feature bit for SCTP offload in hardware this is the sctp code to enable hardware crc32c offload for adapters that support it. Originally by: Vlad Yasevich modified by Jesse Brandeburg Signed-off-by: Jesse Brandeburg Signed-off-by: Vlad Yasevich Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 ++ net/sctp/output.c | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index fe20d171acf1..f8c3619d551f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -670,7 +670,9 @@ struct net_device #define NETIF_F_GRO 16384 /* Generic receive offload */ #define NETIF_F_LRO 32768 /* large receive offload */ +/* the GSO_MASK reserves bits 16 through 23 */ #define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */ +#define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 diff --git a/net/sctp/output.c b/net/sctp/output.c index 7d08f522ec84..f0c91df59d4e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -412,6 +412,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) /* Build the SCTP header. */ sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); + skb_reset_transport_header(nskb); sh->source = htons(packet->source_port); sh->dest = htons(packet->destination_port); @@ -527,15 +528,25 @@ int sctp_packet_transmit(struct sctp_packet *packet) * Note: Adler-32 is no longer applicable, as has been replaced * by CRC32-C as described in . */ - if (!sctp_checksum_disable && !(dst->dev->features & NETIF_F_NO_CSUM)) { + if (!sctp_checksum_disable && + !(dst->dev->features & (NETIF_F_NO_CSUM | NETIF_F_SCTP_CSUM))) { __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); /* 3) Put the resultant value into the checksum field in the * common header, and leave the rest of the bits unchanged. */ sh->checksum = sctp_end_cksum(crc32); - } else - nskb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + if (dst->dev->features & NETIF_F_SCTP_CSUM) { + /* no need to seed psuedo checksum for SCTP */ + nskb->ip_summed = CHECKSUM_PARTIAL; + nskb->csum_start = (skb_transport_header(nskb) - + nskb->head); + nskb->csum_offset = offsetof(struct sctphdr, checksum); + } else { + nskb->ip_summed = CHECKSUM_UNNECESSARY; + } + } /* IP layer ECN support * From RFC 2481 -- cgit v1.2.3 From b9473560c6d882e0fbd3a8817e906c847b11c722 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 27 Apr 2009 22:36:13 +0000 Subject: igb: Enable SCTP checksum offloading Originally from: Vlad Yasevich This patch, both the driver portion and the sctp code was modified by Jesse Brandeburg and is Copyright(c) 2009 Intel Corporation. Thanks go to Vlad for starting this work. Intel 82576 chipset supports SCTP checksum offloading. This patch enables this functionality in the driver. A new NETIF feature is introduced for SCTP checksum offload. If the driver supports CRC32c checksum, it can set this feature flag. The hardware can offload both transmit and receive. Signed-off-by: Jesse Brandeburg Signed-off-by: Vlad Yasevich Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.h | 1 + drivers/net/igb/e1000_defines.h | 1 + drivers/net/igb/igb_ethtool.c | 12 +++++++++--- drivers/net/igb/igb_main.c | 21 ++++++++++++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index eaf977050368..0f16abab2565 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -130,6 +130,7 @@ struct e1000_adv_tx_context_desc { #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ +#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */ /* IPSec Encrypt Enable for ESP */ #define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 65acbbaca2d5..3bda3db73f1f 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -291,6 +291,7 @@ /* Receive Checksum Control */ #define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ +#define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ #define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 27eae49e79c2..b1367ce6586e 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -293,10 +293,16 @@ static u32 igb_get_tx_csum(struct net_device *netdev) static int igb_set_tx_csum(struct net_device *netdev, u32 data) { - if (data) + struct igb_adapter *adapter = netdev_priv(netdev); + + if (data) { netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + if (adapter->hw.mac.type == e1000_82576) + netdev->features |= NETIF_F_SCTP_CSUM; + } else { + netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_SCTP_CSUM); + } return 0; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f7f861215242..bca7e9f76be4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1345,6 +1345,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + if (adapter->hw.mac.type == e1000_82576) + netdev->features |= NETIF_F_SCTP_CSUM; + adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw); /* before reading the NVM, reset the controller to put the device in a @@ -2249,6 +2252,10 @@ static void igb_configure_rx(struct igb_adapter *adapter) /* Don't need to set TUOFL or IPOFL, they default to 1 */ if (!adapter->rx_csum) rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL); + else if (adapter->hw.mac.type == e1000_82576) + /* Enable Receive Checksum Offload for SCTP */ + rxcsum |= E1000_RXCSUM_CRCOFL; + wr32(E1000_RXCSUM, rxcsum); /* Set the default pool for the PF's first queue */ @@ -3064,11 +3071,15 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; if (ip_hdr(skb)->protocol == IPPROTO_TCP) tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; + else if (ip_hdr(skb)->protocol == IPPROTO_SCTP) + tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; break; case cpu_to_be16(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; + else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP) + tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; break; default: if (unlikely(net_ratelimit())) @@ -4449,14 +4460,22 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, /* TCP/UDP checksum error bit is set */ if (status_err & (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { + /* + * work around errata with sctp packets where the TCPE aka + * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) + * packets, (aka let the stack check the crc32c) + */ + if (!((adapter->hw.mac.type == e1000_82576) && + (skb->len == 60))) + adapter->hw_csum_err++; /* let the stack verify checksum errors */ - adapter->hw_csum_err++; return; } /* It must be a TCP or UDP packet with a valid checksum */ if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) skb->ip_summed = CHECKSUM_UNNECESSARY; + dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err); adapter->hw_csum_good++; } -- cgit v1.2.3 From 45a5ead0220cc7cc70f6961879decffbd0a54cc0 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 27 Apr 2009 22:36:35 +0000 Subject: ixgbe: enable hardware offload for sctp Inspired by: Vlad Yasevich This is the code to enable ixgbe for hardware offload support of CRC32c on both transmit and receive of SCTP traffic. only 82599 supports this offload, not 82598. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_ethtool.c | 11 +++++++++-- drivers/net/ixgbe/ixgbe_main.c | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index f0a20facc650..a499b6b31ca2 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -311,10 +311,17 @@ static u32 ixgbe_get_tx_csum(struct net_device *netdev) static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data) { - if (data) + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + if (data) { netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + netdev->features |= NETIF_F_SCTP_CSUM; + } else { netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + netdev->features &= ~NETIF_F_SCTP_CSUM; + } return 0; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 42b803d5cfd3..c3dff8f02e33 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4189,12 +4189,18 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, if (ip_hdr(skb)->protocol == IPPROTO_TCP) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + else if (ip_hdr(skb)->protocol == IPPROTO_SCTP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_SCTP; break; case cpu_to_be16(ETH_P_IPV6): /* XXX what about other V6 headers?? */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_SCTP; break; default: if (unlikely(net_ratelimit())) { @@ -4718,6 +4724,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_TSO6; netdev->features |= NETIF_F_GRO; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + netdev->features |= NETIF_F_SCTP_CSUM; + netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_IP_CSUM; -- cgit v1.2.3 From f8212f979f777af2a8e3a9deb0c11a9fcf35e305 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 27 Apr 2009 22:42:37 +0000 Subject: ixgbe: enable HW RSC for 82599 This patch enables hardware receive side coalescing for 82599 hardware. 82599 can merge multiple frames from the same TCP/IP flow into a single structure that can span one ore more descriptors. The accumulated data is arranged similar to how jumbo frames are arranged with the exception that other packets can be interlaced inbetween. To overcome this issue a next pointer is included in the written back descriptor which indicates the next descriptor in the writeback sequence. This feature sets the NETIF_F_LRO flag and clearing it via the ethtool set flags operation will also disable hardware RSC. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 4 ++ drivers/net/ixgbe/ixgbe_ethtool.c | 24 +++++++- drivers/net/ixgbe/ixgbe_main.c | 121 ++++++++++++++++++++++++++++++++++---- drivers/net/ixgbe/ixgbe_type.h | 15 +++++ 4 files changed, 152 insertions(+), 12 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index c26433d14605..4b44a8efac8c 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -147,6 +147,7 @@ struct ixgbe_ring { u16 work_limit; /* max work per interrupt */ u16 rx_buf_len; + u64 rsc_count; /* stat for coalesced packets */ }; enum ixgbe_ring_f_enum { @@ -294,6 +295,8 @@ struct ixgbe_adapter { #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23) #define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 24) #define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 25) +#define IXGBE_FLAG_RSC_CAPABLE (u32)(1 << 26) +#define IXGBE_FLAG_RSC_ENABLED (u32)(1 << 27) /* default to trying for four seconds */ #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) @@ -325,6 +328,7 @@ struct ixgbe_adapter { struct timer_list sfp_timer; struct work_struct multispeed_fiber_task; struct work_struct sfp_config_module_task; + u64 rsc_count; u32 wol; u16 eeprom_version; }; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index a499b6b31ca2..d822c92058c3 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -67,6 +67,7 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"rx_over_errors", IXGBE_STAT(net_stats.rx_over_errors)}, {"rx_crc_errors", IXGBE_STAT(net_stats.rx_crc_errors)}, {"rx_frame_errors", IXGBE_STAT(net_stats.rx_frame_errors)}, + {"hw_rsc_count", IXGBE_STAT(rsc_count)}, {"rx_fifo_errors", IXGBE_STAT(net_stats.rx_fifo_errors)}, {"rx_missed_errors", IXGBE_STAT(net_stats.rx_missed_errors)}, {"tx_aborted_errors", IXGBE_STAT(net_stats.tx_aborted_errors)}, @@ -1127,6 +1128,27 @@ static int ixgbe_set_coalesce(struct net_device *netdev, return 0; } +static int ixgbe_set_flags(struct net_device *netdev, u32 data) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + ethtool_op_set_flags(netdev, data); + + if (!(adapter->flags & IXGBE_FLAG_RSC_CAPABLE)) + return 0; + + /* if state changes we need to update adapter->flags and reset */ + if ((!!(data & ETH_FLAG_LRO)) != + (!!(adapter->flags & IXGBE_FLAG_RSC_ENABLED))) { + adapter->flags ^= IXGBE_FLAG_RSC_ENABLED; + if (netif_running(netdev)) + ixgbe_reinit_locked(adapter); + else + ixgbe_reset(adapter); + } + return 0; + +} static const struct ethtool_ops ixgbe_ethtool_ops = { .get_settings = ixgbe_get_settings, @@ -1161,7 +1183,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .get_coalesce = ixgbe_get_coalesce, .set_coalesce = ixgbe_set_coalesce, .get_flags = ethtool_op_get_flags, - .set_flags = ethtool_op_set_flags, + .set_flags = ixgbe_set_flags, }; void ixgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c3dff8f02e33..419ce472cef8 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -615,6 +615,40 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; } +static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc) +{ + return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) & + IXGBE_RXDADV_RSCCNT_MASK) >> + IXGBE_RXDADV_RSCCNT_SHIFT; +} + +/** + * ixgbe_transform_rsc_queue - change rsc queue into a full packet + * @skb: pointer to the last skb in the rsc queue + * + * This function changes a queue full of hw rsc buffers into a completed + * packet. It uses the ->prev pointers to find the first packet and then + * turns it into the frag list owner. + **/ +static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb) +{ + unsigned int frag_list_size = 0; + + while (skb->prev) { + struct sk_buff *prev = skb->prev; + frag_list_size += skb->len; + skb->prev = NULL; + skb = prev; + } + + skb_shinfo(skb)->frag_list = skb->next; + skb->next = NULL; + skb->len += frag_list_size; + skb->data_len += frag_list_size; + skb->truesize += frag_list_size; + return skb; +} + static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) @@ -624,7 +658,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, union ixgbe_adv_rx_desc *rx_desc, *next_rxd; struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer; struct sk_buff *skb; - unsigned int i; + unsigned int i, rsc_count = 0; u32 len, staterr; u16 hdr_info; bool cleaned = false; @@ -690,20 +724,38 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, i++; if (i == rx_ring->count) i = 0; - next_buffer = &rx_ring->rx_buffer_info[i]; next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i); prefetch(next_rxd); - cleaned_count++; + + if (adapter->flags & IXGBE_FLAG_RSC_CAPABLE) + rsc_count = ixgbe_get_rsc_count(rx_desc); + + if (rsc_count) { + u32 nextp = (staterr & IXGBE_RXDADV_NEXTP_MASK) >> + IXGBE_RXDADV_NEXTP_SHIFT; + next_buffer = &rx_ring->rx_buffer_info[nextp]; + rx_ring->rsc_count += (rsc_count - 1); + } else { + next_buffer = &rx_ring->rx_buffer_info[i]; + } + if (staterr & IXGBE_RXD_STAT_EOP) { + if (skb->prev) + skb = ixgbe_transform_rsc_queue(skb); rx_ring->stats.packets++; rx_ring->stats.bytes += skb->len; } else { - rx_buffer_info->skb = next_buffer->skb; - rx_buffer_info->dma = next_buffer->dma; - next_buffer->skb = skb; - next_buffer->dma = 0; + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + rx_buffer_info->skb = next_buffer->skb; + rx_buffer_info->dma = next_buffer->dma; + next_buffer->skb = skb; + next_buffer->dma = 0; + } else { + skb->next = next_buffer->skb; + skb->next->prev = skb; + } adapter->non_eop_descs++; goto next_desc; } @@ -733,7 +785,7 @@ next_desc: /* use prefetched values */ rx_desc = next_rxd; - rx_buffer_info = next_buffer; + rx_buffer_info = &rx_ring->rx_buffer_info[i]; staterr = le32_to_cpu(rx_desc->wb.upper.status_error); } @@ -1729,6 +1781,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) u32 fctrl, hlreg0; u32 reta = 0, mrqc = 0; u32 rdrxctl; + u32 rscctrl; int rx_buf_len; /* Decide whether to use packet split mode or not */ @@ -1746,7 +1799,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); } } else { - if (netdev->mtu <= ETH_DATA_LEN) + if (!(adapter->flags & IXGBE_FLAG_RSC_ENABLED) && + (netdev->mtu <= ETH_DATA_LEN)) rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; else rx_buf_len = ALIGN(max_frame, 1024); @@ -1868,8 +1922,38 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82599EB) { rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; + rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } + + if (adapter->flags & IXGBE_FLAG_RSC_ENABLED) { + /* Enable 82599 HW-RSC */ + for (i = 0; i < adapter->num_rx_queues; i++) { + j = adapter->rx_ring[i].reg_idx; + rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); + rscctrl |= IXGBE_RSCCTL_RSCEN; + /* + * if packet split is enabled we can only support up + * to max frags + 1 descriptors. + */ + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) +#if (MAX_SKB_FRAGS < 3) + rscctrl |= IXGBE_RSCCTL_MAXDESC_1; +#elif (MAX_SKB_FRAGS < 7) + rscctrl |= IXGBE_RSCCTL_MAXDESC_4; +#elif (MAX_SKB_FRAGS < 15) + rscctrl |= IXGBE_RSCCTL_MAXDESC_8; +#else + rscctrl |= IXGBE_RSCCTL_MAXDESC_16; +#endif + else + rscctrl |= IXGBE_RSCCTL_MAXDESC_16; + IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl); + } + /* Disable RSC for ACK packets */ + IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, + (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); + } } static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) @@ -2438,8 +2522,13 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_buffer_info->dma = 0; } if (rx_buffer_info->skb) { - dev_kfree_skb(rx_buffer_info->skb); + struct sk_buff *skb = rx_buffer_info->skb; rx_buffer_info->skb = NULL; + do { + struct sk_buff *this = skb; + skb = skb->prev; + dev_kfree_skb(this); + } while (skb); } if (!rx_buffer_info->page) continue; @@ -3180,8 +3269,11 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES; if (hw->mac.type == ixgbe_mac_82598EB) adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; - else if (hw->mac.type == ixgbe_mac_82599EB) + else if (hw->mac.type == ixgbe_mac_82599EB) { adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; + adapter->flags |= IXGBE_FLAG_RSC_CAPABLE; + adapter->flags |= IXGBE_FLAG_RSC_ENABLED; + } #ifdef CONFIG_IXGBE_DCB /* Configure DCB traffic classes */ @@ -3765,9 +3857,13 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; if (hw->mac.type == ixgbe_mac_82599EB) { + u64 rsc_count = 0; for (i = 0; i < 16; i++) adapter->hw_rx_no_dma_resources += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); + for (i = 0; i < adapter->num_rx_queues; i++) + rsc_count += adapter->rx_ring[i].rsc_count; + adapter->rsc_count = rsc_count; } adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); @@ -4742,6 +4838,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + if (adapter->flags & IXGBE_FLAG_RSC_ENABLED) + netdev->features |= NETIF_F_LRO; + /* make sure the EEPROM is good */ if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) { dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n"); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 375f0d4ad965..bdfdf3bca273 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -443,6 +443,21 @@ #define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE 0x4 +/* HW RSC registers */ +#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ + (0x0D02C + ((_i - 64) * 0x40))) +#define IXGBE_RSCDBU 0x03028 +#define IXGBE_RSCCTL_RSCEN 0x01 +#define IXGBE_RSCCTL_MAXDESC_1 0x00 +#define IXGBE_RSCCTL_MAXDESC_4 0x04 +#define IXGBE_RSCCTL_MAXDESC_8 0x08 +#define IXGBE_RSCCTL_MAXDESC_16 0x0C +#define IXGBE_RXDADV_RSCCNT_SHIFT 17 +#define IXGBE_GPIE_RSC_DELAY_SHIFT 11 +#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 +#define IXGBE_RSCDBU_RSCACKDIS 0x00000080 +#define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 + /* DCB registers */ #define IXGBE_RTRPCS 0x02430 #define IXGBE_RTTDCS 0x04900 -- cgit v1.2.3 From 835462fc5d69adc948e8afb2073264888aaa0e2f Mon Sep 17 00:00:00 2001 From: "Nelson, Shannon" Date: Mon, 27 Apr 2009 22:42:54 +0000 Subject: ixgbe: Interrupt management update for 82599 Update the interrupt management to correctly handle greater than 16 queue vectors. Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 90 +++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 419ce472cef8..6c90b6801cbd 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -326,8 +326,18 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, } /* re-arm the interrupt */ - if (count >= tx_ring->work_limit) - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx); + if (count >= tx_ring->work_limit) { + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, + tx_ring->v_idx); + else if (tx_ring->v_idx & 0xFFFFFFFF) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), + tx_ring->v_idx); + else + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), + (tx_ring->v_idx >> 32)); + } + tx_ring->total_bytes += total_bytes; tx_ring->total_packets += total_packets; @@ -1166,7 +1176,13 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); rx_ring = &(adapter->rx_ring[r_idx]); /* disable interrupts on this vector only */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx); + else if (rx_ring->v_idx & 0xFFFFFFFF) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), rx_ring->v_idx); + else + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), + (rx_ring->v_idx >> 32)); napi_schedule(&q_vector->napi); return IRQ_HANDLED; @@ -1180,6 +1196,23 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) return IRQ_HANDLED; } +static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, + u64 qmask) +{ + u32 mask; + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + mask = (IXGBE_EIMS_RTX_QUEUE & qmask); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + } else { + mask = (qmask & 0xFFFFFFFF); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask); + mask = (qmask >> 32); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask); + } + /* skip the flush */ +} + /** * ixgbe_clean_rxonly - msix (aka one shot) rx clean routine * @napi: napi struct with our devices info in it @@ -1212,7 +1245,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx); + ixgbe_irq_enable_queues(adapter, rx_ring->v_idx); } return work_done; @@ -1234,7 +1267,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) struct ixgbe_ring *rx_ring = NULL; int work_done = 0, i; long r_idx; - u16 enable_mask = 0; + u64 enable_mask = 0; /* attempt to distribute budget to each queue fairly, but don't allow * the budget to go below 1 because we'll exit polling */ @@ -1261,7 +1294,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask); + ixgbe_irq_enable_queues(adapter, enable_mask); return 0; } @@ -1481,7 +1514,8 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) { u32 mask; - mask = IXGBE_EIMS_ENABLE_MASK; + + mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) mask |= IXGBE_EIMS_GPI_SDP1; if (adapter->hw.mac.type == ixgbe_mac_82599EB) { @@ -1491,14 +1525,7 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) } IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - /* enable the rest of the queue vectors */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), - (IXGBE_EIMS_RTX_QUEUE << 16)); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), - ((IXGBE_EIMS_RTX_QUEUE << 16) | - IXGBE_EIMS_RTX_QUEUE)); - } + ixgbe_irq_enable_queues(adapter, ~0); IXGBE_WRITE_FLUSH(&adapter->hw); } @@ -1622,10 +1649,12 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) **/ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) { - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); + } else { + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(2), ~0); } IXGBE_WRITE_FLUSH(&adapter->hw); if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { @@ -1637,18 +1666,6 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) } } -static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter) -{ - u32 mask = IXGBE_EIMS_RTX_QUEUE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask << 16); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2), - (mask << 16 | mask)); - } - /* skip the flush */ -} - /** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * @@ -2714,7 +2731,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) if (adapter->itr_setting & 1) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) - ixgbe_irq_enable_queues(adapter); + ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); } return work_done; } @@ -4005,16 +4022,9 @@ static void ixgbe_watchdog(unsigned long data) break; case ixgbe_mac_82599EB: if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - /* - * EICS(0..15) first 0-15 q vectors - * EICS[1] (16..31) q vectors 16-31 - * EICS[2] (0..31) q vectors 32-63 - */ - IXGBE_WRITE_REG(hw, IXGBE_EICS, - (u32)(eics & 0xFFFF)); + IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(0), + (u32)(eics & 0xFFFFFFFF)); IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(1), - (u32)(eics & 0xFFFF0000)); - IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(2), (u32)(eics >> 32)); } else { /* -- cgit v1.2.3 From bc59fcda671ee15362986a902bbd90e218fe84c4 Mon Sep 17 00:00:00 2001 From: "Nelson, Shannon" Date: Mon, 27 Apr 2009 22:43:12 +0000 Subject: ixgbe: Clear out stray tx work on link down Ayyappan at VMware noticed that we're missing this check from ixgbe which is in our other drivers. The difference with this implementation from our other drivers is that this checks all the tx queues rather than just tx[0]. Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 6c90b6801cbd..5020f11ae10f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4110,6 +4110,9 @@ static void ixgbe_watchdog_task(struct work_struct *work) struct ixgbe_hw *hw = &adapter->hw; u32 link_speed = adapter->link_speed; bool link_up = adapter->link_up; + int i; + struct ixgbe_ring *tx_ring; + int some_tx_pending = 0; adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; @@ -4167,6 +4170,25 @@ static void ixgbe_watchdog_task(struct work_struct *work) } } + if (!netif_carrier_ok(netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) { + tx_ring = &adapter->tx_ring[i]; + if (tx_ring->next_to_use != tx_ring->next_to_clean) { + some_tx_pending = 1; + break; + } + } + + if (some_tx_pending) { + /* We've lost link, so the controller stops DMA, + * but we've got queued Tx work that's never going + * to get done, so reset controller to flush Tx. + * (Do the reset outside of interrupt context). + */ + schedule_work(&adapter->reset_task); + } + } + ixgbe_update_stats(adapter); adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK; } -- cgit v1.2.3 From 1d58ea30b141c95bd21fb39021d4b602f48b30be Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 28 Apr 2009 02:05:21 -0700 Subject: fs_enet: Remove dead code CONFIG_DUET doesn't exist anymore, remove all the code that exists to support it. [ Simplify fs_init() even further -DaveM ] Signed-off-by: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/fs_enet/fs_enet-main.c | 39 +------------------------------------- drivers/net/fs_enet/fs_enet.h | 5 ----- drivers/net/fs_enet/mac-fec.c | 34 --------------------------------- 3 files changed, 1 insertion(+), 77 deletions(-) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 9604aaed61d6..b892c3ad9a74 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -941,30 +941,6 @@ extern void fs_mii_disconnect(struct net_device *dev); /**************************************************************************************/ -/* handy pointer to the immap */ -void __iomem *fs_enet_immap = NULL; - -static int setup_immap(void) -{ -#ifdef CONFIG_CPM1 - fs_enet_immap = ioremap(IMAP_ADDR, 0x4000); - WARN_ON(!fs_enet_immap); -#elif defined(CONFIG_CPM2) - fs_enet_immap = cpm2_immr; -#endif - - return 0; -} - -static void cleanup_immap(void) -{ -#if defined(CONFIG_CPM1) - iounmap(fs_enet_immap); -#endif -} - -/**************************************************************************************/ - #ifdef CONFIG_FS_ENET_HAS_FEC #define IS_FEC(match) ((match)->data == &fs_fec_ops) #else @@ -1144,25 +1120,12 @@ static struct of_platform_driver fs_enet_driver = { static int __init fs_init(void) { - int r = setup_immap(); - if (r != 0) - return r; - - r = of_register_platform_driver(&fs_enet_driver); - if (r != 0) - goto out; - - return 0; - -out: - cleanup_immap(); - return r; + return of_register_platform_driver(&fs_enet_driver); } static void __exit fs_cleanup(void) { of_unregister_platform_driver(&fs_enet_driver); - cleanup_immap(); } #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 85a4bab7f630..ef01e09781a5 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -194,9 +194,4 @@ extern const struct fs_ops fs_scc_ops; /*******************************************************************/ -/* handy pointer to the immap */ -extern void __iomem *fs_enet_immap; - -/*******************************************************************/ - #endif diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 14e575313c89..ca7bcb8ab3a1 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -245,10 +245,6 @@ static void set_multicast_list(struct net_device *dev) static void restart(struct net_device *dev) { -#ifdef CONFIG_DUET - immap_t *immap = fs_enet_immap; - u32 cptr; -#endif struct fs_enet_private *fep = netdev_priv(dev); fec_t __iomem *fecp = fep->fec.fecp; const struct fs_platform_info *fpi = fep->fpi; @@ -315,36 +311,6 @@ static void restart(struct net_device *dev) FW(fecp, ievent, 0xffc0); FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); - /* - * adjust to speed (only for DUET & RMII) - */ -#ifdef CONFIG_DUET - if (fpi->use_rmii) { - cptr = in_be32(&immap->im_cpm.cp_cptr); - switch (fs_get_fec_index(fpi->fs_no)) { - case 0: - cptr |= 0x100; - if (fep->speed == 10) - cptr |= 0x0000010; - else if (fep->speed == 100) - cptr &= ~0x0000010; - break; - case 1: - cptr |= 0x80; - if (fep->speed == 10) - cptr |= 0x0000008; - else if (fep->speed == 100) - cptr &= ~0x0000008; - break; - default: - BUG(); /* should never happen */ - break; - } - out_be32(&immap->im_cpm.cp_cptr, cptr); - } -#endif - - FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ /* * adjust to duplex mode -- cgit v1.2.3 From 8555a5948467e941acc34e8b1c30df4c1f2f5862 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 28 Apr 2009 02:11:53 -0700 Subject: net: Fix ucc_geth.c handling of fixed-link w/o phy-connection-type property. Previous rework to ucc_geth.c to add of_mdio support (net: Rework ucc_geth driver to use of_mdio infrastructure) added a block of code which broke older openfirmware device trees which this case. This patch removes the offending blurb. Signed-off-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a53628466637..f18017dc0255 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3631,9 +3631,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma prop = of_get_property(np, "phy-connection-type", NULL); if (!prop) { /* handle interface property present in old trees */ - if (!phy) - return -ENODEV; - prop = of_get_property(phy, "interface", NULL); if (prop != NULL) { phy_interface = enet_to_phy_interface[*prop]; -- cgit v1.2.3 From 6a321cb370ad3db4ba6e405e638b3a42c41089b0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 28 Apr 2009 04:43:42 -0700 Subject: net: netif_tx_queue_stopped too expensive netif_tx_queue_stopped(txq) is most of the time false. Yet its cost is very expensive on SMP. static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue) { return test_bit(__QUEUE_STATE_XOFF, &dev_queue->state); } I saw this on oprofile hunting and bnx2 driver bnx2_tx_int(). We probably should split "struct netdev_queue" in two parts, one being read mostly. __netif_tx_lock() touches _xmit_lock & xmit_lock_owner, these deserve a separate cache line. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f8c3619d551f..505a3c6cb12d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -447,12 +447,18 @@ enum netdev_queue_state_t }; struct netdev_queue { +/* + * read mostly part + */ struct net_device *dev; struct Qdisc *qdisc; unsigned long state; - spinlock_t _xmit_lock; - int xmit_lock_owner; struct Qdisc *qdisc_sleeping; +/* + * write mostly part + */ + spinlock_t _xmit_lock ____cacheline_aligned_in_smp; + int xmit_lock_owner; } ____cacheline_aligned_in_smp; -- cgit v1.2.3 From ac5978e7f83a6cbd9a70282d6e39bd936a31b2bc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 28 Apr 2009 08:03:26 -0700 Subject: inet_diag: Remove dup assignments These are later assigned to other values without being used meanwhile. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 588a7796e3e3..b0b273503e2a 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -198,8 +198,6 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, tmo = 0; r->idiag_family = tw->tw_family; - r->idiag_state = tw->tw_state; - r->idiag_timer = 0; r->idiag_retrans = 0; r->id.idiag_if = tw->tw_bound_dev_if; r->id.idiag_cookie[0] = (u32)(unsigned long)tw; -- cgit v1.2.3 From 6c31d55f755ff2bc1f7dc3b45c500032fe90aff8 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 28 Apr 2009 08:04:10 -0700 Subject: gianfar: Use memset instead of cacheable_memzero cacheable_memzero() is completely overkill for the clearing out the FCB block which is only 8-bytes. The compiler should easily optimize this with memset. Additionally, cacheable_memzero() only exists on ppc32 and thus breaks builds of gianfar on ppc64. Signed-off-by: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index dae14373296a..2bb038b98cc4 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1207,7 +1207,8 @@ static int gfar_enet_open(struct net_device *dev) static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb) { struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN); - cacheable_memzero(fcb, GMAC_FCB_LEN); + + memset(fcb, 0, GMAC_FCB_LEN); return fcb; } -- cgit v1.2.3 From 5103c9f7874506cb40fc3c8d3f22486d3c4d91aa Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 28 Apr 2009 15:29:09 +0000 Subject: netxen: fix link event handling Firmware starting 4.0.402 started supporting link events, disable it for older firmwares. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_ethtool.c | 1 + drivers/net/netxen/netxen_nic_main.c | 2 +- drivers/net/netxen/netxen_nic_phan_reg.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index a452b2facb77..e16ea46c24b8 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -247,6 +247,7 @@ skip: case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: case LINKEVENT_MODULE_TWINAX: ecmd->port = PORT_TP; + break; default: ecmd->port = -1; } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index e877eefdfeb0..8331580fe161 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -797,7 +797,7 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) if (adapter->max_sds_rings > 1) netxen_config_rss(adapter, 1); - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) netxen_linkevent_request(adapter, 1); return 0; diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 845dcf436cf6..b73a62ca74f8 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -126,6 +126,7 @@ #define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) #define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) +#define CRB_FW_CAPABILITIES_1 NETXEN_CAM_RAM(0x128) #define CRB_MAC_BLOCK_START NETXEN_CAM_RAM(0x1c0) /* @@ -136,7 +137,6 @@ #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) #define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) -#define CRB_FW_CAPABILITIES_1 NETXEN_NIC_REG(0x128) #define INTR_SCHEME_PERPORT 0x1 #define MSI_MODE_MULTIFUNC 0x1 -- cgit v1.2.3 From 4ea528a151549df795c984649d75860ea40390bd Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 28 Apr 2009 15:29:10 +0000 Subject: netxen: refactor netxen_recv_context struct o move related fields into netxen_recv_context struct. o allocate rx buffer and descriptor rings dynamically. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 10 ++++---- drivers/net/netxen/netxen_nic_ctx.c | 49 ++++++++++++++++++++---------------- drivers/net/netxen/netxen_nic_hw.c | 2 +- drivers/net/netxen/netxen_nic_init.c | 46 +++++++++++++++++++++++++-------- drivers/net/netxen/netxen_nic_main.c | 4 +-- 5 files changed, 71 insertions(+), 40 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index ebd6c2edc343..16f5e2267eb3 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -775,8 +775,11 @@ struct netxen_recv_context { u16 context_id; u16 virt_port; - struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS]; + struct nx_host_rds_ring *rds_rings; struct nx_host_sds_ring *sds_rings; + + struct netxen_ring_ctx *hwctx; + dma_addr_t phys_addr; }; /* New HW context creation */ @@ -1258,11 +1261,8 @@ struct netxen_adapter { struct netxen_adapter_stats stats; struct netxen_recv_context recv_ctx; - struct nx_host_tx_ring tx_ring; + struct nx_host_tx_ring *tx_ring; - /* Context interface shared between card and host */ - struct netxen_ring_ctx *ctx_desc; - dma_addr_t ctx_desc_phys_addr; int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t); diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index fd82adf4f876..4754f5cffad0 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -323,7 +323,8 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) int err = 0; u64 offset, phys_addr; dma_addr_t rq_phys_addr, rsp_phys_addr; - struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); rq_addr = pci_alloc_consistent(adapter->pdev, @@ -358,7 +359,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr); - offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx); + offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx); prq->cmd_cons_dma_addr = cpu_to_le64(offset); prq_cds = &prq->cds_ring; @@ -541,14 +542,16 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) struct nx_host_tx_ring *tx_ring; int ring; int port = adapter->portnum; - struct netxen_ring_ctx *hwctx = adapter->ctx_desc; + struct netxen_ring_ctx *hwctx; u32 signature; - tx_ring = &adapter->tx_ring; + tx_ring = adapter->tx_ring; + recv_ctx = &adapter->recv_ctx; + hwctx = recv_ctx->hwctx; + hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); - recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; @@ -576,9 +579,9 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE; NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port), - lower32(adapter->ctx_desc_phys_addr)); + lower32(recv_ctx->phys_addr)); NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port), - upper32(adapter->ctx_desc_phys_addr)); + upper32(recv_ctx->phys_addr)); NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), signature | port); return 0; @@ -592,25 +595,28 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; - struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; + struct nx_host_tx_ring *tx_ring; struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; int port = adapter->portnum; + recv_ctx = &adapter->recv_ctx; + tx_ring = adapter->tx_ring; + addr = pci_alloc_consistent(pdev, sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), - &adapter->ctx_desc_phys_addr); - + &recv_ctx->phys_addr); if (addr == NULL) { dev_err(&pdev->dev, "failed to allocate hw context\n"); return -ENOMEM; } + memset(addr, 0, sizeof(struct netxen_ring_ctx)); - adapter->ctx_desc = (struct netxen_ring_ctx *)addr; - adapter->ctx_desc->ctx_id = cpu_to_le32(port); - adapter->ctx_desc->cmd_consumer_offset = - cpu_to_le64(adapter->ctx_desc_phys_addr + + recv_ctx->hwctx = (struct netxen_ring_ctx *)addr; + recv_ctx->hwctx->ctx_id = cpu_to_le32(port); + recv_ctx->hwctx->cmd_consumer_offset = + cpu_to_le64(recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx)); tx_ring->hw_consumer = (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); @@ -627,8 +633,6 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) tx_ring->desc_head = (struct cmd_desc_type0 *)addr; - recv_ctx = &adapter->recv_ctx; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; addr = pci_alloc_consistent(adapter->pdev, @@ -713,16 +717,18 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) netxen_api_unlock(adapter); } - if (adapter->ctx_desc != NULL) { + recv_ctx = &adapter->recv_ctx; + + if (recv_ctx->hwctx != NULL) { pci_free_consistent(adapter->pdev, sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), - adapter->ctx_desc, - adapter->ctx_desc_phys_addr); - adapter->ctx_desc = NULL; + recv_ctx->hwctx, + recv_ctx->phys_addr); + recv_ctx->hwctx = NULL; } - tx_ring = &adapter->tx_ring; + tx_ring = adapter->tx_ring; if (tx_ring->desc_head != NULL) { pci_free_consistent(adapter->pdev, TX_DESC_RINGSIZE(tx_ring), @@ -730,7 +736,6 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) tx_ring->desc_head = NULL; } - recv_ctx = &adapter->recv_ctx; for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 3bb2b8c74d92..db53d9cfad07 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -521,7 +521,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, i = 0; - tx_ring = &adapter->tx_ring; + tx_ring = adapter->tx_ring; netif_tx_lock_bh(adapter->netdev); producer = tx_ring->producer; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 8893a973399a..363ef701e71e 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -137,7 +137,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) struct netxen_cmd_buffer *cmd_buf; struct netxen_skb_frag *buffrag; int i, j; - struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; cmd_buf = tx_ring->cmd_buf_arr; for (i = 0; i < tx_ring->num_desc; i++) { @@ -172,6 +172,10 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) int ring; recv_ctx = &adapter->recv_ctx; + + if (recv_ctx->rds_rings == NULL) + goto skip_rds; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; if (rds_ring->rx_buf_arr) { @@ -179,11 +183,15 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter) rds_ring->rx_buf_arr = NULL; } } + kfree(recv_ctx->rds_rings); + +skip_rds: + if (adapter->tx_ring == NULL) + return; - tx_ring = &adapter->tx_ring; + tx_ring = adapter->tx_ring; if (tx_ring->cmd_buf_arr) vfree(tx_ring->cmd_buf_arr); - return; } int netxen_alloc_sw_resources(struct netxen_adapter *adapter) @@ -191,17 +199,26 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; - struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; + struct nx_host_tx_ring *tx_ring; struct netxen_rx_buffer *rx_buf; - int ring, i, num_rx_bufs; + int ring, i, size; struct netxen_cmd_buffer *cmd_buf_arr; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; + size = sizeof(struct nx_host_tx_ring); + tx_ring = kzalloc(size, GFP_KERNEL); + if (tx_ring == NULL) { + dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n", + netdev->name); + return -ENOMEM; + } + adapter->tx_ring = tx_ring; + tx_ring->num_desc = adapter->num_txd; - cmd_buf_arr = - (struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(tx_ring)); + + cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); if (cmd_buf_arr == NULL) { dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", netdev->name); @@ -211,6 +228,16 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) tx_ring->cmd_buf_arr = cmd_buf_arr; recv_ctx = &adapter->recv_ctx; + + size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring); + rds_ring = kzalloc(size, GFP_KERNEL); + if (rds_ring == NULL) { + dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n", + netdev->name); + return -ENOMEM; + } + recv_ctx->rds_rings = rds_ring; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { rds_ring = &recv_ctx->rds_rings[ring]; switch (ring) { @@ -262,9 +289,8 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) * Now go through all of them, set reference handles * and put them in the queues. */ - num_rx_bufs = rds_ring->num_desc; rx_buf = rds_ring->rx_buf_arr; - for (i = 0; i < num_rx_bufs; i++) { + for (i = 0; i < rds_ring->num_desc; i++) { list_add_tail(&rx_buf->list, &rds_ring->free_list); rx_buf->ref_handle = i; @@ -1064,7 +1090,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct netxen_skb_frag *frag; int done = 0; - struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; if (!spin_trylock(&adapter->tx_clean_lock)) return 1; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 8331580fe161..07959fe06f22 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -857,7 +857,7 @@ netxen_nic_attach(struct netxen_adapter *adapter) } if (adapter->fw_major < 4) { - tx_ring = &adapter->tx_ring; + tx_ring = adapter->tx_ring; tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum]; tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum]; @@ -1315,7 +1315,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct nx_host_tx_ring *tx_ring = &adapter->tx_ring; + struct nx_host_tx_ring *tx_ring = adapter->tx_ring; unsigned int first_seg_len = skb->len - skb->data_len; struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; -- cgit v1.2.3 From f7185c71234434d48b96f9a0387737df1759a4af Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 28 Apr 2009 15:29:11 +0000 Subject: netxen: fix firmware download o hold the firmware in memory across suspend, since filesystem may not be up after resuming. o reset the chip after requesting firmware, to minimize downtime for NC-SI. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 9 +- drivers/net/netxen/netxen_nic_hw.c | 195 ---------------------------------- drivers/net/netxen/netxen_nic_init.c | 196 +++++++++++++++++++++++++++++++++++ drivers/net/netxen/netxen_nic_main.c | 23 ++-- 4 files changed, 216 insertions(+), 207 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 16f5e2267eb3..8dacfbb003e2 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -1255,8 +1256,6 @@ struct netxen_adapter { u32 flags; u32 irq; u32 temp; - u32 fw_major; - u32 fw_version; struct netxen_adapter_stats stats; @@ -1295,6 +1294,10 @@ struct netxen_adapter { struct net_device_stats net_stats; nx_nic_intr_coalesce_t coal; + + u32 fw_major; + u32 fw_version; + const struct firmware *fw; }; /* @@ -1376,6 +1379,8 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); int netxen_load_firmware(struct netxen_adapter *adapter); +void netxen_request_firmware(struct netxen_adapter *adapter); +void netxen_release_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index db53d9cfad07..9f5ced3eaf9d 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -32,7 +32,6 @@ #include "netxen_nic_hw.h" #include "netxen_nic_phan_reg.h" -#include #include #define MASK(n) ((1ULL<<(n))-1) @@ -1016,200 +1015,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) (ulong)adapter->ahw.pci_base0; } -static int -netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, - const struct firmware *fw) -{ - u64 *ptr64; - u32 i, flashaddr, size; - struct pci_dev *pdev = adapter->pdev; - - if (fw) - dev_info(&pdev->dev, "loading firmware from file %s\n", fwname); - else - dev_info(&pdev->dev, "loading firmware from flash\n"); - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); - - if (fw) { - __le64 data; - - size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; - - ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; - flashaddr = NETXEN_BOOTLD_START; - - for (i = 0; i < size; i++) { - data = cpu_to_le64(ptr64[i]); - adapter->pci_mem_write(adapter, flashaddr, &data, 8); - flashaddr += 8; - } - - size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; - size = (__force u32)cpu_to_le32(size) / 8; - - ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; - flashaddr = NETXEN_IMAGE_START; - - for (i = 0; i < size; i++) { - data = cpu_to_le64(ptr64[i]); - - if (adapter->pci_mem_write(adapter, - flashaddr, &data, 8)) - return -EIO; - - flashaddr += 8; - } - } else { - u32 data; - - size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; - flashaddr = NETXEN_BOOTLD_START; - - for (i = 0; i < size; i++) { - if (netxen_rom_fast_read(adapter, - flashaddr, (int *)&data) != 0) - return -EIO; - - if (adapter->pci_mem_write(adapter, - flashaddr, &data, 4)) - return -EIO; - - flashaddr += 4; - } - } - msleep(1); - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); - else { - NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); - NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); - } - - return 0; -} - -static int -netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, - const struct firmware *fw) -{ - __le32 val; - u32 major, minor, build, ver, min_ver, bios; - struct pci_dev *pdev = adapter->pdev; - - if (fw->size < NX_FW_MIN_SIZE) - return -EINVAL; - - val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); - if ((__force u32)val != NETXEN_BDINFO_MAGIC) - return -EINVAL; - - val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - min_ver = NETXEN_VERSION_CODE(4, 0, 216); - else - min_ver = NETXEN_VERSION_CODE(3, 4, 216); - - ver = NETXEN_VERSION_CODE(major, minor, build); - - if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { - dev_err(&pdev->dev, - "%s: firmware version %d.%d.%d unsupported\n", - fwname, major, minor, build); - return -EINVAL; - } - - val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); - netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); - if ((__force u32)val != bios) { - dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", - fwname); - return -EINVAL; - } - - /* check if flashed firmware is newer */ - if (netxen_rom_fast_read(adapter, - NX_FW_VERSION_OFFSET, (int *)&val)) - return -EIO; - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; - if (NETXEN_VERSION_CODE(major, minor, build) > ver) - return -EINVAL; - - NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); - return 0; -} - -static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; - -int netxen_load_firmware(struct netxen_adapter *adapter) -{ - u32 capability, flashed_ver; - const struct firmware *fw; - int fw_type; - struct pci_dev *pdev = adapter->pdev; - int rc = 0; - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - fw_type = NX_P2_MN_ROMIMAGE; - goto request_fw; - } else { - fw_type = NX_P3_CT_ROMIMAGE; - goto request_fw; - } - -request_mn: - capability = 0; - - netxen_rom_fast_read(adapter, - NX_FW_VERSION_OFFSET, (int *)&flashed_ver); - if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { - capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); - if (capability & NX_PEG_TUNE_MN_PRESENT) { - fw_type = NX_P3_MN_ROMIMAGE; - goto request_fw; - } - } - -request_fw: - rc = request_firmware(&fw, fw_name[fw_type], &pdev->dev); - if (rc != 0) { - if (fw_type == NX_P3_CT_ROMIMAGE) { - msleep(1); - goto request_mn; - } - - fw = NULL; - goto load_fw; - } - - rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw); - if (rc != 0) { - release_firmware(fw); - - if (fw_type == NX_P3_CT_ROMIMAGE) { - msleep(1); - goto request_mn; - } - - fw = NULL; - } - -load_fw: - rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw); - - if (fw) - release_firmware(fw); - return rc; -} - int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) { diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 363ef701e71e..d18216779a09 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -683,6 +683,202 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) return 0; } +int +netxen_load_firmware(struct netxen_adapter *adapter) +{ + u64 *ptr64; + u32 i, flashaddr, size; + const struct firmware *fw = adapter->fw; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); + + if (fw) { + __le64 data; + + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; + + ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; + flashaddr = NETXEN_BOOTLD_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + adapter->pci_mem_write(adapter, flashaddr, &data, 8); + flashaddr += 8; + } + + size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; + size = (__force u32)cpu_to_le32(size) / 8; + + ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; + flashaddr = NETXEN_IMAGE_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + + if (adapter->pci_mem_write(adapter, + flashaddr, &data, 8)) + return -EIO; + + flashaddr += 8; + } + } else { + u32 data; + + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; + flashaddr = NETXEN_BOOTLD_START; + + for (i = 0; i < size; i++) { + if (netxen_rom_fast_read(adapter, + flashaddr, (int *)&data) != 0) + return -EIO; + + if (adapter->pci_mem_write(adapter, + flashaddr, &data, 4)) + return -EIO; + + flashaddr += 4; + } + } + msleep(1); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); + else { + NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); + } + + return 0; +} + +static int +netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) +{ + __le32 val; + u32 major, minor, build, ver, min_ver, bios; + struct pci_dev *pdev = adapter->pdev; + const struct firmware *fw = adapter->fw; + + if (fw->size < NX_FW_MIN_SIZE) + return -EINVAL; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); + if ((__force u32)val != NETXEN_BDINFO_MAGIC) + return -EINVAL; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); + major = (__force u32)val & 0xff; + minor = ((__force u32)val >> 8) & 0xff; + build = (__force u32)val >> 16; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + min_ver = NETXEN_VERSION_CODE(4, 0, 216); + else + min_ver = NETXEN_VERSION_CODE(3, 4, 216); + + ver = NETXEN_VERSION_CODE(major, minor, build); + + if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { + dev_err(&pdev->dev, + "%s: firmware version %d.%d.%d unsupported\n", + fwname, major, minor, build); + return -EINVAL; + } + + val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); + netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); + if ((__force u32)val != bios) { + dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", + fwname); + return -EINVAL; + } + + /* check if flashed firmware is newer */ + if (netxen_rom_fast_read(adapter, + NX_FW_VERSION_OFFSET, (int *)&val)) + return -EIO; + major = (__force u32)val & 0xff; + minor = ((__force u32)val >> 8) & 0xff; + build = (__force u32)val >> 16; + if (NETXEN_VERSION_CODE(major, minor, build) > ver) + return -EINVAL; + + NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + return 0; +} + +static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; + +void netxen_request_firmware(struct netxen_adapter *adapter) +{ + u32 capability, flashed_ver; + int fw_type; + struct pci_dev *pdev = adapter->pdev; + int rc = 0; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + fw_type = NX_P2_MN_ROMIMAGE; + goto request_fw; + } else { + fw_type = NX_P3_CT_ROMIMAGE; + goto request_fw; + } + +request_mn: + capability = 0; + + netxen_rom_fast_read(adapter, + NX_FW_VERSION_OFFSET, (int *)&flashed_ver); + if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { + capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); + if (capability & NX_PEG_TUNE_MN_PRESENT) { + fw_type = NX_P3_MN_ROMIMAGE; + goto request_fw; + } + } + +request_fw: + rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); + if (rc != 0) { + if (fw_type == NX_P3_CT_ROMIMAGE) { + msleep(1); + goto request_mn; + } + + adapter->fw = NULL; + goto done; + } + + rc = netxen_validate_firmware(adapter, fw_name[fw_type]); + if (rc != 0) { + release_firmware(adapter->fw); + + if (fw_type == NX_P3_CT_ROMIMAGE) { + msleep(1); + goto request_mn; + } + + adapter->fw = NULL; + goto done; + } + +done: + if (adapter->fw) + dev_info(&pdev->dev, "loading firmware from file %s\n", + fw_name[fw_type]); + else + dev_info(&pdev->dev, "loading firmware from flash\n"); +} + + +void +netxen_release_firmware(struct netxen_adapter *adapter) +{ + if (adapter->fw) + release_firmware(adapter->fw); +} + int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) { uint64_t addr; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 07959fe06f22..5d79c19a6ec0 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -654,19 +654,17 @@ err_out: } static int -netxen_start_firmware(struct netxen_adapter *adapter) +netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) { int val, err, first_boot; struct pci_dev *pdev = adapter->pdev; int first_driver = 0; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - if (adapter->ahw.pci_func == 0) - first_driver = 1; - } else { - if (adapter->portnum == 0) - first_driver = 1; - } + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + first_driver = (adapter->portnum == 0); + else + first_driver = (adapter->ahw.pci_func == 0); if (!first_driver) return 0; @@ -679,6 +677,9 @@ netxen_start_firmware(struct netxen_adapter *adapter) return err; } + if (request_fw) + netxen_request_firmware(adapter); + if (first_boot != 0x55555555) { NXWR32(adapter, CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); @@ -1014,7 +1015,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - err = netxen_start_firmware(adapter); + err = netxen_start_firmware(adapter, 1); if (err) goto err_out_iounmap; @@ -1125,6 +1126,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_cleanup_pci_map(adapter); + netxen_release_firmware(adapter); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); @@ -1176,7 +1179,7 @@ netxen_nic_resume(struct pci_dev *pdev) adapter->curr_window = 255; - err = netxen_start_firmware(adapter); + err = netxen_start_firmware(adapter, 0); if (err) { dev_err(&pdev->dev, "failed to start firmware\n"); return err; -- cgit v1.2.3 From dd4d8ca6446538a904127838cb6c9a4cffe690f7 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 29 Apr 2009 00:22:31 -0700 Subject: ixgbe: Use pci_wake_from_d3() instead of multiple pci_enable_wake() We were calling pci_enable_wake() twice in a row for both D3_hot and D3_cold. This replaces those calls with a call to pci_wake_from_d3() to avoid issues with PCI PM vs ordering constraints. Signed-off-by: Don Skidmore Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5020f11ae10f..01a88265d401 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3738,8 +3738,7 @@ static int ixgbe_resume(struct pci_dev *pdev) } pci_set_master(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); + pci_wake_from_d3(pdev, false); err = ixgbe_init_interrupt_scheme(adapter); if (err) { @@ -3813,13 +3812,10 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0); } - if (wufc && hw->mac.type == ixgbe_mac_82599EB) { - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } + if (wufc && hw->mac.type == ixgbe_mac_82599EB) + pci_wake_from_d3(pdev, true); + else + pci_wake_from_d3(pdev, false); *enable_wake = !!wufc; @@ -5101,8 +5097,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); + pci_wake_from_d3(pdev, false); ixgbe_reset(adapter); IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); -- cgit v1.2.3 From ce105a082371570effb71541f299b1dc2771ee03 Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Wed, 29 Apr 2009 17:22:30 -0700 Subject: pcnet32: Remove pointless memory barriers These two memory barriers in performance-critical paths are not needed on x86. Even if some other architecture does buffer PCI I/O space writes, the existing memory-mapped I/O barriers are unlikely to be what is needed. Signed-off-by: John Dykstra Acked-by: Don Fry Signed-off-by: David S. Miller --- drivers/net/pcnet32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index e5e8c59243b6..1c35e1d637a0 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1405,7 +1405,7 @@ static int pcnet32_poll(struct napi_struct *napi, int budget) /* Set interrupt enable. */ lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); - mmiowb(); + spin_unlock_irqrestore(&lp->lock, flags); } return work_done; @@ -2597,7 +2597,7 @@ pcnet32_interrupt(int irq, void *dev_id) val = lp->a.read_csr(ioaddr, CSR3); val |= 0x5f00; lp->a.write_csr(ioaddr, CSR3, val); - mmiowb(); + __napi_schedule(&lp->napi); break; } -- cgit v1.2.3 From 0821c71751ef88f4251d7206e76ce497ee267a2d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:02:59 +0000 Subject: ethtool: Add port type PORT_OTHER Add a PORT_OTHER to represent all other physical port types. Current NICs generally do not allow switching between multiple port types in software so specific types should not be needed. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 131b127b70f8..5ccb6bd660c7 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -605,6 +605,7 @@ struct ethtool_ops { #define PORT_MII 0x02 #define PORT_FIBRE 0x03 #define PORT_BNC 0x04 +#define PORT_OTHER 0xff /* Which transceiver to use. */ #define XCVR_INTERNAL 0x00 -- cgit v1.2.3 From 52c94dfae11d9ffd70b7bd003a36a4e210f2866a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:04:14 +0000 Subject: mdio: Add register definitions for MDIO (clause 45) IEEE 802.3 clause 45 specifies the MDIO interface and registers for use in 10G and other PHYs, similar to the MII management interface. PHYs may have up to 32 MMDs corresponding to different sub-layers and functions, each with up to 65536 registers. These are addressed by PRTAD (similar to the MII PHY address) and DEVAD. Define a mapping for specifying PRTAD and DEVAD through the existing MII ioctls. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/mdio.h | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 include/linux/mdio.h diff --git a/include/linux/mdio.h b/include/linux/mdio.h new file mode 100644 index 000000000000..d57ddb08a1b2 --- /dev/null +++ b/include/linux/mdio.h @@ -0,0 +1,237 @@ +/* + * linux/mdio.h: definitions for MDIO (clause 45) transceivers + * Copyright 2006-2009 Solarflare Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#ifndef __LINUX_MDIO_H__ +#define __LINUX_MDIO_H__ + +#include + +/* MDIO Manageable Devices (MMDs). */ +#define MDIO_MMD_PMAPMD 1 /* Physical Medium Attachment/ + * Physical Medium Dependent */ +#define MDIO_MMD_WIS 2 /* WAN Interface Sublayer */ +#define MDIO_MMD_PCS 3 /* Physical Coding Sublayer */ +#define MDIO_MMD_PHYXS 4 /* PHY Extender Sublayer */ +#define MDIO_MMD_DTEXS 5 /* DTE Extender Sublayer */ +#define MDIO_MMD_TC 6 /* Transmission Convergence */ +#define MDIO_MMD_AN 7 /* Auto-Negotiation */ +#define MDIO_MMD_C22EXT 29 /* Clause 22 extension */ +#define MDIO_MMD_VEND1 30 /* Vendor specific 1 */ +#define MDIO_MMD_VEND2 31 /* Vendor specific 2 */ + +/* Generic MDIO registers. */ +#define MDIO_CTRL1 MII_BMCR +#define MDIO_STAT1 MII_BMSR +#define MDIO_DEVID1 MII_PHYSID1 +#define MDIO_DEVID2 MII_PHYSID2 +#define MDIO_SPEED 4 /* Speed ability */ +#define MDIO_DEVS1 5 /* Devices in package */ +#define MDIO_DEVS2 6 +#define MDIO_CTRL2 7 /* 10G control 2 */ +#define MDIO_STAT2 8 /* 10G status 2 */ +#define MDIO_PMA_TXDIS 9 /* 10G PMA/PMD transmit disable */ +#define MDIO_PMA_RXDET 10 /* 10G PMA/PMD receive signal detect */ +#define MDIO_PMA_EXTABLE 11 /* 10G PMA/PMD extended ability */ +#define MDIO_PKGID1 14 /* Package identifier */ +#define MDIO_PKGID2 15 +#define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ +#define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ +#define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ + +/* Media-dependent registers. */ +#define MDIO_PMA_10GBT_TXPWR 131 /* 10GBASE-T TX power control */ +#define MDIO_PCS_10GBX_STAT1 24 /* 10GBASE-X PCS status 1 */ +#define MDIO_PCS_10GBRT_STAT1 32 /* 10GBASE-R/-T PCS status 1 */ +#define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */ +#define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */ +#define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */ + +/* Control register 1. */ +/* Enable extended speed selection */ +#define MDIO_CTRL1_SPEEDSELEXT (BMCR_SPEED1000 | BMCR_SPEED100) +/* All speed selection bits */ +#define MDIO_CTRL1_SPEEDSEL (MDIO_CTRL1_SPEEDSELEXT | 0x003c) +#define MDIO_CTRL1_FULLDPLX BMCR_FULLDPLX +#define MDIO_CTRL1_LPOWER BMCR_PDOWN +#define MDIO_CTRL1_RESET BMCR_RESET +#define MDIO_PMA_CTRL1_LOOPBACK 0x0001 +#define MDIO_PMA_CTRL1_SPEED1000 BMCR_SPEED1000 +#define MDIO_PMA_CTRL1_SPEED100 BMCR_SPEED100 +#define MDIO_PCS_CTRL1_LOOPBACK BMCR_LOOPBACK +#define MDIO_PHYXS_CTRL1_LOOPBACK BMCR_LOOPBACK +#define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART +#define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE +#define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */ + +/* 10 Gb/s */ +#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00) +/* 10PASS-TS/2BASE-TL */ +#define MDIO_CTRL1_SPEED10P2B (MDIO_CTRL1_SPEEDSELEXT | 0x04) + +/* Status register 1. */ +#define MDIO_STAT1_LPOWERABLE 0x0002 /* Low-power ability */ +#define MDIO_STAT1_LSTATUS BMSR_LSTATUS +#define MDIO_STAT1_FAULT 0x0080 /* Fault */ +#define MDIO_AN_STAT1_LPABLE 0x0001 /* Link partner AN ability */ +#define MDIO_AN_STAT1_ABLE BMSR_ANEGCAPABLE +#define MDIO_AN_STAT1_RFAULT BMSR_RFAULT +#define MDIO_AN_STAT1_COMPLETE BMSR_ANEGCOMPLETE +#define MDIO_AN_STAT1_PAGE 0x0040 /* Page received */ +#define MDIO_AN_STAT1_XNP 0x0080 /* Extended next page status */ + +/* Speed register. */ +#define MDIO_SPEED_10G 0x0001 /* 10G capable */ +#define MDIO_PMA_SPEED_2B 0x0002 /* 2BASE-TL capable */ +#define MDIO_PMA_SPEED_10P 0x0004 /* 10PASS-TS capable */ +#define MDIO_PMA_SPEED_1000 0x0010 /* 1000M capable */ +#define MDIO_PMA_SPEED_100 0x0020 /* 100M capable */ +#define MDIO_PMA_SPEED_10 0x0040 /* 10M capable */ +#define MDIO_PCS_SPEED_10P2B 0x0002 /* 10PASS-TS/2BASE-TL capable */ + +/* Device present registers. */ +#define MDIO_DEVS_PRESENT(devad) (1 << (devad)) +#define MDIO_DEVS_PMAPMD MDIO_DEVS_PRESENT(MDIO_MMD_PMAPMD) +#define MDIO_DEVS_WIS MDIO_DEVS_PRESENT(MDIO_MMD_WIS) +#define MDIO_DEVS_PCS MDIO_DEVS_PRESENT(MDIO_MMD_PCS) +#define MDIO_DEVS_PHYXS MDIO_DEVS_PRESENT(MDIO_MMD_PHYXS) +#define MDIO_DEVS_DTEXS MDIO_DEVS_PRESENT(MDIO_MMD_DTEXS) +#define MDIO_DEVS_TC MDIO_DEVS_PRESENT(MDIO_MMD_TC) +#define MDIO_DEVS_AN MDIO_DEVS_PRESENT(MDIO_MMD_AN) +#define MDIO_DEVS_C22EXT MDIO_DEVS_PRESENT(MDIO_MMD_C22EXT) + +/* Control register 2. */ +#define MDIO_PMA_CTRL2_TYPE 0x000f /* PMA/PMD type selection */ +#define MDIO_PMA_CTRL2_10GBCX4 0x0000 /* 10GBASE-CX4 type */ +#define MDIO_PMA_CTRL2_10GBEW 0x0001 /* 10GBASE-EW type */ +#define MDIO_PMA_CTRL2_10GBLW 0x0002 /* 10GBASE-LW type */ +#define MDIO_PMA_CTRL2_10GBSW 0x0003 /* 10GBASE-SW type */ +#define MDIO_PMA_CTRL2_10GBLX4 0x0004 /* 10GBASE-LX4 type */ +#define MDIO_PMA_CTRL2_10GBER 0x0005 /* 10GBASE-ER type */ +#define MDIO_PMA_CTRL2_10GBLR 0x0006 /* 10GBASE-LR type */ +#define MDIO_PMA_CTRL2_10GBSR 0x0007 /* 10GBASE-SR type */ +#define MDIO_PMA_CTRL2_10GBLRM 0x0008 /* 10GBASE-LRM type */ +#define MDIO_PMA_CTRL2_10GBT 0x0009 /* 10GBASE-T type */ +#define MDIO_PMA_CTRL2_10GBKX4 0x000a /* 10GBASE-KX4 type */ +#define MDIO_PMA_CTRL2_10GBKR 0x000b /* 10GBASE-KR type */ +#define MDIO_PMA_CTRL2_1000BT 0x000c /* 1000BASE-T type */ +#define MDIO_PMA_CTRL2_1000BKX 0x000d /* 1000BASE-KX type */ +#define MDIO_PMA_CTRL2_100BTX 0x000e /* 100BASE-TX type */ +#define MDIO_PMA_CTRL2_10BT 0x000f /* 10BASE-T type */ +#define MDIO_PCS_CTRL2_TYPE 0x0003 /* PCS type selection */ +#define MDIO_PCS_CTRL2_10GBR 0x0000 /* 10GBASE-R type */ +#define MDIO_PCS_CTRL2_10GBX 0x0001 /* 10GBASE-X type */ +#define MDIO_PCS_CTRL2_10GBW 0x0002 /* 10GBASE-W type */ +#define MDIO_PCS_CTRL2_10GBT 0x0003 /* 10GBASE-T type */ + +/* Status register 2. */ +#define MDIO_STAT2_RXFAULT 0x0400 /* Receive fault */ +#define MDIO_STAT2_TXFAULT 0x0800 /* Transmit fault */ +#define MDIO_STAT2_DEVPRST 0xc000 /* Device present */ +#define MDIO_STAT2_DEVPRST_VAL 0x8000 /* Device present value */ +#define MDIO_PMA_STAT2_LBABLE 0x0001 /* PMA loopback ability */ +#define MDIO_PMA_STAT2_10GBEW 0x0002 /* 10GBASE-EW ability */ +#define MDIO_PMA_STAT2_10GBLW 0x0004 /* 10GBASE-LW ability */ +#define MDIO_PMA_STAT2_10GBSW 0x0008 /* 10GBASE-SW ability */ +#define MDIO_PMA_STAT2_10GBLX4 0x0010 /* 10GBASE-LX4 ability */ +#define MDIO_PMA_STAT2_10GBER 0x0020 /* 10GBASE-ER ability */ +#define MDIO_PMA_STAT2_10GBLR 0x0040 /* 10GBASE-LR ability */ +#define MDIO_PMA_STAT2_10GBSR 0x0080 /* 10GBASE-SR ability */ +#define MDIO_PMD_STAT2_TXDISAB 0x0100 /* PMD TX disable ability */ +#define MDIO_PMA_STAT2_EXTABLE 0x0200 /* Extended abilities */ +#define MDIO_PMA_STAT2_RXFLTABLE 0x1000 /* Receive fault ability */ +#define MDIO_PMA_STAT2_TXFLTABLE 0x2000 /* Transmit fault ability */ +#define MDIO_PCS_STAT2_10GBR 0x0001 /* 10GBASE-R capable */ +#define MDIO_PCS_STAT2_10GBX 0x0002 /* 10GBASE-X capable */ +#define MDIO_PCS_STAT2_10GBW 0x0004 /* 10GBASE-W capable */ +#define MDIO_PCS_STAT2_RXFLTABLE 0x1000 /* Receive fault ability */ +#define MDIO_PCS_STAT2_TXFLTABLE 0x2000 /* Transmit fault ability */ + +/* Transmit disable register. */ +#define MDIO_PMD_TXDIS_GLOBAL 0x0001 /* Global PMD TX disable */ +#define MDIO_PMD_TXDIS_0 0x0002 /* PMD TX disable 0 */ +#define MDIO_PMD_TXDIS_1 0x0004 /* PMD TX disable 1 */ +#define MDIO_PMD_TXDIS_2 0x0008 /* PMD TX disable 2 */ +#define MDIO_PMD_TXDIS_3 0x0010 /* PMD TX disable 3 */ + +/* Receive signal detect register. */ +#define MDIO_PMD_RXDET_GLOBAL 0x0001 /* Global PMD RX signal detect */ +#define MDIO_PMD_RXDET_0 0x0002 /* PMD RX signal detect 0 */ +#define MDIO_PMD_RXDET_1 0x0004 /* PMD RX signal detect 1 */ +#define MDIO_PMD_RXDET_2 0x0008 /* PMD RX signal detect 2 */ +#define MDIO_PMD_RXDET_3 0x0010 /* PMD RX signal detect 3 */ + +/* Extended abilities register. */ +#define MDIO_PMA_EXTABLE_10GCX4 0x0001 /* 10GBASE-CX4 ability */ +#define MDIO_PMA_EXTABLE_10GBLRM 0x0002 /* 10GBASE-LRM ability */ +#define MDIO_PMA_EXTABLE_10GBT 0x0004 /* 10GBASE-T ability */ +#define MDIO_PMA_EXTABLE_10GBKX4 0x0008 /* 10GBASE-KX4 ability */ +#define MDIO_PMA_EXTABLE_10GBKR 0x0010 /* 10GBASE-KR ability */ +#define MDIO_PMA_EXTABLE_1000BT 0x0020 /* 1000BASE-T ability */ +#define MDIO_PMA_EXTABLE_1000BKX 0x0040 /* 1000BASE-KX ability */ +#define MDIO_PMA_EXTABLE_100BTX 0x0080 /* 100BASE-TX ability */ +#define MDIO_PMA_EXTABLE_10BT 0x0100 /* 10BASE-T ability */ + +/* PHY XGXS lane state register. */ +#define MDIO_PHYXS_LNSTAT_SYNC0 0x0001 +#define MDIO_PHYXS_LNSTAT_SYNC1 0x0002 +#define MDIO_PHYXS_LNSTAT_SYNC2 0x0004 +#define MDIO_PHYXS_LNSTAT_SYNC3 0x0008 +#define MDIO_PHYXS_LNSTAT_ALIGN 0x1000 + +/* PMA 10GBASE-T TX power register. */ +#define MDIO_PMA_10GBT_TXPWR_SHORT 0x0001 /* Short-reach mode */ + +/* PCS 10GBASE-R/-T status register 1. */ +#define MDIO_PCS_10GBRT_STAT1_BLKLK 0x0001 /* Block lock attained */ + +/* PCS 10GBASE-R/-T status register 2. */ +#define MDIO_PCS_10GBRT_STAT2_ERR 0x00ff +#define MDIO_PCS_10GBRT_STAT2_BER 0x3f00 + +/* AN 10GBASE-T control register. */ +#define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */ + +/* AN 10GBASE-T status register. */ +#define MDIO_AN_10GBT_STAT_LPTRR 0x0200 /* LP training reset req. */ +#define MDIO_AN_10GBT_STAT_LPLTABLE 0x0400 /* LP loop timing ability */ +#define MDIO_AN_10GBT_STAT_LP10G 0x0800 /* LP is 10GBT capable */ +#define MDIO_AN_10GBT_STAT_REMOK 0x1000 /* Remote OK */ +#define MDIO_AN_10GBT_STAT_LOCOK 0x2000 /* Local OK */ +#define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */ +#define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */ + +/* Mapping between MDIO PRTAD/DEVAD and mii_ioctl_data::phy_id */ + +#define MDIO_PHY_ID_C45 0x8000 +#define MDIO_PHY_ID_PRTAD 0x03e0 +#define MDIO_PHY_ID_DEVAD 0x001f +#define MDIO_PHY_ID_C45_MASK \ + (MDIO_PHY_ID_C45 | MDIO_PHY_ID_PRTAD | MDIO_PHY_ID_DEVAD) + +static inline __u16 mdio_phy_id_c45(int prtad, int devad) +{ + return MDIO_PHY_ID_C45 | (prtad << 5) | devad; +} + +static inline bool mdio_phy_id_is_c45(int phy_id) +{ + return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK); +} + +static inline __u16 mdio_phy_id_prtad(int phy_id) +{ + return (phy_id & MDIO_PHY_ID_PRTAD) >> 5; +} + +static inline __u16 mdio_phy_id_devad(int phy_id) +{ + return phy_id & MDIO_PHY_ID_DEVAD; +} + +#endif /* __LINUX_MDIO_H__ */ -- cgit v1.2.3 From 1b1c2e95103ce391c2ea39a9460968fcb73deb30 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:04:46 +0000 Subject: mdio: Add generic MDIO (clause 45) support functions These roughly mirror many of the MII library functions and are based on code from the sfc driver. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/Kconfig | 3 + drivers/net/Makefile | 1 + drivers/net/mdio.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mdio.h | 66 ++++++++++ 4 files changed, 429 insertions(+) create mode 100644 drivers/net/mdio.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bc7eef12d955..2f81db51b45d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2443,6 +2443,9 @@ menuconfig NETDEV_10000 if NETDEV_10000 +config MDIO + tristate + config CHELSIO_T1 tristate "Chelsio 10Gb Ethernet support" depends on PCI diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 80420f6d0795..dcd5f15dd9e3 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_SH_ETH) += sh_eth.o # obj-$(CONFIG_MII) += mii.o +obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_SUNDANCE) += sundance.o diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c new file mode 100644 index 000000000000..0604a25748ee --- /dev/null +++ b/drivers/net/mdio.c @@ -0,0 +1,359 @@ +/* + * mdio.c: Generic support for MDIO-compatible transceivers + * Copyright 2006-2009 Solarflare Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include +#include +#include +#include +#include +#include + +/** + * mdio45_probe - probe for an MDIO (clause 45) device + * @mdio: MDIO interface + * @prtad: Expected PHY address + * + * This sets @prtad and @mmds in the MDIO interface if successful. + * Returns 0 on success, negative on error. + */ +int mdio45_probe(struct mdio_if_info *mdio, int prtad) +{ + int mmd, stat2, devs1, devs2; + + /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY + * XS or DTE XS; give up if none is present. */ + for (mmd = 1; mmd <= 5; mmd++) { + /* Is this MMD present? */ + stat2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_STAT2); + if (stat2 < 0 || + (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) + continue; + + /* It should tell us about all the other MMDs */ + devs1 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS1); + devs2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS2); + if (devs1 < 0 || devs2 < 0) + continue; + + mdio->prtad = prtad; + mdio->mmds = devs1 | (devs2 << 16); + return 0; + } + + return -ENODEV; +} +EXPORT_SYMBOL(mdio45_probe); + +/** + * mdio_set_flag - set or clear flag in an MDIO register + * @mdio: MDIO interface + * @prtad: PHY address + * @devad: MMD address + * @addr: Register address + * @mask: Mask for flag (single bit set) + * @sense: New value of flag + * + * This debounces changes: it does not write the register if the flag + * already has the proper value. Returns 0 on success, negative on error. + */ +int mdio_set_flag(const struct mdio_if_info *mdio, + int prtad, int devad, u16 addr, int mask, + bool sense) +{ + int old_val = mdio->mdio_read(mdio->dev, prtad, devad, addr); + int new_val; + + if (old_val < 0) + return old_val; + if (sense) + new_val = old_val | mask; + else + new_val = old_val & ~mask; + if (old_val == new_val) + return 0; + return mdio->mdio_write(mdio->dev, prtad, devad, addr, new_val); +} +EXPORT_SYMBOL(mdio_set_flag); + +/** + * mdio_link_ok - is link status up/OK + * @mdio: MDIO interface + * @mmd_mask: Mask for MMDs to check + * + * Returns 1 if the PHY reports link status up/OK, 0 otherwise. + * @mmd_mask is normally @mdio->mmds, but if loopback is enabled + * the MMDs being bypassed should be excluded from the mask. + */ +int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmd_mask) +{ + int devad, reg; + + if (!mmd_mask) { + /* Use absence of XGMII faults in lieu of link state */ + reg = mdio->mdio_read(mdio->dev, mdio->prtad, + MDIO_MMD_PHYXS, MDIO_STAT2); + return reg >= 0 && !(reg & MDIO_STAT2_RXFAULT); + } + + for (devad = 0; mmd_mask; devad++) { + if (mmd_mask & (1 << devad)) { + mmd_mask &= ~(1 << devad); + + /* Read twice because link state is latched and a + * read moves the current state into the register */ + mdio->mdio_read(mdio->dev, mdio->prtad, + devad, MDIO_STAT1); + reg = mdio->mdio_read(mdio->dev, mdio->prtad, + devad, MDIO_STAT1); + if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) + return false; + } + } + + return true; +} +EXPORT_SYMBOL(mdio45_links_ok); + +/** + * mdio45_nway_restart - restart auto-negotiation for this interface + * @mdio: MDIO interface + * + * Returns 0 on success, negative on error. + */ +int mdio45_nway_restart(const struct mdio_if_info *mdio) +{ + if (!(mdio->mmds & MDIO_DEVS_AN)) + return -EOPNOTSUPP; + + mdio_set_flag(mdio, mdio->prtad, MDIO_MMD_AN, MDIO_CTRL1, + MDIO_AN_CTRL1_RESTART, true); + return 0; +} +EXPORT_SYMBOL(mdio45_nway_restart); + +static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr) +{ + u32 result = 0; + int reg; + + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, addr); + if (reg & ADVERTISE_10HALF) + result |= ADVERTISED_10baseT_Half; + if (reg & ADVERTISE_10FULL) + result |= ADVERTISED_10baseT_Full; + if (reg & ADVERTISE_100HALF) + result |= ADVERTISED_100baseT_Half; + if (reg & ADVERTISE_100FULL) + result |= ADVERTISED_100baseT_Full; + return result; +} + +/** + * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET + * @mdio: MDIO interface + * @ecmd: Ethtool request structure + * @npage_adv: Modes currently advertised on next pages + * @npage_lpa: Modes advertised by link partner on next pages + * + * Since the CSRs for auto-negotiation using next pages are not fully + * standardised, this function does not attempt to decode them. The + * caller must pass them in. + */ +void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, + struct ethtool_cmd *ecmd, + u32 npage_adv, u32 npage_lpa) +{ + int reg; + + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = mdio->prtad; + + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_CTRL2); + switch (reg & MDIO_PMA_CTRL2_TYPE) { + case MDIO_PMA_CTRL2_10GBT: + case MDIO_PMA_CTRL2_1000BT: + case MDIO_PMA_CTRL2_100BTX: + case MDIO_PMA_CTRL2_10BT: + ecmd->port = PORT_TP; + ecmd->supported = SUPPORTED_TP; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_SPEED); + if (reg & MDIO_SPEED_10G) + ecmd->supported |= SUPPORTED_10000baseT_Full; + if (reg & MDIO_PMA_SPEED_1000) + ecmd->supported |= (SUPPORTED_1000baseT_Full | + SUPPORTED_1000baseT_Half); + if (reg & MDIO_PMA_SPEED_100) + ecmd->supported |= (SUPPORTED_100baseT_Full | + SUPPORTED_100baseT_Half); + if (reg & MDIO_PMA_SPEED_10) + ecmd->supported |= (SUPPORTED_10baseT_Full | + SUPPORTED_10baseT_Half); + ecmd->advertising = ADVERTISED_TP; + break; + + case MDIO_PMA_CTRL2_10GBCX4: + case MDIO_PMA_CTRL2_10GBKX4: + case MDIO_PMA_CTRL2_10GBKR: + case MDIO_PMA_CTRL2_1000BKX: + ecmd->port = PORT_OTHER; + ecmd->supported = 0; + ecmd->advertising = 0; + break; + + /* All the other defined modes are flavours of optical */ + default: + ecmd->port = PORT_FIBRE; + ecmd->supported = SUPPORTED_FIBRE; + ecmd->advertising = ADVERTISED_FIBRE; + break; + } + + if (mdio->mmds & MDIO_DEVS_AN) { + ecmd->supported |= SUPPORTED_Autoneg; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_CTRL1); + if (reg & MDIO_AN_CTRL1_ENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->advertising |= + ADVERTISED_Autoneg | + mdio45_get_an(mdio, MDIO_AN_ADVERTISE) | + npage_adv; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + } + } else { + ecmd->autoneg = AUTONEG_DISABLE; + } + + if (ecmd->autoneg) { + u32 modes = 0; + + /* If AN is complete and successful, report best common + * mode, otherwise report best advertised mode. */ + if (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_STAT1) & + MDIO_AN_STAT1_COMPLETE) + modes = (ecmd->advertising & + (mdio45_get_an(mdio, MDIO_AN_LPA) | + npage_lpa)); + if (modes == 0) + modes = ecmd->advertising; + + if (modes & ADVERTISED_10000baseT_Full) { + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + } else if (modes & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { + ecmd->speed = SPEED_1000; + ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); + } else if (modes & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { + ecmd->speed = SPEED_100; + ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); + } else { + ecmd->speed = SPEED_10; + ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); + } + } else { + /* Report forced settings */ + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_CTRL1); + ecmd->speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) * + ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10)); + ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX || + ecmd->speed == SPEED_10000); + } +} +EXPORT_SYMBOL(mdio45_ethtool_gset_npage); + +/** + * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs + * @mdio: MDIO interface + * @mii_data: MII ioctl data structure + * @cmd: MII ioctl command + * + * Returns 0 on success, negative on error. + */ +int mdio_mii_ioctl(const struct mdio_if_info *mdio, + struct mii_ioctl_data *mii_data, int cmd) +{ + int prtad, devad; + u16 addr = mii_data->reg_num; + + /* Validate/convert cmd to one of SIOC{G,S}MIIREG */ + switch (cmd) { + case SIOCGMIIPHY: + if (mdio->prtad == MDIO_PRTAD_NONE) + return -EOPNOTSUPP; + mii_data->phy_id = mdio->prtad; + cmd = SIOCGMIIREG; + break; + case SIOCGMIIREG: + break; + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + break; + default: + return -EOPNOTSUPP; + } + + /* Validate/convert phy_id */ + if ((mdio->mode_support & MDIO_SUPPORTS_C45) && + mdio_phy_id_is_c45(mii_data->phy_id)) { + prtad = mdio_phy_id_prtad(mii_data->phy_id); + devad = mdio_phy_id_devad(mii_data->phy_id); + } else if ((mdio->mode_support & MDIO_SUPPORTS_C22) && + mii_data->phy_id < 0x20) { + prtad = mii_data->phy_id; + devad = MDIO_DEVAD_NONE; + addr &= 0x1f; + } else if ((mdio->mode_support & MDIO_EMULATE_C22) && + mdio->prtad != MDIO_PRTAD_NONE && + mii_data->phy_id == mdio->prtad) { + /* Remap commonly-used MII registers. */ + prtad = mdio->prtad; + switch (addr) { + case MII_BMCR: + case MII_BMSR: + case MII_PHYSID1: + case MII_PHYSID2: + devad = __ffs(mdio->mmds); + break; + case MII_ADVERTISE: + case MII_LPA: + if (!(mdio->mmds & MDIO_DEVS_AN)) + return -EINVAL; + devad = MDIO_MMD_AN; + if (addr == MII_ADVERTISE) + addr = MDIO_AN_ADVERTISE; + else + addr = MDIO_AN_LPA; + break; + default: + return -EINVAL; + } + } else { + return -EINVAL; + } + + if (cmd == SIOCGMIIREG) { + int rc = mdio->mdio_read(mdio->dev, prtad, devad, addr); + if (rc < 0) + return rc; + mii_data->val_out = rc; + return 0; + } else { + return mdio->mdio_write(mdio->dev, prtad, devad, addr, + mii_data->val_in); + } +} +EXPORT_SYMBOL(mdio_mii_ioctl); diff --git a/include/linux/mdio.h b/include/linux/mdio.h index d57ddb08a1b2..ba41537eaa8a 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -234,4 +234,70 @@ static inline __u16 mdio_phy_id_devad(int phy_id) return phy_id & MDIO_PHY_ID_DEVAD; } +#ifdef __KERNEL__ + +/** + * struct mdio_if_info - Ethernet controller MDIO interface + * @prtad: PRTAD of the PHY (%MDIO_PRTAD_NONE if not present/unknown) + * @mmds: Mask of MMDs expected to be present in the PHY. This must be + * non-zero unless @prtad = %MDIO_PRTAD_NONE. + * @mode_support: MDIO modes supported. If %MDIO_SUPPORTS_C22 is set then + * MII register access will be passed through with @devad = + * %MDIO_DEVAD_NONE. If %MDIO_EMULATE_C22 is set then access to + * commonly used clause 22 registers will be translated into + * clause 45 registers. + * @dev: Net device structure + * @mdio_read: Register read function; returns value or negative error code + * @mdio_write: Register write function; returns 0 or negative error code + */ +struct mdio_if_info { + int prtad; + u32 __bitwise mmds; + unsigned mode_support; + + struct net_device *dev; + int (*mdio_read)(struct net_device *dev, int prtad, int devad, + u16 addr); + int (*mdio_write)(struct net_device *dev, int prtad, int devad, + u16 addr, u16 val); +}; + +#define MDIO_PRTAD_NONE (-1) +#define MDIO_DEVAD_NONE (-1) +#define MDIO_SUPPORTS_C22 1 +#define MDIO_SUPPORTS_C45 2 +#define MDIO_EMULATE_C22 4 + +struct ethtool_cmd; +struct ethtool_pauseparam; +extern int mdio45_probe(struct mdio_if_info *mdio, int prtad); +extern int mdio_set_flag(const struct mdio_if_info *mdio, + int prtad, int devad, u16 addr, int mask, + bool sense); +extern int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmds); +extern int mdio45_nway_restart(const struct mdio_if_info *mdio); +extern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, + struct ethtool_cmd *ecmd, + u32 npage_adv, u32 npage_lpa); + +/** + * mdio45_ethtool_gset - get settings for ETHTOOL_GSET + * @mdio: MDIO interface + * @ecmd: Ethtool request structure + * + * Since the CSRs for auto-negotiation using next pages are not fully + * standardised, this function does not attempt to decode them. Use + * mdio45_ethtool_gset_npage() to specify advertisement bits from next + * pages. + */ +static inline void mdio45_ethtool_gset(const struct mdio_if_info *mdio, + struct ethtool_cmd *ecmd) +{ + mdio45_ethtool_gset_npage(mdio, ecmd, 0, 0); +} + +extern int mdio_mii_ioctl(const struct mdio_if_info *mdio, + struct mii_ioctl_data *mii_data, int cmd); + +#endif /* __KERNEL__ */ #endif /* __LINUX_MDIO_H__ */ -- cgit v1.2.3 From 68e7f45e118f98b77cfa007aa2d97b5dac69fe6b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:05:08 +0000 Subject: sfc: Use generic MDIO functions and definitions Make use of the newly-added generic MDIO clause 45 support and remove redundant definitions. Add an 'efx_' prefix to the remaining driver-specific MDIO functions and remove arguments which are redundant with efx->mdio.prtad. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/Kconfig | 2 +- drivers/net/sfc/efx.c | 10 +- drivers/net/sfc/ethtool.c | 18 +- drivers/net/sfc/falcon.c | 137 ++++----------- drivers/net/sfc/falcon_hwdefs.h | 3 - drivers/net/sfc/falcon_xmac.c | 2 +- drivers/net/sfc/mdio_10g.c | 379 +++++++++------------------------------- drivers/net/sfc/mdio_10g.h | 281 +++++------------------------ drivers/net/sfc/net_driver.h | 8 +- drivers/net/sfc/selftest.c | 21 ++- drivers/net/sfc/selftest.h | 2 +- drivers/net/sfc/tenxpress.c | 227 ++++++++++-------------- drivers/net/sfc/xenpack.h | 15 +- drivers/net/sfc/xfp_phy.c | 51 +++--- 14 files changed, 311 insertions(+), 845 deletions(-) diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index 12a82966b577..260aafaac235 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig @@ -1,7 +1,7 @@ config SFC tristate "Solarflare Solarstorm SFC4000 support" depends on PCI && INET - select MII + select MDIO select CRC32 select I2C select I2C_ALGOBIT diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 7269a426051c..d3e240b736c7 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1300,10 +1300,16 @@ out_requeue: static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) { struct efx_nic *efx = netdev_priv(net_dev); + struct mii_ioctl_data *data = if_mii(ifr); EFX_ASSERT_RESET_SERIALISED(efx); - return generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL); + /* Convert phy_id from older PRTAD/DEVAD format */ + if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && + (data->phy_id & 0xfc00) == 0x0400) + data->phy_id ^= MDIO_PHY_ID_C45 | 0x0400; + + return mdio_mii_ioctl(&efx->mdio, data, cmd); } /************************************************************************** @@ -1945,7 +1951,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, mutex_init(&efx->mac_lock); efx->mac_op = &efx_dummy_mac_operations; efx->phy_op = &efx_dummy_phy_operations; - efx->mii.dev = net_dev; + efx->mdio.dev = net_dev; INIT_WORK(&efx->phy_work, efx_phy_work); INIT_WORK(&efx->mac_work, efx_mac_work); atomic_set(&efx->netif_stop_count, 1); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 64309f4e8b19..1c7b6849fe01 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "net_driver.h" #include "workarounds.h" @@ -345,8 +346,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, unsigned int n = 0, i; enum efx_loopback_mode mode; - efx_fill_test(n++, strings, data, &tests->mii, - "core", 0, "mii", NULL); + efx_fill_test(n++, strings, data, &tests->mdio, + "core", 0, "mdio", NULL); efx_fill_test(n++, strings, data, &tests->nvram, "core", 0, "nvram", NULL); efx_fill_test(n++, strings, data, &tests->interrupt, @@ -529,14 +530,7 @@ static int efx_ethtool_nway_reset(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, - __ffs(BMCR_ANRESTART), true); - return 0; - } - - return -EOPNOTSUPP; + return mdio45_nway_restart(&efx->mdio); } static u32 efx_ethtool_get_link(struct net_device *net_dev) @@ -689,7 +683,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, return -EINVAL; } - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) && + if (!(efx->phy_op->mmds & MDIO_DEVS_AN) && (wanted_fc & EFX_FC_AUTO)) { EFX_LOG(efx, "PHY does not support flow control " "autonegotiation\n"); @@ -717,7 +711,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, mutex_lock(&efx->mac_lock); efx->wanted_fc = wanted_fc; - mdio_clause45_set_pause(efx); + efx_mdio_set_pause(efx); __efx_reconfigure_port(efx); mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 466a8abb0053..c049364aec46 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -2063,26 +2063,6 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) ************************************************************************** */ -/* Use the top bit of the MII PHY id to indicate the PHY type - * (1G/10G), with the remaining bits as the actual PHY id. - * - * This allows us to avoid leaking information from the mii_if_info - * structure into other data structures. - */ -#define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR) -#define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1) -#define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1) -#define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1) -#define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1)) - - -/* Packing the clause 45 port and device fields into a single value */ -#define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN) -#define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH -#define MD_DEV_ADR_COMP_LBN 0 -#define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH - - /* Wait for GMII access to complete */ static int falcon_gmii_wait(struct efx_nic *efx) { @@ -2108,49 +2088,29 @@ static int falcon_gmii_wait(struct efx_nic *efx) return -ETIMEDOUT; } -/* Writes a GMII register of a PHY connected to Falcon using MDIO. */ -static void falcon_mdio_write(struct net_device *net_dev, int phy_id, - int addr, int value) +/* Write an MDIO register of a PHY connected to Falcon. */ +static int falcon_mdio_write(struct net_device *net_dev, + int prtad, int devad, u16 addr, u16 value) { struct efx_nic *efx = netdev_priv(net_dev); - unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK; efx_oword_t reg; + int rc; - /* The 'generic' prt/dev packing in mdio_10g.h is conveniently - * chosen so that the only current user, Falcon, can take the - * packed value and use them directly. - * Fail to build if this assumption is broken. - */ - BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G); - BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH); - BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN); - BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN); - - if (phy_id2 == PHY_ADDR_INVALID) - return; - - /* See falcon_mdio_read for an explanation. */ - if (!(phy_id & FALCON_PHY_ID_10G)) { - int mmd = ffs(efx->phy_op->mmds) - 1; - EFX_TRACE(efx, "Fixing erroneous clause22 write\n"); - phy_id2 = mdio_clause45_pack(phy_id2, mmd) - & FALCON_PHY_ID_ID_MASK; - } - - EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id, - addr, value); + EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n", + prtad, devad, addr, value); spin_lock_bh(&efx->phy_lock); - /* Check MII not currently being accessed */ - if (falcon_gmii_wait(efx) != 0) + /* Check MDIO not currently being accessed */ + rc = falcon_gmii_wait(efx); + if (rc) goto out; /* Write the address/ID register */ EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); falcon_write(efx, ®, MD_PHY_ADR_REG_KER); - EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2); + EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad); falcon_write(efx, ®, MD_ID_REG_KER); /* Write data */ @@ -2163,7 +2123,8 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, falcon_write(efx, ®, MD_CS_REG_KER); /* Wait for data to be written */ - if (falcon_gmii_wait(efx) != 0) { + rc = falcon_gmii_wait(efx); + if (rc) { /* Abort the write operation */ EFX_POPULATE_OWORD_2(reg, MD_WRC, 0, @@ -2174,45 +2135,28 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, out: spin_unlock_bh(&efx->phy_lock); + return rc; } -/* Reads a GMII register from a PHY connected to Falcon. If no value - * could be read, -1 will be returned. */ -static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) +/* Read an MDIO register of a PHY connected to Falcon. */ +static int falcon_mdio_read(struct net_device *net_dev, + int prtad, int devad, u16 addr) { struct efx_nic *efx = netdev_priv(net_dev); - unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK; efx_oword_t reg; - int value = -1; - - if (phy_addr == PHY_ADDR_INVALID) - return -1; - - /* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G) - * but the generic Linux code does not make any distinction or have - * any state for this. - * We spot the case where someone tried to talk 22 to a 45 PHY and - * redirect the request to the lowest numbered MMD as a clause45 - * request. This is enough to allow simple queries like id and link - * state to succeed. TODO: We may need to do more in future. - */ - if (!(phy_id & FALCON_PHY_ID_10G)) { - int mmd = ffs(efx->phy_op->mmds) - 1; - EFX_TRACE(efx, "Fixing erroneous clause22 read\n"); - phy_addr = mdio_clause45_pack(phy_addr, mmd) - & FALCON_PHY_ID_ID_MASK; - } + int rc; spin_lock_bh(&efx->phy_lock); - /* Check MII not currently being accessed */ - if (falcon_gmii_wait(efx) != 0) + /* Check MDIO not currently being accessed */ + rc = falcon_gmii_wait(efx); + if (rc) goto out; EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); falcon_write(efx, ®, MD_PHY_ADR_REG_KER); - EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr); + EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad); falcon_write(efx, ®, MD_ID_REG_KER); /* Request data to be read */ @@ -2220,12 +2164,12 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) falcon_write(efx, ®, MD_CS_REG_KER); /* Wait for data to become available */ - value = falcon_gmii_wait(efx); - if (value == 0) { + rc = falcon_gmii_wait(efx); + if (rc == 0) { falcon_read(efx, ®, MD_RXD_REG_KER); - value = EFX_OWORD_FIELD(reg, MD_RXD); - EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n", - phy_id, addr, value); + rc = EFX_OWORD_FIELD(reg, MD_RXD); + EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n", + prtad, devad, addr, rc); } else { /* Abort the read operation */ EFX_POPULATE_OWORD_2(reg, @@ -2233,22 +2177,13 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) MD_GC, 1); falcon_write(efx, ®, MD_CS_REG_KER); - EFX_LOG(efx, "read from GMII 0x%x register %02x, got " - "error %d\n", phy_id, addr, value); + EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n", + prtad, devad, addr, rc); } out: spin_unlock_bh(&efx->phy_lock); - - return value; -} - -static void falcon_init_mdio(struct mii_if_info *gmii) -{ - gmii->mdio_read = falcon_mdio_read; - gmii->mdio_write = falcon_mdio_write; - gmii->phy_id_mask = FALCON_PHY_ID_MASK; - gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1); + return rc; } static int falcon_probe_phy(struct efx_nic *efx) @@ -2342,9 +2277,11 @@ int falcon_probe_port(struct efx_nic *efx) if (rc) return rc; - /* Set up GMII structure for PHY */ - efx->mii.supports_gmii = true; - falcon_init_mdio(&efx->mii); + /* Set up MDIO structure for PHY */ + efx->mdio.mmds = efx->phy_op->mmds; + efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + efx->mdio.mdio_read = falcon_mdio_read; + efx->mdio.mdio_write = falcon_mdio_write; /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ if (falcon_rev(efx) >= FALCON_REV_B0) @@ -2761,7 +2698,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) if (rc == -EINVAL) { EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n"); efx->phy_type = PHY_TYPE_NONE; - efx->mii.phy_id = PHY_ADDR_INVALID; + efx->mdio.prtad = MDIO_PRTAD_NONE; board_rev = 0; rc = 0; } else if (rc) { @@ -2771,7 +2708,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; efx->phy_type = v2->port0_phy_type; - efx->mii.phy_id = v2->port0_phy_addr; + efx->mdio.prtad = v2->port0_phy_addr; board_rev = le16_to_cpu(v2->board_revision); if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { @@ -2793,7 +2730,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) /* Read the MAC addresses */ memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); - EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); + EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad); efx_set_board_info(efx, board_rev); diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index bda8d5bb72e4..375e2a5961ec 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h @@ -456,9 +456,6 @@ #define MD_PRT_ADR_WIDTH 5 #define MD_DEV_ADR_LBN 6 #define MD_DEV_ADR_WIDTH 5 -/* Used for writing both at once */ -#define MD_PRT_DEV_ADR_LBN 6 -#define MD_PRT_DEV_ADR_WIDTH 10 /* PHY management status & mask register (DWORD read only) */ #define MD_STAT_REG_KER 0xc50 diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 5a03713685ac..2b3269c03263 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -133,7 +133,7 @@ bool falcon_xaui_link_ok(struct efx_nic *efx) /* If the link is up, then check the phy side of the xaui link */ if (efx->link_up && link_ok) if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) - link_ok = mdio_clause45_phyxgxs_lane_sync(efx); + link_ok = efx_mdio_phyxgxs_lane_sync(efx); return link_ok; } diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 9f5ec3eb3418..11c231a1f875 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -17,7 +17,7 @@ #include "boards.h" #include "workarounds.h" -unsigned mdio_id_oui(u32 id) +unsigned efx_mdio_id_oui(u32 id) { unsigned oui = 0; int i; @@ -32,52 +32,45 @@ unsigned mdio_id_oui(u32 id) return oui; } -int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, +int efx_mdio_reset_mmd(struct efx_nic *port, int mmd, int spins, int spintime) { u32 ctrl; - int phy_id = port->mii.phy_id; /* Catch callers passing values in the wrong units (or just silly) */ EFX_BUG_ON_PARANOID(spins * spintime >= 5000); - mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1, - (1 << MDIO_MMDREG_CTRL1_RESET_LBN)); + efx_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET); /* Wait for the reset bit to clear. */ do { msleep(spintime); - ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1); + ctrl = efx_mdio_read(port, mmd, MDIO_CTRL1); spins--; - } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))); + } while (spins && (ctrl & MDIO_CTRL1_RESET)); return spins ? spins : -ETIMEDOUT; } -static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, - int fault_fatal) +static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal) { int status; - int phy_id = efx->mii.phy_id; if (LOOPBACK_INTERNAL(efx)) return 0; if (mmd != MDIO_MMD_AN) { /* Read MMD STATUS2 to check it is responding. */ - status = mdio_clause45_read(efx, phy_id, mmd, - MDIO_MMDREG_STAT2); - if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & - ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != - MDIO_MMDREG_STAT2_PRESENT_VAL) { + status = efx_mdio_read(efx, mmd, MDIO_STAT2); + if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) { EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); return -EIO; } } /* Read MMD STATUS 1 to check for fault. */ - status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1); - if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) { + status = efx_mdio_read(efx, mmd, MDIO_STAT1); + if (status & MDIO_STAT1_FAULT) { if (fault_fatal) { EFX_ERR(efx, "PHY MMD %d reporting fatal" " fault: status %x\n", mmd, status); @@ -94,8 +87,7 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, #define MDIO45_RESET_TIME 1000 /* ms */ #define MDIO45_RESET_ITERS 100 -int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, - unsigned int mmd_mask) +int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask) { const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; int tries = MDIO45_RESET_ITERS; @@ -109,16 +101,13 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, in_reset = 0; while (mask) { if (mask & 1) { - stat = mdio_clause45_read(efx, - efx->mii.phy_id, - mmd, - MDIO_MMDREG_CTRL1); + stat = efx_mdio_read(efx, mmd, MDIO_CTRL1); if (stat < 0) { EFX_ERR(efx, "failed to read status of" " MMD %d\n", mmd); return -EIO; } - if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)) + if (stat & MDIO_CTRL1_RESET) in_reset |= (1 << mmd); } mask = mask >> 1; @@ -137,28 +126,26 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, return rc; } -int mdio_clause45_check_mmds(struct efx_nic *efx, - unsigned int mmd_mask, unsigned int fatal_mask) +int efx_mdio_check_mmds(struct efx_nic *efx, + unsigned int mmd_mask, unsigned int fatal_mask) { - int mmd = 0, probe_mmd, devs0, devs1; + int mmd = 0, probe_mmd, devs1, devs2; u32 devices; /* Historically we have probed the PHYXS to find out what devices are * present,but that doesn't work so well if the PHYXS isn't expected * to exist, if so just find the first item in the list supplied. */ - probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS : + probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS : __ffs(mmd_mask); /* Check all the expected MMDs are present */ - devs0 = mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS0); - devs1 = mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS1); - if (devs0 < 0 || devs1 < 0) { + devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1); + devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2); + if (devs1 < 0 || devs2 < 0) { EFX_ERR(efx, "failed to read devices present\n"); return -EIO; } - devices = devs0 | (devs1 << 16); + devices = devs1 | (devs2 << 16); if ((devices & mmd_mask) != mmd_mask) { EFX_ERR(efx, "required MMDs not present: got %x, " "wanted %x\n", devices, mmd_mask); @@ -170,7 +157,7 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, while (mmd_mask) { if (mmd_mask & 1) { int fault_fatal = fatal_mask & 1; - if (mdio_clause45_check_mmd(efx, mmd, fault_fatal)) + if (efx_mdio_check_mmd(efx, mmd, fault_fatal)) return -EIO; } mmd_mask = mmd_mask >> 1; @@ -181,13 +168,8 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, return 0; } -bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) +bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask) { - int phy_id = efx->mii.phy_id; - u32 reg; - bool ok = true; - int mmd = 0; - /* If the port is in loopback, then we should only consider a subset * of mmd's */ if (LOOPBACK_INTERNAL(efx)) @@ -197,241 +179,75 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) else if (efx_phy_mode_disabled(efx->phy_mode)) return false; else if (efx->loopback_mode == LOOPBACK_PHYXS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_DEVS_PHYXS | + MDIO_DEVS_PCS | + MDIO_DEVS_PMAPMD | + MDIO_DEVS_AN); else if (efx->loopback_mode == LOOPBACK_PCS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_DEVS_PCS | + MDIO_DEVS_PMAPMD | + MDIO_DEVS_AN); else if (efx->loopback_mode == LOOPBACK_PMAPMD) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); - - if (!mmd_mask) { - /* Use presence of XGMII faults in leui of link state */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_PHYXS_STATUS2); - return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN)); - } + mmd_mask &= ~(MDIO_DEVS_PMAPMD | + MDIO_DEVS_AN); - while (mmd_mask) { - if (mmd_mask & 1) { - /* Double reads because link state is latched, and a - * read moves the current state into the register */ - reg = mdio_clause45_read(efx, phy_id, - mmd, MDIO_MMDREG_STAT1); - reg = mdio_clause45_read(efx, phy_id, - mmd, MDIO_MMDREG_STAT1); - ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN)); - } - mmd_mask = (mmd_mask >> 1); - mmd++; - } - return ok; + return mdio45_links_ok(&efx->mdio, mmd_mask); } -void mdio_clause45_transmit_disable(struct efx_nic *efx) +void efx_mdio_transmit_disable(struct efx_nic *efx) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN, - efx->phy_mode & PHY_MODE_TX_DISABLED); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, + MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL, + efx->phy_mode & PHY_MODE_TX_DISABLED); } -void mdio_clause45_phy_reconfigure(struct efx_nic *efx) +void efx_mdio_phy_reconfigure(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PMAPMD); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PCS); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_NETWORK); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, + MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK, + efx->loopback_mode == LOOPBACK_PMAPMD); + efx_mdio_set_flag(efx, MDIO_MMD_PCS, + MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK, + efx->loopback_mode == LOOPBACK_PCS); + efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, + MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK, + efx->loopback_mode == LOOPBACK_NETWORK); } -static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx, - int lpower, int mmd) +static void efx_mdio_set_mmd_lpower(struct efx_nic *efx, + int lpower, int mmd) { - int phy = efx->mii.phy_id; - int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1); + int stat = efx_mdio_read(efx, mmd, MDIO_STAT1); EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n", mmd, lpower); - if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) { - mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1, - MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower); + if (stat & MDIO_STAT1_LPOWERABLE) { + efx_mdio_set_flag(efx, mmd, MDIO_CTRL1, + MDIO_CTRL1_LPOWER, lpower); } } -void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, - int low_power, unsigned int mmd_mask) +void efx_mdio_set_mmds_lpower(struct efx_nic *efx, + int low_power, unsigned int mmd_mask) { int mmd = 0; - mmd_mask &= ~MDIO_MMDREG_DEVS_AN; + mmd_mask &= ~MDIO_DEVS_AN; while (mmd_mask) { if (mmd_mask & 1) - mdio_clause45_set_mmd_lpower(efx, low_power, mmd); + efx_mdio_set_mmd_lpower(efx, low_power, mmd); mmd_mask = (mmd_mask >> 1); mmd++; } } -static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) -{ - int phy_id = efx->mii.phy_id; - u32 result = 0; - int reg; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr); - if (reg & ADVERTISE_10HALF) - result |= ADVERTISED_10baseT_Half; - if (reg & ADVERTISE_10FULL) - result |= ADVERTISED_10baseT_Full; - if (reg & ADVERTISE_100HALF) - result |= ADVERTISED_100baseT_Half; - if (reg & ADVERTISE_100FULL) - result |= ADVERTISED_100baseT_Full; - return result; -} - -/** - * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd) -{ - mdio_clause45_get_settings_ext(efx, ecmd, 0, 0); -} - /** - * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * @xnp: Advertised Extended Next Page state - * @xnp_lpa: Link Partner's advertised XNP state - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings_ext(struct efx_nic *efx, - struct ethtool_cmd *ecmd, - u32 npage_adv, u32 npage_lpa) -{ - int phy_id = efx->mii.phy_id; - int reg; - - ecmd->transceiver = XCVR_INTERNAL; - ecmd->phy_address = phy_id; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL2); - switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) { - case MDIO_PMAPMD_CTRL2_10G_BT: - case MDIO_PMAPMD_CTRL2_1G_BT: - case MDIO_PMAPMD_CTRL2_100_BT: - case MDIO_PMAPMD_CTRL2_10_BT: - ecmd->port = PORT_TP; - ecmd->supported = SUPPORTED_TP; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_SPEED); - if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN)) - ecmd->supported |= SUPPORTED_10000baseT_Full; - if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN)) - ecmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_1000baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN)) - ecmd->supported |= (SUPPORTED_100baseT_Full | - SUPPORTED_100baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN)) - ecmd->supported |= (SUPPORTED_10baseT_Full | - SUPPORTED_10baseT_Half); - ecmd->advertising = ADVERTISED_TP; - break; - - /* We represent CX4 as fibre in the absence of anything better */ - case MDIO_PMAPMD_CTRL2_10G_CX4: - /* All the other defined modes are flavours of optical */ - default: - ecmd->port = PORT_FIBRE; - ecmd->supported = SUPPORTED_FIBRE; - ecmd->advertising = ADVERTISED_FIBRE; - break; - } - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - ecmd->supported |= SUPPORTED_Autoneg; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - ecmd->autoneg = AUTONEG_ENABLE; - ecmd->advertising |= - ADVERTISED_Autoneg | - mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) | - npage_adv; - } else - ecmd->autoneg = AUTONEG_DISABLE; - } else - ecmd->autoneg = AUTONEG_DISABLE; - - if (ecmd->autoneg) { - /* If AN is complete, report best common mode, - * otherwise report best advertised mode. */ - u32 modes = 0; - if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_STAT1) & - (1 << MDIO_AN_STATUS_AN_DONE_LBN)) - modes = (ecmd->advertising & - (mdio_clause45_get_an(efx, MDIO_AN_LPA) | - npage_lpa)); - if (modes == 0) - modes = ecmd->advertising; - - if (modes & ADVERTISED_10000baseT_Full) { - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - } else if (modes & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { - ecmd->speed = SPEED_1000; - ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); - } else if (modes & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { - ecmd->speed = SPEED_100; - ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); - } else { - ecmd->speed = SPEED_10; - ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); - } - } else { - /* Report forced settings */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) * - ((reg & BMCR_SPEED100) ? 100 : 10)); - ecmd->duplex = (reg & BMCR_FULLDPLX || - ecmd->speed == SPEED_10000); - } -} - -/** - * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO. + * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO. * @efx: Efx NIC * @ecmd: New settings */ -int mdio_clause45_set_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd) +int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; struct ethtool_cmd prev; u32 required; int reg; @@ -489,94 +305,67 @@ int mdio_clause45_set_settings(struct efx_nic *efx, ADVERTISED_1000baseT_Full)) reg |= ADVERTISE_NPAGE; reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); + efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); /* Set up the (extended) next page if necessary */ if (efx->phy_op->set_npage_adv) efx->phy_op->set_npage_adv(efx, ecmd->advertising); /* Enable and restart AN */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - reg |= BMCR_ANENABLE; + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); + reg |= MDIO_AN_CTRL1_ENABLE; if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) - reg |= BMCR_ANRESTART; + reg |= MDIO_AN_CTRL1_RESTART; if (xnp) - reg |= 1 << MDIO_AN_CTRL_XNP_LBN; + reg |= MDIO_AN_CTRL1_XNP; else - reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); + reg &= ~MDIO_AN_CTRL1_XNP; + efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); } else { /* Disable AN */ - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, - __ffs(BMCR_ANENABLE), false); + efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_CTRL1, + MDIO_AN_CTRL1_ENABLE, false); /* Set the basic control bits */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | - 0x003c); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1); + reg &= ~(MDIO_CTRL1_SPEEDSEL | MDIO_CTRL1_FULLDPLX); if (ecmd->speed == SPEED_100) - reg |= BMCR_SPEED100; + reg |= MDIO_PMA_CTRL1_SPEED100; if (ecmd->duplex) - reg |= BMCR_FULLDPLX; - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, reg); + reg |= MDIO_CTRL1_FULLDPLX; + efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, reg); } return 0; } -void mdio_clause45_set_pause(struct efx_nic *efx) +void efx_mdio_set_pause(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; int reg; - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { + if (efx->phy_op->mmds & MDIO_DEVS_AN) { /* Set pause capability advertising */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE); + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE); reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); + efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); /* Restart auto-negotiation */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - reg |= BMCR_ANRESTART; - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); + if (reg & MDIO_AN_CTRL1_ENABLE) { + reg |= MDIO_AN_CTRL1_RESTART; + efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); } } } -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx) +enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; int lpa; - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN))) + if (!(efx->phy_op->mmds & MDIO_DEVS_AN)) return efx->wanted_fc; - lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA); + lpa = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA); return efx_fc_resolve(efx->wanted_fc, lpa); } - -void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense) -{ - int old_val = mdio_clause45_read(efx, prt, dev, addr); - int new_val; - - if (sense) - new_val = old_val | (1 << bit); - else - new_val = old_val & ~(1 << bit); - if (old_val != new_val) - mdio_clause45_write(efx, prt, dev, addr, new_val); -} diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index 7014d2279c20..ea4587d93698 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -10,247 +10,53 @@ #ifndef EFX_MDIO_10G_H #define EFX_MDIO_10G_H +#include + /* - * Definitions needed for doing 10G MDIO as specified in clause 45 - * MDIO, which do not appear in Linux yet. Also some helper functions. + * Helper functions for doing 10G MDIO as specified in IEEE 802.3 clause 45. */ #include "efx.h" #include "boards.h" -/* Numbering of the MDIO Manageable Devices (MMDs) */ -/* Physical Medium Attachment/ Physical Medium Dependent sublayer */ -#define MDIO_MMD_PMAPMD (1) -/* WAN Interface Sublayer */ -#define MDIO_MMD_WIS (2) -/* Physical Coding Sublayer */ -#define MDIO_MMD_PCS (3) -/* PHY Extender Sublayer */ -#define MDIO_MMD_PHYXS (4) -/* Extender Sublayer */ -#define MDIO_MMD_DTEXS (5) -/* Transmission convergence */ -#define MDIO_MMD_TC (6) -/* Auto negotiation */ -#define MDIO_MMD_AN (7) -/* Clause 22 extension */ -#define MDIO_MMD_C22EXT 29 - -/* Generic register locations */ -#define MDIO_MMDREG_CTRL1 (0) -#define MDIO_MMDREG_STAT1 (1) -#define MDIO_MMDREG_IDHI (2) -#define MDIO_MMDREG_IDLOW (3) -#define MDIO_MMDREG_SPEED (4) -#define MDIO_MMDREG_DEVS0 (5) -#define MDIO_MMDREG_DEVS1 (6) -#define MDIO_MMDREG_CTRL2 (7) -#define MDIO_MMDREG_STAT2 (8) -#define MDIO_MMDREG_TXDIS (9) - -/* Bits in MMDREG_CTRL1 */ -/* Reset */ -#define MDIO_MMDREG_CTRL1_RESET_LBN (15) -#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1) -/* Loopback */ -/* Loopback bit for WIS, PCS, PHYSX and DTEXS */ -#define MDIO_MMDREG_CTRL1_LBACK_LBN (14) -#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1) -/* Low power */ -#define MDIO_MMDREG_CTRL1_LPOWER_LBN (11) -#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH (1) - -/* Bits in MMDREG_STAT1 */ -#define MDIO_MMDREG_STAT1_FAULT_LBN (7) -#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1) -/* Link state */ -#define MDIO_MMDREG_STAT1_LINK_LBN (2) -#define MDIO_MMDREG_STAT1_LINK_WIDTH (1) -/* Low power ability */ -#define MDIO_MMDREG_STAT1_LPABLE_LBN (1) -#define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1) - -/* Bits in combined ID regs */ -static inline unsigned mdio_id_rev(u32 id) { return id & 0xf; } -static inline unsigned mdio_id_model(u32 id) { return (id >> 4) & 0x3f; } -extern unsigned mdio_id_oui(u32 id); - -/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out - * so the 'bit present' bit number of an MMD is the number of - * that MMD */ -#define DEV_PRESENT_BIT(_b) (1 << _b) - -#define MDIO_MMDREG_DEVS_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS) -#define MDIO_MMDREG_DEVS_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS) -#define MDIO_MMDREG_DEVS_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD) -#define MDIO_MMDREG_DEVS_AN DEV_PRESENT_BIT(MDIO_MMD_AN) -#define MDIO_MMDREG_DEVS_C22EXT DEV_PRESENT_BIT(MDIO_MMD_C22EXT) - -/* Bits in MMDREG_SPEED */ -#define MDIO_MMDREG_SPEED_10G_LBN 0 -#define MDIO_MMDREG_SPEED_10G_WIDTH 1 -#define MDIO_MMDREG_SPEED_1000M_LBN 4 -#define MDIO_MMDREG_SPEED_1000M_WIDTH 1 -#define MDIO_MMDREG_SPEED_100M_LBN 5 -#define MDIO_MMDREG_SPEED_100M_WIDTH 1 -#define MDIO_MMDREG_SPEED_10M_LBN 6 -#define MDIO_MMDREG_SPEED_10M_WIDTH 1 - -/* Bits in MMDREG_STAT2 */ -#define MDIO_MMDREG_STAT2_PRESENT_VAL (2) -#define MDIO_MMDREG_STAT2_PRESENT_LBN (14) -#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2) - -/* Bits in MMDREG_TXDIS */ -#define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0) -#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1) - -/* MMD-specific bits, ordered by MMD, then register */ -#define MDIO_PMAPMD_CTRL1_LBACK_LBN (0) -#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1) - -/* PMA type (4 bits) */ -#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0) -#define MDIO_PMAPMD_CTRL2_10G_EW (0x1) -#define MDIO_PMAPMD_CTRL2_10G_LW (0x2) -#define MDIO_PMAPMD_CTRL2_10G_SW (0x3) -#define MDIO_PMAPMD_CTRL2_10G_LX4 (0x4) -#define MDIO_PMAPMD_CTRL2_10G_ER (0x5) -#define MDIO_PMAPMD_CTRL2_10G_LR (0x6) -#define MDIO_PMAPMD_CTRL2_10G_SR (0x7) -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_10G_BT (0x9) -/* Reserved */ -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_1G_BT (0xc) -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_100_BT (0xe) -#define MDIO_PMAPMD_CTRL2_10_BT (0xf) -#define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf) - -/* PMA 10GBT registers */ -#define MDIO_PMAPMD_10GBT_TXPWR (131) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1) - -/* PHY XGXS Status 2 */ -#define MDIO_PHYXS_STATUS2 (8) -#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10 - -/* PHY XGXS lane state */ -#define MDIO_PHYXS_LANE_STATE (0x18) -#define MDIO_PHYXS_LANE_ALIGNED_LBN (12) - -/* AN registers */ -#define MDIO_AN_CTRL_XNP_LBN 13 -#define MDIO_AN_STATUS (1) -#define MDIO_AN_STATUS_XNP_LBN (7) -#define MDIO_AN_STATUS_PAGE_LBN (6) -#define MDIO_AN_STATUS_AN_DONE_LBN (5) -#define MDIO_AN_STATUS_LP_AN_CAP_LBN (0) - -#define MDIO_AN_ADVERTISE 16 -#define MDIO_AN_ADVERTISE_XNP_LBN 12 -#define MDIO_AN_LPA 19 -#define MDIO_AN_XNP 22 -#define MDIO_AN_LPA_XNP 25 - -#define MDIO_AN_10GBT_CTRL 32 -#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12 -#define MDIO_AN_10GBT_STATUS (33) -#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ -#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ -#define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */ -#define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */ -#define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */ -#define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */ -#define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9) /* LP Training Reset Request */ +static inline unsigned efx_mdio_id_rev(u32 id) { return id & 0xf; } +static inline unsigned efx_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; } +extern unsigned efx_mdio_id_oui(u32 id); - -/* Packing of the prt and dev arguments of clause 45 style MDIO into a - * single int so they can be passed into the mdio_read/write functions - * that currently exist. Note that as Falcon is the only current user, - * the packed form is chosen to match what Falcon needs to write into - * a register. This is checked at compile-time so do not change it. If - * your target chip needs things layed out differently you will need - * to unpack the arguments in your chip-specific mdio functions. - */ - /* These are defined by the standard. */ -#define MDIO45_PRT_ID_WIDTH (5) -#define MDIO45_DEV_ID_WIDTH (5) - -/* The prt ID is just packed in immediately to the left of the dev ID */ -#define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH) - -#define MDIO45_PRT_ID_MASK ((1 << MDIO45_PRT_DEV_WIDTH) - 1) -/* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */ -#define MDIO45_XPRT_ID_WIDTH (MDIO45_PRT_DEV_WIDTH + 1) -#define MDIO45_XPRT_ID_MASK ((1 << MDIO45_XPRT_ID_WIDTH) - 1) -#define MDIO45_XPRT_ID_IS10G (1 << (MDIO45_XPRT_ID_WIDTH - 1)) - - -#define MDIO45_PRT_ID_COMP_LBN MDIO45_DEV_ID_WIDTH -#define MDIO45_PRT_ID_COMP_WIDTH MDIO45_PRT_ID_WIDTH -#define MDIO45_DEV_ID_COMP_LBN 0 -#define MDIO45_DEV_ID_COMP_WIDTH MDIO45_DEV_ID_WIDTH - -/* Compose port and device into a phy_id */ -static inline int mdio_clause45_pack(u8 prt, u8 dev) -{ - efx_dword_t phy_id; - EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt, - MDIO45_DEV_ID_COMP, dev); - return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id); -} - -static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev) +static inline int efx_mdio_read(struct efx_nic *efx, int devad, int addr) { - efx_dword_t phy_id; - EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val); - *prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP); - *dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP); + return efx->mdio.mdio_read(efx->net_dev, efx->mdio.prtad, devad, addr); } -static inline int mdio_clause45_read(struct efx_nic *efx, - u8 prt, u8 dev, u16 addr) +static inline void +efx_mdio_write(struct efx_nic *efx, int devad, int addr, int value) { - return efx->mii.mdio_read(efx->net_dev, - mdio_clause45_pack(prt, dev), addr); + efx->mdio.mdio_write(efx->net_dev, efx->mdio.prtad, devad, addr, value); } -static inline void mdio_clause45_write(struct efx_nic *efx, - u8 prt, u8 dev, u16 addr, int value) -{ - efx->mii.mdio_write(efx->net_dev, - mdio_clause45_pack(prt, dev), addr, value); -} - - -static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd) +static inline u32 efx_mdio_read_id(struct efx_nic *efx, int mmd) { - int phy_id = efx->mii.phy_id; - u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW); - u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI); + u16 id_low = efx_mdio_read(efx, mmd, MDIO_DEVID2); + u16 id_hi = efx_mdio_read(efx, mmd, MDIO_DEVID1); return (id_hi << 16) | (id_low); } -static inline bool mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx) +static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx) { int i, lane_status; bool sync; for (i = 0; i < 2; ++i) - lane_status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PHYXS, - MDIO_PHYXS_LANE_STATE); + lane_status = efx_mdio_read(efx, MDIO_MMD_PHYXS, + MDIO_PHYXS_LNSTAT); - sync = !!(lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)); + sync = !!(lane_status & MDIO_PHYXS_LNSTAT_ALIGN); if (!sync) EFX_LOG(efx, "XGXS lane status: %x\n", lane_status); return sync; } -extern const char *mdio_clause45_mmd_name(int mmd); +extern const char *efx_mdio_mmd_name(int mmd); /* * Reset a specific MMD and wait for reset to clear. @@ -258,54 +64,47 @@ extern const char *mdio_clause45_mmd_name(int mmd); * * This function will sleep */ -extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd, - int spins, int spintime); +extern int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd, + int spins, int spintime); -/* As mdio_clause45_check_mmd but for multiple MMDs */ -int mdio_clause45_check_mmds(struct efx_nic *efx, - unsigned int mmd_mask, unsigned int fatal_mask); +/* As efx_mdio_check_mmd but for multiple MMDs */ +int efx_mdio_check_mmds(struct efx_nic *efx, + unsigned int mmd_mask, unsigned int fatal_mask); /* Check the link status of specified mmds in bit mask */ -extern bool mdio_clause45_links_ok(struct efx_nic *efx, - unsigned int mmd_mask); +extern bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask); /* Generic transmit disable support though PMAPMD */ -extern void mdio_clause45_transmit_disable(struct efx_nic *efx); +extern void efx_mdio_transmit_disable(struct efx_nic *efx); /* Generic part of reconfigure: set/clear loopback bits */ -extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx); +extern void efx_mdio_phy_reconfigure(struct efx_nic *efx); /* Set the power state of the specified MMDs */ -extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, - int low_power, unsigned int mmd_mask); - -/* Read (some of) the PHY settings over MDIO */ -extern void mdio_clause45_get_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd); - -/* Read (some of) the PHY settings over MDIO */ -extern void -mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd, - u32 xnp, u32 xnp_lpa); +extern void efx_mdio_set_mmds_lpower(struct efx_nic *efx, + int low_power, unsigned int mmd_mask); /* Set (some of) the PHY settings over MDIO */ -extern int mdio_clause45_set_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd); +extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); /* Set pause parameters to be advertised through AN (if available) */ -extern void mdio_clause45_set_pause(struct efx_nic *efx); +extern void efx_mdio_set_pause(struct efx_nic *efx); /* Get pause parameters from AN if available (otherwise return * requested pause parameters) */ -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx); +enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx); /* Wait for specified MMDs to exit reset within a timeout */ -extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, - unsigned int mmd_mask); +extern int efx_mdio_wait_reset_mmds(struct efx_nic *efx, + unsigned int mmd_mask); /* Set or clear flag, debouncing */ -extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense); +static inline void +efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr, + int mask, bool state) +{ + mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state); +} #endif /* EFX_MDIO_10G_H */ diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index e169e5dcd1e6..457e2f1d4b43 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -458,8 +458,6 @@ enum phy_type { PHY_TYPE_MAX /* Insert any new items before this */ }; -#define PHY_ADDR_INVALID 0xff - #define EFX_IS10G(efx) ((efx)->link_speed == 10000) enum nic_state { @@ -758,7 +756,7 @@ union efx_multicast_hash { * @phy_lock: PHY access lock * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) - * @mii: PHY interface + * @mdio: PHY MDIO interface * @phy_mode: PHY operating mode. Serialised by @mac_lock. * @mac_up: MAC link state * @link_up: Link status @@ -845,7 +843,7 @@ struct efx_nic { struct work_struct phy_work; struct efx_phy_operations *phy_op; void *phy_data; - struct mii_if_info mii; + struct mdio_if_info mdio; enum efx_phy_mode phy_mode; bool mac_up; diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 0a598084c513..043795715955 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -80,39 +80,38 @@ struct efx_loopback_state { * **************************************************************************/ -static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests) +static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) { int rc = 0; + int devad = __ffs(efx->mdio.mmds); u16 physid1, physid2; - struct mii_if_info *mii = &efx->mii; - struct net_device *net_dev = efx->net_dev; if (efx->phy_type == PHY_TYPE_NONE) return 0; mutex_lock(&efx->mac_lock); - tests->mii = -1; + tests->mdio = -1; - physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1); - physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2); + physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1); + physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2); if ((physid1 == 0x0000) || (physid1 == 0xffff) || (physid2 == 0x0000) || (physid2 == 0xffff)) { - EFX_ERR(efx, "no MII PHY present with ID %d\n", - mii->phy_id); + EFX_ERR(efx, "no MDIO PHY present with ID %d\n", + efx->mdio.prtad); rc = -EINVAL; goto out; } if (EFX_IS10G(efx)) { - rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); + rc = efx_mdio_check_mmds(efx, efx->phy_op->mmds, 0); if (rc) goto out; } out: mutex_unlock(&efx->mac_lock); - tests->mii = rc ? -1 : 1; + tests->mdio = rc ? -1 : 1; return rc; } @@ -673,7 +672,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* Online (i.e. non-disruptive) testing * This checks interrupt generation, event delivery and PHY presence. */ - rc = efx_test_mii(efx, tests); + rc = efx_test_mdio(efx, tests); if (rc && !rc_test) rc_test = rc; diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index 39451cf938cf..f6feee04c96b 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h @@ -32,7 +32,7 @@ struct efx_loopback_self_tests { */ struct efx_self_tests { /* online tests */ - int mii; + int mdio; int nvram; int interrupt; int eventq_dma[EFX_MAX_CHANNELS]; diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index e61dc4d4741c..403f7d70c223 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -23,10 +23,10 @@ * clause 22 extension MMD, but since it doesn't have all the generic * MMD registers it is pointless to include it here. */ -#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PHYXS | \ - MDIO_MMDREG_DEVS_AN) +#define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \ + MDIO_DEVS_PCS | \ + MDIO_DEVS_PHYXS | \ + MDIO_DEVS_AN) #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ (1 << LOOPBACK_PCS) | \ @@ -153,10 +153,6 @@ #define LOOPBACK_NEAR_LBN (8) #define LOOPBACK_NEAR_WIDTH (1) -#define PCS_10GBASET_STAT1 32 -#define PCS_10GBASET_BLKLK_LBN 0 -#define PCS_10GBASET_BLKLK_WIDTH 1 - /* Boot status register */ #define PCS_BOOT_STATUS_REG 53248 #define PCS_BOOT_FATAL_ERROR_LBN 0 @@ -206,10 +202,8 @@ static ssize_t show_phy_short_reach(struct device *dev, struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); int reg; - reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR); - return sprintf(buf, "%d\n", - !!(reg & (1 << MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN))); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR); + return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT)); } static ssize_t set_phy_short_reach(struct device *dev, @@ -219,10 +213,9 @@ static ssize_t set_phy_short_reach(struct device *dev, struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); rtnl_lock(); - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR, - MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN, - count != 0 && *buf != '0'); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, + MDIO_PMA_10GBT_TXPWR_SHORT, + count != 0 && *buf != '0'); efx_reconfigure_port(efx); rtnl_unlock(); @@ -238,9 +231,8 @@ int sft9001_wait_boot(struct efx_nic *efx) int boot_stat; for (;;) { - boot_stat = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PCS, - PCS_BOOT_STATUS_REG); + boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS, + PCS_BOOT_STATUS_REG); if (boot_stat >= 0) { EFX_LOG(efx, "PHY boot status = %#x\n", boot_stat); switch (boot_stat & @@ -286,38 +278,32 @@ int sft9001_wait_boot(struct efx_nic *efx) static int tenxpress_init(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; int reg; if (efx->phy_type == PHY_TYPE_SFX7101) { /* Enable 312.5 MHz clock */ - mdio_clause45_write(efx, phy_id, - MDIO_MMD_PCS, PCS_TEST_SELECT_REG, - 1 << CLK312_EN_LBN); + efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, + 1 << CLK312_EN_LBN); } else { /* Enable 312.5 MHz clock and GMII */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | (1 << PMA_PMD_EXT_CLK_OUT_LBN) | (1 << PMA_PMD_EXT_CLK312_LBN) | (1 << PMA_PMD_EXT_ROBUST_LBN)); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, GPHY_ISOLATE_LBN, - false); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); + efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, + GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN, + false); } /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ if (efx->phy_type == PHY_TYPE_SFX7101) { - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_CTRL_REG, - PMA_PMA_LED_ACTIVITY_LBN, - true); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, PMA_PMD_LED_DEFAULT); + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, + 1 << PMA_PMA_LED_ACTIVITY_LBN, true); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, + PMA_PMD_LED_DEFAULT); } return 0; @@ -337,22 +323,19 @@ static int tenxpress_phy_init(struct efx_nic *efx) if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { if (efx->phy_type == PHY_TYPE_SFT9001A) { int reg; - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_XCONTROL_REG); reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + PMA_PMD_XCONTROL_REG, reg); mdelay(200); } - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); + rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) goto fail; - rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); + rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); if (rc < 0) goto fail; } @@ -360,7 +343,7 @@ static int tenxpress_phy_init(struct efx_nic *efx) rc = tenxpress_init(efx); if (rc < 0) goto fail; - mdio_clause45_set_pause(efx); + efx_mdio_set_pause(efx); if (efx->phy_type == PHY_TYPE_SFT9001B) { rc = device_create_file(&efx->pci_dev->dev, @@ -395,17 +378,14 @@ static int tenxpress_special_reset(struct efx_nic *efx) efx_stats_disable(efx); /* Initiate reset */ - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); mdelay(200); /* Wait for the blocks to come out of reset */ - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); + rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) goto out; @@ -424,7 +404,6 @@ out: static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) { struct tenxpress_phy_data *pd = efx->phy_data; - int phy_id = efx->mii.phy_id; bool bad_lp; int reg; @@ -432,11 +411,10 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) bad_lp = false; } else { /* Check that AN has started but not completed. */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_STATUS); - if (!(reg & (1 << MDIO_AN_STATUS_LP_AN_CAP_LBN))) + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1); + if (!(reg & MDIO_AN_STAT1_LPABLE)) return; /* LP status is unknown */ - bad_lp = !(reg & (1 << MDIO_AN_STATUS_AN_DONE_LBN)); + bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE); if (bad_lp) pd->bad_lp_tries++; } @@ -448,8 +426,8 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) /* Use the RX (red) LED as an error indicator once we've seen AN * failure several times in a row, and also log a message. */ if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_LED_OVERR_REG); reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN); if (!bad_lp) { reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN; @@ -460,23 +438,22 @@ static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) " supports 10GBASE-T ONLY, so no link can" " be established\n"); } - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + PMA_PMD_LED_OVERR_REG, reg); pd->bad_lp_tries = bad_lp; } } static bool sfx7101_link_ok(struct efx_nic *efx) { - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PHYXS); + return efx_mdio_links_ok(efx, + MDIO_DEVS_PMAPMD | + MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS); } static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; u32 reg; if (efx_phy_mode_disabled(efx->phy_mode)) @@ -484,50 +461,43 @@ static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) else if (efx->loopback_mode == LOOPBACK_GPHY) return true; else if (efx->loopback_mode) - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PHYXS); + return efx_mdio_links_ok(efx, + MDIO_DEVS_PMAPMD | + MDIO_DEVS_PHYXS); /* We must use the same definition of link state as LASI, * otherwise we can miss a link state transition */ if (ecmd->speed == 10000) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_10GBASET_STAT1); - return reg & (1 << PCS_10GBASET_BLKLK_LBN); + reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1); + return reg & MDIO_PCS_10GBRT_STAT1_BLKLK; } else { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_STATUS_REG); + reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG); return reg & (1 << C22EXT_STATUS_LINK_LBN); } } static void tenxpress_ext_loopback(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - PHYXS_TEST1, LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_PHYXS); + efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1, + 1 << LOOPBACK_NEAR_LBN, + efx->loopback_mode == LOOPBACK_PHYXS); if (efx->phy_type != PHY_TYPE_SFX7101) - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, - GPHY_LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_GPHY); + efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG, + 1 << GPHY_LOOPBACK_NEAR_LBN, + efx->loopback_mode == LOOPBACK_GPHY); } static void tenxpress_low_power(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - if (efx->phy_type == PHY_TYPE_SFX7101) - mdio_clause45_set_mmds_lpower( + efx_mdio_set_mmds_lpower( efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), TENXPRESS_REQUIRED_DEVS); else - mdio_clause45_set_flag( - efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, PMA_PMD_EXT_LPOWER_LBN, + efx_mdio_set_flag( + efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, + 1 << PMA_PMD_EXT_LPOWER_LBN, !!(efx->phy_mode & PHY_MODE_LOW_POWER)); } @@ -568,8 +538,8 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) WARN_ON(rc); } - mdio_clause45_transmit_disable(efx); - mdio_clause45_phy_reconfigure(efx); + efx_mdio_transmit_disable(efx); + efx_mdio_phy_reconfigure(efx); tenxpress_ext_loopback(efx); phy_data->loopback_mode = efx->loopback_mode; @@ -585,7 +555,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) efx->link_fd = ecmd.duplex == DUPLEX_FULL; efx->link_up = sft9001_link_ok(efx, &ecmd); } - efx->link_fc = mdio_clause45_get_pause(efx); + efx->link_fc = efx_mdio_get_pause(efx); } /* Poll PHY for interrupt */ @@ -599,7 +569,7 @@ static void tenxpress_phy_poll(struct efx_nic *efx) if (link_ok != efx->link_up) { change = true; } else { - unsigned int link_fc = mdio_clause45_get_pause(efx); + unsigned int link_fc = efx_mdio_get_pause(efx); if (link_fc != efx->link_fc) change = true; } @@ -609,9 +579,8 @@ static void tenxpress_phy_poll(struct efx_nic *efx) if (link_ok != efx->link_up) change = true; } else { - u32 status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_LASI_STATUS); + int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_LASI_STATUS); if (status & (1 << PMA_PMD_LS_ALARM_LBN)) change = true; } @@ -634,8 +603,7 @@ static void tenxpress_phy_fini(struct efx_nic *efx) if (efx->phy_type == PHY_TYPE_SFX7101) { /* Power down the LNPGA */ reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); /* Waiting here ensures that the board fini, which can turn * off the power to the PHY, won't get run until the LNPGA @@ -661,8 +629,7 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink) else reg = PMA_PMD_LED_DEFAULT; - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg); } static const char *const sfx7101_test_names[] = { @@ -698,7 +665,6 @@ static const char *const sft9001_test_names[] = { static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) { struct ethtool_cmd ecmd; - int phy_id = efx->mii.phy_id; int rc = 0, rc2, i, ctrl_reg, res_reg; if (flags & ETH_TEST_FL_OFFLINE) @@ -717,11 +683,10 @@ static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) * must reset the PHY to resume normal service. */ ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN); } - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_CTRL_REG, ctrl_reg); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG, + ctrl_reg); i = 0; - while (mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_CTRL_REG) & + while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) & (1 << CDIAG_CTRL_IN_PROG_LBN)) { if (++i == 50) { rc = -ETIMEDOUT; @@ -729,15 +694,13 @@ static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) } msleep(100); } - res_reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_RES_REG); + res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG); for (i = 0; i < 4; i++) { int pair_res = (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH)) & ((1 << CDIAG_RES_WIDTH) - 1); - int len_reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_LEN_REG + i); + int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, + PMA_PMD_CDIAG_LEN_REG + i); if (pair_res == CDIAG_RES_OK) results[1 + i] = 1; else if (pair_res == CDIAG_RES_INVALID) @@ -769,32 +732,27 @@ out: static void tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; u32 adv = 0, lpa = 0; int reg; if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL); + reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL); if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN)) adv |= ADVERTISED_1000baseT_Full; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_STATUS); + reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS); if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN)) lpa |= ADVERTISED_1000baseT_Half; if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) lpa |= ADVERTISED_1000baseT_Full; } - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL); - if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN)) + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); + if (reg & MDIO_AN_10GBT_CTRL_ADV10G) adv |= ADVERTISED_10000baseT_Full; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_STATUS); - if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) + reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); + if (reg & MDIO_AN_10GBT_STAT_LP10G) lpa |= ADVERTISED_10000baseT_Full; - mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa); + mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa); if (efx->phy_type != PHY_TYPE_SFX7101) ecmd->supported |= (SUPPORTED_100baseT_Full | @@ -813,29 +771,24 @@ static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) if (!ecmd->autoneg) return -EINVAL; - return mdio_clause45_set_settings(efx, ecmd); + return efx_mdio_set_settings(efx, ecmd); } static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); + efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G, + advertising & ADVERTISED_10000baseT_Full); } static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) { - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL, - C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, - advertising & ADVERTISED_1000baseT_Full); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); + efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL, + 1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, + advertising & ADVERTISED_1000baseT_Full); + efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G, + advertising & ADVERTISED_10000baseT_Full); } struct efx_phy_operations falcon_sfx7101_phy_ops = { diff --git a/drivers/net/sfc/xenpack.h b/drivers/net/sfc/xenpack.h index b0d1f225b70a..4e52286e542d 100644 --- a/drivers/net/sfc/xenpack.h +++ b/drivers/net/sfc/xenpack.h @@ -34,29 +34,24 @@ /* Enable LASI interrupts for PHY */ static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx) { - int reg; - int phy_id = efx->mii.phy_id; /* Read to clear LASI status register */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_STAT); + efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_CTRL, + XP_LASI_LS_ALARM); } /* Read the LASI interrupt status to clear the interrupt. */ static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx) { /* Read to clear link status alarm */ - return mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT); + return efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT); } /* Turn off LASI interrupts */ static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx) { - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_CTRL, 0); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_XP_LASI_CTRL, 0); } #endif /* EFX_XENPACK_H */ diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index bb1ef77d5f56..aad2dca19772 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -19,9 +19,9 @@ #include "phy.h" #include "falcon.h" -#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PHYXS) +#define XFP_REQUIRED_DEVS (MDIO_DEVS_PCS | \ + MDIO_DEVS_PMAPMD | \ + MDIO_DEVS_PHYXS) #define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \ (1 << LOOPBACK_PMAPMD) | \ @@ -49,8 +49,7 @@ void xfp_set_led(struct efx_nic *p, int led, int mode) { int addr = MDIO_QUAKE_LED0_REG + led; - mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr, - mode); + efx_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode); } struct xfp_phy_data { @@ -63,14 +62,12 @@ struct xfp_phy_data { static int qt2025c_wait_reset(struct efx_nic *efx) { unsigned long timeout = jiffies + 10 * HZ; - int phy_id = efx->mii.phy_id; int reg, old_counter = 0; /* Wait for firmware heartbeat to start */ for (;;) { int counter; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_FW_HEARTBEAT_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG); if (reg < 0) return reg; counter = ((reg >> PCS_FW_HEARTB_LBN) & @@ -86,8 +83,7 @@ static int qt2025c_wait_reset(struct efx_nic *efx) /* Wait for firmware status to look good */ for (;;) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_UC8051_STATUS_REG); + reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG); if (reg < 0) return reg; if ((reg & @@ -109,9 +105,9 @@ static int xfp_reset_phy(struct efx_nic *efx) { int rc; - rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS, - XFP_MAX_RESET_TIME / XFP_RESET_WAIT, - XFP_RESET_WAIT); + rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS, + XFP_MAX_RESET_TIME / XFP_RESET_WAIT, + XFP_RESET_WAIT); if (rc < 0) goto fail; @@ -126,8 +122,7 @@ static int xfp_reset_phy(struct efx_nic *efx) /* Check that all the MMDs we expect are present and responding. We * expect faults on some if the link is down, but not on the PHY XS */ - rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS, - MDIO_MMDREG_DEVS_PHYXS); + rc = efx_mdio_check_mmds(efx, XFP_REQUIRED_DEVS, MDIO_DEVS_PHYXS); if (rc < 0) goto fail; @@ -143,7 +138,7 @@ static int xfp_reset_phy(struct efx_nic *efx) static int xfp_phy_init(struct efx_nic *efx) { struct xfp_phy_data *phy_data; - u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); + u32 devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS); int rc; phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); @@ -152,8 +147,8 @@ static int xfp_phy_init(struct efx_nic *efx) efx->phy_data = phy_data; EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", - devid, mdio_id_oui(devid), mdio_id_model(devid), - mdio_id_rev(devid)); + devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid), + efx_mdio_id_rev(devid)); phy_data->phy_mode = efx->phy_mode; @@ -179,7 +174,7 @@ static void xfp_phy_clear_interrupt(struct efx_nic *efx) static int xfp_link_ok(struct efx_nic *efx) { - return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS); + return efx_mdio_links_ok(efx, XFP_REQUIRED_DEVS); } static void xfp_phy_poll(struct efx_nic *efx) @@ -200,9 +195,9 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) * or optical transceivers, varying somewhat between * firmware versions. Only 'static mode' appears to * cover everything. */ - mdio_clause45_set_flag( - efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_FTX_CTRL2_REG, PMA_PMD_FTX_STATIC_LBN, + mdio_set_flag( + &efx->mdio, efx->mdio.prtad, MDIO_MMD_PMAPMD, + PMA_PMD_FTX_CTRL2_REG, 1 << PMA_PMD_FTX_STATIC_LBN, efx->phy_mode & PHY_MODE_TX_DISABLED || efx->phy_mode & PHY_MODE_LOW_POWER || efx->loopback_mode == LOOPBACK_PCS || @@ -213,10 +208,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) (phy_data->phy_mode & PHY_MODE_TX_DISABLED)) xfp_reset_phy(efx); - mdio_clause45_transmit_disable(efx); + efx_mdio_transmit_disable(efx); } - mdio_clause45_phy_reconfigure(efx); + efx_mdio_phy_reconfigure(efx); phy_data->phy_mode = efx->phy_mode; efx->link_up = xfp_link_ok(efx); @@ -225,6 +220,10 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) efx->link_fc = efx->wanted_fc; } +static void xfp_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +{ + mdio45_ethtool_gset(&efx->mdio, ecmd); +} static void xfp_phy_fini(struct efx_nic *efx) { @@ -243,8 +242,8 @@ struct efx_phy_operations falcon_xfp_phy_ops = { .poll = xfp_phy_poll, .fini = xfp_phy_fini, .clear_interrupt = xfp_phy_clear_interrupt, - .get_settings = mdio_clause45_get_settings, - .set_settings = mdio_clause45_set_settings, + .get_settings = xfp_phy_get_settings, + .set_settings = efx_mdio_set_settings, .mmds = XFP_REQUIRED_DEVS, .loopbacks = XFP_LOOPBACKS, }; -- cgit v1.2.3 From 23c3320cb039debfb94b27e8e9bfe26dd47692c3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:06:34 +0000 Subject: chelsio: Use generic MDIO definitions and mdio_mii_ioctl() Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/chelsio/common.h | 2 +- drivers/net/chelsio/cphy.h | 45 +++++++++++++++++++++++------------------ drivers/net/chelsio/cxgb2.c | 36 +++------------------------------ drivers/net/chelsio/mv88x201x.c | 45 +++++++++++++++++++++-------------------- drivers/net/chelsio/my3126.c | 10 +++++---- drivers/net/chelsio/subr.c | 43 +++++++++++++++++++++------------------ 7 files changed, 82 insertions(+), 100 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2f81db51b45d..1ccd54714c4c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2450,6 +2450,7 @@ config CHELSIO_T1 tristate "Chelsio 10Gb Ethernet support" depends on PCI select CRC32 + select MDIO help This driver supports Chelsio gigabit and 10-gigabit Ethernet cards. More information about adapter features and diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 4bd2455b0fe3..699d22c5fe09 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h index 79d855e267e0..8b5165a5af3f 100644 --- a/drivers/net/chelsio/cphy.h +++ b/drivers/net/chelsio/cphy.h @@ -43,10 +43,11 @@ struct mdio_ops { void (*init)(adapter_t *adapter, const struct board_info *bi); - int (*read)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*write)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + int (*read)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr); + int (*write)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val); + unsigned mode_support; }; /* PHY interrupt types */ @@ -83,11 +84,12 @@ struct cphy_ops { int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex); int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed, int *duplex, int *fc); + + u32 mmds; }; /* A PHY instance */ struct cphy { - int addr; /* PHY address */ int state; /* Link status state machine */ adapter_t *adapter; /* associated adapter */ @@ -101,36 +103,37 @@ struct cphy { u32 elmer_gpo; const struct cphy_ops *ops; /* PHY operations */ - int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + struct mdio_if_info mdio; struct cphy_instance *instance; }; /* Convenience MDIO read/write wrappers */ -static inline int mdio_read(struct cphy *cphy, int mmd, int reg, - unsigned int *valp) +static inline int cphy_mdio_read(struct cphy *cphy, int mmd, int reg, + unsigned int *valp) { - return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp); + int rc = cphy->mdio.mdio_read(cphy->mdio.dev, cphy->mdio.prtad, mmd, + reg); + *valp = (rc >= 0) ? rc : -1; + return (rc >= 0) ? 0 : rc; } -static inline int mdio_write(struct cphy *cphy, int mmd, int reg, - unsigned int val) +static inline int cphy_mdio_write(struct cphy *cphy, int mmd, int reg, + unsigned int val) { - return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val); + return cphy->mdio.mdio_write(cphy->mdio.dev, cphy->mdio.prtad, mmd, + reg, val); } static inline int simple_mdio_read(struct cphy *cphy, int reg, unsigned int *valp) { - return mdio_read(cphy, 0, reg, valp); + return cphy_mdio_read(cphy, MDIO_DEVAD_NONE, reg, valp); } static inline int simple_mdio_write(struct cphy *cphy, int reg, unsigned int val) { - return mdio_write(cphy, 0, reg, val); + return cphy_mdio_write(cphy, MDIO_DEVAD_NONE, reg, val); } /* Convenience initializer */ @@ -139,11 +142,13 @@ static inline void cphy_init(struct cphy *phy, adapter_t *adapter, const struct mdio_ops *mdio_ops) { phy->adapter = adapter; - phy->addr = phy_addr; phy->ops = phy_ops; if (mdio_ops) { - phy->mdio_read = mdio_ops->read; - phy->mdio_write = mdio_ops->write; + phy->mdio.prtad = phy_addr; + phy->mdio.mmds = phy_ops->mmds; + phy->mdio.mode_support = mdio_ops->mode_support; + phy->mdio.mdio_read = mdio_ops->read; + phy->mdio.mdio_write = mdio_ops->write; } } diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index fa06994f9737..082cdb28b510 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -589,7 +589,7 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) } cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - cmd->phy_address = p->phy->addr; + cmd->phy_address = p->phy->mdio.prtad; cmd->transceiver = XCVR_EXTERNAL; cmd->autoneg = p->link_config.autoneg; cmd->maxtxpkt = 0; @@ -849,39 +849,9 @@ static const struct ethtool_ops t1_ethtool_ops = { static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { struct adapter *adapter = dev->ml_priv; - struct mii_ioctl_data *data = if_mii(req); - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = adapter->port[dev->if_port].phy->addr; - /* FALLTHRU */ - case SIOCGMIIREG: { - struct cphy *phy = adapter->port[dev->if_port].phy; - u32 val; - - if (!phy->mdio_read) - return -EOPNOTSUPP; - phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f, - &val); - data->val_out = val; - break; - } - case SIOCSMIIREG: { - struct cphy *phy = adapter->port[dev->if_port].phy; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!phy->mdio_write) - return -EOPNOTSUPP; - phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f, - data->val_in); - break; - } + struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio; - default: - return -EOPNOTSUPP; - } - return 0; + return mdio_mii_ioctl(mdio, if_mii(req), cmd); } static int t1_change_mtu(struct net_device *dev, int new_mtu) diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c index cd856041af34..29e0cba48d53 100644 --- a/drivers/net/chelsio/mv88x201x.c +++ b/drivers/net/chelsio/mv88x201x.c @@ -53,7 +53,7 @@ static int led_init(struct cphy *cphy) * Writing these bits maps control to another * register. mmd(0x1) addr(0x7) */ - mdio_write(cphy, 0x3, 0x8304, 0xdddd); + cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd); return 0; } @@ -62,14 +62,14 @@ static int led_link(struct cphy *cphy, u32 do_enable) u32 led = 0; #define LINK_ENABLE_BIT 0x1 - mdio_read(cphy, 0x1, 0x7, &led); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led); if (do_enable & LINK_ENABLE_BIT) { led |= LINK_ENABLE_BIT; - mdio_write(cphy, 0x1, 0x7, led); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led); } else { led &= ~LINK_ENABLE_BIT; - mdio_write(cphy, 0x1, 0x7, led); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led); } return 0; } @@ -86,7 +86,7 @@ static int mv88x201x_reset(struct cphy *cphy, int wait) static int mv88x201x_interrupt_enable(struct cphy *cphy) { /* Enable PHY LASI interrupts. */ - mdio_write(cphy, 0x1, 0x9002, 0x1); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x1); /* Enable Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { @@ -102,7 +102,7 @@ static int mv88x201x_interrupt_enable(struct cphy *cphy) static int mv88x201x_interrupt_disable(struct cphy *cphy) { /* Disable PHY LASI interrupts. */ - mdio_write(cphy, 0x1, 0x9002, 0x0); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x0); /* Disable Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { @@ -122,25 +122,25 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy) #ifdef MV88x2010_LINK_STATUS_BUGS /* Required to read twice before clear takes affect. */ - mdio_read(cphy, 0x1, 0x9003, &val); - mdio_read(cphy, 0x1, 0x9004, &val); - mdio_read(cphy, 0x1, 0x9005, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val); /* Read this register after the others above it else * the register doesn't clear correctly. */ - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); #endif /* Clear link status. */ - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); /* Clear PHY LASI interrupts. */ - mdio_read(cphy, 0x1, 0x9005, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val); #ifdef MV88x2010_LINK_STATUS_BUGS /* Do it again. */ - mdio_read(cphy, 0x1, 0x9003, &val); - mdio_read(cphy, 0x1, 0x9004, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val); #endif /* Clear Marvell interrupts through Elmer0. */ @@ -172,13 +172,12 @@ static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok, int *speed, int *duplex, int *fc) { u32 val = 0; -#define LINK_STATUS_BIT 0x4 if (link_ok) { /* Read link status. */ - mdio_read(cphy, 0x1, 0x1, &val); - val &= LINK_STATUS_BIT; - *link_ok = (val == LINK_STATUS_BIT); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); + val &= MDIO_STAT1_LSTATUS; + *link_ok = (val == MDIO_STAT1_LSTATUS); /* Turn on/off Link LED */ led_link(cphy, *link_ok); } @@ -205,6 +204,8 @@ static struct cphy_ops mv88x201x_ops = { .interrupt_handler = mv88x201x_interrupt_handler, .get_link_status = mv88x201x_get_link_status, .set_loopback = mv88x201x_set_loopback, + .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS | MDIO_DEVS_WIS), }; static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr, @@ -219,12 +220,12 @@ static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr, cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops); /* Commands the PHY to enable XFP's clock. */ - mdio_read(cphy, 0x3, 0x8300, &val); - mdio_write(cphy, 0x3, 0x8300, val | 1); + cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val); + cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1); /* Clear link status. Required because of a bug in the PHY. */ - mdio_read(cphy, 0x1, 0x8, &val); - mdio_read(cphy, 0x3, 0x8, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val); + cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val); /* Allows for Link,Ack LED turn on/off */ led_init(cphy); diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c index 040acd29995a..977c7e08b0e0 100644 --- a/drivers/net/chelsio/my3126.c +++ b/drivers/net/chelsio/my3126.c @@ -43,11 +43,11 @@ static int my3126_interrupt_handler(struct cphy *cphy) adapter = cphy->adapter; if (cphy->count == 50) { - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val16 = (u16) val; status = cphy->bmsr ^ val16; - if (status & BMSR_LSTATUS) + if (status & MDIO_STAT1_LSTATUS) t1_link_changed(adapter, 0); cphy->bmsr = val16; @@ -114,14 +114,14 @@ static int my3126_get_link_status(struct cphy *cphy, adapter_t *adapter; adapter = cphy->adapter; - mdio_read(cphy, 0x1, 0x1, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val16 = (u16) val; /* Populate elmer_gpo with the register value */ t1_tpi_read(adapter, A_ELMER0_GPO, &val); cphy->elmer_gpo = val; - *link_ok = (val16 & BMSR_LSTATUS); + *link_ok = (val16 & MDIO_STAT1_LSTATUS); if (*link_ok) { /* Turn on the LED. */ @@ -163,6 +163,8 @@ static struct cphy_ops my3126_ops = { .interrupt_handler = my3126_interrupt_handler, .get_link_status = my3126_get_link_status, .set_loopback = my3126_set_loopback, + .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | + MDIO_DEVS_PHYXS), }; static struct cphy *my3126_phy_create(adapter_t *adapter, diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 7adf30230c4f..2564312b3056 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -284,32 +284,29 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi) /* * Elmer MI1 MDIO read/write operations. */ -static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); - - if (mmd_addr) - return -EINVAL; + unsigned int val; spin_lock(&adapter->tpi_lock); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ); mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); - __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); + __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val); spin_unlock(&adapter->tpi_lock); - return 0; + return val; } -static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); - if (mmd_addr) - return -EINVAL; - spin_lock(&adapter->tpi_lock); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); @@ -324,16 +321,19 @@ static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr, static const struct mdio_ops mi1_mdio_ops = { .init = mi1_mdio_init, .read = mi1_mdio_read, - .write = mi1_mdio_write + .write = mi1_mdio_write, + .mode_support = MDIO_SUPPORTS_C22 }; #endif #endif -static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); + unsigned int val; spin_lock(&adapter->tpi_lock); @@ -350,14 +350,15 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); /* Read the data. */ - __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); + __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val); spin_unlock(&adapter->tpi_lock); - return 0; + return val; } -static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr, + int mmd_addr, u16 reg_addr, u16 val) { + struct adapter *adapter = dev->ml_priv; u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); spin_lock(&adapter->tpi_lock); @@ -380,7 +381,8 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, static const struct mdio_ops mi1_mdio_ext_ops = { .init = mi1_mdio_init, .read = mi1_mdio_ext_read, - .write = mi1_mdio_ext_write + .write = mi1_mdio_ext_write, + .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22 }; enum { @@ -1140,6 +1142,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, adapter->name, i); goto error; } + adapter->port[i].phy->mdio.dev = adapter->port[i].dev; adapter->port[i].mac = mac = bi->gmac->create(adapter, i); if (!mac) { -- cgit v1.2.3 From 0f07c4ee8c800923ae7918c231532a9256233eed Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:07:20 +0000 Subject: cxgb3: Use generic MDIO definitions and mdio_mii_ioctl() Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/cxgb3/ael1002.c | 146 +++++++++++++++++++++-------------------- drivers/net/cxgb3/common.h | 53 +++++++-------- drivers/net/cxgb3/cxgb3_main.c | 71 ++++---------------- drivers/net/cxgb3/t3_hw.c | 78 ++++++++++++---------- drivers/net/cxgb3/vsc8211.c | 70 +++++++++++--------- 6 files changed, 195 insertions(+), 224 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1ccd54714c4c..435bbc96444f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2483,6 +2483,7 @@ config CHELSIO_T3 tristate "Chelsio Communications T3 10Gb Ethernet support" depends on CHELSIO_T3_DEPENDS select FW_LOADER + select MDIO help This driver supports Chelsio T3-based gigabit and 10Gb Ethernet adapters. diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c index e1b22490ff59..bebc00d2424d 100644 --- a/drivers/net/cxgb3/ael1002.c +++ b/drivers/net/cxgb3/ael1002.c @@ -33,14 +33,6 @@ #include "regs.h" enum { - PMD_RSD = 10, /* PMA/PMD receive signal detect register */ - PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */ - PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */ - XS_LN_STAT = 24 /* XS lane status register */ -}; - -enum { - AEL100X_TX_DISABLE = 9, AEL100X_TX_CONFIG1 = 0xc002, AEL1002_PWR_DOWN_HI = 0xc011, AEL1002_PWR_DOWN_LO = 0xc012, @@ -74,8 +66,8 @@ static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) for (err = 0; rv->mmd_addr && !err; rv++) { if (rv->clear_bits == 0xffff) - err = mdio_write(phy, rv->mmd_addr, rv->reg_addr, - rv->set_bits); + err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr, + rv->set_bits); else err = t3_mdio_change_bits(phy, rv->mmd_addr, rv->reg_addr, rv->clear_bits, @@ -86,7 +78,8 @@ static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) static void ael100x_txon(struct cphy *phy) { - int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; + int tx_on_gpio = + phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; msleep(100); t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); @@ -97,10 +90,11 @@ static int ael1002_power_down(struct cphy *phy, int enable) { int err; - err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable); if (!err) - err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, - BMCR_PDOWN, enable ? BMCR_PDOWN : 0); + err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, + MDIO_MMD_PMAPMD, MDIO_CTRL1, + MDIO_CTRL1_LPOWER, enable); return err; } @@ -109,11 +103,11 @@ static int ael1002_reset(struct cphy *phy, int wait) int err; if ((err = ael1002_power_down(phy, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || - (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) || + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) || + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) || + (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) || + (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN, 0, 1 << 5))) return err; return 0; @@ -132,12 +126,15 @@ static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed, { if (link_ok) { unsigned int stat0, stat1, stat2; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, + MDIO_PMA_RXDET, &stat0); if (!err) - err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1); + err = t3_mdio_read(phy, MDIO_MMD_PCS, + MDIO_PCS_10GBRT_STAT1, &stat1); if (!err) - err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); + err = t3_mdio_read(phy, MDIO_MMD_PHYXS, + MDIO_PHYXS_LNSTAT, &stat2); if (err) return err; *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1; @@ -157,6 +154,7 @@ static struct cphy_ops ael1002_ops = { .intr_handler = ael1002_intr_noop, .get_link_status = get_link_status_r, .power_down = ael1002_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -171,13 +169,13 @@ int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, static int ael1006_reset(struct cphy *phy, int wait) { - return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); + return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait); } static int ael1006_power_down(struct cphy *phy, int enable) { - return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, - BMCR_PDOWN, enable ? BMCR_PDOWN : 0); + return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD, + MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable); } static struct cphy_ops ael1006_ops = { @@ -188,6 +186,7 @@ static struct cphy_ops ael1006_ops = { .intr_handler = t3_phy_lasi_intr_handler, .get_link_status = get_link_status_r, .power_down = ael1006_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -203,9 +202,9 @@ int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, static int ael2005_setup_sr_edc(struct cphy *phy) { static struct reg_val regs[] = { - { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 }, - { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a }, - { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 }, + { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 }, + { MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a }, + { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 }, { 0, 0, 0, 0 } }; static u16 sr_edc[] = { @@ -490,8 +489,8 @@ static int ael2005_setup_sr_edc(struct cphy *phy) msleep(50); for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2) - err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i], - sr_edc[i + 1]); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i], + sr_edc[i + 1]); if (!err) phy->priv = edc_sr; return err; @@ -500,12 +499,12 @@ static int ael2005_setup_sr_edc(struct cphy *phy) static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) { static struct reg_val regs[] = { - { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 }, + { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 }, { 0, 0, 0, 0 } }; static struct reg_val preemphasis[] = { - { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 }, - { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 }, + { MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 }, + { MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 }, { 0, 0, 0, 0 } }; static u16 twinax_edc[] = { @@ -887,8 +886,8 @@ static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) msleep(50); for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2) - err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i], - twinax_edc[i + 1]); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i], + twinax_edc[i + 1]); if (!err) phy->priv = edc_twinax; return err; @@ -899,26 +898,26 @@ static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) int i, err; unsigned int stat, data; - err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, - (dev_addr << 8) | (1 << 8) | word_addr); + err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL, + (dev_addr << 8) | (1 << 8) | word_addr); if (err) return err; for (i = 0; i < 5; i++) { msleep(1); - err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat); if (err) return err; if ((stat & 3) == 1) { - err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, - &data); + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA, + &data); if (err) return err; return data >> 8; } } CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n", - phy->addr, word_addr); + phy->mdio.prtad, word_addr); return -ETIMEDOUT; } @@ -927,7 +926,7 @@ static int get_module_type(struct cphy *phy, int delay_ms) int v; unsigned int stat; - v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat); + v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat); if (v) return v; @@ -971,48 +970,48 @@ unknown: static int ael2005_intr_enable(struct cphy *phy) { - int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200); + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200); return err ? err : t3_phy_lasi_intr_enable(phy); } static int ael2005_intr_disable(struct cphy *phy) { - int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100); + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100); return err ? err : t3_phy_lasi_intr_disable(phy); } static int ael2005_intr_clear(struct cphy *phy) { - int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00); + int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00); return err ? err : t3_phy_lasi_intr_clear(phy); } static int ael2005_reset(struct cphy *phy, int wait) { static struct reg_val regs0[] = { - { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 }, - { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 }, - { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, - { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 }, + { MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 }, + { MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 }, + { MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 }, + { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 }, { 0, 0, 0, 0 } }; static struct reg_val regs1[] = { - { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 }, - { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 }, + { MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 }, + { MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 }, { 0, 0, 0, 0 } }; int err; unsigned int lasi_ctrl; - err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl); + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_CTRL, &lasi_ctrl); if (err) return err; - err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0); + err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0); if (err) return err; @@ -1051,13 +1050,13 @@ static int ael2005_intr_handler(struct cphy *phy) unsigned int stat; int ret, edc_needed, cause = 0; - ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat); + ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat); if (ret) return ret; if (stat & AEL2005_MODDET_IRQ) { - ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, - 0xd00); + ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, + 0xd00); if (ret) return ret; @@ -1098,6 +1097,7 @@ static struct cphy_ops ael2005_ops = { .intr_handler = ael2005_intr_handler, .get_link_status = get_link_status_r, .power_down = ael1002_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -1107,7 +1107,7 @@ int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | SUPPORTED_IRQ, "10GBASE-R"); msleep(125); - return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0, + return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0, 1 << 5); } @@ -1119,12 +1119,15 @@ static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, { if (link_ok) { unsigned int stat0, stat1, stat2; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, + MDIO_PMA_RXDET, &stat0); if (!err) - err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1); + err = t3_mdio_read(phy, MDIO_MMD_PCS, + MDIO_PCS_10GBX_STAT1, &stat1); if (!err) - err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); + err = t3_mdio_read(phy, MDIO_MMD_PHYXS, + MDIO_PHYXS_LNSTAT, &stat2); if (err) return err; *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1; @@ -1144,6 +1147,7 @@ static struct cphy_ops qt2045_ops = { .intr_handler = t3_phy_lasi_intr_handler, .get_link_status = get_link_status_x, .power_down = ael1006_power_down, + .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, }; int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, @@ -1159,9 +1163,10 @@ int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, * Some cards where the PHY is supposed to be at address 0 actually * have it at 1. */ - if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && + if (!phy_addr && + !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) && stat == 0xffff) - phy->addr = 1; + phy->mdio.prtad = 1; return 0; } @@ -1175,15 +1180,16 @@ static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, { if (link_ok) { unsigned int status; + int prtad = phy->mdio.prtad; status = t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | + XGM_REG(A_XGM_SERDES_STAT0, prtad)) | t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | + XGM_REG(A_XGM_SERDES_STAT1, prtad)) | t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | + XGM_REG(A_XGM_SERDES_STAT2, prtad)) | t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); + XGM_REG(A_XGM_SERDES_STAT3, prtad)); *link_ok = !(status & F_LOWSIG0); } if (speed) @@ -1211,7 +1217,7 @@ static struct cphy_ops xaui_direct_ops = { int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops) { - cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops, + cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops, SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, "10GBASE-CX4"); return 0; diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index e508dc32f3ec..3147789aecec 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "version.h" #define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__) @@ -184,10 +184,11 @@ struct cphy; struct adapter; struct mdio_ops { - int (*read)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*write)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + int (*read)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr); + int (*write)(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val); + unsigned mode_support; }; struct adapter_info { @@ -520,17 +521,6 @@ enum { MAC_RXFIFO_SIZE = 32768 }; -/* IEEE 802.3 specified MDIO devices */ -enum { - MDIO_DEV_PMA_PMD = 1, - MDIO_DEV_WIS = 2, - MDIO_DEV_PCS = 3, - MDIO_DEV_XGXS = 4, - MDIO_DEV_ANEG = 7, - MDIO_DEV_VEND1 = 30, - MDIO_DEV_VEND2 = 31 -}; - /* LASI control and status registers */ enum { RX_ALARM_CTRL = 0x9000, @@ -583,11 +573,12 @@ struct cphy_ops { int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed, int *duplex, int *fc); int (*power_down)(struct cphy *phy, int enable); + + u32 mmds; }; /* A PHY instance */ struct cphy { - u8 addr; /* PHY address */ u8 modtype; /* PHY module type */ short priv; /* scratch pad */ unsigned int caps; /* PHY capabilities */ @@ -595,23 +586,23 @@ struct cphy { const char *desc; /* PHY description */ unsigned long fifo_errors; /* FIFO over/under-flows */ const struct cphy_ops *ops; /* PHY operations */ - int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*mdio_write)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); + struct mdio_if_info mdio; }; /* Convenience MDIO read/write wrappers */ -static inline int mdio_read(struct cphy *phy, int mmd, int reg, - unsigned int *valp) +static inline int t3_mdio_read(struct cphy *phy, int mmd, int reg, + unsigned int *valp) { - return phy->mdio_read(phy->adapter, phy->addr, mmd, reg, valp); + int rc = phy->mdio.mdio_read(phy->mdio.dev, phy->mdio.prtad, mmd, reg); + *valp = (rc >= 0) ? rc : -1; + return (rc >= 0) ? 0 : rc; } -static inline int mdio_write(struct cphy *phy, int mmd, int reg, - unsigned int val) +static inline int t3_mdio_write(struct cphy *phy, int mmd, int reg, + unsigned int val) { - return phy->mdio_write(phy->adapter, phy->addr, mmd, reg, val); + return phy->mdio.mdio_write(phy->mdio.dev, phy->mdio.prtad, mmd, + reg, val); } /* Convenience initializer */ @@ -620,14 +611,16 @@ static inline void cphy_init(struct cphy *phy, struct adapter *adapter, const struct mdio_ops *mdio_ops, unsigned int caps, const char *desc) { - phy->addr = phy_addr; phy->caps = caps; phy->adapter = adapter; phy->desc = desc; phy->ops = phy_ops; if (mdio_ops) { - phy->mdio_read = mdio_ops->read; - phy->mdio_write = mdio_ops->write; + phy->mdio.prtad = phy_addr; + phy->mdio.mmds = phy_ops->mmds; + phy->mdio.mode_support = mdio_ops->mode_support; + phy->mdio.mdio_read = mdio_ops->read; + phy->mdio.mdio_write = mdio_ops->write; } } diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 7ea48414c6cb..0b87fee023f5 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -1593,7 +1593,7 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) } cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - cmd->phy_address = p->phy.addr; + cmd->phy_address = p->phy.mdio.prtad; cmd->transceiver = XCVR_EXTERNAL; cmd->autoneg = p->link_config.autoneg; cmd->maxtxpkt = 0; @@ -2308,70 +2308,25 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) struct mii_ioctl_data *data = if_mii(req); struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - int ret, mmd; switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = pi->phy.addr; + case SIOCGMIIREG: + case SIOCSMIIREG: + /* Convert phy_id from older PRTAD/DEVAD format */ + if (is_10G(adapter) && + !mdio_phy_id_is_c45(data->phy_id) && + (data->phy_id & 0x1f00) && + !(data->phy_id & 0xe0e0)) + data->phy_id = mdio_phy_id_c45(data->phy_id >> 8, + data->phy_id & 0x1f); /* FALLTHRU */ - case SIOCGMIIREG:{ - u32 val; - struct cphy *phy = &pi->phy; - - if (!phy->mdio_read) - return -EOPNOTSUPP; - if (is_10G(adapter)) { - mmd = data->phy_id >> 8; - if (!mmd) - mmd = MDIO_DEV_PCS; - else if (mmd > MDIO_DEV_VEND2) - return -EINVAL; - - ret = - phy->mdio_read(adapter, data->phy_id & 0x1f, - mmd, data->reg_num, &val); - } else - ret = - phy->mdio_read(adapter, data->phy_id & 0x1f, - 0, data->reg_num & 0x1f, - &val); - if (!ret) - data->val_out = val; - break; - } - case SIOCSMIIREG:{ - struct cphy *phy = &pi->phy; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!phy->mdio_write) - return -EOPNOTSUPP; - if (is_10G(adapter)) { - mmd = data->phy_id >> 8; - if (!mmd) - mmd = MDIO_DEV_PCS; - else if (mmd > MDIO_DEV_VEND2) - return -EINVAL; - - ret = - phy->mdio_write(adapter, - data->phy_id & 0x1f, mmd, - data->reg_num, - data->val_in); - } else - ret = - phy->mdio_write(adapter, - data->phy_id & 0x1f, 0, - data->reg_num & 0x1f, - data->val_in); - break; - } + case SIOCGMIIPHY: + return mdio_mii_ioctl(&pi->phy.mdio, data, cmd); case SIOCCHIOCTL: return cxgb_extension_ioctl(dev, req->ifr_data); default: return -EOPNOTSUPP; } - return ret; } static int cxgb_change_mtu(struct net_device *dev, int new_mtu) diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index e1bd690ff831..1dd1637663a3 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -204,35 +204,33 @@ static void mi1_init(struct adapter *adap, const struct adapter_info *ai) /* * MI1 read/write operations for clause 22 PHYs. */ -static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); - if (mmd_addr) - return -EINVAL; - mutex_lock(&adapter->mdio_lock); t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); t3_write_reg(adapter, A_MI1_ADDR, addr); t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); if (!ret) - *valp = t3_read_reg(adapter, A_MI1_DATA); + ret = t3_read_reg(adapter, A_MI1_DATA); mutex_unlock(&adapter->mdio_lock); return ret; } -static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); - if (mmd_addr) - return -EINVAL; - mutex_lock(&adapter->mdio_lock); t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); t3_write_reg(adapter, A_MI1_ADDR, addr); @@ -244,8 +242,9 @@ static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, } static const struct mdio_ops mi1_mdio_ops = { - t3_mi1_read, - t3_mi1_write + .read = t3_mi1_read, + .write = t3_mi1_write, + .mode_support = MDIO_SUPPORTS_C22 }; /* @@ -268,9 +267,11 @@ static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr, /* * MI1 read/write operations for indirect-addressed PHYs. */ -static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) +static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; mutex_lock(&adapter->mdio_lock); @@ -280,15 +281,17 @@ static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); if (!ret) - *valp = t3_read_reg(adapter, A_MI1_DATA); + ret = t3_read_reg(adapter, A_MI1_DATA); } mutex_unlock(&adapter->mdio_lock); return ret; } -static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) +static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr, + u16 reg_addr, u16 val) { + struct port_info *pi = netdev_priv(dev); + struct adapter *adapter = pi->adapter; int ret; mutex_lock(&adapter->mdio_lock); @@ -304,8 +307,9 @@ static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, } static const struct mdio_ops mi1_mdio_ext_ops = { - mi1_ext_read, - mi1_ext_write + .read = mi1_ext_read, + .write = mi1_ext_write, + .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22 }; /** @@ -325,10 +329,10 @@ int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, int ret; unsigned int val; - ret = mdio_read(phy, mmd, reg, &val); + ret = t3_mdio_read(phy, mmd, reg, &val); if (!ret) { val &= ~clear; - ret = mdio_write(phy, mmd, reg, val | set); + ret = t3_mdio_write(phy, mmd, reg, val | set); } return ret; } @@ -348,15 +352,16 @@ int t3_phy_reset(struct cphy *phy, int mmd, int wait) int err; unsigned int ctl; - err = t3_mdio_change_bits(phy, mmd, MII_BMCR, BMCR_PDOWN, BMCR_RESET); + err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER, + MDIO_CTRL1_RESET); if (err || !wait) return err; do { - err = mdio_read(phy, mmd, MII_BMCR, &ctl); + err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl); if (err) return err; - ctl &= BMCR_RESET; + ctl &= MDIO_CTRL1_RESET; if (ctl) msleep(1); } while (ctl && --wait); @@ -377,7 +382,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) int err; unsigned int val = 0; - err = mdio_read(phy, 0, MII_CTRL1000, &val); + err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val); if (err) return err; @@ -387,7 +392,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) if (advert & ADVERTISED_1000baseT_Full) val |= ADVERTISE_1000FULL; - err = mdio_write(phy, 0, MII_CTRL1000, val); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val); if (err) return err; @@ -404,7 +409,7 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) val |= ADVERTISE_PAUSE_CAP; if (advert & ADVERTISED_Asym_Pause) val |= ADVERTISE_PAUSE_ASYM; - return mdio_write(phy, 0, MII_ADVERTISE, val); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val); } /** @@ -427,7 +432,7 @@ int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert) val |= ADVERTISE_1000XPAUSE; if (advert & ADVERTISED_Asym_Pause) val |= ADVERTISE_1000XPSE_ASYM; - return mdio_write(phy, 0, MII_ADVERTISE, val); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val); } /** @@ -444,7 +449,7 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) int err; unsigned int ctl; - err = mdio_read(phy, 0, MII_BMCR, &ctl); + err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl); if (err) return err; @@ -462,30 +467,30 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) } if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */ ctl |= BMCR_ANENABLE; - return mdio_write(phy, 0, MII_BMCR, ctl); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl); } int t3_phy_lasi_intr_enable(struct cphy *phy) { - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); + return t3_mdio_write(phy, MDIO_MMD_PMAPMD, LASI_CTRL, 1); } int t3_phy_lasi_intr_disable(struct cphy *phy) { - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); + return t3_mdio_write(phy, MDIO_MMD_PMAPMD, LASI_CTRL, 0); } int t3_phy_lasi_intr_clear(struct cphy *phy) { u32 val; - return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); + return t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_STAT, &val); } int t3_phy_lasi_intr_handler(struct cphy *phy) { unsigned int status; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_STAT, &status); if (err) return err; @@ -3863,6 +3868,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, ai->mdio_ops); if (ret) return ret; + p->phy.mdio.dev = adapter->port[i]; mac_prep(&p->mac, adapter, j); /* @@ -3918,7 +3924,7 @@ int t3_replay_prep_adapter(struct adapter *adapter) ; pti = &port_types[adapter->params.vpd.port_type[j]]; - ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL); + ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL); if (ret) return ret; p->phy.ops->power_down(&p->phy, 1); diff --git a/drivers/net/cxgb3/vsc8211.c b/drivers/net/cxgb3/vsc8211.c index d07130971b8f..4f9a1c2724f4 100644 --- a/drivers/net/cxgb3/vsc8211.c +++ b/drivers/net/cxgb3/vsc8211.c @@ -91,17 +91,18 @@ enum { */ static int vsc8211_reset(struct cphy *cphy, int wait) { - return t3_phy_reset(cphy, 0, 0); + return t3_phy_reset(cphy, MDIO_DEVAD_NONE, 0); } static int vsc8211_intr_enable(struct cphy *cphy) { - return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, INTR_MASK); + return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE, + INTR_MASK); } static int vsc8211_intr_disable(struct cphy *cphy) { - return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, 0); + return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE, 0); } static int vsc8211_intr_clear(struct cphy *cphy) @@ -109,18 +110,20 @@ static int vsc8211_intr_clear(struct cphy *cphy) u32 val; /* Clear PHY interrupts by reading the register. */ - return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val); + return t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &val); } static int vsc8211_autoneg_enable(struct cphy *cphy) { - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, + return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR, + BMCR_PDOWN | BMCR_ISOLATE, BMCR_ANENABLE | BMCR_ANRESTART); } static int vsc8211_autoneg_restart(struct cphy *cphy) { - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, + return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR, + BMCR_PDOWN | BMCR_ISOLATE, BMCR_ANRESTART); } @@ -130,9 +133,9 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, unsigned int bmcr, status, lpa, adv; int err, sp = -1, dplx = -1, pause = 0; - err = mdio_read(cphy, 0, MII_BMCR, &bmcr); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr); if (!err) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status); if (err) return err; @@ -142,7 +145,8 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, * once more to get the current link state. */ if (!(status & BMSR_LSTATUS)) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, + &status); if (err) return err; *link_ok = (status & BMSR_LSTATUS) != 0; @@ -156,7 +160,8 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, else sp = SPEED_10; } else if (status & BMSR_ANEGCOMPLETE) { - err = mdio_read(cphy, 0, VSC8211_AUX_CTRL_STAT, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_AUX_CTRL_STAT, + &status); if (err) return err; @@ -170,9 +175,11 @@ static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, sp = SPEED_1000; if (fc && dplx == DUPLEX_FULL) { - err = mdio_read(cphy, 0, MII_LPA, &lpa); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA, + &lpa); if (!err) - err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, + MII_ADVERTISE, &adv); if (err) return err; @@ -202,9 +209,9 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, unsigned int bmcr, status, lpa, adv; int err, sp = -1, dplx = -1, pause = 0; - err = mdio_read(cphy, 0, MII_BMCR, &bmcr); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr); if (!err) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status); if (err) return err; @@ -214,7 +221,8 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, * once more to get the current link state. */ if (!(status & BMSR_LSTATUS)) - err = mdio_read(cphy, 0, MII_BMSR, &status); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, + &status); if (err) return err; *link_ok = (status & BMSR_LSTATUS) != 0; @@ -228,9 +236,10 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, else sp = SPEED_10; } else if (status & BMSR_ANEGCOMPLETE) { - err = mdio_read(cphy, 0, MII_LPA, &lpa); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA, &lpa); if (!err) - err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_ADVERTISE, + &adv); if (err) return err; @@ -270,23 +279,23 @@ static int vsc8211_set_automdi(struct cphy *phy, int enable) { int err; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0x52b5); if (err) return err; - err = mdio_write(phy, 0, 18, 0x12); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 18, 0x12); if (err) return err; - err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 17, enable ? 0x2803 : 0x3003); if (err) return err; - err = mdio_write(phy, 0, 16, 0x87fa); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 16, 0x87fa); if (err) return err; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0); if (err) return err; @@ -315,7 +324,7 @@ static int vsc8211_intr_handler(struct cphy *cphy) unsigned int cause; int err, cphy_cause = 0; - err = mdio_read(cphy, 0, VSC8211_INTR_STATUS, &cause); + err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &cause); if (err) return err; @@ -367,12 +376,13 @@ int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T"); msleep(20); /* PHY needs ~10ms to start responding to MDIO */ - err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val); + err = t3_mdio_read(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL, &val); if (err) return err; if (val & VSC_CTRL_MEDIA_MODE_HI) { /* copper interface, just need to configure the LEDs */ - return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100); + return t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_LED_CTRL, + 0x100); } phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | @@ -380,20 +390,20 @@ int t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, phy->desc = "1000BASE-X"; phy->ops = &vsc8211_fiber_ops; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 1); if (err) return err; - err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_SIGDET_CTRL, 1); if (err) return err; - err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0); if (err) return err; - err = mdio_write(phy, 0, VSC8211_EXT_CTRL, - val | VSC_CTRL_CLAUSE37_VIEW); + err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL, + val | VSC_CTRL_CLAUSE37_VIEW); if (err) return err; -- cgit v1.2.3 From 6b73e10d2d89f9ce773f9b47d61b195936d059ba Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:08:58 +0000 Subject: ixgbe: Use generic MDIO definitions and functions Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/ixgbe/ixgbe_82598.c | 33 +++++++------- drivers/net/ixgbe/ixgbe_82599.c | 17 ++++---- drivers/net/ixgbe/ixgbe_main.c | 42 ++++++++++++++++++ drivers/net/ixgbe/ixgbe_phy.c | 95 ++++++++++++++--------------------------- drivers/net/ixgbe/ixgbe_type.h | 33 ++------------ 6 files changed, 102 insertions(+), 119 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 435bbc96444f..b8727d54bdbb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2519,6 +2519,7 @@ config ENIC config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" depends on PCI && INET + select MDIO ---help--- This driver supports Intel(R) 10GbE PCI Express family of adapters. For more information on how to identify your adapter, go diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 03eb54f4f1cc..e051964347e4 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -229,14 +229,13 @@ static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw, *speed = 0; *autoneg = true; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, &speed_ability); if (status == 0) { - if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + if (speed_ability & MDIO_SPEED_10G) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + if (speed_ability & MDIO_PMA_SPEED_1000) *speed |= IXGBE_LINK_SPEED_1GB_FULL; } @@ -526,9 +525,9 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, * clear indicates active; set indicates inactive. */ if (hw->phy.type == ixgbe_phy_nl) { - hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); - hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); - hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, + hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg); + hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg); + hw->phy.ops.read_reg(hw, 0xC00C, MDIO_MMD_PMAPMD, &adapt_comp_reg); if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { @@ -541,10 +540,10 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, } msleep(100); hw->phy.ops.read_reg(hw, 0xC79F, - IXGBE_TWINAX_DEV, + MDIO_MMD_PMAPMD, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, - IXGBE_TWINAX_DEV, + MDIO_MMD_PMAPMD, &adapt_comp_reg); } } else { @@ -990,14 +989,14 @@ static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK); hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + MDIO_MMD_PMAPMD, sfp_addr); /* Poll status */ for (i = 0; i < 100; i++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + MDIO_MMD_PMAPMD, &sfp_stat); sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK; if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS) @@ -1013,7 +1012,7 @@ static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, /* Read data */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data); + MDIO_MMD_PMAPMD, &sfp_data); *eeprom_data = (u8)(sfp_data >> 8); } else { @@ -1045,13 +1044,13 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) * physical layer because 10GBase-T PHYs use LMS = KX4/KX */ if (hw->phy.type == ixgbe_phy_tn || hw->phy.type == ixgbe_phy_cu_unknown) { - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); - if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) + hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD, + &ext_ability); + if (ext_ability & MDIO_PMA_EXTABLE_10GBT) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; - if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) + if (ext_ability & MDIO_PMA_EXTABLE_1000BT) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; - if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) + if (ext_ability & MDIO_PMA_EXTABLE_100BTX) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; goto out; } diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 9e824b450416..6038ed14c9f9 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -314,14 +314,13 @@ static s32 ixgbe_get_copper_link_capabilities_82599(struct ixgbe_hw *hw, *speed = 0; *autoneg = true; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD, &speed_ability); if (status == 0) { - if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + if (speed_ability & MDIO_SPEED_10G) *speed |= IXGBE_LINK_SPEED_10GB_FULL; - if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + if (speed_ability & MDIO_PMA_SPEED_1000) *speed |= IXGBE_LINK_SPEED_1GB_FULL; } @@ -1153,13 +1152,13 @@ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) if (hw->phy.type == ixgbe_phy_tn || hw->phy.type == ixgbe_phy_cu_unknown) { - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); - if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) + hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD, + &ext_ability); + if (ext_ability & MDIO_PMA_EXTABLE_10GBT) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; - if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) + if (ext_ability & MDIO_PMA_EXTABLE_1000BT) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; - if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) + if (ext_ability & MDIO_PMA_EXTABLE_100BTX) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; goto out; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 01a88265d401..661bed64407f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4642,6 +4642,40 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p) return 0; } +static int +ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u16 value; + int rc; + + if (prtad != hw->phy.mdio.prtad) + return -EINVAL; + rc = hw->phy.ops.read_reg(hw, addr, devad, &value); + if (!rc) + rc = value; + return rc; +} + +static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad, + u16 addr, u16 value) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + + if (prtad != hw->phy.mdio.prtad) + return -EINVAL; + return hw->phy.ops.write_reg(hw, addr, devad, value); +} + +static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd); +} + #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs @@ -4675,6 +4709,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_vlan_rx_register = ixgbe_vlan_rx_register, .ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid, + .ndo_do_ioctl = ixgbe_ioctl, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ixgbe_netpoll, #endif @@ -4789,6 +4824,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* PHY */ memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops)); hw->phy.sfp_type = ixgbe_sfp_type_unknown; + /* ixgbe_identify_phy_generic will set prtad and mmds properly */ + hw->phy.mdio.prtad = MDIO_PRTAD_NONE; + hw->phy.mdio.mmds = 0; + hw->phy.mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + hw->phy.mdio.dev = netdev; + hw->phy.mdio.mdio_read = ixgbe_mdio_read; + hw->phy.mdio.mdio_write = ixgbe_mdio_write; /* set up this timer and work struct before calling get_invariants * which might start the timer diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 2543c32ca84a..6d385ea3c2a1 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -44,7 +44,6 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data); static bool ixgbe_get_i2c_data(u32 *i2cctl); static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw); -static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw); @@ -61,8 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { - if (ixgbe_validate_phy_addr(hw, phy_addr)) { - hw->phy.addr = phy_addr; + if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { ixgbe_get_phy_id(hw); hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); @@ -77,26 +75,6 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) return status; } -/** - * ixgbe_validate_phy_addr - Determines phy address is valid - * @hw: pointer to hardware structure - * - **/ -static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) -{ - u16 phy_id = 0; - bool valid = false; - - hw->phy.addr = phy_addr; - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); - - if (phy_id != 0xFFFF && phy_id != 0x0) - valid = true; - - return valid; -} - /** * ixgbe_get_phy_id - Get the phy type * @hw: pointer to hardware structure @@ -108,14 +86,12 @@ static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw) u16 phy_id_high = 0; u16 phy_id_low = 0; - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_DEVID1, MDIO_MMD_PMAPMD, &phy_id_high); if (status == 0) { hw->phy.id = (u32)(phy_id_high << 16); - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW, - IXGBE_MDIO_PMA_PMD_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_DEVID2, MDIO_MMD_PMAPMD, &phy_id_low); hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK); hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); @@ -160,9 +136,8 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) * Perform soft PHY reset to the PHY_XS. * This will cause a soft reset to the PHY */ - return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, - IXGBE_MDIO_PHY_XS_RESET); + return hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, + MDIO_CTRL1_RESET); } /** @@ -192,7 +167,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -223,7 +198,8 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << + IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -292,7 +268,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -323,7 +299,8 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | - (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | + (hw->phy.mdio.prtad << + IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); @@ -365,7 +342,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) s32 status = IXGBE_NOT_IMPLEMENTED; u32 time_out; u32 max_time_out = 10; - u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; + u16 autoneg_reg; /* * Set advertisement settings in PHY based on autoneg_advertised @@ -373,36 +350,31 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) * tnx devices cannot be "forced" to a autoneg 10G and fail. But can * for a 1G. */ - hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg); if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) - autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */ + autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; else - autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */ + autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; - hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg); /* Restart PHY autonegotiation and wait for completion */ - hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, &autoneg_reg); - autoneg_reg |= IXGBE_MII_RESTART; + autoneg_reg |= MDIO_AN_CTRL1_RESTART; - hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, autoneg_reg); /* Wait for autonegotiation to finish */ for (time_out = 0; time_out < max_time_out; time_out++) { udelay(10); /* Restart PHY autonegotiation and wait for completion */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &autoneg_reg); - autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; - if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) { + autoneg_reg &= MDIO_AN_STAT1_COMPLETE; + if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) { status = 0; break; } @@ -457,23 +429,21 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) s32 ret_val = 0; u32 i; - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data); /* reset the PHY and poll for completion */ - hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, - (phy_data | IXGBE_MDIO_PHY_XS_RESET)); + hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, + (phy_data | MDIO_CTRL1_RESET)); for (i = 0; i < 100; i++) { - hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, - IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); - if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0) + hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, + &phy_data); + if ((phy_data & MDIO_CTRL1_RESET) == 0) break; msleep(10); } - if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) { + if ((phy_data & MDIO_CTRL1_RESET) != 0) { hw_dbg(hw, "PHY reset did not complete.\n"); ret_val = IXGBE_ERR_PHY; goto out; @@ -509,7 +479,7 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) for (i = 0; i < edata; i++) { hw->eeprom.ops.read(hw, data_offset, &eword); hw->phy.ops.write_reg(hw, phy_offset, - IXGBE_TWINAX_DEV, eword); + MDIO_MMD_PMAPMD, eword); hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword, phy_offset); data_offset++; @@ -1302,7 +1272,7 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, udelay(10); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + MDIO_MMD_VEND1, &phy_data); phy_link = phy_data & IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; @@ -1330,8 +1300,7 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, { s32 status = 0; - status = hw->phy.ops.read_reg(hw, TNX_FW_REV, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + status = hw->phy.ops.read_reg(hw, TNX_FW_REV, MDIO_MMD_VEND1, firmware_version); return status; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index bdfdf3bca273..e49e8af59eda 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -29,6 +29,7 @@ #define _IXGBE_TYPE_H_ #include +#include /* Vendor ID */ #define IXGBE_INTEL_VENDOR_ID 0x8086 @@ -848,13 +849,7 @@ /* Omer bit masks */ #define IXGBE_CORECTL_WRITE_CMD 0x00010000 -/* Device Type definitions for new protocol MDIO commands */ -#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 -#define IXGBE_MDIO_PCS_DEV_TYPE 0x3 -#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4 -#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 -#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ -#define IXGBE_TWINAX_DEV 1 +/* MDIO definitions */ #define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ @@ -865,32 +860,10 @@ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED 0x0018 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED 0x0010 -#define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */ -#define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */ -#define IXGBE_MDIO_PHY_XS_CONTROL 0x0 /* PHY_XS Control Reg */ -#define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */ -#define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ -#define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ -#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */ -#define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */ -#define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */ -#define IXGBE_MDIO_PHY_EXT_ABILITY 0xB /* Ext Ability Reg */ -#define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */ -#define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */ -#define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */ - #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ -/* MII clause 22/28 definitions */ -#define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 - -#define IXGBE_MII_SPEED_SELECTION_REG 0x10 -#define IXGBE_MII_RESTART 0x200 -#define IXGBE_MII_AUTONEG_COMPLETE 0x20 -#define IXGBE_MII_AUTONEG_REG 0x0 - #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 #define IXGBE_MAX_PHY_ADDR 32 @@ -2214,8 +2187,8 @@ struct ixgbe_mac_info { struct ixgbe_phy_info { struct ixgbe_phy_operations ops; + struct mdio_if_info mdio; enum ixgbe_phy_type type; - u32 addr; u32 id; enum ixgbe_sfp_type sfp_type; bool sfp_setup_needed; -- cgit v1.2.3 From cdbf0eb478dd4c76aa665c80976837dc58367f52 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:11:05 +0000 Subject: ixgb: Use generic MDIO definitions Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ixgb/ixgb_hw.c | 20 ++++++++++---------- drivers/net/ixgb/ixgb_hw.h | 14 ++------------ 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c index 11dcda0f453e..ff67a84e6802 100644 --- a/drivers/net/ixgb/ixgb_hw.c +++ b/drivers/net/ixgb/ixgb_hw.c @@ -192,7 +192,7 @@ ixgb_identify_xpak_vendor(struct ixgb_hw *hw) vendor_name[i] = ixgb_read_phy_reg(hw, MDIO_PMA_PMD_XPAK_VENDOR_NAME + i, IXGB_PHY_ADDRESS, - MDIO_PMA_PMD_DID); + MDIO_MMD_PMAPMD); } /* Determine the actual vendor */ @@ -1225,15 +1225,15 @@ ixgb_optics_reset(struct ixgb_hw *hw) u16 mdio_reg; ixgb_write_phy_reg(hw, - MDIO_PMA_PMD_CR1, - IXGB_PHY_ADDRESS, - MDIO_PMA_PMD_DID, - MDIO_PMA_PMD_CR1_RESET); - - mdio_reg = ixgb_read_phy_reg( hw, - MDIO_PMA_PMD_CR1, - IXGB_PHY_ADDRESS, - MDIO_PMA_PMD_DID); + MDIO_CTRL1, + IXGB_PHY_ADDRESS, + MDIO_MMD_PMAPMD, + MDIO_CTRL1_RESET); + + mdio_reg = ixgb_read_phy_reg(hw, + MDIO_CTRL1, + IXGB_PHY_ADDRESS, + MDIO_MMD_PMAPMD); } return; diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h index 831fe0c58b2b..af6ca3aab5ad 100644 --- a/drivers/net/ixgb/ixgb_hw.h +++ b/drivers/net/ixgb/ixgb_hw.h @@ -29,6 +29,8 @@ #ifndef _IXGB_HW_H_ #define _IXGB_HW_H_ +#include + #include "ixgb_osdep.h" /* Enums */ @@ -507,18 +509,6 @@ typedef enum { /* Definitions for the optics devices on the MDIO bus. */ #define IXGB_PHY_ADDRESS 0x0 /* Single PHY, multiple "Devices" */ -/* Standard five-bit Device IDs. See IEEE 802.3ae, clause 45 */ -#define MDIO_PMA_PMD_DID 0x01 -#define MDIO_WIS_DID 0x02 -#define MDIO_PCS_DID 0x03 -#define MDIO_XGXS_DID 0x04 - -/* Standard PMA/PMD registers and bit definitions. */ -/* Note: This is a very limited set of definitions, */ -/* only implemented features are defined. */ -#define MDIO_PMA_PMD_CR1 0x0000 -#define MDIO_PMA_PMD_CR1_RESET 0x8000 - #define MDIO_PMA_PMD_XPAK_VENDOR_NAME 0x803A /* XPAK/XENPAK devices only */ /* Vendor-specific MDIO registers */ -- cgit v1.2.3 From 4023939667a906f0c02022ce7ec06d6512470211 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:13:29 +0000 Subject: s2io: Use generic MDIO definitions Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/s2io-regs.h | 5 ----- drivers/net/s2io.c | 21 +++++++++++---------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index f8274f8941ea..416669fd68c6 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -271,11 +271,6 @@ struct XENA_dev_config { u64 mdio_control; #define MDIO_MMD_INDX_ADDR(val) vBIT(val, 0, 16) #define MDIO_MMD_DEV_ADDR(val) vBIT(val, 19, 5) -#define MDIO_MMD_PMA_DEV_ADDR 0x1 -#define MDIO_MMD_PMD_DEV_ADDR 0x1 -#define MDIO_MMD_WIS_DEV_ADDR 0x2 -#define MDIO_MMD_PCS_DEV_ADDR 0x3 -#define MDIO_MMD_PHYXS_DEV_ADDR 0x4 #define MDIO_MMS_PRT_ADDR(val) vBIT(val, 27, 5) #define MDIO_CTRL_START_TRANS(val) vBIT(val, 56, 4) #define MDIO_OP(val) vBIT(val, 60, 2) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 1a4979f27fb5..80562ea77de3 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -3328,9 +3329,9 @@ static void s2io_updt_xpak_counter(struct net_device *dev) struct stat_block *stat_info = sp->mac_control.stats_info; /* Check the communication with the MDIO slave */ - addr = 0x0000; + addr = MDIO_CTRL1; val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); if((val64 == 0xFFFF) || (val64 == 0x0000)) { DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - " @@ -3338,24 +3339,24 @@ static void s2io_updt_xpak_counter(struct net_device *dev) return; } - /* Check for the expecte value of 2040 at PMA address 0x0000 */ - if(val64 != 0x2040) + /* Check for the expected value of control reg 1 */ + if(val64 != MDIO_CTRL1_SPEED10G) { DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - "); - DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n", - (unsigned long long)val64); + DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x%x\n", + (unsigned long long)val64, MDIO_CTRL1_SPEED10G); return; } /* Loading the DOM register to MDIO register */ addr = 0xA100; - s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev); - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + s2io_mdio_write(MDIO_MMD_PMAPMD, addr, val16, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); /* Reading the Alarm flags */ addr = 0xA070; val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); flag = CHECKBIT(val64, 0x7); type = 1; @@ -3387,7 +3388,7 @@ static void s2io_updt_xpak_counter(struct net_device *dev) /* Reading the Warning flags */ addr = 0xA074; val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev); if(CHECKBIT(val64, 0x7)) stat_info->xpak_stat.warn_transceiver_temp_high++; -- cgit v1.2.3 From 44c22ee91b56d7cad3b48c439dd96aad2e910fbc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:15:05 +0000 Subject: mii: Simplify mii_resolve_flowctrl_fdx() This is a shorter and more comprehensible formulation of the conditions for each flow control mode. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/mii.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/include/linux/mii.h b/include/linux/mii.h index ad748588faf1..14ecb2e114f1 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -250,18 +250,12 @@ static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv) { u8 cap = 0; - if (lcladv & ADVERTISE_PAUSE_CAP) { - if (lcladv & ADVERTISE_PAUSE_ASYM) { - if (rmtadv & LPA_PAUSE_CAP) - cap = FLOW_CTRL_TX | FLOW_CTRL_RX; - else if (rmtadv & LPA_PAUSE_ASYM) - cap = FLOW_CTRL_RX; - } else { - if (rmtadv & LPA_PAUSE_CAP) - cap = FLOW_CTRL_TX | FLOW_CTRL_RX; - } - } else if (lcladv & ADVERTISE_PAUSE_ASYM) { - if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) + if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) { + cap = FLOW_CTRL_TX | FLOW_CTRL_RX; + } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) { + if (lcladv & ADVERTISE_PAUSE_CAP) + cap = FLOW_CTRL_RX; + else if (rmtadv & ADVERTISE_PAUSE_CAP) cap = FLOW_CTRL_TX; } -- cgit v1.2.3 From a8c30832b5b12e5d4e9d1c20cdac3cc2880e08b8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:19:03 +0000 Subject: mii: Add mii_advertise_flowctrl() This converts flow control capabilites to an advertising mask and can be useful in combination with mii_resolve_flowctrl_fdx(). Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/mii.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/mii.h b/include/linux/mii.h index 14ecb2e114f1..359fba880274 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -239,6 +239,22 @@ static inline unsigned int mii_duplex (unsigned int duplex_lock, return 0; } +/** + * mii_advertise_flowctrl - get flow control advertisement flags + * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both) + */ +static inline u16 mii_advertise_flowctrl(int cap) +{ + u16 adv = 0; + + if (cap & FLOW_CTRL_RX) + adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + if (cap & FLOW_CTRL_TX) + adv ^= ADVERTISE_PAUSE_ASYM; + + return adv; +} + /** * mii_resolve_flowctrl_fdx * @lcladv: value of MII ADVERTISE register -- cgit v1.2.3 From af2a3eac2fe6a6d8e9fdf6927284b34466a7d808 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:19:36 +0000 Subject: mdio: Add mdio45_ethtool_spauseparam_an() This implements the ETHTOOL_SPAUSEPARAM operation for MDIO (clause 45) PHYs with auto-negotiation MMDs. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/mdio.c | 30 ++++++++++++++++++++++++++++++ include/linux/mdio.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index 0604a25748ee..2fb0d16b61f7 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -274,6 +274,36 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, } EXPORT_SYMBOL(mdio45_ethtool_gset_npage); +/** + * mdio45_ethtool_spauseparam_an - set auto-negotiated pause parameters + * @mdio: MDIO interface + * @ecmd: Ethtool request structure + * + * This function assumes that the PHY has an auto-negotiation MMD. It + * will enable and disable advertising of flow control as appropriate. + */ +void mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio, + const struct ethtool_pauseparam *ecmd) +{ + int adv, old_adv; + + WARN_ON(!(mdio->mmds & MDIO_DEVS_AN)); + + old_adv = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_AN_ADVERTISE); + adv = old_adv & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + if (ecmd->autoneg) + adv |= mii_advertise_flowctrl( + (ecmd->rx_pause ? FLOW_CTRL_RX : 0) | + (ecmd->tx_pause ? FLOW_CTRL_TX : 0)); + if (adv != old_adv) { + mdio->mdio_write(mdio->dev, mdio->prtad, MDIO_MMD_AN, + MDIO_AN_ADVERTISE, adv); + mdio45_nway_restart(mdio); + } +} +EXPORT_SYMBOL(mdio45_ethtool_spauseparam_an); + /** * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs * @mdio: MDIO interface diff --git a/include/linux/mdio.h b/include/linux/mdio.h index ba41537eaa8a..5645c0f863dc 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -279,6 +279,9 @@ extern int mdio45_nway_restart(const struct mdio_if_info *mdio); extern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, struct ethtool_cmd *ecmd, u32 npage_adv, u32 npage_lpa); +extern void +mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio, + const struct ethtool_pauseparam *ecmd); /** * mdio45_ethtool_gset - get settings for ETHTOOL_GSET -- cgit v1.2.3 From 3f926da82f128c68c479247b1771729b9487502a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:20:37 +0000 Subject: sfc: Use generic MDIO flow control auto-negotiation functions Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/ethtool.c | 3 ++- drivers/net/sfc/mdio_10g.c | 22 +--------------------- drivers/net/sfc/mdio_10g.h | 3 --- drivers/net/sfc/net_driver.h | 26 ++++---------------------- drivers/net/sfc/tenxpress.c | 1 - 5 files changed, 7 insertions(+), 48 deletions(-) diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 1c7b6849fe01..997ea2a3d53f 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -711,7 +711,8 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, mutex_lock(&efx->mac_lock); efx->wanted_fc = wanted_fc; - efx_mdio_set_pause(efx); + if (efx->phy_op->mmds & MDIO_DEVS_AN) + mdio45_ethtool_spauseparam_an(&efx->mdio, pause); __efx_reconfigure_port(efx); mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 11c231a1f875..6c33459f9ea9 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -304,7 +304,7 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) reg |= ADVERTISE_NPAGE; - reg |= efx_fc_advertise(efx->wanted_fc); + reg |= mii_advertise_flowctrl(efx->wanted_fc); efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); /* Set up the (extended) next page if necessary */ @@ -340,26 +340,6 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) return 0; } -void efx_mdio_set_pause(struct efx_nic *efx) -{ - int reg; - - if (efx->phy_op->mmds & MDIO_DEVS_AN) { - /* Set pause capability advertising */ - reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE); - reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - reg |= efx_fc_advertise(efx->wanted_fc); - efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); - - /* Restart auto-negotiation */ - reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); - if (reg & MDIO_AN_CTRL1_ENABLE) { - reg |= MDIO_AN_CTRL1_RESTART; - efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); - } - } -} - enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) { int lpa; diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index ea4587d93698..6b14421a7444 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -87,9 +87,6 @@ extern void efx_mdio_set_mmds_lpower(struct efx_nic *efx, /* Set (some of) the PHY settings over MDIO */ extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); -/* Set pause parameters to be advertised through AN (if available) */ -extern void efx_mdio_set_pause(struct efx_nic *efx); - /* Get pause parameters from AN if available (otherwise return * requested pause parameters) */ diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 457e2f1d4b43..5eabede9ac18 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -495,8 +495,8 @@ struct efx_nic; /* Pseudo bit-mask flow control field */ enum efx_fc_type { - EFX_FC_RX = 1, - EFX_FC_TX = 2, + EFX_FC_RX = FLOW_CTRL_RX, + EFX_FC_TX = FLOW_CTRL_TX, EFX_FC_AUTO = 4, }; @@ -506,33 +506,15 @@ enum efx_mac_type { EFX_XMAC = 2, }; -static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc) -{ - unsigned int adv = 0; - if (wanted_fc & EFX_FC_RX) - adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - if (wanted_fc & EFX_FC_TX) - adv ^= ADVERTISE_PAUSE_ASYM; - return adv; -} - static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc, unsigned int lpa) { - unsigned int adv = efx_fc_advertise(wanted_fc); + BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX)); if (!(wanted_fc & EFX_FC_AUTO)) return wanted_fc; - if (adv & lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX | EFX_FC_TX; - if (adv & lpa & ADVERTISE_PAUSE_ASYM) { - if (adv & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX; - if (lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_TX; - } - return 0; + return mii_resolve_flowctrl_fdx(mii_advertise_flowctrl(wanted_fc), lpa); } /** diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 403f7d70c223..0421190db7de 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -343,7 +343,6 @@ static int tenxpress_phy_init(struct efx_nic *efx) rc = tenxpress_init(efx); if (rc < 0) goto fail; - efx_mdio_set_pause(efx); if (efx->phy_type == PHY_TYPE_SFT9001B) { rc = device_create_file(&efx->pci_dev->dev, -- cgit v1.2.3 From 0c09c1a49cc7b819b33566a49d9901f7cfdd6889 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:21:53 +0000 Subject: ethtool/mdio: Report MDIO mode support and link partner advertising Add mdio_support and lp_advertising fields to ethtool_cmd. Set these in mdio45_ethtool_gset{,_npage}(). Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/mdio.c | 19 ++++++++++++------- include/linux/ethtool.h | 4 +++- include/linux/mdio.h | 5 +++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index 2fb0d16b61f7..ee383c256931 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -173,6 +173,8 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, ecmd->transceiver = XCVR_INTERNAL; ecmd->phy_address = mdio->prtad; + ecmd->mdio_support = + mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22); reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, MDIO_CTRL2); @@ -235,16 +237,19 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, if (ecmd->autoneg) { u32 modes = 0; + int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad, + MDIO_MMD_AN, MDIO_STAT1); /* If AN is complete and successful, report best common * mode, otherwise report best advertised mode. */ - if (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, - MDIO_STAT1) & - MDIO_AN_STAT1_COMPLETE) - modes = (ecmd->advertising & - (mdio45_get_an(mdio, MDIO_AN_LPA) | - npage_lpa)); - if (modes == 0) + if (an_stat & MDIO_AN_STAT1_COMPLETE) { + ecmd->lp_advertising = + mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa; + if (an_stat & MDIO_AN_STAT1_LPABLE) + ecmd->lp_advertising |= ADVERTISED_Autoneg; + modes = ecmd->advertising & ecmd->lp_advertising; + } + if ((modes & ~ADVERTISED_Autoneg) == 0) modes = ecmd->advertising; if (modes & ADVERTISED_10000baseT_Full) { diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 5ccb6bd660c7..14e6bc860112 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -26,11 +26,13 @@ struct ethtool_cmd { __u8 phy_address; __u8 transceiver; /* Which transceiver to use */ __u8 autoneg; /* Enable or disable autonegotiation */ + __u8 mdio_support; __u32 maxtxpkt; /* Tx pkts before generating tx int */ __u32 maxrxpkt; /* Rx pkts before generating rx int */ __u16 speed_hi; __u16 reserved2; - __u32 reserved[3]; + __u32 lp_advertising; /* Features the link partner advertises */ + __u32 reserved[2]; }; static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 5645c0f863dc..1bff2f2d0e19 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -234,6 +234,9 @@ static inline __u16 mdio_phy_id_devad(int phy_id) return phy_id & MDIO_PHY_ID_DEVAD; } +#define MDIO_SUPPORTS_C22 1 +#define MDIO_SUPPORTS_C45 2 + #ifdef __KERNEL__ /** @@ -264,8 +267,6 @@ struct mdio_if_info { #define MDIO_PRTAD_NONE (-1) #define MDIO_DEVAD_NONE (-1) -#define MDIO_SUPPORTS_C22 1 -#define MDIO_SUPPORTS_C45 2 #define MDIO_EMULATE_C22 4 struct ethtool_cmd; -- cgit v1.2.3 From 894b19a6b343ce3589237167a56e6df0fe72ef0d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:25:57 +0000 Subject: ethtool/mdio: Support backplane mode negotiation Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/mdio.c | 30 +++++++++++++++++++++++++----- include/linux/ethtool.h | 10 ++++++++++ include/linux/mdio.h | 5 +++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index ee383c256931..66483035f683 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -202,12 +202,29 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, break; case MDIO_PMA_CTRL2_10GBCX4: + ecmd->port = PORT_OTHER; + ecmd->supported = 0; + ecmd->advertising = 0; + break; + case MDIO_PMA_CTRL2_10GBKX4: case MDIO_PMA_CTRL2_10GBKR: case MDIO_PMA_CTRL2_1000BKX: ecmd->port = PORT_OTHER; - ecmd->supported = 0; - ecmd->advertising = 0; + ecmd->supported = SUPPORTED_Backplane; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_PMA_EXTABLE); + if (reg & MDIO_PMA_EXTABLE_10GBKX4) + ecmd->supported |= SUPPORTED_10000baseKX4_Full; + if (reg & MDIO_PMA_EXTABLE_10GBKR) + ecmd->supported |= SUPPORTED_10000baseKR_Full; + if (reg & MDIO_PMA_EXTABLE_1000BKX) + ecmd->supported |= SUPPORTED_1000baseKX_Full; + reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, + MDIO_PMA_10GBR_FECABLE); + if (reg & MDIO_PMA_10GBR_FECABLE_ABLE) + ecmd->supported |= SUPPORTED_10000baseR_FEC; + ecmd->advertising = ADVERTISED_Backplane; break; /* All the other defined modes are flavours of optical */ @@ -252,13 +269,16 @@ void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, if ((modes & ~ADVERTISED_Autoneg) == 0) modes = ecmd->advertising; - if (modes & ADVERTISED_10000baseT_Full) { + if (modes & (ADVERTISED_10000baseT_Full | + ADVERTISED_10000baseKX4_Full | + ADVERTISED_10000baseKR_Full)) { ecmd->speed = SPEED_10000; ecmd->duplex = DUPLEX_FULL; } else if (modes & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseKX_Full)) { ecmd->speed = SPEED_1000; - ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); + ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half); } else if (modes & (ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half)) { ecmd->speed = SPEED_100; diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 14e6bc860112..380b04272bf1 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -565,6 +565,11 @@ struct ethtool_ops { #define SUPPORTED_Pause (1 << 13) #define SUPPORTED_Asym_Pause (1 << 14) #define SUPPORTED_2500baseX_Full (1 << 15) +#define SUPPORTED_Backplane (1 << 16) +#define SUPPORTED_1000baseKX_Full (1 << 17) +#define SUPPORTED_10000baseKX4_Full (1 << 18) +#define SUPPORTED_10000baseKR_Full (1 << 19) +#define SUPPORTED_10000baseR_FEC (1 << 20) /* Indicates what features are advertised by the interface. */ #define ADVERTISED_10baseT_Half (1 << 0) @@ -583,6 +588,11 @@ struct ethtool_ops { #define ADVERTISED_Pause (1 << 13) #define ADVERTISED_Asym_Pause (1 << 14) #define ADVERTISED_2500baseX_Full (1 << 15) +#define ADVERTISED_Backplane (1 << 16) +#define ADVERTISED_1000baseKX_Full (1 << 17) +#define ADVERTISED_10000baseKX4_Full (1 << 18) +#define ADVERTISED_10000baseKR_Full (1 << 19) +#define ADVERTISED_10000baseR_FEC (1 << 20) /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 1bff2f2d0e19..26b4eb3bbee9 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -46,6 +46,7 @@ /* Media-dependent registers. */ #define MDIO_PMA_10GBT_TXPWR 131 /* 10GBASE-T TX power control */ +#define MDIO_PMA_10GBR_FECABLE 170 /* 10GBASE-R FEC ability */ #define MDIO_PCS_10GBX_STAT1 24 /* 10GBASE-X PCS status 1 */ #define MDIO_PCS_10GBRT_STAT1 32 /* 10GBASE-R/-T PCS status 1 */ #define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */ @@ -187,6 +188,10 @@ /* PMA 10GBASE-T TX power register. */ #define MDIO_PMA_10GBT_TXPWR_SHORT 0x0001 /* Short-reach mode */ +/* PMA 10GBASE-R FEC ability register. */ +#define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */ +#define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */ + /* PCS 10GBASE-R/-T status register 1. */ #define MDIO_PCS_10GBRT_STAT1_BLKLK 0x0001 /* Block lock attained */ -- cgit v1.2.3 From 5974700c288aa160fd02b1cb9294173664bcc172 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Apr 2009 08:34:44 +0000 Subject: mii: Rewrite mii_ethtool_gset() to report mdio_support and lp_advertising Ignore link partner advertising flags while AN is not complete. Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/mii.c | 91 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 92056051f269..d81a5d22a3a9 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -31,7 +31,27 @@ #include #include #include -#include +#include + +static u32 mii_get_an(struct mii_if_info *mii, u16 addr) +{ + u32 result = 0; + int advert; + + advert = mii->mdio_read(mii->dev, mii->phy_id, addr); + if (advert & LPA_LPACK) + result |= ADVERTISED_Autoneg; + if (advert & ADVERTISE_10HALF) + result |= ADVERTISED_10baseT_Half; + if (advert & ADVERTISE_10FULL) + result |= ADVERTISED_10baseT_Full; + if (advert & ADVERTISE_100HALF) + result |= ADVERTISED_100baseT_Half; + if (advert & ADVERTISE_100FULL) + result |= ADVERTISED_100baseT_Full; + + return result; +} /** * mii_ethtool_gset - get settings that are specified in @ecmd @@ -43,8 +63,8 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) { struct net_device *dev = mii->dev; - u32 advert, bmcr, lpa, nego; - u32 advert2 = 0, bmcr2 = 0, lpa2 = 0; + u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; + u32 nego; ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | @@ -62,50 +82,51 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) /* this isn't fully supported at higher layers */ ecmd->phy_address = mii->phy_id; + ecmd->mdio_support = MDIO_SUPPORTS_C22; ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); - if (mii->supports_gmii) - advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - - if (advert & ADVERTISE_10HALF) - ecmd->advertising |= ADVERTISED_10baseT_Half; - if (advert & ADVERTISE_10FULL) - ecmd->advertising |= ADVERTISED_10baseT_Full; - if (advert & ADVERTISE_100HALF) - ecmd->advertising |= ADVERTISED_100baseT_Half; - if (advert & ADVERTISE_100FULL) - ecmd->advertising |= ADVERTISED_100baseT_Full; - if (advert2 & ADVERTISE_1000HALF) - ecmd->advertising |= ADVERTISED_1000baseT_Half; - if (advert2 & ADVERTISE_1000FULL) - ecmd->advertising |= ADVERTISED_1000baseT_Full; bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); + bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); if (mii->supports_gmii) { - bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); + ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); + stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); } if (bmcr & BMCR_ANENABLE) { ecmd->advertising |= ADVERTISED_Autoneg; ecmd->autoneg = AUTONEG_ENABLE; - nego = mii_nway_result(advert & lpa); - if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) & - (lpa2 >> 2)) + ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE); + if (ctrl1000 & ADVERTISE_1000HALF) + ecmd->advertising |= ADVERTISED_1000baseT_Half; + if (ctrl1000 & ADVERTISE_1000FULL) + ecmd->advertising |= ADVERTISED_1000baseT_Full; + + if (bmsr & BMSR_ANEGCOMPLETE) { + ecmd->lp_advertising = mii_get_an(mii, MII_LPA); + if (stat1000 & LPA_1000HALF) + ecmd->lp_advertising |= + ADVERTISED_1000baseT_Half; + if (stat1000 & LPA_1000FULL) + ecmd->lp_advertising |= + ADVERTISED_1000baseT_Full; + } else { + ecmd->lp_advertising = 0; + } + + nego = ecmd->advertising & ecmd->lp_advertising; + + if (nego & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { ecmd->speed = SPEED_1000; - else if (nego == LPA_100FULL || nego == LPA_100HALF) + ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full); + } else if (nego & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { ecmd->speed = SPEED_100; - else - ecmd->speed = SPEED_10; - if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL || - nego == LPA_10FULL) { - ecmd->duplex = DUPLEX_FULL; - mii->full_duplex = 1; + ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full); } else { - ecmd->duplex = DUPLEX_HALF; - mii->full_duplex = 0; + ecmd->speed = SPEED_10; + ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full); } } else { ecmd->autoneg = AUTONEG_DISABLE; @@ -116,6 +137,8 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } + mii->full_duplex = ecmd->duplex; + /* ignore maxtxpkt, maxrxpkt for now */ return 0; -- cgit v1.2.3 From a4fe91ee711f4e955ea85ab05b092cfe384b073e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 29 Apr 2009 17:53:20 -0700 Subject: Revert "vxge: use max() instead of VXGE_HW_SET_LEVEL" This reverts commit 011983048a120e520147361be1067dd82343038e. Causes warnings in the build as reported by Stephen Rothwell. So this change is worse than what it's curing. Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-traffic.c | 55 ++++++++++++++++++++++++----------------- drivers/net/vxge/vxge-traffic.h | 2 ++ 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c index cf4ebb55273d..506625b180ac 100644 --- a/drivers/net/vxge/vxge-traffic.c +++ b/drivers/net/vxge/vxge-traffic.c @@ -505,7 +505,7 @@ enum vxge_hw_status vxge_hw_device_begin_irq(struct __vxge_hw_device *hldev, ret = __vxge_hw_vpath_alarm_process( &hldev->virtual_paths[i], skip_alarms); - error_level = max(ret, error_level); + error_level = VXGE_HW_SET_LEVEL(ret, error_level); if (unlikely((ret == VXGE_HW_ERR_CRITICAL) || (ret == VXGE_HW_ERR_SLOT_FREEZE))) @@ -1921,7 +1921,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( struct vxge_hw_vpath_reg __iomem *vp_reg; if (vpath == NULL) { - alarm_event = max(VXGE_HW_EVENT_UNKNOWN, + alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN, alarm_event); goto out2; } @@ -1931,7 +1931,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( alarm_status = readq(&vp_reg->vpath_general_int_status); if (alarm_status == VXGE_HW_ALL_FOXES) { - alarm_event = max(VXGE_HW_EVENT_SLOT_FREEZE, + alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_SLOT_FREEZE, alarm_event); goto out; } @@ -1945,7 +1945,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) { sw_stats->error_stats.unknown_alarms++; - alarm_event = max(VXGE_HW_EVENT_UNKNOWN, + alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN, alarm_event); goto out; } @@ -1975,8 +1975,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( &vp_reg->asic_ntwk_vp_err_mask); __vxge_hw_device_handle_link_down_ind(hldev); - alarm_event = max(VXGE_HW_EVENT_LINK_DOWN, - alarm_event); + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_LINK_DOWN, alarm_event); } if (((val64 & @@ -1996,15 +1996,15 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( &vp_reg->asic_ntwk_vp_err_mask); __vxge_hw_device_handle_link_up_ind(hldev); - alarm_event = max(VXGE_HW_EVENT_LINK_UP, - alarm_event); + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_LINK_UP, alarm_event); } writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->asic_ntwk_vp_err_reg); - alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, - alarm_event); + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); if (skip_alarms) return VXGE_HW_OK; @@ -2026,8 +2026,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.ini_serr_det++; - alarm_event = max(VXGE_HW_EVENT_SERR, - alarm_event); + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_SERR, alarm_event); } if ((val64 & @@ -2035,8 +2035,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.dblgen_fifo0_overflow++; - alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, - alarm_event); + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_FIFO_ERR, alarm_event); } if ((val64 & @@ -2057,7 +2057,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( if (!skip_alarms) { writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->general_errors_reg); - alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); } } @@ -2073,7 +2074,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.kdfcctl_fifo0_overwrite++; - alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_FIFO_ERR, alarm_event); } @@ -2082,7 +2084,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.kdfcctl_fifo0_poison++; - alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_FIFO_ERR, alarm_event); } @@ -2091,14 +2094,16 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.kdfcctl_fifo0_dma_error++; - alarm_event = max(VXGE_HW_EVENT_FIFO_ERR, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_FIFO_ERR, alarm_event); } if (!skip_alarms) { writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_reg); - alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); } } @@ -2122,7 +2127,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( ~mask64) { sw_stats->error_stats.prc_rxdcm_sc_err++; - alarm_event = max(VXGE_HW_EVENT_VPATH_ERR, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_VPATH_ERR, alarm_event); } @@ -2130,7 +2136,8 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( & ~mask64) { sw_stats->error_stats.prc_rxdcm_sc_abort++; - alarm_event = max(VXGE_HW_EVENT_VPATH_ERR, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_VPATH_ERR, alarm_event); } @@ -2138,14 +2145,16 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process( & ~mask64) { sw_stats->error_stats.prc_quanta_size_err++; - alarm_event = max(VXGE_HW_EVENT_VPATH_ERR, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_VPATH_ERR, alarm_event); } if (!skip_alarms) { writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->prc_alarm_reg); - alarm_event = max(VXGE_HW_EVENT_ALARM_CLEARED, + alarm_event = VXGE_HW_SET_LEVEL( + VXGE_HW_EVENT_ALARM_CLEARED, alarm_event); } } diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index d03f3d3805c9..7567a1140d07 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h @@ -110,6 +110,8 @@ enum vxge_hw_event { VXGE_HW_EVENT_SLOT_FREEZE = VXGE_HW_EVENT_BASE + 14, }; +#define VXGE_HW_SET_LEVEL(a, b) (((a) > (b)) ? (a) : (b)) + /* * struct vxge_hw_mempool_dma - Represents DMA objects passed to the caller. -- cgit v1.2.3 From 1aec5bdfed91b50aedbcad43393bcb05033c7ef3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 30 Apr 2009 12:19:31 +0000 Subject: net: remove driver_data direct access of struct device In the near future, the driver core is going to not allow direct access to the driver_data pointer in struct device. Instead, the functions dev_get_drvdata() and dev_set_drvdata() should be used. These functions have been around since the beginning, so are backwards compatible with all older kernel versions. Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/3c509.c | 12 ++++++------ drivers/net/depca.c | 4 ++-- drivers/net/hp100.c | 4 ++-- drivers/net/ne3210.c | 4 ++-- drivers/net/smc-mca.c | 4 ++-- drivers/net/tulip/de4x5.c | 6 +++--- drivers/net/usb/hso.c | 4 ++-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index fbb371921991..393e4e711965 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -653,11 +653,11 @@ static int __init el3_mca_probe(struct device *device) netdev_boot_setup_check(dev); el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA); - device->driver_data = dev; + dev_set_drvdata(device, dev); err = el3_common_init(dev); if (err) { - device->driver_data = NULL; + dev_set_drvdata(device, NULL); free_netdev(dev); return -ENOMEM; } @@ -721,12 +721,12 @@ static int __init el3_eisa_probe (struct device *device) /* This remove works for all device types. * - * The net dev must be stored in the driver_data field */ + * The net dev must be stored in the driver data field */ static int __devexit el3_device_remove (struct device *device) { struct net_device *dev; - dev = device->driver_data; + dev = dev_get_drvdata(device); el3_common_remove (dev); return 0; @@ -1451,7 +1451,7 @@ el3_suspend(struct device *pdev, pm_message_t state) struct el3_private *lp; int ioaddr; - dev = pdev->driver_data; + dev = dev_get_drvdata(pdev); lp = netdev_priv(dev); ioaddr = dev->base_addr; @@ -1475,7 +1475,7 @@ el3_resume(struct device *pdev) struct el3_private *lp; int ioaddr; - dev = pdev->driver_data; + dev = dev_get_drvdata(pdev); lp = netdev_priv(dev); ioaddr = dev->base_addr; diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 357f565851ed..9301eb28d9e2 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -810,7 +810,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) dev->mem_start = 0; - device->driver_data = dev; + dev_set_drvdata(device, dev); SET_NETDEV_DEV (dev, device); status = register_netdev(dev); @@ -1614,7 +1614,7 @@ static int __devexit depca_device_remove (struct device *device) struct depca_private *lp; int bus; - dev = device->driver_data; + dev = dev_get_drvdata(device); lp = netdev_priv(dev); unregister_netdev (dev); diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index de3f49f991a3..8feda9fe8297 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -2864,7 +2864,7 @@ static int __init hp100_eisa_probe (struct device *gendev) printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name, dev->base_addr); #endif - gendev->driver_data = dev; + dev_set_drvdata(gendev, dev); return 0; out1: free_netdev(dev); @@ -2873,7 +2873,7 @@ static int __init hp100_eisa_probe (struct device *gendev) static int __devexit hp100_eisa_remove (struct device *gendev) { - struct net_device *dev = gendev->driver_data; + struct net_device *dev = dev_get_drvdata(gendev); cleanup_dev(dev); return 0; } diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index 6a843f7350ab..a00bbfb9aed0 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c @@ -104,7 +104,7 @@ static int __init ne3210_eisa_probe (struct device *device) } SET_NETDEV_DEV(dev, device); - device->driver_data = dev; + dev_set_drvdata(device, dev); ioaddr = edev->base_addr; if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) { @@ -225,7 +225,7 @@ static int __init ne3210_eisa_probe (struct device *device) static int __devexit ne3210_eisa_remove (struct device *device) { - struct net_device *dev = device->driver_data; + struct net_device *dev = dev_get_drvdata(device); unsigned long ioaddr = to_eisa_device (device)->base_addr; unregister_netdev (dev); diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 8d36d40649ef..c791ef76c1d6 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -370,7 +370,7 @@ static int __init ultramca_probe(struct device *gen_dev) outb(reg4, ioaddr + 4); - gen_dev->driver_data = dev; + dev_set_drvdata(gen_dev, dev); /* The 8390 isn't at the base address, so fake the offset */ @@ -531,7 +531,7 @@ static int ultramca_close_card(struct net_device *dev) static int ultramca_remove(struct device *gen_dev) { struct mca_device *mca_dev = to_mca_device(gen_dev); - struct net_device *dev = (struct net_device *)gen_dev->driver_data; + struct net_device *dev = dev_get_drvdata(gen_dev); if (dev) { /* NB: ultra_close_card() does free_irq */ diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index f9491bd787d1..32256179a205 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1099,7 +1099,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) struct pci_dev *pdev = NULL; int i, status=0; - gendev->driver_data = dev; + dev_set_drvdata(gendev, dev); /* Ensure we're not sleeping */ if (lp->bus == EISA) { @@ -2094,7 +2094,7 @@ static int __devexit de4x5_eisa_remove (struct device *device) struct net_device *dev; u_long iobase; - dev = device->driver_data; + dev = dev_get_drvdata(device); iobase = dev->base_addr; unregister_netdev (dev); @@ -2338,7 +2338,7 @@ static void __devexit de4x5_pci_remove (struct pci_dev *pdev) struct net_device *dev; u_long iobase; - dev = pdev->dev.driver_data; + dev = dev_get_drvdata(&pdev->dev); iobase = dev->base_addr; unregister_netdev (dev); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index d696e5fbc176..837135f0390a 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -482,7 +482,7 @@ static ssize_t hso_sysfs_show_porttype(struct device *dev, struct device_attribute *attr, char *buf) { - struct hso_device *hso_dev = dev->driver_data; + struct hso_device *hso_dev = dev_get_drvdata(dev); char *port_name; if (!hso_dev) @@ -2313,7 +2313,7 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, serial->parent->dev = tty_register_device(tty_drv, minor, &serial->parent->interface->dev); dev = serial->parent->dev; - dev->driver_data = serial->parent; + dev_set_drvdata(dev, serial->parent); i = device_create_file(dev, &dev_attr_hsotype); /* fill in specific data for later use */ -- cgit v1.2.3 From 88d7d8b00cdc3117150faab4c4ace6d464b71c22 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Fri, 1 May 2009 01:41:50 +0000 Subject: forcedeth: add clock gating feature This patch adds new logic to support a clock gating feature found on the latest set of chipsets. The clock gating is performed on the tx/rx engines when the link is disconnected. Clock gating helps in reducing power consumption. * modified based on comments from netdev Signed-off-by: Ayaz Abdulla Signed-off-by: David S. Miller --- drivers/net/forcedeth.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f9a846b1b92f..d0b1d9f17a5d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -343,6 +343,7 @@ enum { #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15 #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 #define NVREG_POWERSTATE2_PHY_RESET 0x0004 +#define NVREG_POWERSTATE2_GATE_CLOCKS 0x0F00 }; /* Big endian: should work, but is untested */ @@ -1017,6 +1018,23 @@ static int using_multi_irqs(struct net_device *dev) return 1; } +static void nv_txrx_gate(struct net_device *dev, bool gate) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 powerstate; + + if (!np->mac_in_use && + (np->driver_data & DEV_HAS_POWER_CNTRL)) { + powerstate = readl(base + NvRegPowerState2); + if (gate) + powerstate |= NVREG_POWERSTATE2_GATE_CLOCKS; + else + powerstate &= ~NVREG_POWERSTATE2_GATE_CLOCKS; + writel(powerstate, base + NvRegPowerState2); + } +} + static void nv_enable_irq(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); @@ -3394,12 +3412,14 @@ static void nv_linkchange(struct net_device *dev) if (!netif_carrier_ok(dev)) { netif_carrier_on(dev); printk(KERN_INFO "%s: link up.\n", dev->name); + nv_txrx_gate(dev, false); nv_start_rx(dev); } } else { if (netif_carrier_ok(dev)) { netif_carrier_off(dev); printk(KERN_INFO "%s: link down.\n", dev->name); + nv_txrx_gate(dev, true); nv_stop_rx(dev); } } @@ -5327,6 +5347,7 @@ static int nv_open(struct net_device *dev) mii_rw(dev, np->phyaddr, MII_BMCR, mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN); + nv_txrx_gate(dev, false); /* erase previous misconfiguration */ if (np->driver_data & DEV_HAS_POWER_CNTRL) nv_mac_reset(dev); @@ -5514,12 +5535,14 @@ static int nv_close(struct net_device *dev) nv_drain_rxtx(dev); if (np->wolenabled) { + nv_txrx_gate(dev, false); writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); nv_start_rx(dev); } else { /* power down phy */ mii_rw(dev, np->phyaddr, MII_BMCR, mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN); + nv_txrx_gate(dev, true); } /* FIXME: power down nic */ -- cgit v1.2.3 From f0a3a1538d57dfb51c73d012cbb72f985cd419aa Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Fri, 1 May 2009 19:21:26 -0700 Subject: 3c589_cs: add cis(firmware) of 3Com multifunction pcmcia card 3c589_cs,3c574_cs,serial_cs: (1)add cis(firmware) of 3Com lan&modem mulitifunction pcmcia card. (2)load correct configuration register for 3Com card Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller --- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 4 ++-- drivers/serial/serial_cs.c | 22 +++++++++++++++++----- firmware/Makefile | 2 ++ firmware/WHENCE | 20 ++++++++++++++++++++ firmware/cis/3CCFEM556.cis.ihex | 13 +++++++++++++ firmware/cis/3CXEM556.cis.ihex | 13 +++++++++++++ 7 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 firmware/cis/3CCFEM556.cis.ihex create mode 100644 firmware/cis/3CXEM556.cis.ihex diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 8f3872b8985d..f35c609ba020 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -1195,7 +1195,7 @@ static int el3_close(struct net_device *dev) static struct pcmcia_device_id tc574_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, tc574_ids); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index cdf661a6092c..ec7cf5ac4f05 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -967,8 +967,8 @@ static struct pcmcia_device_id tc589_ids[] = { PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis"), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, tc589_ids); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 7546aa887fa7..79c9c5f5cdba 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -681,7 +681,7 @@ static int serial_config(struct pcmcia_device * link) u_char *buf; cisparse_t *parse; cistpl_cftable_entry_t *cf; - int i; + int i, last_ret, last_fn; DEBUG(0, "serial_config(0x%p)\n", link); @@ -699,6 +699,16 @@ static int serial_config(struct pcmcia_device * link) tuple->TupleDataMax = 255; tuple->Attributes = 0; + /* Get configuration register information */ + tuple->DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(link, tuple, parse); + if (last_ret != 0) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse->config.base; + link->conf.Present = parse->config.rmask[0]; + /* Is this a compliant multifunction card? */ tuple->DesiredTuple = CISTPL_LONGLINK_MFC; tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; @@ -761,7 +771,9 @@ static int serial_config(struct pcmcia_device * link) kfree(cfg_mem); return 0; - failed: +cs_failed: + cs_error(link, last_fn, last_ret); +failed: serial_remove(link); kfree(cfg_mem); return -ENODEV; @@ -863,10 +875,10 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ diff --git a/firmware/Makefile b/firmware/Makefile index 1c670e0c0448..96c3dd8cc683 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -48,6 +48,8 @@ fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \ e100/d102e_ucode.bin fw-shipped-$(CONFIG_MYRI_SBUS) += myricom/lanai.bin fw-shipped-$(CONFIG_PCMCIA_PCNET) += cis/LA-PCM.cis +fw-shipped-$(CONFIG_PCMCIA_3C589) += cis/3CXEM556.cis +fw-shipped-$(CONFIG_PCMCIA_3C574) += cis/3CCFEM556.cis fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ advansys/3550.bin advansys/38C0800.bin diff --git a/firmware/WHENCE b/firmware/WHENCE index c1e9c5ab694c..bb8fda8f06b8 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -586,6 +586,26 @@ Originally developed by the pcmcia-cs project -------------------------------------------------------------------------- +Driver: PCMCIA_3C589 - 3Com PCMCIA adapter + +File: cis/3CXEM556.cis + +Licence: GPL + +Originally developed by the pcmcia-cs project + +-------------------------------------------------------------------------- + +Driver: PCMCIA_3C574 - 3Com PCMCIA adapter + +File: cis/3CCFEM556.cis + +Licence: GPL + +Originally developed by the pcmcia-cs project + +-------------------------------------------------------------------------- + Driver: PCMCIA_SMC91C92 - SMC 91Cxx PCMCIA File: ositech/Xilinx7OD.bin diff --git a/firmware/cis/3CCFEM556.cis.ihex b/firmware/cis/3CCFEM556.cis.ihex new file mode 100644 index 000000000000..e4d92b173e17 --- /dev/null +++ b/firmware/cis/3CCFEM556.cis.ihex @@ -0,0 +1,13 @@ +:1000000001030000FF152D050033436F6D004D65A2 +:100010006761686572747A2033434346454D3535D0 +:1000200036004C414E202B2035366B204D6F6465D9 +:100030006D0000FF20040101560521020000060B9F +:1000400002004D000000006B000000FF001303439E +:100050004953210206001A060507001067021B0912 +:1000600087011901556430FFFFFF00130343495313 +:10007000210202001A060527001177021B09A701B9 +:090080001901552330FFFFFF00B8 +:00000001FF +# +# This card is MFC-compliant, but identifies itself as single function +# diff --git a/firmware/cis/3CXEM556.cis.ihex b/firmware/cis/3CXEM556.cis.ihex new file mode 100644 index 000000000000..895010b230ff --- /dev/null +++ b/firmware/cis/3CXEM556.cis.ihex @@ -0,0 +1,13 @@ +:1000000001030000FF152C050033436F6D004D65A3 +:100010006761686572747A20334358454D353536CB +:10002000004C414E202B2035366B204D6F64656DA2 +:100030000000FF20040101350021020000060B0230 +:10004000004C0000000069000000FF00130343495A +:1000500053210206001A0501070008631B098701E6 +:100060001901556430FFFFFF001303434953210278 +:1000700002001A0501270009631B09A70119015590 +:060080002330FFFFFF002A +:00000001FF +# +# This card is MFC-compliant, but identifies itself as single function +# -- cgit v1.2.3 From eb457f36929da6d78c1f03cbb9038ef62646d79d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 2 May 2009 23:55:06 +0000 Subject: ne2k-pci: use dev->addr_len instead of "6" Spotted a tiny ugliness in a recently posted patch. This patch cuts it out. Jirka Signed-off-by: Jiri Pirko drivers/net/ne2k-pci.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) Signed-off-by: David S. Miller --- drivers/net/ne2k-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 7d83896b8c26..3fcebb70151c 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -374,7 +374,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, dev->ethtool_ops = &ne2k_pci_ethtool_ops; NS8390_init(dev, 0); - memcpy(dev->dev_addr, SA_prom, 6); + memcpy(dev->dev_addr, SA_prom, dev->addr_len); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); i = register_netdev(dev); -- cgit v1.2.3 From accc5b4f902b0ba83b2c6c48f2d9e7c204cef4a8 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Sun, 3 May 2009 08:58:48 +0000 Subject: ipv4: remove unused macro (FIB_RES_RESET) from ip_fib.h. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- include/net/ip_fib.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 34855eede5fe..ef91fe924ba4 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -124,14 +124,12 @@ struct fib_result_nl { #ifdef CONFIG_IP_ROUTE_MULTIPATH #define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel]) -#define FIB_RES_RESET(res) ((res).nh_sel = 0) #define FIB_TABLE_HASHSZ 2 #else /* CONFIG_IP_ROUTE_MULTIPATH */ #define FIB_RES_NH(res) ((res).fi->fib_nh[0]) -#define FIB_RES_RESET(res) #define FIB_TABLE_HASHSZ 256 -- cgit v1.2.3 From 513de11bba246b7a67df4c314d9fc936b6a75d0e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 3 May 2009 14:43:10 -0700 Subject: net: Avoid modulus in skb_tx_hash() for forwarding case. Based almost entirely upon a patch by Eric Dumazet. The common case is to have num-tx-queues <= num_rx_queues and even if num_tx_queues is larger it will not be significantly larger. Therefore, a subtraction loop is always going to be faster than modulus. Signed-off-by: David S. Miller --- net/core/dev.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 81442957c5c2..3c8073fe970a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1735,8 +1735,12 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) { u32 hash; - if (skb_rx_queue_recorded(skb)) - return skb_get_rx_queue(skb) % dev->real_num_tx_queues; + if (skb_rx_queue_recorded(skb)) { + hash = skb_get_rx_queue(skb); + while (unlikely (hash >= dev->real_num_tx_queues)) + hash -= dev->real_num_tx_queues; + return hash; + } if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; -- cgit v1.2.3 From 255cac91c3c9ce7dca7713b93ab03c75b7902e0e Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 4 May 2009 11:07:36 -0700 Subject: tcp: extend ECN sysctl to allow server-side only ECN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should be very safe compared with full enabled, so I see no reason why it shouldn't be done right away. As ECN can only be negotiated if the SYN sending party is also supporting it, somebody in the loop probably knows what he/she is doing. If SYN does not ask for ECN, the server side SYN-ACK is identical to what it is without ECN. Thus it's quite safe. The chosen value is safe w.r.t to existing configs which choose to currently set manually either 0 or 1 but silently upgrades those who have not explicitly requested ECN off. Whether to just enable both sides comes up time to time but unless that gets done now we can at least make the servers aware of ECN already. As there are some known problems to occur if ECN is enabled, it's currently questionable whether there's any real gain from enabling clients as servers mostly won't support it anyway (so we'd hit just the negative sides). After enabling the servers and getting that deployed, the client end enable really has some potential gain too. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 11 ++++++++++- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_output.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index ec5de02f543f..7f98aa3962c6 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -168,7 +168,16 @@ tcp_dsack - BOOLEAN Allows TCP to send "duplicate" SACKs. tcp_ecn - BOOLEAN - Enable Explicit Congestion Notification in TCP. + Enable Explicit Congestion Notification (ECN) in TCP. ECN is only + used when both ends of the TCP flow support it. It is useful to + avoid losses due to congestion (when the bottleneck router supports + ECN). + Possible values are: + 0 disable ECN + 1 ECN enabled + 2 Only server-side ECN enabled. If the other end does + not support ECN, behavior is like with ECN disabled. + Default: 2 tcp_fack - BOOLEAN Enable FACK congestion avoidance and fast retransmission. diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c96a6bb25430..56dcf97a97fb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -77,7 +77,7 @@ int sysctl_tcp_window_scaling __read_mostly = 1; int sysctl_tcp_sack __read_mostly = 1; int sysctl_tcp_fack __read_mostly = 1; int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH; -int sysctl_tcp_ecn __read_mostly; +int sysctl_tcp_ecn __read_mostly = 2; int sysctl_tcp_dsack __read_mostly = 1; int sysctl_tcp_app_win __read_mostly = 31; int sysctl_tcp_adv_win_scale __read_mostly = 2; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 59aec609cec6..79c39dc9b01c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -288,7 +288,7 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); tp->ecn_flags = 0; - if (sysctl_tcp_ecn) { + if (sysctl_tcp_ecn == 1) { TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE | TCPCB_FLAG_CWR; tp->ecn_flags = TCP_ECN_OK; } -- cgit v1.2.3 From 6e8cf5c069c6cb7b316e9b1715eac38873dd5cab Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 4 May 2009 11:08:41 -0700 Subject: macb: Add support of the netpoll API With this patch in place, I'm successfully able to use the netconsole mechanism with the Calao USB-A9263 board, which uses the AT91SAM9263 CPU, which in terms of Ethernet controller is supported by the macb driver. Signed-off-by: Thomas Petazzoni [haavard.skinnemoen@atmel.com: disable_irq() -> local_irq_save()] [haavard.skinnemoen@atmel.com: convert to net_device_ops] Signed-off-by: Haavard Skinnemoen Signed-off-by: David S. Miller --- drivers/net/macb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index e82aee41d77e..722265920da8 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -599,6 +599,21 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void macb_poll_controller(struct net_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + macb_interrupt(dev->irq, dev); + local_irq_restore(flags); +} +#endif + static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct macb *bp = netdev_priv(dev); @@ -1094,6 +1109,9 @@ static const struct net_device_ops macb_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = macb_poll_controller, +#endif }; static int __init macb_probe(struct platform_device *pdev) -- cgit v1.2.3 From 4a84822c60afa2b0e2d3370041f69f9526a34757 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 4 May 2009 11:11:38 -0700 Subject: netns 1/2: don't get/put old netns on CLONE_NEWNET copy_net_ns() doesn't copy anything, it creates fresh netns, so get/put of old netns isn't needed. Signed-off-by: Alexey Dobriyan Acked-by: Serge Hallyn Signed-off-by: David S. Miller --- net/core/net_namespace.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index e3bebd36f053..4488010d5a52 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -120,10 +120,8 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) struct net *new_net = NULL; int err; - get_net(old_net); - if (!(flags & CLONE_NEWNET)) - return old_net; + return get_net(old_net); err = -ENOMEM; new_net = net_alloc(); @@ -142,7 +140,6 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) if (err) goto out_free; out: - put_net(old_net); return new_net; out_free: -- cgit v1.2.3 From 088eb2d905de9518dad913995bb8aef493d4a7c5 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 4 May 2009 11:12:14 -0700 Subject: netns 2/2: extract net_create() net_create() will be used by C/R to create fresh netns on restart. Signed-off-by: Alexey Dobriyan Acked-by: Serge Hallyn Signed-off-by: David S. Miller --- net/core/net_namespace.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 4488010d5a52..6b3edc9e6f19 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -115,38 +115,34 @@ static void net_free(struct net *net) kmem_cache_free(net_cachep, net); } -struct net *copy_net_ns(unsigned long flags, struct net *old_net) +static struct net *net_create(void) { - struct net *new_net = NULL; - int err; - - if (!(flags & CLONE_NEWNET)) - return get_net(old_net); - - err = -ENOMEM; - new_net = net_alloc(); - if (!new_net) - goto out_err; + struct net *net; + int rv; + net = net_alloc(); + if (!net) + return ERR_PTR(-ENOMEM); mutex_lock(&net_mutex); - err = setup_net(new_net); - if (!err) { + rv = setup_net(net); + if (rv == 0) { rtnl_lock(); - list_add_tail(&new_net->list, &net_namespace_list); + list_add_tail(&net->list, &net_namespace_list); rtnl_unlock(); } mutex_unlock(&net_mutex); + if (rv < 0) { + net_free(net); + return ERR_PTR(rv); + } + return net; +} - if (err) - goto out_free; -out: - return new_net; - -out_free: - net_free(new_net); -out_err: - new_net = ERR_PTR(err); - goto out; +struct net *copy_net_ns(unsigned long flags, struct net *old_net) +{ + if (!(flags & CLONE_NEWNET)) + return get_net(old_net); + return net_create(); } static void cleanup_net(struct work_struct *work) -- cgit v1.2.3 From c7ae011dc8306d982c25fb4f679752e790a08dc4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 May 2009 21:33:19 -0700 Subject: net: remove driver_data direct access of struct device from more drivers In the near future, the driver core is going to not allow direct access to the driver_data pointer in struct device. Instead, the functions dev_get_drvdata() and dev_set_drvdata() should be used. These functions have been around since the beginning, so are backwards compatible with all older kernel versions. Signed-off-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/net/ehea/ehea_main.c | 8 ++++---- drivers/net/ibmveth.c | 8 ++++---- drivers/net/sb1250-mac.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 604c844d0769..37a190d85fcd 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3256,7 +3256,7 @@ static ssize_t ehea_probe_port(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ehea_adapter *adapter = dev->driver_data; + struct ehea_adapter *adapter = dev_get_drvdata(dev); struct ehea_port *port; struct device_node *eth_dn = NULL; int i; @@ -3311,7 +3311,7 @@ static ssize_t ehea_remove_port(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct ehea_adapter *adapter = dev->driver_data; + struct ehea_adapter *adapter = dev_get_drvdata(dev); struct ehea_port *port; int i; u32 logical_port_id; @@ -3399,7 +3399,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, adapter->pd = EHEA_PD_ID; - dev->dev.driver_data = adapter; + dev_set_drvdata(&dev->dev, adapter); /* initialize adapter and ports */ @@ -3463,7 +3463,7 @@ out: static int __devexit ehea_remove(struct of_device *dev) { - struct ehea_adapter *adapter = dev->dev.driver_data; + struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); int i; for (i = 0; i < EHEA_MAX_PORTS; i++) diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 0a51b0bd1e49..7902e5e16a1a 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1255,7 +1255,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ return -ENOMEM; adapter = netdev_priv(netdev); - dev->dev.driver_data = netdev; + dev_set_drvdata(&dev->dev, netdev); adapter->vdev = dev; adapter->netdev = netdev; @@ -1341,7 +1341,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ static int __devexit ibmveth_remove(struct vio_dev *dev) { - struct net_device *netdev = dev->dev.driver_data; + struct net_device *netdev = dev_get_drvdata(&dev->dev); struct ibmveth_adapter *adapter = netdev_priv(netdev); int i; @@ -1474,8 +1474,8 @@ const char * buf, size_t count) struct ibmveth_buff_pool *pool = container_of(kobj, struct ibmveth_buff_pool, kobj); - struct net_device *netdev = - container_of(kobj->parent, struct device, kobj)->driver_data; + struct net_device *netdev = dev_get_drvdata( + container_of(kobj->parent, struct device, kobj)); struct ibmveth_adapter *adapter = netdev_priv(netdev); long value = simple_strtol(buf, NULL, 10); long rc; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index aaeebf57a9a4..7a4b9fbddbaf 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2300,7 +2300,7 @@ static const struct net_device_ops sbmac_netdev_ops = { static int sbmac_init(struct platform_device *pldev, long long base) { - struct net_device *dev = pldev->dev.driver_data; + struct net_device *dev = dev_get_drvdata(&pldev->dev); int idx = pldev->id; struct sbmac_softc *sc = netdev_priv(dev); unsigned char *eaddr; @@ -2731,7 +2731,7 @@ static int __init sbmac_probe(struct platform_device *pldev) goto out_unmap; } - pldev->dev.driver_data = dev; + dev_set_drvdata(&pldev->dev, dev); SET_NETDEV_DEV(dev, &pldev->dev); sc = netdev_priv(dev); @@ -2756,7 +2756,7 @@ out_out: static int __exit sbmac_remove(struct platform_device *pldev) { - struct net_device *dev = pldev->dev.driver_data; + struct net_device *dev = dev_get_drvdata(&pldev->dev); struct sbmac_softc *sc = netdev_priv(dev); unregister_netdev(dev); -- cgit v1.2.3 From b6907b0c705b6db221f937b4d343e2a6b280c8c5 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 5 May 2009 12:22:53 -0700 Subject: net: smsc911x: add power management functions This adds a power management implementation for smsc911x.c which assumes the chips remains powered during suspend. The device is put in its D1 power saving mode. Signed-off-by: Daniel Mack Acked-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 5113b26fc2d9..9a8528c5bb5e 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -2109,12 +2109,58 @@ out_0: return retval; } +#ifdef CONFIG_PM +/* This implementation assumes the devices remains powered on its VDDVARIO + * pins during suspend. */ + +static int smsc911x_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct smsc911x_data *pdata = netdev_priv(dev); + + /* enable wake on LAN, energy detection and the external PME + * signal. */ + smsc911x_reg_write(pdata, PMT_CTRL, + PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ | + PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_); + + return 0; +} + +static int smsc911x_resume(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct smsc911x_data *pdata = netdev_priv(dev); + unsigned int to = 100; + + /* Note 3.11 from the datasheet: + * "When the LAN9220 is in a power saving state, a write of any + * data to the BYTE_TEST register will wake-up the device." + */ + smsc911x_reg_write(pdata, BYTE_TEST, 0); + + /* poll the READY bit in PMT_CTRL. Any other access to the device is + * forbidden while this bit isn't set. Try for 100ms and return -EIO + * if it failed. */ + while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) + udelay(1000); + + return (to == 0) ? -EIO : 0; +} + +#else +#define smsc911x_suspend NULL +#define smsc911x_resume NULL +#endif + static struct platform_driver smsc911x_driver = { .probe = smsc911x_drv_probe, .remove = smsc911x_drv_remove, .driver = { .name = SMSC_CHIPNAME, }, + .suspend = smsc911x_suspend, + .resume = smsc911x_resume, }; /* Entry point for loading the module */ -- cgit v1.2.3 From f001fde5eadd915f4858d22ed70d7040f48767cf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 5 May 2009 02:48:28 +0000 Subject: net: introduce a list of device addresses dev_addr_list (v6) v5 -> v6 (current): -removed so far unused static functions -corrected dev_addr_del_multiple to call del instead of add v4 -> v5: -added device address type (suggested by davem) -removed refcounting (better to have simplier code then safe potentially few bytes) v3 -> v4: -changed kzalloc to kmalloc in __hw_addr_add_ii() -ASSERT_RTNL() avoided in dev_addr_flush() and dev_addr_init() v2 -> v3: -removed unnecessary rcu read locking -moved dev_addr_flush() calling to ensure no null dereference of dev_addr v1 -> v2: -added forgotten ASSERT_RTNL to dev_addr_init and dev_addr_flush -removed unnecessary rcu_read locking in dev_addr_init -use compare_ether_addr_64bits instead of compare_ether_addr -use L1_CACHE_BYTES as size for allocating struct netdev_hw_addr -use call_rcu instead of rcu_synchronize -moved is_etherdev_addr into __KERNEL__ ifdef This patch introduces a new list in struct net_device and brings a set of functions to handle the work with device address list. The list is a replacement for the original dev_addr field and because in some situations there is need to carry several device addresses with the net device. To be backward compatible, dev_addr is made to point to the first member of the list so original drivers sees no difference. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- include/linux/etherdevice.h | 27 +++++ include/linux/netdevice.h | 37 ++++++- net/core/dev.c | 250 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 312 insertions(+), 2 deletions(-) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index a1f17abba7dc..3d7a6687d247 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -182,6 +182,33 @@ static inline unsigned compare_ether_addr_64bits(const u8 addr1[6+2], return compare_ether_addr(addr1, addr2); #endif } + +/** + * is_etherdev_addr - Tell if given Ethernet address belongs to the device. + * @dev: Pointer to a device structure + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Compare passed address with all addresses of the device. Return true if the + * address if one of the device addresses. + * + * Note that this function calls compare_ether_addr_64bits() so take care of + * the right padding. + */ +static inline bool is_etherdev_addr(const struct net_device *dev, + const u8 addr[6 + 2]) +{ + struct netdev_hw_addr *ha; + int res = 1; + + rcu_read_lock(); + for_each_dev_addr(dev, ha) { + res = compare_ether_addr_64bits(addr, ha->addr); + if (!res) + break; + } + rcu_read_unlock(); + return !res; +} #endif /* __KERNEL__ */ /** diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ff42aba403c5..02882e2ebd49 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -210,6 +210,16 @@ struct dev_addr_list #define dmi_users da_users #define dmi_gusers da_gusers +struct netdev_hw_addr { + struct list_head list; + unsigned char addr[MAX_ADDR_LEN]; + unsigned char type; +#define NETDEV_HW_ADDR_T_LAN 1 +#define NETDEV_HW_ADDR_T_SAN 2 +#define NETDEV_HW_ADDR_T_SLAVE 3 + struct rcu_head rcu_head; +}; + struct hh_cache { struct hh_cache *hh_next; /* Next entry */ @@ -784,8 +794,11 @@ struct net_device */ unsigned long last_rx; /* Time of last Rx */ /* Interface address info used in eth_type_trans() */ - unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast - because most packets are unicast) */ + unsigned char *dev_addr; /* hw address, (before bcast + because most packets are + unicast) */ + + struct list_head dev_addr_list; /* list of device hw addresses */ unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ @@ -1791,6 +1804,13 @@ static inline void netif_addr_unlock_bh(struct net_device *dev) spin_unlock_bh(&dev->addr_list_lock); } +/* + * dev_addr_list walker. Should be used only for read access. Call with + * rcu_read_lock held. + */ +#define for_each_dev_addr(dev, ha) \ + list_for_each_entry_rcu(ha, &dev->dev_addr_list, list) + /* These functions live elsewhere (drivers/net/net_init.c, but related) */ extern void ether_setup(struct net_device *dev); @@ -1803,6 +1823,19 @@ extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, alloc_netdev_mq(sizeof_priv, name, setup, 1) extern int register_netdev(struct net_device *dev); extern void unregister_netdev(struct net_device *dev); + +/* Functions used for device addresses handling */ +extern int dev_addr_add(struct net_device *dev, unsigned char *addr, + unsigned char addr_type); +extern int dev_addr_del(struct net_device *dev, unsigned char *addr, + unsigned char addr_type); +extern int dev_addr_add_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type); +extern int dev_addr_del_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type); + /* Functions used for secondary unicast and multicast support */ extern void dev_set_rx_mode(struct net_device *dev); extern void __dev_set_rx_mode(struct net_device *dev); diff --git a/net/core/dev.c b/net/core/dev.c index 3c8073fe970a..637ea71b0a0d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3434,6 +3434,252 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } +/* hw addresses list handling functions */ + +static int __hw_addr_add(struct list_head *list, unsigned char *addr, + int addr_len, unsigned char addr_type) +{ + struct netdev_hw_addr *ha; + int alloc_size; + + if (addr_len > MAX_ADDR_LEN) + return -EINVAL; + + alloc_size = sizeof(*ha); + if (alloc_size < L1_CACHE_BYTES) + alloc_size = L1_CACHE_BYTES; + ha = kmalloc(alloc_size, GFP_ATOMIC); + if (!ha) + return -ENOMEM; + memcpy(ha->addr, addr, addr_len); + ha->type = addr_type; + list_add_tail_rcu(&ha->list, list); + return 0; +} + +static void ha_rcu_free(struct rcu_head *head) +{ + struct netdev_hw_addr *ha; + + ha = container_of(head, struct netdev_hw_addr, rcu_head); + kfree(ha); +} + +static int __hw_addr_del_ii(struct list_head *list, unsigned char *addr, + int addr_len, unsigned char addr_type, + int ignore_index) +{ + struct netdev_hw_addr *ha; + int i = 0; + + list_for_each_entry(ha, list, list) { + if (i++ != ignore_index && + !memcmp(ha->addr, addr, addr_len) && + (ha->type == addr_type || !addr_type)) { + list_del_rcu(&ha->list); + call_rcu(&ha->rcu_head, ha_rcu_free); + return 0; + } + } + return -ENOENT; +} + +static int __hw_addr_add_multiple_ii(struct list_head *to_list, + struct list_head *from_list, + int addr_len, unsigned char addr_type, + int ignore_index) +{ + int err; + struct netdev_hw_addr *ha, *ha2; + unsigned char type; + + list_for_each_entry(ha, from_list, list) { + type = addr_type ? addr_type : ha->type; + err = __hw_addr_add(to_list, ha->addr, addr_len, type); + if (err) + goto unroll; + } + return 0; + +unroll: + list_for_each_entry(ha2, from_list, list) { + if (ha2 == ha) + break; + type = addr_type ? addr_type : ha2->type; + __hw_addr_del_ii(to_list, ha2->addr, addr_len, type, + ignore_index); + } + return err; +} + +static void __hw_addr_del_multiple_ii(struct list_head *to_list, + struct list_head *from_list, + int addr_len, unsigned char addr_type, + int ignore_index) +{ + struct netdev_hw_addr *ha; + unsigned char type; + + list_for_each_entry(ha, from_list, list) { + type = addr_type ? addr_type : ha->type; + __hw_addr_del_ii(to_list, ha->addr, addr_len, addr_type, + ignore_index); + } +} + +static void __hw_addr_flush(struct list_head *list) +{ + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, list, list) { + list_del_rcu(&ha->list); + call_rcu(&ha->rcu_head, ha_rcu_free); + } +} + +/* Device addresses handling functions */ + +static void dev_addr_flush(struct net_device *dev) +{ + /* rtnl_mutex must be held here */ + + __hw_addr_flush(&dev->dev_addr_list); + dev->dev_addr = NULL; +} + +static int dev_addr_init(struct net_device *dev) +{ + unsigned char addr[MAX_ADDR_LEN]; + struct netdev_hw_addr *ha; + int err; + + /* rtnl_mutex must be held here */ + + INIT_LIST_HEAD(&dev->dev_addr_list); + memset(addr, 0, sizeof(*addr)); + err = __hw_addr_add(&dev->dev_addr_list, addr, sizeof(*addr), + NETDEV_HW_ADDR_T_LAN); + if (!err) { + /* + * Get the first (previously created) address from the list + * and set dev_addr pointer to this location. + */ + ha = list_first_entry(&dev->dev_addr_list, + struct netdev_hw_addr, list); + dev->dev_addr = ha->addr; + } + return err; +} + +/** + * dev_addr_add - Add a device address + * @dev: device + * @addr: address to add + * @addr_type: address type + * + * Add a device address to the device or increase the reference count if + * it already exists. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_add(struct net_device *dev, unsigned char *addr, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + err = __hw_addr_add(&dev->dev_addr_list, addr, dev->addr_len, + addr_type); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + return err; +} +EXPORT_SYMBOL(dev_addr_add); + +/** + * dev_addr_del - Release a device address. + * @dev: device + * @addr: address to delete + * @addr_type: address type + * + * Release reference to a device address and remove it from the device + * if the reference count drops to zero. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_del(struct net_device *dev, unsigned char *addr, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + err = __hw_addr_del_ii(&dev->dev_addr_list, addr, dev->addr_len, + addr_type, 0); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + return err; +} +EXPORT_SYMBOL(dev_addr_del); + +/** + * dev_addr_add_multiple - Add device addresses from another device + * @to_dev: device to which addresses will be added + * @from_dev: device from which addresses will be added + * @addr_type: address type - 0 means type will be used from from_dev + * + * Add device addresses of the one device to another. + ** + * The caller must hold the rtnl_mutex. + */ +int dev_addr_add_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type) +{ + int err; + + ASSERT_RTNL(); + + if (from_dev->addr_len != to_dev->addr_len) + return -EINVAL; + err = __hw_addr_add_multiple_ii(&to_dev->dev_addr_list, + &from_dev->dev_addr_list, + to_dev->addr_len, addr_type, 0); + if (!err) + call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); + return err; +} +EXPORT_SYMBOL(dev_addr_add_multiple); + +/** + * dev_addr_del_multiple - Delete device addresses by another device + * @to_dev: device where the addresses will be deleted + * @from_dev: device by which addresses the addresses will be deleted + * @addr_type: address type - 0 means type will used from from_dev + * + * Deletes addresses in to device by the list of addresses in from device. + * + * The caller must hold the rtnl_mutex. + */ +int dev_addr_del_multiple(struct net_device *to_dev, + struct net_device *from_dev, + unsigned char addr_type) +{ + ASSERT_RTNL(); + + if (from_dev->addr_len != to_dev->addr_len) + return -EINVAL; + __hw_addr_del_multiple_ii(&to_dev->dev_addr_list, + &from_dev->dev_addr_list, + to_dev->addr_len, addr_type, 0); + call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); + return 0; +} +EXPORT_SYMBOL(dev_addr_del_multiple); + +/* unicast and multicast addresses handling functions */ + int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int glbl) { @@ -4776,6 +5022,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, dev->gso_max_size = GSO_MAX_SIZE; + dev_addr_init(dev); netdev_init_queues(dev); INIT_LIST_HEAD(&dev->napi_list); @@ -4801,6 +5048,9 @@ void free_netdev(struct net_device *dev) kfree(dev->_tx); + /* Flush device addresses */ + dev_addr_flush(dev); + list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) netif_napi_del(p); -- cgit v1.2.3 From aee64faf236815e0f337408892c01b373cd340f3 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 5 May 2009 06:20:51 +0000 Subject: bonding: get rid of CONFIG_PROC_FS ifdefs Remove CONFIG_PROC_FS ifdefs from the code by adding void functions. Signed-off-by: Jiri Pirko drivers/net/bonding/bond_main.c | 30 ++++++++++++++++++++---------- 1 files changed, 20 insertions(+), 10 deletions(-) Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e3af662b0559..815191dd03c3 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3459,8 +3459,28 @@ static void bond_destroy_proc_dir(void) bond_proc_dir = NULL; } } + +#else /* !CONFIG_PROC_FS */ + +static int bond_create_proc_entry(struct bonding *bond) +{ +} + +static void bond_remove_proc_entry(struct bonding *bond) +{ +} + +static void bond_create_proc_dir(void) +{ +} + +static void bond_destroy_proc_dir(void) +{ +} + #endif /* CONFIG_PROC_FS */ + /*-------------------------- netdev event handling --------------------------*/ /* @@ -3468,10 +3488,8 @@ static void bond_destroy_proc_dir(void) */ static int bond_event_changename(struct bonding *bond) { -#ifdef CONFIG_PROC_FS bond_remove_proc_entry(bond); bond_create_proc_entry(bond); -#endif down_write(&(bonding_rwsem)); bond_destroy_sysfs_entry(bond); bond_create_sysfs_entry(bond); @@ -4637,9 +4655,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); -#ifdef CONFIG_PROC_FS bond_create_proc_entry(bond); -#endif list_add_tail(&bond->bond_list, &bond_dev_list); return 0; @@ -4677,9 +4693,7 @@ static void bond_deinit(struct net_device *bond_dev) bond_work_cancel_all(bond); -#ifdef CONFIG_PROC_FS bond_remove_proc_entry(bond); -#endif } /* Unregister and free all bond devices. @@ -4698,9 +4712,7 @@ static void bond_free_all(void) bond_destroy(bond); } -#ifdef CONFIG_PROC_FS bond_destroy_proc_dir(); -#endif } /*------------------------- Module initialization ---------------------------*/ @@ -5196,9 +5208,7 @@ static int __init bonding_init(void) goto out; } -#ifdef CONFIG_PROC_FS bond_create_proc_dir(); -#endif init_rwsem(&bonding_rwsem); -- cgit v1.2.3 From c8014fe1d4548da8b9ea54730852c48a7117b03f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 May 2009 20:30:01 +0000 Subject: r6040: check for absent PHY Some devices have two R6040 MACs but the second one is not wired to any PHY, therefore the interface is just unusable. Warn the user about that and prevent device from registering. Tested-by: bifferos Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 6f97b47d74a6..65627253c988 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -742,6 +742,14 @@ static int r6040_up(struct net_device *dev) struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; int ret; + u16 val; + + /* Check presence of a second PHY */ + val = r6040_phy_read(ioaddr, lp->phy_addr, 2); + if (val == 0xFFFF) { + printk(KERN_ERR DRV_NAME " no second PHY attached\n"); + return -EIO; + } /* Initialise and alloc RX/TX buffers */ r6040_init_txbufs(dev); -- cgit v1.2.3 From ba1cd541ecdaa659c5bf952659c4ad0d0707394d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 4 May 2009 20:30:45 +0000 Subject: r6040: bump version to 0.23 and date to 05May2009 Bump version to 0.23 and date to 05May2009. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/r6040.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 65627253c988..1508b124e3d8 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include #define DRV_NAME "r6040" -#define DRV_VERSION "0.22" -#define DRV_RELDATE "25Mar2009" +#define DRV_VERSION "0.23" +#define DRV_RELDATE "05May2009" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ -- cgit v1.2.3 From ae8d7f884a24ee920e417077b2615c6862be687f Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Tue, 5 May 2009 01:01:29 +0000 Subject: tcp:fix the code indent Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bda74e8aed7e..fc79e3416288 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1593,7 +1593,7 @@ process: #endif { if (!tcp_prequeue(sk, skb)) - ret = tcp_v4_do_rcv(sk, skb); + ret = tcp_v4_do_rcv(sk, skb); } } else sk_add_backlog(sk, skb); -- cgit v1.2.3 From 78a658d9720ce1b3dd71af3ee6d207ca751a48f5 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Tue, 5 May 2009 01:03:32 +0000 Subject: lasi_82596: fix printk format warning drivers/net/lasi_82596.c:164: warning: format '%lx' expects type 'long unsigned int', but argument 3 has type 'resource_size_t' drivers/net/lasi_82596.c:169: warning: format '%lx' expects type 'long unsigned int', but argument 2 has type 'resource_size_t' Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/lasi_82596.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index efbae4b8398e..a0c578585a50 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -161,12 +161,12 @@ lan_init_chip(struct parisc_device *dev) if (!dev->irq) { printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n", - __FILE__, dev->hpa.start); + __FILE__, (unsigned long)dev->hpa.start); return -ENODEV; } - printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start, - dev->irq); + printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", + (unsigned long)dev->hpa.start, dev->irq); netdevice = alloc_etherdev(sizeof(struct i596_private)); if (!netdevice) -- cgit v1.2.3 From 0e41f715c04f85a40ae6531d660be2241717be1c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 11:48:56 +0200 Subject: mac80211: fix various problems in ibss code There are a few problems in the IBSS code: a) it tries to activate interfaces that are down after scanning b) it crashes after scanning on an IBSS iface that isn't active c) since the ssid_len is used as a flag, need to make it visible only after all other settings are set, this helps protect against b) For b), we get a system crash: wlan0: Creating new IBSS network, BSSID ce:f9:88:76:1e:4d BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<...>] ieee80211_sta_find_ibss+0x294/0x37d [mac80211] Call Trace: [<...>] ieee80211_ibss_notify_scan_completed+0x0/0x88 [mac80211] Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6030e003180c..895f4854760c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -786,8 +786,12 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; if (sdata->vif.type != NL80211_IFTYPE_ADHOC) continue; + if (!sdata->u.ibss.ssid_len) + continue; sdata->u.ibss.last_scan_completed = jiffies; ieee80211_sta_find_ibss(sdata); } @@ -827,9 +831,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, { struct sk_buff *skb; - memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); - sdata->u.ibss.ssid_len = params->ssid_len; - if (params->bssid) { memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); sdata->u.ibss.fixed_bssid = true; @@ -859,6 +860,17 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; sdata->u.ibss.ibss_join_req = jiffies; + memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + + /* + * The ssid_len setting below is used to see whether + * we are active, and we need all other settings + * before that may get visible. + */ + mb(); + + sdata->u.ibss.ssid_len = params->ssid_len; + set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); -- cgit v1.2.3 From d5edaedc16ebd0635435dec068d49e07a76ba7d9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Apr 2009 23:02:51 +0200 Subject: mac80211: fix PS vs. scan race When somebody changes the PS parameters while scanning is in progress, we enable PS -- during the scan. This is clearly not desirable, and we can just abort enabling PS when scanning since when the scan finishes it will be taken care of. Signed-off-by: Johannes Berg Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3610c11286bc..2029b71eb879 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -487,6 +487,13 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, { struct ieee80211_conf *conf = &local->hw.conf; + /* + * If we are scanning right now then the parameters will + * take effect when scan finishes. + */ + if (local->hw_scanning || local->sw_scanning) + return; + if (conf->dynamic_ps_timeout > 0 && !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { mod_timer(&local->dynamic_ps_timer, jiffies + -- cgit v1.2.3 From 9ccebe6148bcb0aba2d89743df2ff182ced505ec Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 10:32:36 +0200 Subject: mac80211: rename max_sleep_interval to max_sleep_period Kalle points out that max_sleep_interval is somewhat confusing because the value is measured in beacon intervals, and not in TU. Rename it to max_sleep_period to be consistent with things like DTIM period that are also measured in beacon intervals. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++-- net/mac80211/mlme.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 446dbf75a1c5..81d706d85226 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -559,7 +559,7 @@ enum ieee80211_conf_changed { * @beacon_int: beacon interval (TODO make interface config) * * @listen_interval: listen interval in units of beacon interval - * @max_sleep_interval: the maximum number of beacon intervals to sleep for + * @max_sleep_period: the maximum number of beacon intervals to sleep for * before checking the beacon for a TIM bit (managed mode only); this * value will be only achievable between DTIM frames, the hardware * needs to check for the multicast traffic bit in DTIM beacons. @@ -584,7 +584,7 @@ struct ieee80211_conf { int beacon_int; u32 flags; int power_level, dynamic_ps_timeout; - int max_sleep_interval; + int max_sleep_period; u16 listen_interval; bool radio_enabled; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2029b71eb879..f8925ca7c8f0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -562,7 +562,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) maxslp = min_t(int, dtimper, latency / beaconint_us); - local->hw.conf.max_sleep_interval = maxslp; + local->hw.conf.max_sleep_period = maxslp; local->ps_sdata = found; } } else { -- cgit v1.2.3 From 2d72289095e9621158acf1d59a830cfe920fa93b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 10:38:26 +0200 Subject: mac80211: internally clear failed scans properly When the IBSS code wants to scan, but that fails, we can get stuck in a situation where you can never scan again. Fix this by properly notifying ourselves when the scan request has failed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 895f4854760c..9fe1f937e0b4 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -439,7 +439,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) memcpy(sdata->local->int_scan_req.ssids[0].ssid, ifibss->ssid, IEEE80211_MAX_SSID_LEN); sdata->local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; - ieee80211_request_scan(sdata, &sdata->local->int_scan_req); + if (ieee80211_request_scan(sdata, &sdata->local->int_scan_req)) + ieee80211_scan_failed(sdata->local); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -560,7 +561,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) ifibss->ssid, IEEE80211_MAX_SSID_LEN); local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; - ieee80211_request_scan(sdata, &local->int_scan_req); + if (ieee80211_request_scan(sdata, &local->int_scan_req)) + ieee80211_scan_failed(local); } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; -- cgit v1.2.3 From f3b85252f081581a8f257545ed748062dce7798b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 16:01:47 +0200 Subject: mac80211: fix scan races and rework scanning There are some places marked /* XXX maybe racy? */ and they really are racy because there's no locking. This patch reworks much of the scan code, and introduces proper locking for the scan request as well as the internal scanning (which is necessary for IBSS/managed modes). Helper functions are added to call the scanning code whenever necessary. The scan deferring is changed to simply queue the scanning work instead of trying to start the scan in place, the scanning work will then take care of the rest. Also, currently when internal scans are requested for an interface that is trying to associate, we reject such scans. This was not intended, the mlme code has provisions to scan twice when it can't find the BSS to associate with right away; this has never worked properly. Fix this by not rejecting internal scan requests for an interface that is associating. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 22 +-- net/mac80211/ieee80211_i.h | 6 +- net/mac80211/main.c | 2 + net/mac80211/mlme.c | 28 ++-- net/mac80211/scan.c | 387 +++++++++++++++++++++++++-------------------- 5 files changed, 229 insertions(+), 216 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 9fe1f937e0b4..25ff583612ef 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -432,15 +432,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->dev->name); - /* XXX maybe racy? */ - if (sdata->local->scan_req) - return; - - memcpy(sdata->local->int_scan_req.ssids[0].ssid, - ifibss->ssid, IEEE80211_MAX_SSID_LEN); - sdata->local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; - if (ieee80211_request_scan(sdata, &sdata->local->int_scan_req)) - ieee80211_scan_failed(sdata->local); + ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -553,16 +545,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->dev->name); - /* XXX maybe racy? */ - if (local->scan_req) - return; - - memcpy(local->int_scan_req.ssids[0].ssid, - ifibss->ssid, IEEE80211_MAX_SSID_LEN); - local->int_scan_req.ssids[0].ssid_len = - ifibss->ssid_len; - if (ieee80211_request_scan(sdata, &local->int_scan_req)) - ieee80211_scan_failed(local); + ieee80211_request_internal_scan(sdata, ifibss->ssid, + ifibss->ssid_len); } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1579bc92c88d..e6fd4bcf1c3c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -659,6 +659,7 @@ struct ieee80211_local { /* Scanning and BSS list */ + struct mutex scan_mtx; bool sw_scanning, hw_scanning; struct cfg80211_ssid scan_ssid; struct cfg80211_scan_request int_scan_req; @@ -947,6 +948,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); +int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len); int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); int ieee80211_scan_results(struct ieee80211_local *local, @@ -960,9 +963,6 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, const char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); -void ieee80211_scan_failed(struct ieee80211_local *local); -int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, - struct cfg80211_scan_request *req); struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5ca62ea15079..e00d124e4ef7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -783,6 +783,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_LIST_HEAD(&local->interfaces); mutex_init(&local->iflist_mtx); + mutex_init(&local->scan_mtx); spin_lock_init(&local->key_lock); @@ -1126,6 +1127,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); mutex_destroy(&local->iflist_mtx); + mutex_destroy(&local->scan_mtx); wiphy_free(local->hw.wiphy); } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f8925ca7c8f0..a2f5e6223059 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2072,19 +2072,15 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) return 0; } else { if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { + u8 ssid_len = 0; + + if (!(ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL)) + ssid_len = ifmgd->ssid_len; + ifmgd->assoc_scan_tries++; - /* XXX maybe racy? */ - if (local->scan_req) - return -1; - memcpy(local->int_scan_req.ssids[0].ssid, - ifmgd->ssid, IEEE80211_MAX_SSID_LEN); - if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) - local->int_scan_req.ssids[0].ssid_len = 0; - else - local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; - if (ieee80211_start_scan(sdata, &local->int_scan_req)) - ieee80211_scan_failed(local); + ieee80211_request_internal_scan(sdata, ifmgd->ssid, + ssid_len); ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); @@ -2122,14 +2118,8 @@ static void ieee80211_sta_work(struct work_struct *work) ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { - /* - * The call to ieee80211_start_scan can fail but ieee80211_request_scan - * (which queued ieee80211_sta_work) did not return an error. Thus, call - * ieee80211_scan_failed here if ieee80211_start_scan fails in order to - * notify the scan requester. - */ - if (ieee80211_start_scan(sdata, local->scan_req)) - ieee80211_scan_failed(local); + queue_delayed_work(local->hw.workqueue, &local->scan_work, + round_jiffies_relative(0)); return; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f25b07feabf9..086d21645cbc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -202,18 +202,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_QUEUED; } -void ieee80211_scan_failed(struct ieee80211_local *local) -{ - if (WARN_ON(!local->scan_req)) - return; - - /* notify cfg80211 about the failed scan */ - if (local->scan_req != &local->int_scan_req) - cfg80211_scan_done(local->scan_req, true); - - local->scan_req = NULL; -} - /* * inform AP that we will go to sleep so that it will buffer the frames * while we scan @@ -274,29 +262,46 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) } } +static void ieee80211_restore_scan_ies(struct ieee80211_local *local) +{ + kfree(local->scan_req->ie); + local->scan_req->ie = local->orig_ies; + local->scan_req->ie_len = local->orig_ies_len; +} + void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; + bool was_hw_scan; - if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) - return; + mutex_lock(&local->scan_mtx); - if (WARN_ON(!local->scan_req)) + if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) { + mutex_unlock(&local->scan_mtx); return; + } - if (local->hw_scanning) { - kfree(local->scan_req->ie); - local->scan_req->ie = local->orig_ies; - local->scan_req->ie_len = local->orig_ies_len; + if (WARN_ON(!local->scan_req)) { + mutex_unlock(&local->scan_mtx); + return; } + if (local->hw_scanning) + ieee80211_restore_scan_ies(local); + if (local->scan_req != &local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; - if (local->hw_scanning) { - local->hw_scanning = false; + was_hw_scan = local->hw_scanning; + local->hw_scanning = false; + local->sw_scanning = false; + + /* we only have to protect scan_req and hw/sw scan */ + mutex_unlock(&local->scan_mtx); + + if (was_hw_scan) { /* * Somebody might have requested channel change during scan * that we won't have acted upon, try now. ieee80211_hw_config @@ -306,7 +311,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) goto done; } - local->sw_scanning = false; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); netif_tx_lock_bh(local->mdev); @@ -354,6 +358,146 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) } EXPORT_SYMBOL(ieee80211_scan_completed); +static int ieee80211_start_sw_scan(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + /* + * Hardware/driver doesn't support hw_scan, so use software + * scanning instead. First send a nullfunc frame with power save + * bit on so that AP will buffer the frames for us while we are not + * listening, then send probe requests to each channel and wait for + * the responses. After all channels are scanned, tune back to the + * original channel and send a nullfunc frame with power save bit + * off to trigger the AP to send us all the buffered frames. + * + * Note that while local->sw_scanning is true everything else but + * nullfunc frames and probe requests will be dropped in + * ieee80211_tx_h_check_assoc(). + */ + if (local->ops->sw_scan_start) + local->ops->sw_scan_start(local_to_hw(local)); + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + + /* disable beaconing */ + if (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + ieee80211_if_config(sdata, + IEEE80211_IFCC_BEACON_ENABLED); + + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { + netif_tx_stop_all_queues(sdata->dev); + ieee80211_scan_ps_enable(sdata); + } + } else + netif_tx_stop_all_queues(sdata->dev); + } + mutex_unlock(&local->iflist_mtx); + + local->scan_state = SCAN_SET_CHANNEL; + local->scan_channel_idx = 0; + + netif_addr_lock_bh(local->mdev); + local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; + local->ops->configure_filter(local_to_hw(local), + FIF_BCN_PRBRESP_PROMISC, + &local->filter_flags, + local->mdev->mc_count, + local->mdev->mc_list); + netif_addr_unlock_bh(local->mdev); + + /* TODO: start scan as soon as all nullfunc frames are ACKed */ + queue_delayed_work(local->hw.workqueue, &local->scan_work, + IEEE80211_CHANNEL_TIME); + + return 0; +} + + +static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + int rc; + + if (local->scan_req) + return -EBUSY; + + if (local->ops->hw_scan) { + u8 *ies; + int ielen; + + ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + + local->scan_ies_len + req->ie_len, GFP_KERNEL); + if (!ies) + return -ENOMEM; + + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + local->orig_ies = req->ie; + local->orig_ies_len = req->ie_len; + req->ie = ies; + req->ie_len = ielen; + } + + local->scan_req = req; + local->scan_sdata = sdata; + + if (req != &local->int_scan_req && + sdata->vif.type == NL80211_IFTYPE_STATION && + (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE || + ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || + ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE)) { + /* actually wait for the assoc to finish/time out */ + set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); + return 0; + } + + if (local->ops->hw_scan) + local->hw_scanning = true; + else + local->sw_scanning = true; + /* + * Kicking off the scan need not be protected, + * only the scan variable stuff, since now + * local->scan_req is assigned and other callers + * will abort their scan attempts. + * + * This avoids getting a scan_mtx -> iflist_mtx + * dependency, so that the scan completed calls + * have more locking freedom. + */ + mutex_unlock(&local->scan_mtx); + + if (local->ops->hw_scan) + rc = local->ops->hw_scan(local_to_hw(local), + local->scan_req); + else + rc = ieee80211_start_sw_scan(local); + + mutex_lock(&local->scan_mtx); + + if (rc) { + if (local->ops->hw_scan) { + local->hw_scanning = false; + ieee80211_restore_scan_ies(local); + } else + local->sw_scanning = false; + + local->scan_req = NULL; + local->scan_sdata = NULL; + } + + return rc; +} + void ieee80211_scan_work(struct work_struct *work) { struct ieee80211_local *local = @@ -363,17 +507,41 @@ void ieee80211_scan_work(struct work_struct *work) int skip, i; unsigned long next_delay = 0; + mutex_lock(&local->scan_mtx); + if (!sdata || !local->scan_req) { + mutex_unlock(&local->scan_mtx); + return; + } + + if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) { + struct cfg80211_scan_request *req = local->scan_req; + int rc; + + local->scan_req = NULL; + + rc = __ieee80211_start_scan(sdata, req); + mutex_unlock(&local->scan_mtx); + + if (rc) + ieee80211_scan_completed(&local->hw, true); + return; + } + + mutex_unlock(&local->scan_mtx); + /* * Avoid re-scheduling when the sdata is going away. */ - if (!netif_running(sdata->dev)) + if (!netif_running(sdata->dev)) { + ieee80211_scan_completed(&local->hw, true); return; + } switch (local->scan_state) { case SCAN_SET_CHANNEL: /* if no more bands/channels left, complete scan */ if (local->scan_channel_idx >= local->scan_req->n_channels) { - ieee80211_scan_completed(local_to_hw(local), false); + ieee80211_scan_completed(&local->hw, false); return; } skip = 0; @@ -422,166 +590,35 @@ void ieee80211_scan_work(struct work_struct *work) next_delay); } - -int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, - struct cfg80211_scan_request *req) +int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req) { - struct ieee80211_local *local = scan_sdata->local; - struct ieee80211_sub_if_data *sdata; - - if (!req) - return -EINVAL; - - if (local->scan_req && local->scan_req != req) - return -EBUSY; - - local->scan_req = req; - - /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) - * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS - * BSSID: MACAddress - * SSID - * ScanType: ACTIVE, PASSIVE - * ProbeDelay: delay (in microseconds) to be used prior to transmitting - * a Probe frame during active scanning - * ChannelList - * MinChannelTime (>= ProbeDelay), in TU - * MaxChannelTime: (>= MinChannelTime), in TU - */ - - /* MLME-SCAN.confirm - * BSSDescriptionSet - * ResultCode: SUCCESS, INVALID_PARAMETERS - */ - - if (local->sw_scanning || local->hw_scanning) { - if (local->scan_sdata == scan_sdata) - return 0; - return -EBUSY; - } - - if (local->ops->hw_scan) { - u8 *ies; - int rc, ielen; - - ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + - local->scan_ies_len + req->ie_len, GFP_KERNEL); - if (!ies) - return -ENOMEM; + int res; - ielen = ieee80211_build_preq_ies(local, ies, - req->ie, req->ie_len); - local->orig_ies = req->ie; - local->orig_ies_len = req->ie_len; - req->ie = ies; - req->ie_len = ielen; - - local->hw_scanning = true; - rc = local->ops->hw_scan(local_to_hw(local), req); - if (rc) { - local->hw_scanning = false; - kfree(ies); - req->ie_len = local->orig_ies_len; - req->ie = local->orig_ies; - return rc; - } - local->scan_sdata = scan_sdata; - return 0; - } + mutex_lock(&sdata->local->scan_mtx); + res = __ieee80211_start_scan(sdata, req); + mutex_unlock(&sdata->local->scan_mtx); - /* - * Hardware/driver doesn't support hw_scan, so use software - * scanning instead. First send a nullfunc frame with power save - * bit on so that AP will buffer the frames for us while we are not - * listening, then send probe requests to each channel and wait for - * the responses. After all channels are scanned, tune back to the - * original channel and send a nullfunc frame with power save bit - * off to trigger the AP to send us all the buffered frames. - * - * Note that while local->sw_scanning is true everything else but - * nullfunc frames and probe requests will be dropped in - * ieee80211_tx_h_check_assoc(). - */ - local->sw_scanning = true; - if (local->ops->sw_scan_start) - local->ops->sw_scan_start(local_to_hw(local)); - - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) - continue; - - /* disable beaconing */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_if_config(sdata, - IEEE80211_IFCC_BEACON_ENABLED); - - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { - netif_tx_stop_all_queues(sdata->dev); - ieee80211_scan_ps_enable(sdata); - } - } else - netif_tx_stop_all_queues(sdata->dev); - } - mutex_unlock(&local->iflist_mtx); - - local->scan_state = SCAN_SET_CHANNEL; - local->scan_channel_idx = 0; - local->scan_sdata = scan_sdata; - local->scan_req = req; - - netif_addr_lock_bh(local->mdev); - local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); - netif_addr_unlock_bh(local->mdev); - - /* TODO: start scan as soon as all nullfunc frames are ACKed */ - queue_delayed_work(local->hw.workqueue, &local->scan_work, - IEEE80211_CHANNEL_TIME); - - return 0; + return res; } - -int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, - struct cfg80211_scan_request *req) +int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd; - - if (!req) - return -EINVAL; - - if (local->scan_req && local->scan_req != req) - return -EBUSY; - - local->scan_req = req; + int ret = -EBUSY; - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return ieee80211_start_scan(sdata, req); + mutex_lock(&local->scan_mtx); - /* - * STA has a state machine that might need to defer scanning - * while it's trying to associate/authenticate, therefore we - * queue it up to the state machine in that case. - */ + /* busy scanning */ + if (local->scan_req) + goto unlock; - if (local->sw_scanning || local->hw_scanning) { - if (local->scan_sdata == sdata) - return 0; - return -EBUSY; - } - - ifmgd = &sdata->u.mgd; - set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); - queue_work(local->hw.workqueue, &ifmgd->work); + memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); + local->int_scan_req.ssids[0].ssid_len = ssid_len; - return 0; + ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); + unlock: + mutex_unlock(&local->scan_mtx); + return ret; } -- cgit v1.2.3 From 57c4d7b4c4986037be51476b8e3025d5ba18d8b8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 16:10:04 +0200 Subject: mac80211: clean up beacon interval settings We currently have two beacon interval configuration knobs: hw.conf.beacon_int and vif.bss_info.beacon_int. This is rather confusing, even though the former is used when we beacon ourselves and the latter when we are associated to an AP. This just deprecates the hw.conf.beacon_int setting in favour of always using vif.bss_info.beacon_int. Since it touches all the beaconing IBSS code anyway, we can also add support for the cfg80211 IBSS beacon interval configuration easily. NOTE: The hw.conf.beacon_int setting is retained for now due to drivers still using it -- I couldn't untangle all drivers, some are updated in this patch. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/mac.c | 6 +++--- drivers/net/wireless/ath/ar9170/main.c | 5 ++++- drivers/net/wireless/ath/ath5k/base.c | 5 ++++- drivers/net/wireless/ath/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath/ath9k/beacon.c | 9 +++------ drivers/net/wireless/ath/ath9k/main.c | 22 ++++++++++++---------- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- drivers/net/wireless/b43/main.c | 12 +++++++----- drivers/net/wireless/b43legacy/main.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 ++--- drivers/net/wireless/libertas_tf/main.c | 2 +- drivers/net/wireless/mac80211_hwsim.c | 20 ++++++++++++-------- include/net/mac80211.h | 14 ++++++++++++-- net/mac80211/cfg.c | 17 +++++------------ net/mac80211/ibss.c | 25 +++++++++++++++++-------- net/mac80211/main.c | 17 +++++++++++------ net/mac80211/mlme.c | 1 + net/mac80211/sta_info.c | 12 ++++++------ net/mac80211/tx.c | 2 +- 21 files changed, 112 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index c8fa3073169f..0e5967dd119c 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -316,9 +316,9 @@ int ar9170_set_beacon_timers(struct ar9170 *ar) u32 v = 0; u32 pretbtt = 0; - v |= ar->hw->conf.beacon_int; - if (ar->vif) { + v |= ar->vif->bss_conf.beacon_int; + switch (ar->vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: @@ -326,7 +326,7 @@ int ar9170_set_beacon_timers(struct ar9170 *ar) break; case NL80211_IFTYPE_AP: v |= BIT(24); - pretbtt = (ar->hw->conf.beacon_int - 6) << 16; + pretbtt = (ar->vif->bss_conf.beacon_int - 6) << 16; break; default: break; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 1b60906b80c9..49c729bc7147 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1337,7 +1337,7 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) goto out; } - if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) { + if (changed & BSS_CHANGED_BEACON_INT) { err = ar9170_set_beacon_timers(ar); if (err) goto out; @@ -1499,6 +1499,9 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, #endif /* CONFIG_AR9170_LEDS */ } + if (changed & BSS_CHANGED_BEACON_INT) + err = ar9170_set_beacon_timers(ar); + if (changed & BSS_CHANGED_HT) { /* TODO */ err = 0; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c8c658bfcf9d..e4b1d9efa42e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2756,7 +2756,6 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&sc->lock); - sc->bintval = conf->beacon_int; sc->power_level = conf->power_level; ret = ath5k_chan_set(sc, conf->channel); @@ -3083,6 +3082,10 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct ath5k_softc *sc = hw->priv; + + if (changes & BSS_CHANGED_BEACON_INT) + sc->bintval = bss_conf->beacon_int; + if (changes & BSS_CHANGED_ASSOC) { mutex_lock(&sc->lock); sc->assoc = bss_conf->assoc; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c92d46fa9d51..d5084ddf44ff 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -590,6 +590,8 @@ struct ath_softc { int led_on_cnt; int led_off_cnt; + int beacon_interval; + struct ath_rfkill rf_kill; struct ath_ani ani; struct ath9k_node_stats nodestats; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index eb4759fc6a0d..c17b8382e328 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -320,8 +320,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) u64 tsfadjust; int intval; - intval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; /* * Calculate the TSF offset for this beacon slot, i.e., the @@ -431,8 +430,7 @@ void ath_beacon_tasklet(unsigned long data) * on the tsf to safeguard against missing an swba. */ - intval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf); @@ -711,8 +709,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) /* Setup the beacon configuration parameters */ memset(&conf, 0, sizeof(struct ath_beacon_config)); - conf.beacon_interval = sc->hw->conf.beacon_int ? - sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; + conf.beacon_interval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; conf.listen_interval = 1; conf.dtim_period = conf.beacon_interval; conf.dtim_count = 1; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2398d4f45f28..28cc9cd52f32 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2358,16 +2358,6 @@ skip_chan_change: if (changed & IEEE80211_CONF_CHANGE_POWER) sc->config.txpowlimit = 2 * conf->power_level; - /* - * The HW TSF has to be reset when the beacon interval changes. - * We set the flag here, and ath_beacon_config_ap() would take this - * into account when it gets called through the subsequent - * config_interface() call - with IFCC_BEACON in the changed field. - */ - - if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) - sc->sc_flags |= SC_OP_TSF_RESET; - mutex_unlock(&sc->mutex); return 0; @@ -2635,6 +2625,18 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath9k_bss_assoc_info(sc, vif, bss_conf); } + /* + * The HW TSF has to be reset when the beacon interval changes. + * We set the flag here, and ath_beacon_config_ap() would take this + * into account when it gets called through the subsequent + * config_interface() call - with IFCC_BEACON in the changed field. + */ + + if (changed & BSS_CHANGED_BEACON_INT) { + sc->sc_flags |= SC_OP_TSF_RESET; + sc->beacon_interval = bss_conf->beacon_int; + } + mutex_unlock(&sc->mutex); } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index faf2cab49ea3..501493ffc3a7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -971,7 +971,7 @@ int ath_cabq_update(struct ath_softc *sc) else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; - qi.tqi_readyTime = (sc->hw->conf.beacon_int * + qi.tqi_readyTime = (sc->beacon_interval * sc->config.cabqReadytime) / 100; ath_txq_update(sc, qnum, &qi); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a97c6ff0f12e..3c693e6ec904 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3468,11 +3468,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) if (phy->ops->set_rx_antenna) phy->ops->set_rx_antenna(dev, antenna); - /* Update templates for AP/mesh mode. */ - if (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) - b43_set_beacon_int(dev, conf->beacon_int); - if (!!conf->radio_enabled != phy->radio_on) { if (conf->radio_enabled) { b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED); @@ -3556,6 +3551,13 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, goto out_unlock_mutex; b43_mac_suspend(dev); + /* Update templates for AP/mesh mode. */ + if (changed & BSS_CHANGED_BEACON_INT && + (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || + b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43_set_beacon_int(dev, conf->beacon_int); + if (changed & BSS_CHANGED_BASIC_RATES) b43_update_basic_rates(dev, conf->basic_rates); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index ee202b4f77b5..276f314688f7 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2721,11 +2721,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Antennas for RX and management frame TX. */ b43legacy_mgmtframe_txantenna(dev, antenna_tx); - /* Update templates for AP mode. */ - if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) - b43legacy_set_beacon_int(dev, conf->beacon_int); - - if (!!conf->radio_enabled != phy->radio_on) { if (conf->radio_enabled) { b43legacy_radio_turn_on(dev); @@ -2827,6 +2822,11 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, b43legacy_mac_suspend(dev); + if (changed & BSS_CHANGED_BEACON_INT && + (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) || + b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))) + b43legacy_set_beacon_int(dev, conf->beacon_int); + if (changed & BSS_CHANGED_BASIC_RATES) b43legacy_update_basic_rates(dev, conf->basic_rates); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 277dfc57fde9..4920dcf7d7b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -567,7 +567,8 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv) beacon_int = iwl_adjust_beacon_interval(priv->beacon_int); priv->rxon_timing.atim_window = 0; } else { - beacon_int = iwl_adjust_beacon_interval(conf->beacon_int); + beacon_int = iwl_adjust_beacon_interval( + priv->vif->bss_conf.beacon_int); /* TODO: we need to get atim_window from upper stack * for now we set to 0 */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3dec2d25fa3d..cd8a5ed97c4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1313,7 +1313,6 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; - hw->conf.beacon_int = 100; hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) @@ -2751,7 +2750,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) priv->ibss_beacon = NULL; - priv->beacon_int = priv->hw->conf.beacon_int; + priv->beacon_int = priv->vif->bss_conf.beacon_int; priv->timestamp = 0; if ((priv->iw_mode == NL80211_IFTYPE_STATION)) priv->beacon_int = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a782292ed435..f9d9b65ef300 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -551,7 +551,8 @@ static void iwl3945_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.atim_window = 0; } else { priv->rxon_timing.beacon_interval = - iwl3945_adjust_beacon_interval(conf->beacon_int); + iwl3945_adjust_beacon_interval( + priv->vif->bss_conf.beacon_int); /* TODO: we need to get atim_window from upper stack * for now we set to 0 */ priv->rxon_timing.atim_window = 0; @@ -4211,8 +4212,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; - hw->conf.beacon_int = 100; - if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index e7289e2e7f16..68e47fb47a1e 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -380,7 +380,7 @@ static int lbtf_op_config_interface(struct ieee80211_hw *hw, if (beacon) { lbtf_beacon_set(priv, beacon); kfree_skb(beacon); - lbtf_beacon_ctrl(priv, 1, hw->conf.beacon_int); + lbtf_beacon_ctrl(priv, 1, vif->bss_conf.beacon_int); } break; default: diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index d4fdc8b7d7d8..24c95a619e4c 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -553,18 +553,13 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) struct mac80211_hwsim_data *data = hw->priv; struct ieee80211_conf *conf = &hw->conf; - printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n", + printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d)\n", wiphy_name(hw->wiphy), __func__, - conf->channel->center_freq, conf->radio_enabled, - conf->beacon_int); + conf->channel->center_freq, conf->radio_enabled); data->channel = conf->channel; data->radio_enabled = conf->radio_enabled; - data->beacon_int = 1024 * conf->beacon_int / 1000 * HZ / 1000; - if (data->beacon_int < 1) - data->beacon_int = 1; - - if (!data->started || !data->radio_enabled) + if (!data->started || !data->radio_enabled || !data->beacon_int) del_timer(&data->beacon_timer); else mod_timer(&data->beacon_timer, jiffies + data->beacon_int); @@ -615,6 +610,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct hwsim_vif_priv *vp = (void *)vif->drv_priv; + struct mac80211_hwsim_data *data = hw->priv; hwsim_check_magic(vif); @@ -628,6 +624,14 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, vp->aid = info->aid; } + if (changed & BSS_CHANGED_BEACON_INT) { + printk(KERN_DEBUG " %s: BCNINT: %d\n", + wiphy_name(hw->wiphy), info->beacon_int); + data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; + if (WARN_ON(data->beacon_int)) + data->beacon_int = 1; + } + if (changed & BSS_CHANGED_ERP_CTS_PROT) { printk(KERN_DEBUG " %s: ERP_CTS_PROT: %d\n", wiphy_name(hw->wiphy), info->use_cts_prot); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 81d706d85226..22c65e8cbb71 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -149,6 +149,7 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_ERP_SLOT: slot timing changed * @BSS_CHANGED_HT: 802.11n parameters changed * @BSS_CHANGED_BASIC_RATES: Basic rateset changed + * @BSS_CHANGED_BEACON_INT: Beacon interval changed */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -157,6 +158,7 @@ enum ieee80211_bss_change { BSS_CHANGED_ERP_SLOT = 1<<3, BSS_CHANGED_HT = 1<<4, BSS_CHANGED_BASIC_RATES = 1<<5, + BSS_CHANGED_BEACON_INT = 1<<6, }; /** @@ -529,7 +531,7 @@ enum ieee80211_conf_flags { * enum ieee80211_conf_changed - denotes which configuration changed * * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed - * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed + * @_IEEE80211_CONF_CHANGE_BEACON_INTERVAL: DEPRECATED * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed @@ -539,7 +541,7 @@ enum ieee80211_conf_flags { */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), - IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), + _IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), IEEE80211_CONF_CHANGE_PS = BIT(4), @@ -548,6 +550,14 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), }; +static inline __deprecated enum ieee80211_conf_changed +__IEEE80211_CONF_CHANGE_BEACON_INTERVAL(void) +{ + return _IEEE80211_CONF_CHANGE_BEACON_INTERVAL; +} +#define IEEE80211_CONF_CHANGE_BEACON_INTERVAL \ + __IEEE80211_CONF_CHANGE_BEACON_INTERVAL() + /** * struct ieee80211_conf - configuration of the device * diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5e1c230744b5..a898ccd3f2c9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -451,18 +451,11 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, * This is a kludge. beacon interval should really be part * of the beacon information. */ - if (params->interval && (sdata->local->hw.conf.beacon_int != - params->interval)) { - sdata->local->hw.conf.beacon_int = params->interval; - err = ieee80211_hw_config(sdata->local, - IEEE80211_CONF_CHANGE_BEACON_INTERVAL); - if (err < 0) - return err; - /* - * We updated some parameter so if below bails out - * it's not an error. - */ - err = 0; + if (params->interval && + (sdata->vif.bss_conf.beacon_int != params->interval)) { + sdata->vif.bss_conf.beacon_int = params->interval; + ieee80211_bss_info_change_notify(sdata, + BSS_CHANGED_BEACON_INT); } /* Need to have a beacon head if we don't have one yet */ diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 25ff583612ef..f4879dad3cd7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -73,6 +73,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt; u8 *pos; struct ieee80211_supported_band *sband; + u32 bss_change; if (local->ops->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ @@ -92,8 +93,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, memcpy(ifibss->bssid, bssid, ETH_ALEN); - local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; - sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); @@ -101,6 +100,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, local->oper_channel = chan; local->oper_channel_type = NL80211_CHAN_NO_HT; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + + sdata->vif.bss_conf.beacon_int = beacon_int; + bss_change = BSS_CHANGED_BEACON_INT; + bss_change |= ieee80211_reset_erp_info(sdata); + ieee80211_bss_info_change_notify(sdata, bss_change); + sband = local->hw.wiphy->bands[chan->band]; /* Build IBSS probe response */ @@ -111,7 +116,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, memset(mgmt->da, 0xff, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); - mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int); + mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); mgmt->u.beacon.timestamp = cpu_to_le64(tsf); mgmt->u.beacon.capab_info = cpu_to_le16(capability); @@ -181,8 +186,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss) { + u16 beacon_int = bss->cbss.beacon_interval; + + if (beacon_int < 10) + beacon_int = 10; + __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, - bss->cbss.beacon_interval, + beacon_int, bss->cbss.channel, bss->supp_rates_len, bss->supp_rates, bss->cbss.capability, @@ -464,9 +474,6 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) sband = local->hw.wiphy->bands[ifibss->channel->band]; - if (local->hw.conf.beacon_int == 0) - local->hw.conf.beacon_int = 100; - capability = WLAN_CAPABILITY_IBSS; if (sdata->default_key) @@ -480,7 +487,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) *pos++ = (u8) (rate / 5); } - __ieee80211_sta_join_ibss(sdata, bssid, local->hw.conf.beacon_int, + __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, ifibss->channel, sband->n_bitrates, supp_rates, capability, 0); } @@ -823,6 +830,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, } else sdata->u.ibss.fixed_bssid = false; + sdata->vif.bss_conf.beacon_int = params->beacon_interval; + sdata->u.ibss.channel = params->channel; sdata->u.ibss.fixed_channel = params->channel_fixed; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index e00d124e4ef7..b254879d8631 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -294,9 +294,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; - if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) - return; - if (!changed) return; @@ -305,6 +302,17 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, &sdata->vif, &sdata->vif.bss_conf, changed); + + /* + * DEPRECATED + * + * ~changed is just there to not do this at resume time + */ + if (changed & BSS_CHANGED_BEACON_INT && ~changed) { + local->hw.conf.beacon_int = sdata->vif.bss_conf.beacon_int; + ieee80211_hw_config(local, + _IEEE80211_CONF_CHANGE_BEACON_INTERVAL); + } } u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) @@ -971,9 +979,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) debugfs_hw_add(local); - if (local->hw.conf.beacon_int < 10) - local->hw.conf.beacon_int = 100; - if (local->hw.max_listen_interval == 0) local->hw.max_listen_interval = 1; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a2f5e6223059..bfd571e6f221 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -842,6 +842,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.timestamp = bss->cbss.tsf; sdata->vif.bss_conf.dtim_period = bss->dtim_period; + bss_info_changed |= BSS_CHANGED_BEACON_INT; bss_info_changed |= ieee80211_handle_bss_capability(sdata, bss->cbss.capability, bss->has_erp_value, bss->erp_value); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 654a8e963ccb..7116220d06be 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -543,9 +543,8 @@ void sta_info_unlink(struct sta_info **sta) spin_unlock_irqrestore(&local->sta_lock, flags); } -static inline int sta_info_buffer_expired(struct ieee80211_local *local, - struct sta_info *sta, - struct sk_buff *skb) +static int sta_info_buffer_expired(struct sta_info *sta, + struct sk_buff *skb) { struct ieee80211_tx_info *info; int timeout; @@ -556,8 +555,9 @@ static inline int sta_info_buffer_expired(struct ieee80211_local *local, info = IEEE80211_SKB_CB(skb); /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ - timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 / - 15625) * HZ; + timeout = (sta->listen_interval * + sta->sdata->vif.bss_conf.beacon_int * + 32 / 15625) * HZ; if (timeout < STA_TX_BUFFER_EXPIRE) timeout = STA_TX_BUFFER_EXPIRE; return time_after(jiffies, info->control.jiffies + timeout); @@ -577,7 +577,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, for (;;) { spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); skb = skb_peek(&sta->ps_tx_buf); - if (sta_info_buffer_expired(local, sta, skb)) + if (sta_info_buffer_expired(sta, skb)) skb = __skb_dequeue(&sta->ps_tx_buf); else skb = NULL; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1865622003c9..29df65045fc9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2132,7 +2132,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.beacon.beacon_int = - cpu_to_le16(local->hw.conf.beacon_int); + cpu_to_le16(sdata->vif.bss_conf.beacon_int); mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ pos = skb_put(skb, 2); -- cgit v1.2.3 From 2d0ddec5b2b859f06116f631fc0ffe94fbceb556 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 16:13:26 +0200 Subject: mac80211: unify config_interface and bss_info_changed The config_interface method is a little strange, it contains the BSSID and beacon updates, while bss_info_changed contains most other BSS information for each interface. This patch removes config_interface and rolls all the information it previously passed to drivers into bss_info_changed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 14 ++- drivers/net/wireless/at76c50x-usb.c | 15 ++- drivers/net/wireless/ath/ar9170/main.c | 39 ++---- drivers/net/wireless/ath/ath5k/base.c | 71 +++++------ drivers/net/wireless/ath/ath9k/main.c | 182 +++++++++++++--------------- drivers/net/wireless/b43/main.c | 64 ++++------ drivers/net/wireless/b43legacy/main.c | 63 ++++------ drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.c | 162 +++++++++---------------- drivers/net/wireless/iwlwifi/iwl-core.h | 3 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - drivers/net/wireless/libertas_tf/main.c | 56 ++++----- drivers/net/wireless/mac80211_hwsim.c | 25 ++-- drivers/net/wireless/mwl8k.c | 18 +-- drivers/net/wireless/p54/p54common.c | 63 ++++------ drivers/net/wireless/rt2x00/rt2400pci.c | 1 - drivers/net/wireless/rt2x00/rt2500pci.c | 1 - drivers/net/wireless/rt2x00/rt2500usb.c | 1 - drivers/net/wireless/rt2x00/rt2x00.h | 3 - drivers/net/wireless/rt2x00/rt2x00mac.c | 88 ++++++-------- drivers/net/wireless/rt2x00/rt61pci.c | 1 - drivers/net/wireless/rt2x00/rt73usb.c | 1 - drivers/net/wireless/rtl818x/rtl8180_dev.c | 33 +++-- drivers/net/wireless/rtl818x/rtl8187_dev.c | 48 ++++---- drivers/net/wireless/zd1211rw/zd_mac.c | 80 +++++------- include/net/mac80211.h | 51 ++------ net/mac80211/cfg.c | 8 +- net/mac80211/ibss.c | 18 ++- net/mac80211/ieee80211_i.h | 1 - net/mac80211/main.c | 131 +++++++++----------- net/mac80211/mesh.c | 6 +- net/mac80211/mlme.c | 8 +- net/mac80211/scan.c | 8 +- net/mac80211/util.c | 17 +-- 34 files changed, 504 insertions(+), 778 deletions(-) diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index f71821795018..2b9e379994a1 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1311,18 +1311,20 @@ static int adm8211_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int adm8211_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) +static void adm8211_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changes) { struct adm8211_priv *priv = dev->priv; + if (!(changes & BSS_CHANGED_BSSID)) + return; + if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) { adm8211_set_bssid(dev, conf->bssid); memcpy(priv->bssid, conf->bssid, ETH_ALEN); } - - return 0; } static void adm8211_configure_filter(struct ieee80211_hw *dev, @@ -1753,7 +1755,7 @@ static const struct ieee80211_ops adm8211_ops = { .add_interface = adm8211_add_interface, .remove_interface = adm8211_remove_interface, .config = adm8211_config, - .config_interface = adm8211_config_interface, + .bss_info_changed = adm8211_bss_info_changed, .configure_filter = adm8211_configure_filter, .get_stats = adm8211_get_stats, .get_tx_stats = adm8211_get_tx_stats, diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 55f947ac56d1..cea7f1466c54 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1965,13 +1965,18 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed) return 0; } -static int at76_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) +static void at76_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed) { struct at76_priv *priv = hw->priv; at76_dbg(DBG_MAC80211, "%s():", __func__); + + if (!(changed & BSS_CHANGED_BSSID)) + return; + at76_dbg_dump(DBG_MAC80211, conf->bssid, ETH_ALEN, "bssid:"); mutex_lock(&priv->mtx); @@ -1983,8 +1988,6 @@ static int at76_config_interface(struct ieee80211_hw *hw, at76_join(priv); mutex_unlock(&priv->mtx); - - return 0; } /* must be atomic */ @@ -2076,7 +2079,7 @@ static const struct ieee80211_ops at76_ops = { .add_interface = at76_add_interface, .remove_interface = at76_remove_interface, .config = at76_config, - .config_interface = at76_config_interface, + .bss_info_changed = at76_bss_info_changed, .configure_filter = at76_configure_filter, .start = at76_mac80211_start, .stop = at76_mac80211_stop, diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 49c729bc7147..3bd3a61225ce 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1360,33 +1360,6 @@ out: return err; } -static int ar9170_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (conf->changed & IEEE80211_IFCC_BSSID) { - memcpy(ar->bssid, conf->bssid, ETH_ALEN); - err = ar9170_set_operating_mode(ar); - } - - if (conf->changed & IEEE80211_IFCC_BEACON) { - err = ar9170_update_beacon(ar); - - if (err) - goto out; - err = ar9170_set_beacon_timers(ar); - } - -out: - mutex_unlock(&ar->mutex); - return err; -} - static void ar9170_set_filters(struct work_struct *work) { struct ar9170 *ar = container_of(work, struct ar9170, @@ -1488,6 +1461,17 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&ar->mutex); + if (changed & BSS_CHANGED_BSSID) { + memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN); + err = ar9170_set_operating_mode(ar); + } + + if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) { + err = ar9170_update_beacon(ar); + if (!err) + ar9170_set_beacon_timers(ar); + } + ar9170_regwrite_begin(ar); if (changed & BSS_CHANGED_ASSOC) { @@ -1796,7 +1780,6 @@ static const struct ieee80211_ops ar9170_ops = { .add_interface = ar9170_op_add_interface, .remove_interface = ar9170_op_remove_interface, .config = ar9170_op_config, - .config_interface = ar9170_op_config_interface, .configure_filter = ar9170_op_configure_filter, .conf_tx = ar9170_conf_tx, .bss_info_changed = ar9170_op_bss_info_changed, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index e4b1d9efa42e..410fc4cfc4c6 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -227,9 +227,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, static void ath5k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); -static int ath5k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); static void ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, @@ -259,7 +256,6 @@ static const struct ieee80211_ops ath5k_hw_ops = { .add_interface = ath5k_add_interface, .remove_interface = ath5k_remove_interface, .config = ath5k_config, - .config_interface = ath5k_config_interface, .configure_filter = ath5k_configure_filter, .set_key = ath5k_set_key, .get_stats = ath5k_get_stats, @@ -2764,44 +2760,6 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) return ret; } -static int -ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - int ret = 0; - - mutex_lock(&sc->lock); - if (sc->vif != vif) { - ret = -EIO; - goto unlock; - } - if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { - /* Cache for later use during resets */ - memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); - /* XXX: assoc id is set to 0 for now, mac80211 doesn't have - * a clean way of letting us retrieve this yet. */ - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - mmiowb(); - } - if (conf->changed & IEEE80211_IFCC_BEACON && - (vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_AP)) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) { - ret = -ENOMEM; - goto unlock; - } - ath5k_beacon_update(sc, beacon); - } - -unlock: - mutex_unlock(&sc->lock); - return ret; -} - #define SUPPORTED_FIF_FLAGS \ FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ @@ -3082,15 +3040,40 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + + mutex_lock(&sc->lock); + if (WARN_ON(sc->vif != vif)) + goto unlock; + + if (changes & BSS_CHANGED_BSSID) { + /* Cache for later use during resets */ + memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN); + /* XXX: assoc id is set to 0 for now, mac80211 doesn't have + * a clean way of letting us retrieve this yet. */ + ath5k_hw_set_associd(ah, ah->ah_bssid, 0); + mmiowb(); + } if (changes & BSS_CHANGED_BEACON_INT) sc->bintval = bss_conf->beacon_int; if (changes & BSS_CHANGED_ASSOC) { - mutex_lock(&sc->lock); sc->assoc = bss_conf->assoc; if (sc->opmode == NL80211_IFTYPE_STATION) set_beacon_filter(hw, sc->assoc); - mutex_unlock(&sc->lock); } + + if (changes & BSS_CHANGED_BEACON && + (vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_AP)) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) + ath5k_beacon_update(sc, beacon); + } + + unlock: + mutex_unlock(&sc->lock); } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 28cc9cd52f32..d3dc8e2c77b2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2363,104 +2363,6 @@ skip_chan_change: return 0; } -static int ath9k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; - struct ath_vif *avp = (void *)vif->drv_priv; - u32 rfilt = 0; - int error, i; - - mutex_lock(&sc->mutex); - - /* TODO: Need to decide which hw opmode to use for multi-interface - * cases */ - if (vif->type == NL80211_IFTYPE_AP && - ah->opmode != NL80211_IFTYPE_AP) { - ah->opmode = NL80211_IFTYPE_STATION; - ath9k_hw_setopmode(ah); - memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - /* Request full reset to get hw opmode changed properly */ - sc->sc_flags |= SC_OP_FULL_RESET; - } - - if ((conf->changed & IEEE80211_IFCC_BSSID) && - !is_zero_ether_addr(conf->bssid)) { - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - /* Set BSSID */ - memcpy(sc->curbssid, conf->bssid, ETH_ALEN); - memcpy(avp->bssid, conf->bssid, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - - /* Set aggregation protection mode parameters */ - sc->config.ath_aggr_prot = 0; - - DPRINTF(sc, ATH_DBG_CONFIG, - "RX filter 0x%x bssid %pM aid 0x%x\n", - rfilt, sc->curbssid, sc->curaid); - - /* need to reconfigure the beacon */ - sc->sc_flags &= ~SC_OP_BEACONS ; - - break; - default: - break; - } - } - - if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((conf->changed & IEEE80211_IFCC_BEACON) || - (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && - conf->enable_beacon)) { - /* - * Allocate and setup the beacon frame. - * - * Stop any previous beacon DMA. This may be - * necessary, for example, when an ibss merge - * causes reconfiguration; we may be called - * with beacon transmission active. - */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - error = ath_beacon_alloc(aphy, vif); - if (error != 0) { - mutex_unlock(&sc->mutex); - return error; - } - - ath_beacon_config(sc, vif); - } - } - - /* Check for WLAN_CAPABILITY_PRIVACY ? */ - if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { - for (i = 0; i < IEEE80211_WEP_NKID; i++) - if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) - ath9k_hw_keysetmac(sc->sc_ah, - (u16)i, - sc->curbssid); - } - - /* Only legacy IBSS for now */ - if (vif->type == NL80211_IFTYPE_ADHOC) - ath_update_chainmask(sc, 0); - - mutex_unlock(&sc->mutex); - - return 0; -} - #define SUPPORTED_FILTERS \ (FIF_PROMISC_IN_BSS | \ FIF_ALLMULTI | \ @@ -2597,9 +2499,92 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + struct ath_vif *avp = (void *)vif->drv_priv; + u32 rfilt = 0; + int error, i; mutex_lock(&sc->mutex); + /* + * TODO: Need to decide which hw opmode to use for + * multi-interface cases + * XXX: This belongs into add_interface! + */ + if (vif->type == NL80211_IFTYPE_AP && + ah->opmode != NL80211_IFTYPE_AP) { + ah->opmode = NL80211_IFTYPE_STATION; + ath9k_hw_setopmode(ah); + memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); + sc->curaid = 0; + ath9k_hw_write_associd(sc); + /* Request full reset to get hw opmode changed properly */ + sc->sc_flags |= SC_OP_FULL_RESET; + } + + if ((changed & BSS_CHANGED_BSSID) && + !is_zero_ether_addr(bss_conf->bssid)) { + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + /* Set BSSID */ + memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN); + memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); + sc->curaid = 0; + ath9k_hw_write_associd(sc); + + /* Set aggregation protection mode parameters */ + sc->config.ath_aggr_prot = 0; + + DPRINTF(sc, ATH_DBG_CONFIG, + "RX filter 0x%x bssid %pM aid 0x%x\n", + rfilt, sc->curbssid, sc->curaid); + + /* need to reconfigure the beacon */ + sc->sc_flags &= ~SC_OP_BEACONS ; + + break; + default: + break; + } + } + + if ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { + if ((changed & BSS_CHANGED_BEACON) || + (changed & BSS_CHANGED_BEACON_ENABLED && + bss_conf->enable_beacon)) { + /* + * Allocate and setup the beacon frame. + * + * Stop any previous beacon DMA. This may be + * necessary, for example, when an ibss merge + * causes reconfiguration; we may be called + * with beacon transmission active. + */ + ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); + + error = ath_beacon_alloc(aphy, vif); + if (!error) + ath_beacon_config(sc, vif); + } + } + + /* Check for WLAN_CAPABILITY_PRIVACY ? */ + if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { + for (i = 0; i < IEEE80211_WEP_NKID; i++) + if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) + ath9k_hw_keysetmac(sc->sc_ah, + (u16)i, + sc->curbssid); + } + + /* Only legacy IBSS for now */ + if (vif->type == NL80211_IFTYPE_ADHOC) + ath_update_chainmask(sc, 0); + if (changed & BSS_CHANGED_ERP_PREAMBLE) { DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", bss_conf->use_short_preamble); @@ -2757,7 +2742,6 @@ struct ieee80211_ops ath9k_ops = { .add_interface = ath9k_add_interface, .remove_interface = ath9k_remove_interface, .config = ath9k_config, - .config_interface = ath9k_config_interface, .configure_filter = ath9k_configure_filter, .sta_notify = ath9k_sta_notify, .conf_tx = ath9k_conf_tx, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3c693e6ec904..2615aaf7df6a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3543,12 +3543,38 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; + unsigned long flags; mutex_lock(&wl->mutex); dev = wl->current_dev; if (!dev || b43_status(dev) < B43_STAT_STARTED) goto out_unlock_mutex; + + B43_WARN_ON(wl->vif != vif); + + if (changed & BSS_CHANGED_BSSID) { + spin_lock_irqsave(&wl->irq_lock, flags); + if (conf->bssid) + memcpy(wl->bssid, conf->bssid, ETH_ALEN); + else + memset(wl->bssid, 0, ETH_ALEN); + + if (b43_status(dev) >= B43_STAT_INITIALIZED) { + if (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { + B43_WARN_ON(vif->type != wl->if_type); + if (changed & BSS_CHANGED_BEACON) + b43_update_templates(wl); + } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { + if (changed & BSS_CHANGED_BEACON) + b43_update_templates(wl); + } + b43_write_mac_bssid_templates(dev); + } + spin_unlock_irqrestore(&wl->irq_lock, flags); + } + b43_mac_suspend(dev); /* Update templates for AP/mesh mode. */ @@ -3571,8 +3597,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, b43_mac_enable(dev); out_unlock_mutex: mutex_unlock(&wl->mutex); - - return; } static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, @@ -3730,41 +3754,6 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); } -static int b43_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev = wl->current_dev; - unsigned long flags; - - if (!dev) - return -ENODEV; - mutex_lock(&wl->mutex); - spin_lock_irqsave(&wl->irq_lock, flags); - B43_WARN_ON(wl->vif != vif); - if (conf->bssid) - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - else - memset(wl->bssid, 0, ETH_ALEN); - if (b43_status(dev) >= B43_STAT_INITIALIZED) { - if (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { - B43_WARN_ON(vif->type != wl->if_type); - if (conf->changed & IEEE80211_IFCC_BEACON) - b43_update_templates(wl); - } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { - if (conf->changed & IEEE80211_IFCC_BEACON) - b43_update_templates(wl); - } - b43_write_mac_bssid_templates(dev); - } - spin_unlock_irqrestore(&wl->irq_lock, flags); - mutex_unlock(&wl->mutex); - - return 0; -} - /* Locking: wl->mutex */ static void b43_wireless_core_stop(struct b43_wldev *dev) { @@ -4434,7 +4423,6 @@ static const struct ieee80211_ops b43_hw_ops = { .remove_interface = b43_op_remove_interface, .config = b43_op_config, .bss_info_changed = b43_op_bss_info_changed, - .config_interface = b43_op_config_interface, .configure_filter = b43_op_configure_filter, .set_key = b43_op_set_key, .get_stats = b43_op_get_stats, diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 276f314688f7..07c7898c87ac 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2804,6 +2804,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, u32 savedirqs; mutex_lock(&wl->mutex); + B43legacy_WARN_ON(wl->vif != vif); dev = wl->current_dev; phy = &dev->phy; @@ -2817,8 +2818,29 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, goto out_unlock_mutex; } savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43legacy_synchronize_irq(dev); + + if (changed & BSS_CHANGED_BSSID) { + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43legacy_synchronize_irq(dev); + + if (conf->bssid) + memcpy(wl->bssid, conf->bssid, ETH_ALEN); + else + memset(wl->bssid, 0, ETH_ALEN); + + if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { + if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) { + B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP); + if (changed & BSS_CHANGED_BEACON) + b43legacy_update_templates(wl); + } else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) { + if (changed & BSS_CHANGED_BEACON) + b43legacy_update_templates(wl); + } + b43legacy_write_mac_bssid_templates(dev); + } + spin_unlock_irqrestore(&wl->irq_lock, flags); + } b43legacy_mac_suspend(dev); @@ -2846,8 +2868,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); out_unlock_mutex: mutex_unlock(&wl->mutex); - - return; } static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, @@ -2889,40 +2909,6 @@ static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, spin_unlock_irqrestore(&wl->irq_lock, flags); } -static int b43legacy_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - unsigned long flags; - - if (!dev) - return -ENODEV; - mutex_lock(&wl->mutex); - spin_lock_irqsave(&wl->irq_lock, flags); - B43legacy_WARN_ON(wl->vif != vif); - if (conf->bssid) - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - else - memset(wl->bssid, 0, ETH_ALEN); - if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { - if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) { - B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP); - if (conf->changed & IEEE80211_IFCC_BEACON) - b43legacy_update_templates(wl); - } else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) { - if (conf->changed & IEEE80211_IFCC_BEACON) - b43legacy_update_templates(wl); - } - b43legacy_write_mac_bssid_templates(dev); - } - spin_unlock_irqrestore(&wl->irq_lock, flags); - mutex_unlock(&wl->mutex); - - return 0; -} - /* Locking: wl->mutex */ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) { @@ -3563,7 +3549,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .remove_interface = b43legacy_op_remove_interface, .config = b43legacy_op_dev_config, .bss_info_changed = b43legacy_op_bss_info_changed, - .config_interface = b43legacy_op_config_interface, .configure_filter = b43legacy_op_configure_filter, .get_stats = b43legacy_op_get_stats, .get_tx_stats = b43legacy_op_get_tx_stats, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4920dcf7d7b0..dd8b15ed8296 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2623,7 +2623,6 @@ static struct ieee80211_ops iwl_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .config_interface = iwl_mac_config_interface, .configure_filter = iwl_configure_filter, .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index cd8a5ed97c4f..0f21fc136ca7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2238,15 +2238,69 @@ static void iwl_ht_conf(struct iwl_priv *priv, #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) { struct iwl_priv *priv = hw->priv; int ret; IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); + if (!iwl_is_alive(priv)) + return; + + mutex_lock(&priv->mutex); + + if (changes & BSS_CHANGED_BEACON && + priv->iw_mode == NL80211_IFTYPE_AP) { + dev_kfree_skb(priv->ibss_beacon); + priv->ibss_beacon = ieee80211_beacon_get(hw, vif); + } + + if ((changes & BSS_CHANGED_BSSID) && !iwl_is_rfkill(priv)) { + /* If there is currently a HW scan going on in the background + * then we need to cancel it else the RXON below will fail. */ + if (iwl_scan_cancel_timeout(priv, 100)) { + IWL_WARN(priv, "Aborted scan still in progress " + "after 100ms\n"); + IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); + mutex_unlock(&priv->mutex); + return; + } + memcpy(priv->staging_rxon.bssid_addr, + bss_conf->bssid, ETH_ALEN); + + /* TODO: Audit driver for usage of these members and see + * if mac80211 deprecates them (priv->bssid looks like it + * shouldn't be there, but I haven't scanned the IBSS code + * to verify) - jpk */ + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + + if (priv->iw_mode == NL80211_IFTYPE_AP) + iwlcore_config_ap(priv); + else { + int rc = iwlcore_commit_rxon(priv); + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) + iwl_rxon_add_station( + priv, priv->active_rxon.bssid_addr, 1); + } + } else if (!iwl_is_rfkill(priv)) { + iwl_scan_cancel_timeout(priv, 100); + priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + iwlcore_commit_rxon(priv); + } + + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && + changes & BSS_CHANGED_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) + iwl_mac_beacon_update(hw, beacon); + } + + mutex_unlock(&priv->mutex); + if (changes & BSS_CHANGED_ERP_PREAMBLE) { IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); @@ -2305,7 +2359,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, &priv->staging_rxon, sizeof(struct iwl_rxon_cmd)); } - + IWL_DEBUG_MAC80211(priv, "leave\n"); } EXPORT_SYMBOL(iwl_bss_info_changed); @@ -2589,106 +2643,6 @@ out: } EXPORT_SYMBOL(iwl_mac_config); -int iwl_mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - int rc; - - if (conf == NULL) - return -EIO; - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n"); - return 0; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - if (!beacon) - return -ENOMEM; - mutex_lock(&priv->mutex); - rc = iwl_mac_beacon_update(hw, beacon); - mutex_unlock(&priv->mutex); - if (rc) - return rc; - } - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - - if (conf->bssid) - IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid); - -/* - * very dubious code was here; the probe filtering flag is never set: - * - if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && - !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { - */ - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - if (!conf->bssid) { - conf->bssid = priv->mac_addr; - memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); - IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n", - conf->bssid); - } - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); - } - - if (iwl_is_rfkill(priv)) - goto done; - - if (conf->bssid && !is_zero_ether_addr(conf->bssid) && - !is_multicast_ether_addr(conf->bssid)) { - /* If there is currently a HW scan going on in the background - * then we need to cancel it else the RXON below will fail. */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress " - "after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - mutex_unlock(&priv->mutex); - return -EAGAIN; - } - memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN); - - /* TODO: Audit driver for usage of these members and see - * if mac80211 deprecates them (priv->bssid looks like it - * shouldn't be there, but I haven't scanned the IBSS code - * to verify) - jpk */ - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwlcore_config_ap(priv); - else { - rc = iwlcore_commit_rxon(priv); - if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) - iwl_rxon_add_station( - priv, priv->active_rxon.bssid_addr, 1); - } - - } else { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - done: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - - return 0; -} -EXPORT_SYMBOL(iwl_mac_config_interface); - int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d4c60afa2891..bd7f9d9616bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -281,9 +281,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); void iwl_config_ap(struct iwl_priv *priv); -int iwl_mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats); void iwl_mac_reset_tsf(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f9d9b65ef300..5cd4321d7cf5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4106,7 +4106,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .config_interface = iwl_mac_config_interface, .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, .get_tx_stats = iwl_mac_get_tx_stats, diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 68e47fb47a1e..10a99e26d392 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -366,36 +366,6 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) return 0; } -static int lbtf_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct lbtf_private *priv = hw->priv; - struct sk_buff *beacon; - - switch (priv->vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - beacon = ieee80211_beacon_get(hw, vif); - if (beacon) { - lbtf_beacon_set(priv, beacon); - kfree_skb(beacon); - lbtf_beacon_ctrl(priv, 1, vif->bss_conf.beacon_int); - } - break; - default: - break; - } - - if (conf->bssid) { - u8 null_bssid[ETH_ALEN] = {0}; - bool activate = compare_ether_addr(conf->bssid, null_bssid); - lbtf_set_bssid(priv, activate, conf->bssid); - } - - return 0; -} - #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) static void lbtf_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, @@ -451,6 +421,29 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct lbtf_private *priv = hw->priv; + struct sk_buff *beacon; + + if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) { + switch (priv->vif->type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + beacon = ieee80211_beacon_get(hw, vif); + if (beacon) { + lbtf_beacon_set(priv, beacon); + kfree_skb(beacon); + lbtf_beacon_ctrl(priv, 1, + bss_conf->beacon_int); + } + break; + default: + break; + } + } + + if (changes & BSS_CHANGED_BSSID) { + bool activate = !is_zero_ether_addr(bss_conf->bssid); + lbtf_set_bssid(priv, activate, bss_conf->bssid); + } if (changes & BSS_CHANGED_ERP_PREAMBLE) { if (bss_conf->use_short_preamble) @@ -459,8 +452,6 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, priv->preamble = CMD_TYPE_LONG_PREAMBLE; lbtf_set_radio_control(priv); } - - return; } static const struct ieee80211_ops lbtf_ops = { @@ -470,7 +461,6 @@ static const struct ieee80211_ops lbtf_ops = { .add_interface = lbtf_op_add_interface, .remove_interface = lbtf_op_remove_interface, .config = lbtf_op_config, - .config_interface = lbtf_op_config_interface, .configure_filter = lbtf_op_configure_filter, .bss_info_changed = lbtf_op_bss_info_changed, }; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 24c95a619e4c..e67b424f925e 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -587,23 +587,6 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, *total_flags = data->rx_filter; } -static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - - hwsim_check_magic(vif); - if (conf->changed & IEEE80211_IFCC_BSSID) { - DECLARE_MAC_BUF(mac); - printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", - wiphy_name(hw->wiphy), __func__, - conf->bssid); - memcpy(vp->bssid, conf->bssid, ETH_ALEN); - } - return 0; -} - static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -617,6 +600,13 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, printk(KERN_DEBUG "%s:%s(changed=0x%x)\n", wiphy_name(hw->wiphy), __func__, changed); + if (changed & BSS_CHANGED_BSSID) { + printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", + wiphy_name(hw->wiphy), __func__, + info->bssid); + memcpy(vp->bssid, info->bssid, ETH_ALEN); + } + if (changed & BSS_CHANGED_ASSOC) { printk(KERN_DEBUG " %s: ASSOC: assoc=%d aid=%d\n", wiphy_name(hw->wiphy), info->assoc, info->aid); @@ -708,7 +698,6 @@ static const struct ieee80211_ops mac80211_hwsim_ops = .remove_interface = mac80211_hwsim_remove_interface, .config = mac80211_hwsim_config, .configure_filter = mac80211_hwsim_configure_filter, - .config_interface = mac80211_hwsim_config_interface, .bss_info_changed = mac80211_hwsim_bss_info_changed, .sta_notify = mac80211_hwsim_sta_notify, .set_tim = mac80211_hwsim_set_tim, diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a9a970469c2a..46b288dc8f4d 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3089,19 +3089,6 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) return rc ? -EINVAL : 0; } -static int mwl8k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - u32 changed = conf->changed; - - if (changed & IEEE80211_IFCC_BSSID) - memcpy(mv_vif->bssid, conf->bssid, IEEE80211_ADDR_LEN); - - return 0; -} - struct mwl8k_bss_info_changed_worker { struct mwl8k_work_struct header; struct ieee80211_vif *vif; @@ -3183,8 +3170,12 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, { struct mwl8k_bss_info_changed_worker *worker; struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); int rc; + if (changed & BSS_CHANGED_BSSID) + memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN); + if ((changed & BSS_CHANGED_ASSOC) == 0) return; @@ -3442,7 +3433,6 @@ static const struct ieee80211_ops mwl8k_ops = { .add_interface = mwl8k_add_interface, .remove_interface = mwl8k_remove_interface, .config = mwl8k_config, - .config_interface = mwl8k_config_interface, .bss_info_changed = mwl8k_bss_info_changed, .configure_filter = mwl8k_configure_filter, .set_rts_threshold = mwl8k_set_rts_threshold, diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 71394968d450..b85785291803 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -2204,41 +2204,6 @@ out: return ret; } -static int p54_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct p54_common *priv = dev->priv; - int ret = 0; - - mutex_lock(&priv->conf_mutex); - if (conf->changed & IEEE80211_IFCC_BSSID) { - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - ret = p54_setup_mac(dev); - if (ret) - goto out; - } - - if (conf->changed & IEEE80211_IFCC_BEACON) { - ret = p54_scan(dev, P54_SCAN_EXIT, 0); - if (ret) - goto out; - ret = p54_setup_mac(dev); - if (ret) - goto out; - ret = p54_beacon_update(dev, vif); - if (ret) - goto out; - ret = p54_set_edcf(dev); - if (ret) - goto out; - } - -out: - mutex_unlock(&priv->conf_mutex); - return ret; -} - static void p54_configure_filter(struct ieee80211_hw *dev, unsigned int changed_flags, unsigned int *total_flags, @@ -2342,8 +2307,32 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, u32 changed) { struct p54_common *priv = dev->priv; + int ret; + + mutex_lock(&priv->conf_mutex); + if (changed & BSS_CHANGED_BSSID) { + memcpy(priv->bssid, info->bssid, ETH_ALEN); + ret = p54_setup_mac(dev); + if (ret) + goto out; + } + + if (changed & BSS_CHANGED_BEACON) { + ret = p54_scan(dev, P54_SCAN_EXIT, 0); + if (ret) + goto out; + ret = p54_setup_mac(dev); + if (ret) + goto out; + ret = p54_beacon_update(dev, vif); + if (ret) + goto out; + } + /* XXX: this mimics having two callbacks... clean up */ + out: + mutex_unlock(&priv->conf_mutex); - if (changed & BSS_CHANGED_ERP_SLOT) { + if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) { priv->use_short_slot = info->use_short_slot; p54_set_edcf(dev); } @@ -2364,7 +2353,6 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, p54_setup_mac(dev); } } - } static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, @@ -2619,7 +2607,6 @@ static const struct ieee80211_ops p54_ops = { .sta_notify = p54_sta_notify, .set_key = p54_set_key, .config = p54_config, - .config_interface = p54_config_interface, .bss_info_changed = p54_bss_info_changed, .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 411eb9cbb4e5..6f39ba662188 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1580,7 +1580,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index e1be67ca23d8..906960f67b6c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1879,7 +1879,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9e630e70fc97..08e88333b0ff 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1908,7 +1908,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index e03d69975ea4..0be395528261 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -943,9 +943,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c41a0b9e473d..c4c06b4e1f08 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -390,56 +390,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) } EXPORT_SYMBOL_GPL(rt2x00mac_config); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(vif); - int update_bssid = 0; - int status = 0; - - /* - * Mac80211 might be calling this function while we are trying - * to remove the device or perhaps suspending it. - */ - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return 0; - - spin_lock(&intf->lock); - - /* - * conf->bssid can be NULL if coming from the internal - * beacon update routine. - */ - if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { - update_bssid = 1; - memcpy(&intf->bssid, conf->bssid, ETH_ALEN); - } - - spin_unlock(&intf->lock); - - /* - * Call rt2x00_config_intf() outside of the spinlock context since - * the call will sleep for USB drivers. By using the ieee80211_if_conf - * values as arguments we make keep access to rt2x00_intf thread safe - * even without the lock. - */ - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, - update_bssid ? conf->bssid : NULL); - - /* - * Update the beacon. - */ - if (conf->changed & (IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED)) - status = rt2x00queue_update_beacon(rt2x00dev, vif, - conf->enable_beacon); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); - void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -623,6 +573,44 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); unsigned int delayed = 0; + int update_bssid = 0; + + /* + * Mac80211 might be calling this function while we are trying + * to remove the device or perhaps suspending it. + */ + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return; + + spin_lock(&intf->lock); + + /* + * conf->bssid can be NULL if coming from the internal + * beacon update routine. + */ + if (changes & BSS_CHANGED_BSSID) { + update_bssid = 1; + memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); + } + + spin_unlock(&intf->lock); + + /* + * Call rt2x00_config_intf() outside of the spinlock context since + * the call will sleep for USB drivers. By using the ieee80211_if_conf + * values as arguments we make keep access to rt2x00_intf thread safe + * even without the lock. + */ + if (changes & BSS_CHANGED_BSSID) + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, + update_bssid ? bss_conf->bssid : NULL); + + /* + * Update the beacon. + */ + if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) + rt2x00queue_update_beacon(rt2x00dev, vif, + bss_conf->enable_beacon); /* * When the association status has changed we must reset the link diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 4346cd1494bc..cb521ee7a8f0 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2735,7 +2735,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 853b2b279b64..6bd28a6bcef2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2259,7 +2259,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 387c133ec0f2..7e65d7c31802 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -702,30 +702,26 @@ static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int rtl8180_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); - - if (is_valid_ether_addr(conf->bssid)) - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); - - return 0; -} - static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { struct rtl8180_priv *priv = dev->priv; + int i; + + if (changed & BSS_CHANGED_BSSID) { + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->BSSID[i], + info->bssid[i]); + + if (is_valid_ether_addr(info->bssid)) + rtl818x_iowrite8(priv, &priv->map->MSR, + RTL818X_MSR_INFRA); + else + rtl818x_iowrite8(priv, &priv->map->MSR, + RTL818X_MSR_NO_LINK); + } if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) priv->rf->conf_erp(dev, info); @@ -770,7 +766,6 @@ static const struct ieee80211_ops rtl8180_ops = { .add_interface = rtl8180_add_interface, .remove_interface = rtl8180_remove_interface, .config = rtl8180_config, - .config_interface = rtl8180_config_interface, .bss_info_changed = rtl8180_bss_info_changed, .configure_filter = rtl8180_configure_filter, }; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index ac558da92aac..158827e50c55 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1090,32 +1090,6 @@ static int rtl8187_config(struct ieee80211_hw *dev, u32 changed) return 0; } -static int rtl8187_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - u8 reg; - - mutex_lock(&priv->conf_mutex); - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); - - if (is_valid_ether_addr(conf->bssid)) { - reg = RTL818X_MSR_INFRA; - if (priv->is_rtl8187b) - reg |= RTL818X_MSR_ENEDCA; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } else { - reg = RTL818X_MSR_NO_LINK; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } - - mutex_unlock(&priv->conf_mutex); - return 0; -} - /* * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for * example. Thus we have to use raw values for AC_*_PARAM register addresses. @@ -1193,6 +1167,27 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, u32 changed) { struct rtl8187_priv *priv = dev->priv; + int i; + u8 reg; + + if (changed & BSS_CHANGED_BSSID) { + mutex_lock(&priv->conf_mutex); + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->BSSID[i], + info->bssid[i]); + + if (is_valid_ether_addr(info->bssid)) { + reg = RTL818X_MSR_INFRA; + if (priv->is_rtl8187b) + reg |= RTL818X_MSR_ENEDCA; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } else { + reg = RTL818X_MSR_NO_LINK; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } + + mutex_unlock(&priv->conf_mutex); + } if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) rtl8187_conf_erp(priv, info->use_short_slot, @@ -1274,7 +1269,6 @@ static const struct ieee80211_ops rtl8187_ops = { .add_interface = rtl8187_add_interface, .remove_interface = rtl8187_remove_interface, .config = rtl8187_config, - .config_interface = rtl8187_config_interface, .bss_info_changed = rtl8187_bss_info_changed, .configure_filter = rtl8187_configure_filter, .conf_tx = rtl8187_conf_tx diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index c3a51266de20..6bdb1704083b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -755,52 +755,6 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed) return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); } -static int zd_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct zd_mac *mac = zd_hw_mac(hw); - int associated; - int r; - - if (mac->type == NL80211_IFTYPE_MESH_POINT || - mac->type == NL80211_IFTYPE_ADHOC) { - associated = true; - if (conf->changed & IEEE80211_IFCC_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - - if (!beacon) - return -ENOMEM; - r = zd_mac_config_beacon(hw, beacon); - kfree_skb(beacon); - - if (r < 0) - return r; - } - - if (conf->changed & IEEE80211_IFCC_BEACON_ENABLED) { - u32 interval; - - if (conf->enable_beacon) - interval = BCN_MODE_IBSS | hw->conf.beacon_int; - else - interval = 0; - - r = zd_set_beacon_interval(&mac->chip, interval); - if (r < 0) - return r; - } - } else - associated = is_valid_ether_addr(conf->bssid); - - spin_lock_irq(&mac->lock); - mac->associated = associated; - spin_unlock_irq(&mac->lock); - - /* TODO: do hardware bssid filtering */ - return 0; -} - static void zd_process_intr(struct work_struct *work) { u16 int_status; @@ -923,9 +877,42 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, { struct zd_mac *mac = zd_hw_mac(hw); unsigned long flags; + int associated; dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); + if (mac->type == NL80211_IFTYPE_MESH_POINT || + mac->type == NL80211_IFTYPE_ADHOC) { + associated = true; + if (changes & BSS_CHANGED_BEACON) { + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) { + zd_mac_config_beacon(hw, beacon); + kfree_skb(beacon); + } + } + + if (changes & BSS_CHANGED_BEACON_ENABLED) { + u32 interval; + + if (bss_conf->enable_beacon) + interval = BCN_MODE_IBSS | + bss_conf->beacon_int; + else + interval = 0; + + zd_set_beacon_interval(&mac->chip, interval); + } + } else + associated = is_valid_ether_addr(bss_conf->bssid); + + spin_lock_irq(&mac->lock); + mac->associated = associated; + spin_unlock_irq(&mac->lock); + + /* TODO: do hardware bssid filtering */ + if (changes & BSS_CHANGED_ERP_PREAMBLE) { spin_lock_irqsave(&mac->lock, flags); mac->short_preamble = bss_conf->use_short_preamble; @@ -952,7 +939,6 @@ static const struct ieee80211_ops zd_ops = { .add_interface = zd_op_add_interface, .remove_interface = zd_op_remove_interface, .config = zd_op_config, - .config_interface = zd_op_config_interface, .configure_filter = zd_op_configure_filter, .bss_info_changed = zd_op_bss_info_changed, .get_tsf = zd_op_get_tsf, diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 22c65e8cbb71..7806e22f4ace 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -150,6 +150,12 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_HT: 802.11n parameters changed * @BSS_CHANGED_BASIC_RATES: Basic rateset changed * @BSS_CHANGED_BEACON_INT: Beacon interval changed + * @BSS_CHANGED_BSSID: BSSID changed, for whatever + * reason (IBSS and managed mode) + * @BSS_CHANGED_BEACON: Beacon data changed, retrieve + * new beacon (beaconing modes) + * @BSS_CHANGED_BEACON_ENABLED: Beaconing should be + * enabled/disabled (beaconing modes) */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -159,6 +165,9 @@ enum ieee80211_bss_change { BSS_CHANGED_HT = 1<<4, BSS_CHANGED_BASIC_RATES = 1<<5, BSS_CHANGED_BEACON_INT = 1<<6, + BSS_CHANGED_BSSID = 1<<7, + BSS_CHANGED_BEACON = 1<<8, + BSS_CHANGED_BEACON_ENABLED = 1<<9, }; /** @@ -192,8 +201,11 @@ struct ieee80211_bss_ht_conf { * @basic_rates: bitmap of basic rates, each bit stands for an * index into the rate table configured by the driver in * the current band. + * @bssid: The BSSID for this BSS + * @enable_beacon: whether beaconing should be enabled or not */ struct ieee80211_bss_conf { + const u8 *bssid; /* association related data */ bool assoc; u16 aid; @@ -201,6 +213,7 @@ struct ieee80211_bss_conf { bool use_cts_prot; bool use_short_preamble; bool use_short_slot; + bool enable_beacon; u8 dtim_period; u16 beacon_int; u16 assoc_capability; @@ -659,37 +672,6 @@ struct ieee80211_if_init_conf { void *mac_addr; }; -/** - * enum ieee80211_if_conf_change - interface config change flags - * - * @IEEE80211_IFCC_BSSID: The BSSID changed. - * @IEEE80211_IFCC_BEACON: The beacon for this interface changed - * (currently AP and MESH only), use ieee80211_beacon_get(). - * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed. - */ -enum ieee80211_if_conf_change { - IEEE80211_IFCC_BSSID = BIT(0), - IEEE80211_IFCC_BEACON = BIT(1), - IEEE80211_IFCC_BEACON_ENABLED = BIT(2), -}; - -/** - * struct ieee80211_if_conf - configuration of an interface - * - * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. - * @bssid: BSSID of the network we are associated to/creating. - * @enable_beacon: Indicates whether beacons can be sent. - * This is valid only for AP/IBSS/MESH modes. - * - * This structure is passed to the config_interface() callback of - * &struct ieee80211_hw. - */ -struct ieee80211_if_conf { - u32 changed; - const u8 *bssid; - bool enable_beacon; -}; - /** * enum ieee80211_key_alg - key algorithm * @ALG_WEP: WEP40 or WEP104 @@ -1358,10 +1340,6 @@ enum ieee80211_ampdu_mlme_action { * This function should never fail but returns a negative error code * if it does. * - * @config_interface: Handler for configuration requests related to interfaces - * (e.g. BSSID changes.) - * Returns a negative error code which will be seen in userspace. - * * @bss_info_changed: Handler for configuration requests related to BSS * parameters that may vary during BSS's lifespan, and may affect low * level driver (e.g. assoc/disassoc status, erp parameters). @@ -1463,9 +1441,6 @@ struct ieee80211_ops { void (*remove_interface)(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int (*config)(struct ieee80211_hw *hw, u32 changed); - int (*config_interface)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); void (*bss_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a898ccd3f2c9..648bac1c850e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -521,8 +521,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_BEACON); + return 0; } static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -573,7 +574,8 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) synchronize_rcu(); kfree(old); - return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); + return 0; } /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f4879dad3cd7..c87caad383f0 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -95,17 +95,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); - local->oper_channel = chan; local->oper_channel_type = NL80211_CHAN_NO_HT; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - sdata->vif.bss_conf.beacon_int = beacon_int; - bss_change = BSS_CHANGED_BEACON_INT; - bss_change |= ieee80211_reset_erp_info(sdata); - ieee80211_bss_info_change_notify(sdata, bss_change); - sband = local->hw.wiphy->bands[chan->band]; /* Build IBSS probe response */ @@ -161,8 +154,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, rcu_assign_pointer(ifibss->presp, skb); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED); + sdata->vif.bss_conf.beacon_int = beacon_int; + bss_change = BSS_CHANGED_BEACON_INT; + bss_change |= ieee80211_reset_erp_info(sdata); + bss_change |= BSS_CHANGED_BSSID; + bss_change |= BSS_CHANGED_BEACON; + bss_change |= BSS_CHANGED_BEACON_ENABLED; + ieee80211_bss_info_change_notify(sdata, bss_change); rates = 0; for (i = 0; i < supp_rates_len; i++) { @@ -887,7 +885,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) kfree(sdata->u.ibss.ie); skb = sdata->u.ibss.presp; rcu_assign_pointer(sdata->u.ibss.presp, NULL); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); synchronize_rcu(); kfree_skb(skb); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e6fd4bcf1c3c..d8de1e159ee0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -906,7 +906,6 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); -int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b254879d8631..c817c9ef215a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -152,82 +152,6 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev) ieee80211_configure_filter(local); } -/* everything else */ - -int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_conf conf; - - if (WARN_ON(!netif_running(sdata->dev))) - return 0; - - memset(&conf, 0, sizeof(conf)); - - if (sdata->vif.type == NL80211_IFTYPE_STATION) - conf.bssid = sdata->u.mgd.bssid; - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - conf.bssid = sdata->u.ibss.bssid; - else if (sdata->vif.type == NL80211_IFTYPE_AP) - conf.bssid = sdata->dev->dev_addr; - else if (ieee80211_vif_is_mesh(&sdata->vif)) { - static const u8 zero[ETH_ALEN] = { 0 }; - conf.bssid = zero; - } else { - WARN_ON(1); - return -EINVAL; - } - - if (!local->ops->config_interface) - return 0; - - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - break; - default: - /* do not warn to simplify caller in scan.c */ - changed &= ~IEEE80211_IFCC_BEACON_ENABLED; - if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) - return -EINVAL; - changed &= ~IEEE80211_IFCC_BEACON; - break; - } - - if (changed & IEEE80211_IFCC_BEACON_ENABLED) { - if (local->sw_scanning) { - conf.enable_beacon = false; - } else { - /* - * Beacon should be enabled, but AP mode must - * check whether there is a beacon configured. - */ - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: - conf.enable_beacon = - !!rcu_dereference(sdata->u.ap.beacon); - break; - case NL80211_IFTYPE_ADHOC: - conf.enable_beacon = !!sdata->u.ibss.presp; - break; - case NL80211_IFTYPE_MESH_POINT: - conf.enable_beacon = true; - break; - default: - /* not reached */ - WARN_ON(1); - break; - } - } - } - - conf.changed = changed; - - return local->ops->config_interface(local_to_hw(local), - &sdata->vif, &conf); -} - int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) { struct ieee80211_channel *chan; @@ -297,6 +221,61 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, if (!changed) return; + if (sdata->vif.type == NL80211_IFTYPE_STATION) + sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; + else if (sdata->vif.type == NL80211_IFTYPE_AP) + sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; + else if (ieee80211_vif_is_mesh(&sdata->vif)) { + static const u8 zero[ETH_ALEN] = { 0 }; + sdata->vif.bss_conf.bssid = zero; + } else { + WARN_ON(1); + return; + } + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + break; + default: + /* do not warn to simplify caller in scan.c */ + changed &= ~BSS_CHANGED_BEACON_ENABLED; + if (WARN_ON(changed & BSS_CHANGED_BEACON)) + return; + break; + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (local->sw_scanning) { + sdata->vif.bss_conf.enable_beacon = false; + } else { + /* + * Beacon should be enabled, but AP mode must + * check whether there is a beacon configured. + */ + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + sdata->vif.bss_conf.enable_beacon = + !!rcu_dereference(sdata->u.ap.beacon); + break; + case NL80211_IFTYPE_ADHOC: + sdata->vif.bss_conf.enable_beacon = + !!rcu_dereference(sdata->u.ibss.presp); + break; + case NL80211_IFTYPE_MESH_POINT: + sdata->vif.bss_conf.enable_beacon = true; + break; + default: + /* not reached */ + WARN_ON(1); + break; + } + } + } + if (local->ops->bss_info_changed) local->ops->bss_info_changed(local_to_hw(local), &sdata->vif, diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9a3e5de0410a..9000b01a1671 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -417,7 +417,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.mesh.accepting_plinks) - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); ifmsh->housekeeping = false; mod_timer(&ifmsh->housekeeping_timer, @@ -432,8 +432,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ifmsh->housekeeping = true; queue_work(local->hw.workqueue, &ifmsh->work); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED); } void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bfd571e6f221..c7971196d9d5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2289,12 +2289,8 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) ifmgd->flags &= ~IEEE80211_STA_BSSID_SET; } - if (netif_running(sdata->dev)) { - if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", sdata->dev->name); - } - } + if (netif_running(sdata->dev)) + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); return ieee80211_sta_commit(sdata); } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 086d21645cbc..04e270abdd22 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -346,8 +346,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_ADHOC || sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_if_config(sdata, - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); } mutex_unlock(&local->iflist_mtx); @@ -387,8 +387,8 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_ADHOC || sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_if_config(sdata, - IEEE80211_IFCC_BEACON_ENABLED); + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 61876eb50b49..2cde9bbfe7d9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1063,24 +1063,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: /* disable beacon change bits */ - changed &= ~IEEE80211_IFCC_BEACON; + changed &= ~(BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED); /* fall through */ case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: - /* - * Driver's config_interface can fail if rfkill is - * enabled. Accommodate this return code. - * FIXME: When mac80211 has knowledge of rfkill - * state the code below can change back to: - * WARN(ieee80211_if_config(sdata, changed)); - * ieee80211_bss_info_change_notify(sdata, ~0); - */ - if (ieee80211_if_config(sdata, changed)) - printk(KERN_DEBUG "%s: failed to configure interface during resume\n", - sdata->dev->name); - else - ieee80211_bss_info_change_notify(sdata, ~0); + ieee80211_bss_info_change_notify(sdata, changed); break; case NL80211_IFTYPE_WDS: break; -- cgit v1.2.3 From 2448798133d747ad339e57099e32a1d1e68aca1c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Apr 2009 18:52:52 +0200 Subject: mac80211: add driver ops wrappers In order to later add tracing or verifications to the driver calls mac80211 makes, this patch adds static inline wrappers for all operations. All calls are now written as drv_(local, ...); instead of local->ops->(&local->hw, ...); Where necessary, the wrappers also do existence checking and return default values as appropriate. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 11 ++- net/mac80211/agg-tx.c | 13 ++-- net/mac80211/cfg.c | 24 +++--- net/mac80211/debugfs.c | 20 +++-- net/mac80211/driver-ops.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/ibss.c | 26 +++---- net/mac80211/iface.c | 22 +++--- net/mac80211/key.c | 8 +- net/mac80211/main.c | 17 ++--- net/mac80211/mlme.c | 14 ++-- net/mac80211/pm.c | 9 ++- net/mac80211/rx.c | 9 +-- net/mac80211/scan.c | 28 +++---- net/mac80211/sta_info.c | 14 ++-- net/mac80211/tkip.c | 6 +- net/mac80211/tx.c | 3 +- net/mac80211/util.c | 14 ++-- 17 files changed, 292 insertions(+), 130 deletions(-) create mode 100644 net/mac80211/driver-ops.h diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 07656d830bc4..fff24c3d6460 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -16,12 +16,12 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, u16 initiator, u16 reason) { struct ieee80211_local *local = sta->local; - struct ieee80211_hw *hw = &local->hw; int i; /* check if TID is in operational state */ @@ -41,8 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - if (local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, - &sta->sta, tid, NULL)) + if (drv_ampdu_action(local, IEEE80211_AMPDU_RX_STOP, + &sta->sta, tid, NULL)) printk(KERN_DEBUG "HW problem - can not stop rx " "aggregation for tid %d\n", tid); @@ -278,9 +278,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, goto end; } - if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num); + ret = drv_ampdu_action(local, IEEE80211_AMPDU_RX_START, + &sta->sta, tid, &start_seq_num); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); #endif /* CONFIG_MAC80211_HT_DEBUG */ diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 947aaaad35d2..43d00ffd3988 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -16,6 +16,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "wme.h" /** @@ -134,8 +135,8 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, *state = HT_AGG_STATE_REQ_STOP_BA_MSK | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); - ret = local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_STOP, - &sta->sta, tid, NULL); + ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_STOP, + &sta->sta, tid, NULL); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -306,8 +307,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) start_seq_num = sta->tid_seq[tid]; - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, - &sta->sta, tid, &start_seq_num); + ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_START, + &sta->sta, tid, &start_seq_num); if (ret) { #ifdef CONFIG_MAC80211_HT_DEBUG @@ -418,8 +419,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, ieee80211_agg_splice_finish(local, sta, tid); spin_unlock(&local->ampdu_lock); - local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL); + drv_ampdu_action(local, IEEE80211_AMPDU_TX_OPERATIONAL, + &sta->sta, tid, NULL); } void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 648bac1c850e..d0ca6da33ca9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -13,6 +13,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "cfg.h" #include "rate.h" #include "mesh.h" @@ -245,12 +246,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, iv32 = key->u.tkip.tx.iv32; iv16 = key->u.tkip.tx.iv16; - if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && - sdata->local->ops->get_tkip_seq) - sdata->local->ops->get_tkip_seq( - local_to_hw(sdata->local), - key->conf.hw_key_idx, - &iv32, &iv16); + if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + drv_get_tkip_seq(sdata->local, + key->conf.hw_key_idx, + &iv32, &iv16); seq[0] = iv16 & 0xff; seq[1] = (iv16 >> 8) & 0xff; @@ -1115,7 +1114,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, p.cw_max = params->cwmax; p.cw_min = params->cwmin; p.txop = params->txop; - if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { + if (drv_conf_tx(local, params->queue, &p)) { printk(KERN_DEBUG "%s: failed to set TX queue " "parameters for queue %d\n", local->mdev->name, params->queue); @@ -1296,16 +1295,13 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct ieee80211_local *local = wiphy_priv(wiphy); + int err; if (changed & WIPHY_PARAM_RTS_THRESHOLD) { - int err; + err = drv_set_rts_threshold(local, wiphy->rts_threshold); - if (local->ops->set_rts_threshold) { - err = local->ops->set_rts_threshold( - local_to_hw(local), wiphy->rts_threshold); - if (err) - return err; - } + if (err) + return err; } if (changed & WIPHY_PARAM_RETRY_SHORT) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 5001328be46b..ac793201b701 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -10,6 +10,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "debugfs.h" @@ -70,11 +71,10 @@ static ssize_t tsf_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ieee80211_local *local = file->private_data; - u64 tsf = 0; + u64 tsf; char buf[100]; - if (local->ops->get_tsf) - tsf = local->ops->get_tsf(local_to_hw(local)); + tsf = drv_get_tsf(local); snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); @@ -97,13 +97,13 @@ static ssize_t tsf_write(struct file *file, if (strncmp(buf, "reset", 5) == 0) { if (local->ops->reset_tsf) { - local->ops->reset_tsf(local_to_hw(local)); + drv_reset_tsf(local); printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); } } else { tsf = simple_strtoul(buf, NULL, 0); if (local->ops->set_tsf) { - local->ops->set_tsf(local_to_hw(local), tsf); + drv_set_tsf(local, tsf); printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); } } @@ -150,14 +150,12 @@ static ssize_t format_devstat_counter(struct ieee80211_local *local, char buf[20]; int res; - if (!local->ops->get_stats) - return -EOPNOTSUPP; - rtnl_lock(); - res = local->ops->get_stats(local_to_hw(local), &stats); + res = drv_get_stats(local, &stats); rtnl_unlock(); - if (!res) - res = printvalue(&stats, buf, sizeof(buf)); + if (res) + return res; + res = printvalue(&stats, buf, sizeof(buf)); return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h new file mode 100644 index 000000000000..3912b5334b9c --- /dev/null +++ b/net/mac80211/driver-ops.h @@ -0,0 +1,184 @@ +#ifndef __MAC80211_DRIVER_OPS +#define __MAC80211_DRIVER_OPS + +#include +#include "ieee80211_i.h" + +static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) +{ + return local->ops->tx(&local->hw, skb); +} + +static inline int drv_start(struct ieee80211_local *local) +{ + return local->ops->start(&local->hw); +} + +static inline void drv_stop(struct ieee80211_local *local) +{ + local->ops->stop(&local->hw); +} + +static inline int drv_add_interface(struct ieee80211_local *local, + struct ieee80211_if_init_conf *conf) +{ + return local->ops->add_interface(&local->hw, conf); +} + +static inline void drv_remove_interface(struct ieee80211_local *local, + struct ieee80211_if_init_conf *conf) +{ + local->ops->remove_interface(&local->hw, conf); +} + +static inline int drv_config(struct ieee80211_local *local, u32 changed) +{ + return local->ops->config(&local->hw, changed); +} + +static inline void drv_bss_info_changed(struct ieee80211_local *local, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + if (local->ops->bss_info_changed) + local->ops->bss_info_changed(&local->hw, vif, info, changed); +} + +static inline void drv_configure_filter(struct ieee80211_local *local, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) +{ + local->ops->configure_filter(&local->hw, changed_flags, total_flags, + mc_count, mc_list); +} + +static inline int drv_set_tim(struct ieee80211_local *local, + struct ieee80211_sta *sta, bool set) +{ + if (local->ops->set_tim) + return local->ops->set_tim(&local->hw, sta, set); + return 0; +} + +static inline int drv_set_key(struct ieee80211_local *local, + enum set_key_cmd cmd, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + return local->ops->set_key(&local->hw, cmd, vif, sta, key); +} + +static inline void drv_update_tkip_key(struct ieee80211_local *local, + struct ieee80211_key_conf *conf, + const u8 *address, u32 iv32, + u16 *phase1key) +{ + if (local->ops->update_tkip_key) + local->ops->update_tkip_key(&local->hw, conf, address, + iv32, phase1key); +} + +static inline int drv_hw_scan(struct ieee80211_local *local, + struct cfg80211_scan_request *req) +{ + return local->ops->hw_scan(&local->hw, req); +} + +static inline void drv_sw_scan_start(struct ieee80211_local *local) +{ + if (local->ops->sw_scan_start) + local->ops->sw_scan_start(&local->hw); +} + +static inline void drv_sw_scan_complete(struct ieee80211_local *local) +{ + if (local->ops->sw_scan_complete) + local->ops->sw_scan_complete(&local->hw); +} + +static inline int drv_get_stats(struct ieee80211_local *local, + struct ieee80211_low_level_stats *stats) +{ + if (!local->ops->get_stats) + return -EOPNOTSUPP; + return local->ops->get_stats(&local->hw, stats); +} + +static inline void drv_get_tkip_seq(struct ieee80211_local *local, + u8 hw_key_idx, u32 *iv32, u16 *iv16) +{ + if (local->ops->get_tkip_seq) + local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); +} + +static inline int drv_set_rts_threshold(struct ieee80211_local *local, + u32 value) +{ + if (local->ops->set_rts_threshold) + return local->ops->set_rts_threshold(&local->hw, value); + return 0; +} + +static inline void drv_sta_notify(struct ieee80211_local *local, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + if (local->ops->sta_notify) + local->ops->sta_notify(&local->hw, vif, cmd, sta); +} + +static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + if (local->ops->conf_tx) + return local->ops->conf_tx(&local->hw, queue, params); + return -EOPNOTSUPP; +} + +static inline int drv_get_tx_stats(struct ieee80211_local *local, + struct ieee80211_tx_queue_stats *stats) +{ + return local->ops->get_tx_stats(&local->hw, stats); +} + +static inline u64 drv_get_tsf(struct ieee80211_local *local) +{ + if (local->ops->get_tsf) + return local->ops->get_tsf(&local->hw); + return -1ULL; +} + +static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) +{ + if (local->ops->set_tsf) + local->ops->set_tsf(&local->hw, tsf); +} + +static inline void drv_reset_tsf(struct ieee80211_local *local) +{ + if (local->ops->reset_tsf) + local->ops->reset_tsf(&local->hw); +} + +static inline int drv_tx_last_beacon(struct ieee80211_local *local) +{ + if (local->ops->tx_last_beacon) + return local->ops->tx_last_beacon(&local->hw); + return 1; +} + +static inline int drv_ampdu_action(struct ieee80211_local *local, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, + u16 *ssn) +{ + if (local->ops->ampdu_action) + return local->ops->ampdu_action(&local->hw, action, + sta, tid, ssn); + return -EOPNOTSUPP; +} +#endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c87caad383f0..a8e23232267e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -22,6 +22,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #define IEEE80211_SCAN_INTERVAL (2 * HZ) @@ -75,10 +76,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband; u32 bss_change; - if (local->ops->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->ops->reset_tsf(local_to_hw(local)); - } + + /* Reset own TSF to allow time synchronization work. */ + drv_reset_tsf(local); skb = ifibss->skb; rcu_assign_pointer(ifibss->presp, NULL); @@ -315,12 +315,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bitrates[rx_status->rate_idx].bitrate; rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); - } else if (local && local->ops && local->ops->get_tsf) - /* second best option: get current TSF */ - rx_timestamp = local->ops->get_tsf(local_to_hw(local)); - else - /* can't merge without knowing the TSF */ - rx_timestamp = -1LLU; + } else { + /* + * second best option: get current TSF + * (will return -1 if not supported) + */ + rx_timestamp = drv_get_tsf(local); + } #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" @@ -591,10 +592,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, len < 24 + 2 || !ifibss->presp) return; - if (local->ops->tx_last_beacon) - tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local)); - else - tx_last_beacon = 1; + tx_last_beacon = drv_tx_last_beacon(local); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 52425975bbbe..256fa19e14ec 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -20,6 +20,7 @@ #include "debugfs_netdev.h" #include "mesh.h" #include "led.h" +#include "driver-ops.h" /** * DOC: Interface list locking @@ -164,9 +165,7 @@ static int ieee80211_open(struct net_device *dev) } if (local->open_count == 0) { - res = 0; - if (local->ops->start) - res = local->ops->start(local_to_hw(local)); + res = drv_start(local); if (res) goto err_del_bss; /* we're brought up, everything changes */ @@ -199,8 +198,8 @@ static int ieee80211_open(struct net_device *dev) * Validate the MAC address for this device. */ if (!is_valid_ether_addr(dev->dev_addr)) { - if (!local->open_count && local->ops->stop) - local->ops->stop(local_to_hw(local)); + if (!local->open_count) + drv_stop(local); return -EADDRNOTAVAIL; } @@ -241,7 +240,7 @@ static int ieee80211_open(struct net_device *dev) conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = dev->dev_addr; - res = local->ops->add_interface(local_to_hw(local), &conf); + res = drv_add_interface(local, &conf); if (res) goto err_stop; @@ -328,10 +327,10 @@ static int ieee80211_open(struct net_device *dev) return 0; err_del_interface: - local->ops->remove_interface(local_to_hw(local), &conf); + drv_remove_interface(local, &conf); err_stop: - if (!local->open_count && local->ops->stop) - local->ops->stop(local_to_hw(local)); + if (!local->open_count) + drv_stop(local); err_del_bss: sdata->bss = NULL; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) @@ -544,7 +543,7 @@ static int ieee80211_stop(struct net_device *dev) conf.mac_addr = dev->dev_addr; /* disable all keys for as long as this netdev is down */ ieee80211_disable_keys(sdata); - local->ops->remove_interface(local_to_hw(local), &conf); + drv_remove_interface(local, &conf); } sdata->bss = NULL; @@ -553,8 +552,7 @@ static int ieee80211_stop(struct net_device *dev) if (netif_running(local->mdev)) dev_close(local->mdev); - if (local->ops->stop) - local->ops->stop(local_to_hw(local)); + drv_stop(local); ieee80211_led_radio(local, 0); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 687acf23054d..b7e1350273bb 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -16,6 +16,7 @@ #include #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "debugfs_key.h" #include "aes_ccm.h" #include "aes_cmac.h" @@ -136,8 +137,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, - &sdata->vif, sta, &key->conf); + ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); if (!ret) { spin_lock(&todo_lock); @@ -179,8 +179,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, - &sdata->vif, sta, &key->conf); + ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, + sta, &key->conf); if (ret) printk(KERN_ERR "mac80211-%s: failed to remove key " diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c817c9ef215a..b80bc80e46cf 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -26,6 +26,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "mesh.h" #include "wep.h" @@ -81,10 +82,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local) /* be a bit nasty */ new_flags |= (1<<31); - local->ops->configure_filter(local_to_hw(local), - changed_flags, &new_flags, - local->mdev->mc_count, - local->mdev->mc_list); + drv_configure_filter(local, changed_flags, &new_flags, + local->mdev->mc_count, + local->mdev->mc_list); WARN_ON(new_flags & (1<<31)); @@ -192,7 +192,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) } if (changed && local->open_count) { - ret = local->ops->config(local_to_hw(local), changed); + ret = drv_config(local, changed); /* * Goal: * HW reconfiguration should never fail, the driver has told @@ -276,11 +276,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, } } - if (local->ops->bss_info_changed) - local->ops->bss_info_changed(local_to_hw(local), - &sdata->vif, - &sdata->vif.bss_conf, - changed); + drv_bss_info_changed(local, &sdata->vif, + &sdata->vif.bss_conf, changed); /* * DEPRECATED diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c7971196d9d5..42f33fd3c5ec 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -23,6 +23,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "led.h" @@ -683,11 +684,10 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.txop); #endif - if (local->ops->conf_tx && - local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { + if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", local->mdev->name, queue); - } + "parameters for queue %d\n", local->mdev->name, + queue); } } @@ -1982,10 +1982,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - if (local->ops->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->ops->reset_tsf(local_to_hw(local)); - } + /* Reset own TSF to allow time synchronization work. */ + drv_reset_tsf(local); ifmgd->wmm_last_param_set = -1; /* allow any WMM update */ diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index b38986c9deef..9d3d89abbb57 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -2,6 +2,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "led.h" int __ieee80211_suspend(struct ieee80211_hw *hw) @@ -43,8 +44,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(hw, &sdata->vif, - STA_NOTIFY_REMOVE, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + &sta->sta); } spin_unlock_irqrestore(&local->sta_lock, flags); } @@ -57,7 +58,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = sdata->dev->dev_addr; - local->ops->remove_interface(hw, &conf); + drv_remove_interface(local, &conf); } } @@ -67,7 +68,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) /* stop hardware */ if (local->open_count) { ieee80211_led_radio(local, false); - local->ops->stop(hw); + drv_stop(local); } return 0; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a5afb79dab6e..6a9d89b392e3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -19,6 +19,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "led.h" #include "mesh.h" #include "wep.h" @@ -773,9 +774,7 @@ static void ap_sta_ps_start(struct sta_info *sta) atomic_inc(&sdata->bss->num_sta_ps); set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); - if (local->ops->sta_notify) - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_SLEEP, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", sdata->dev->name, sta->sta.addr, sta->sta.aid); @@ -792,9 +791,7 @@ static int ap_sta_ps_end(struct sta_info *sta) atomic_dec(&sdata->bss->num_sta_ps); clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); - if (local->ops->sta_notify) - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_AWAKE, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); if (!skb_queue_empty(&sta->ps_tx_buf)) sta_info_clear_tim_bit(sta); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 04e270abdd22..127bd54e0e38 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -21,6 +21,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "mesh.h" #define IEEE80211_PROBE_DELAY (HZ / 33) @@ -316,17 +317,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) netif_tx_lock_bh(local->mdev); netif_addr_lock(local->mdev); local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); + drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, + &local->filter_flags, + local->mdev->mc_count, + local->mdev->mc_list); netif_addr_unlock(local->mdev); netif_tx_unlock_bh(local->mdev); - if (local->ops->sw_scan_complete) - local->ops->sw_scan_complete(local_to_hw(local)); + drv_sw_scan_complete(local); mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { @@ -375,8 +374,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) * nullfunc frames and probe requests will be dropped in * ieee80211_tx_h_check_assoc(). */ - if (local->ops->sw_scan_start) - local->ops->sw_scan_start(local_to_hw(local)); + drv_sw_scan_start(local); mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { @@ -405,11 +403,10 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); + drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, + &local->filter_flags, + local->mdev->mc_count, + local->mdev->mc_list); netif_addr_unlock_bh(local->mdev); /* TODO: start scan as soon as all nullfunc frames are ACKed */ @@ -477,8 +474,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, mutex_unlock(&local->scan_mtx); if (local->ops->hw_scan) - rc = local->ops->hw_scan(local_to_hw(local), - local->scan_req); + rc = drv_hw_scan(local, local->scan_req); else rc = ieee80211_start_sw_scan(local); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 7116220d06be..a98ea273a155 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -19,6 +19,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "sta_info.h" #include "debugfs_sta.h" @@ -346,8 +347,7 @@ int sta_info_insert(struct sta_info *sta) struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_ADD, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -405,8 +405,7 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; - sta->local->ops->set_tim(local_to_hw(sta->local), - &sta->sta, true); + drv_set_tim(sta->local, &sta->sta, true); sta->local->tim_in_locked_section = false; } } @@ -431,8 +430,7 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; - sta->local->ops->set_tim(local_to_hw(sta->local), - &sta->sta, false); + drv_set_tim(sta->local, &sta->sta, false); sta->local->tim_in_locked_section = false; } } @@ -482,8 +480,8 @@ static void __sta_info_unlink(struct sta_info **sta) struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_REMOVE, &(*sta)->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + &(*sta)->sta); } if (ieee80211_vif_is_mesh(&sdata->vif)) { diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 38fa111d2dc6..964b7faa7f17 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -13,6 +13,7 @@ #include #include +#include "driver-ops.h" #include "key.h" #include "tkip.h" #include "wep.h" @@ -307,9 +308,8 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, if (is_multicast_ether_addr(ra)) sta_addr = bcast; - key->local->ops->update_tkip_key( - local_to_hw(key->local), &key->conf, - sta_addr, iv32, key->u.tkip.rx[queue].p1k); + drv_update_tkip_key(key->local, &key->conf, sta_addr, + iv32, key->u.tkip.rx[queue].p1k); } } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 29df65045fc9..1564a3018cf5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -25,6 +25,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "led.h" #include "mesh.h" #include "wep.h" @@ -1162,7 +1163,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, next = skb->next; len = skb->len; - ret = local->ops->tx(local_to_hw(local), skb); + ret = drv_tx(local, skb); if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { dev_kfree_skb(skb); ret = NETDEV_TX_OK; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 2cde9bbfe7d9..97b613affe08 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -26,6 +26,7 @@ #include #include "ieee80211_i.h" +#include "driver-ops.h" #include "rate.h" #include "mesh.h" #include "wme.h" @@ -726,7 +727,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) qparam.txop = 0; for (i = 0; i < local_to_hw(local)->queues; i++) - local->ops->conf_tx(local_to_hw(local), i, &qparam); + drv_conf_tx(local, i, &qparam); } void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, @@ -1000,7 +1001,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* restart hardware */ if (local->open_count) { - res = local->ops->start(hw); + res = drv_start(local); ieee80211_led_radio(local, hw->conf.radio_enabled); } @@ -1013,7 +1014,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = sdata->dev->dev_addr; - res = local->ops->add_interface(hw, &conf); + res = drv_add_interface(local, &conf); } } @@ -1026,8 +1027,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_sub_if_data, u.ap); - local->ops->sta_notify(hw, &sdata->vif, - STA_NOTIFY_ADD, &sta->sta); + drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, + &sta->sta); } spin_unlock_irqrestore(&local->sta_lock, flags); } @@ -1045,8 +1046,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) rcu_read_unlock(); /* setup RTS threshold */ - if (local->ops->set_rts_threshold) - local->ops->set_rts_threshold(hw, hw->wiphy->rts_threshold); + drv_set_rts_threshold(local, hw->wiphy->rts_threshold); /* reconfigure hardware */ ieee80211_hw_config(local, ~0); -- cgit v1.2.3 From e61f234079b49c7e075b12551797fc4954704019 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2009 00:00:00 +0300 Subject: nl80211: Send timeout event on failed direct probe If the direct probe times out, we need to send the authentication timeout event to notify SME in the same way as we notify on timeout with authentication frames since the direct probe is run as part of the authentication attempt. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 42f33fd3c5ec..30a0034b9124 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -890,7 +890,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_sta_send_apinfo(sdata); + cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); /* * Most likely AP is not in the range so remove the -- cgit v1.2.3 From d91f190c412aff940a46cabaccf114361c133605 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 24 Apr 2009 15:13:54 +0200 Subject: mac80211_hwsim: fix bogus warning A typo slipped into my patch to configure beacon intervals properly -- this warning is supposed to trigger when the beacon interval is zero, not non-zero. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e67b424f925e..8fa6e6ce5705 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -618,7 +618,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, printk(KERN_DEBUG " %s: BCNINT: %d\n", wiphy_name(hw->wiphy), info->beacon_int); data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; - if (WARN_ON(data->beacon_int)) + if (WARN_ON(!data->beacon_int)) data->beacon_int = 1; } -- cgit v1.2.3 From 16cf438a1eca2b7206bd7ac7763637c2a87c00c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 24 Apr 2009 15:15:25 +0200 Subject: mac80211: fix probe response processing Due to the use of a _REQ_DIRECT_PROBE bit, which is unnecessary (and I wonder why it was done that way), an interesting situation can arise: 1) we try to probe an access point 2) the AP doesn't response in time 3) we tell userspace that we gave up 4) the AP suddenly responds 5) we auth/assoc with the AP I've seen 4) happen in testing with hostapd SIGSTOPped, and when SIGCONTinued it processes the probe requests that came in and send responses. But 5) is not supposed to happen after we tell everybody we've given up on the AP. To fix this, remove the _REQ_DIRECT_PROBE request bit, and process probe responses when we're in the relevant MLME state, namely IEEE80211_STA_MLME_DIRECT_PROBE. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 5 ++--- net/mac80211/mlme.c | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d8de1e159ee0..236ea098bb6c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -248,9 +248,8 @@ struct mesh_preq_queue { #define IEEE80211_STA_EXT_SME BIT(17) /* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 -#define IEEE80211_STA_REQ_DIRECT_PROBE 1 -#define IEEE80211_STA_REQ_AUTH 2 -#define IEEE80211_STA_REQ_RUN 3 +#define IEEE80211_STA_REQ_AUTH 1 +#define IEEE80211_STA_REQ_RUN 2 /* bitfield of allowed auth algs */ #define IEEE80211_AUTH_ALG_OPEN BIT(0) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 30a0034b9124..2ded4766d014 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -915,8 +915,6 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; - set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifmgd->request); - /* Direct probe is sent to broadcast address as some APs * will not answer to direct packet in unassociated state. */ @@ -1738,8 +1736,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); /* direct probe may be part of the association flow */ - if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, - &ifmgd->request)) { + if (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE) { printk(KERN_DEBUG "%s direct probe responded\n", sdata->dev->name); ieee80211_authenticate(sdata); -- cgit v1.2.3 From 083c4687bc3abc315c73830b9c74ad67e005d8c2 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 24 Apr 2009 21:35:57 +0200 Subject: ar9170: handle otus' A-MPDU density definitions Otus uses slightly different set of "Minimum MPDU Start Spacing" values than the 802.11n D2.0 specifies. (the whole table is shifted by one and therefore the 16us spacing is not officially available!) And while we're at it, we also initialize our MAC's density register. So, this annoying _feature_ will not break TX A-MPDU later. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/hw.h | 2 ++ drivers/net/wireless/ath/ar9170/mac.c | 23 +++++++++++++++++++++++ drivers/net/wireless/ath/ar9170/main.c | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 95bf812d6fcc..3293e0fb24fb 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -207,6 +207,8 @@ enum ar9170_cmd { #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_SET (AR9170_MAC_REG_BASE + 0xba0) + #define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) #define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index 0e5967dd119c..45986b6eadbc 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -72,6 +72,24 @@ int ar9170_set_qos(struct ar9170 *ar) return ar9170_regwrite_result(); } +static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) +{ + u32 val; + + /* don't allow AMPDU density > 8us */ + if (mpdudensity > 6) + return -EINVAL; + + /* Watch out! Otus uses slightly different density values. */ + val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); + + ar9170_regwrite_begin(ar); + ar9170_regwrite(AR9170_MAC_REG_AMPDU_SET, val); + ar9170_regwrite_finish(); + + return ar9170_regwrite_result(); +} + int ar9170_init_mac(struct ar9170 *ar) { ar9170_regwrite_begin(ar); @@ -296,6 +314,11 @@ int ar9170_set_operating_mode(struct ar9170 *ar) if (err) return err; + /* set AMPDU density to 8us. */ + err = ar9170_set_ampdu_density(ar, 6); + if (err) + return err; + ar9170_regwrite_begin(ar); ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 3bd3a61225ce..4ef1d2fc859c 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -151,8 +151,8 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { IEEE80211_HT_CAP_SGI_40 | \ IEEE80211_HT_CAP_DSSSCCK40 | \ IEEE80211_HT_CAP_SM_PS, \ - .ampdu_factor = 3, /* ?? */ \ - .ampdu_density = 7, /* ?? */ \ + .ampdu_factor = 3, \ + .ampdu_density = 6, \ .mcs = { \ .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \ }, \ -- cgit v1.2.3 From 2cfb1f5e20f260e6ff306ba181efee956ba48f54 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 24 Apr 2009 21:41:18 +0200 Subject: ar9170: uncomment powermgt case handle This patch uncomment a few lines that survived the RFCs. However, there is not much to worry about, since AP mode is not officially advertised and supported. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index 45986b6eadbc..43aeb69685d3 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -283,9 +283,9 @@ int ar9170_set_operating_mode(struct ar9170 *ar) case NL80211_IFTYPE_ADHOC: pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; break; -/* case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP: pm_mode |= AR9170_MAC_REG_POWERMGT_AP; - break;*/ + break; case NL80211_IFTYPE_WDS: pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; break; -- cgit v1.2.3 From 0ef9ccdd9ec7f2cf28d0605c216d853687f5291d Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Fri, 24 Apr 2009 14:09:31 -0700 Subject: cfg80211: remove superfluous !last_request check in reg_device_remove() Commit 0ad8acaf "cfg80211: fix NULL pointer deference in reg_device_remove()" added a check that last_request is non-NULL, rendering the 2nd check superfluous. While there, rearrange the code a bit so it's a little more straight forward. Signed-off-by: Chris Wright Signed-off-by: John W. Linville --- net/wireless/reg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f38cc39fa79e..9fea910204db 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2100,14 +2100,14 @@ void reg_device_remove(struct wiphy *wiphy) assert_cfg80211_lock(); + kfree(wiphy->regd); + if (last_request) request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); - kfree(wiphy->regd); - if (!last_request || !request_wiphy) - return; - if (request_wiphy != wiphy) + if (!request_wiphy || request_wiphy != wiphy) return; + last_request->wiphy_idx = WIPHY_IDX_STALE; last_request->country_ie_env = ENVIRON_ANY; } -- cgit v1.2.3 From aeca78b9b094d00cccca39e9a1055c74ad83ea69 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 24 Apr 2009 15:26:02 -0700 Subject: net/rfkill/rfkill.c: fix build with CONFIG_RFKILL_LEDS=n net/rfkill/rfkill.c: In function 'update_rfkill_state': net/rfkill/rfkill.c:99: error: implicit declaration of function 'rfkill_led_trigger' Caused by : commit 492301fb5d12e4a77a1010ad2b6f1ed306014123 : Author: Larry Finger : Date: Thu Apr 9 22:14:19 2009 -0500 : : rfkill: Fix broken rfkill LED in 2.6.30-rc1 Cc: Henrique de Moraes Holschuh Cc: Ivo van Doorn Cc: Michael Buesch Cc: David S. Miller Cc: Larry Finger Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- net/rfkill/rfkill.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index e2d4510623f2..4f5a83183c95 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -75,6 +75,11 @@ static void rfkill_led_trigger_activate(struct led_classdev *led) rfkill_led_trigger(rfkill, rfkill->state); } +#else +static inline void rfkill_led_trigger(struct rfkill *rfkill, + enum rfkill_state state) +{ +} #endif /* CONFIG_RFKILL_LEDS */ static void rfkill_uevent(struct rfkill *rfkill) -- cgit v1.2.3 From ded7a7eaab2a39b7b5c36a2ec3be46f6ebcedba5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 25 Apr 2009 14:09:23 +0200 Subject: ath5k: 5211, don't crypt every protected frame Set null key type even on ar5211, otherwise it en/decrypts every frame with protected bit set which renders the card unusable on encrypted networks. Signed-off-by: Jiri Slaby Cc: Luis R. Rodriguez Cc: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 55122f1e1986..5f07e876d4bd 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -1003,7 +1003,7 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) * Note2: Windows driver (ndiswrapper) sets this to * 0x00000714 instead of 0x00000007 */ - if (ah->ah_version > AR5K_AR5211) { + if (ah->ah_version >= AR5K_AR5211) { ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(entry)); -- cgit v1.2.3 From a406ac0dc15b22807b65f5a6590b9cb34d99d4ab Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 25 Apr 2009 21:11:55 +0200 Subject: p54usb: remove some dead code Since "p54: prevent upload of wrong firmwares" we no longer allow outdated LM86 firmwares to be uploaded on ISL3887 (LM87) devices. Therefore we can purge this buggy legacy code altogether. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 56 +++------------------------------------ 1 file changed, 3 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 6cc6cbc9234f..44ab3ccac910 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -206,53 +206,6 @@ static int p54u_init_urbs(struct ieee80211_hw *dev) return ret; } -static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54u_priv *priv = dev->priv; - struct urb *addr_urb, *data_urb; - int err = 0; - - addr_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!addr_urb) - return; - - data_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!data_urb) { - usb_free_urb(addr_urb); - return; - } - - usb_fill_bulk_urb(addr_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - &((struct p54_hdr *)skb->data)->req_id, 4, - p54u_tx_dummy_cb, dev); - usb_fill_bulk_urb(data_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - skb->data, skb->len, FREE_AFTER_TX(skb) ? - p54u_tx_cb : p54u_tx_dummy_cb, skb); - addr_urb->transfer_flags |= URB_ZERO_PACKET; - data_urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(addr_urb, &priv->submitted); - err = usb_submit_urb(addr_urb, GFP_ATOMIC); - if (err) { - usb_unanchor_urb(addr_urb); - goto out; - } - - usb_anchor_urb(data_urb, &priv->submitted); - err = usb_submit_urb(data_urb, GFP_ATOMIC); - if (err) - usb_unanchor_urb(data_urb); - - out: - usb_free_urb(addr_urb); - usb_free_urb(data_urb); - - if (err) - p54_free_skb(dev, skb); -} - static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) { u32 chk = 0; @@ -954,13 +907,10 @@ static int __devinit p54u_probe(struct usb_interface *intf, priv->common.stop = p54u_stop; if (recognized_pipes < P54U_PIPE_NUMBER) { priv->hw_type = P54U_3887; + dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); + priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); + priv->common.tx = p54u_tx_lm87; err = p54u_upload_firmware_3887(dev); - if (priv->common.fw_interface == FW_LM87) { - dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); - priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); - priv->common.tx = p54u_tx_lm87; - } else - priv->common.tx = p54u_tx_3887; } else { priv->hw_type = P54U_NET2280; dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); -- cgit v1.2.3 From 1ca5f2e94c40b04d5dec437cd41fd5ba12aaac31 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 25 Apr 2009 21:12:09 +0200 Subject: p54usb: rework driver for resume This patch redo the driver code so that p54usb no longer hangs the kernel on resume. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 256 ++++++++++++++++++++++++-------------- drivers/net/wireless/p54/p54usb.h | 16 ++- 2 files changed, 177 insertions(+), 95 deletions(-) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 44ab3ccac910..ec6c95474f1a 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -81,6 +81,29 @@ static struct usb_device_id p54u_table[] __devinitdata = { MODULE_DEVICE_TABLE(usb, p54u_table); +static const struct { + u32 intf; + enum p54u_hw_type type; + char fw[FIRMWARE_NAME_MAX]; + char fw_legacy[FIRMWARE_NAME_MAX]; + char hw[20]; +} p54u_fwlist[__NUM_P54U_HWTYPES] = { + { + .type = P54U_NET2280, + .intf = FW_LM86, + .fw = "isl3886usb", + .fw_legacy = "isl3890usb", + .hw = "ISL3886 + net2280", + }, + { + .type = P54U_3887, + .intf = FW_LM87, + .fw = "isl3887usb", + .fw_legacy = "isl3887usb_bare", + .hw = "ISL3887", + }, +}; + static void p54u_rx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; @@ -125,11 +148,7 @@ static void p54u_rx_cb(struct urb *urb) } skb_reset_tail_pointer(skb); skb_trim(skb, 0); - if (urb->transfer_buffer != skb_tail_pointer(skb)) { - /* this should not happen */ - WARN_ON(1); - urb->transfer_buffer = skb_tail_pointer(skb); - } + urb->transfer_buffer = skb_tail_pointer(skb); } skb_queue_tail(&priv->rx_queue, skb); usb_anchor_urb(urb, &priv->submitted); @@ -378,20 +397,16 @@ static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep, data, len, &alen, 2000); } -static const char p54u_romboot_3887[] = "~~~~"; -static const char p54u_firmware_upload_3887[] = "<\r"; - -static int p54u_device_reset_3887(struct ieee80211_hw *dev) +static int p54u_device_reset(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING); - u8 buf[4]; if (lock) { ret = usb_lock_device_for_reset(priv->udev, priv->intf); if (ret < 0) { dev_err(&priv->udev->dev, "(p54usb) unable to lock " - " device for reset: %d\n", ret); + "device for reset (%d)!\n", ret); return ret; } } @@ -400,26 +415,34 @@ static int p54u_device_reset_3887(struct ieee80211_hw *dev) if (lock) usb_unlock_device(priv->udev); - if (ret) { + if (ret) dev_err(&priv->udev->dev, "(p54usb) unable to reset " - "device: %d\n", ret); - return ret; - } + "device (%d)!\n", ret); + + return ret; +} + +static const char p54u_romboot_3887[] = "~~~~"; +static int p54u_firmware_reset_3887(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + u8 buf[4]; + int ret; memcpy(&buf, p54u_romboot_3887, sizeof(buf)); ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(buf)); if (ret) dev_err(&priv->udev->dev, "(p54usb) unable to jump to " - "boot ROM: %d\n", ret); + "boot ROM (%d)!\n", ret); return ret; } +static const char p54u_firmware_upload_3887[] = "<\r"; static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; int err, alen; u8 carry = 0; u8 *buf, *tmp; @@ -428,51 +451,29 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) struct x2_header *hdr; unsigned long timeout; + err = p54u_firmware_reset_3887(dev); + if (err) + return err; + tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL); if (!buf) { dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware" "upload buffer!\n"); - err = -ENOMEM; - goto err_bufalloc; - } - - err = p54u_device_reset_3887(dev); - if (err) - goto err_reset; - - err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev); - if (err) { - dev_err(&priv->udev->dev, "p54usb: cannot find firmware " - "(isl3887usb)\n"); - err = request_firmware(&fw_entry, "isl3887usb_bare", - &priv->udev->dev); - if (err) - goto err_req_fw_failed; - } - - err = p54_parse_firmware(dev, fw_entry); - if (err) - goto err_upload_failed; - - if (priv->common.fw_interface != FW_LM87) { - dev_err(&priv->udev->dev, "wrong firmware, " - "please get a LM87 firmware and try again.\n"); - err = -EINVAL; - goto err_upload_failed; + return -ENOMEM; } - left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); + left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size); strcpy(buf, p54u_firmware_upload_3887); left -= strlen(p54u_firmware_upload_3887); tmp += strlen(p54u_firmware_upload_3887); - data = fw_entry->data; - remains = fw_entry->size; + data = priv->fw->data; + remains = priv->fw->size; hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887)); memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); - hdr->fw_length = cpu_to_le32(fw_entry->size); + hdr->fw_length = cpu_to_le32(priv->fw->size); hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr, sizeof(u32)*2)); left -= sizeof(*hdr); @@ -514,7 +515,8 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) left = block_size = min((unsigned int)P54U_FW_BLOCK, remains); } - *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size)); + *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data, + priv->fw->size)); err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); if (err) { dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n"); @@ -565,19 +567,14 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) if (err) goto err_upload_failed; - err_upload_failed: - release_firmware(fw_entry); - err_req_fw_failed: - err_reset: +err_upload_failed: kfree(buf); - err_bufalloc: return err; } static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE; int err, alen; void *buf; @@ -592,33 +589,6 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) return -ENOMEM; } - err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) cannot find firmware " - "(isl3886usb)\n"); - err = request_firmware(&fw_entry, "isl3890usb", - &priv->udev->dev); - if (err) { - kfree(buf); - return err; - } - } - - err = p54_parse_firmware(dev, fw_entry); - if (err) { - kfree(buf); - release_firmware(fw_entry); - return err; - } - - if (priv->common.fw_interface != FW_LM86) { - dev_err(&priv->udev->dev, "wrong firmware, " - "please get a LM86(USB) firmware and try again.\n"); - kfree(buf); - release_firmware(fw_entry); - return -EINVAL; - } - #define P54U_WRITE(type, addr, data) \ do {\ err = p54u_write(priv, buf, type,\ @@ -718,8 +688,8 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); /* finally, we can upload firmware now! */ - remains = fw_entry->size; - data = fw_entry->data; + remains = priv->fw->size; + data = priv->fw->data; offset = ISL38XX_DEV_FIRMWARE_ADDR; while (remains) { @@ -828,12 +798,54 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) #undef P54U_WRITE #undef P54U_READ - fail: - release_firmware(fw_entry); +fail: kfree(buf); return err; } +static int p54u_load_firmware(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + int err, i; + + BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES); + + for (i = 0; i < __NUM_P54U_HWTYPES; i++) + if (p54u_fwlist[i].type == priv->hw_type) + break; + + if (i == __NUM_P54U_HWTYPES) + return -EOPNOTSUPP; + + err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev); + if (err) { + dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " + "(%d)!\n", p54u_fwlist[i].fw, err); + + err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy, + &priv->udev->dev); + if (err) + return err; + } + + err = p54_parse_firmware(dev, priv->fw); + if (err) + goto out; + + if (priv->common.fw_interface != p54u_fwlist[i].intf) { + dev_err(&priv->udev->dev, "wrong firmware, please get " + "a firmware for \"%s\" and try again.\n", + p54u_fwlist[i].hw); + err = -EINVAL; + } + +out: + if (err) + release_firmware(priv->fw); + + return err; +} + static int p54u_open(struct ieee80211_hw *dev) { struct p54u_priv *priv = dev->priv; @@ -875,6 +887,7 @@ static int __devinit p54u_probe(struct usb_interface *intf, } priv = dev->priv; + priv->hw_type = P54U_INVALID_HW; SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -906,34 +919,46 @@ static int __devinit p54u_probe(struct usb_interface *intf, priv->common.open = p54u_open; priv->common.stop = p54u_stop; if (recognized_pipes < P54U_PIPE_NUMBER) { + /* ISL3887 needs a full reset on resume */ + udev->reset_resume = 1; + err = p54u_device_reset(dev); + priv->hw_type = P54U_3887; dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); priv->common.tx = p54u_tx_lm87; - err = p54u_upload_firmware_3887(dev); + priv->upload_fw = p54u_upload_firmware_3887; } else { priv->hw_type = P54U_NET2280; dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); priv->common.tx = p54u_tx_net2280; - err = p54u_upload_firmware_net2280(dev); + priv->upload_fw = p54u_upload_firmware_net2280; } + err = p54u_load_firmware(dev); if (err) goto err_free_dev; + err = priv->upload_fw(dev); + if (err) + goto err_free_fw; + p54u_open(dev); err = p54_read_eeprom(dev); p54u_stop(dev); if (err) - goto err_free_dev; + goto err_free_fw; err = p54_register_common(dev, &udev->dev); if (err) - goto err_free_dev; + goto err_free_fw; return 0; - err_free_dev: +err_free_fw: + release_firmware(priv->fw); + +err_free_dev: ieee80211_free_hw(dev); usb_set_intfdata(intf, NULL); usb_put_dev(udev); @@ -952,20 +977,64 @@ static void __devexit p54u_disconnect(struct usb_interface *intf) priv = dev->priv; usb_put_dev(interface_to_usbdev(intf)); + release_firmware(priv->fw); p54_free_common(dev); ieee80211_free_hw(dev); } static int p54u_pre_reset(struct usb_interface *intf) { + struct ieee80211_hw *dev = usb_get_intfdata(intf); + + if (!dev) + return -ENODEV; + + p54u_stop(dev); return 0; } +static int p54u_resume(struct usb_interface *intf) +{ + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct p54u_priv *priv; + + if (!dev) + return -ENODEV; + + priv = dev->priv; + if (unlikely(!(priv->upload_fw && priv->fw))) + return 0; + + return priv->upload_fw(dev); +} + static int p54u_post_reset(struct usb_interface *intf) { + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct p54u_priv *priv; + int err; + + err = p54u_resume(intf); + if (err) + return err; + + /* reinitialize old device state */ + priv = dev->priv; + if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) + ieee80211_restart_hw(dev); + return 0; } +#ifdef CONFIG_PM + +static int p54u_suspend(struct usb_interface *intf, pm_message_t message) +{ + return p54u_pre_reset(intf); +} + +#endif /* CONFIG_PM */ + static struct usb_driver p54u_driver = { .name = "p54usb", .id_table = p54u_table, @@ -973,6 +1042,11 @@ static struct usb_driver p54u_driver = { .disconnect = p54u_disconnect, .pre_reset = p54u_pre_reset, .post_reset = p54u_post_reset, +#ifdef CONFIG_PM + .suspend = p54u_suspend, + .resume = p54u_resume, + .reset_resume = p54u_resume, +#endif /* CONFIG_PM */ .soft_unbind = 1, }; diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h index 8bc58982d8dd..e935b79f7f75 100644 --- a/drivers/net/wireless/p54/p54usb.h +++ b/drivers/net/wireless/p54/p54usb.h @@ -123,18 +123,26 @@ struct p54u_rx_info { struct ieee80211_hw *dev; }; +enum p54u_hw_type { + P54U_INVALID_HW, + P54U_NET2280, + P54U_3887, + + /* keep last */ + __NUM_P54U_HWTYPES, +}; + struct p54u_priv { struct p54_common common; struct usb_device *udev; struct usb_interface *intf; - enum { - P54U_NET2280 = 0, - P54U_3887 - } hw_type; + int (*upload_fw)(struct ieee80211_hw *dev); + enum p54u_hw_type hw_type; spinlock_t lock; struct sk_buff_head rx_queue; struct usb_anchor submitted; + const struct firmware *fw; }; #endif /* P54USB_H */ -- cgit v1.2.3 From 90ccda9baccec8223ca5456fbe49adf7264d1543 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 25 Apr 2009 21:32:09 +0200 Subject: ar9170usb: reset device on resume This patch takes care of an outstanding comment in "[PATCH] ar9170usb: fix hang on resume" commit message. >However, the device does not accept the firmware on resume. >and it will exit with: > >> firmware part 1 upload failed (-71). >> device is in a bad state. please reconnect it! Reported-by: Johannes Berg Signed-off-by: Christian Lamparter Tested-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index fddda477095c..368fc2d42641 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -689,6 +689,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, aru->common.exec_cmd = ar9170_usb_exec_cmd; aru->common.callback_cmd = ar9170_usb_callback_cmd; + udev->reset_resume = 1; err = ar9170_usb_reset(aru); if (err) goto err_freehw; @@ -805,6 +806,7 @@ static struct usb_driver ar9170_driver = { #ifdef CONFIG_PM .suspend = ar9170_suspend, .resume = ar9170_resume, + .reset_resume = ar9170_resume, #endif /* CONFIG_PM */ }; -- cgit v1.2.3 From 273de92c8461776aaac7b32f8d5889a72b38ea10 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Apr 2009 22:28:55 +0200 Subject: cfg80211: Remove unnecessary ksize() call This removes an unnecessary ksize() call. krealloc() will do this test internally and won't perform any allocation if the space is already sufficient to hold the data. So remove the redundant check. Signed-off-by: Michael Buesch Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/scan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 723aeb3d9462..5dd909a4e601 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -384,11 +384,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, } else { u8 *ies = found->pub.information_elements; - if (found->ies_allocated) { - if (ksize(ies) < ielen) - ies = krealloc(ies, ielen, - GFP_ATOMIC); - } else + if (found->ies_allocated) + ies = krealloc(ies, ielen, GFP_ATOMIC); + else ies = kmalloc(ielen, GFP_ATOMIC); if (ies) { -- cgit v1.2.3 From 44e1b98f733e48bb781e4229120e1de5e0c9fdbb Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 26 Apr 2009 11:27:33 +0200 Subject: cfg80211: Use the correct IE buffer pointer If the IE buffer was allocated, the pub.information_elements pointer was also changed to the allocated space. So we must not assume anymore that the pointer points at the "found" tail. So if it was allocated previously, take the codebranch that grows the buffer size (if necessary) and put the data into the allocated buffer. Signed-off-by: Michael Buesch Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 5dd909a4e601..10b4887dfa6b 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -377,7 +377,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, size_t used = dev->wiphy.bss_priv_size + sizeof(*res); size_t ielen = res->pub.len_information_elements; - if (ksize(found) >= used + ielen) { + if (!found->ies_allocated && ksize(found) >= used + ielen) { memcpy(found->pub.information_elements, res->pub.information_elements, ielen); found->pub.len_information_elements = ielen; -- cgit v1.2.3 From ba5101d098d6a8471d1a3147fb610b2ee3dbb397 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 26 Apr 2009 14:40:59 +0200 Subject: ar9170: wrong test on outlen in ar9170_usb_exec_cmd() ? remove redundant test: outlen is unsigned Signed-off-by: Roel Kluin Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 368fc2d42641..d7b562dcebd2 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -350,7 +350,7 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, goto err_unbuf; } - if (outlen >= 0 && aru->readlen != outlen) { + if (aru->readlen != outlen) { err = -EMSGSIZE; goto err_unbuf; } -- cgit v1.2.3 From bbb33881ae5bfe4197a005dc03b29b7dcc07fa28 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 26 Apr 2009 14:58:40 +0200 Subject: ath5k: Storage class should be before const qualifier commit 8e218fb24faef0bfe95bc91b3c05261e20439527 reverted the previous patch (commit 925be8a3077351edbf2b59ca689105df214a0792). The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Acked-by: Jiri Slaby Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index c0fb3b09ba45..c85429d2de3f 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -640,9 +640,9 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) static inline void ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) { - const static u16 intercepts3[] = + static const u16 intercepts3[] = { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; - const static u16 intercepts3_2[] = + static const u16 intercepts3_2[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; const u16 *ip; int i; -- cgit v1.2.3 From 9eb4e21e289beba9cfe34f24920eee83c144e62f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 26 Apr 2009 16:08:30 +0200 Subject: rt2x00: Move iv_len into tx descriptor data By placing the iv_len into the tx descriptor data and by passing this data to the crypto IV handlers we can save multiple calls to ieee80211_get_hdrlen_from_skb() and some if-statements when copying/removing the IV data from the outgoing frame. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00crypto.c | 19 +++++++++---------- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 ++++++---- drivers/net/wireless/rt2x00/rt2x00queue.c | 8 ++------ drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 0b41845d9543..ae31581372c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -66,6 +66,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, txdesc->key_idx = hw_key->hw_key_idx; txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); + txdesc->iv_len = hw_key->iv_len; if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags); @@ -103,34 +104,32 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, return overhead; } -void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len) +void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); - if (unlikely(!iv_len)) + if (unlikely(!txdesc->iv_len)) return; /* Copy IV/EIV data */ - memcpy(skbdesc->iv, skb->data + header_length, iv_len); + memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len); } -void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len) +void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); - if (unlikely(!iv_len)) + if (unlikely(!txdesc->iv_len)) return; /* Copy IV/EIV data */ - memcpy(skbdesc->iv, skb->data + header_length, iv_len); + memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len); /* Move ieee80211 header */ - memmove(skb->data + iv_len, skb->data, header_length); + memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset); /* Pull buffer to correct size */ - skb_pull(skb, iv_len); + skb_pull(skb, txdesc->iv_len); /* IV/EIV data has officially be stripped */ skbdesc->flags |= FRAME_DESC_IV_STRIPPED; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index a631613177d0..af3c47bd43bd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -295,8 +295,10 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc); unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); -void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len); -void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len); +void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, + struct txentry_desc *txdesc); +void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, + struct txentry_desc *txdesc); void rt2x00crypto_tx_insert_iv(struct sk_buff *skb); void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, unsigned int header_length, @@ -319,12 +321,12 @@ static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev } static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, - unsigned int iv_len) + struct txentry_desc *txdesc) { } static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, - unsigned int iv_len) + struct txentry_desc *txdesc) { } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a5664bd8493e..6f78915b364c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -368,7 +368,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct txentry_desc txdesc; struct skb_frame_desc *skbdesc; - unsigned int iv_len = 0; u8 rate_idx, rate_flags; if (unlikely(rt2x00queue_full(queue))) @@ -390,9 +389,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) entry->skb = skb; rt2x00queue_create_tx_descriptor(entry, &txdesc); - if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL) - iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; - /* * All information is retrieved from the skb->cb array, * now we should claim ownership of the driver part of that @@ -415,9 +411,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) - rt2x00crypto_tx_copy_iv(skb, iv_len); + rt2x00crypto_tx_copy_iv(skb, &txdesc); else - rt2x00crypto_tx_remove_iv(skb, iv_len); + rt2x00crypto_tx_remove_iv(skb, &txdesc); } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 97e2ab08f080..e3bfd73e319b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -280,6 +280,7 @@ enum txentry_desc_flags { * @cipher: Cipher type used for encryption. * @key_idx: Key index used for encryption. * @iv_offset: Position where IV should be inserted by hardware. + * @iv_len: Length of IV data. */ struct txentry_desc { unsigned long flags; @@ -302,6 +303,7 @@ struct txentry_desc { enum cipher cipher; u16 key_idx; u16 iv_offset; + u16 iv_len; }; /** -- cgit v1.2.3 From 9f1661718c7fcf82e25c6aed20b729ee372d9d65 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 26 Apr 2009 16:08:50 +0200 Subject: rt2x00: Add support for L2 padding during TX/RX Some hardware require L2 padding between header and payload because both must be aligned to a 4-byte boundary. This hardware also is easier during the RX path since we no longer need to move the entire payload but rather only the header to remove the padding (mac80211 only wants the payload to be 4-byte aligned). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 10 +++++ drivers/net/wireless/rt2x00/rt2x00crypto.c | 68 ++++++++++++++++++------------ drivers/net/wireless/rt2x00/rt2x00dev.c | 33 ++++++++------- drivers/net/wireless/rt2x00/rt2x00lib.h | 27 +++++++++--- drivers/net/wireless/rt2x00/rt2x00queue.c | 39 +++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.h | 14 +++++- 6 files changed, 143 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 0be395528261..7c5cbb192a6c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -102,6 +102,15 @@ #define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate)) #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) +/* + * Determine the alignment requirement, + * to make sure the 802.11 payload is padded to a 4-byte boundrary + * we must determine the address of the payload and calculate the + * amount of bytes needed to move the data. + */ +#define ALIGN_SIZE(__skb, __header) \ + ( ((unsigned long)((__skb)->data + (__header))) & 3 ) + /* * Standard timing and size defines. * These values should follow the ieee80211 specifications. @@ -590,6 +599,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_SCHEDULED, DRIVER_REQUIRE_DMA, DRIVER_REQUIRE_COPY_IV, + DRIVER_REQUIRE_L2PAD, /* * Driver features diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index ae31581372c0..57ab42cfed34 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -65,7 +65,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); txdesc->key_idx = hw_key->hw_key_idx; - txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); + txdesc->iv_offset = txdesc->header_length; txdesc->iv_len = hw_key->iv_len; if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) @@ -132,17 +132,16 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) skb_pull(skb, txdesc->iv_len); /* IV/EIV data has officially be stripped */ - skbdesc->flags |= FRAME_DESC_IV_STRIPPED; + skbdesc->flags |= SKBDESC_IV_STRIPPED; } -void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) +void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); const unsigned int iv_len = ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); - if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) + if (!(skbdesc->flags & SKBDESC_IV_STRIPPED)) return; skb_push(skb, iv_len); @@ -154,14 +153,15 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) memcpy(skb->data + header_length, skbdesc->iv, iv_len); /* IV/EIV data has returned into the frame */ - skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; + skbdesc->flags &= ~SKBDESC_IV_STRIPPED; } -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, +void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc) { unsigned int payload_len = rxdesc->size - header_length; + unsigned int align = ALIGN_SIZE(skb, header_length); unsigned int iv_len; unsigned int icv_len; unsigned int transfer = 0; @@ -191,32 +191,48 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, } /* - * Make room for new data, note that we increase both - * headsize and tailsize when required. The tailsize is - * only needed when ICV data needs to be inserted and - * the padding is smaller than the ICV data. - * When alignment requirements is greater than the - * ICV data we must trim the skb to the correct size - * because we need to remove the extra bytes. + * Make room for new data. There are 2 possibilities + * either the alignment is already present between + * the 802.11 header and payload. In that case we + * we have to move the header less then the iv_len + * since we can use the already available l2pad bytes + * for the iv data. + * When the alignment must be added manually we must + * move the header more then iv_len since we must + * make room for the payload move as well. */ - skb_push(skb, iv_len + align); - if (align < icv_len) - skb_put(skb, icv_len - align); - else if (align > icv_len) - skb_trim(skb, rxdesc->size + iv_len + icv_len); + if (l2pad) { + skb_push(skb, iv_len - align); + skb_put(skb, icv_len); - /* Move ieee80211 header */ - memmove(skb->data + transfer, - skb->data + transfer + iv_len + align, - header_length); - transfer += header_length; + /* Move ieee80211 header */ + memmove(skb->data + transfer, + skb->data + transfer + (iv_len - align), + header_length); + transfer += header_length; + } else { + skb_push(skb, iv_len + align); + if (align < icv_len) + skb_put(skb, icv_len - align); + else if (align > icv_len) + skb_trim(skb, rxdesc->size + iv_len + icv_len); + + /* Move ieee80211 header */ + memmove(skb->data + transfer, + skb->data + transfer + iv_len + align, + header_length); + transfer += header_length; + } /* Copy IV/EIV data */ memcpy(skb->data + transfer, rxdesc->iv, iv_len); transfer += iv_len; - /* Move payload */ - if (align) { + /* + * Move payload for alignment purposes. Note that + * this is only needed when no l2 padding is present. + */ + if (!l2pad) { memmove(skb->data + transfer, skb->data + transfer + align, payload_len); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 5752aaae906b..e15086af7278 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -227,6 +227,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); + unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); u8 rate_idx, rate_flags; /* @@ -234,6 +235,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, */ rt2x00queue_unmap_skb(rt2x00dev, entry->skb); + /* + * Remove L2 padding which was added during + */ + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + rt2x00queue_payload_align(entry->skb, true, header_length); + /* * If the IV/EIV data was stripped from the frame before it was * passed to the hardware, we should now reinsert it again because @@ -241,7 +248,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * frame as it was passed to us. */ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) - rt2x00crypto_tx_insert_iv(entry->skb); + rt2x00crypto_tx_insert_iv(entry->skb, header_length); /* * Send frame to debugfs immediately, after this call is completed @@ -325,7 +332,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct ieee80211_supported_band *sband; const struct rt2x00_rate *rate; unsigned int header_length; - unsigned int align; + bool l2pad; unsigned int i; int idx = -1; @@ -348,12 +355,15 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); + /* Trim buffer to correct size */ + skb_trim(entry->skb, rxdesc.size); + /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - align = ((unsigned long)(entry->skb->data + header_length)) & 3; + l2pad = !!(rxdesc.dev_flags & RXDONE_L2PAD); /* * Hardware might have stripped the IV/EIV/ICV data, @@ -362,18 +372,11 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, * in which case we should reinsert the data into the frame. */ if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && - (rxdesc.flags & RX_FLAG_IV_STRIPPED)) { - rt2x00crypto_rx_insert_iv(entry->skb, align, - header_length, &rxdesc); - } else if (align) { - skb_push(entry->skb, align); - /* Move entire frame in 1 command */ - memmove(entry->skb->data, entry->skb->data + align, - rxdesc.size); - } - - /* Update data pointers, trim buffer to correct size */ - skb_trim(entry->skb, rxdesc.size); + (rxdesc.flags & RX_FLAG_IV_STRIPPED)) + rt2x00crypto_rx_insert_iv(entry->skb, l2pad, header_length, + &rxdesc); + else + rt2x00queue_payload_align(entry->skb, l2pad, header_length); /* * Update RX statistics. diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index af3c47bd43bd..aa284e48d2c2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -112,6 +112,23 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); */ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +/** + * rt2x00queue_payload_align - Align 802.11 payload to 4-byte boundary + * @skb: The skb to align + * @l2pad: Should L2 padding be used + * @header_length: Length of 802.11 header + * + * This function prepares the @skb to be send to the device or mac80211. + * If @l2pad is set to true padding will occur between the 802.11 header + * and payload. Otherwise the padding will be done in front of the 802.11 + * header. + * When @l2pad is set the function will check for the &SKBDESC_L2_PADDED + * flag in &skb_frame_desc. If that flag is set, the padding is removed + * and the flag cleared. Otherwise the padding is added and the flag is set. + */ +void rt2x00queue_payload_align(struct sk_buff *skb, + bool l2pad, unsigned int header_length); + /** * rt2x00queue_write_tx_frame - Write TX frame to hardware * @queue: Queue over which the frame should be send @@ -299,8 +316,8 @@ void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc); void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc); -void rt2x00crypto_tx_insert_iv(struct sk_buff *skb); -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, +void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length); +void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc); #else @@ -330,12 +347,12 @@ static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, { } -static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) +static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, + unsigned int header_length) { } -static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, - unsigned int align, +static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc) { diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 6f78915b364c..bc1742c1d51c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -148,6 +148,35 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) dev_kfree_skb_any(skb); } +void rt2x00queue_payload_align(struct sk_buff *skb, + bool l2pad, unsigned int header_length) +{ + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + unsigned int frame_length = skb->len; + unsigned int align = ALIGN_SIZE(skb, header_length); + + if (!align) + return; + + if (l2pad) { + if (skbdesc->flags & SKBDESC_L2_PADDED) { + /* Remove L2 padding */ + memmove(skb->data + align, skb->data, header_length); + skb_pull(skb, align); + skbdesc->flags &= ~SKBDESC_L2_PADDED; + } else { + /* Add L2 padding */ + skb_push(skb, align); + memmove(skb->data, skb->data + align, header_length); + skbdesc->flags |= SKBDESC_L2_PADDED; + } + } else { + /* Generic payload alignment to 4-byte boundary */ + skb_push(skb, align); + memmove(skb->data, skb->data + align, frame_length); + } +} + static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, struct txentry_desc *txdesc) { @@ -258,6 +287,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, txdesc->cw_max = entry->queue->cw_max; txdesc->aifs = entry->queue->aifs; + /* + * Header and alignment information. + */ + txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); + /* * Check whether this frame is to be acked. */ @@ -416,6 +451,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) rt2x00crypto_tx_remove_iv(skb, &txdesc); } + if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) + rt2x00queue_payload_align(entry->skb, true, + txdesc.header_length); + /* * It could be possible that the queue was corrupted and this * call failed. Since we always return NETDEV_TX_OK to mac80211, diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index e3bfd73e319b..13e0ece176a1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -87,13 +87,16 @@ enum data_queue_qid { * * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX - * @FRAME_DESC_IV_STRIPPED: Frame contained a IV/EIV provided by + * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by * mac80211 but was stripped for processing by the driver. + * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, + * the padded bytes are located between header and payload. */ enum skb_frame_desc_flags { SKBDESC_DMA_MAPPED_RX = 1 << 0, SKBDESC_DMA_MAPPED_TX = 1 << 1, - FRAME_DESC_IV_STRIPPED = 1 << 2, + SKBDESC_IV_STRIPPED = 1 << 2, + SKBDESC_L2_PADDED = 1 << 3 }; /** @@ -148,6 +151,7 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) * @RXDONE_MY_BSS: Does this frame originate from device's BSS. * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. * @RXDONE_CRYPTO_ICV: Driver provided ICV data. + * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary. */ enum rxdone_entry_desc_flags { RXDONE_SIGNAL_PLCP = 1 << 0, @@ -155,6 +159,7 @@ enum rxdone_entry_desc_flags { RXDONE_MY_BSS = 1 << 2, RXDONE_CRYPTO_IV = 1 << 3, RXDONE_CRYPTO_ICV = 1 << 4, + RXDONE_L2PAD = 1 << 5, }; /** @@ -267,6 +272,8 @@ enum txentry_desc_flags { * * @flags: Descriptor flags (See &enum queue_entry_flags). * @queue: Queue identification (See &enum data_queue_qid). + * @header_length: Length of 802.11 header. + * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary. * @length_high: PLCP length high word. * @length_low: PLCP length low word. * @signal: PLCP signal. @@ -287,6 +294,9 @@ struct txentry_desc { enum data_queue_qid queue; + u16 header_length; + u16 l2pad; + u16 length_high; u16 length_low; u16 signal; -- cgit v1.2.3 From 35f00cfcc06bb85e0659f9847400518008d78145 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 26 Apr 2009 16:09:32 +0200 Subject: rt2x00: Implement support for 802.11n Extend rt2x00lib capabilities to support 802.11n, it still lacks aggregation support, but that can be added in the future. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 3 + drivers/net/wireless/rt2x00/Makefile | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 11 ++++ drivers/net/wireless/rt2x00/rt2x00config.c | 5 ++ drivers/net/wireless/rt2x00/rt2x00dev.c | 92 ++++++++++++++++++++++-------- drivers/net/wireless/rt2x00/rt2x00ht.c | 69 ++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00lib.h | 24 ++++++++ drivers/net/wireless/rt2x00/rt2x00queue.c | 1 + drivers/net/wireless/rt2x00/rt2x00queue.h | 39 ++++++++++--- 9 files changed, 211 insertions(+), 34 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2x00ht.c diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index bfc5d9cf716e..4338c93d5b63 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -88,6 +88,9 @@ config RT2X00_LIB_USB config RT2X00_LIB tristate +config RT2X00_LIB_HT + boolean + config RT2X00_LIB_FIRMWARE boolean select FW_LOADER diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index f22d808d8c51..776ec2b8c4e7 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -8,6 +8,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o +rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7c5cbb192a6c..ebe5f276679b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -366,6 +366,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) * for @tx_power_a, @tx_power_bg and @channels. * @channels: Device/chipset specific channel values (See &struct rf_channel). * @channels_info: Additional information for channels (See &struct channel_info). + * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). */ struct hw_mode_spec { unsigned int supported_bands; @@ -379,6 +380,8 @@ struct hw_mode_spec { unsigned int num_channels; const struct rf_channel *channels; const struct channel_info *channels_info; + + struct ieee80211_sta_ht_cap ht; }; /* @@ -616,6 +619,7 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, + CONFIG_CHANNEL_HT40, }; /* @@ -787,6 +791,13 @@ struct rt2x00_dev { */ u8 freq_offset; + /* + * Calibration information (for rt2800usb & rt2800pci). + * [0] -> BW20 + * [1] -> BW40 + */ + u8 calibration[2]; + /* * Low level statistics which will have * to be kept up to date while device is running. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 9c2f5517af2a..863e399d4fa6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -173,6 +173,11 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, libconf.conf = conf; if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { + if (conf_is_ht40(conf)) + __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + else + __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); + memcpy(&libconf.rf, &rt2x00dev->spec.channels[conf->channel->hw_value], sizeof(libconf.rf)); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e15086af7278..f2270845072a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -323,19 +323,54 @@ void rt2x00lib_txdone(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); +static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, + struct rxdone_entry_desc *rxdesc) +{ + struct ieee80211_supported_band *sband; + const struct rt2x00_rate *rate; + unsigned int i; + int signal; + int type; + + /* + * For non-HT rates the MCS value needs to contain the + * actually used rate modulation (CCK or OFDM). + */ + if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) + signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal); + else + signal = rxdesc->signal; + + type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); + + sband = &rt2x00dev->bands[rt2x00dev->curr_band]; + for (i = 0; i < sband->n_bitrates; i++) { + rate = rt2x00_get_rate(sband->bitrates[i].hw_value); + + if (((type == RXDONE_SIGNAL_PLCP) && + (rate->plcp == signal)) || + ((type == RXDONE_SIGNAL_BITRATE) && + (rate->bitrate == signal)) || + ((type == RXDONE_SIGNAL_MCS) && + (rate->mcs == signal))) { + return i; + } + } + + WARNING(rt2x00dev, "Frame received with unrecognized signal, " + "signal=0x%.4x, type=%d.\n", signal, type); + return 0; +} + void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - struct ieee80211_supported_band *sband; - const struct rt2x00_rate *rate; unsigned int header_length; bool l2pad; - unsigned int i; - int idx = -1; - + int rate_idx; /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. @@ -379,26 +414,17 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rt2x00queue_payload_align(entry->skb, l2pad, header_length); /* - * Update RX statistics. + * Check if the frame was received using HT. In that case, + * the rate is the MCS index and should be passed to mac80211 + * directly. Otherwise we need to translate the signal to + * the correct bitrate index. */ - sband = &rt2x00dev->bands[rt2x00dev->curr_band]; - for (i = 0; i < sband->n_bitrates; i++) { - rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - - if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && - (rate->plcp == rxdesc.signal)) || - ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) && - (rate->bitrate == rxdesc.signal))) { - idx = i; - break; - } - } - - if (idx < 0) { - WARNING(rt2x00dev, "Frame received with unrecognized signal," - "signal=0x%.2x, type=%d.\n", rxdesc.signal, - (rxdesc.dev_flags & RXDONE_SIGNAL_MASK)); - idx = 0; + if (rxdesc.rate_mode == RATE_MODE_CCK || + rxdesc.rate_mode == RATE_MODE_OFDM) { + rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); + } else { + rxdesc.flags |= RX_FLAG_HT; + rate_idx = rxdesc.signal; } /* @@ -408,7 +434,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rt2x00debug_update_crypto(rt2x00dev, &rxdesc); rx_status->mactime = rxdesc.timestamp; - rx_status->rate_idx = idx; + rx_status->rate_idx = rate_idx; rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); rx_status->signal = rxdesc.rssi; rx_status->noise = rxdesc.noise; @@ -443,72 +469,84 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = { .bitrate = 10, .ratemask = BIT(0), .plcp = 0x00, + .mcs = RATE_MCS(RATE_MODE_CCK, 0), }, { .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 20, .ratemask = BIT(1), .plcp = 0x01, + .mcs = RATE_MCS(RATE_MODE_CCK, 1), }, { .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 55, .ratemask = BIT(2), .plcp = 0x02, + .mcs = RATE_MCS(RATE_MODE_CCK, 2), }, { .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 110, .ratemask = BIT(3), .plcp = 0x03, + .mcs = RATE_MCS(RATE_MODE_CCK, 3), }, { .flags = DEV_RATE_OFDM, .bitrate = 60, .ratemask = BIT(4), .plcp = 0x0b, + .mcs = RATE_MCS(RATE_MODE_OFDM, 0), }, { .flags = DEV_RATE_OFDM, .bitrate = 90, .ratemask = BIT(5), .plcp = 0x0f, + .mcs = RATE_MCS(RATE_MODE_OFDM, 1), }, { .flags = DEV_RATE_OFDM, .bitrate = 120, .ratemask = BIT(6), .plcp = 0x0a, + .mcs = RATE_MCS(RATE_MODE_OFDM, 2), }, { .flags = DEV_RATE_OFDM, .bitrate = 180, .ratemask = BIT(7), .plcp = 0x0e, + .mcs = RATE_MCS(RATE_MODE_OFDM, 3), }, { .flags = DEV_RATE_OFDM, .bitrate = 240, .ratemask = BIT(8), .plcp = 0x09, + .mcs = RATE_MCS(RATE_MODE_OFDM, 4), }, { .flags = DEV_RATE_OFDM, .bitrate = 360, .ratemask = BIT(9), .plcp = 0x0d, + .mcs = RATE_MCS(RATE_MODE_OFDM, 5), }, { .flags = DEV_RATE_OFDM, .bitrate = 480, .ratemask = BIT(10), .plcp = 0x08, + .mcs = RATE_MCS(RATE_MODE_OFDM, 6), }, { .flags = DEV_RATE_OFDM, .bitrate = 540, .ratemask = BIT(11), .plcp = 0x0c, + .mcs = RATE_MCS(RATE_MODE_OFDM, 7), }, }; @@ -584,6 +622,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; + memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap, + &spec->ht, sizeof(spec->ht)); } /* @@ -600,6 +640,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; + memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap, + &spec->ht, sizeof(spec->ht)); } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c new file mode 100644 index 000000000000..e3cec839e540 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -0,0 +1,69 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + 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; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00lib + Abstract: rt2x00 HT specific routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; + + if (tx_info->control.sta) + txdesc->mpdu_density = + tx_info->control.sta->ht_cap.ampdu_density; + else + txdesc->mpdu_density = 0; + + txdesc->ba_size = 7; /* FIXME: What value is needed? */ + txdesc->stbc = 0; /* FIXME: What value is needed? */ + + txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); + if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + txdesc->mcs |= 0x08; + + /* + * Convert flags + */ + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) + __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); + + /* + * Determine HT Mix/Greenfield rate mode + */ + if (txrate->flags & IEEE80211_TX_RC_MCS) + txdesc->rate_mode = RATE_MODE_HT_MIX; + if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) + txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; + if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); + if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) + __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); +} diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index aa284e48d2c2..ccc7ba4f3181 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -48,6 +48,7 @@ struct rt2x00_rate { unsigned short ratemask; unsigned short plcp; + unsigned short mcs; }; extern const struct rt2x00_rate rt2x00_supported_rates[12]; @@ -57,6 +58,14 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) return &rt2x00_supported_rates[hw_value & 0xff]; } +#define RATE_MCS(__mode, __mcs) \ + ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) + +static inline int rt2x00_get_rate_mcs(const u16 mcs_value) +{ + return (mcs_value & 0x00ff); +} + /* * Radio control handlers. */ @@ -359,6 +368,21 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, } #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +/* + * HT handlers. + */ +#ifdef CONFIG_RT2X00_LIB_HT +void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate); +#else +static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, + struct txentry_desc *txdesc, + const struct rt2x00_rate *hwrate) +{ +} +#endif /* CONFIG_RT2X00_LIB_HT */ + /* * RFkill handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index bc1742c1d51c..44e5b3279ca7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -361,6 +361,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * Apply TX descriptor handling by components */ rt2x00crypto_create_tx_descriptor(entry, txdesc); + rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); rt2x00queue_create_tx_descriptor_seq(entry, txdesc); rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 13e0ece176a1..b5e06347c8a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -35,9 +35,12 @@ * for USB devices this restriction does not apply, but the value of * 2432 makes sense since it is big enough to contain the maximum fragment * size according to the ieee802.11 specs. + * The aggregation size depends on support from the driver, but should + * be something around 3840 bytes. */ -#define DATA_FRAME_SIZE 2432 -#define MGMT_FRAME_SIZE 256 +#define DATA_FRAME_SIZE 2432 +#define MGMT_FRAME_SIZE 256 +#define AGGREGATION_SIZE 3840 /** * DOC: Number of entries per queue @@ -148,18 +151,20 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) * * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. + * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value. * @RXDONE_MY_BSS: Does this frame originate from device's BSS. * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. * @RXDONE_CRYPTO_ICV: Driver provided ICV data. * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary. */ enum rxdone_entry_desc_flags { - RXDONE_SIGNAL_PLCP = 1 << 0, - RXDONE_SIGNAL_BITRATE = 1 << 1, - RXDONE_MY_BSS = 1 << 2, - RXDONE_CRYPTO_IV = 1 << 3, - RXDONE_CRYPTO_ICV = 1 << 4, - RXDONE_L2PAD = 1 << 5, + RXDONE_SIGNAL_PLCP = BIT(0), + RXDONE_SIGNAL_BITRATE = BIT(1), + RXDONE_SIGNAL_MCS = BIT(2), + RXDONE_MY_BSS = BIT(3), + RXDONE_CRYPTO_IV = BIT(4), + RXDONE_CRYPTO_ICV = BIT(5), + RXDONE_L2PAD = BIT(6), }; /** @@ -168,7 +173,7 @@ enum rxdone_entry_desc_flags { * from &rxdone_entry_desc to a signal value type. */ #define RXDONE_SIGNAL_MASK \ - ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE ) + ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS ) /** * struct rxdone_entry_desc: RX Entry descriptor @@ -182,6 +187,7 @@ enum rxdone_entry_desc_flags { * @size: Data size of the received frame. * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). + * @rate_mode: Rate mode (See @enum rate_modulation). * @cipher: Cipher type used during decryption. * @cipher_status: Decryption status. * @iv: IV/EIV data used during decryption. @@ -195,6 +201,7 @@ struct rxdone_entry_desc { int size; int flags; int dev_flags; + u16 rate_mode; u8 cipher; u8 cipher_status; @@ -248,6 +255,9 @@ struct txdone_entry_desc { * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared). * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware. * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware. + * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. + * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. + * @ENTRY_TXD_HT_SHORT_GI: Use short GI. */ enum txentry_desc_flags { ENTRY_TXD_RTS_FRAME, @@ -263,6 +273,9 @@ enum txentry_desc_flags { ENTRY_TXD_ENCRYPT_PAIRWISE, ENTRY_TXD_ENCRYPT_IV, ENTRY_TXD_ENCRYPT_MMIC, + ENTRY_TXD_HT_AMPDU, + ENTRY_TXD_HT_BW_40, + ENTRY_TXD_HT_SHORT_GI, }; /** @@ -278,7 +291,11 @@ enum txentry_desc_flags { * @length_low: PLCP length low word. * @signal: PLCP signal. * @service: PLCP service. + * @msc: MCS. + * @stbc: STBC. + * @ba_size: BA size. * @rate_mode: Rate mode (See @enum rate_modulation). + * @mpdu_density: MDPU density. * @retry_limit: Max number of retries. * @aifs: AIFS value. * @ifs: IFS value. @@ -302,7 +319,11 @@ struct txentry_desc { u16 signal; u16 service; + u16 mcs; + u16 stbc; + u16 ba_size; u16 rate_mode; + u16 mpdu_density; short retry_limit; short aifs; -- cgit v1.2.3 From 2516baa63bc7d05a6573a0f584135484ed182a87 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 27 Apr 2009 22:18:10 -0400 Subject: ath5k: correct interrupt storm warning Ben Greear points out that the "too many interrupts" message will never print in the intended case since the interrupt counter will be -1 after the loop. Change it to pre-decrement so it will be 0 on the thousandth iteration. Cc: Ben Greear Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 410fc4cfc4c6..7b80cebffd41 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2505,7 +2505,7 @@ ath5k_intr(int irq, void *dev_id) ath5k_hw_update_mib_counters(ah, &sc->ll_stats); } } - } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); + } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); if (unlikely(!counter)) ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); -- cgit v1.2.3 From 4edf040afc9237aa8cc90bcf54b521ac47d1ed78 Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Thu, 23 Apr 2009 19:36:00 +0200 Subject: mac80211: Fix handling of retry count of NO_ACK frames in minstrel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the retry count zero (total try count = 1) for frames with IEEE80211_TX_CTL_NO_ACK set. Also remove the check for is_multicast_ether_addr in use_low_rate, which is redundant because all multicasts have IEEE80211_TX_CTL_NO_ACK set. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 3824990d340b..5196006b35e0 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -80,8 +80,7 @@ use_low_rate(struct sk_buff *skb) fc = le16_to_cpu(hdr->frame_control); return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || - (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1)); + (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA); } @@ -245,7 +244,10 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, if (!sta || !mi || use_low_rate(skb)) { ar[0].idx = rate_lowest_index(sband, sta); - ar[0].count = mp->max_retry; + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + ar[0].count = 1; + else + ar[0].count = mp->max_retry; return; } -- cgit v1.2.3 From 922368414e5700d1ed51510e54137359297d78e7 Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Thu, 23 Apr 2009 20:06:06 +0200 Subject: mac80211: Fix handling of retry count of NO_ACK frames in PID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make PID check for IEEE80211_TX_CTL_NO_ACK instead of is_multicast_ether_addr when determining whether to use the lowest rate, and set the retry count to 0 (total try count = 1) if IEEE80211_TX_CTL_NO_ACK is set. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_algo.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index b16801cde06f..2b33e3a7ee7d 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -289,13 +289,15 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, info->control.rates[0].count = txrc->hw->conf.short_frame_max_tx_count; - /* Send management frames and broadcast/multicast data using lowest - * rate. */ + /* Send management frames and NO_ACK data using lowest rate. */ fc = le16_to_cpu(hdr->frame_control); if (!sta || !spinfo || (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1)) { + info->flags & IEEE80211_TX_CTL_NO_ACK) { info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + info->control.rates[0].count = 1; + return; } -- cgit v1.2.3 From 514d65c18ee3595f7f9c9132895ed449f911ecd4 Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Thu, 23 Apr 2009 19:36:08 +0200 Subject: iwlwifi: Fix handling of retry count of NO_ACK frames in iwl-{3945|agn}-rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make iwl-{3945|agn}-rs check for IEEE80211_TX_CTL_NO_ACK instead of is_multicast_ether_addr when determining whether to use the lowest rate, and set the retry count to 0 (total try count = 1) if IEEE80211_TX_CTL_NO_ACK is set. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index f63a9c5ba262..814afaf6d10b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -683,11 +683,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, if (sta) rate_mask = sta->supp_rates[sband->band]; - /* Send management frames and broadcast/multicast data using lowest - * rate. */ + /* Send management frames and NO_ACK data using lowest rate. */ fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1) || + info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !priv_sta) { IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); if (!rate_mask) @@ -696,6 +695,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, else info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + info->control.rates[0].count = 1; return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3504279c7586..29d38b938f38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -172,7 +172,7 @@ struct iwl_lq_sta { }; static void rs_rate_scale_perform(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, + struct sk_buff *skb, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta); static void rs_fill_link_cmd(const struct iwl_priv *priv, @@ -829,7 +829,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); if (!ieee80211_is_data(hdr->frame_control) || - is_multicast_ether_addr(hdr->addr1)) + info->flags & IEEE80211_TX_CTL_NO_ACK) return; /* This packet was aggregated but doesn't carry rate scale info */ @@ -995,7 +995,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) - rs_rate_scale_perform(priv, hdr, sta, lq_sta); + rs_rate_scale_perform(priv, skb, sta, lq_sta); out: return; } @@ -1975,12 +1975,14 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) * Do rate scaling and search for new modulation mode. */ static void rs_rate_scale_perform(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, + struct sk_buff *skb, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta) { struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; int low = IWL_RATE_INVALID; int high = IWL_RATE_INVALID; int index; @@ -2006,11 +2008,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); - /* Send management frames and broadcast/multicast data using - * lowest rate. */ + /* Send management frames and NO_ACK data using lowest rate. */ /* TODO: this could probably be improved.. */ if (!ieee80211_is_data(hdr->frame_control) || - is_multicast_ether_addr(hdr->addr1)) + info->flags & IEEE80211_TX_CTL_NO_ACK) return; if (!sta || !lq_sta) @@ -2450,16 +2451,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, if (sta) mask_bit = sta->supp_rates[sband->band]; - /* Send management frames and broadcast/multicast data using lowest - * rate. */ + /* Send management frames and NO_ACK data using lowest rate. */ if (!ieee80211_is_data(hdr->frame_control) || - is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) { + info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) { if (!mask_bit) info->control.rates[0].idx = rate_lowest_index(sband, NULL); else info->control.rates[0].idx = rate_lowest_index(sband, sta); + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + info->control.rates[0].count = 1; return; } -- cgit v1.2.3 From 97d3f458a1e3350dfcbdc3b6aefa75d20d59ee17 Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Thu, 23 Apr 2009 19:36:11 +0200 Subject: ath9k: Fix handling of retry count of NO_ACK frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check for IEEE80211_TX_CTL_NO_ACK instead of is_multicast_ether_addr when determining whether to use lowest rate without retries. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 8f3cf10f65c4..e526dbce57d1 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1568,12 +1568,13 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ath_rate_priv *ath_rc_priv = priv_sta; __le16 fc = hdr->frame_control; - /* lowest rate for management and multicast/broadcast frames */ - if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta) { + /* lowest rate for management and NO_ACK frames */ + if (!ieee80211_is_data(fc) || + tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) { tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); tx_info->control.rates[0].count = - is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; + (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ? + 1 : ATH_MGT_TXMAXTRY; return; } -- cgit v1.2.3 From 9955151df7c6452cae2ed9649f53d265c91cf155 Mon Sep 17 00:00:00 2001 From: Gábor Stefanik Date: Thu, 23 Apr 2009 19:36:14 +0200 Subject: mac80211: Warn if the rate controller requests retries for a NO_ACK frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To deter future rate scaling algorithm writers from requesting NO_ACK packets to be retried, throw a WARN_ON_ONCE if the algorithm hands us a try count over 1 for NO_ACK packet. Signed-off-by: Gábor Stefanik Signed-off-by: John W. Linville --- net/mac80211/tx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1564a3018cf5..36e8e2de980c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -558,6 +558,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) if (unlikely(!info->control.rates[0].count)) info->control.rates[0].count = 1; + if (WARN_ON_ONCE((info->control.rates[0].count > 1) && + (info->flags & IEEE80211_TX_CTL_NO_ACK))) + info->control.rates[0].count = 1; + if (is_multicast_ether_addr(hdr->addr1)) { /* * XXX: verify the rate is in the basic rateset -- cgit v1.2.3 From 5cff20e6c5a6591a79d3b027af222870f52bb550 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 Apr 2009 12:26:17 +0200 Subject: mac80211: tell driver when idle When we aren't doing anything in mac80211, we can turn off much of the hardware, depending on the driver/hw. Not doing anything, aka being idle, means: * no monitor interfaces * no AP/mesh/wds interfaces * any station interfaces are in DISABLED state * any IBSS interfaces aren't trying to be in a network * we aren't trying to scan By creating a new function that verifies these conditions and calling it at strategic points where the states of those conditions change, we can easily make mac80211 tell the driver when we are idle to save power. Additionally, this fixes a small quirk where a recalculated powersave state is passed to the driver even if the hardware is about to stopped completely. This patch intentionally doesn't touch radio_enabled because that is currently implemented to be a soft rfkill which is inappropriate here when we need to be able to wake up with low latency. One thing I'm not entirely sure about is this: phy0: device no longer idle - in use wlan0: direct probe to AP 00:11:24:91:07:4d try 1 wlan0 direct probe responded wlan0: authenticate with AP 00:11:24:91:07:4d wlan0: authenticated > phy0: device now idle > phy0: device no longer idle - in use wlan0: associate with AP 00:11:24:91:07:4d wlan0: RX AssocResp from 00:11:24:91:07:4d (capab=0x401 status=0 aid=1) wlan0: associated Is it appropriate to go into idle state for a short time when we have just authenticated, but not associated yet? This happens only with the userspace SME, because we cannot really know how long it will wait before asking us to associate. Would going idle after a short timeout be more appropriate? We may need to revisit this, depending on what happens. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 6 ++- include/net/mac80211.h | 8 ++++ net/mac80211/ibss.c | 5 +++ net/mac80211/ieee80211_i.h | 2 + net/mac80211/iface.c | 78 ++++++++++++++++++++++++++++++++++- net/mac80211/mlme.c | 11 +++++ net/mac80211/scan.c | 17 ++++---- 7 files changed, 113 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 8fa6e6ce5705..b1213b6a6b9f 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -553,9 +553,11 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) struct mac80211_hwsim_data *data = hw->priv; struct ieee80211_conf *conf = &hw->conf; - printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d)\n", + printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d idle=%d ps=%d)\n", wiphy_name(hw->wiphy), __func__, - conf->channel->center_freq, conf->radio_enabled); + conf->channel->center_freq, conf->radio_enabled, + !!(conf->flags & IEEE80211_CONF_IDLE), + !!(conf->flags & IEEE80211_CONF_PS)); data->channel = conf->channel; data->radio_enabled = conf->radio_enabled; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7806e22f4ace..38dc1cd10270 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -533,10 +533,16 @@ struct ieee80211_rx_status { * * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only) + * @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set + * the driver should be prepared to handle configuration requests but + * may turn the device off as much as possible. Typically, this flag will + * be set when an interface is set UP but not associated or scanning, but + * it can also be unset in that case when monitor interfaces are active. */ enum ieee80211_conf_flags { IEEE80211_CONF_RADIOTAP = (1<<0), IEEE80211_CONF_PS = (1<<1), + IEEE80211_CONF_IDLE = (1<<2), }; @@ -551,6 +557,7 @@ enum ieee80211_conf_flags { * @IEEE80211_CONF_CHANGE_POWER: the TX power changed * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed + * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), @@ -561,6 +568,7 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_POWER = BIT(5), IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), + IEEE80211_CONF_CHANGE_IDLE = BIT(8), }; static inline __deprecated enum ieee80211_conf_changed diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index a8e23232267e..aa537681f87c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -862,6 +862,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.ssid_len = params->ssid_len; + ieee80211_recalc_idle(sdata->local); + set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); @@ -889,6 +891,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) skb_queue_purge(&sdata->u.ibss.skb_queue); memset(sdata->u.ibss.bssid, 0, ETH_ALEN); + sdata->u.ibss.ssid_len = 0; + + ieee80211_recalc_idle(sdata->local); return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 236ea098bb6c..03e0d22603c8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -985,6 +985,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, enum nl80211_iftype type); void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); +u32 __ieee80211_recalc_idle(struct ieee80211_local *local); +void ieee80211_recalc_idle(struct ieee80211_local *local); /* tx handling */ void ieee80211_clear_tx_pending(struct ieee80211_local *local); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 256fa19e14ec..8b6daf0219f4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -301,6 +301,8 @@ static int ieee80211_open(struct net_device *dev) if (sdata->flags & IEEE80211_SDATA_PROMISC) atomic_inc(&local->iff_promiscs); + hw_reconf_flags |= __ieee80211_recalc_idle(local); + local->open_count++; if (hw_reconf_flags) { ieee80211_hw_config(local, hw_reconf_flags); @@ -548,6 +550,10 @@ static int ieee80211_stop(struct net_device *dev) sdata->bss = NULL; + hw_reconf_flags |= __ieee80211_recalc_idle(local); + + ieee80211_recalc_ps(local, -1); + if (local->open_count == 0) { if (netif_running(local->mdev)) dev_close(local->mdev); @@ -565,8 +571,6 @@ static int ieee80211_stop(struct net_device *dev) hw_reconf_flags = 0; } - ieee80211_recalc_ps(local, -1); - /* do after stop to avoid reconfiguring when we stop anyway */ if (hw_reconf_flags) ieee80211_hw_config(local, hw_reconf_flags); @@ -892,3 +896,73 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) unregister_netdevice(sdata->dev); } } + +static u32 ieee80211_idle_off(struct ieee80211_local *local, + const char *reason) +{ + if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) + return 0; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: device no longer idle - %s\n", + wiphy_name(local->hw.wiphy), reason); +#endif + + local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; + return IEEE80211_CONF_CHANGE_IDLE; +} + +static u32 ieee80211_idle_on(struct ieee80211_local *local) +{ + if (local->hw.conf.flags & IEEE80211_CONF_IDLE) + return 0; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: device now idle\n", + wiphy_name(local->hw.wiphy)); +#endif + + local->hw.conf.flags |= IEEE80211_CONF_IDLE; + return IEEE80211_CONF_CHANGE_IDLE; +} + +u32 __ieee80211_recalc_idle(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + int count = 0; + + if (local->hw_scanning || local->sw_scanning) + return ieee80211_idle_off(local, "scanning"); + + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + /* do not count disabled managed interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.state == IEEE80211_STA_MLME_DISABLED) + continue; + /* do not count unused IBSS interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + !sdata->u.ibss.ssid_len) + continue; + /* count everything else */ + count++; + } + + if (!count) + return ieee80211_idle_on(local); + else + return ieee80211_idle_off(local, "in use"); + + return 0; +} + +void ieee80211_recalc_idle(struct ieee80211_local *local) +{ + u32 chg; + + mutex_lock(&local->iflist_mtx); + chg = __ieee80211_recalc_idle(local); + mutex_unlock(&local->iflist_mtx); + ieee80211_hw_config(local, chg); +} diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2ded4766d014..5509c5aa6beb 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -890,6 +890,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(local); cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); /* @@ -938,6 +939,7 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) " timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(local); cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, @@ -1041,6 +1043,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); + ieee80211_recalc_idle(local); + /* channel(_type) changes are handled by ieee80211_hw_config */ local->oper_channel_type = NL80211_CHAN_NO_HT; @@ -1121,6 +1125,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) " timed out\n", sdata->dev->name, ifmgd->bssid); ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(local); cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid); ieee80211_rx_bss_remove(sdata, ifmgd->bssid, sdata->local->hw.conf.channel->center_freq, @@ -1141,6 +1146,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: mismatch in privacy configuration and " "mixed-cell disabled - abort association\n", sdata->dev->name); ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(local); return; } @@ -1279,6 +1285,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata) if (ifmgd->flags & IEEE80211_STA_EXT_SME) { /* Wait for SME to request association */ ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(sdata->local); } else ieee80211_associate(sdata); } @@ -1515,6 +1522,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (ifmgd->flags & IEEE80211_STA_EXT_SME) { /* Wait for SME to decide what to do next */ ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(local); } return; } @@ -2083,6 +2091,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) } else { ifmgd->assoc_scan_tries = 0; ifmgd->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_recalc_idle(local); } } return -1; @@ -2126,6 +2135,8 @@ static void ieee80211_sta_work(struct work_struct *work) } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request)) return; + ieee80211_recalc_idle(local); + switch (ifmgd->state) { case IEEE80211_STA_MLME_DISABLED: break; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 127bd54e0e38..c99ef8d04d3d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -302,17 +302,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) /* we only have to protect scan_req and hw/sw scan */ mutex_unlock(&local->scan_mtx); - if (was_hw_scan) { - /* - * Somebody might have requested channel change during scan - * that we won't have acted upon, try now. ieee80211_hw_config - * will set the flag based on actual changes. - */ - ieee80211_hw_config(local, 0); - goto done; - } - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + if (was_hw_scan) + goto done; netif_tx_lock_bh(local->mdev); netif_addr_lock(local->mdev); @@ -351,6 +343,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) mutex_unlock(&local->iflist_mtx); done: + ieee80211_recalc_idle(local); ieee80211_mlme_notify_scan_completed(local); ieee80211_ibss_notify_scan_completed(local); ieee80211_mesh_notify_scan_completed(local); @@ -471,6 +464,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, * dependency, so that the scan completed calls * have more locking freedom. */ + + ieee80211_recalc_idle(local); mutex_unlock(&local->scan_mtx); if (local->ops->hw_scan) @@ -487,6 +482,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, } else local->sw_scanning = false; + ieee80211_recalc_idle(local); + local->scan_req = NULL; local->scan_sdata = NULL; } -- cgit v1.2.3 From fb4a3d35a26aa8ef5049f10666e6a163b4c32855 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 29 Apr 2009 13:01:58 +0200 Subject: ath9k: uninline ath9k_io{read,write}32 routines The spin_lock handling uses lots of instructions on some archs. With this patch the size of the ath9k module will be significantly smaller. Signed-off-by: Gabor Juhos Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 33 ++------------------------------- drivers/net/wireless/ath/ath9k/hw.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index d5084ddf44ff..90b6314a8169 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -697,36 +697,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, bool ath9k_wiphy_scanning(struct ath_softc *sc); void ath9k_wiphy_work(struct work_struct *work); -/* - * Read and write, they both share the same lock. We do this to serialize - * reads and writes on Atheros 802.11n PCI devices only. This is required - * as the FIFO on these devices can only accept sanely 2 requests. After - * that the device goes bananas. Serializing the reads/writes prevents this - * from happening. - */ - -static inline void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) -{ - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - iowrite32(val, ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - iowrite32(val, ah->ah_sc->mem + reg_offset); -} - -static inline unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) -{ - u32 val; - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - val = ioread32(ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - val = ioread32(ah->ah_sc->mem + reg_offset); - return val; -} +void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); +unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); #endif /* ATH9K_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ec2a7a40b00d..02f40154e831 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -84,6 +84,38 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) return ath9k_hw_mac_clks(ah, usecs); } +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) +{ + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + iowrite32(val, ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + iowrite32(val, ah->ah_sc->mem + reg_offset); +} + +unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) +{ + u32 val; + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + val = ioread32(ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + val = ioread32(ah->ah_sc->mem + reg_offset); + return val; +} + bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) { int i; -- cgit v1.2.3 From 206eade5a68f7a06adbe7c65e47fd88843ad0546 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Wed, 29 Apr 2009 22:00:23 +0200 Subject: rt2x00: Style fix for interval defines Extra parenthesis are not needed in these 2 cases, all other defines in rt2x00 are done without parenthesis so just fixup these 2 cases. Signed-off-by: Alban Browaeys Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00lib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index ccc7ba4f3181..39e00b3d7811 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -32,8 +32,8 @@ * Interval defines * Both the link tuner as the rfkill will be called once per second. */ -#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) -#define RFKILL_POLL_INTERVAL ( 1000 ) +#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) +#define RFKILL_POLL_INTERVAL 1000 /* * rt2x00_rate: Per rate device information -- cgit v1.2.3 From d53d9e67b55f6a9fc3f836c5c392eb41ce5676f4 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 26 Apr 2009 15:47:48 +0200 Subject: rt2x00: Implement support for rt2800usb Add support for the rt2800usb chipset. Current problems: * Cannot scan 11n AP's * No TX during first minute after association * Broken Hardware encryption Includes various patches from Mattias, Felix, Xose and Axel. Signed-off-by: Mattias Nissler Signed-off-by: Felix Fietkau Signed-off-by: Xose Vazquez Perez Signed-off-by: Axel Kollhofer Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 14 + drivers/net/wireless/rt2x00/Makefile | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 3046 +++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800usb.h | 1934 ++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00.h | 1 + 5 files changed, 4996 insertions(+) create mode 100644 drivers/net/wireless/rt2x00/rt2800usb.c create mode 100644 drivers/net/wireless/rt2x00/rt2800usb.h diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 4338c93d5b63..18ee7d6c4028 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -77,6 +77,20 @@ config RT73USB When compiled as a module, this driver will be called "rt73usb.ko". +config RT2800USB + tristate "Ralink rt2800 (USB) support" + depends on USB + select RT2X00_LIB_USB + select RT2X00_LIB_HT + select RT2X00_LIB_FIRMWARE + select RT2X00_LIB_CRYPTO + select CRC_CCITT + ---help--- + This adds support for rt2800 wireless chipset family. + Supported chips: RT2770, RT2870 & RT3070. + + When compiled as a module, this driver will be called "rt2800usb.ko". + config RT2X00_LIB_PCI tristate select RT2X00_LIB diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 776ec2b8c4e7..bfc7226f0afe 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_RT2500PCI) += rt2500pci.o obj-$(CONFIG_RT61PCI) += rt61pci.o obj-$(CONFIG_RT2500USB) += rt2500usb.o obj-$(CONFIG_RT73USB) += rt73usb.o +obj-$(CONFIG_RT2800USB) += rt2800usb.o diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c new file mode 100644 index 000000000000..812912e508cd --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -0,0 +1,3046 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + 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; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2800usb + Abstract: rt2800usb device specific routines. + Supported chipsets: RT2800U. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rt2x00.h" +#include "rt2x00usb.h" +#include "rt2800usb.h" + +/* + * Allow hardware encryption to be disabled. + */ +static int modparam_nohwcrypt = 1; +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +/* + * Register access. + * All access to the CSR registers will go through the methods + * rt2x00usb_register_read and rt2x00usb_register_write. + * BBP and RF register require indirect register access, + * and use the CSR registers BBPCSR and RFCSR to achieve this. + * These indirect registers work with busy bits, + * and we will try maximal REGISTER_BUSY_COUNT times to access + * the register while taking a REGISTER_BUSY_DELAY us delay + * between each attampt. When the busy bit is still set at that time, + * the access attempt is considered to have failed, + * and we will print an error. + * The _lock versions must be used if you already hold the csr_mutex + */ +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RFCSR(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) +#define WAIT_FOR_MCU(__dev, __reg) \ + rt2x00usb_regbusy_read((__dev), H2M_MAILBOX_CSR, \ + H2M_MAILBOX_CSR_OWNER, (__reg)) + +static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); + rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_BBP(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rfcsr_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rfcsr_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RFCSR becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ + if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); + rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); + rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); + + WAIT_FOR_RFCSR(rt2x00dev, ®); + } + + *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u32 value) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); + rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); + rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); + + rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1) +{ + u32 reg; + + mutex_lock(&rt2x00dev->csr_mutex); + + /* + * Wait until the MCU becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_MCU(rt2x00dev, ®)) { + rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); + rt2x00usb_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); + + reg = 0; + rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); + rt2x00usb_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +} + +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +static const struct rt2x00debug rt2800usb_rt2x00debug = { + .owner = THIS_MODULE, + .csr = { + .read = rt2x00usb_register_read, + .write = rt2x00usb_register_write, + .flags = RT2X00DEBUGFS_OFFSET, + .word_base = CSR_REG_BASE, + .word_size = sizeof(u32), + .word_count = CSR_REG_SIZE / sizeof(u32), + }, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, + .word_base = EEPROM_BASE, + .word_size = sizeof(u16), + .word_count = EEPROM_SIZE / sizeof(u16), + }, + .bbp = { + .read = rt2800usb_bbp_read, + .write = rt2800usb_bbp_write, + .word_base = BBP_BASE, + .word_size = sizeof(u8), + .word_count = BBP_SIZE / sizeof(u8), + }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2800usb_rf_write, + .word_base = RF_BASE, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, +}; +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + +#ifdef CONFIG_RT2X00_LIB_RFKILL +static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); +} +#else +#define rt2800usb_rfkill_poll NULL +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + +#ifdef CONFIG_RT2X00_LIB_LEDS +static void rt2800usb_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int bg_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + unsigned int polarity = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_POLARITY); + unsigned int ledmode = + rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, + EEPROM_FREQ_LED_MODE); + + if (led->type == LED_TYPE_RADIO) { + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? 0x20 : 0); + } else if (led->type == LED_TYPE_ASSOC) { + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * The specs tell us the following levels: + * 0, 1 ,3, 7, 15, 31 + * to determine the level in a simple way we can simply + * work with bitshifting: + * (1 << level) - 1 + */ + rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + (1 << brightness / (LED_FULL / 6)) - 1, + polarity); + } +} + +static int rt2800usb_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00usb_register_read(led->rt2x00dev, LED_CFG, ®); + rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); + rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); + rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); + rt2x00usb_register_write(led->rt2x00dev, LED_CFG, reg); + + return 0; +} + +static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type) +{ + led->rt2x00dev = rt2x00dev; + led->type = type; + led->led_dev.brightness_set = rt2800usb_brightness_set; + led->led_dev.blink_set = rt2800usb_blink_set; + led->flags = LED_INITIALIZED; +} +#endif /* CONFIG_RT2X00_LIB_LEDS */ + +/* + * Configuration handlers. + */ +static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct mac_wcid_entry wcid_entry; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + u32 reg; + + offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, + (crypto->cmd == SET_KEY) * crypto->bssidx); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + + memset(&iveiv_entry, 0, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || + (crypto->cipher == CIPHER_TKIP_NO_MIC) || + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; + rt2x00usb_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + offset = MAC_WCID_ENTRY(key->hw_key_idx); + + memset(&wcid_entry, 0, sizeof(wcid_entry)); + if (crypto->cmd == SET_KEY) + memcpy(&wcid_entry, crypto->address, ETH_ALEN); + rt2x00usb_register_multiwrite(rt2x00dev, offset, + &wcid_entry, sizeof(wcid_entry)); +} + +static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + struct rt2x00_field32 field; + int timeout; + u32 offset; + u32 reg; + + if (crypto->cmd == SET_KEY) { + key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = SHARED_KEY_ENTRY(key->hw_key_idx); + timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + offset, &key_entry, + sizeof(key_entry), + timeout); + } + + /* + * The cipher types are stored over multiple registers + * starting with SHARED_KEY_MODE_BASE each word will have + * 32 bits and contains the cipher types for 2 bssidx each. + * Using the correct defines correctly will cause overhead, + * so just calculate the correct offset. + */ + field.bit_offset = 4 * (key->hw_key_idx % 8); + field.bit_mask = 0x7 << field.bit_offset; + + offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + /* + * Update WCID information + */ + rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ + struct hw_key_entry key_entry; + int timeout; + u32 offset; + + if (crypto->cmd == SET_KEY) { + /* + * 1 pairwise key is possible per AID, this means that the AID + * equals our hw_key_idx. Make sure the WCID starts _after_ the + * last possible shared key entry. + */ + if (crypto->aid > (256 - 32)) + return -ENOSPC; + + key->hw_key_idx = 32 + crypto->aid; + + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, + sizeof(key_entry.tx_mic)); + memcpy(key_entry.rx_mic, crypto->rx_mic, + sizeof(key_entry.rx_mic)); + + offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); + timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + offset, &key_entry, + sizeof(key_entry), + timeout); + } + + /* + * Update WCID information + */ + rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); + + return 0; +} + +static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00usb_register_read(rt2x00dev, RX_FILTER_CFG, ®); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, + !(filter_flags & FIF_CONTROL)); + rt2x00usb_register_write(rt2x00dev, RX_FILTER_CFG, reg); +} + +static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) +{ + unsigned int beacon_base; + u32 reg; + + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00usb_register_write(rt2x00dev, beacon_base, 0); + + /* + * Enable synchronisation. + */ + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } + + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); + + rt2x00usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, + conf->mac, sizeof(conf->mac)); + } + + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); + rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); + conf->bssid[1] = cpu_to_le32(reg); + + rt2x00usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, + conf->bssid, sizeof(conf->bssid)); + } +} + +static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, + DIV_ROUND_UP(erp->ack_timeout, erp->slot_time)); + rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, + !!erp->short_preamble); + rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, + !!erp->short_preamble); + rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, + erp->cts_protection ? 2 : 0); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, + erp->basic_rates); + rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); + rt2x00usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, XIFS_TIME_CFG, ®); + rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); + rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); + rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg); +} + +static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, + struct antenna_setup *ant) +{ + u8 r1; + u8 r3; + + rt2800usb_bbp_read(rt2x00dev, 1, &r1); + rt2800usb_bbp_read(rt2x00dev, 3, &r3); + + /* + * Configure the TX antenna. + */ + switch ((int)ant->tx) { + case 1: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); + break; + case 3: + /* Do nothing */ + break; + } + + /* + * Configure the RX antenna. + */ + switch ((int)ant->rx) { + case 1: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); + break; + case 3: + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); + break; + } + + rt2800usb_bbp_write(rt2x00dev, 3, r3); + rt2800usb_bbp_write(rt2x00dev, 1, r1); +} + +static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u16 eeprom; + short lna_gain; + + if (libconf->rf.channel <= 14) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); + } else if (libconf->rf.channel <= 64) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); + } else { + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); + } + + rt2x00dev->lna_gain = lna_gain; +} + +static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); + + if (rt2x00dev->default_ant.tx == 1) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); + + if (rt2x00dev->default_ant.rx == 1) { + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + } else if (rt2x00dev->default_ant.rx == 2) + rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); + + if (rf->channel > 14) { + /* + * When TX power is below 0, we should increase it by 7 to + * make it a positive value (Minumum value is -7). + * However this means that values between 0 and 7 have + * double meaning, and we should set a 7DBm boost flag. + */ + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, + (info->tx_power1 >= 0)); + + if (info->tx_power1 < 0) + info->tx_power1 += 7; + + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power1)); + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, + (info->tx_power2 >= 0)); + + if (info->tx_power2 < 0) + info->tx_power2 += 7; + + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, + TXPOWER_A_TO_DEV(info->tx_power2)); + } else { + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, + TXPOWER_G_TO_DEV(info->tx_power2)); + } + + rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(200); + + rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); +} + +static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u8 rfcsr; + + rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf1); + rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf3); + + rt2800usb_rfcsr_read(rt2x00dev, 6, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); + rt2800usb_rfcsr_write(rt2x00dev, 6, rfcsr); + + rt2800usb_rfcsr_read(rt2x00dev, 12, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, + TXPOWER_G_TO_DEV(info->tx_power1)); + rt2800usb_rfcsr_write(rt2x00dev, 12, rfcsr); + + rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); + rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); + + rt2800usb_rfcsr_write(rt2x00dev, 24, + rt2x00dev->calibration[conf_is_ht40(conf)]); + + rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); + rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); +} + +static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + u32 reg; + unsigned int tx_pin; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info); + else + rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info); + + /* + * Change BBP settings + */ + rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800usb_bbp_write(rt2x00dev, 86, 0); + + if (rf->channel <= 14) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { + rt2800usb_bbp_write(rt2x00dev, 82, 0x62); + rt2800usb_bbp_write(rt2x00dev, 75, 0x46); + } else { + rt2800usb_bbp_write(rt2x00dev, 82, 0x84); + rt2800usb_bbp_write(rt2x00dev, 75, 0x50); + } + } else { + rt2800usb_bbp_write(rt2x00dev, 82, 0xf2); + + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) + rt2800usb_bbp_write(rt2x00dev, 75, 0x46); + else + rt2800usb_bbp_write(rt2x00dev, 75, 0x50); + } + + rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, ®); + rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); + rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); + rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg); + + tx_pin = 0; + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.tx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); + } + + /* Turn on unused PA or LNA when not using 1T or 1R */ + if (rt2x00dev->default_ant.rx != 1) { + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + } + + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); + + rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + rt2800usb_bbp_read(rt2x00dev, 3, &bbp); + rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); + rt2800usb_bbp_write(rt2x00dev, 3, bbp); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + if (conf_is_ht40(conf)) { + rt2800usb_bbp_write(rt2x00dev, 69, 0x1a); + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 73, 0x16); + } else { + rt2800usb_bbp_write(rt2x00dev, 69, 0x16); + rt2800usb_bbp_write(rt2x00dev, 70, 0x08); + rt2800usb_bbp_write(rt2x00dev, 73, 0x11); + } + } + + msleep(1); +} + +static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev, + const int txpower) +{ + u32 reg; + u32 value = TXPOWER_G_TO_DEV(txpower); + u8 r1; + + rt2800usb_bbp_read(rt2x00dev, 1, &r1); + rt2x00_set_field8(®, BBP1_TX_POWER, 0); + rt2800usb_bbp_write(rt2x00dev, 1, r1); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_0, ®); + rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_1, ®); + rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); + rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_2, ®); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); + rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_3, ®); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); + rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg); + + rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_4, ®); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); + rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); + rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg); +} + +static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TX_RTY_CFG, ®); + rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, + libconf->conf->short_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, + libconf->conf->long_frame_max_tx_count); + rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); + rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); + rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); + rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg); +} + +static void rt2800usb_config_duration(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, + libconf->conf->beacon_int * 16); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); +} + +static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; + u32 reg; + + if (state == STATE_SLEEP) { + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + + rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, + libconf->conf->listen_interval - 1); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + + rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); + } else { + rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + + rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); + } +} + +static void rt2800usb_config(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags) +{ + /* Always recalculate LNA gain before changing configuration */ + rt2800usb_config_lna_gain(rt2x00dev, libconf); + + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) + rt2800usb_config_channel(rt2x00dev, libconf->conf, + &libconf->rf, &libconf->channel); + if (flags & IEEE80211_CONF_CHANGE_POWER) + rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + rt2800usb_config_retry_limit(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) + rt2800usb_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2800usb_config_ps(rt2x00dev, libconf); +} + +/* + * Link tuning + */ +static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); + qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); +} + +static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev) +{ + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) + return 0x1c + (2 * rt2x00dev->lna_gain); + else + return 0x2e + rt2x00dev->lna_gain; + } + + if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + return 0x32 + (rt2x00dev->lna_gain * 5) / 3; + else + return 0x3a + (rt2x00dev->lna_gain * 5) / 3; +} + +static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, u8 vgc_level) +{ + if (qual->vgc_level != vgc_level) { + rt2800usb_bbp_write(rt2x00dev, 66, vgc_level); + qual->vgc_level = vgc_level; + qual->vgc_level_reg = vgc_level; + } +} + +static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) +{ + rt2800usb_set_vgc(rt2x00dev, qual, + rt2800usb_get_default_vgc(rt2x00dev)); +} + +static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) +{ + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) + return; + + /* + * When RSSI is better then -80 increase VGC level with 0x10 + */ + rt2800usb_set_vgc(rt2x00dev, qual, + rt2800usb_get_default_vgc(rt2x00dev) + + ((qual->rssi > -80) * 0x10)); +} + +/* + * Firmware functions + */ +static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) +{ + return FIRMWARE_RT2870; +} + +static bool rt2800usb_check_crc(const u8 *data, const size_t len) +{ + u16 fw_crc; + u16 crc; + + /* + * The last 2 bytes in the firmware array are the crc checksum itself, + * this means that we should never pass those 2 bytes to the crc + * algorithm. + */ + fw_crc = (data[len - 2] << 8 | data[len - 1]); + + /* + * Use the crc ccitt algorithm. + * This will return the same value as the legacy driver which + * used bit ordering reversion on the both the firmware bytes + * before input input as well as on the final output. + * Obviously using crc ccitt directly is much more efficient. + */ + crc = crc_ccitt(~0, data, len - 2); + + /* + * There is a small difference between the crc-itu-t + bitrev and + * the crc-ccitt crc calculation. In the latter method the 2 bytes + * will be swapped, use swab16 to convert the crc to the correct + * value. + */ + crc = swab16(crc); + + return fw_crc == crc; +} + +static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) +{ + u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; + size_t offset = 0; + + /* + * Firmware files: + * There are 2 variations of the rt2870 firmware. + * a) size: 4kb + * b) size: 8kb + * Note that (b) contains 2 seperate firmware blobs of 4k + * within the file. The first blob is the same firmware as (a), + * but the second blob is for the additional chipsets. + */ + if (len != 4096 && len != 8192) + return FW_BAD_LENGTH; + + /* + * Check if we need the upper 4kb firmware data or not. + */ + if ((len == 4096) && + (chipset != 0x2860) && + (chipset != 0x2872) && + (chipset != 0x3070)) + return FW_BAD_VERSION; + + /* + * 8kb firmware files must be checked as if it were + * 2 seperate firmware files. + */ + while (offset < len) { + if (!rt2800usb_check_crc(data + offset, 4096)) + return FW_BAD_CRC; + + offset += 4096; + } + + return FW_OK; +} + +static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, + const u8 *data, const size_t len) +{ + unsigned int i; + int status; + u32 reg; + u32 offset; + u32 length; + u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; + + /* + * Check which section of the firmware we need. + */ + if ((chipset == 0x2860) || (chipset == 0x2872) || (chipset == 0x3070)) { + offset = 0; + length = 4096; + } else { + offset = 4096; + length = 4096; + } + + /* + * Wait for stable hardware. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; + } + + /* + * Write firmware to device. + */ + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + FIRMWARE_IMAGE_BASE, + data + offset, length, + REGISTER_TIMEOUT32(length)); + + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + + /* + * Send firmware request to device to load firmware, + * we need to specify a long timeout time. + */ + status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, + 0, USB_MODE_FIRMWARE, + REGISTER_TIMEOUT_FIRMWARE); + if (status < 0) { + ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); + return status; + } + + /* + * Wait for device to stabilize. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "PBF system register not ready.\n"); + return -EBUSY; + } + + /* + * Initialize firmware. + */ + rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + return 0; +} + +/* + * Initialization functions. + */ +static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + unsigned int i; + + /* + * Wait untill BBP and RF are ready. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + if (reg && reg != ~0) + break; + msleep(1); + } + + if (i == REGISTER_BUSY_COUNT) { + ERROR(rt2x00dev, "Unstable hardware.\n"); + return -EBUSY; + } + + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); + + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, + USB_MODE_RESET, REGISTER_TIMEOUT); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00usb_register_read(rt2x00dev, BCN_OFFSET0, ®); + rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ + rt2x00usb_register_write(rt2x00dev, BCN_OFFSET0, reg); + + rt2x00usb_register_read(rt2x00dev, BCN_OFFSET1, ®); + rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ + rt2x00usb_register_write(rt2x00dev, BCN_OFFSET1, reg); + + rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); + rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + } else { + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + } + + rt2x00usb_register_read(rt2x00dev, TX_LINK_CFG, ®); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); + rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); + rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); + rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); + rt2x00usb_register_write(rt2x00dev, TX_LINK_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); + rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); + if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && + rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); + rt2x00usb_register_write(rt2x00dev, MAX_LEN_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); + + rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); + rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); + rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); + rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); + rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); + rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); + rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); + rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + rt2x00usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); + + rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, + IEEE80211_MAX_RTS_THRESHOLD); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ + for (i = 0; i < 256; i++) { + u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); + + rt2x00usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); + rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + + for (i = 0; i < 16; i++) + rt2x00usb_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); + + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0); + rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0); + + rt2x00usb_register_read(rt2x00dev, USB_CYC_CFG, ®); + rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); + rt2x00usb_register_write(rt2x00dev, USB_CYC_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG0, ®); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); + rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); + rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG0, reg); + + rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG1, ®); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); + rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); + rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG1, reg); + + rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 3); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); + rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); + rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG0, reg); + + rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG1, ®); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); + rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); + rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG1, reg); + + /* + * We must clear the error counters. + * These registers are cleared on read, + * so we may pass a useless variable to store the value. + */ + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT1, ®); + rt2x00usb_register_read(rt2x00dev, RX_STA_CNT2, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT0, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT1, ®); + rt2x00usb_register_read(rt2x00dev, TX_STA_CNT2, ®); + + return 0; +} + +static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, MAC_STATUS_CFG, ®); + if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) + return 0; + + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u8 value; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800usb_bbp_read(rt2x00dev, 0, &value); + if ((value != 0xff) && (value != 0x00)) + return 0; + udelay(REGISTER_BUSY_DELAY); + } + + ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u16 eeprom; + u8 reg_id; + u8 value; + + if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) || + rt2800usb_wait_bbp_ready(rt2x00dev))) + return -EACCES; + + rt2800usb_bbp_write(rt2x00dev, 65, 0x2c); + rt2800usb_bbp_write(rt2x00dev, 66, 0x38); + rt2800usb_bbp_write(rt2x00dev, 69, 0x12); + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 73, 0x10); + rt2800usb_bbp_write(rt2x00dev, 81, 0x37); + rt2800usb_bbp_write(rt2x00dev, 82, 0x62); + rt2800usb_bbp_write(rt2x00dev, 83, 0x6a); + rt2800usb_bbp_write(rt2x00dev, 84, 0x99); + rt2800usb_bbp_write(rt2x00dev, 86, 0x00); + rt2800usb_bbp_write(rt2x00dev, 91, 0x04); + rt2800usb_bbp_write(rt2x00dev, 92, 0x00); + rt2800usb_bbp_write(rt2x00dev, 103, 0x00); + rt2800usb_bbp_write(rt2x00dev, 105, 0x05); + + if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 69, 0x16); + rt2800usb_bbp_write(rt2x00dev, 73, 0x12); + } + + if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 84, 0x19); + } + + if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); + rt2800usb_bbp_write(rt2x00dev, 84, 0x99); + rt2800usb_bbp_write(rt2x00dev, 105, 0x05); + } + + for (i = 0; i < EEPROM_BBP_SIZE; i++) { + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); + + if (eeprom != 0xffff && eeprom != 0x0000) { + reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); + value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); + rt2800usb_bbp_write(rt2x00dev, reg_id, value); + } + } + + return 0; +} + +static u8 rt2800usb_init_rx_filter(struct rt2x00_dev *rt2x00dev, + bool bw40, u8 rfcsr24, u8 filter_target) +{ + unsigned int i; + u8 bbp; + u8 rfcsr; + u8 passband; + u8 stopband; + u8 overtuned = 0; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); + rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * Set power & frequency of passband test tone + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0); + + for (i = 0; i < 100; i++) { + rt2800usb_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800usb_bbp_read(rt2x00dev, 55, &passband); + if (passband) + break; + } + + /* + * Set power & frequency of stopband test tone + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0x06); + + for (i = 0; i < 100; i++) { + rt2800usb_bbp_write(rt2x00dev, 25, 0x90); + msleep(1); + + rt2800usb_bbp_read(rt2x00dev, 55, &stopband); + + if ((passband - stopband) <= filter_target) { + rfcsr24++; + overtuned += ((passband - stopband) == filter_target); + } else + break; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + } + + rfcsr24 -= !!overtuned; + + rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); + return rfcsr24; +} + +static int rt2800usb_init_rfcsr(struct rt2x00_dev *rt2x00dev) +{ + u8 rfcsr; + u8 bbp; + + if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + return 0; + + /* + * Init RF calibration. + */ + rt2800usb_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); + rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); + msleep(1); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); + rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); + + rt2800usb_rfcsr_write(rt2x00dev, 4, 0x40); + rt2800usb_rfcsr_write(rt2x00dev, 5, 0x03); + rt2800usb_rfcsr_write(rt2x00dev, 6, 0x02); + rt2800usb_rfcsr_write(rt2x00dev, 7, 0x70); + rt2800usb_rfcsr_write(rt2x00dev, 9, 0x0f); + rt2800usb_rfcsr_write(rt2x00dev, 10, 0x71); + rt2800usb_rfcsr_write(rt2x00dev, 11, 0x21); + rt2800usb_rfcsr_write(rt2x00dev, 12, 0x7b); + rt2800usb_rfcsr_write(rt2x00dev, 14, 0x90); + rt2800usb_rfcsr_write(rt2x00dev, 15, 0x58); + rt2800usb_rfcsr_write(rt2x00dev, 16, 0xb3); + rt2800usb_rfcsr_write(rt2x00dev, 17, 0x92); + rt2800usb_rfcsr_write(rt2x00dev, 18, 0x2c); + rt2800usb_rfcsr_write(rt2x00dev, 19, 0x02); + rt2800usb_rfcsr_write(rt2x00dev, 20, 0xba); + rt2800usb_rfcsr_write(rt2x00dev, 21, 0xdb); + rt2800usb_rfcsr_write(rt2x00dev, 24, 0x16); + rt2800usb_rfcsr_write(rt2x00dev, 25, 0x01); + rt2800usb_rfcsr_write(rt2x00dev, 27, 0x03); + rt2800usb_rfcsr_write(rt2x00dev, 29, 0x1f); + + /* + * Set RX Filter calibration for 20MHz and 40MHz + */ + rt2x00dev->calibration[0] = + rt2800usb_init_rx_filter(rt2x00dev, false, 0x07, 0x16); + rt2x00dev->calibration[1] = + rt2800usb_init_rx_filter(rt2x00dev, true, 0x27, 0x19); + + /* + * Set back to initial state + */ + rt2800usb_bbp_write(rt2x00dev, 24, 0); + + rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); + rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); + + /* + * set BBP back to BW20 + */ + rt2800usb_bbp_read(rt2x00dev, 4, &bbp); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); + rt2800usb_bbp_write(rt2x00dev, 4, bbp); + + return 0; +} + +/* + * Device state switch handlers. + */ +static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, + enum dev_state state) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, + (state == STATE_RADIO_RX_ON) || + (state == STATE_RADIO_RX_ON_LINK)); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +} + +static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && + !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) + return 0; + + msleep(1); + } + + ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); + return -EACCES; +} + +static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + u16 word; + + /* + * Initialize all registers. + */ + if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || + rt2800usb_init_registers(rt2x00dev) || + rt2800usb_init_bbp(rt2x00dev) || + rt2800usb_init_rfcsr(rt2x00dev))) + return -EIO; + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + udelay(50); + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + + rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); + rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); + /* Don't use bulk in aggregation when working with USB 1.1 */ + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, + (rt2x00dev->rx->usb_maxpacket == 512)); + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); + /* FIXME: Calculate this value based on Aggregation defines */ + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, 21); + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); + rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); + rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + + /* + * Send signal to firmware during boot time. + */ + rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + + /* + * Initialize LED control + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); + rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + word & 0xff, (word >> 8) & 0xff); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); + rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + word & 0xff, (word >> 8) & 0xff); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); + rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + word & 0xff, (word >> 8) & 0xff); + + return 0; +} + +static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); + rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); + rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); + + rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0); + rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0); + rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, 0); + + /* Wait for DMA, ignore error */ + rt2800usb_wait_wpdma_ready(rt2x00dev); + + rt2x00usb_disable_radio(rt2x00dev); +} + +static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, + enum dev_state state) +{ + rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + + if (state == STATE_AWAKE) + rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + else + rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + + return 0; +} + +static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, + enum dev_state state) +{ + int retval = 0; + + switch (state) { + case STATE_RADIO_ON: + /* + * Before the radio can be enabled, the device first has + * to be woken up. After that it needs a bit of time + * to be fully awake and the radio can be enabled. + */ + rt2800usb_set_state(rt2x00dev, STATE_AWAKE); + msleep(1); + retval = rt2800usb_enable_radio(rt2x00dev); + break; + case STATE_RADIO_OFF: + /* + * After the radio has been disablee, the device should + * be put to sleep for powersaving. + */ + rt2800usb_disable_radio(rt2x00dev); + rt2800usb_set_state(rt2x00dev, STATE_SLEEP); + break; + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_ON_LINK: + case STATE_RADIO_RX_OFF: + case STATE_RADIO_RX_OFF_LINK: + rt2800usb_toggle_rx(rt2x00dev, state); + break; + case STATE_RADIO_IRQ_ON: + case STATE_RADIO_IRQ_OFF: + /* No support, but no error either */ + break; + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt2800usb_set_state(rt2x00dev, state); + break; + default: + retval = -ENOTSUPP; + break; + } + + if (unlikely(retval)) + ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", + state, retval); + + return retval; +} + +/* + * TX descriptor initialization + */ +static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb, + struct txentry_desc *txdesc) +{ + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + __le32 *txi = skbdesc->desc; + __le32 *txwi = &txi[TXINFO_DESC_SIZE / sizeof(__le32)]; + u32 word; + + /* + * Initialize TX Info descriptor + */ + rt2x00_desc_read(txwi, 0, &word); + rt2x00_set_field32(&word, TXWI_W0_FRAG, + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); + rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); + rt2x00_set_field32(&word, TXWI_W0_TS, + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_AMPDU, + test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); + rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs); + rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); + rt2x00_set_field32(&word, TXWI_W0_BW, + test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, + test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); + rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); + rt2x00_desc_write(txwi, 0, word); + + rt2x00_desc_read(txwi, 1, &word); + rt2x00_set_field32(&word, TXWI_W1_ACK, + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_NSEQ, + test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); + rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, + test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? + txdesc->key_idx : 0xff); + rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, + skb->len - txdesc->l2pad); + rt2x00_set_field32(&word, TXWI_W1_PACKETID, + skbdesc->entry->entry_idx); + rt2x00_desc_write(txwi, 1, word); + + /* + * Always write 0 to IV/EIV fields, hardware will insert the IV + * from the IVEIV register when TXINFO_W0_WIV is set to 0. + * When TXINFO_W0_WIV is set to 1 it will use the IV data + * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which + * crypto entry in the registers should be used to encrypt the frame. + */ + _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); + _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); + + /* + * Initialize TX descriptor + */ + rt2x00_desc_read(txi, 0, &word); + rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, + skb->len + TXWI_DESC_SIZE); + rt2x00_set_field32(&word, TXINFO_W0_WIV, + !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); + rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); + rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0); + rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0); + rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST, + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); + rt2x00_desc_write(txi, 0, word); +} + +/* + * TX data initialization + */ +static void rt2800usb_write_beacon(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + unsigned int beacon_base; + u32 reg; + + /* + * Add the descriptor in front of the skb. + */ + skb_push(entry->skb, entry->queue->desc_size); + memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); + skbdesc->desc = entry->skb->data; + + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + /* + * Write entire beacon with descriptor to register. + */ + beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, beacon_base, + entry->skb->data, entry->skb->len, + REGISTER_TIMEOUT32(entry->skb->len)); + + /* + * Clean up the beacon skb. + */ + dev_kfree_skb(entry->skb); + entry->skb = NULL; +} + +static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +{ + int length; + + /* + * The length _must_ include 4 bytes padding, + * it should always be multiple of 4, + * but it must _not_ be a multiple of the USB packet size. + */ + length = roundup(entry->skb->len + 4, 4); + length += (4 * !(length % entry->queue->usb_maxpacket)); + + return length; +} + +static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + const enum data_queue_qid queue) +{ + u32 reg; + + if (queue != QID_BEACON) { + rt2x00usb_kick_tx_queue(rt2x00dev, queue); + return; + } + + rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); + if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); + } +} + +/* + * RX control handlers + */ +static void rt2800usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *rxd = (__le32 *)entry->skb->data; + __le32 *rxwi; + u32 rxd0; + u32 rxwi0; + u32 rxwi1; + u32 rxwi2; + u32 rxwi3; + + /* + * Copy descriptor to the skbdesc->desc buffer, making it safe from + * moving of frame data in rt2x00usb. + */ + memcpy(skbdesc->desc, rxd, skbdesc->desc_len); + rxd = (__le32 *)skbdesc->desc; + rxwi = &rxd[RXD_DESC_SIZE / sizeof(__le32)]; + + /* + * It is now safe to read the descriptor on all architectures. + */ + rt2x00_desc_read(rxd, 0, &rxd0); + rt2x00_desc_read(rxwi, 0, &rxwi0); + rt2x00_desc_read(rxwi, 1, &rxwi1); + rt2x00_desc_read(rxwi, 2, &rxwi2); + rt2x00_desc_read(rxwi, 3, &rxwi3); + + if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; + + if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { + rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); + rxdesc->cipher_status = + rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); + } + + if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { + /* + * Hardware has stripped IV/EIV data from 802.11 frame during + * decryption. Unfortunately the descriptor doesn't contain + * any fields with the EIV/IV data either, so they can't + * be restored by rt2x00lib. + */ + rxdesc->flags |= RX_FLAG_IV_STRIPPED; + + if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) + rxdesc->flags |= RX_FLAG_DECRYPTED; + else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) + rxdesc->flags |= RX_FLAG_MMIC_ERROR; + } + + if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; + + if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) + rxdesc->dev_flags |= RXDONE_L2PAD; + + if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) + rxdesc->flags |= RX_FLAG_SHORT_GI; + + if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) + rxdesc->flags |= RX_FLAG_40MHZ; + + /* + * Detect RX rate, always use MCS as signal type. + */ + rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; + rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); + rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); + + /* + * Mask of 0x8 bit to remove the short preamble flag. + */ + if (rxdesc->rate_mode == RATE_MODE_CCK) + rxdesc->signal &= ~0x8; + + rxdesc->rssi = + (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + + rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; + + rxdesc->noise = + (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + + rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; + + rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); + + /* + * Remove RXWI descriptor from start of buffer. + */ + skb_pull(entry->skb, skbdesc->desc_len); + skb_trim(entry->skb, rxdesc->size); +} + +/* + * Device probe functions. + */ +static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) +{ + u16 word; + u8 *mac; + u8 default_lna_gain; + + rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); + + /* + * Start validation of the data that has been read. + */ + mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); + if (!is_valid_ether_addr(mac)) { + DECLARE_MAC_BUF(macbuf); + + random_ether_addr(mac); + EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); + if (word == 0xffff) { + rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); + rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); + rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); + rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); + } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { + /* + * There is a max of 2 RX streams for RT2870 series + */ + if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) + rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); + rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); + if (word == 0xffff) { + rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); + rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); + rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); + rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); + rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); + EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); + if ((word & 0x00ff) == 0x00ff) { + rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); + rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, + LED_MODE_TXRX_ACTIVITY); + rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); + EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); + } + + /* + * During the LNA validation we are going to use + * lna0 as correct value. Note that EEPROM_LNA + * is never validated. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); + default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); + if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, + default_lna_gain); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); + if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, + default_lna_gain); + rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + + return 0; +} + +static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + u16 value; + u16 eeprom; + + /* + * Read EEPROM word for configuration. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + + /* + * Identify RF chipset. + */ + value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); + rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); + rt2x00_set_chip(rt2x00dev, RT2870, value, reg); + + /* + * The check for rt2860 is not a typo, some rt2870 hardware + * identifies itself as rt2860 in the CSR register. + */ + if ((rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x2860) && + (rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x2870) && + (rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x3070)) { + ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); + return -ENODEV; + } + + if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && + !rt2x00_rf(&rt2x00dev->chip, RF2850) && + !rt2x00_rf(&rt2x00dev->chip, RF2720) && + !rt2x00_rf(&rt2x00dev->chip, RF2750) && + !rt2x00_rf(&rt2x00dev->chip, RF3020) && + !rt2x00_rf(&rt2x00dev->chip, RF2020)) { + ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); + return -ENODEV; + } + + /* + * Identify default antenna configuration. + */ + rt2x00dev->default_ant.tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); + rt2x00dev->default_ant.rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); + + /* + * Read frequency offset and RF programming sequence. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); + + /* + * Read external LNA informations. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + + if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) + __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) + __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + + /* + * Detect if this device has an hardware controlled radio. + */ +#ifdef CONFIG_RT2X00_LIB_RFKILL + if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + + /* + * Store led settings, for correct led behaviour. + */ +#ifdef CONFIG_RT2X00_LIB_LEDS + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, + &rt2x00dev->led_mcu_reg); +#endif /* CONFIG_RT2X00_LIB_LEDS */ + + return 0; +} + +/* + * RF value list for rt2870 + * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) + */ +static const struct rf_channel rf_vals[] = { + { 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b }, + { 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f }, + { 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b }, + { 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f }, + { 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b }, + { 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f }, + { 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b }, + { 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f }, + { 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b }, + { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f }, + { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b }, + { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f }, + { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b }, + { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 }, + { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 }, + { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 }, + { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 }, + { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b }, + { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b }, + { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 }, + { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 }, + { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b }, + { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 }, + { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 }, + { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 }, + + /* 802.11 HyperLan 2 */ + { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, + { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 }, + { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 }, + { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 }, + { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, + { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, + { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, + { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 }, + { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 }, + { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 }, + { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b }, + { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 }, + { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b }, + { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 }, + { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b }, + { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 }, + + /* 802.11 UNII */ + { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 }, + { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 }, + { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f }, + { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f }, + { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 }, + { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 }, + { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 }, + { 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f }, + { 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 }, + { 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 }, + { 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f }, + + /* 802.11 Japan */ + { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b }, + { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 }, + { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b }, + { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 }, + { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 }, + { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b }, + { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 }, +}; + +/* + * RF value list for rt3070 + * Supports: 2.4 GHz + */ +static const struct rf_channel rf_vals_3070[] = { + {1, 241, 2, 2 }, + {2, 241, 2, 7 }, + {3, 242, 2, 2 }, + {4, 242, 2, 7 }, + {5, 243, 2, 2 }, + {6, 243, 2, 7 }, + {7, 244, 2, 2 }, + {8, 244, 2, 7 }, + {9, 245, 2, 2 }, + {10, 245, 2, 7 }, + {11, 246, 2, 2 }, + {12, 246, 2, 7 }, + {13, 247, 2, 2 }, + {14, 248, 2, 4 }, +}; + +static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) +{ + struct hw_mode_spec *spec = &rt2x00dev->spec; + struct channel_info *info; + char *tx_power1; + char *tx_power2; + unsigned int i; + u16 eeprom; + + /* + * Initialize all hw fields. + */ + rt2x00dev->hw->flags = + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; + rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; + + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + + /* + * Initialize HT information. + */ + spec->ht.ht_supported = true; + spec->ht.cap = + IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_TX_STBC | + IEEE80211_HT_CAP_RX_STBC | + IEEE80211_HT_CAP_PSMP_SUPPORT; + spec->ht.ampdu_factor = 3; + spec->ht.ampdu_density = 4; + spec->ht.mcs.tx_params = + IEEE80211_HT_MCS_TX_DEFINED | + IEEE80211_HT_MCS_TX_RX_DIFF | + ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); + + switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { + case 3: + spec->ht.mcs.rx_mask[2] = 0xff; + case 2: + spec->ht.mcs.rx_mask[1] = 0xff; + case 1: + spec->ht.mcs.rx_mask[0] = 0xff; + spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ + break; + } + + /* + * Initialize hw_mode information. + */ + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; + + if (rt2x00_rf(&rt2x00dev->chip, RF2820) || + rt2x00_rf(&rt2x00dev->chip, RF2720)) { + spec->num_channels = 14; + spec->channels = rf_vals; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || + rt2x00_rf(&rt2x00dev->chip, RF2750)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; + spec->num_channels = ARRAY_SIZE(rf_vals); + spec->channels = rf_vals; + } else if (rt2x00_rf(&rt2x00dev->chip, RF3020) || + rt2x00_rf(&rt2x00dev->chip, RF2020)) { + spec->num_channels = ARRAY_SIZE(rf_vals_3070); + spec->channels = rf_vals_3070; + } + + /* + * Create channel information array + */ + info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + spec->channels_info = info; + + tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); + tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + + for (i = 0; i < 14; i++) { + info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); + info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); + } + + if (spec->num_channels > 14) { + tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); + tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); + + for (i = 14; i < spec->num_channels; i++) { + info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); + info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); + } + } + + return 0; +} + +static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) +{ + int retval; + + /* + * Allocate eeprom data. + */ + retval = rt2800usb_validate_eeprom(rt2x00dev); + if (retval) + return retval; + + retval = rt2800usb_init_eeprom(rt2x00dev); + if (retval) + return retval; + + /* + * Initialize hw specifications. + */ + retval = rt2800usb_probe_hw_mode(rt2x00dev); + if (retval) + return retval; + + /* + * This device requires firmware. + */ + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + if (!modparam_nohwcrypt) + __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + + /* + * Set the rssi offset. + */ + rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + + return 0; +} + +/* + * IEEE80211 stack callback functions. + */ +static void rt2800usb_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, + u32 *iv32, u16 *iv16) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct mac_iveiv_entry iveiv_entry; + u32 offset; + + offset = MAC_IVEIV_ENTRY(hw_key_idx); + rt2x00usb_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); + memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); +} + +static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u32 reg; + bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); + + rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); + rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); + rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); + rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); + rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); + rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); + rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); + rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + return 0; +} + +static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, + const struct ieee80211_tx_queue_params *params) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + struct rt2x00_field32 field; + int retval; + u32 reg; + u32 offset; + + /* + * First pass the configuration through rt2x00lib, that will + * update the queue settings and validate the input. After that + * we are free to update the registers based on the value + * in the queue parameter. + */ + retval = rt2x00mac_conf_tx(hw, queue_idx, params); + if (retval) + return retval; + + /* + * We only need to perform additional register initialization + * for WMM queues/ + */ + if (queue_idx >= 4) + return 0; + + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + + /* Update WMM TXOP register */ + offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); + field.bit_offset = (queue_idx & 1) * 16; + field.bit_mask = 0xffff << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, queue->txop); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + /* Update WMM registers */ + field.bit_offset = queue_idx * 4; + field.bit_mask = 0xf << field.bit_offset; + + rt2x00usb_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); + rt2x00_set_field32(®, field, queue->aifs); + rt2x00usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_min); + rt2x00usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); + + rt2x00usb_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); + rt2x00_set_field32(®, field, queue->cw_max); + rt2x00usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); + + /* Update EDCA registers */ + offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); + + rt2x00usb_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); + rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); + rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); + rt2x00usb_register_write(rt2x00dev, offset, reg); + + return 0; +} + +static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u64 tsf; + u32 reg; + + rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW1, ®); + tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; + rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW0, ®); + tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); + + return tsf; +} + +static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .configure_filter = rt2x00mac_configure_filter, + .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, + .get_tkip_seq = rt2800usb_get_tkip_seq, + .set_rts_threshold = rt2800usb_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800usb_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, + .get_tsf = rt2800usb_get_tsf, +}; + +static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { + .probe_hw = rt2800usb_probe_hw, + .get_firmware_name = rt2800usb_get_firmware_name, + .check_firmware = rt2800usb_check_firmware, + .load_firmware = rt2800usb_load_firmware, + .initialize = rt2x00usb_initialize, + .uninitialize = rt2x00usb_uninitialize, + .clear_entry = rt2x00usb_clear_entry, + .set_device_state = rt2800usb_set_device_state, + .rfkill_poll = rt2800usb_rfkill_poll, + .link_stats = rt2800usb_link_stats, + .reset_tuner = rt2800usb_reset_tuner, + .link_tuner = rt2800usb_link_tuner, + .write_tx_desc = rt2800usb_write_tx_desc, + .write_tx_data = rt2x00usb_write_tx_data, + .write_beacon = rt2800usb_write_beacon, + .get_tx_data_len = rt2800usb_get_tx_data_len, + .kick_tx_queue = rt2800usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_tx_queue, + .fill_rxdone = rt2800usb_fill_rxdone, + .config_shared_key = rt2800usb_config_shared_key, + .config_pairwise_key = rt2800usb_config_pairwise_key, + .config_filter = rt2800usb_config_filter, + .config_intf = rt2800usb_config_intf, + .config_erp = rt2800usb_config_erp, + .config_ant = rt2800usb_config_ant, + .config = rt2800usb_config, +}; + +static const struct data_queue_desc rt2800usb_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = AGGREGATION_SIZE, + .desc_size = RXD_DESC_SIZE + RXWI_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb), +}; + +static const struct data_queue_desc rt2800usb_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = AGGREGATION_SIZE, + .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb), +}; + +static const struct data_queue_desc rt2800usb_queue_bcn = { + .entry_num = 8 * BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb), +}; + +static const struct rt2x00_ops rt2800usb_ops = { + .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 8, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .tx_queues = NUM_TX_QUEUES, + .rx = &rt2800usb_queue_rx, + .tx = &rt2800usb_queue_tx, + .bcn = &rt2800usb_queue_bcn, + .lib = &rt2800usb_rt2x00_ops, + .hw = &rt2800usb_mac80211_ops, +#ifdef CONFIG_RT2X00_LIB_DEBUGFS + .debugfs = &rt2800usb_rt2x00debug, +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +}; + +/* + * rt2800usb module information. + */ +static struct usb_device_id rt2800usb_device_table[] = { + /* ??? */ + { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Abocom */ + { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AirTies */ + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Amigo */ + { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Amit */ + { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AzureWave */ + { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Belkin */ + { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Buffalo */ + { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Conceptronic */ + { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Corega */ + { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* D-Link */ + { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Edimax */ + { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* EnGenius */ + { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gemtek */ + { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gigabyte */ + { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Hawking */ + { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* LevelOne */ + { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Linksys */ + { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Logitec */ + { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Motorola */ + { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ovislink */ + { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Pegatron */ + { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Philips */ + { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Planex */ + { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Qcom */ + { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Quanta */ + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ralink */ + { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Samsung */ + { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Siemens */ + { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sitecom */ + { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* SMC */ + { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sparklan */ + { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* U-Media*/ + { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ZCOM */ + { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zinwell */ + { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zyxel */ + { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { 0, } +}; + +MODULE_AUTHOR(DRV_PROJECT); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver."); +MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards"); +MODULE_DEVICE_TABLE(usb, rt2800usb_device_table); +MODULE_FIRMWARE(FIRMWARE_RT2870); +MODULE_LICENSE("GPL"); + +static struct usb_driver rt2800usb_driver = { + .name = KBUILD_MODNAME, + .id_table = rt2800usb_device_table, + .probe = rt2x00usb_probe, + .disconnect = rt2x00usb_disconnect, + .suspend = rt2x00usb_suspend, + .resume = rt2x00usb_resume, +}; + +static int __init rt2800usb_init(void) +{ + return usb_register(&rt2800usb_driver); +} + +static void __exit rt2800usb_exit(void) +{ + usb_deregister(&rt2800usb_driver); +} + +module_init(rt2800usb_init); +module_exit(rt2800usb_exit); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h new file mode 100644 index 000000000000..8e4291d280b3 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -0,0 +1,1934 @@ +/* + Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + 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; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2800usb + Abstract: Data structures and registers for the rt2800usb module. + Supported chipsets: RT2800U. + */ + +#ifndef RT2800USB_H +#define RT2800USB_H + +/* + * RF chip defines. + * + * RF2820 2.4G 2T3R + * RF2850 2.4G/5G 2T3R + * RF2720 2.4G 1T2R + * RF2750 2.4G/5G 1T2R + * RF3020 2.4G 1T1R + * RF2020 2.4G B/G + */ +#define RF2820 0x0001 +#define RF2850 0x0002 +#define RF2720 0x0003 +#define RF2750 0x0004 +#define RF3020 0x0005 +#define RF2020 0x0006 + +/* + * RT2870 version + */ +#define RT2860C_VERSION 0x28600100 +#define RT2860D_VERSION 0x28600101 +#define RT2880E_VERSION 0x28720200 +#define RT2883_VERSION 0x28830300 +#define RT3070_VERSION 0x30700200 + +/* + * Signal information. + * Defaul offset is required for RSSI <-> dBm conversion. + */ +#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ + +/* + * Register layout information. + */ +#define CSR_REG_BASE 0x1000 +#define CSR_REG_SIZE 0x0800 +#define EEPROM_BASE 0x0000 +#define EEPROM_SIZE 0x0110 +#define BBP_BASE 0x0000 +#define BBP_SIZE 0x0080 +#define RF_BASE 0x0004 +#define RF_SIZE 0x0010 + +/* + * Number of TX queues. + */ +#define NUM_TX_QUEUES 4 + +/* + * USB registers. + */ + +/* + * HOST-MCU shared memory + */ +#define HOST_CMD_CSR 0x0404 +#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) + +/* + * INT_SOURCE_CSR: Interrupt source register. + * Write one to clear corresponding bit. + * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c + */ +#define INT_SOURCE_CSR 0x0200 +#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) +#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) +#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) +#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. + */ +#define INT_MASK_CSR 0x0204 +#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) +#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) +#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) +#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) +#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) +#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) +#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) +#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) +#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) +#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) +#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) +#define INT_MASK_CSR_TBTT FIELD32(0x00000800) +#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) +#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) +#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) +#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) +#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) +#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) + +/* + * WPDMA_GLO_CFG + */ +#define WPDMA_GLO_CFG 0x0208 +#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) +#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) +#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) +#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) +#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) +#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) +#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) +#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) +#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) + +/* + * WPDMA_RST_IDX + */ +#define WPDMA_RST_IDX 0x020c +#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) +#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) +#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) +#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) +#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) +#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) +#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) + +/* + * DELAY_INT_CFG + */ +#define DELAY_INT_CFG 0x0210 +#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) +#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) +#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) +#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) +#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) +#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) + +/* + * WMM_AIFSN_CFG: Aifsn for each EDCA AC + * AIFSN0: AC_BE + * AIFSN1: AC_BK + * AIFSN1: AC_VI + * AIFSN1: AC_VO + */ +#define WMM_AIFSN_CFG 0x0214 +#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) +#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) +#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) +#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) + +/* + * WMM_CWMIN_CSR: CWmin for each EDCA AC + * CWMIN0: AC_BE + * CWMIN1: AC_BK + * CWMIN1: AC_VI + * CWMIN1: AC_VO + */ +#define WMM_CWMIN_CFG 0x0218 +#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) +#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) +#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) +#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) + +/* + * WMM_CWMAX_CSR: CWmax for each EDCA AC + * CWMAX0: AC_BE + * CWMAX1: AC_BK + * CWMAX1: AC_VI + * CWMAX1: AC_VO + */ +#define WMM_CWMAX_CFG 0x021c +#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) +#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) +#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) +#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) + +/* + * AC_TXOP0: AC_BK/AC_BE TXOP register + * AC0TXOP: AC_BK in unit of 32us + * AC1TXOP: AC_BE in unit of 32us + */ +#define WMM_TXOP0_CFG 0x0220 +#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) +#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) + +/* + * AC_TXOP1: AC_VO/AC_VI TXOP register + * AC2TXOP: AC_VI in unit of 32us + * AC3TXOP: AC_VO in unit of 32us + */ +#define WMM_TXOP1_CFG 0x0224 +#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) +#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) + +/* + * GPIO_CTRL_CFG: + */ +#define GPIO_CTRL_CFG 0x0228 +#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) +#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) +#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) +#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) +#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) +#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) +#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) +#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) +#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) + +/* + * MCU_CMD_CFG + */ +#define MCU_CMD_CFG 0x022c + +/* + * AC_BK register offsets + */ +#define TX_BASE_PTR0 0x0230 +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c + +/* + * AC_BE register offsets + */ +#define TX_BASE_PTR1 0x0240 +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c + +/* + * AC_VI register offsets + */ +#define TX_BASE_PTR2 0x0250 +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c + +/* + * AC_VO register offsets + */ +#define TX_BASE_PTR3 0x0260 +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c + +/* + * HCCA register offsets + */ +#define TX_BASE_PTR4 0x0270 +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c + +/* + * MGMT register offsets + */ +#define TX_BASE_PTR5 0x0280 +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c + +/* + * RX register offsets + */ +#define RX_BASE_PTR 0x0290 +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + +/* + * USB_DMA_CFG + * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. + * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. + * PHY_CLEAR: phy watch dog enable. + * TX_CLEAR: Clear USB DMA TX path. + * TXOP_HALT: Halt TXOP count down when TX buffer is full. + * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. + * RX_BULK_EN: Enable USB DMA Rx. + * TX_BULK_EN: Enable USB DMA Tx. + * EP_OUT_VALID: OUT endpoint data valid. + * RX_BUSY: USB DMA RX FSM busy. + * TX_BUSY: USB DMA TX FSM busy. + */ +#define USB_DMA_CFG 0x02a0 +#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) +#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) +#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) +#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) +#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) +#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) +#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) +#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) +#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) +#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) +#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) + +/* + * USB_CYC_CFG + */ +#define USB_CYC_CFG 0x02a4 +#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) + +/* + * PBF_SYS_CTRL + * HOST_RAM_WRITE: enable Host program ram write selection + */ +#define PBF_SYS_CTRL 0x0400 +#define PBF_SYS_CTRL_READY FIELD32(0x00000080) +#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040c +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 + +/* + * BCN_OFFSET0: + */ +#define BCN_OFFSET0 0x042c +#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) +#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) +#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) +#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) + +/* + * BCN_OFFSET1: + */ +#define BCN_OFFSET1 0x0430 +#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) +#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) +#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) +#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) + +/* + * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c + +/* + * RF registers + */ +#define RF_CSR_CFG 0x0500 +#define RF_CSR_CFG_DATA FIELD32(0x000000ff) +#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) +#define RF_CSR_CFG_WRITE FIELD32(0x00010000) +#define RF_CSR_CFG_BUSY FIELD32(0x00020000) + +/* + * MAC Control/Status Registers(CSR). + * Some values are set in TU, whereas 1 TU == 1024 us. + */ + +/* + * MAC_CSR0: ASIC revision number. + * ASIC_REV: 0 + * ASIC_VER: 2870 + */ +#define MAC_CSR0 0x1000 +#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) +#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) + +/* + * MAC_SYS_CTRL: + */ +#define MAC_SYS_CTRL 0x1004 +#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) +#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) +#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) +#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) +#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) +#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) +#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) +#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) + +/* + * MAC_ADDR_DW0: STA MAC register 0 + */ +#define MAC_ADDR_DW0 0x1008 +#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_ADDR_DW1: STA MAC register 1 + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK + */ +#define MAC_ADDR_DW1 0x100c +#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) + +/* + * MAC_BSSID_DW0: BSSID register 0 + */ +#define MAC_BSSID_DW0 0x1010 +#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) +#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) +#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) +#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) + +/* + * MAC_BSSID_DW1: BSSID register 1 + * BSS_ID_MASK: + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) + * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) + * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + */ +#define MAC_BSSID_DW1 0x1014 +#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) +#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) +#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) +#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) + +/* + * MAX_LEN_CFG: Maximum frame length register. + * MAX_MPDU: rt2860b max 16k bytes + * MAX_PSDU: Maximum PSDU length + * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 + */ +#define MAX_LEN_CFG 0x1018 +#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) +#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) +#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) +#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) + +/* + * BBP_CSR_CFG: BBP serial control register + * VALUE: Register value to program into BBP + * REG_NUM: Selected BBP register + * READ_CONTROL: 0 write BBP, 1 read BBP + * BUSY: ASIC is busy executing BBP commands + * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks + * BBP_RW_MODE: 0 serial, 1 paralell + */ +#define BBP_CSR_CFG 0x101c +#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) +#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) +#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) +#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) +#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) +#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) + +/* + * RF_CSR_CFG0: RF control register + * REGID_AND_VALUE: Register value to program into RF + * BITWIDTH: Selected RF register + * STANDBYMODE: 0 high when standby, 1 low when standby + * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate + * BUSY: ASIC is busy executing RF commands + */ +#define RF_CSR_CFG0 0x1020 +#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) +#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) +#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) +#define RF_CSR_CFG0_SEL FIELD32(0x40000000) +#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) + +/* + * RF_CSR_CFG1: RF control register + * REGID_AND_VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG1 0x1024 +#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) +#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) + +/* + * RF_CSR_CFG2: RF control register + * VALUE: Register value to program into RF + * RFGAP: Gap between BB_CONTROL_RF and RF_LE + * 0: 3 system clock cycle (37.5usec) + * 1: 5 system clock cycle (62.5usec) + */ +#define RF_CSR_CFG2 0x1028 +#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) + +/* + * LED_CFG: LED control + * color LED's: + * 0: off + * 1: blinking upon TX2 + * 2: periodic slow blinking + * 3: always on + * LED polarity: + * 0: active low + * 1: active high + */ +#define LED_CFG 0x102c +#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) +#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) +#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) +#define LED_CFG_R_LED_MODE FIELD32(0x03000000) +#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) +#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) +#define LED_CFG_LED_POLAR FIELD32(0x40000000) + +/* + * XIFS_TIME_CFG: MAC timing + * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX + * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX + * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX + * when MAC doesn't reference BBP signal BBRXEND + * EIFS: unit 1us + * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer + * + */ +#define XIFS_TIME_CFG 0x1100 +#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) +#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) +#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) +#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) +#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) + +/* + * BKOFF_SLOT_CFG: + */ +#define BKOFF_SLOT_CFG 0x1104 +#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) +#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) + +/* + * NAV_TIME_CFG: + */ +#define NAV_TIME_CFG 0x1108 +#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) +#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) +#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) +#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) + +/* + * CH_TIME_CFG: count as channel busy + */ +#define CH_TIME_CFG 0x110c + +/* + * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us + */ +#define PBF_LIFE_TIMER 0x1110 + +/* + * BCN_TIME_CFG: + * BEACON_INTERVAL: in unit of 1/16 TU + * TSF_TICKING: Enable TSF auto counting + * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + * BEACON_GEN: Enable beacon generator + */ +#define BCN_TIME_CFG 0x1114 +#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) +#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) +#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) +#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) +#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) +#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) + +/* + * TBTT_SYNC_CFG: + */ +#define TBTT_SYNC_CFG 0x1118 + +/* + * TSF_TIMER_DW0: Local lsb TSF timer, read-only + */ +#define TSF_TIMER_DW0 0x111c +#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) + +/* + * TSF_TIMER_DW1: Local msb TSF timer, read-only + */ +#define TSF_TIMER_DW1 0x1120 +#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) + +/* + * TBTT_TIMER: TImer remains till next TBTT, read-only + */ +#define TBTT_TIMER 0x1124 + +/* + * INT_TIMER_CFG: + */ +#define INT_TIMER_CFG 0x1128 + +/* + * INT_TIMER_EN: GP-timer and pre-tbtt Int enable + */ +#define INT_TIMER_EN 0x112c + +/* + * CH_IDLE_STA: channel idle time + */ +#define CH_IDLE_STA 0x1130 + +/* + * CH_BUSY_STA: channel busy time + */ +#define CH_BUSY_STA 0x1134 + +/* + * MAC_STATUS_CFG: + * BBP_RF_BUSY: When set to 0, BBP and RF are stable. + * if 1 or higher one of the 2 registers is busy. + */ +#define MAC_STATUS_CFG 0x1200 +#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) + +/* + * PWR_PIN_CFG: + */ +#define PWR_PIN_CFG 0x1204 + +/* + * AUTOWAKEUP_CFG: Manual power control / status register + * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set + * AUTOWAKE: 0:sleep, 1:awake + */ +#define AUTOWAKEUP_CFG 0x1208 +#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) +#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) +#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) + +/* + * EDCA_AC0_CFG: + */ +#define EDCA_AC0_CFG 0x1300 +#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC1_CFG: + */ +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC2_CFG: + */ +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_AC3_CFG: + */ +#define EDCA_AC3_CFG 0x130c +#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) +#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) +#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) +#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) + +/* + * EDCA_TID_AC_MAP: + */ +#define EDCA_TID_AC_MAP 0x1310 + +/* + * TX_PWR_CFG_0: + */ +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) +#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) +#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) +#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_1: + */ +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) +#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) +#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) +#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) +#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) +#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) +#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) +#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_2: + */ +#define TX_PWR_CFG_2 0x131c +#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) +#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) +#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) +#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) +#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) +#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) +#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) +#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_3: + */ +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) +#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) +#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) +#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) +#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) +#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) + +/* + * TX_PWR_CFG_4: + */ +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) +#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) +#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) +#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) + +/* + * TX_PIN_CFG: + */ +#define TX_PIN_CFG 0x1328 +#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) +#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) +#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) +#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) +#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) +#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) +#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) +#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) +#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) +#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) +#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) +#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) +#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) +#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) +#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) +#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) +#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) +#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) +#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) +#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) + +/* + * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz + */ +#define TX_BAND_CFG 0x132c +#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_A FIELD32(0x00000002) +#define TX_BAND_CFG_BG FIELD32(0x00000004) + +/* + * TX_SW_CFG0: + */ +#define TX_SW_CFG0 0x1330 + +/* + * TX_SW_CFG1: + */ +#define TX_SW_CFG1 0x1334 + +/* + * TX_SW_CFG2: + */ +#define TX_SW_CFG2 0x1338 + +/* + * TXOP_THRES_CFG: + */ +#define TXOP_THRES_CFG 0x133c + +/* + * TXOP_CTRL_CFG: + */ +#define TXOP_CTRL_CFG 0x1340 + +/* + * TX_RTS_CFG: + * RTS_THRES: unit:byte + * RTS_FBK_EN: enable rts rate fallback + */ +#define TX_RTS_CFG 0x1344 +#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) +#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) +#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) + +/* + * TX_TIMEOUT_CFG: + * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us + * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure + * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. + * it is recommended that: + * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + */ +#define TX_TIMEOUT_CFG 0x1348 +#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) +#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) +#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) + +/* + * TX_RTY_CFG: + * SHORT_RTY_LIMIT: short retry limit + * LONG_RTY_LIMIT: long retry limit + * LONG_RTY_THRE: Long retry threshoold + * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * AGG_RTY_MODE: Aggregate MPDU retry mode + * 0:expired by retry limit, 1: expired by mpdu life timer + * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable + */ +#define TX_RTY_CFG 0x134c +#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) +#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) +#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) +#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) +#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) +#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) + +/* + * TX_LINK_CFG: + * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us + * MFB_ENABLE: TX apply remote MFB 1:enable + * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable + * 0: not apply remote remote unsolicit (MFS=7) + * TX_MRQ_EN: MCS request TX enable + * TX_RDG_EN: RDG TX enable + * TX_CF_ACK_EN: Piggyback CF-ACK enable + * REMOTE_MFB: remote MCS feedback + * REMOTE_MFS: remote MCS feedback sequence number + */ +#define TX_LINK_CFG 0x1350 +#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) +#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) +#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) +#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) +#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) +#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) +#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) +#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) + +/* + * HT_FBK_CFG0: + */ +#define HT_FBK_CFG0 0x1354 +#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) +#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) +#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) +#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) +#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) +#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) +#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) +#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) + +/* + * HT_FBK_CFG1: + */ +#define HT_FBK_CFG1 0x1358 +#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) +#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) +#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) +#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) +#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) +#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) +#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) +#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG0: + */ +#define LG_FBK_CFG0 0x135c +#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) +#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) +#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) +#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) +#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) + +/* + * LG_FBK_CFG1: + */ +#define LG_FBK_CFG1 0x1360 +#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) +#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) +#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) +#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) + +/* + * CCK_PROT_CFG: CCK Protection + * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) + * PROTECT_CTRL: Protection control frame type for CCK TX + * 0:none, 1:RTS/CTS, 2:CTS-to-self + * PROTECT_NAV: TXOP protection type for CCK TX + * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect + * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow + * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow + * RTS_TH_EN: RTS threshold enable on CCK TX + */ +#define CCK_PROT_CFG 0x1364 +#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * OFDM_PROT_CFG: OFDM Protection + */ +#define OFDM_PROT_CFG 0x1368 +#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM20_PROT_CFG: MM20 Protection + */ +#define MM20_PROT_CFG 0x136c +#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * MM40_PROT_CFG: MM40 Protection + */ +#define MM40_PROT_CFG 0x1370 +#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF20_PROT_CFG: GF20 Protection + */ +#define GF20_PROT_CFG 0x1374 +#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * GF40_PROT_CFG: GF40 Protection + */ +#define GF40_PROT_CFG 0x1378 +#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) +#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) +#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) +#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) +#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) +#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) +#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) +#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) + +/* + * EXP_CTS_TIME: + */ +#define EXP_CTS_TIME 0x137c + +/* + * EXP_ACK_TIME: + */ +#define EXP_ACK_TIME 0x1380 + +/* + * RX_FILTER_CFG: RX configuration register. + */ +#define RX_FILTER_CFG 0x1400 +#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) +#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) +#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) +#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) +#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) +#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) +#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) +#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) +#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) +#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) +#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) +#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) +#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) +#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) +#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) +#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) +#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) + +/* + * AUTO_RSP_CFG: + * AUTORESPONDER: 0: disable, 1: enable + * BAC_ACK_POLICY: 0:long, 1:short preamble + * CTS_40_MMODE: Response CTS 40MHz duplicate mode + * CTS_40_MREF: Response CTS 40MHz duplicate mode + * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble + * DUAL_CTS_EN: Power bit value in control frame + * ACK_CTS_PSM_BIT:Power bit value in control frame + */ +#define AUTO_RSP_CFG 0x1404 +#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) +#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) +#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) +#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) +#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) +#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) +#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) + +/* + * LEGACY_BASIC_RATE: + */ +#define LEGACY_BASIC_RATE 0x1408 + +/* + * HT_BASIC_RATE: + */ +#define HT_BASIC_RATE 0x140c + +/* + * HT_CTRL_CFG: + */ +#define HT_CTRL_CFG 0x1410 + +/* + * SIFS_COST_CFG: + */ +#define SIFS_COST_CFG 0x1414 + +/* + * RX_PARSER_CFG: + * Set NAV for all received frames + */ +#define RX_PARSER_CFG 0x1418 + +/* + * TX_SEC_CNT0: + */ +#define TX_SEC_CNT0 0x1500 + +/* + * RX_SEC_CNT0: + */ +#define RX_SEC_CNT0 0x1504 + +/* + * CCMP_FC_MUTE: + */ +#define CCMP_FC_MUTE 0x1508 + +/* + * TXOP_HLDR_ADDR0: + */ +#define TXOP_HLDR_ADDR0 0x1600 + +/* + * TXOP_HLDR_ADDR1: + */ +#define TXOP_HLDR_ADDR1 0x1604 + +/* + * TXOP_HLDR_ET: + */ +#define TXOP_HLDR_ET 0x1608 + +/* + * QOS_CFPOLL_RA_DW0: + */ +#define QOS_CFPOLL_RA_DW0 0x160c + +/* + * QOS_CFPOLL_RA_DW1: + */ +#define QOS_CFPOLL_RA_DW1 0x1610 + +/* + * QOS_CFPOLL_QC: + */ +#define QOS_CFPOLL_QC 0x1614 + +/* + * RX_STA_CNT0: RX PLCP error count & RX CRC error count + */ +#define RX_STA_CNT0 0x1700 +#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) +#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT1: RX False CCA count & RX LONG frame count + */ +#define RX_STA_CNT1 0x1704 +#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) +#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) + +/* + * RX_STA_CNT2: + */ +#define RX_STA_CNT2 0x1708 +#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) +#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) + +/* + * TX_STA_CNT0: TX Beacon count + */ +#define TX_STA_CNT0 0x170c +#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) + +/* + * TX_STA_CNT1: TX tx count + */ +#define TX_STA_CNT1 0x1710 +#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) +#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) + +/* + * TX_STA_CNT2: TX tx count + */ +#define TX_STA_CNT2 0x1714 +#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) +#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) + +/* + * TX_STA_FIFO: TX Result for specific PID status fifo register + */ +#define TX_STA_FIFO 0x1718 +#define TX_STA_FIFO_VALID FIELD32(0x00000001) +#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) +#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) +#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) +#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) +#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) +#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) + +/* + * TX_AGG_CNT: Debug counter + */ +#define TX_AGG_CNT 0x171c +#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT0: + */ +#define TX_AGG_CNT0 0x1720 +#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT1: + */ +#define TX_AGG_CNT1 0x1724 +#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT2: + */ +#define TX_AGG_CNT2 0x1728 +#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT3: + */ +#define TX_AGG_CNT3 0x172c +#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT4: + */ +#define TX_AGG_CNT4 0x1730 +#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT5: + */ +#define TX_AGG_CNT5 0x1734 +#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT6: + */ +#define TX_AGG_CNT6 0x1738 +#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) + +/* + * TX_AGG_CNT7: + */ +#define TX_AGG_CNT7 0x173c +#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) +#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) + +/* + * MPDU_DENSITY_CNT: + * TX_ZERO_DEL: TX zero length delimiter count + * RX_ZERO_DEL: RX zero length delimiter count + */ +#define MPDU_DENSITY_CNT 0x1740 +#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) +#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) + +/* + * Security key table memory. + * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry + * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry + * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry + * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry + * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry + * SHARED_KEY_MODE_BASE: 4-byte * 16-entry + */ +#define MAC_WCID_BASE 0x1800 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 +#define MAC_IVEIV_TABLE_BASE 0x6000 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 +#define SHARED_KEY_TABLE_BASE 0x6c00 +#define SHARED_KEY_MODE_BASE 0x7000 + +#define MAC_WCID_ENTRY(__idx) \ + ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) +#define PAIRWISE_KEY_ENTRY(__idx) \ + ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define MAC_IVEIV_ENTRY(__idx) \ + ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) +#define MAC_WCID_ATTR_ENTRY(__idx) \ + ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) +#define SHARED_KEY_ENTRY(__idx) \ + ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) +#define SHARED_KEY_MODE_ENTRY(__idx) \ + ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + +struct mac_wcid_entry { + u8 mac[6]; + u8 reserved[2]; +} __attribute__ ((packed)); + +struct hw_key_entry { + u8 key[16]; + u8 tx_mic[8]; + u8 rx_mic[8]; +} __attribute__ ((packed)); + +struct mac_iveiv_entry { + u8 iv[8]; +} __attribute__ ((packed)); + +/* + * MAC_WCID_ATTRIBUTE: + */ +#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) +#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) +#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) +#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) + +/* + * SHARED_KEY_MODE: + */ +#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) +#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) +#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) +#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) +#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) +#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) +#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) +#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) + +/* + * HOST-MCU communication + */ + +/* + * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. + */ +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) +#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) + +/* + * H2M_MAILBOX_CID: + */ +#define H2M_MAILBOX_CID 0x7014 + +/* + * H2M_MAILBOX_STATUS: + */ +#define H2M_MAILBOX_STATUS 0x701c + +/* + * H2M_INT_SRC: + */ +#define H2M_INT_SRC 0x7024 + +/* + * H2M_BBP_AGENT: + */ +#define H2M_BBP_AGENT 0x7028 + +/* + * MCU_LEDCS: LED control for MCU Mailbox. + */ +#define MCU_LEDCS_LED_MODE FIELD8(0x1f) +#define MCU_LEDCS_POLARITY FIELD8(0x01) + +/* + * HW_CS_CTS_BASE: + * Carrier-sense CTS frame base address. + * It's where mac stores carrier-sense frame for carrier-sense function. + */ +#define HW_CS_CTS_BASE 0x7700 + +/* + * HW_DFS_CTS_BASE: + * FS CTS frame base address. It's where mac stores CTS frame for DFS. + */ +#define HW_DFS_CTS_BASE 0x7780 + +/* + * TXRX control registers - base address 0x3000 + */ + +/* + * TXRX_CSR1: + * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. + */ +#define TXRX_CSR1 0x77d0 + +/* + * HW_DEBUG_SETTING_BASE: + * since NULL frame won't be that long (256 byte) + * We steal 16 tail bytes to save debugging settings + */ +#define HW_DEBUG_SETTING_BASE 0x77f0 +#define HW_DEBUG_SETTING_BASE2 0x7770 + +/* + * HW_BEACON_BASE + * In order to support maximum 8 MBSS and its maximum length + * is 512 bytes for each beacon + * Three section discontinue memory segments will be used. + * 1. The original region for BCN 0~3 + * 2. Extract memory from FCE table for BCN 4~5 + * 3. Extract memory from Pair-wise key table for BCN 6~7 + * It occupied those memory of wcid 238~253 for BCN 6 + * and wcid 222~237 for BCN 7 + * + * IMPORTANT NOTE: Not sure why legacy driver does this, + * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. + */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7a00 +#define HW_BEACON_BASE2 0x7c00 +#define HW_BEACON_BASE3 0x7e00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5dc0 +#define HW_BEACON_BASE7 0x5bc0 + +#define HW_BEACON_OFFSET(__index) \ + ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ + (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) + +/* + * 8051 firmware image. + */ +#define FIRMWARE_RT2870 "rt2870.bin" +#define FIRMWARE_IMAGE_BASE 0x3000 + +/* + * BBP registers. + * The wordsize of the BBP is 8 bits. + */ + +/* + * BBP 1: TX Antenna + */ +#define BBP1_TX_POWER FIELD8(0x07) +#define BBP1_TX_ANTENNA FIELD8(0x18) + +/* + * BBP 3: RX Antenna + */ +#define BBP3_RX_ANTENNA FIELD8(0x18) +#define BBP3_HT40_PLUS FIELD8(0x20) + +/* + * BBP 4: Bandwidth + */ +#define BBP4_TX_BF FIELD8(0x01) +#define BBP4_BANDWIDTH FIELD8(0x18) + +/* + * RFCSR registers + * The wordsize of the RFCSR is 8 bits. + */ + +/* + * RFCSR 6: + */ +#define RFCSR6_R FIELD8(0x03) + +/* + * RFCSR 7: + */ +#define RFCSR7_RF_TUNING FIELD8(0x01) + +/* + * RFCSR 12: + */ +#define RFCSR12_TX_POWER FIELD8(0x1f) + +/* + * RFCSR 22: + */ +#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) + +/* + * RFCSR 23: + */ +#define RFCSR23_FREQ_OFFSET FIELD8(0x7f) + +/* + * RFCSR 30: + */ +#define RFCSR30_RF_CALIBRATION FIELD8(0x80) + +/* + * RF registers + */ + +/* + * RF 2 + */ +#define RF2_ANTENNA_RX2 FIELD32(0x00000040) +#define RF2_ANTENNA_TX1 FIELD32(0x00004000) +#define RF2_ANTENNA_RX1 FIELD32(0x00020000) + +/* + * RF 3 + */ +#define RF3_TXPOWER_G FIELD32(0x00003e00) +#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) +#define RF3_TXPOWER_A FIELD32(0x00003c00) + +/* + * RF 4 + */ +#define RF4_TXPOWER_G FIELD32(0x000007c0) +#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) +#define RF4_TXPOWER_A FIELD32(0x00000780) +#define RF4_FREQ_OFFSET FIELD32(0x001f8000) +#define RF4_HT40 FIELD32(0x00200000) + +/* + * EEPROM content. + * The wordsize of the EEPROM is 16 bits. + */ + +/* + * EEPROM Version + */ +#define EEPROM_VERSION 0x0001 +#define EEPROM_VERSION_FAE FIELD16(0x00ff) +#define EEPROM_VERSION_VERSION FIELD16(0xff00) + +/* + * HW MAC address. + */ +#define EEPROM_MAC_ADDR_0 0x0002 +#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_1 0x0003 +#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) +#define EEPROM_MAC_ADDR_2 0x0004 +#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) +#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) + +/* + * EEPROM ANTENNA config + * RXPATH: 1: 1R, 2: 2R, 3: 3R + * TXPATH: 1: 1T, 2: 2T + */ +#define EEPROM_ANTENNA 0x001a +#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) +#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) +#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) + +/* + * EEPROM NIC config + * CARDBUS_ACCEL: 0 - enable, 1 - disable + */ +#define EEPROM_NIC 0x001b +#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) +#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) +#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) +#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) +#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) +#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) +#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) +#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) +#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) +#define EEPROM_NIC_BW40M_A FIELD16(0x0200) + +/* + * EEPROM frequency + */ +#define EEPROM_FREQ 0x001d +#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) +#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) +#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) + +/* + * EEPROM LED + * POLARITY_RDY_G: Polarity RDY_G setting. + * POLARITY_RDY_A: Polarity RDY_A setting. + * POLARITY_ACT: Polarity ACT setting. + * POLARITY_GPIO_0: Polarity GPIO0 setting. + * POLARITY_GPIO_1: Polarity GPIO1 setting. + * POLARITY_GPIO_2: Polarity GPIO2 setting. + * POLARITY_GPIO_3: Polarity GPIO3 setting. + * POLARITY_GPIO_4: Polarity GPIO4 setting. + * LED_MODE: Led mode. + */ +#define EEPROM_LED1 0x001e +#define EEPROM_LED2 0x001f +#define EEPROM_LED3 0x0020 +#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) +#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) +#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) +#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) +#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) +#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) +#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) +#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) +#define EEPROM_LED_LED_MODE FIELD16(0x1f00) + +/* + * EEPROM LNA + */ +#define EEPROM_LNA 0x0022 +#define EEPROM_LNA_BG FIELD16(0x00ff) +#define EEPROM_LNA_A0 FIELD16(0xff00) + +/* + * EEPROM RSSI BG offset + */ +#define EEPROM_RSSI_BG 0x0023 +#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI BG2 offset + */ +#define EEPROM_RSSI_BG2 0x0024 +#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) + +/* + * EEPROM RSSI A offset + */ +#define EEPROM_RSSI_A 0x0025 +#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) +#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) + +/* + * EEPROM RSSI A2 offset + */ +#define EEPROM_RSSI_A2 0x0026 +#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) +#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) + +/* + * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. + * This is delta in 40MHZ. + * VALUE: Tx Power dalta value (MAX=4) + * TYPE: 1: Plus the delta value, 0: minus the delta value + * TXPOWER: Enable: + */ +#define EEPROM_TXPOWER_DELTA 0x0028 +#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) +#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) +#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) + +/* + * EEPROM TXPOWER 802.11BG + */ +#define EEPROM_TXPOWER_BG1 0x0029 +#define EEPROM_TXPOWER_BG2 0x0030 +#define EEPROM_TXPOWER_BG_SIZE 7 +#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) + +/* + * EEPROM TXPOWER 802.11A + */ +#define EEPROM_TXPOWER_A1 0x003c +#define EEPROM_TXPOWER_A2 0x0053 +#define EEPROM_TXPOWER_A_SIZE 6 +#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) +#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) + +/* + * EEPROM TXpower byrate: 20MHZ power + */ +#define EEPROM_TXPOWER_BYRATE 0x006f + +/* + * EEPROM BBP. + */ +#define EEPROM_BBP_START 0x0078 +#define EEPROM_BBP_SIZE 16 +#define EEPROM_BBP_VALUE FIELD16(0x00ff) +#define EEPROM_BBP_REG_ID FIELD16(0xff00) + +/* + * MCU mailbox commands. + */ +#define MCU_SLEEP 0x30 +#define MCU_WAKEUP 0x31 +#define MCU_RADIO_OFF 0x35 +#define MCU_LED 0x50 +#define MCU_LED_STRENGTH 0x51 +#define MCU_LED_1 0x52 +#define MCU_LED_2 0x53 +#define MCU_LED_3 0x54 +#define MCU_RADAR 0x60 +#define MCU_BOOT_SIGNAL 0x72 +#define MCU_BBP_SIGNAL 0x80 + +/* + * DMA descriptor defines. + */ +#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) +#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) + +/* + * TX descriptor format for TX, PRIO and Beacon Ring. + */ + +/* + * Word0 + */ +#define TXD_W0_SD_PTR0 FIELD32(0xffffffff) + +/* + * Word1 + */ +#define TXD_W1_SD_LEN1 FIELD32(0x00003fff) +#define TXD_W1_LAST_SEC1 FIELD32(0x00004000) +#define TXD_W1_BURST FIELD32(0x00008000) +#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) +#define TXD_W1_LAST_SEC0 FIELD32(0x40000000) +#define TXD_W1_DMA_DONE FIELD32(0x80000000) + +/* + * Word2 + */ +#define TXD_W2_SD_PTR1 FIELD32(0xffffffff) + +/* + * Word3 + * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI + * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. + * 0:MGMT, 1:HCCA 2:EDCA + */ +#define TXD_W3_WIV FIELD32(0x01000000) +#define TXD_W3_QSEL FIELD32(0x06000000) +#define TXD_W3_TCO FIELD32(0x20000000) +#define TXD_W3_UCO FIELD32(0x40000000) +#define TXD_W3_ICO FIELD32(0x80000000) + +/* + * TX Info structure + */ + +/* + * Word0 + * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI + * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. + * 0:MGMT, 1:HCCA 2:EDCA + * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid + * DMA_TX_BURST: used ONLY in USB bulk Aggregation. + * Force USB DMA transmit frame from current selected endpoint + */ +#define TXINFO_W0_USB_DMA_TX_PKT_LEN FIELD32(0x0000ffff) +#define TXINFO_W0_WIV FIELD32(0x01000000) +#define TXINFO_W0_QSEL FIELD32(0x06000000) +#define TXINFO_W0_SW_USE_LAST_ROUND FIELD32(0x08000000) +#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000) +#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) + +/* + * TX WI structure + */ + +/* + * Word0 + * FRAG: 1 To inform TKIP engine this is a fragment. + * MIMO_PS: The remote peer is in dynamic MIMO-PS mode + * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs + * BW: Channel bandwidth 20MHz or 40 MHz + * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED + */ +#define TXWI_W0_FRAG FIELD32(0x00000001) +#define TXWI_W0_MIMO_PS FIELD32(0x00000002) +#define TXWI_W0_CF_ACK FIELD32(0x00000004) +#define TXWI_W0_TS FIELD32(0x00000008) +#define TXWI_W0_AMPDU FIELD32(0x00000010) +#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) +#define TXWI_W0_TX_OP FIELD32(0x00000300) +#define TXWI_W0_MCS FIELD32(0x007f0000) +#define TXWI_W0_BW FIELD32(0x00800000) +#define TXWI_W0_SHORT_GI FIELD32(0x01000000) +#define TXWI_W0_STBC FIELD32(0x06000000) +#define TXWI_W0_IFS FIELD32(0x08000000) +#define TXWI_W0_PHYMODE FIELD32(0xc0000000) + +/* + * Word1 + */ +#define TXWI_W1_ACK FIELD32(0x00000001) +#define TXWI_W1_NSEQ FIELD32(0x00000002) +#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) +#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) +#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define TXWI_W1_PACKETID FIELD32(0xf0000000) + +/* + * Word2 + */ +#define TXWI_W2_IV FIELD32(0xffffffff) + +/* + * Word3 + */ +#define TXWI_W3_EIV FIELD32(0xffffffff) + +/* + * RX descriptor format for RX Ring. + */ + +/* + * Word0 + * UNICAST_TO_ME: This RX frame is unicast to me. + * MULTICAST: This is a multicast frame. + * BROADCAST: This is a broadcast frame. + * MY_BSS: this frame belongs to the same BSSID. + * CRC_ERROR: CRC error. + * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid. + * AMSDU: rx with 802.3 header, not 802.11 header. + */ + +#define RXD_W0_BA FIELD32(0x00000001) +#define RXD_W0_DATA FIELD32(0x00000002) +#define RXD_W0_NULLDATA FIELD32(0x00000004) +#define RXD_W0_FRAG FIELD32(0x00000008) +#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) +#define RXD_W0_MULTICAST FIELD32(0x00000020) +#define RXD_W0_BROADCAST FIELD32(0x00000040) +#define RXD_W0_MY_BSS FIELD32(0x00000080) +#define RXD_W0_CRC_ERROR FIELD32(0x00000100) +#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) +#define RXD_W0_AMSDU FIELD32(0x00000800) +#define RXD_W0_HTC FIELD32(0x00001000) +#define RXD_W0_RSSI FIELD32(0x00002000) +#define RXD_W0_L2PAD FIELD32(0x00004000) +#define RXD_W0_AMPDU FIELD32(0x00008000) +#define RXD_W0_DECRYPTED FIELD32(0x00010000) +#define RXD_W0_PLCP_RSSI FIELD32(0x00020000) +#define RXD_W0_CIPHER_ALG FIELD32(0x00040000) +#define RXD_W0_LAST_AMSDU FIELD32(0x00080000) +#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) + +/* + * RX WI structure + */ + +/* + * Word0 + */ +#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) +#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) +#define RXWI_W0_BSSID FIELD32(0x00001c00) +#define RXWI_W0_UDF FIELD32(0x0000e000) +#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define RXWI_W0_TID FIELD32(0xf0000000) + +/* + * Word1 + */ +#define RXWI_W1_FRAG FIELD32(0x0000000f) +#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) +#define RXWI_W1_MCS FIELD32(0x007f0000) +#define RXWI_W1_BW FIELD32(0x00800000) +#define RXWI_W1_SHORT_GI FIELD32(0x01000000) +#define RXWI_W1_STBC FIELD32(0x06000000) +#define RXWI_W1_PHYMODE FIELD32(0xc0000000) + +/* + * Word2 + */ +#define RXWI_W2_RSSI0 FIELD32(0x000000ff) +#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) +#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) + +/* + * Word3 + */ +#define RXWI_W3_SNR0 FIELD32(0x000000ff) +#define RXWI_W3_SNR1 FIELD32(0x0000ff00) + +/* + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. + */ +#define MIN_G_TXPOWER 0 +#define MIN_A_TXPOWER -7 +#define MAX_G_TXPOWER 31 +#define MAX_A_TXPOWER 15 +#define DEFAULT_TXPOWER 5 + +#define TXPOWER_G_FROM_DEV(__txpower) \ + ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_G_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) + +#define TXPOWER_A_FROM_DEV(__txpower) \ + ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) + +#define TXPOWER_A_TO_DEV(__txpower) \ + clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) + +#endif /* RT2800USB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ebe5f276679b..8d933ee30583 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -147,6 +147,7 @@ struct rt2x00_chip { #define RT2561 0x0302 #define RT2661 0x0401 #define RT2571 0x1300 +#define RT2870 0x1600 u16 rf; u32 rev; -- cgit v1.2.3 From 2f01a1f58889fbfeb68b1bc1b52e4197f3333490 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 29 Apr 2009 23:33:31 +0300 Subject: wl12xx: add driver wl12xx is a driver for TI wl1251 802.11 chipset designed for embedded devices, supporting both SDIO and SPI busses. Currently the driver supports only SPI. Adding support 1253 (the 5 GHz version) should be relatively easy. More information here: http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?contentId=4711&navigationId=12494&templateId=6123 (Collapsed original sequence of pre-merge patches into single commit for initial merge. -- JWL) Signed-off-by: Kalle Valo Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 2 + drivers/net/wireless/wl12xx/Kconfig | 11 + drivers/net/wireless/wl12xx/Makefile | 4 + drivers/net/wireless/wl12xx/acx.c | 689 ++++++++++++++ drivers/net/wireless/wl12xx/acx.h | 1245 +++++++++++++++++++++++++ drivers/net/wireless/wl12xx/boot.c | 295 ++++++ drivers/net/wireless/wl12xx/boot.h | 40 + drivers/net/wireless/wl12xx/cmd.c | 353 ++++++++ drivers/net/wireless/wl12xx/cmd.h | 265 ++++++ drivers/net/wireless/wl12xx/debugfs.c | 508 +++++++++++ drivers/net/wireless/wl12xx/debugfs.h | 33 + drivers/net/wireless/wl12xx/event.c | 127 +++ drivers/net/wireless/wl12xx/event.h | 121 +++ drivers/net/wireless/wl12xx/init.c | 200 ++++ drivers/net/wireless/wl12xx/init.h | 40 + drivers/net/wireless/wl12xx/main.c | 1358 ++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/ps.c | 151 ++++ drivers/net/wireless/wl12xx/ps.h | 36 + drivers/net/wireless/wl12xx/reg.h | 745 +++++++++++++++ drivers/net/wireless/wl12xx/rx.c | 208 +++++ drivers/net/wireless/wl12xx/rx.h | 122 +++ drivers/net/wireless/wl12xx/spi.c | 358 ++++++++ drivers/net/wireless/wl12xx/spi.h | 109 +++ drivers/net/wireless/wl12xx/tx.c | 557 ++++++++++++ drivers/net/wireless/wl12xx/tx.h | 215 +++++ drivers/net/wireless/wl12xx/wl1251.c | 709 +++++++++++++++ drivers/net/wireless/wl12xx/wl1251.h | 165 ++++ drivers/net/wireless/wl12xx/wl12xx.h | 409 +++++++++ drivers/net/wireless/wl12xx/wl12xx_80211.h | 156 ++++ include/linux/spi/wl12xx.h | 31 + 31 files changed, 9263 insertions(+) create mode 100644 drivers/net/wireless/wl12xx/Kconfig create mode 100644 drivers/net/wireless/wl12xx/Makefile create mode 100644 drivers/net/wireless/wl12xx/acx.c create mode 100644 drivers/net/wireless/wl12xx/acx.h create mode 100644 drivers/net/wireless/wl12xx/boot.c create mode 100644 drivers/net/wireless/wl12xx/boot.h create mode 100644 drivers/net/wireless/wl12xx/cmd.c create mode 100644 drivers/net/wireless/wl12xx/cmd.h create mode 100644 drivers/net/wireless/wl12xx/debugfs.c create mode 100644 drivers/net/wireless/wl12xx/debugfs.h create mode 100644 drivers/net/wireless/wl12xx/event.c create mode 100644 drivers/net/wireless/wl12xx/event.h create mode 100644 drivers/net/wireless/wl12xx/init.c create mode 100644 drivers/net/wireless/wl12xx/init.h create mode 100644 drivers/net/wireless/wl12xx/main.c create mode 100644 drivers/net/wireless/wl12xx/ps.c create mode 100644 drivers/net/wireless/wl12xx/ps.h create mode 100644 drivers/net/wireless/wl12xx/reg.h create mode 100644 drivers/net/wireless/wl12xx/rx.c create mode 100644 drivers/net/wireless/wl12xx/rx.h create mode 100644 drivers/net/wireless/wl12xx/spi.c create mode 100644 drivers/net/wireless/wl12xx/spi.h create mode 100644 drivers/net/wireless/wl12xx/tx.c create mode 100644 drivers/net/wireless/wl12xx/tx.h create mode 100644 drivers/net/wireless/wl12xx/wl1251.c create mode 100644 drivers/net/wireless/wl12xx/wl1251.h create mode 100644 drivers/net/wireless/wl12xx/wl12xx.h create mode 100644 drivers/net/wireless/wl12xx/wl12xx_80211.h create mode 100644 include/linux/spi/wl12xx.h diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 2d8434f409b6..91be3e7bf133 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -500,5 +500,6 @@ source "drivers/net/wireless/b43legacy/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" source "drivers/net/wireless/orinoco/Kconfig" +source "drivers/net/wireless/wl12xx/Kconfig" endmenu diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 0625e91b5995..f2b1861e6bcb 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -58,3 +58,5 @@ obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_ATH_COMMON) += ath/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o + +obj-$(CONFIG_WL12XX) += wl12xx/ diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig new file mode 100644 index 000000000000..20a9633569f2 --- /dev/null +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -0,0 +1,11 @@ +config WL12XX + tristate "TI wl1251/wl1271 support" + depends on MAC80211 && WLAN_80211 && SPI_MASTER && EXPERIMENTAL + select FW_LOADER + select CRC7 + ---help--- + This module adds support for wireless adapters based on + TI wl1251/wl1271 chipsets. + + If you choose to build a module, it'll be called wl12xx. Say N if + unsure. diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile new file mode 100644 index 000000000000..d43de27dc54c --- /dev/null +++ b/drivers/net/wireless/wl12xx/Makefile @@ -0,0 +1,4 @@ +wl12xx-objs = main.o spi.o event.o tx.o rx.o \ + ps.o cmd.o acx.o boot.o init.o wl1251.o \ + debugfs.o +obj-$(CONFIG_WL12XX) += wl12xx.o diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c new file mode 100644 index 000000000000..1cfd458ad5ab --- /dev/null +++ b/drivers/net/wireless/wl12xx/acx.c @@ -0,0 +1,689 @@ +#include "acx.h" + +#include +#include +#include + +#include "wl12xx.h" +#include "wl12xx_80211.h" +#include "reg.h" +#include "spi.h" +#include "ps.h" + +int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod, + u8 mgt_rate, u8 mgt_mod) +{ + int ret; + struct acx_fw_gen_frame_rates rates; + + wl12xx_debug(DEBUG_ACX, "acx frame rates"); + + rates.header.id = ACX_FW_GEN_FRAME_RATES; + rates.header.len = sizeof(struct acx_fw_gen_frame_rates) - + sizeof(struct acx_header); + + rates.tx_ctrl_frame_rate = ctrl_rate; + rates.tx_ctrl_frame_mod = ctrl_mod; + rates.tx_mgt_frame_rate = mgt_rate; + rates.tx_mgt_frame_mod = mgt_mod; + + ret = wl12xx_cmd_configure(wl, &rates, sizeof(rates)); + if (ret < 0) { + wl12xx_error("Failed to set FW rates and modulation"); + return ret; + } + + return 0; +} + + +int wl12xx_acx_station_id(struct wl12xx *wl) +{ + int ret, i; + struct dot11_station_id mac; + + wl12xx_debug(DEBUG_ACX, "acx dot11_station_id"); + + mac.header.id = DOT11_STATION_ID; + mac.header.len = sizeof(mac) - sizeof(struct acx_header); + + for (i = 0; i < ETH_ALEN; i++) + mac.mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; + + ret = wl12xx_cmd_configure(wl, &mac, sizeof(mac)); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id) +{ + struct acx_dot11_default_key default_key; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); + + default_key.header.id = DOT11_DEFAULT_KEY; + default_key.header.len = sizeof(default_key) - + sizeof(struct acx_header); + + default_key.id = key_id; + + ret = wl12xx_cmd_configure(wl, &default_key, sizeof(default_key)); + if (ret < 0) { + wl12xx_error("Couldnt set default key"); + return ret; + } + + wl->default_key = key_id; + + return 0; +} + +int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval) +{ + struct acx_wake_up_condition wake_up; + + wl12xx_debug(DEBUG_ACX, "acx wake up conditions"); + + wake_up.header.id = ACX_WAKE_UP_CONDITIONS; + wake_up.header.len = sizeof(wake_up) - sizeof(struct acx_header); + + wake_up.wake_up_event = WAKE_UP_EVENT_DTIM_BITMAP; + wake_up.listen_interval = listen_interval; + + return wl12xx_cmd_configure(wl, &wake_up, sizeof(wake_up)); +} + +int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth) +{ + int ret; + struct acx_sleep_auth auth; + + wl12xx_debug(DEBUG_ACX, "acx sleep auth"); + + auth.header.id = ACX_SLEEP_AUTH; + auth.header.len = sizeof(auth) - sizeof(struct acx_header); + + auth.sleep_auth = sleep_auth; + + ret = wl12xx_cmd_configure(wl, &auth, sizeof(auth)); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len) +{ + struct wl12xx_command cmd; + struct acx_revision *rev; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx fw rev"); + + memset(&cmd, 0, sizeof(cmd)); + + ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, sizeof(*rev), &cmd); + if (ret < 0) { + wl12xx_warning("ACX_FW_REV interrogate failed"); + return ret; + } + + rev = (struct acx_revision *) &cmd.parameters; + + /* be careful with the buffer sizes */ + strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); + + /* + * if the firmware version string is exactly + * sizeof(rev->fw_version) long or fw_len is less than + * sizeof(rev->fw_version) it won't be null terminated + */ + buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; + + return 0; +} + +int wl12xx_acx_tx_power(struct wl12xx *wl, int power) +{ + struct acx_current_tx_power ie; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); + + if (power < 0 || power > 25) + return -EINVAL; + + memset(&ie, 0, sizeof(ie)); + + ie.header.id = DOT11_CUR_TX_PWR; + ie.header.len = sizeof(ie) - sizeof(struct acx_header); + ie.current_tx_power = power * 10; + + ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie)); + if (ret < 0) { + wl12xx_warning("configure of tx power failed: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_feature_cfg(struct wl12xx *wl) +{ + struct acx_feature_config feature; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx feature cfg"); + + memset(&feature, 0, sizeof(feature)); + + feature.header.id = ACX_FEATURE_CFG; + feature.header.len = sizeof(feature) - sizeof(struct acx_header); + + /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ + feature.data_flow_options = 0; + feature.options = 0; + + ret = wl12xx_cmd_configure(wl, &feature, sizeof(feature)); + if (ret < 0) + wl12xx_error("Couldnt set HW encryption"); + + return ret; +} + +int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len) +{ + struct wl12xx_command cmd; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx mem map"); + + ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, len, &cmd); + if (ret < 0) + return ret; + else if (cmd.status != CMD_STATUS_SUCCESS) + return -EIO; + + memcpy(mem_map, &cmd.parameters, len); + + return 0; +} + +int wl12xx_acx_data_path_params(struct wl12xx *wl, + struct acx_data_path_params_resp *data_path) +{ + struct acx_data_path_params params; + struct wl12xx_command cmd; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx data path params"); + + params.rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; + params.tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; + + params.rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM; + params.tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM; + + params.tx_complete_threshold = 1; + + params.tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE; + + params.tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT; + + params.header.id = ACX_DATA_PATH_PARAMS; + params.header.len = sizeof(params) - sizeof(struct acx_header); + + ret = wl12xx_cmd_configure(wl, ¶ms, sizeof(params)); + if (ret < 0) + return ret; + + + ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS, + sizeof(struct acx_data_path_params_resp), + &cmd); + + if (ret < 0) { + wl12xx_warning("failed to read data path parameters: %d", ret); + return ret; + } else if (cmd.status != CMD_STATUS_SUCCESS) { + wl12xx_warning("data path parameter acx status failed"); + return -EIO; + } + + memcpy(data_path, &cmd.parameters, sizeof(*data_path)); + + return 0; +} + +int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time) +{ + struct rx_msdu_lifetime msdu_lifetime; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx rx msdu life time"); + + msdu_lifetime.header.id = DOT11_RX_MSDU_LIFE_TIME; + msdu_lifetime.header.len = sizeof(msdu_lifetime) - + sizeof(struct acx_header); + msdu_lifetime.lifetime = life_time; + + ret = wl12xx_cmd_configure(wl, &msdu_lifetime, sizeof(msdu_lifetime)); + if (ret < 0) { + wl12xx_warning("failed to set rx msdu life time: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter) +{ + struct acx_rx_config rx_config; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx rx config"); + + rx_config.header.id = ACX_RX_CFG; + rx_config.header.len = sizeof(rx_config) - sizeof(struct acx_header); + rx_config.config_options = config; + rx_config.filter_options = filter; + + ret = wl12xx_cmd_configure(wl, &rx_config, sizeof(rx_config)); + if (ret < 0) { + wl12xx_warning("failed to set rx config: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_pd_threshold(struct wl12xx *wl) +{ + struct acx_packet_detection packet_detection; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx data pd threshold"); + + /* FIXME: threshold value not set */ + packet_detection.header.id = ACX_PD_THRESHOLD; + packet_detection.header.len = sizeof(packet_detection) - + sizeof(struct acx_header); + + ret = wl12xx_cmd_configure(wl, &packet_detection, + sizeof(packet_detection)); + if (ret < 0) { + wl12xx_warning("failed to set pd threshold: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time) +{ + struct acx_slot slot; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx slot"); + + slot.header.id = ACX_SLOT; + slot.header.len = sizeof(slot) - sizeof(struct acx_header); + + slot.wone_index = STATION_WONE_INDEX; + slot.slot_time = slot_time; + + ret = wl12xx_cmd_configure(wl, &slot, sizeof(slot)); + if (ret < 0) { + wl12xx_warning("failed to set slot time: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_group_address_tbl(struct wl12xx *wl) +{ + struct multicast_grp_addr_start multicast; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx group address tbl"); + + /* MAC filtering */ + multicast.header.id = DOT11_GROUP_ADDRESS_TBL; + multicast.header.len = sizeof(multicast) - sizeof(struct acx_header); + + multicast.enabled = 0; + multicast.num_groups = 0; + memset(multicast.mac_table, 0, ADDRESS_GROUP_MAX_LEN); + + ret = wl12xx_cmd_configure(wl, &multicast, sizeof(multicast)); + if (ret < 0) { + wl12xx_warning("failed to set group addr table: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_service_period_timeout(struct wl12xx *wl) +{ + struct acx_rx_timeout rx_timeout; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx service period timeout"); + + /* RX timeout */ + rx_timeout.header.id = ACX_SERVICE_PERIOD_TIMEOUT; + rx_timeout.header.len = sizeof(rx_timeout) - sizeof(struct acx_header); + + rx_timeout.ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; + rx_timeout.upsd_timeout = RX_TIMEOUT_UPSD_DEF; + + ret = wl12xx_cmd_configure(wl, &rx_timeout, sizeof(rx_timeout)); + if (ret < 0) { + wl12xx_warning("failed to set service period timeout: %d", + ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold) +{ + struct acx_rts_threshold rts; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx rts threshold"); + + rts.header.id = DOT11_RTS_THRESHOLD; + rts.header.len = sizeof(rts) - sizeof(struct acx_header); + + rts.threshold = rts_threshold; + + ret = wl12xx_cmd_configure(wl, &rts, sizeof(rts)); + if (ret < 0) { + wl12xx_warning("failed to set rts threshold: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl) +{ + struct acx_beacon_filter_option beacon_filter; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx beacon filter opt"); + + beacon_filter.header.id = ACX_BEACON_FILTER_OPT; + beacon_filter.header.len = sizeof(beacon_filter) - + sizeof(struct acx_header); + + beacon_filter.enable = 0; + beacon_filter.max_num_beacons = 0; + + ret = wl12xx_cmd_configure(wl, &beacon_filter, sizeof(beacon_filter)); + if (ret < 0) { + wl12xx_warning("failed to set beacon filter opt: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_beacon_filter_table(struct wl12xx *wl) +{ + struct acx_beacon_filter_ie_table ie_table; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx beacon filter table"); + + ie_table.header.id = ACX_BEACON_FILTER_TABLE; + ie_table.header.len = sizeof(ie_table) - sizeof(struct acx_header); + + ie_table.num_ie = 0; + memset(ie_table.table, 0, BEACON_FILTER_TABLE_MAX_SIZE); + + ret = wl12xx_cmd_configure(wl, &ie_table, sizeof(ie_table)); + if (ret < 0) { + wl12xx_warning("failed to set beacon filter table: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_sg_enable(struct wl12xx *wl) +{ + struct acx_bt_wlan_coex pta; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx sg enable"); + + pta.header.id = ACX_SG_ENABLE; + pta.header.len = sizeof(pta) - sizeof(struct acx_header); + + pta.enable = SG_ENABLE; + + ret = wl12xx_cmd_configure(wl, &pta, sizeof(pta)); + if (ret < 0) { + wl12xx_warning("failed to set softgemini enable: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_sg_cfg(struct wl12xx *wl) +{ + struct acx_bt_wlan_coex_param param; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx sg cfg"); + + /* BT-WLAN coext parameters */ + param.header.id = ACX_SG_CFG; + param.header.len = sizeof(param) - sizeof(struct acx_header); + + param.min_rate = RATE_INDEX_24MBPS; + param.bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; + param.wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; + param.sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; + param.rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; + param.tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; + param.rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; + param.tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; + param.wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; + param.bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; + param.next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; + param.wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; + param.hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; + param.next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; + param.antenna_type = PTA_ANTENNA_TYPE_DEF; + param.signal_type = PTA_SIGNALING_TYPE_DEF; + param.afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; + param.quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; + param.max_cts = PTA_MAX_NUM_CTS_DEF; + param.wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; + param.bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; + param.missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; + param.wlan_elp_hp = PTA_ELP_HP_DEF; + param.bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; + param.ack_mode_dual_ant = PTA_ACK_MODE_DEF; + param.pa_sd_enable = PTA_ALLOW_PA_SD_DEF; + param.pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; + param.bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; + + ret = wl12xx_cmd_configure(wl, ¶m, sizeof(param)); + if (ret < 0) { + wl12xx_warning("failed to set sg config: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_cca_threshold(struct wl12xx *wl) +{ + struct acx_energy_detection detection; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx cca threshold"); + + detection.header.id = ACX_CCA_THRESHOLD; + detection.header.len = sizeof(detection) - sizeof(struct acx_header); + + detection.rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; + detection.tx_energy_detection = 0; + + ret = wl12xx_cmd_configure(wl, &detection, sizeof(detection)); + if (ret < 0) { + wl12xx_warning("failed to set cca threshold: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl) +{ + struct acx_beacon_broadcast bb; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx bcn dtim options"); + + bb.header.id = ACX_BCN_DTIM_OPTIONS; + bb.header.len = sizeof(bb) - sizeof(struct acx_header); + + bb.beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; + bb.broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; + bb.rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; + bb.ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; + + ret = wl12xx_cmd_configure(wl, &bb, sizeof(bb)); + if (ret < 0) { + wl12xx_warning("failed to set rx config: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_aid(struct wl12xx *wl, u16 aid) +{ + struct acx_aid acx_aid; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx aid"); + + acx_aid.header.id = ACX_AID; + acx_aid.header.len = sizeof(acx_aid) - sizeof(struct acx_header); + + acx_aid.aid = aid; + + ret = wl12xx_cmd_configure(wl, &acx_aid, sizeof(acx_aid)); + if (ret < 0) { + wl12xx_warning("failed to set aid: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask) +{ + struct acx_event_mask mask; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx event mbox mask"); + + mask.header.id = ACX_EVENT_MBOX_MASK; + mask.header.len = sizeof(mask) - sizeof(struct acx_header); + + /* high event mask is unused */ + mask.high_event_mask = 0xffffffff; + + mask.event_mask = event_mask; + + ret = wl12xx_cmd_configure(wl, &mask, sizeof(mask)); + if (ret < 0) { + wl12xx_warning("failed to set aid: %d", ret); + return ret; + } + + return 0; +} + +int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble) +{ + struct acx_preamble ie; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx_set_preamble"); + + memset(&ie, 0, sizeof(ie)); + + ie.header.id = ACX_PREAMBLE_TYPE; + ie.header.len = sizeof(ie) - sizeof(struct acx_header); + ie.preamble = preamble; + ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie)); + if (ret < 0) { + wl12xx_warning("Setting of preamble failed: %d", ret); + return ret; + } + return 0; +} + +int wl12xx_acx_cts_protect(struct wl12xx *wl, + enum acx_ctsprotect_type ctsprotect) +{ + struct acx_ctsprotect ie; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect"); + + memset(&ie, 0, sizeof(ie)); + + ie.header.id = ACX_CTS_PROTECTION; + ie.header.len = sizeof(ie) - sizeof(struct acx_header); + ie.ctsprotect = ctsprotect; + ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie)); + if (ret < 0) { + wl12xx_warning("Setting of ctsprotect failed: %d", ret); + return ret; + } + return 0; +} + +int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats) +{ + struct wl12xx_command *answer; + int ret; + + wl12xx_debug(DEBUG_ACX, "acx statistics"); + + answer = kmalloc(sizeof(*answer), GFP_KERNEL); + if (!answer) { + wl12xx_warning("could not allocate memory for acx statistics"); + ret = -ENOMEM; + goto out; + } + + ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, sizeof(*answer), + answer); + if (ret < 0) { + wl12xx_warning("acx statistics failed: %d", ret); + goto out; + } + + memcpy(stats, answer->parameters, sizeof(*stats)); + +out: + kfree(answer); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h new file mode 100644 index 000000000000..fb2d2340993c --- /dev/null +++ b/drivers/net/wireless/wl12xx/acx.h @@ -0,0 +1,1245 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_ACX_H__ +#define __WL12XX_ACX_H__ + +#include "wl12xx.h" + +/* Target's information element */ +struct acx_header { + u16 id; + u16 len; +}; + +struct acx_error_counter { + struct acx_header header; + + /* The number of PLCP errors since the last time this */ + /* information element was interrogated. This field is */ + /* automatically cleared when it is interrogated.*/ + u32 PLCP_error; + + /* The number of FCS errors since the last time this */ + /* information element was interrogated. This field is */ + /* automatically cleared when it is interrogated.*/ + u32 FCS_error; + + /* The number of MPDUs without PLCP header errors received*/ + /* since the last time this information element was interrogated. */ + /* This field is automatically cleared when it is interrogated.*/ + u32 valid_frame; + + /* the number of missed sequence numbers in the squentially */ + /* values of frames seq numbers */ + u32 seq_num_miss; +} __attribute__ ((packed)); + +struct acx_revision { + struct acx_header header; + + /* + * The WiLink firmware version, an ASCII string x.x.x.x, + * that uniquely identifies the current firmware. + * The left most digit is incremented each time a + * significant change is made to the firmware, such as + * code redesign or new platform support. + * The second digit is incremented when major enhancements + * are added or major fixes are made. + * The third digit is incremented for each GA release. + * The fourth digit is incremented for each build. + * The first two digits identify a firmware release version, + * in other words, a unique set of features. + * The first three digits identify a GA release. + */ + char fw_version[20]; + + /* + * This 4 byte field specifies the WiLink hardware version. + * bits 0 - 15: Reserved. + * bits 16 - 23: Version ID - The WiLink version ID + * (1 = first spin, 2 = second spin, and so on). + * bits 24 - 31: Chip ID - The WiLink chip ID. + */ + u32 hw_version; +} __attribute__ ((packed)); + +enum wl12xx_psm_mode { + /* Active mode */ + WL12XX_PSM_CAM = 0, + + /* Power save mode */ + WL12XX_PSM_PS = 1, + + /* Extreme low power */ + WL12XX_PSM_ELP = 2, +}; + +struct acx_sleep_auth { + struct acx_header header; + + /* The sleep level authorization of the device. */ + /* 0 - Always active*/ + /* 1 - Power down mode: light / fast sleep*/ + /* 2 - ELP mode: Deep / Max sleep*/ + u8 sleep_auth; + u8 padding[3]; +} __attribute__ ((packed)); + +#define TIM_ELE_ID 5 +#define PARTIAL_VBM_MAX 251 + +struct tim { + u8 identity; + u8 length; + u8 dtim_count; + u8 dtim_period; + u8 bitmap_ctrl; + u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ +} __attribute__ ((packed)); + +/* Virtual Bit Map update */ +struct vbm_update_request { + __le16 len; + u8 padding[2]; + struct tim tim; +} __attribute__ ((packed)); + +enum { + HOSTIF_PCI_MASTER_HOST_INDIRECT, + HOSTIF_PCI_MASTER_HOST_DIRECT, + HOSTIF_SLAVE, + HOSTIF_PKT_RING, + HOSTIF_DONTCARE = 0xFF +}; + +#define DEFAULT_UCAST_PRIORITY 0 +#define DEFAULT_RX_Q_PRIORITY 0 +#define DEFAULT_NUM_STATIONS 1 +#define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */ +#define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */ +#define TRACE_BUFFER_MAX_SIZE 256 + +#define DP_RX_PACKET_RING_CHUNK_SIZE 1600 +#define DP_TX_PACKET_RING_CHUNK_SIZE 1600 +#define DP_RX_PACKET_RING_CHUNK_NUM 2 +#define DP_TX_PACKET_RING_CHUNK_NUM 2 +#define DP_TX_COMPLETE_TIME_OUT 20 +#define FW_TX_CMPLT_BLOCK_SIZE 16 + +struct acx_data_path_params { + struct acx_header header; + + u16 rx_packet_ring_chunk_size; + u16 tx_packet_ring_chunk_size; + + u8 rx_packet_ring_chunk_num; + u8 tx_packet_ring_chunk_num; + + /* + * Maximum number of packets that can be gathered + * in the TX complete ring before an interrupt + * is generated. + */ + u8 tx_complete_threshold; + + /* Number of pending TX complete entries in cyclic ring.*/ + u8 tx_complete_ring_depth; + + /* + * Max num microseconds since a packet enters the TX + * complete ring until an interrupt is generated. + */ + u32 tx_complete_timeout; +} __attribute__ ((packed)); + + +struct acx_data_path_params_resp { + struct acx_header header; + + u16 rx_packet_ring_chunk_size; + u16 tx_packet_ring_chunk_size; + + u8 rx_packet_ring_chunk_num; + u8 tx_packet_ring_chunk_num; + + u8 pad[2]; + + u32 rx_packet_ring_addr; + u32 tx_packet_ring_addr; + + u32 rx_control_addr; + u32 tx_control_addr; + + u32 tx_complete_addr; +} __attribute__ ((packed)); + +#define TX_MSDU_LIFETIME_MIN 0 +#define TX_MSDU_LIFETIME_MAX 3000 +#define TX_MSDU_LIFETIME_DEF 512 +#define RX_MSDU_LIFETIME_MIN 0 +#define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF +#define RX_MSDU_LIFETIME_DEF 512000 + +struct rx_msdu_lifetime { + struct acx_header header; + + /* + * The maximum amount of time, in TU, before the + * firmware discards the MSDU. + */ + u32 lifetime; +} __attribute__ ((packed)); + +/* + * RX Config Options Table + * Bit Definition + * === ========== + * 31:14 Reserved + * 13 Copy RX Status - when set, write three receive status words + * to top of rx'd MPDUs. + * When cleared, do not write three status words (added rev 1.5) + * 12 Reserved + * 11 RX Complete upon FCS error - when set, give rx complete + * interrupt for FCS errors, after the rx filtering, e.g. unicast + * frames not to us with FCS error will not generate an interrupt. + * 10 SSID Filter Enable - When set, the WiLink discards all beacon, + * probe request, and probe response frames with an SSID that does + * not match the SSID specified by the host in the START/JOIN + * command. + * When clear, the WiLink receives frames with any SSID. + * 9 Broadcast Filter Enable - When set, the WiLink discards all + * broadcast frames. When clear, the WiLink receives all received + * broadcast frames. + * 8:6 Reserved + * 5 BSSID Filter Enable - When set, the WiLink discards any frames + * with a BSSID that does not match the BSSID specified by the + * host. + * When clear, the WiLink receives frames from any BSSID. + * 4 MAC Addr Filter - When set, the WiLink discards any frames + * with a destination address that does not match the MAC address + * of the adaptor. + * When clear, the WiLink receives frames destined to any MAC + * address. + * 3 Promiscuous - When set, the WiLink receives all valid frames + * (i.e., all frames that pass the FCS check). + * When clear, only frames that pass the other filters specified + * are received. + * 2 FCS - When set, the WiLink includes the FCS with the received + * frame. + * When cleared, the FCS is discarded. + * 1 PLCP header - When set, write all data from baseband to frame + * buffer including PHY header. + * 0 Reserved - Always equal to 0. + * + * RX Filter Options Table + * Bit Definition + * === ========== + * 31:12 Reserved - Always equal to 0. + * 11 Association - When set, the WiLink receives all association + * related frames (association request/response, reassocation + * request/response, and disassociation). When clear, these frames + * are discarded. + * 10 Auth/De auth - When set, the WiLink receives all authentication + * and de-authentication frames. When clear, these frames are + * discarded. + * 9 Beacon - When set, the WiLink receives all beacon frames. + * When clear, these frames are discarded. + * 8 Contention Free - When set, the WiLink receives all contention + * free frames. + * When clear, these frames are discarded. + * 7 Control - When set, the WiLink receives all control frames. + * When clear, these frames are discarded. + * 6 Data - When set, the WiLink receives all data frames. + * When clear, these frames are discarded. + * 5 FCS Error - When set, the WiLink receives frames that have FCS + * errors. + * When clear, these frames are discarded. + * 4 Management - When set, the WiLink receives all management + * frames. + * When clear, these frames are discarded. + * 3 Probe Request - When set, the WiLink receives all probe request + * frames. + * When clear, these frames are discarded. + * 2 Probe Response - When set, the WiLink receives all probe + * response frames. + * When clear, these frames are discarded. + * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK + * frames. + * When clear, these frames are discarded. + * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames + * that have reserved frame types and sub types as defined by the + * 802.11 specification. + * When clear, these frames are discarded. + */ +struct acx_rx_config { + struct acx_header header; + + u32 config_options; + u32 filter_options; +} __attribute__ ((packed)); + +enum { + QOS_AC_BE = 0, + QOS_AC_BK, + QOS_AC_VI, + QOS_AC_VO, + QOS_HIGHEST_AC_INDEX = QOS_AC_VO, +}; + +#define MAX_NUM_OF_AC (QOS_HIGHEST_AC_INDEX+1) +#define FIRST_AC_INDEX QOS_AC_BE +#define MAX_NUM_OF_802_1d_TAGS 8 +#define AC_PARAMS_MAX_TSID 15 +#define MAX_APSD_CONF 0xffff + +#define QOS_TX_HIGH_MIN (0) +#define QOS_TX_HIGH_MAX (100) + +#define QOS_TX_HIGH_BK_DEF (25) +#define QOS_TX_HIGH_BE_DEF (35) +#define QOS_TX_HIGH_VI_DEF (35) +#define QOS_TX_HIGH_VO_DEF (35) + +#define QOS_TX_LOW_BK_DEF (15) +#define QOS_TX_LOW_BE_DEF (25) +#define QOS_TX_LOW_VI_DEF (25) +#define QOS_TX_LOW_VO_DEF (25) + +struct acx_tx_queue_qos_config { + struct acx_header header; + + u8 qid; + u8 pad[3]; + + /* Max number of blocks allowd in the queue */ + u16 high_threshold; + + /* Lowest memory blocks guaranteed for this queue */ + u16 low_threshold; +} __attribute__ ((packed)); + +struct acx_packet_detection { + struct acx_header header; + + u32 threshold; +} __attribute__ ((packed)); + + +enum acx_slot_type { + SLOT_TIME_LONG = 0, + SLOT_TIME_SHORT = 1, + DEFAULT_SLOT_TIME = SLOT_TIME_SHORT, + MAX_SLOT_TIMES = 0xFF +}; + +#define STATION_WONE_INDEX 0 + +struct acx_slot { + struct acx_header header; + + u8 wone_index; /* Reserved */ + u8 slot_time; + u8 reserved[6]; +} __attribute__ ((packed)); + + +#define ADDRESS_GROUP_MAX (8) +#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) + +struct multicast_grp_addr_start { + struct acx_header header; + + u8 enabled; + u8 num_groups; + u8 pad[2]; + u8 mac_table[ADDRESS_GROUP_MAX_LEN]; +} __attribute__ ((packed)); + + +#define RX_TIMEOUT_PS_POLL_MIN 0 +#define RX_TIMEOUT_PS_POLL_MAX (200000) +#define RX_TIMEOUT_PS_POLL_DEF (15) +#define RX_TIMEOUT_UPSD_MIN 0 +#define RX_TIMEOUT_UPSD_MAX (200000) +#define RX_TIMEOUT_UPSD_DEF (15) + +struct acx_rx_timeout { + struct acx_header header; + + /* + * The longest time the STA will wait to receive + * traffic from the AP after a PS-poll has been + * transmitted. + */ + u16 ps_poll_timeout; + + /* + * The longest time the STA will wait to receive + * traffic from the AP after a frame has been sent + * from an UPSD enabled queue. + */ + u16 upsd_timeout; +} __attribute__ ((packed)); + +#define RTS_THRESHOLD_MIN 0 +#define RTS_THRESHOLD_MAX 4096 +#define RTS_THRESHOLD_DEF 2347 + +struct acx_rts_threshold { + struct acx_header header; + + u16 threshold; + u8 pad[2]; +} __attribute__ ((packed)); + +struct acx_beacon_filter_option { + struct acx_header header; + + u8 enable; + + /* + * The number of beacons without the unicast TIM + * bit set that the firmware buffers before + * signaling the host about ready frames. + * When set to 0 and the filter is enabled, beacons + * without the unicast TIM bit set are dropped. + */ + u8 max_num_beacons; + u8 pad[2]; +} __attribute__ ((packed)); + +/* + * ACXBeaconFilterEntry (not 221) + * Byte Offset Size (Bytes) Definition + * =========== ============ ========== + * 0 1 IE identifier + * 1 1 Treatment bit mask + * + * ACXBeaconFilterEntry (221) + * Byte Offset Size (Bytes) Definition + * =========== ============ ========== + * 0 1 IE identifier + * 1 1 Treatment bit mask + * 2 3 OUI + * 5 1 Type + * 6 2 Version + * + * + * Treatment bit mask - The information element handling: + * bit 0 - The information element is compared and transferred + * in case of change. + * bit 1 - The information element is transferred to the host + * with each appearance or disappearance. + * Note that both bits can be set at the same time. + */ +#define BEACON_FILTER_TABLE_MAX_IE_NUM (32) +#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6) +#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE (2) +#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6) +#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \ + BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \ + (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ + BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) + +struct acx_beacon_filter_ie_table { + struct acx_header header; + + u8 num_ie; + u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; + u8 pad[3]; +} __attribute__ ((packed)); + +enum { + SG_ENABLE = 0, + SG_DISABLE, + SG_SENSE_NO_ACTIVITY, + SG_SENSE_ACTIVE +}; + +struct acx_bt_wlan_coex { + struct acx_header header; + + /* + * 0 -> PTA enabled + * 1 -> PTA disabled + * 2 -> sense no active mode, i.e. + * an interrupt is sent upon + * BT activity. + * 3 -> PTA is switched on in response + * to the interrupt sending. + */ + u8 enable; + u8 pad[3]; +} __attribute__ ((packed)); + +#define PTA_ANTENNA_TYPE_DEF (0) +#define PTA_BT_HP_MAXTIME_DEF (2000) +#define PTA_WLAN_HP_MAX_TIME_DEF (5000) +#define PTA_SENSE_DISABLE_TIMER_DEF (1350) +#define PTA_PROTECTIVE_RX_TIME_DEF (1500) +#define PTA_PROTECTIVE_TX_TIME_DEF (1500) +#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) +#define PTA_SIGNALING_TYPE_DEF (1) +#define PTA_AFH_LEVERAGE_ON_DEF (0) +#define PTA_NUMBER_QUIET_CYCLE_DEF (0) +#define PTA_MAX_NUM_CTS_DEF (3) +#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) +#define PTA_NUMBER_OF_BT_PACKETS_DEF (2) +#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) +#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) +#define PTA_CYCLE_TIME_FAST_DEF (8700) +#define PTA_RX_FOR_AVALANCHE_DEF (5) +#define PTA_ELP_HP_DEF (0) +#define PTA_ANTI_STARVE_PERIOD_DEF (500) +#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) +#define PTA_ALLOW_PA_SD_DEF (1) +#define PTA_TIME_BEFORE_BEACON_DEF (6300) +#define PTA_HPDM_MAX_TIME_DEF (1600) +#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) +#define PTA_AUTO_MODE_NO_CTS_DEF (0) +#define PTA_BT_HP_RESPECTED_DEF (3) +#define PTA_WLAN_RX_MIN_RATE_DEF (24) +#define PTA_ACK_MODE_DEF (1) + +struct acx_bt_wlan_coex_param { + struct acx_header header; + + /* + * The minimum rate of a received WLAN packet in the STA, + * during protective mode, of which a new BT-HP request + * during this Rx will always be respected and gain the antenna. + */ + u32 min_rate; + + /* Max time the BT HP will be respected. */ + u16 bt_hp_max_time; + + /* Max time the WLAN HP will be respected. */ + u16 wlan_hp_max_time; + + /* + * The time between the last BT activity + * and the moment when the sense mode returns + * to SENSE_INACTIVE. + */ + u16 sense_disable_timer; + + /* Time before the next BT HP instance */ + u16 rx_time_bt_hp; + u16 tx_time_bt_hp; + + /* range: 10-20000 default: 1500 */ + u16 rx_time_bt_hp_fast; + u16 tx_time_bt_hp_fast; + + /* range: 2000-65535 default: 8700 */ + u16 wlan_cycle_fast; + + /* range: 0 - 15000 (Msec) default: 1000 */ + u16 bt_anti_starvation_period; + + /* range 400-10000(Usec) default: 3000 */ + u16 next_bt_lp_packet; + + /* Deafult: worst case for BT DH5 traffic */ + u16 wake_up_beacon; + + /* range: 0-50000(Usec) default: 1050 */ + u16 hp_dm_max_guard_time; + + /* + * This is to prevent both BT & WLAN antenna + * starvation. + * Range: 100-50000(Usec) default:2550 + */ + u16 next_wlan_packet; + + /* 0 -> shared antenna */ + u8 antenna_type; + + /* + * 0 -> TI legacy + * 1 -> Palau + */ + u8 signal_type; + + /* + * BT AFH status + * 0 -> no AFH + * 1 -> from dedicated GPIO + * 2 -> AFH on (from host) + */ + u8 afh_leverage_on; + + /* + * The number of cycles during which no + * TX will be sent after 1 cycle of RX + * transaction in protective mode + */ + u8 quiet_cycle_num; + + /* + * The maximum number of CTSs that will + * be sent for receiving RX packet in + * protective mode + */ + u8 max_cts; + + /* + * The number of WLAN packets + * transferred in common mode before + * switching to BT. + */ + u8 wlan_packets_num; + + /* + * The number of BT packets + * transferred in common mode before + * switching to WLAN. + */ + u8 bt_packets_num; + + /* range: 1-255 default: 5 */ + u8 missed_rx_avalanche; + + /* range: 0-1 default: 1 */ + u8 wlan_elp_hp; + + /* range: 0 - 15 default: 4 */ + u8 bt_anti_starvation_cycles; + + u8 ack_mode_dual_ant; + + /* + * Allow PA_SD assertion/de-assertion + * during enabled BT activity. + */ + u8 pa_sd_enable; + + /* + * Enable/Disable PTA in auto mode: + * Support Both Active & P.S modes + */ + u8 pta_auto_mode_enable; + + /* range: 0 - 20 default: 1 */ + u8 bt_hp_respected_num; +} __attribute__ ((packed)); + +#define CCA_THRSH_ENABLE_ENERGY_D 0x140A +#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF + +struct acx_energy_detection { + struct acx_header header; + + /* The RX Clear Channel Assessment threshold in the PHY */ + u16 rx_cca_threshold; + u8 tx_energy_detection; + u8 pad; +} __attribute__ ((packed)); + +#define BCN_RX_TIMEOUT_DEF_VALUE 10000 +#define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000 +#define RX_BROADCAST_IN_PS_DEF_VALUE 1 +#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4 + +struct acx_beacon_broadcast { + struct acx_header header; + + u16 beacon_rx_timeout; + u16 broadcast_timeout; + + /* Enables receiving of broadcast packets in PS mode */ + u8 rx_broadcast_in_ps; + + /* Consecutive PS Poll failures before updating the host */ + u8 ps_poll_threshold; + u8 pad[2]; +} __attribute__ ((packed)); + +struct acx_event_mask { + struct acx_header header; + + u32 event_mask; + u32 high_event_mask; /* Unused */ +} __attribute__ ((packed)); + +#define CFG_RX_FCS BIT(2) +#define CFG_RX_ALL_GOOD BIT(3) +#define CFG_UNI_FILTER_EN BIT(4) +#define CFG_BSSID_FILTER_EN BIT(5) +#define CFG_MC_FILTER_EN BIT(6) +#define CFG_MC_ADDR0_EN BIT(7) +#define CFG_MC_ADDR1_EN BIT(8) +#define CFG_BC_REJECT_EN BIT(9) +#define CFG_SSID_FILTER_EN BIT(10) +#define CFG_RX_INT_FCS_ERROR BIT(11) +#define CFG_RX_INT_ENCRYPTED BIT(12) +#define CFG_RX_WR_RX_STATUS BIT(13) +#define CFG_RX_FILTER_NULTI BIT(14) +#define CFG_RX_RESERVE BIT(15) +#define CFG_RX_TIMESTAMP_TSF BIT(16) + +#define CFG_RX_RSV_EN BIT(0) +#define CFG_RX_RCTS_ACK BIT(1) +#define CFG_RX_PRSP_EN BIT(2) +#define CFG_RX_PREQ_EN BIT(3) +#define CFG_RX_MGMT_EN BIT(4) +#define CFG_RX_FCS_ERROR BIT(5) +#define CFG_RX_DATA_EN BIT(6) +#define CFG_RX_CTL_EN BIT(7) +#define CFG_RX_CF_EN BIT(8) +#define CFG_RX_BCN_EN BIT(9) +#define CFG_RX_AUTH_EN BIT(10) +#define CFG_RX_ASSOC_EN BIT(11) + +#define SCAN_PASSIVE BIT(0) +#define SCAN_5GHZ_BAND BIT(1) +#define SCAN_TRIGGERED BIT(2) +#define SCAN_PRIORITY_HIGH BIT(3) + +struct acx_fw_gen_frame_rates { + struct acx_header header; + + u8 tx_ctrl_frame_rate; /* RATE_* */ + u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */ + u8 tx_mgt_frame_rate; + u8 tx_mgt_frame_mod; +} __attribute__ ((packed)); + +/* STA MAC */ +struct dot11_station_id { + struct acx_header header; + + u8 mac[ETH_ALEN]; + u8 pad[2]; +} __attribute__ ((packed)); + +/* HW encryption keys */ +#define NUM_ACCESS_CATEGORIES_COPY 4 +#define MAX_KEY_SIZE 32 + +/* When set, disable HW encryption */ +#define DF_ENCRYPTION_DISABLE 0x01 +/* When set, disable HW decryption */ +#define DF_SNIFF_MODE_ENABLE 0x80 + +struct acx_feature_config { + struct acx_header header; + + u32 options; + u32 data_flow_options; +} __attribute__ ((packed)); + +enum acx_key_action { + KEY_ADD_OR_REPLACE = 1, + KEY_REMOVE = 2, + KEY_SET_ID = 3, + MAX_KEY_ACTION = 0xffff, +}; + +enum acx_key_type { + KEY_WEP_DEFAULT = 0, + KEY_WEP_ADDR = 1, + KEY_AES_GROUP = 4, + KEY_AES_PAIRWISE = 5, + KEY_WEP_GROUP = 6, + KEY_TKIP_MIC_GROUP = 10, + KEY_TKIP_MIC_PAIRWISE = 11, +}; + +/* + * + * key_type_e key size key format + * ---------- --------- ---------- + * 0x00 5, 13, 29 Key data + * 0x01 5, 13, 29 Key data + * 0x04 16 16 bytes of key data + * 0x05 16 16 bytes of key data + * 0x0a 32 16 bytes of TKIP key data + * 8 bytes of RX MIC key data + * 8 bytes of TX MIC key data + * 0x0b 32 16 bytes of TKIP key data + * 8 bytes of RX MIC key data + * 8 bytes of TX MIC key data + * + */ + +struct acx_set_key { + /* Ignored for default WEP key */ + u8 addr[ETH_ALEN]; + + /* key_action_e */ + u16 key_action; + + u16 reserved_1; + + /* key size in bytes */ + u8 key_size; + + /* key_type_e */ + u8 key_type; + u8 ssid_profile; + + /* + * TKIP, AES: frame's key id field. + * For WEP default key: key id; + */ + u8 id; + u8 reserved_2[6]; + u8 key[MAX_KEY_SIZE]; + u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; + u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; +} __attribute__ ((packed)); + +struct acx_current_tx_power { + struct acx_header header; + + u8 current_tx_power; + u8 padding[3]; +} __attribute__ ((packed)); + +struct acx_dot11_default_key { + struct acx_header header; + + u8 id; + u8 pad[3]; +} __attribute__ ((packed)); + +struct acx_tsf_info { + struct acx_header header; + + u32 current_tsf_msb; + u32 current_tsf_lsb; + u32 last_TBTT_msb; + u32 last_TBTT_lsb; + u8 last_dtim_count; + u8 pad[3]; +} __attribute__ ((packed)); + +/* 802.11 PS */ +enum acx_ps_mode { + STATION_ACTIVE_MODE, + STATION_POWER_SAVE_MODE +}; + +struct acx_ps_params { + u8 ps_mode; /* STATION_* */ + u8 send_null_data; /* Do we have to send NULL data packet ? */ + u8 retries; /* Number of retires for the initial NULL data packet */ + + /* + * TUs during which the target stays awake after switching + * to power save mode. + */ + u8 hang_over_period; + u16 null_data_rate; + u8 pad[2]; +} __attribute__ ((packed)); + +enum acx_wake_up_event { + WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ + WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ + WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */ + WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */ + WAKE_UP_EVENT_BITS_MASK = 0x0F +}; + +struct acx_wake_up_condition { + struct acx_header header; + + u8 wake_up_event; /* Only one bit can be set */ + u8 listen_interval; + u8 pad[2]; +} __attribute__ ((packed)); + +struct acx_aid { + struct acx_header header; + + /* + * To be set when associated with an AP. + */ + u16 aid; + u8 pad[2]; +} __attribute__ ((packed)); + +enum acx_preamble_type { + ACX_PREAMBLE_LONG = 0, + ACX_PREAMBLE_SHORT = 1 +}; + +struct acx_preamble { + struct acx_header header; + /* + * When set, the WiLink transmits the frames with a short preamble and + * when cleared, the WiLink transmits the frames with a long preamble. + */ + u8 preamble; + u8 padding[3]; +} __attribute__ ((packed)); + +enum acx_ctsprotect_type { + CTSPROTECT_DISABLE = 0, + CTSPROTECT_ENABLE = 1 +}; + +struct acx_ctsprotect { + struct acx_header header; + u8 ctsprotect; + u8 padding[3]; +} __attribute__ ((packed)); + +struct acx_tx_statistics { + u32 internal_desc_overflow; +} __attribute__ ((packed)); + +struct acx_rx_statistics { + u32 out_of_mem; + u32 hdr_overflow; + u32 hw_stuck; + u32 dropped; + u32 fcs_err; + u32 xfr_hint_trig; + u32 path_reset; + u32 reset_counter; +} __attribute__ ((packed)); + +struct acx_dma_statistics { + u32 rx_requested; + u32 rx_errors; + u32 tx_requested; + u32 tx_errors; +} __attribute__ ((packed)); + +struct acx_isr_statistics { + /* host command complete */ + u32 cmd_cmplt; + + /* fiqisr() */ + u32 fiqs; + + /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ + u32 rx_headers; + + /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ + u32 rx_completes; + + /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ + u32 rx_mem_overflow; + + /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ + u32 rx_rdys; + + /* irqisr() */ + u32 irqs; + + /* (INT_STS_ND & INT_TRIG_TX_PROC) */ + u32 tx_procs; + + /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ + u32 decrypt_done; + + /* (INT_STS_ND & INT_TRIG_DMA0) */ + u32 dma0_done; + + /* (INT_STS_ND & INT_TRIG_DMA1) */ + u32 dma1_done; + + /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ + u32 tx_exch_complete; + + /* (INT_STS_ND & INT_TRIG_COMMAND) */ + u32 commands; + + /* (INT_STS_ND & INT_TRIG_RX_PROC) */ + u32 rx_procs; + + /* (INT_STS_ND & INT_TRIG_PM_802) */ + u32 hw_pm_mode_changes; + + /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ + u32 host_acknowledges; + + /* (INT_STS_ND & INT_TRIG_PM_PCI) */ + u32 pci_pm; + + /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ + u32 wakeups; + + /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ + u32 low_rssi; +} __attribute__ ((packed)); + +struct acx_wep_statistics { + /* WEP address keys configured */ + u32 addr_key_count; + + /* default keys configured */ + u32 default_key_count; + + u32 reserved; + + /* number of times that WEP key not found on lookup */ + u32 key_not_found; + + /* number of times that WEP key decryption failed */ + u32 decrypt_fail; + + /* WEP packets decrypted */ + u32 packets; + + /* WEP decrypt interrupts */ + u32 interrupt; +} __attribute__ ((packed)); + +#define ACX_MISSED_BEACONS_SPREAD 10 + +struct acx_pwr_statistics { + /* the amount of enters into power save mode (both PD & ELP) */ + u32 ps_enter; + + /* the amount of enters into ELP mode */ + u32 elp_enter; + + /* the amount of missing beacon interrupts to the host */ + u32 missing_bcns; + + /* the amount of wake on host-access times */ + u32 wake_on_host; + + /* the amount of wake on timer-expire */ + u32 wake_on_timer_exp; + + /* the number of packets that were transmitted with PS bit set */ + u32 tx_with_ps; + + /* the number of packets that were transmitted with PS bit clear */ + u32 tx_without_ps; + + /* the number of received beacons */ + u32 rcvd_beacons; + + /* the number of entering into PowerOn (power save off) */ + u32 power_save_off; + + /* the number of entries into power save mode */ + u16 enable_ps; + + /* + * the number of exits from power save, not including failed PS + * transitions + */ + u16 disable_ps; + + /* + * the number of times the TSF counter was adjusted because + * of drift + */ + u32 fix_tsf_ps; + + /* Gives statistics about the spread continuous missed beacons. + * The 16 LSB are dedicated for the PS mode. + * The 16 MSB are dedicated for the PS mode. + * cont_miss_bcns_spread[0] - single missed beacon. + * cont_miss_bcns_spread[1] - two continuous missed beacons. + * cont_miss_bcns_spread[2] - three continuous missed beacons. + * ... + * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. + */ + u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; + + /* the number of beacons in awake mode */ + u32 rcvd_awake_beacons; +} __attribute__ ((packed)); + +struct acx_mic_statistics { + u32 rx_pkts; + u32 calc_failure; +} __attribute__ ((packed)); + +struct acx_aes_statistics { + u32 encrypt_fail; + u32 decrypt_fail; + u32 encrypt_packets; + u32 decrypt_packets; + u32 encrypt_interrupt; + u32 decrypt_interrupt; +} __attribute__ ((packed)); + +struct acx_event_statistics { + u32 heart_beat; + u32 calibration; + u32 rx_mismatch; + u32 rx_mem_empty; + u32 rx_pool; + u32 oom_late; + u32 phy_transmit_error; + u32 tx_stuck; +} __attribute__ ((packed)); + +struct acx_ps_statistics { + u32 pspoll_timeouts; + u32 upsd_timeouts; + u32 upsd_max_sptime; + u32 upsd_max_apturn; + u32 pspoll_max_apturn; + u32 pspoll_utilization; + u32 upsd_utilization; +} __attribute__ ((packed)); + +struct acx_rxpipe_statistics { + u32 rx_prep_beacon_drop; + u32 descr_host_int_trig_rx_data; + u32 beacon_buffer_thres_host_int_trig_rx_data; + u32 missed_beacon_host_int_trig_rx_data; + u32 tx_xfr_host_int_trig_rx_data; +} __attribute__ ((packed)); + +struct acx_statistics { + struct acx_header header; + + struct acx_tx_statistics tx; + struct acx_rx_statistics rx; + struct acx_dma_statistics dma; + struct acx_isr_statistics isr; + struct acx_wep_statistics wep; + struct acx_pwr_statistics pwr; + struct acx_aes_statistics aes; + struct acx_mic_statistics mic; + struct acx_event_statistics event; + struct acx_ps_statistics ps; + struct acx_rxpipe_statistics rxpipe; +} __attribute__ ((packed)); + +enum { + ACX_WAKE_UP_CONDITIONS = 0x0002, + ACX_MEM_CFG = 0x0003, + ACX_SLOT = 0x0004, + ACX_QUEUE_HEAD = 0x0005, /* for MASTER mode only */ + ACX_AC_CFG = 0x0007, + ACX_MEM_MAP = 0x0008, + ACX_AID = 0x000A, + ACX_RADIO_PARAM = 0x000B, /* Not used */ + ACX_CFG = 0x000C, /* Not used */ + ACX_FW_REV = 0x000D, + ACX_MEDIUM_USAGE = 0x000F, + ACX_RX_CFG = 0x0010, + ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ + ACX_BSS_IN_PS = 0x0012, /* for AP only */ + ACX_STATISTICS = 0x0013, /* Debug API */ + ACX_FEATURE_CFG = 0x0015, + ACX_MISC_CFG = 0x0017, /* Not used */ + ACX_TID_CFG = 0x001A, + ACX_BEACON_FILTER_OPT = 0x001F, + ACX_LOW_RSSI = 0x0020, + ACX_NOISE_HIST = 0x0021, + ACX_HDK_VERSION = 0x0022, /* ??? */ + ACX_PD_THRESHOLD = 0x0023, + ACX_DATA_PATH_PARAMS = 0x0024, /* WO */ + ACX_DATA_PATH_RESP_PARAMS = 0x0024, /* RO */ + ACX_CCA_THRESHOLD = 0x0025, + ACX_EVENT_MBOX_MASK = 0x0026, +#ifdef FW_RUNNING_AS_AP + ACX_DTIM_PERIOD = 0x0027, /* for AP only */ +#else + ACX_WR_TBTT_AND_DTIM = 0x0027, /* STA only */ +#endif + ACX_ACI_OPTION_CFG = 0x0029, /* OBSOLETE (for 1251)*/ + ACX_GPIO_CFG = 0x002A, /* Not used */ + ACX_GPIO_SET = 0x002B, /* Not used */ + ACX_PM_CFG = 0x002C, /* To Be Documented */ + ACX_CONN_MONIT_PARAMS = 0x002D, + ACX_AVERAGE_RSSI = 0x002E, /* Not used */ + ACX_CONS_TX_FAILURE = 0x002F, + ACX_BCN_DTIM_OPTIONS = 0x0031, + ACX_SG_ENABLE = 0x0032, + ACX_SG_CFG = 0x0033, + ACX_ANTENNA_DIVERSITY_CFG = 0x0035, /* To Be Documented */ + ACX_LOW_SNR = 0x0037, /* To Be Documented */ + ACX_BEACON_FILTER_TABLE = 0x0038, + ACX_ARP_IP_FILTER = 0x0039, + ACX_ROAMING_STATISTICS_TBL = 0x003B, + ACX_RATE_POLICY = 0x003D, + ACX_CTS_PROTECTION = 0x003E, + ACX_SLEEP_AUTH = 0x003F, + ACX_PREAMBLE_TYPE = 0x0040, + ACX_ERROR_CNT = 0x0041, + ACX_FW_GEN_FRAME_RATES = 0x0042, + ACX_IBSS_FILTER = 0x0044, + ACX_SERVICE_PERIOD_TIMEOUT = 0x0045, + ACX_TSF_INFO = 0x0046, + ACX_CONFIG_PS_WMM = 0x0049, + ACX_ENABLE_RX_DATA_FILTER = 0x004A, + ACX_SET_RX_DATA_FILTER = 0x004B, + ACX_GET_DATA_FILTER_STATISTICS = 0x004C, + ACX_POWER_LEVEL_TABLE = 0x004D, + ACX_BET_ENABLE = 0x0050, + DOT11_STATION_ID = 0x1001, + DOT11_RX_MSDU_LIFE_TIME = 0x1004, + DOT11_CUR_TX_PWR = 0x100D, + DOT11_DEFAULT_KEY = 0x1010, + DOT11_RX_DOT11_MODE = 0x1012, + DOT11_RTS_THRESHOLD = 0x1013, + DOT11_GROUP_ADDRESS_TBL = 0x1014, + + MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, + + MAX_IE = 0xFFFF +}; + + +int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod, + u8 mgt_rate, u8 mgt_mod); +int wl12xx_acx_station_id(struct wl12xx *wl); +int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id); +int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval); +int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth); +int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len); +int wl12xx_acx_tx_power(struct wl12xx *wl, int power); +int wl12xx_acx_feature_cfg(struct wl12xx *wl); +int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len); +int wl12xx_acx_data_path_params(struct wl12xx *wl, + struct acx_data_path_params_resp *data_path); +int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time); +int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter); +int wl12xx_acx_pd_threshold(struct wl12xx *wl); +int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time); +int wl12xx_acx_group_address_tbl(struct wl12xx *wl); +int wl12xx_acx_service_period_timeout(struct wl12xx *wl); +int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold); +int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl); +int wl12xx_acx_beacon_filter_table(struct wl12xx *wl); +int wl12xx_acx_sg_enable(struct wl12xx *wl); +int wl12xx_acx_sg_cfg(struct wl12xx *wl); +int wl12xx_acx_cca_threshold(struct wl12xx *wl); +int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl); +int wl12xx_acx_aid(struct wl12xx *wl, u16 aid); +int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask); +int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble); +int wl12xx_acx_cts_protect(struct wl12xx *wl, + enum acx_ctsprotect_type ctsprotect); +int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats); + +#endif /* __WL12XX_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c new file mode 100644 index 000000000000..48ac08c429bd --- /dev/null +++ b/drivers/net/wireless/wl12xx/boot.c @@ -0,0 +1,295 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include + +#include "reg.h" +#include "boot.h" +#include "spi.h" +#include "event.h" + +static void wl12xx_boot_enable_interrupts(struct wl12xx *wl) +{ + enable_irq(wl->irq); +} + +void wl12xx_boot_target_enable_interrupts(struct wl12xx *wl) +{ + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); + wl12xx_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL); +} + +int wl12xx_boot_soft_reset(struct wl12xx *wl) +{ + unsigned long timeout; + u32 boot_data; + + /* perform soft reset */ + wl12xx_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); + + /* SOFT_RESET is self clearing */ + timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); + while (1) { + boot_data = wl12xx_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); + wl12xx_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); + if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) + break; + + if (time_after(jiffies, timeout)) { + /* 1.2 check pWhalBus->uSelfClearTime if the + * timeout was reached */ + wl12xx_error("soft reset timeout"); + return -1; + } + + udelay(SOFT_RESET_STALL_TIME); + } + + /* disable Rx/Tx */ + wl12xx_reg_write32(wl, ENABLE, 0x0); + + /* disable auto calibration on start*/ + wl12xx_reg_write32(wl, SPARE_A2, 0xffff); + + return 0; +} + +int wl12xx_boot_init_seq(struct wl12xx *wl) +{ + u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq; + + /* + * col #1: INTEGER_DIVIDER + * col #2: FRACTIONAL_DIVIDER + * col #3: ATTN_BB + * col #4: ALPHA_BB + * col #5: STOP_TIME_BB + * col #6: BB_PLL_LOOP_FILTER + */ + static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = { + + { 83, 87381, 0xB, 5, 0xF00, 3}, /* REF_FREQ_19_2*/ + { 61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/ + { 41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/ + { 40, 0, 0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/ + { 47, 162280, 0xC, 6, 0x2760, 1} /* REF_FREQ_33_6 */ + }; + + /* read NVS params */ + scr_pad6 = wl12xx_reg_read32(wl, SCR_PAD6); + wl12xx_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6); + + /* read ELP_CMD */ + elp_cmd = wl12xx_reg_read32(wl, ELP_CMD); + wl12xx_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd); + + /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */ + ref_freq = scr_pad6 & 0x000000FF; + wl12xx_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq); + + wl12xx_reg_write32(wl, PLL_CAL_TIME, 0x9); + + /* + * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME) + */ + wl12xx_reg_write32(wl, CLK_BUF_TIME, 0x6); + + /* + * set the clock detect feature to work in the restart wu procedure + * (ELP_CFG_MODE[14]) and Select the clock source type + * (ELP_CFG_MODE[13:12]) + */ + tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000; + wl12xx_reg_write32(wl, ELP_CFG_MODE, tmp); + + /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */ + elp_cmd |= 0x00000040; + wl12xx_reg_write32(wl, ELP_CMD, elp_cmd); + + /* PG 1.2: Set the BB PLL stable time to be 1000usec + * (PLL_STABLE_TIME) */ + wl12xx_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20); + + /* PG 1.2: read clock request time */ + init_data = wl12xx_reg_read32(wl, CLK_REQ_TIME); + + /* + * PG 1.2: set the clock request time to be ref_clk_settling_time - + * 1ms = 4ms + */ + if (init_data > 0x21) + tmp = init_data - 0x21; + else + tmp = 0; + wl12xx_reg_write32(wl, CLK_REQ_TIME, tmp); + + /* set BB PLL configurations in RF AFE */ + wl12xx_reg_write32(wl, 0x003058cc, 0x4B5); + + /* set RF_AFE_REG_5 */ + wl12xx_reg_write32(wl, 0x003058d4, 0x50); + + /* set RF_AFE_CTRL_REG_2 */ + wl12xx_reg_write32(wl, 0x00305948, 0x11c001); + + /* + * change RF PLL and BB PLL divider for VCO clock and adjust VCO + * bais current(RF_AFE_REG_13) + */ + wl12xx_reg_write32(wl, 0x003058f4, 0x1e); + + /* set BB PLL configurations */ + tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000; + wl12xx_reg_write32(wl, 0x00305840, tmp); + + /* set fractional divider according to Appendix C-BB PLL + * Calculations + */ + tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER]; + wl12xx_reg_write32(wl, 0x00305844, tmp); + + /* set the initial data for the sigma delta */ + wl12xx_reg_write32(wl, 0x00305848, 0x3039); + + /* + * set the accumulator attenuation value, calibration loop1 + * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and + * the VCO gain + */ + tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) | + (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1; + wl12xx_reg_write32(wl, 0x00305854, tmp); + + /* + * set the calibration stop time after holdoff time expires and set + * settling time HOLD_OFF_TIME_BB + */ + tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000; + wl12xx_reg_write32(wl, 0x00305858, tmp); + + /* + * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL + * constant leakage current to linearize PFD to 0uA - + * BB_ILOOPF[7:3] + */ + tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030; + wl12xx_reg_write32(wl, 0x003058f8, tmp); + + /* + * set regulator output voltage for n divider to + * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2], + * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB + * PLL auto-call to normal mode- BB_CALGAIN_3DB[8] + */ + wl12xx_reg_write32(wl, 0x003058f0, 0x29); + + /* enable restart wakeup sequence (ELP_CMD[0]) */ + wl12xx_reg_write32(wl, ELP_CMD, elp_cmd | 0x1); + + /* restart sequence completed */ + udelay(2000); + + return 0; +} + +int wl12xx_boot_run_firmware(struct wl12xx *wl) +{ + int loop, ret; + u32 chip_id, interrupt; + + wl->chip.op_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); + + chip_id = wl12xx_reg_read32(wl, CHIP_ID_B); + + wl12xx_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); + + if (chip_id != wl->chip.id) { + wl12xx_error("chip id doesn't match after firmware boot"); + return -EIO; + } + + /* wait for init to complete */ + loop = 0; + while (loop++ < INIT_LOOP) { + udelay(INIT_LOOP_DELAY); + interrupt = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + + if (interrupt == 0xffffffff) { + wl12xx_error("error reading hardware complete " + "init indication"); + return -EIO; + } + /* check that ACX_INTR_INIT_COMPLETE is enabled */ + else if (interrupt & wl->chip.intr_init_complete) { + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_ACK, + wl->chip.intr_init_complete); + break; + } + } + + if (loop >= INIT_LOOP) { + wl12xx_error("timeout waiting for the hardware to " + "complete initialization"); + return -EIO; + } + + /* get hardware config command mail box */ + wl->cmd_box_addr = wl12xx_reg_read32(wl, REG_COMMAND_MAILBOX_PTR); + + /* get hardware config event mail box */ + wl->event_box_addr = wl12xx_reg_read32(wl, REG_EVENT_MAILBOX_PTR); + + /* set the working partition to its "running" mode offset */ + wl12xx_set_partition(wl, + wl->chip.p_table[PART_WORK].mem.start, + wl->chip.p_table[PART_WORK].mem.size, + wl->chip.p_table[PART_WORK].reg.start, + wl->chip.p_table[PART_WORK].reg.size); + + wl12xx_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", + wl->cmd_box_addr, wl->event_box_addr); + + /* + * in case of full asynchronous mode the firmware event must be + * ready to receive event from the command mailbox + */ + + /* enable gpio interrupts */ + wl12xx_boot_enable_interrupts(wl); + + wl->chip.op_target_enable_interrupts(wl); + + /* unmask all mbox events */ + wl->event_mask = 0xffffffff; + + ret = wl12xx_event_unmask(wl); + if (ret < 0) { + wl12xx_error("EVENT mask setting failed"); + return ret; + } + + wl12xx_event_mbox_config(wl); + + /* firmware startup completed */ + return 0; +} diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h new file mode 100644 index 000000000000..4fa73132baae --- /dev/null +++ b/drivers/net/wireless/wl12xx/boot.h @@ -0,0 +1,40 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __BOOT_H__ +#define __BOOT_H__ + +#include "wl12xx.h" + +int wl12xx_boot_soft_reset(struct wl12xx *wl); +int wl12xx_boot_init_seq(struct wl12xx *wl); +int wl12xx_boot_run_firmware(struct wl12xx *wl); +void wl12xx_boot_target_enable_interrupts(struct wl12xx *wl); + +/* number of times we try to read the INIT interrupt */ +#define INIT_LOOP 20000 + +/* delay between retries */ +#define INIT_LOOP_DELAY 50 + +#endif diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c new file mode 100644 index 000000000000..f73ab602b7ae --- /dev/null +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -0,0 +1,353 @@ +#include "cmd.h" + +#include +#include +#include + +#include "wl12xx.h" +#include "wl12xx_80211.h" +#include "reg.h" +#include "spi.h" +#include "ps.h" + +int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len) +{ + struct wl12xx_command cmd; + unsigned long timeout; + size_t cmd_len; + u32 intr; + int ret = 0; + + memset(&cmd, 0, sizeof(cmd)); + cmd.id = type; + cmd.status = 0; + memcpy(cmd.parameters, buf, buf_len); + cmd_len = ALIGN(buf_len, 4) + CMDMBOX_HEADER_LEN; + + wl12xx_ps_elp_wakeup(wl); + + wl12xx_spi_mem_write(wl, wl->cmd_box_addr, &cmd, cmd_len); + + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); + + timeout = jiffies + msecs_to_jiffies(WL12XX_COMMAND_TIMEOUT); + + intr = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + while (!(intr & wl->chip.intr_cmd_complete)) { + if (time_after(jiffies, timeout)) { + wl12xx_error("command complete timeout"); + ret = -ETIMEDOUT; + goto out; + } + + msleep(1); + + intr = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + } + + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_ACK, + wl->chip.intr_cmd_complete); + +out: + wl12xx_ps_elp_sleep(wl); + + return ret; +} + +int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer) +{ + int ret; + + wl12xx_debug(DEBUG_CMD, "cmd test"); + + ret = wl12xx_cmd_send(wl, CMD_TEST, buf, buf_len); + if (ret < 0) { + wl12xx_warning("TEST command failed"); + return ret; + } + + if (answer) { + struct wl12xx_command *cmd_answer; + + /* + * The test command got in, we can read the answer. + * The answer would be a wl12xx_command, where the + * parameter array contains the actual answer. + */ + + wl12xx_ps_elp_wakeup(wl); + + wl12xx_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); + + wl12xx_ps_elp_sleep(wl); + + cmd_answer = buf; + if (cmd_answer->status != CMD_STATUS_SUCCESS) + wl12xx_error("TEST command answer error: %d", + cmd_answer->status); + } + + return 0; +} + + +int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 ie_id, u16 ie_len, + void *answer) +{ + struct wl12xx_command *cmd; + struct acx_header header; + int ret; + + wl12xx_debug(DEBUG_CMD, "cmd interrogate"); + + header.id = ie_id; + header.len = ie_len - sizeof(header); + + ret = wl12xx_cmd_send(wl, CMD_INTERROGATE, &header, sizeof(header)); + if (ret < 0) { + wl12xx_error("INTERROGATE command failed"); + return ret; + } + + wl12xx_ps_elp_wakeup(wl); + + /* the interrogate command got in, we can read the answer */ + wl12xx_spi_mem_read(wl, wl->cmd_box_addr, answer, + CMDMBOX_HEADER_LEN + ie_len); + + wl12xx_ps_elp_sleep(wl); + + cmd = answer; + if (cmd->status != CMD_STATUS_SUCCESS) + wl12xx_error("INTERROGATE command error: %d", + cmd->status); + + return 0; + +} + +int wl12xx_cmd_configure(struct wl12xx *wl, void *ie, int ie_len) +{ + int ret; + + wl12xx_debug(DEBUG_CMD, "cmd configure"); + + ret = wl12xx_cmd_send(wl, CMD_CONFIGURE, ie, + ie_len); + if (ret < 0) { + wl12xx_warning("CONFIGURE command NOK"); + return ret; + } + + return 0; + +} + +int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity, + void *bitmap, u16 bitmap_len, u8 bitmap_control) +{ + struct vbm_update_request vbm; + int ret; + + wl12xx_debug(DEBUG_CMD, "cmd vbm"); + + /* Count and period will be filled by the target */ + vbm.tim.bitmap_ctrl = bitmap_control; + if (bitmap_len > PARTIAL_VBM_MAX) { + wl12xx_warning("cmd vbm len is %d B, truncating to %d", + bitmap_len, PARTIAL_VBM_MAX); + bitmap_len = PARTIAL_VBM_MAX; + } + memcpy(vbm.tim.pvb_field, bitmap, bitmap_len); + vbm.tim.identity = identity; + vbm.tim.length = bitmap_len + 3; + + vbm.len = cpu_to_le16(bitmap_len + 5); + + ret = wl12xx_cmd_send(wl, CMD_VBM, &vbm, sizeof(vbm)); + if (ret < 0) { + wl12xx_error("VBM command failed"); + return ret; + } + + return 0; +} + +int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable) +{ + int ret; + u16 cmd_rx, cmd_tx; + + wl12xx_debug(DEBUG_CMD, "cmd data path"); + + if (enable) { + cmd_rx = CMD_ENABLE_RX; + cmd_tx = CMD_ENABLE_TX; + } else { + cmd_rx = CMD_DISABLE_RX; + cmd_tx = CMD_DISABLE_TX; + } + + ret = wl12xx_cmd_send(wl, cmd_rx, &channel, sizeof(channel)); + if (ret < 0) { + wl12xx_error("rx %s cmd for channel %d failed", + enable ? "start" : "stop", channel); + return ret; + } + + wl12xx_debug(DEBUG_BOOT, "rx %s cmd channel %d", + enable ? "start" : "stop", channel); + + ret = wl12xx_cmd_send(wl, cmd_tx, &channel, sizeof(channel)); + if (ret < 0) { + wl12xx_error("tx %s cmd for channel %d failed", + enable ? "start" : "stop", channel); + return ret; + } + + wl12xx_debug(DEBUG_BOOT, "tx %s cmd channel %d", + enable ? "start" : "stop", channel); + + return 0; +} + +int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, + u16 beacon_interval, u8 wait) +{ + unsigned long timeout; + struct cmd_join join = {}; + int ret, i; + u8 *bssid; + + /* FIXME: this should be in main.c */ + ret = wl12xx_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE, + DEFAULT_HW_GEN_MODULATION_TYPE, + wl->tx_mgmt_frm_rate, + wl->tx_mgmt_frm_mod); + if (ret < 0) + return ret; + + wl12xx_debug(DEBUG_CMD, "cmd join"); + + /* Reverse order BSSID */ + bssid = (u8 *)&join.bssid_lsb; + for (i = 0; i < ETH_ALEN; i++) + bssid[i] = wl->bssid[ETH_ALEN - i - 1]; + + join.rx_config_options = wl->rx_config; + join.rx_filter_options = wl->rx_filter; + + join.basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | + RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; + + join.beacon_interval = beacon_interval; + join.dtim_interval = dtim_interval; + join.bss_type = bss_type; + join.channel = wl->channel; + join.ctrl = JOIN_CMD_CTRL_TX_FLUSH; + + ret = wl12xx_cmd_send(wl, CMD_START_JOIN, &join, sizeof(join)); + if (ret < 0) { + wl12xx_error("failed to initiate cmd join"); + return ret; + } + + timeout = msecs_to_jiffies(JOIN_TIMEOUT); + + /* + * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to + * simplify locking we just sleep instead, for now + */ + if (wait) + msleep(10); + + return 0; +} + +int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode) +{ + int ret; + struct acx_ps_params ps_params; + + /* FIXME: this should be in ps.c */ + ret = wl12xx_acx_wake_up_conditions(wl, wl->listen_int); + if (ret < 0) { + wl12xx_error("Couldnt set wake up conditions"); + return ret; + } + + wl12xx_debug(DEBUG_CMD, "cmd set ps mode"); + + ps_params.ps_mode = ps_mode; + ps_params.send_null_data = 1; + ps_params.retries = 5; + ps_params.hang_over_period = 128; + ps_params.null_data_rate = 1; /* 1 Mbps */ + + ret = wl12xx_cmd_send(wl, CMD_SET_PS_MODE, &ps_params, + sizeof(ps_params)); + if (ret < 0) { + wl12xx_error("cmd set_ps_mode failed"); + return ret; + } + + return 0; +} + +int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, u32 len, void *answer) +{ + struct cmd_read_write_memory mem_cmd, *mem_answer; + struct wl12xx_command cmd; + int ret; + + wl12xx_debug(DEBUG_CMD, "cmd read memory"); + + memset(&mem_cmd, 0, sizeof(mem_cmd)); + mem_cmd.addr = addr; + mem_cmd.size = len; + + ret = wl12xx_cmd_send(wl, CMD_READ_MEMORY, &mem_cmd, sizeof(mem_cmd)); + if (ret < 0) { + wl12xx_error("read memory command failed: %d", ret); + return ret; + } + + /* the read command got in, we can now read the answer */ + wl12xx_spi_mem_read(wl, wl->cmd_box_addr, &cmd, + CMDMBOX_HEADER_LEN + sizeof(mem_cmd)); + + if (cmd.status != CMD_STATUS_SUCCESS) + wl12xx_error("error in read command result: %d", cmd.status); + + mem_answer = (struct cmd_read_write_memory *) cmd.parameters; + memcpy(answer, mem_answer->value, len); + + return 0; +} + +int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id, + void *buf, size_t buf_len) +{ + struct wl12xx_cmd_packet_template template; + int ret; + + wl12xx_debug(DEBUG_CMD, "cmd template %d", cmd_id); + + memset(&template, 0, sizeof(template)); + + WARN_ON(buf_len > WL12XX_MAX_TEMPLATE_SIZE); + buf_len = min_t(size_t, buf_len, WL12XX_MAX_TEMPLATE_SIZE); + template.size = cpu_to_le16(buf_len); + + if (buf) + memcpy(template.template, buf, buf_len); + + ret = wl12xx_cmd_send(wl, cmd_id, &template, + sizeof(template.size) + buf_len); + if (ret < 0) { + wl12xx_warning("cmd set_template failed: %d", ret); + return ret; + } + + return 0; +} diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h new file mode 100644 index 000000000000..aa307dcd081f --- /dev/null +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -0,0 +1,265 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_CMD_H__ +#define __WL12XX_CMD_H__ + +#include "wl12xx.h" + +int wl12xx_cmd_send(struct wl12xx *wl, u16 type, void *buf, size_t buf_len); +int wl12xx_cmd_test(struct wl12xx *wl, void *buf, size_t buf_len, u8 answer); +int wl12xx_cmd_interrogate(struct wl12xx *wl, u16 ie_id, u16 ie_len, + void *answer); +int wl12xx_cmd_configure(struct wl12xx *wl, void *ie, int ie_len); +int wl12xx_cmd_vbm(struct wl12xx *wl, u8 identity, + void *bitmap, u16 bitmap_len, u8 bitmap_control); +int wl12xx_cmd_data_path(struct wl12xx *wl, u8 channel, u8 enable); +int wl12xx_cmd_join(struct wl12xx *wl, u8 bss_type, u8 dtim_interval, + u16 beacon_interval, u8 wait); +int wl12xx_cmd_ps_mode(struct wl12xx *wl, u8 ps_mode); +int wl12xx_cmd_read_memory(struct wl12xx *wl, u32 addr, u32 len, void *answer); +int wl12xx_cmd_template_set(struct wl12xx *wl, u16 cmd_id, + void *buf, size_t buf_len); + +/* unit ms */ +#define WL12XX_COMMAND_TIMEOUT 2000 + +#define WL12XX_MAX_TEMPLATE_SIZE 300 + +struct wl12xx_cmd_packet_template { + __le16 size; + u8 template[WL12XX_MAX_TEMPLATE_SIZE]; +} __attribute__ ((packed)); + +enum wl12xx_commands { + CMD_RESET = 0, + CMD_INTERROGATE = 1, /*use this to read information elements*/ + CMD_CONFIGURE = 2, /*use this to write information elements*/ + CMD_ENABLE_RX = 3, + CMD_ENABLE_TX = 4, + CMD_DISABLE_RX = 5, + CMD_DISABLE_TX = 6, + CMD_SCAN = 8, + CMD_STOP_SCAN = 9, + CMD_VBM = 10, + CMD_START_JOIN = 11, + CMD_SET_KEYS = 12, + CMD_READ_MEMORY = 13, + CMD_WRITE_MEMORY = 14, + CMD_BEACON = 19, + CMD_PROBE_RESP = 20, + CMD_NULL_DATA = 21, + CMD_PROBE_REQ = 22, + CMD_TEST = 23, + CMD_RADIO_CALIBRATE = 25, /* OBSOLETE */ + CMD_ENABLE_RX_PATH = 27, /* OBSOLETE */ + CMD_NOISE_HIST = 28, + CMD_RX_RESET = 29, + CMD_PS_POLL = 30, + CMD_QOS_NULL_DATA = 31, + CMD_LNA_CONTROL = 32, + CMD_SET_BCN_MODE = 33, + CMD_MEASUREMENT = 34, + CMD_STOP_MEASUREMENT = 35, + CMD_DISCONNECT = 36, + CMD_SET_PS_MODE = 37, + CMD_CHANNEL_SWITCH = 38, + CMD_STOP_CHANNEL_SWICTH = 39, + CMD_AP_DISCOVERY = 40, + CMD_STOP_AP_DISCOVERY = 41, + CMD_SPS_SCAN = 42, + CMD_STOP_SPS_SCAN = 43, + CMD_HEALTH_CHECK = 45, + CMD_DEBUG = 46, + CMD_TRIGGER_SCAN_TO = 47, + + NUM_COMMANDS, + MAX_COMMAND_ID = 0xFFFF, +}; + +#define MAX_CMD_PARAMS 572 + +struct wl12xx_command { + u16 id; + u16 status; + u8 parameters[MAX_CMD_PARAMS]; +}; + +enum { + CMD_MAILBOX_IDLE = 0, + CMD_STATUS_SUCCESS = 1, + CMD_STATUS_UNKNOWN_CMD = 2, + CMD_STATUS_UNKNOWN_IE = 3, + CMD_STATUS_REJECT_MEAS_SG_ACTIVE = 11, + CMD_STATUS_RX_BUSY = 13, + CMD_STATUS_INVALID_PARAM = 14, + CMD_STATUS_TEMPLATE_TOO_LARGE = 15, + CMD_STATUS_OUT_OF_MEMORY = 16, + CMD_STATUS_STA_TABLE_FULL = 17, + CMD_STATUS_RADIO_ERROR = 18, + CMD_STATUS_WRONG_NESTING = 19, + CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ + CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ + MAX_COMMAND_STATUS = 0xff +}; + + +/* + * CMD_READ_MEMORY + * + * The host issues this command to read the WiLink device memory/registers. + * + * Note: The Base Band address has special handling (16 bits registers and + * addresses). For more information, see the hardware specification. + */ +/* + * CMD_WRITE_MEMORY + * + * The host issues this command to write the WiLink device memory/registers. + * + * The Base Band address has special handling (16 bits registers and + * addresses). For more information, see the hardware specification. + */ +#define MAX_READ_SIZE 256 + +struct cmd_read_write_memory { + /* The address of the memory to read from or write to.*/ + u32 addr; + + /* The amount of data in bytes to read from or write to the WiLink + * device.*/ + u32 size; + + /* The actual value read from or written to the Wilink. The source + of this field is the Host in WRITE command or the Wilink in READ + command. */ + u8 value[MAX_READ_SIZE]; +}; + +#define CMDMBOX_HEADER_LEN 4 +#define CMDMBOX_INFO_ELEM_HEADER_LEN 4 + + +struct basic_scan_parameters { + u32 rx_config_options; + u32 rx_filter_options; + + /* + * Scan options: + * bit 0: When this bit is set, passive scan. + * bit 1: Band, when this bit is set we scan + * in the 5Ghz band. + * bit 2: voice mode, 0 for normal scan. + * bit 3: scan priority, 1 for high priority. + */ + u16 scan_options; + + /* Number of channels to scan */ + u8 num_channels; + + /* Number opf probe requests to send, per channel */ + u8 num_probe_requests; + + /* Rate and modulation for probe requests */ + u16 tx_rate; + + u8 tid_trigger; + u8 ssid_len; + u32 ssid[8]; + +} __attribute__ ((packed)); + +struct basic_scan_channel_parameters { + u32 min_duration; /* in TU */ + u32 max_duration; /* in TU */ + u32 bssid_lsb; + u16 bssid_msb; + + /* + * bits 0-3: Early termination count. + * bits 4-5: Early termination condition. + */ + u8 early_termination; + + u8 tx_power_att; + u8 channel; + u8 pad[3]; +} __attribute__ ((packed)); + +/* SCAN parameters */ +#define SCAN_MAX_NUM_OF_CHANNELS 16 + +struct cmd_scan { + struct basic_scan_parameters params; + struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; +} __attribute__ ((packed)); + +enum { + BSS_TYPE_IBSS = 0, + BSS_TYPE_STA_BSS = 2, + BSS_TYPE_AP_BSS = 3, + MAX_BSS_TYPE = 0xFF +}; + +#define JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ +#define JOIN_CMD_CTRL_EARLY_WAKEUP_ENABLE 0x01 /* Early wakeup time */ + + +struct cmd_join { + u32 bssid_lsb; + u16 bssid_msb; + u16 beacon_interval; /* in TBTTs */ + u32 rx_config_options; + u32 rx_filter_options; + + /* + * The target uses this field to determine the rate at + * which to transmit control frame responses (such as + * ACK or CTS frames). + */ + u16 basic_rate_set; + u8 dtim_interval; + u8 tx_ctrl_frame_rate; /* OBSOLETE */ + u8 tx_ctrl_frame_mod; /* OBSOLETE */ + /* + * bits 0-2: This bitwise field specifies the type + * of BSS to start or join (BSS_TYPE_*). + * bit 4: Band - The radio band in which to join + * or start. + * 0 - 2.4GHz band + * 1 - 5GHz band + * bits 3, 5-7: Reserved + */ + u8 bss_type; + u8 channel; + u8 ssid_len; + u8 ssid[IW_ESSID_MAX_SIZE]; + u8 ctrl; /* JOIN_CMD_CTRL_* */ + u8 tx_mgt_frame_rate; /* OBSOLETE */ + u8 tx_mgt_frame_mod; /* OBSOLETE */ + u8 reserved; +} __attribute__ ((packed)); + + +#endif /* __WL12XX_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c new file mode 100644 index 000000000000..cdb368ce4dae --- /dev/null +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -0,0 +1,508 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "debugfs.h" + +#include + +#include "wl12xx.h" +#include "acx.h" + +/* ms */ +#define WL12XX_DEBUGFS_STATS_LIFETIME 1000 + +/* debugfs macros idea from mac80211 */ + +#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ +static ssize_t name## _read(struct file *file, char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wl12xx *wl = file->private_data; \ + char buf[buflen]; \ + int res; \ + \ + res = scnprintf(buf, buflen, fmt "\n", ##value); \ + return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ +} \ + \ +static const struct file_operations name## _ops = { \ + .read = name## _read, \ + .open = wl12xx_open_file_generic, \ +}; + +#define DEBUGFS_ADD(name, parent) \ + wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ + wl, &name## _ops); \ + if (IS_ERR(wl->debugfs.name)) { \ + ret = PTR_ERR(wl->debugfs.name); \ + wl->debugfs.name = NULL; \ + goto out; \ + } + +#define DEBUGFS_DEL(name) \ + do { \ + debugfs_remove(wl->debugfs.name); \ + wl->debugfs.name = NULL; \ + } while (0) + +#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ +static ssize_t sub## _ ##name## _read(struct file *file, \ + char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wl12xx *wl = file->private_data; \ + char buf[buflen]; \ + int res; \ + \ + wl12xx_debugfs_update_stats(wl); \ + \ + res = scnprintf(buf, buflen, fmt "\n", \ + wl->stats.fw_stats->sub.name); \ + return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ +} \ + \ +static const struct file_operations sub## _ ##name## _ops = { \ + .read = sub## _ ##name## _read, \ + .open = wl12xx_open_file_generic, \ +}; + +#define DEBUGFS_FWSTATS_ADD(sub, name) \ + DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) + +#define DEBUGFS_FWSTATS_DEL(sub, name) \ + DEBUGFS_DEL(sub## _ ##name) + +static void wl12xx_debugfs_update_stats(struct wl12xx *wl) +{ + mutex_lock(&wl->mutex); + + if (wl->state == WL12XX_STATE_ON && + time_after(jiffies, wl->stats.fw_stats_update + + msecs_to_jiffies(WL12XX_DEBUGFS_STATS_LIFETIME))) { + wl12xx_acx_statistics(wl, wl->stats.fw_stats); + wl->stats.fw_stats_update = jiffies; + } + + mutex_unlock(&wl->mutex); +} + +static int wl12xx_open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); +DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); +DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); +DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); +/* skipping wep.reserved */ +DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); +DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); +DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); +DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); +/* skipping cont_miss_bcns_spread for now */ +DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); +DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); +DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); + +DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, + 20, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); + +DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); +DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", + wl->stats.excessive_retries); + +static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct wl12xx *wl = file->private_data; + u32 queue_len; + char buf[20]; + int res; + + queue_len = skb_queue_len(&wl->tx_queue); + + res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); + return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} + +static const struct file_operations tx_queue_len_ops = { + .read = tx_queue_len_read, + .open = wl12xx_open_file_generic, +}; + +static void wl12xx_debugfs_delete_files(struct wl12xx *wl) +{ + DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); + + DEBUGFS_FWSTATS_DEL(rx, out_of_mem); + DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); + DEBUGFS_FWSTATS_DEL(rx, hw_stuck); + DEBUGFS_FWSTATS_DEL(rx, dropped); + DEBUGFS_FWSTATS_DEL(rx, fcs_err); + DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); + DEBUGFS_FWSTATS_DEL(rx, path_reset); + DEBUGFS_FWSTATS_DEL(rx, reset_counter); + + DEBUGFS_FWSTATS_DEL(dma, rx_requested); + DEBUGFS_FWSTATS_DEL(dma, rx_errors); + DEBUGFS_FWSTATS_DEL(dma, tx_requested); + DEBUGFS_FWSTATS_DEL(dma, tx_errors); + + DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); + DEBUGFS_FWSTATS_DEL(isr, fiqs); + DEBUGFS_FWSTATS_DEL(isr, rx_headers); + DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); + DEBUGFS_FWSTATS_DEL(isr, rx_rdys); + DEBUGFS_FWSTATS_DEL(isr, irqs); + DEBUGFS_FWSTATS_DEL(isr, tx_procs); + DEBUGFS_FWSTATS_DEL(isr, decrypt_done); + DEBUGFS_FWSTATS_DEL(isr, dma0_done); + DEBUGFS_FWSTATS_DEL(isr, dma1_done); + DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); + DEBUGFS_FWSTATS_DEL(isr, commands); + DEBUGFS_FWSTATS_DEL(isr, rx_procs); + DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); + DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); + DEBUGFS_FWSTATS_DEL(isr, pci_pm); + DEBUGFS_FWSTATS_DEL(isr, wakeups); + DEBUGFS_FWSTATS_DEL(isr, low_rssi); + + DEBUGFS_FWSTATS_DEL(wep, addr_key_count); + DEBUGFS_FWSTATS_DEL(wep, default_key_count); + /* skipping wep.reserved */ + DEBUGFS_FWSTATS_DEL(wep, key_not_found); + DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); + DEBUGFS_FWSTATS_DEL(wep, packets); + DEBUGFS_FWSTATS_DEL(wep, interrupt); + + DEBUGFS_FWSTATS_DEL(pwr, ps_enter); + DEBUGFS_FWSTATS_DEL(pwr, elp_enter); + DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); + DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); + DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); + DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); + DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); + DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); + DEBUGFS_FWSTATS_DEL(pwr, power_save_off); + DEBUGFS_FWSTATS_DEL(pwr, enable_ps); + DEBUGFS_FWSTATS_DEL(pwr, disable_ps); + DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); + /* skipping cont_miss_bcns_spread for now */ + DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); + + DEBUGFS_FWSTATS_DEL(mic, rx_pkts); + DEBUGFS_FWSTATS_DEL(mic, calc_failure); + + DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); + DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); + DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); + DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); + DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); + DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); + + DEBUGFS_FWSTATS_DEL(event, heart_beat); + DEBUGFS_FWSTATS_DEL(event, calibration); + DEBUGFS_FWSTATS_DEL(event, rx_mismatch); + DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); + DEBUGFS_FWSTATS_DEL(event, rx_pool); + DEBUGFS_FWSTATS_DEL(event, oom_late); + DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); + DEBUGFS_FWSTATS_DEL(event, tx_stuck); + + DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); + DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); + DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); + DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); + DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); + DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); + DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); + + DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); + DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); + DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); + DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); + DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); + + DEBUGFS_DEL(tx_queue_len); + DEBUGFS_DEL(retry_count); + DEBUGFS_DEL(excessive_retries); +} + +static int wl12xx_debugfs_add_files(struct wl12xx *wl) +{ + int ret = 0; + + DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); + + DEBUGFS_FWSTATS_ADD(rx, out_of_mem); + DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); + DEBUGFS_FWSTATS_ADD(rx, hw_stuck); + DEBUGFS_FWSTATS_ADD(rx, dropped); + DEBUGFS_FWSTATS_ADD(rx, fcs_err); + DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); + DEBUGFS_FWSTATS_ADD(rx, path_reset); + DEBUGFS_FWSTATS_ADD(rx, reset_counter); + + DEBUGFS_FWSTATS_ADD(dma, rx_requested); + DEBUGFS_FWSTATS_ADD(dma, rx_errors); + DEBUGFS_FWSTATS_ADD(dma, tx_requested); + DEBUGFS_FWSTATS_ADD(dma, tx_errors); + + DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); + DEBUGFS_FWSTATS_ADD(isr, fiqs); + DEBUGFS_FWSTATS_ADD(isr, rx_headers); + DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); + DEBUGFS_FWSTATS_ADD(isr, rx_rdys); + DEBUGFS_FWSTATS_ADD(isr, irqs); + DEBUGFS_FWSTATS_ADD(isr, tx_procs); + DEBUGFS_FWSTATS_ADD(isr, decrypt_done); + DEBUGFS_FWSTATS_ADD(isr, dma0_done); + DEBUGFS_FWSTATS_ADD(isr, dma1_done); + DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); + DEBUGFS_FWSTATS_ADD(isr, commands); + DEBUGFS_FWSTATS_ADD(isr, rx_procs); + DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); + DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); + DEBUGFS_FWSTATS_ADD(isr, pci_pm); + DEBUGFS_FWSTATS_ADD(isr, wakeups); + DEBUGFS_FWSTATS_ADD(isr, low_rssi); + + DEBUGFS_FWSTATS_ADD(wep, addr_key_count); + DEBUGFS_FWSTATS_ADD(wep, default_key_count); + /* skipping wep.reserved */ + DEBUGFS_FWSTATS_ADD(wep, key_not_found); + DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); + DEBUGFS_FWSTATS_ADD(wep, packets); + DEBUGFS_FWSTATS_ADD(wep, interrupt); + + DEBUGFS_FWSTATS_ADD(pwr, ps_enter); + DEBUGFS_FWSTATS_ADD(pwr, elp_enter); + DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); + DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); + DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); + DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); + DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); + DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); + DEBUGFS_FWSTATS_ADD(pwr, power_save_off); + DEBUGFS_FWSTATS_ADD(pwr, enable_ps); + DEBUGFS_FWSTATS_ADD(pwr, disable_ps); + DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); + /* skipping cont_miss_bcns_spread for now */ + DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); + + DEBUGFS_FWSTATS_ADD(mic, rx_pkts); + DEBUGFS_FWSTATS_ADD(mic, calc_failure); + + DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); + DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); + DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); + DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); + DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); + DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); + + DEBUGFS_FWSTATS_ADD(event, heart_beat); + DEBUGFS_FWSTATS_ADD(event, calibration); + DEBUGFS_FWSTATS_ADD(event, rx_mismatch); + DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); + DEBUGFS_FWSTATS_ADD(event, rx_pool); + DEBUGFS_FWSTATS_ADD(event, oom_late); + DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); + DEBUGFS_FWSTATS_ADD(event, tx_stuck); + + DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); + DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); + DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); + DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); + DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); + DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); + DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); + + DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); + DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); + + DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); + DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); + DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); + +out: + if (ret < 0) + wl12xx_debugfs_delete_files(wl); + + return ret; +} + +void wl12xx_debugfs_reset(struct wl12xx *wl) +{ + memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); + wl->stats.retry_count = 0; + wl->stats.excessive_retries = 0; +} + +int wl12xx_debugfs_init(struct wl12xx *wl) +{ + int ret; + + wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); + + if (IS_ERR(wl->debugfs.rootdir)) { + ret = PTR_ERR(wl->debugfs.rootdir); + wl->debugfs.rootdir = NULL; + goto err; + } + + wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", + wl->debugfs.rootdir); + + if (IS_ERR(wl->debugfs.fw_statistics)) { + ret = PTR_ERR(wl->debugfs.fw_statistics); + wl->debugfs.fw_statistics = NULL; + goto err_root; + } + + wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), + GFP_KERNEL); + + if (!wl->stats.fw_stats) { + ret = -ENOMEM; + goto err_fw; + } + + wl->stats.fw_stats_update = jiffies; + + ret = wl12xx_debugfs_add_files(wl); + + if (ret < 0) + goto err_file; + + return 0; + +err_file: + kfree(wl->stats.fw_stats); + wl->stats.fw_stats = NULL; + +err_fw: + debugfs_remove(wl->debugfs.fw_statistics); + wl->debugfs.fw_statistics = NULL; + +err_root: + debugfs_remove(wl->debugfs.rootdir); + wl->debugfs.rootdir = NULL; + +err: + return ret; +} + +void wl12xx_debugfs_exit(struct wl12xx *wl) +{ + wl12xx_debugfs_delete_files(wl); + + kfree(wl->stats.fw_stats); + wl->stats.fw_stats = NULL; + + debugfs_remove(wl->debugfs.fw_statistics); + wl->debugfs.fw_statistics = NULL; + + debugfs_remove(wl->debugfs.rootdir); + wl->debugfs.rootdir = NULL; + +} diff --git a/drivers/net/wireless/wl12xx/debugfs.h b/drivers/net/wireless/wl12xx/debugfs.h new file mode 100644 index 000000000000..562cdcbcc874 --- /dev/null +++ b/drivers/net/wireless/wl12xx/debugfs.h @@ -0,0 +1,33 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef WL12XX_DEBUGFS_H +#define WL12XX_DEBUGFS_H + +#include "wl12xx.h" + +int wl12xx_debugfs_init(struct wl12xx *wl); +void wl12xx_debugfs_exit(struct wl12xx *wl); +void wl12xx_debugfs_reset(struct wl12xx *wl); + +#endif /* WL12XX_DEBUGFS_H */ diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c new file mode 100644 index 000000000000..99529ca89a7e --- /dev/null +++ b/drivers/net/wireless/wl12xx/event.c @@ -0,0 +1,127 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "wl12xx.h" +#include "reg.h" +#include "spi.h" +#include "event.h" +#include "ps.h" + +static int wl12xx_event_scan_complete(struct wl12xx *wl, + struct event_mailbox *mbox) +{ + wl12xx_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", + mbox->scheduled_scan_status, + mbox->scheduled_scan_channels); + + if (wl->scanning) { + mutex_unlock(&wl->mutex); + ieee80211_scan_completed(wl->hw, false); + mutex_lock(&wl->mutex); + wl->scanning = false; + } + + return 0; +} + +static void wl12xx_event_mbox_dump(struct event_mailbox *mbox) +{ + wl12xx_debug(DEBUG_EVENT, "MBOX DUMP:"); + wl12xx_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); + wl12xx_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); +} + +static int wl12xx_event_process(struct wl12xx *wl, struct event_mailbox *mbox) +{ + int ret; + u32 vector; + + wl12xx_event_mbox_dump(mbox); + + vector = mbox->events_vector & ~(mbox->events_mask); + wl12xx_debug(DEBUG_EVENT, "vector: 0x%x", vector); + + if (vector & SCAN_COMPLETE_EVENT_ID) { + ret = wl12xx_event_scan_complete(wl, mbox); + if (ret < 0) + return ret; + } + + if (vector & BSS_LOSE_EVENT_ID) { + wl12xx_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); + + if (wl->psm_requested && wl->psm) { + ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE); + if (ret < 0) + return ret; + } + } + + return 0; +} + +int wl12xx_event_unmask(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_event_mbox_mask(wl, ~(wl->event_mask)); + if (ret < 0) + return ret; + + return 0; +} + +void wl12xx_event_mbox_config(struct wl12xx *wl) +{ + wl->mbox_ptr[0] = wl12xx_reg_read32(wl, REG_EVENT_MAILBOX_PTR); + wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); + + wl12xx_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", + wl->mbox_ptr[0], wl->mbox_ptr[1]); +} + +int wl12xx_event_handle(struct wl12xx *wl, u8 mbox_num) +{ + struct event_mailbox mbox; + int ret; + + wl12xx_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); + + if (mbox_num > 1) + return -EINVAL; + + /* first we read the mbox descriptor */ + wl12xx_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, + sizeof(struct event_mailbox)); + + /* process the descriptor */ + ret = wl12xx_event_process(wl, &mbox); + if (ret < 0) + return ret; + + /* then we let the firmware know it can go on...*/ + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); + + return 0; +} diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h new file mode 100644 index 000000000000..1f4c2f7438a7 --- /dev/null +++ b/drivers/net/wireless/wl12xx/event.h @@ -0,0 +1,121 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_EVENT_H__ +#define __WL12XX_EVENT_H__ + +/* + * Mbox events + * + * The event mechanism is based on a pair of event buffers (buffers A and + * B) at fixed locations in the target's memory. The host processes one + * buffer while the other buffer continues to collect events. If the host + * is not processing events, an interrupt is issued to signal that a buffer + * is ready. Once the host is done with processing events from one buffer, + * it signals the target (with an ACK interrupt) that the event buffer is + * free. + */ + +enum { + RESERVED1_EVENT_ID = BIT(0), + RESERVED2_EVENT_ID = BIT(1), + MEASUREMENT_START_EVENT_ID = BIT(2), + SCAN_COMPLETE_EVENT_ID = BIT(3), + CALIBRATION_COMPLETE_EVENT_ID = BIT(4), + ROAMING_TRIGGER_LOW_RSSI_EVENT_ID = BIT(5), + PS_REPORT_EVENT_ID = BIT(6), + SYNCHRONIZATION_TIMEOUT_EVENT_ID = BIT(7), + HEALTH_REPORT_EVENT_ID = BIT(8), + ACI_DETECTION_EVENT_ID = BIT(9), + DEBUG_REPORT_EVENT_ID = BIT(10), + MAC_STATUS_EVENT_ID = BIT(11), + DISCONNECT_EVENT_COMPLETE_ID = BIT(12), + JOIN_EVENT_COMPLETE_ID = BIT(13), + CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(14), + BSS_LOSE_EVENT_ID = BIT(15), + ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(16), + MEASUREMENT_COMPLETE_EVENT_ID = BIT(17), + AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(18), + SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(19), + PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(20), + RESET_BSS_EVENT_ID = BIT(21), + REGAINED_BSS_EVENT_ID = BIT(22), + ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID = BIT(23), + ROAMING_TRIGGER_LOW_SNR_EVENT_ID = BIT(24), + ROAMING_TRIGGER_REGAINED_SNR_EVENT_ID = BIT(25), + + DBG_EVENT_ID = BIT(26), + BT_PTA_SENSE_EVENT_ID = BIT(27), + BT_PTA_PREDICTION_EVENT_ID = BIT(28), + BT_PTA_AVALANCHE_EVENT_ID = BIT(29), + + PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(30), + + EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, +}; + +struct event_debug_report { + u8 debug_event_id; + u8 num_params; + u16 pad; + u32 report_1; + u32 report_2; + u32 report_3; +} __attribute__ ((packed)); + +struct event_mailbox { + u32 events_vector; + u32 events_mask; + u32 reserved_1; + u32 reserved_2; + + char average_rssi_level; + u8 ps_status; + u8 channel_switch_status; + u8 scheduled_scan_status; + + /* Channels scanned by the scheduled scan */ + u16 scheduled_scan_channels; + + /* If bit 0 is set -> target's fatal error */ + u16 health_report; + u16 bad_fft_counter; + u8 bt_pta_sense_info; + u8 bt_pta_protective_info; + u32 reserved; + u32 debug_report[2]; + + /* Number of FCS errors since last event */ + u32 fcs_err_counter; + + struct event_debug_report report; + u8 average_snr_level; + u8 padding[19]; +} __attribute__ ((packed)); + +int wl12xx_event_unmask(struct wl12xx *wl); +void wl12xx_event_mbox_config(struct wl12xx *wl); +int wl12xx_event_handle(struct wl12xx *wl, u8 mbox); + +#endif diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c new file mode 100644 index 000000000000..2a573a6010bd --- /dev/null +++ b/drivers/net/wireless/wl12xx/init.c @@ -0,0 +1,200 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include + +#include "init.h" +#include "wl12xx_80211.h" +#include "acx.h" +#include "cmd.h" + +int wl12xx_hw_init_hwenc_config(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_feature_cfg(wl); + if (ret < 0) { + wl12xx_warning("couldn't set feature config"); + return ret; + } + + ret = wl12xx_acx_default_key(wl, wl->default_key); + if (ret < 0) { + wl12xx_warning("couldn't set default key"); + return ret; + } + + return 0; +} + +int wl12xx_hw_init_templates_config(struct wl12xx *wl) +{ + int ret; + u8 partial_vbm[PARTIAL_VBM_MAX]; + + /* send empty templates for fw memory reservation */ + ret = wl12xx_cmd_template_set(wl, CMD_PROBE_REQ, NULL, + sizeof(struct wl12xx_probe_req_template)); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_template_set(wl, CMD_NULL_DATA, NULL, + sizeof(struct wl12xx_null_data_template)); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_template_set(wl, CMD_PS_POLL, NULL, + sizeof(struct wl12xx_ps_poll_template)); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL, + sizeof + (struct wl12xx_qos_null_data_template)); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_template_set(wl, CMD_PROBE_RESP, NULL, + sizeof + (struct wl12xx_probe_resp_template)); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_template_set(wl, CMD_BEACON, NULL, + sizeof + (struct wl12xx_beacon_template)); + if (ret < 0) + return ret; + + /* tim templates, first reserve space then allocate an empty one */ + memset(partial_vbm, 0, PARTIAL_VBM_MAX); + ret = wl12xx_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_rx_config(struct wl12xx *wl, u32 config, u32 filter) +{ + int ret; + + ret = wl12xx_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); + if (ret < 0) + return ret; + + ret = wl12xx_acx_rx_config(wl, config, filter); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_phy_config(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_pd_threshold(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_slot(wl, DEFAULT_SLOT_TIME); + if (ret < 0) + return ret; + + ret = wl12xx_acx_group_address_tbl(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_service_period_timeout(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_beacon_filter(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_beacon_filter_opt(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_beacon_filter_table(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_pta(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_sg_enable(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_sg_cfg(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_energy_detection(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_cca_threshold(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_beacon_broadcast(struct wl12xx *wl) +{ + int ret; + + ret = wl12xx_acx_bcn_dtim_options(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_hw_init_power_auth(struct wl12xx *wl) +{ + return wl12xx_acx_sleep_auth(wl, WL12XX_PSM_CAM); +} diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h new file mode 100644 index 000000000000..c8b6cd0b7c3e --- /dev/null +++ b/drivers/net/wireless/wl12xx/init.h @@ -0,0 +1,40 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_INIT_H__ +#define __WL12XX_INIT_H__ + +#include "wl12xx.h" + +int wl12xx_hw_init_hwenc_config(struct wl12xx *wl); +int wl12xx_hw_init_templates_config(struct wl12xx *wl); +int wl12xx_hw_init_mem_config(struct wl12xx *wl); +int wl12xx_hw_init_rx_config(struct wl12xx *wl, u32 config, u32 filter); +int wl12xx_hw_init_phy_config(struct wl12xx *wl); +int wl12xx_hw_init_beacon_filter(struct wl12xx *wl); +int wl12xx_hw_init_pta(struct wl12xx *wl); +int wl12xx_hw_init_energy_detection(struct wl12xx *wl); +int wl12xx_hw_init_beacon_broadcast(struct wl12xx *wl); +int wl12xx_hw_init_power_auth(struct wl12xx *wl); + +#endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c new file mode 100644 index 000000000000..744f4ce5993b --- /dev/null +++ b/drivers/net/wireless/wl12xx/main.c @@ -0,0 +1,1358 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wl12xx.h" +#include "wl12xx_80211.h" +#include "reg.h" +#include "wl1251.h" +#include "spi.h" +#include "event.h" +#include "tx.h" +#include "rx.h" +#include "ps.h" +#include "init.h" +#include "debugfs.h" + +static void wl12xx_disable_interrupts(struct wl12xx *wl) +{ + disable_irq(wl->irq); +} + +static void wl12xx_power_off(struct wl12xx *wl) +{ + wl->set_power(false); +} + +static void wl12xx_power_on(struct wl12xx *wl) +{ + wl->set_power(true); +} + +static irqreturn_t wl12xx_irq(int irq, void *cookie) +{ + struct wl12xx *wl; + + wl12xx_debug(DEBUG_IRQ, "IRQ"); + + wl = cookie; + + schedule_work(&wl->irq_work); + + return IRQ_HANDLED; +} + +static int wl12xx_fetch_firmware(struct wl12xx *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, wl->chip.fw_filename, &wl->spi->dev); + + if (ret < 0) { + wl12xx_error("could not get firmware: %d", ret); + return ret; + } + + if (fw->size % 4) { + wl12xx_error("firmware size is not multiple of 32 bits: %d", + fw->size); + ret = -EILSEQ; + goto out; + } + + wl->fw_len = fw->size; + wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); + + if (!wl->fw) { + wl12xx_error("could not allocate memory for the firmware"); + ret = -ENOMEM; + goto out; + } + + memcpy(wl->fw, fw->data, wl->fw_len); + + ret = 0; + +out: + release_firmware(fw); + + return ret; +} + +static int wl12xx_fetch_nvs(struct wl12xx *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, wl->chip.nvs_filename, &wl->spi->dev); + + if (ret < 0) { + wl12xx_error("could not get nvs file: %d", ret); + return ret; + } + + if (fw->size % 4) { + wl12xx_error("nvs size is not multiple of 32 bits: %d", + fw->size); + ret = -EILSEQ; + goto out; + } + + wl->nvs_len = fw->size; + wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); + + if (!wl->nvs) { + wl12xx_error("could not allocate memory for the nvs file"); + ret = -ENOMEM; + goto out; + } + + memcpy(wl->nvs, fw->data, wl->nvs_len); + + ret = 0; + +out: + release_firmware(fw); + + return ret; +} + +static void wl12xx_fw_wakeup(struct wl12xx *wl) +{ + u32 elp_reg; + + elp_reg = ELPCTRL_WAKE_UP; + wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); + elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + + if (!(elp_reg & ELPCTRL_WLAN_READY)) { + wl12xx_warning("WLAN not ready"); + elp_reg = ELPCTRL_WAKE_UP_WLAN_READY; + wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); + } +} + +static int wl12xx_chip_wakeup(struct wl12xx *wl) +{ + int ret = 0; + + wl12xx_power_on(wl); + msleep(wl->chip.power_on_sleep); + wl12xx_spi_reset(wl); + wl12xx_spi_init(wl); + + /* We don't need a real memory partition here, because we only want + * to use the registers at this point. */ + wl12xx_set_partition(wl, + 0x00000000, + 0x00000000, + REGISTERS_BASE, + REGISTERS_DOWN_SIZE); + + /* ELP module wake up */ + wl12xx_fw_wakeup(wl); + + /* whal_FwCtrl_BootSm() */ + + /* 0. read chip id from CHIP_ID */ + wl->chip.id = wl12xx_reg_read32(wl, CHIP_ID_B); + + /* 1. check if chip id is valid */ + + switch (wl->chip.id) { + case CHIP_ID_1251_PG12: + wl12xx_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", + wl->chip.id); + + wl1251_setup(wl); + + break; + case CHIP_ID_1271_PG10: + case CHIP_ID_1251_PG10: + case CHIP_ID_1251_PG11: + default: + wl12xx_error("unsupported chip id: 0x%x", wl->chip.id); + ret = -ENODEV; + goto out; + } + + if (wl->fw == NULL) { + ret = wl12xx_fetch_firmware(wl); + if (ret < 0) + goto out; + } + + /* No NVS from netlink, try to get it from the filesystem */ + if (wl->nvs == NULL) { + ret = wl12xx_fetch_nvs(wl); + if (ret < 0) + goto out; + } + +out: + return ret; +} + +static void wl12xx_filter_work(struct work_struct *work) +{ + struct wl12xx *wl = + container_of(work, struct wl12xx, filter_work); + int ret; + + mutex_lock(&wl->mutex); + + if (wl->state == WL12XX_STATE_OFF) + goto out; + + ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0); + if (ret < 0) + goto out; + +out: + mutex_unlock(&wl->mutex); +} + +int wl12xx_plt_start(struct wl12xx *wl) +{ + int ret; + + wl12xx_notice("power up"); + + if (wl->state != WL12XX_STATE_OFF) { + wl12xx_error("cannot go into PLT state because not " + "in off state: %d", wl->state); + return -EBUSY; + } + + wl->state = WL12XX_STATE_PLT; + + ret = wl12xx_chip_wakeup(wl); + if (ret < 0) + return ret; + + ret = wl->chip.op_boot(wl); + if (ret < 0) + return ret; + + wl12xx_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); + + ret = wl->chip.op_plt_init(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl12xx_plt_stop(struct wl12xx *wl) +{ + wl12xx_notice("power down"); + + if (wl->state != WL12XX_STATE_PLT) { + wl12xx_error("cannot power down because not in PLT " + "state: %d", wl->state); + return -EBUSY; + } + + wl12xx_disable_interrupts(wl); + wl12xx_power_off(wl); + + wl->state = WL12XX_STATE_OFF; + + return 0; +} + + +static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct wl12xx *wl = hw->priv; + + skb_queue_tail(&wl->tx_queue, skb); + + schedule_work(&wl->tx_work); + + /* + * The workqueue is slow to process the tx_queue and we need stop + * the queue here, otherwise the queue will get too long. + */ + if (skb_queue_len(&wl->tx_queue) >= WL12XX_TX_QUEUE_MAX_LENGTH) { + ieee80211_stop_queues(wl->hw); + + /* + * FIXME: this is racy, the variable is not properly + * protected. Maybe fix this by removing the stupid + * variable altogether and checking the real queue state? + */ + wl->tx_queue_stopped = true; + } + + return NETDEV_TX_OK; +} + +static int wl12xx_op_start(struct ieee80211_hw *hw) +{ + struct wl12xx *wl = hw->priv; + int ret = 0; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 start"); + + mutex_lock(&wl->mutex); + + if (wl->state != WL12XX_STATE_OFF) { + wl12xx_error("cannot start because not in off state: %d", + wl->state); + ret = -EBUSY; + goto out; + } + + ret = wl12xx_chip_wakeup(wl); + if (ret < 0) + return ret; + + ret = wl->chip.op_boot(wl); + if (ret < 0) + goto out; + + ret = wl->chip.op_hw_init(wl); + if (ret < 0) + goto out; + + ret = wl12xx_acx_station_id(wl); + if (ret < 0) + goto out; + + wl->state = WL12XX_STATE_ON; + + wl12xx_info("firmware booted (%s)", wl->chip.fw_ver); + +out: + if (ret < 0) + wl12xx_power_off(wl); + + mutex_unlock(&wl->mutex); + + return ret; +} + +static void wl12xx_op_stop(struct ieee80211_hw *hw) +{ + struct wl12xx *wl = hw->priv; + + wl12xx_info("down"); + + wl12xx_debug(DEBUG_MAC80211, "mac80211 stop"); + + mutex_lock(&wl->mutex); + + WARN_ON(wl->state != WL12XX_STATE_ON); + + if (wl->scanning) { + mutex_unlock(&wl->mutex); + ieee80211_scan_completed(wl->hw, true); + mutex_lock(&wl->mutex); + wl->scanning = false; + } + + wl->state = WL12XX_STATE_OFF; + + wl12xx_disable_interrupts(wl); + + mutex_unlock(&wl->mutex); + + cancel_work_sync(&wl->irq_work); + cancel_work_sync(&wl->tx_work); + cancel_work_sync(&wl->filter_work); + + mutex_lock(&wl->mutex); + + /* let's notify MAC80211 about the remaining pending TX frames */ + wl12xx_tx_flush(wl); + + wl12xx_power_off(wl); + + memset(wl->bssid, 0, ETH_ALEN); + wl->listen_int = 1; + wl->bss_type = MAX_BSS_TYPE; + + wl->data_in_count = 0; + wl->rx_counter = 0; + wl->rx_handled = 0; + wl->rx_current_buffer = 0; + wl->rx_last_id = 0; + wl->next_tx_complete = 0; + wl->elp = false; + wl->psm = 0; + wl->tx_queue_stopped = false; + wl->power_level = WL12XX_DEFAULT_POWER_LEVEL; + + wl12xx_debugfs_reset(wl); + + mutex_unlock(&wl->mutex); +} + +static int wl12xx_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct wl12xx *wl = hw->priv; + DECLARE_MAC_BUF(mac); + int ret = 0; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s", + conf->type, print_mac(mac, conf->mac_addr)); + + mutex_lock(&wl->mutex); + + switch (conf->type) { + case NL80211_IFTYPE_STATION: + wl->bss_type = BSS_TYPE_STA_BSS; + break; + case NL80211_IFTYPE_ADHOC: + wl->bss_type = BSS_TYPE_IBSS; + break; + default: + ret = -EOPNOTSUPP; + goto out; + } + + if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { + memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); + ret = wl12xx_acx_station_id(wl); + if (ret < 0) + goto out; + } + +out: + mutex_unlock(&wl->mutex); + return ret; +} + +static void wl12xx_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + wl12xx_debug(DEBUG_MAC80211, "mac80211 remove interface"); +} + +static int wl12xx_build_null_data(struct wl12xx *wl) +{ + struct wl12xx_null_data_template template; + + if (!is_zero_ether_addr(wl->bssid)) { + memcpy(template.header.da, wl->bssid, ETH_ALEN); + memcpy(template.header.bssid, wl->bssid, ETH_ALEN); + } else { + memset(template.header.da, 0xff, ETH_ALEN); + memset(template.header.bssid, 0xff, ETH_ALEN); + } + + memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); + template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_NULLFUNC); + + return wl12xx_cmd_template_set(wl, CMD_NULL_DATA, &template, + sizeof(template)); + +} + +static int wl12xx_build_ps_poll(struct wl12xx *wl, u16 aid) +{ + struct wl12xx_ps_poll_template template; + + memcpy(template.bssid, wl->bssid, ETH_ALEN); + memcpy(template.ta, wl->mac_addr, ETH_ALEN); + template.aid = aid; + template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); + + return wl12xx_cmd_template_set(wl, CMD_PS_POLL, &template, + sizeof(template)); + +} + +static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct wl12xx *wl = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + int channel, ret = 0; + + channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + + wl12xx_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", + channel, + conf->flags & IEEE80211_CONF_PS ? "on" : "off", + conf->power_level); + + mutex_lock(&wl->mutex); + + if (channel != wl->channel) { + /* FIXME: use beacon interval provided by mac80211 */ + ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0); + if (ret < 0) + goto out; + + wl->channel = channel; + } + + ret = wl12xx_build_null_data(wl); + if (ret < 0) + goto out; + + if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { + wl12xx_info("psm enabled"); + + wl->psm_requested = true; + + /* + * We enter PSM only if we're already associated. + * If we're not, we'll enter it when joining an SSID, + * through the bss_info_changed() hook. + */ + ret = wl12xx_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + } else if (!(conf->flags & IEEE80211_CONF_PS) && + wl->psm_requested) { + wl12xx_info("psm disabled"); + + wl->psm_requested = false; + + if (wl->psm) + ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE); + } + + if (conf->power_level != wl->power_level) { + ret = wl12xx_acx_tx_power(wl, conf->power_level); + if (ret < 0) + goto out; + + wl->power_level = conf->power_level; + } + +out: + mutex_unlock(&wl->mutex); + return ret; +} + +#define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ + FIF_ALLMULTI | \ + FIF_FCSFAIL | \ + FIF_BCN_PRBRESP_PROMISC | \ + FIF_CONTROL | \ + FIF_OTHER_BSS) + +static void wl12xx_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed, + unsigned int *total, + int mc_count, + struct dev_addr_list *mc_list) +{ + struct wl12xx *wl = hw->priv; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 configure filter"); + + *total &= WL12XX_SUPPORTED_FILTERS; + changed &= WL12XX_SUPPORTED_FILTERS; + + if (changed == 0) + /* no filters which we support changed */ + return; + + /* FIXME: wl->rx_config and wl->rx_filter are not protected */ + + wl->rx_config = WL12XX_DEFAULT_RX_CONFIG; + wl->rx_filter = WL12XX_DEFAULT_RX_FILTER; + + if (*total & FIF_PROMISC_IN_BSS) { + wl->rx_config |= CFG_BSSID_FILTER_EN; + wl->rx_config |= CFG_RX_ALL_GOOD; + } + if (*total & FIF_ALLMULTI) + /* + * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive + * all multicast frames + */ + wl->rx_config &= ~CFG_MC_FILTER_EN; + if (*total & FIF_FCSFAIL) + wl->rx_filter |= CFG_RX_FCS_ERROR; + if (*total & FIF_BCN_PRBRESP_PROMISC) { + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + wl->rx_config &= ~CFG_SSID_FILTER_EN; + } + if (*total & FIF_CONTROL) + wl->rx_filter |= CFG_RX_CTL_EN; + if (*total & FIF_OTHER_BSS) + wl->rx_filter &= ~CFG_BSSID_FILTER_EN; + + /* + * FIXME: workqueues need to be properly cancelled on stop(), for + * now let's just disable changing the filter settings. They will + * be updated any on config(). + */ + /* schedule_work(&wl->filter_work); */ +} + +/* HW encryption */ +static int wl12xx_set_key_type(struct wl12xx *wl, struct acx_set_key *key, + enum set_key_cmd cmd, + struct ieee80211_key_conf *mac80211_key, + const u8 *addr) +{ + switch (mac80211_key->alg) { + case ALG_WEP: + if (is_broadcast_ether_addr(addr)) + key->key_type = KEY_WEP_DEFAULT; + else + key->key_type = KEY_WEP_ADDR; + + mac80211_key->hw_key_idx = mac80211_key->keyidx; + break; + case ALG_TKIP: + if (is_broadcast_ether_addr(addr)) + key->key_type = KEY_TKIP_MIC_GROUP; + else + key->key_type = KEY_TKIP_MIC_PAIRWISE; + + mac80211_key->hw_key_idx = mac80211_key->keyidx; + break; + case ALG_CCMP: + if (is_broadcast_ether_addr(addr)) + key->key_type = KEY_AES_GROUP; + else + key->key_type = KEY_AES_PAIRWISE; + mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + break; + default: + wl12xx_error("Unknown key algo 0x%x", mac80211_key->alg); + return -EOPNOTSUPP; + } + + return 0; +} + +static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct wl12xx *wl = hw->priv; + struct acx_set_key wl_key; + const u8 *addr; + int ret; + + static const u8 bcast_addr[ETH_ALEN] = + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 set key"); + + memset(&wl_key, 0, sizeof(wl_key)); + + addr = sta ? sta->addr : bcast_addr; + + wl12xx_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); + wl12xx_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); + wl12xx_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", + key->alg, key->keyidx, key->keylen, key->flags); + wl12xx_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); + + mutex_lock(&wl->mutex); + + switch (cmd) { + case SET_KEY: + wl_key.key_action = KEY_ADD_OR_REPLACE; + break; + case DISABLE_KEY: + wl_key.key_action = KEY_REMOVE; + break; + default: + wl12xx_error("Unsupported key cmd 0x%x", cmd); + break; + } + + ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr); + if (ret < 0) { + wl12xx_error("Set KEY type failed"); + goto out; + } + + if (wl_key.key_type != KEY_WEP_DEFAULT) + memcpy(wl_key.addr, addr, ETH_ALEN); + + if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) || + (wl_key.key_type == KEY_TKIP_MIC_PAIRWISE)) { + /* + * We get the key in the following form: + * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) + * but the target is expecting: + * TKIP - RX MIC - TX MIC + */ + memcpy(wl_key.key, key->key, 16); + memcpy(wl_key.key + 16, key->key + 24, 8); + memcpy(wl_key.key + 24, key->key + 16, 8); + + } else { + memcpy(wl_key.key, key->key, key->keylen); + } + wl_key.key_size = key->keylen; + + wl_key.id = key->keyidx; + wl_key.ssid_profile = 0; + + wl12xx_dump(DEBUG_CRYPT, "TARGET KEY: ", &wl_key, sizeof(wl_key)); + + if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key, sizeof(wl_key)) < 0) { + wl12xx_error("Set KEY failed"); + ret = -EOPNOTSUPP; + goto out; + } + +out: + mutex_unlock(&wl->mutex); + return ret; +} + +static int wl12xx_build_basic_rates(char *rates) +{ + u8 index = 0; + + rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; + rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; + rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; + rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; + + return index; +} + +static int wl12xx_build_extended_rates(char *rates) +{ + u8 index = 0; + + rates[index++] = IEEE80211_OFDM_RATE_6MB; + rates[index++] = IEEE80211_OFDM_RATE_9MB; + rates[index++] = IEEE80211_OFDM_RATE_12MB; + rates[index++] = IEEE80211_OFDM_RATE_18MB; + rates[index++] = IEEE80211_OFDM_RATE_24MB; + rates[index++] = IEEE80211_OFDM_RATE_36MB; + rates[index++] = IEEE80211_OFDM_RATE_48MB; + rates[index++] = IEEE80211_OFDM_RATE_54MB; + + return index; +} + + +static int wl12xx_build_probe_req(struct wl12xx *wl, u8 *ssid, size_t ssid_len) +{ + struct wl12xx_probe_req_template template; + struct wl12xx_ie_rates *rates; + char *ptr; + u16 size; + + ptr = (char *)&template; + size = sizeof(struct ieee80211_header); + + memset(template.header.da, 0xff, ETH_ALEN); + memset(template.header.bssid, 0xff, ETH_ALEN); + memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); + template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); + + /* IEs */ + /* SSID */ + template.ssid.header.id = WLAN_EID_SSID; + template.ssid.header.len = ssid_len; + if (ssid_len && ssid) + memcpy(template.ssid.ssid, ssid, ssid_len); + size += sizeof(struct wl12xx_ie_header) + ssid_len; + ptr += size; + + /* Basic Rates */ + rates = (struct wl12xx_ie_rates *)ptr; + rates->header.id = WLAN_EID_SUPP_RATES; + rates->header.len = wl12xx_build_basic_rates(rates->rates); + size += sizeof(struct wl12xx_ie_header) + rates->header.len; + ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; + + /* Extended rates */ + rates = (struct wl12xx_ie_rates *)ptr; + rates->header.id = WLAN_EID_EXT_SUPP_RATES; + rates->header.len = wl12xx_build_extended_rates(rates->rates); + size += sizeof(struct wl12xx_ie_header) + rates->header.len; + + wl12xx_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); + + return wl12xx_cmd_template_set(wl, CMD_PROBE_REQ, &template, + size); +} + +static int wl12xx_hw_scan(struct wl12xx *wl, u8 *ssid, size_t len, + u8 active_scan, u8 high_prio, u8 num_channels, + u8 probe_requests) +{ + int i, ret; + u32 split_scan = 0; + u16 scan_options = 0; + struct cmd_scan *params; + struct wl12xx_command *cmd_answer; + + if (wl->scanning) + return -EINVAL; + + params = kzalloc(sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; + + params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); + params->params.rx_filter_options = + cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); + + /* High priority scan */ + if (!active_scan) + scan_options |= SCAN_PASSIVE; + if (high_prio) + scan_options |= SCAN_PRIORITY_HIGH; + params->params.scan_options = scan_options; + + params->params.num_channels = num_channels; + params->params.num_probe_requests = probe_requests; + params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ + params->params.tid_trigger = 0; + + for (i = 0; i < num_channels; i++) { + params->channels[i].min_duration = cpu_to_le32(30000); + params->channels[i].max_duration = cpu_to_le32(60000); + memset(¶ms->channels[i].bssid_lsb, 0xff, 4); + memset(¶ms->channels[i].bssid_msb, 0xff, 2); + params->channels[i].early_termination = 0; + params->channels[i].tx_power_att = 0; + params->channels[i].channel = i + 1; + memset(params->channels[i].pad, 0, 3); + } + + for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++) + memset(¶ms->channels[i], 0, + sizeof(struct basic_scan_channel_parameters)); + + if (len && ssid) { + params->params.ssid_len = len; + memcpy(params->params.ssid, ssid, len); + } else { + params->params.ssid_len = 0; + memset(params->params.ssid, 0, 32); + } + + ret = wl12xx_build_probe_req(wl, ssid, len); + if (ret < 0) { + wl12xx_error("PROBE request template failed"); + goto out; + } + + ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan, + sizeof(u32)); + if (ret < 0) { + wl12xx_error("Split SCAN failed"); + goto out; + } + + wl12xx_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); + + wl->scanning = true; + + ret = wl12xx_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); + if (ret < 0) + wl12xx_error("SCAN failed"); + + wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); + + cmd_answer = (struct wl12xx_command *) params; + if (cmd_answer->status != CMD_STATUS_SUCCESS) { + wl12xx_error("TEST command answer error: %d", + cmd_answer->status); + wl->scanning = false; + ret = -EIO; + goto out; + } + +out: + kfree(params); + return ret; + +} + +static int wl12xx_op_hw_scan(struct ieee80211_hw *hw, + struct cfg80211_scan_request *req) +{ + struct wl12xx *wl = hw->priv; + int ret; + u8 *ssid = NULL; + size_t ssid_len = 0; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 hw scan"); + + if (req->n_ssids) { + ssid = req->ssids[0].ssid; + ssid_len = req->ssids[0].ssid_len; + } + + mutex_lock(&wl->mutex); + ret = wl12xx_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); + mutex_unlock(&wl->mutex); + + return ret; +} + +static int wl12xx_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct wl12xx *wl = hw->priv; + int ret; + + ret = wl12xx_acx_rts_threshold(wl, (u16) value); + + if (ret < 0) + wl12xx_warning("wl12xx_op_set_rts_threshold failed: %d", ret); + + return ret; +} + +static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + enum acx_ps_mode mode; + struct wl12xx *wl = hw->priv; + struct sk_buff *beacon; + int ret; + + wl12xx_debug(DEBUG_MAC80211, "mac80211 bss info changed"); + + mutex_lock(&wl->mutex); + + if (changed & BSS_CHANGED_ASSOC) { + if (bss_conf->assoc) { + wl->aid = bss_conf->aid; + + ret = wl12xx_build_ps_poll(wl, wl->aid); + if (ret < 0) + goto out; + + ret = wl12xx_acx_aid(wl, wl->aid); + if (ret < 0) + goto out; + + /* If we want to go in PSM but we're not there yet */ + if (wl->psm_requested && !wl->psm) { + mode = STATION_POWER_SAVE_MODE; + ret = wl12xx_ps_set_mode(wl, mode); + if (ret < 0) + goto out; + } + } + } + if (changed & BSS_CHANGED_ERP_SLOT) { + if (bss_conf->use_short_slot) + ret = wl12xx_acx_slot(wl, SLOT_TIME_SHORT); + else + ret = wl12xx_acx_slot(wl, SLOT_TIME_LONG); + if (ret < 0) { + wl12xx_warning("Set slot time failed %d", ret); + goto out; + } + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + if (bss_conf->use_short_preamble) + wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); + else + wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_LONG); + } + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + if (bss_conf->use_cts_prot) + ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_ENABLE); + else + ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_DISABLE); + if (ret < 0) { + wl12xx_warning("Set ctsprotect failed %d", ret); + goto out; + } + } + + if (changed & BSS_CHANGED_BSSID) { + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + + ret = wl12xx_build_null_data(wl); + if (ret < 0) + goto out; + + if (wl->bss_type != BSS_TYPE_IBSS) { + ret = wl12xx_cmd_join(wl, wl->bss_type, 5, 100, 1); + if (ret < 0) + goto out; + } + } + + if (changed & BSS_CHANGED_BEACON) { + beacon = ieee80211_beacon_get(hw, vif); + ret = wl12xx_cmd_template_set(wl, CMD_BEACON, beacon->data, + beacon->len); + + if (ret < 0) { + dev_kfree_skb(beacon); + goto out; + } + + ret = wl12xx_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, + beacon->len); + + dev_kfree_skb(beacon); + + if (ret < 0) + goto out; + + ret = wl12xx_cmd_join(wl, wl->bss_type, 1, 100, 0); + + if (ret < 0) + goto out; + } + +out: + mutex_unlock(&wl->mutex); +} + + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_rate wl12xx_rates[] = { + { .bitrate = 10, + .hw_value = 0x1, + .hw_value_short = 0x1, }, + { .bitrate = 20, + .hw_value = 0x2, + .hw_value_short = 0x2, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, + .hw_value = 0x4, + .hw_value_short = 0x4, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, + .hw_value = 0x20, + .hw_value_short = 0x20, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, + .hw_value = 0x8, + .hw_value_short = 0x8, }, + { .bitrate = 90, + .hw_value = 0x10, + .hw_value_short = 0x10, }, + { .bitrate = 120, + .hw_value = 0x40, + .hw_value_short = 0x40, }, + { .bitrate = 180, + .hw_value = 0x80, + .hw_value_short = 0x80, }, + { .bitrate = 240, + .hw_value = 0x200, + .hw_value_short = 0x200, }, + { .bitrate = 360, + .hw_value = 0x400, + .hw_value_short = 0x400, }, + { .bitrate = 480, + .hw_value = 0x800, + .hw_value_short = 0x800, }, + { .bitrate = 540, + .hw_value = 0x1000, + .hw_value_short = 0x1000, }, +}; + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_channel wl12xx_channels[] = { + { .hw_value = 1, .center_freq = 2412}, + { .hw_value = 2, .center_freq = 2417}, + { .hw_value = 3, .center_freq = 2422}, + { .hw_value = 4, .center_freq = 2427}, + { .hw_value = 5, .center_freq = 2432}, + { .hw_value = 6, .center_freq = 2437}, + { .hw_value = 7, .center_freq = 2442}, + { .hw_value = 8, .center_freq = 2447}, + { .hw_value = 9, .center_freq = 2452}, + { .hw_value = 10, .center_freq = 2457}, + { .hw_value = 11, .center_freq = 2462}, + { .hw_value = 12, .center_freq = 2467}, + { .hw_value = 13, .center_freq = 2472}, +}; + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_supported_band wl12xx_band_2ghz = { + .channels = wl12xx_channels, + .n_channels = ARRAY_SIZE(wl12xx_channels), + .bitrates = wl12xx_rates, + .n_bitrates = ARRAY_SIZE(wl12xx_rates), +}; + +static const struct ieee80211_ops wl12xx_ops = { + .start = wl12xx_op_start, + .stop = wl12xx_op_stop, + .add_interface = wl12xx_op_add_interface, + .remove_interface = wl12xx_op_remove_interface, + .config = wl12xx_op_config, + .configure_filter = wl12xx_op_configure_filter, + .tx = wl12xx_op_tx, + .set_key = wl12xx_op_set_key, + .hw_scan = wl12xx_op_hw_scan, + .bss_info_changed = wl12xx_op_bss_info_changed, + .set_rts_threshold = wl12xx_op_set_rts_threshold, +}; + +static int wl12xx_register_hw(struct wl12xx *wl) +{ + int ret; + + if (wl->mac80211_registered) + return 0; + + SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); + + ret = ieee80211_register_hw(wl->hw); + if (ret < 0) { + wl12xx_error("unable to register mac80211 hw: %d", ret); + return ret; + } + + wl->mac80211_registered = true; + + wl12xx_notice("loaded"); + + return 0; +} + +static int wl12xx_init_ieee80211(struct wl12xx *wl) +{ + /* The tx descriptor buffer and the TKIP space */ + wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc) + + WL12XX_TKIP_IV_SPACE; + + /* unit us */ + /* FIXME: find a proper value */ + wl->hw->channel_change_time = 10000; + + wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + + wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + wl->hw->wiphy->max_scan_ssids = 1; + wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl12xx_band_2ghz; + + SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); + + return 0; +} + +#define WL12XX_DEFAULT_CHANNEL 1 +static int __devinit wl12xx_probe(struct spi_device *spi) +{ + struct wl12xx_platform_data *pdata; + struct ieee80211_hw *hw; + struct wl12xx *wl; + int ret, i; + static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; + + pdata = spi->dev.platform_data; + if (!pdata) { + wl12xx_error("no platform data"); + return -ENODEV; + } + + hw = ieee80211_alloc_hw(sizeof(*wl), &wl12xx_ops); + if (!hw) { + wl12xx_error("could not alloc ieee80211_hw"); + return -ENOMEM; + } + + wl = hw->priv; + memset(wl, 0, sizeof(*wl)); + + wl->hw = hw; + dev_set_drvdata(&spi->dev, wl); + wl->spi = spi; + + wl->data_in_count = 0; + + skb_queue_head_init(&wl->tx_queue); + + INIT_WORK(&wl->tx_work, wl12xx_tx_work); + INIT_WORK(&wl->filter_work, wl12xx_filter_work); + wl->channel = WL12XX_DEFAULT_CHANNEL; + wl->scanning = false; + wl->default_key = 0; + wl->listen_int = 1; + wl->rx_counter = 0; + wl->rx_handled = 0; + wl->rx_current_buffer = 0; + wl->rx_last_id = 0; + wl->rx_config = WL12XX_DEFAULT_RX_CONFIG; + wl->rx_filter = WL12XX_DEFAULT_RX_FILTER; + wl->elp = false; + wl->psm = 0; + wl->psm_requested = false; + wl->tx_queue_stopped = false; + wl->power_level = WL12XX_DEFAULT_POWER_LEVEL; + + /* We use the default power on sleep time until we know which chip + * we're using */ + wl->chip.power_on_sleep = WL12XX_DEFAULT_POWER_ON_SLEEP; + + for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) + wl->tx_frames[i] = NULL; + + wl->next_tx_complete = 0; + + /* + * In case our MAC address is not correctly set, + * we use a random but Nokia MAC. + */ + memcpy(wl->mac_addr, nokia_oui, 3); + get_random_bytes(wl->mac_addr + 3, 3); + + wl->state = WL12XX_STATE_OFF; + mutex_init(&wl->mutex); + + wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; + wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; + + /* This is the only SPI value that we need to set here, the rest + * comes from the board-peripherals file */ + spi->bits_per_word = 32; + + ret = spi_setup(spi); + if (ret < 0) { + wl12xx_error("spi_setup failed"); + goto out_free; + } + + wl->set_power = pdata->set_power; + if (!wl->set_power) { + wl12xx_error("set power function missing in platform data"); + return -ENODEV; + } + + wl->irq = spi->irq; + if (wl->irq < 0) { + wl12xx_error("irq missing in platform data"); + return -ENODEV; + } + + ret = request_irq(wl->irq, wl12xx_irq, 0, DRIVER_NAME, wl); + if (ret < 0) { + wl12xx_error("request_irq() failed: %d", ret); + goto out_free; + } + + set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); + + disable_irq(wl->irq); + + ret = wl12xx_init_ieee80211(wl); + if (ret) + goto out_irq; + + ret = wl12xx_register_hw(wl); + if (ret) + goto out_irq; + + wl12xx_debugfs_init(wl); + + wl12xx_notice("initialized"); + + return 0; + + out_irq: + free_irq(wl->irq, wl); + + out_free: + ieee80211_free_hw(hw); + + return ret; +} + +static int __devexit wl12xx_remove(struct spi_device *spi) +{ + struct wl12xx *wl = dev_get_drvdata(&spi->dev); + + ieee80211_unregister_hw(wl->hw); + + wl12xx_debugfs_exit(wl); + + free_irq(wl->irq, wl); + kfree(wl->target_mem_map); + kfree(wl->data_path); + kfree(wl->fw); + wl->fw = NULL; + kfree(wl->nvs); + wl->nvs = NULL; + ieee80211_free_hw(wl->hw); + + return 0; +} + + +static struct spi_driver wl12xx_spi_driver = { + .driver = { + .name = "wl12xx", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = wl12xx_probe, + .remove = __devexit_p(wl12xx_remove), +}; + +static int __init wl12xx_init(void) +{ + int ret; + + ret = spi_register_driver(&wl12xx_spi_driver); + if (ret < 0) { + wl12xx_error("failed to register spi driver: %d", ret); + goto out; + } + +out: + return ret; +} + +static void __exit wl12xx_exit(void) +{ + spi_unregister_driver(&wl12xx_spi_driver); + + wl12xx_notice("unloaded"); +} + +module_init(wl12xx_init); +module_exit(wl12xx_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kalle Valo , " + "Luciano Coelho "); diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c new file mode 100644 index 000000000000..83a10117330b --- /dev/null +++ b/drivers/net/wireless/wl12xx/ps.c @@ -0,0 +1,151 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "reg.h" +#include "ps.h" +#include "spi.h" + +#define WL12XX_WAKEUP_TIMEOUT 2000 + +/* Routines to toggle sleep mode while in ELP */ +void wl12xx_ps_elp_sleep(struct wl12xx *wl) +{ + if (wl->elp || !wl->psm) + return; + + wl12xx_debug(DEBUG_PSM, "chip to elp"); + + wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); + + wl->elp = true; +} + +int wl12xx_ps_elp_wakeup(struct wl12xx *wl) +{ + unsigned long timeout; + u32 elp_reg; + + if (!wl->elp) + return 0; + + wl12xx_debug(DEBUG_PSM, "waking up chip from elp"); + + timeout = jiffies + msecs_to_jiffies(WL12XX_WAKEUP_TIMEOUT); + + wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); + + elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + + /* + * FIXME: we should wait for irq from chip but, as a temporary + * solution to simplify locking, let's poll instead + */ + while (!(elp_reg & ELPCTRL_WLAN_READY)) { + if (time_after(jiffies, timeout)) { + wl12xx_error("elp wakeup timeout"); + return -ETIMEDOUT; + } + msleep(1); + elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); + } + + wl12xx_debug(DEBUG_PSM, "wakeup time: %u ms", + jiffies_to_msecs(jiffies) - + (jiffies_to_msecs(timeout) - WL12XX_WAKEUP_TIMEOUT)); + + wl->elp = false; + + return 0; +} + +static int wl12xx_ps_set_elp(struct wl12xx *wl, bool enable) +{ + int ret; + + if (enable) { + wl12xx_debug(DEBUG_PSM, "sleep auth psm/elp"); + + /* + * FIXME: we should PSM_ELP, but because of firmware wakeup + * problems let's use only PSM_PS + */ + ret = wl12xx_acx_sleep_auth(wl, WL12XX_PSM_PS); + if (ret < 0) + return ret; + + wl12xx_ps_elp_sleep(wl); + } else { + wl12xx_debug(DEBUG_PSM, "sleep auth cam"); + + /* + * When the target is in ELP, we can only + * access the ELP control register. Thus, + * we have to wake the target up before + * changing the power authorization. + */ + + wl12xx_ps_elp_wakeup(wl); + + ret = wl12xx_acx_sleep_auth(wl, WL12XX_PSM_CAM); + if (ret < 0) + return ret; + } + + return 0; +} + +int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode) +{ + int ret; + + switch (mode) { + case STATION_POWER_SAVE_MODE: + wl12xx_debug(DEBUG_PSM, "entering psm"); + ret = wl12xx_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); + if (ret < 0) + return ret; + + ret = wl12xx_ps_set_elp(wl, true); + if (ret < 0) + return ret; + + wl->psm = 1; + break; + case STATION_ACTIVE_MODE: + default: + wl12xx_debug(DEBUG_PSM, "leaving psm"); + ret = wl12xx_ps_set_elp(wl, false); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_ps_mode(wl, STATION_ACTIVE_MODE); + if (ret < 0) + return ret; + + wl->psm = 0; + break; + } + + return ret; +} + diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h new file mode 100644 index 000000000000..5d7c52553830 --- /dev/null +++ b/drivers/net/wireless/wl12xx/ps.h @@ -0,0 +1,36 @@ +#ifndef __WL12XX_PS_H__ +#define __WL12XX_PS_H__ + +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "wl12xx.h" +#include "acx.h" + +int wl12xx_ps_set_mode(struct wl12xx *wl, enum acx_ps_mode mode); +void wl12xx_ps_elp_sleep(struct wl12xx *wl); +int wl12xx_ps_elp_wakeup(struct wl12xx *wl); + + +#endif /* __WL12XX_PS_H__ */ diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h new file mode 100644 index 000000000000..e421643215cd --- /dev/null +++ b/drivers/net/wireless/wl12xx/reg.h @@ -0,0 +1,745 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __REG_H__ +#define __REG_H__ + +#include +#include "wl12xx.h" + +#define REGISTERS_BASE 0x00300000 +#define DRPW_BASE 0x00310000 + +#define REGISTERS_DOWN_SIZE 0x00008800 +#define REGISTERS_WORK_SIZE 0x0000b000 + +#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC + +/* ELP register commands */ +#define ELPCTRL_WAKE_UP 0x1 +#define ELPCTRL_WAKE_UP_WLAN_READY 0x5 +#define ELPCTRL_SLEEP 0x0 +/* ELP WLAN_READY bit */ +#define ELPCTRL_WLAN_READY 0x2 + +/* + * Interrupt registers. + * 64 bit interrupt sources registers ws ced. + * sme interupts were removed and new ones were added. + * Order was changed. + */ +#define FIQ_MASK (REGISTERS_BASE + 0x0400) +#define FIQ_MASK_L (REGISTERS_BASE + 0x0400) +#define FIQ_MASK_H (REGISTERS_BASE + 0x0404) +#define FIQ_MASK_SET (REGISTERS_BASE + 0x0408) +#define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408) +#define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C) +#define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410) +#define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410) +#define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414) +#define IRQ_MASK (REGISTERS_BASE + 0x0418) +#define IRQ_MASK_L (REGISTERS_BASE + 0x0418) +#define IRQ_MASK_H (REGISTERS_BASE + 0x041C) +#define IRQ_MASK_SET (REGISTERS_BASE + 0x0420) +#define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420) +#define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424) +#define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428) +#define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428) +#define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C) +#define ECPU_MASK (REGISTERS_BASE + 0x0448) +#define FIQ_STS_L (REGISTERS_BASE + 0x044C) +#define FIQ_STS_H (REGISTERS_BASE + 0x0450) +#define IRQ_STS_L (REGISTERS_BASE + 0x0454) +#define IRQ_STS_H (REGISTERS_BASE + 0x0458) +#define INT_STS_ND (REGISTERS_BASE + 0x0464) +#define INT_STS_RAW_L (REGISTERS_BASE + 0x0464) +#define INT_STS_RAW_H (REGISTERS_BASE + 0x0468) +#define INT_STS_CLR (REGISTERS_BASE + 0x04B4) +#define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4) +#define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8) +#define INT_ACK (REGISTERS_BASE + 0x046C) +#define INT_ACK_L (REGISTERS_BASE + 0x046C) +#define INT_ACK_H (REGISTERS_BASE + 0x0470) +#define INT_TRIG (REGISTERS_BASE + 0x0474) +#define INT_TRIG_L (REGISTERS_BASE + 0x0474) +#define INT_TRIG_H (REGISTERS_BASE + 0x0478) +#define HOST_STS_L (REGISTERS_BASE + 0x045C) +#define HOST_STS_H (REGISTERS_BASE + 0x0460) +#define HOST_MASK (REGISTERS_BASE + 0x0430) +#define HOST_MASK_L (REGISTERS_BASE + 0x0430) +#define HOST_MASK_H (REGISTERS_BASE + 0x0434) +#define HOST_MASK_SET (REGISTERS_BASE + 0x0438) +#define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438) +#define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C) +#define HOST_MASK_CLR (REGISTERS_BASE + 0x0440) +#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) +#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) + +/* Host Interrupts*/ +#define HINT_MASK (REGISTERS_BASE + 0x0494) +#define HINT_MASK_SET (REGISTERS_BASE + 0x0498) +#define HINT_MASK_CLR (REGISTERS_BASE + 0x049C) +#define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0) +/*1150 spec calls this HINT_STS_RAW*/ +#define HINT_STS_ND (REGISTERS_BASE + 0x04B0) +#define HINT_STS_CLR (REGISTERS_BASE + 0x04A4) +#define HINT_ACK (REGISTERS_BASE + 0x04A8) +#define HINT_TRIG (REGISTERS_BASE + 0x04AC) + +/* Device Configuration registers*/ +#define SOR_CFG (REGISTERS_BASE + 0x0800) +#define ECPU_CTRL (REGISTERS_BASE + 0x0804) +#define HI_CFG (REGISTERS_BASE + 0x0808) +#define EE_START (REGISTERS_BASE + 0x080C) + +#define CHIP_ID_B (REGISTERS_BASE + 0x5674) + +#define CHIP_ID_1251_PG10 (0x7010101) +#define CHIP_ID_1251_PG11 (0x7020101) +#define CHIP_ID_1251_PG12 (0x7030101) + +#define ENABLE (REGISTERS_BASE + 0x5450) + +/* Power Management registers */ +#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804) +#define ELP_CMD (REGISTERS_BASE + 0x5808) +#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810) +#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814) +#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818) + +#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) + +/* Scratch Pad registers*/ +#define SCR_PAD0 (REGISTERS_BASE + 0x5608) +#define SCR_PAD1 (REGISTERS_BASE + 0x560C) +#define SCR_PAD2 (REGISTERS_BASE + 0x5610) +#define SCR_PAD3 (REGISTERS_BASE + 0x5614) +#define SCR_PAD4 (REGISTERS_BASE + 0x5618) +#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C) +#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) +#define SCR_PAD5 (REGISTERS_BASE + 0x5624) +#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628) +#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) +#define SCR_PAD6 (REGISTERS_BASE + 0x5630) +#define SCR_PAD7 (REGISTERS_BASE + 0x5634) +#define SCR_PAD8 (REGISTERS_BASE + 0x5638) +#define SCR_PAD9 (REGISTERS_BASE + 0x563C) + +/* Spare registers*/ +#define SPARE_A1 (REGISTERS_BASE + 0x0994) +#define SPARE_A2 (REGISTERS_BASE + 0x0998) +#define SPARE_A3 (REGISTERS_BASE + 0x099C) +#define SPARE_A4 (REGISTERS_BASE + 0x09A0) +#define SPARE_A5 (REGISTERS_BASE + 0x09A4) +#define SPARE_A6 (REGISTERS_BASE + 0x09A8) +#define SPARE_A7 (REGISTERS_BASE + 0x09AC) +#define SPARE_A8 (REGISTERS_BASE + 0x09B0) +#define SPARE_B1 (REGISTERS_BASE + 0x5420) +#define SPARE_B2 (REGISTERS_BASE + 0x5424) +#define SPARE_B3 (REGISTERS_BASE + 0x5428) +#define SPARE_B4 (REGISTERS_BASE + 0x542C) +#define SPARE_B5 (REGISTERS_BASE + 0x5430) +#define SPARE_B6 (REGISTERS_BASE + 0x5434) +#define SPARE_B7 (REGISTERS_BASE + 0x5438) +#define SPARE_B8 (REGISTERS_BASE + 0x543C) + +enum wl12xx_acx_int_reg { + ACX_REG_INTERRUPT_TRIG, + ACX_REG_INTERRUPT_TRIG_H, + +/*============================================= + Host Interrupt Mask Register - 32bit (RW) + ------------------------------------------ + Setting a bit in this register masks the + corresponding interrupt to the host. + 0 - RX0 - Rx first dubble buffer Data Interrupt + 1 - TXD - Tx Data Interrupt + 2 - TXXFR - Tx Transfer Interrupt + 3 - RX1 - Rx second dubble buffer Data Interrupt + 4 - RXXFR - Rx Transfer Interrupt + 5 - EVENT_A - Event Mailbox interrupt + 6 - EVENT_B - Event Mailbox interrupt + 7 - WNONHST - Wake On Host Interrupt + 8 - TRACE_A - Debug Trace interrupt + 9 - TRACE_B - Debug Trace interrupt + 10 - CDCMP - Command Complete Interrupt + 11 - + 12 - + 13 - + 14 - ICOMP - Initialization Complete Interrupt + 16 - SG SE - Soft Gemini - Sense enable interrupt + 17 - SG SD - Soft Gemini - Sense disable interrupt + 18 - - + 19 - - + 20 - - + 21- - + Default: 0x0001 +*==============================================*/ + ACX_REG_INTERRUPT_MASK, + +/*============================================= + Host Interrupt Mask Set 16bit, (Write only) + ------------------------------------------ + Setting a bit in this register sets + the corresponding bin in ACX_HINT_MASK register + without effecting the mask + state of other bits (0 = no effect). +==============================================*/ + ACX_REG_HINT_MASK_SET, + +/*============================================= + Host Interrupt Mask Clear 16bit,(Write only) + ------------------------------------------ + Setting a bit in this register clears + the corresponding bin in ACX_HINT_MASK register + without effecting the mask + state of other bits (0 = no effect). +=============================================*/ + ACX_REG_HINT_MASK_CLR, + +/*============================================= + Host Interrupt Status Nondestructive Read + 16bit,(Read only) + ------------------------------------------ + The host can read this register to determine + which interrupts are active. + Reading this register doesn't + effect its content. +=============================================*/ + ACX_REG_INTERRUPT_NO_CLEAR, + +/*============================================= + Host Interrupt Status Clear on Read Register + 16bit,(Read only) + ------------------------------------------ + The host can read this register to determine + which interrupts are active. + Reading this register clears it, + thus making all interrupts inactive. +==============================================*/ + ACX_REG_INTERRUPT_CLEAR, + +/*============================================= + Host Interrupt Acknowledge Register + 16bit,(Write only) + ------------------------------------------ + The host can set individual bits in this + register to clear (acknowledge) the corresp. + interrupt status bits in the HINT_STS_CLR and + HINT_STS_ND registers, thus making the + assotiated interrupt inactive. (0-no effect) +==============================================*/ + ACX_REG_INTERRUPT_ACK, + +/*=============================================== + Host Software Reset - 32bit RW + ------------------------------------------ + [31:1] Reserved + 0 SOFT_RESET Soft Reset - When this bit is set, + it holds the Wlan hardware in a soft reset state. + This reset disables all MAC and baseband processor + clocks except the CardBus/PCI interface clock. + It also initializes all MAC state machines except + the host interface. It does not reload the + contents of the EEPROM. When this bit is cleared + (not self-clearing), the Wlan hardware + exits the software reset state. +===============================================*/ + ACX_REG_SLV_SOFT_RESET, + +/*=============================================== + EEPROM Burst Read Start - 32bit RW + ------------------------------------------ + [31:1] Reserved + 0 ACX_EE_START - EEPROM Burst Read Start 0 + Setting this bit starts a burst read from + the external EEPROM. + If this bit is set (after reset) before an EEPROM read/write, + the burst read starts at EEPROM address 0. + Otherwise, it starts at the address + following the address of the previous access. + TheWlan hardware hardware clears this bit automatically. + + Default: 0x00000000 +*================================================*/ + ACX_REG_EE_START, + +/* Embedded ARM CPU Control */ + +/*=============================================== + Halt eCPU - 32bit RW + ------------------------------------------ + 0 HALT_ECPU Halt Embedded CPU - This bit is the + compliment of bit 1 (MDATA2) in the SOR_CFG register. + During a hardware reset, this bit holds + the inverse of MDATA2. + When downloading firmware from the host, + set this bit (pull down MDATA2). + The host clears this bit after downloading the firmware into + zero-wait-state SSRAM. + When loading firmware from Flash, clear this bit (pull up MDATA2) + so that the eCPU can run the bootloader code in Flash + HALT_ECPU eCPU State + -------------------- + 1 halt eCPU + 0 enable eCPU + ===============================================*/ + ACX_REG_ECPU_CONTROL, + + ACX_REG_TABLE_LEN +}; + +#define ACX_SLV_SOFT_RESET_BIT BIT(1) +#define ACX_REG_EEPROM_START_BIT BIT(1) + +/* Command/Information Mailbox Pointers */ + +/*=============================================== + Command Mailbox Pointer - 32bit RW + ------------------------------------------ + This register holds the start address of + the command mailbox located in the Wlan hardware memory. + The host must read this pointer after a reset to + find the location of the command mailbox. + The Wlan hardware initializes the command mailbox + pointer with the default address of the command mailbox. + The command mailbox pointer is not valid until after + the host receives the Init Complete interrupt from + the Wlan hardware. + ===============================================*/ +#define REG_COMMAND_MAILBOX_PTR (SCR_PAD0) + +/*=============================================== + Information Mailbox Pointer - 32bit RW + ------------------------------------------ + This register holds the start address of + the information mailbox located in the Wlan hardware memory. + The host must read this pointer after a reset to find + the location of the information mailbox. + The Wlan hardware initializes the information mailbox pointer + with the default address of the information mailbox. + The information mailbox pointer is not valid + until after the host receives the Init Complete interrupt from + the Wlan hardware. + ===============================================*/ +#define REG_EVENT_MAILBOX_PTR (SCR_PAD1) + + +/* Misc */ + +#define REG_ENABLE_TX_RX (ENABLE) +/* + * Rx configuration (filter) information element + * --------------------------------------------- + */ +#define REG_RX_CONFIG (RX_CFG) +#define REG_RX_FILTER (RX_FILTER_CFG) + + +#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002 + +/* promiscuous - receives all valid frames */ +#define RX_CFG_PROMISCUOUS 0x0008 + +/* receives frames from any BSSID */ +#define RX_CFG_BSSID 0x0020 + +/* receives frames destined to any MAC address */ +#define RX_CFG_MAC 0x0010 + +#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010 +#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000 +#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020 +#define RX_CFG_ENABLE_ANY_BSSID 0x0000 + +/* discards all broadcast frames */ +#define RX_CFG_DISABLE_BCAST 0x0200 + +#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400 +#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800 +#define RX_CFG_COPY_RX_STATUS 0x2000 +#define RX_CFG_TSF 0x10000 + +#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ + RX_CFG_ENABLE_ONLY_MY_BSSID) + +#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ + | RX_CFG_ENABLE_ANY_BSSID) + +#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ + RX_CFG_ENABLE_ANY_BSSID) + +#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ + | RX_CFG_ENABLE_ONLY_MY_BSSID) + +#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \ + | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \ + | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF) + +#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC) + +#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \ + RX_CFG_ENABLE_ONLY_MY_DEST_MAC) + +#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \ + RX_CFG_ENABLE_ONLY_MY_DEST_MAC) + +#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ + | CFG_RX_CTL_EN | CFG_RX_BCN_EN\ + | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) + +#define RX_FILTER_OPTION_FILTER_ALL 0 + +#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\ + | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN) + +#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ + | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\ + | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\ + | CFG_RX_PRSP_EN) + + +/*=============================================== + Phy regs + ===============================================*/ +#define ACX_PHY_ADDR_REG SBB_ADDR +#define ACX_PHY_DATA_REG SBB_DATA +#define ACX_PHY_CTRL_REG SBB_CTL +#define ACX_PHY_REG_WR_MASK 0x00000001ul +#define ACX_PHY_REG_RD_MASK 0x00000002ul + + +/*=============================================== + EEPROM Read/Write Request 32bit RW + ------------------------------------------ + 1 EE_READ - EEPROM Read Request 1 - Setting this bit + loads a single byte of data into the EE_DATA + register from the EEPROM location specified in + the EE_ADDR register. + The Wlan hardware hardware clears this bit automatically. + EE_DATA is valid when this bit is cleared. + + 0 EE_WRITE - EEPROM Write Request - Setting this bit + writes a single byte of data from the EE_DATA register into the + EEPROM location specified in the EE_ADDR register. + The Wlan hardware hardware clears this bit automatically. +*===============================================*/ +#define ACX_EE_CTL_REG EE_CTL +#define EE_WRITE 0x00000001ul +#define EE_READ 0x00000002ul + +/*=============================================== + EEPROM Address - 32bit RW + ------------------------------------------ + This register specifies the address + within the EEPROM from/to which to read/write data. + ===============================================*/ +#define ACX_EE_ADDR_REG EE_ADDR + +/*=============================================== + EEPROM Data - 32bit RW + ------------------------------------------ + This register either holds the read 8 bits of + data from the EEPROM or the write data + to be written to the EEPROM. + ===============================================*/ +#define ACX_EE_DATA_REG EE_DATA + +/*=============================================== + EEPROM Base Address - 32bit RW + ------------------------------------------ + This register holds the upper nine bits + [23:15] of the 24-bit Wlan hardware memory + address for burst reads from EEPROM accesses. + The EEPROM provides the lower 15 bits of this address. + The MSB of the address from the EEPROM is ignored. + ===============================================*/ +#define ACX_EE_CFG EE_CFG + +/*=============================================== + GPIO Output Values -32bit, RW + ------------------------------------------ + [31:16] Reserved + [15: 0] Specify the output values (at the output driver inputs) for + GPIO[15:0], respectively. + ===============================================*/ +#define ACX_GPIO_OUT_REG GPIO_OUT +#define ACX_MAX_GPIO_LINES 15 + +/*=============================================== + Contention window -32bit, RW + ------------------------------------------ + [31:26] Reserved + [25:16] Max (0x3ff) + [15:07] Reserved + [06:00] Current contention window value - default is 0x1F + ===============================================*/ +#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG +#define ACX_CONT_WIND_MIN_MASK 0x0000007f +#define ACX_CONT_WIND_MAX 0x03ff0000 + +/* + * Indirect slave register/memory registers + * ---------------------------------------- + */ +#define HW_SLAVE_REG_ADDR_REG 0x00000004 +#define HW_SLAVE_REG_DATA_REG 0x00000008 +#define HW_SLAVE_REG_CTRL_REG 0x0000000c + +#define SLAVE_AUTO_INC 0x00010000 +#define SLAVE_NO_AUTO_INC 0x00000000 +#define SLAVE_HOST_LITTLE_ENDIAN 0x00000000 + +#define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR +#define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA +#define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL +#define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL + +#define HW_FUNC_EVENT_INT_EN 0x8000 +#define HW_FUNC_EVENT_MASK_REG 0x00000034 + +#define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP) + +/*=============================================== + HI_CFG Interface Configuration Register Values + ------------------------------------------ + ===============================================*/ +#define HI_CFG_UART_ENABLE 0x00000004 +#define HI_CFG_RST232_ENABLE 0x00000008 +#define HI_CFG_CLOCK_REQ_SELECT 0x00000010 +#define HI_CFG_HOST_INT_ENABLE 0x00000020 +#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 +#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 +#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 +#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 +#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 + +/* + * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile + * for platforms using active high interrupt level + */ +#ifdef USE_ACTIVE_HIGH +#define HI_CFG_DEF_VAL \ + (HI_CFG_UART_ENABLE | \ + HI_CFG_RST232_ENABLE | \ + HI_CFG_CLOCK_REQ_SELECT | \ + HI_CFG_HOST_INT_ENABLE) +#else +#define HI_CFG_DEF_VAL \ + (HI_CFG_UART_ENABLE | \ + HI_CFG_RST232_ENABLE | \ + HI_CFG_CLOCK_REQ_SELECT | \ + HI_CFG_HOST_INT_ENABLE) + +#endif + +#define REF_FREQ_19_2 0 +#define REF_FREQ_26_0 1 +#define REF_FREQ_38_4 2 +#define REF_FREQ_40_0 3 +#define REF_FREQ_33_6 4 +#define REF_FREQ_NUM 5 + +#define LUT_PARAM_INTEGER_DIVIDER 0 +#define LUT_PARAM_FRACTIONAL_DIVIDER 1 +#define LUT_PARAM_ATTN_BB 2 +#define LUT_PARAM_ALPHA_BB 3 +#define LUT_PARAM_STOP_TIME_BB 4 +#define LUT_PARAM_BB_PLL_LOOP_FILTER 5 +#define LUT_PARAM_NUM 6 + +#define ACX_EEPROMLESS_IND_REG (SCR_PAD4) +#define USE_EEPROM 0 +#define SOFT_RESET_MAX_TIME 1000000 +#define SOFT_RESET_STALL_TIME 1000 +#define NVS_DATA_BUNDARY_ALIGNMENT 4 + + +/* Firmware image load chunk size */ +#define CHUNK_SIZE 512 + +/* Firmware image header size */ +#define FW_HDR_SIZE 8 + +#define ECPU_CONTROL_HALT 0x00000101 + + +/****************************************************************************** + + CHANNELS, BAND & REG DOMAINS definitions + +******************************************************************************/ + + +enum { + RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */ + RADIO_BAND_5GHZ = 1, /* 5 Ghz band */ + RADIO_BAND_JAPAN_4_9_GHZ = 2, + DEFAULT_BAND = RADIO_BAND_2_4GHZ, + INVALID_BAND = 0xFE, + MAX_RADIO_BANDS = 0xFF +}; + +enum { + NO_RATE = 0, + RATE_1MBPS = 0x0A, + RATE_2MBPS = 0x14, + RATE_5_5MBPS = 0x37, + RATE_6MBPS = 0x0B, + RATE_9MBPS = 0x0F, + RATE_11MBPS = 0x6E, + RATE_12MBPS = 0x0A, + RATE_18MBPS = 0x0E, + RATE_22MBPS = 0xDC, + RATE_24MBPS = 0x09, + RATE_36MBPS = 0x0D, + RATE_48MBPS = 0x08, + RATE_54MBPS = 0x0C +}; + +enum { + RATE_INDEX_1MBPS = 0, + RATE_INDEX_2MBPS = 1, + RATE_INDEX_5_5MBPS = 2, + RATE_INDEX_6MBPS = 3, + RATE_INDEX_9MBPS = 4, + RATE_INDEX_11MBPS = 5, + RATE_INDEX_12MBPS = 6, + RATE_INDEX_18MBPS = 7, + RATE_INDEX_22MBPS = 8, + RATE_INDEX_24MBPS = 9, + RATE_INDEX_36MBPS = 10, + RATE_INDEX_48MBPS = 11, + RATE_INDEX_54MBPS = 12, + RATE_INDEX_MAX = RATE_INDEX_54MBPS, + MAX_RATE_INDEX, + INVALID_RATE_INDEX = MAX_RATE_INDEX, + RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF +}; + +enum { + RATE_MASK_1MBPS = 0x1, + RATE_MASK_2MBPS = 0x2, + RATE_MASK_5_5MBPS = 0x4, + RATE_MASK_11MBPS = 0x20, +}; + +#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ +#define OFDM_RATE_BIT BIT(6) +#define PBCC_RATE_BIT BIT(7) + +enum { + CCK_LONG = 0, + CCK_SHORT = SHORT_PREAMBLE_BIT, + PBCC_LONG = PBCC_RATE_BIT, + PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT, + OFDM = OFDM_RATE_BIT +}; + +/****************************************************************************** + +Transmit-Descriptor RATE-SET field definitions... + +Define a new "Rate-Set" for TX path that incorporates the +Rate & Modulation info into a single 16-bit field. + +TxdRateSet_t: +b15 - Indicates Preamble type (1=SHORT, 0=LONG). + Notes: + Must be LONG (0) for 1Mbps rate. + Does not apply (set to 0) for RevG-OFDM rates. +b14 - Indicates PBCC encoding (1=PBCC, 0=not). + Notes: + Does not apply (set to 0) for rates 1 and 2 Mbps. + Does not apply (set to 0) for RevG-OFDM rates. +b13 - Unused (set to 0). +b12-b0 - Supported Rate indicator bits as defined below. + +******************************************************************************/ + + +#define TNETW1251_CHIP_ID_PG1_0 0x07010101 +#define TNETW1251_CHIP_ID_PG1_1 0x07020101 +#define TNETW1251_CHIP_ID_PG1_2 0x07030101 + +/************************************************************************* + + Interrupt Trigger Register (Host -> WiLink) + +**************************************************************************/ + +/* Hardware to Embedded CPU Interrupts - first 32-bit register set */ + +/* + * Host Command Interrupt. Setting this bit masks + * the interrupt that the host issues to inform + * the FW that it has sent a command + * to the Wlan hardware Command Mailbox. + */ +#define INTR_TRIG_CMD BIT(0) + +/* + * Host Event Acknowlegde Interrupt. The host + * sets this bit to acknowledge that it received + * the unsolicited information from the event + * mailbox. + */ +#define INTR_TRIG_EVENT_ACK BIT(1) + +/* + * The host sets this bit to inform the Wlan + * FW that a TX packet is in the XFER + * Buffer #0. + */ +#define INTR_TRIG_TX_PROC0 BIT(2) + +/* + * The host sets this bit to inform the FW + * that it read a packet from RX XFER + * Buffer #0. + */ +#define INTR_TRIG_RX_PROC0 BIT(3) + +#define INTR_TRIG_DEBUG_ACK BIT(4) + +#define INTR_TRIG_STATE_CHANGED BIT(5) + + +/* Hardware to Embedded CPU Interrupts - second 32-bit register set */ + +/* + * The host sets this bit to inform the FW + * that it read a packet from RX XFER + * Buffer #1. + */ +#define INTR_TRIG_RX_PROC1 BIT(17) + +/* + * The host sets this bit to inform the Wlan + * hardware that a TX packet is in the XFER + * Buffer #1. + */ +#define INTR_TRIG_TX_PROC1 BIT(18) + +#endif diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c new file mode 100644 index 000000000000..981ea259eb89 --- /dev/null +++ b/drivers/net/wireless/wl12xx/rx.c @@ -0,0 +1,208 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include + +#include "wl12xx.h" +#include "reg.h" +#include "spi.h" +#include "rx.h" + +static void wl12xx_rx_header(struct wl12xx *wl, + struct wl12xx_rx_descriptor *desc) +{ + u32 rx_packet_ring_addr; + + rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr; + if (wl->rx_current_buffer) + rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; + + wl12xx_spi_mem_read(wl, rx_packet_ring_addr, desc, + sizeof(struct wl12xx_rx_descriptor)); +} + +static void wl12xx_rx_status(struct wl12xx *wl, + struct wl12xx_rx_descriptor *desc, + struct ieee80211_rx_status *status, + u8 beacon) +{ + memset(status, 0, sizeof(struct ieee80211_rx_status)); + + status->band = IEEE80211_BAND_2GHZ; + status->mactime = desc->timestamp; + + /* + * The rx status timestamp is a 32 bits value while the TSF is a + * 64 bits one. + * For IBSS merging, TSF is mandatory, so we have to get it + * somehow, so we ask for ACX_TSF_INFO. + * That could be moved to the get_tsf() hook, but unfortunately, + * this one must be atomic, while our SPI routines can sleep. + */ + if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) { + u64 mactime; + int ret; + struct wl12xx_command cmd; + struct acx_tsf_info *tsf_info; + + memset(&cmd, 0, sizeof(cmd)); + + ret = wl12xx_cmd_interrogate(wl, ACX_TSF_INFO, + sizeof(struct acx_tsf_info), + &cmd); + if (ret < 0) { + wl12xx_warning("ACX_FW_REV interrogate failed"); + return; + } + + tsf_info = (struct acx_tsf_info *)&(cmd.parameters); + + mactime = tsf_info->current_tsf_lsb | + (tsf_info->current_tsf_msb << 31); + + status->mactime = mactime; + } + + status->signal = desc->rssi; + status->qual = (desc->rssi - WL12XX_RX_MIN_RSSI) * 100 / + (WL12XX_RX_MAX_RSSI - WL12XX_RX_MIN_RSSI); + status->qual = min(status->qual, 100); + status->qual = max(status->qual, 0); + + /* + * FIXME: guessing that snr needs to be divided by two, otherwise + * the values don't make any sense + */ + status->noise = desc->rssi - desc->snr / 2; + + status->freq = ieee80211_channel_to_frequency(desc->channel); + + status->flag |= RX_FLAG_TSFT; + + if (desc->flags & RX_DESC_ENCRYPTION_MASK) { + status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; + + if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL))) + status->flag |= RX_FLAG_DECRYPTED; + + if (unlikely(desc->flags & RX_DESC_MIC_FAIL)) + status->flag |= RX_FLAG_MMIC_ERROR; + } + + if (unlikely(!(desc->flags & RX_DESC_VALID_FCS))) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + + /* FIXME: set status->rate_idx */ +} + +static void wl12xx_rx_body(struct wl12xx *wl, + struct wl12xx_rx_descriptor *desc) +{ + struct sk_buff *skb; + struct ieee80211_rx_status status; + u8 *rx_buffer, beacon = 0; + u16 length, *fc; + u32 curr_id, last_id_inc, rx_packet_ring_addr; + + length = WL12XX_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH); + curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT; + last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1); + + if (last_id_inc != curr_id) { + wl12xx_warning("curr ID:%d, last ID inc:%d", + curr_id, last_id_inc); + wl->rx_last_id = curr_id; + } else { + wl->rx_last_id = last_id_inc; + } + + rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr + + sizeof(struct wl12xx_rx_descriptor) + 20; + if (wl->rx_current_buffer) + rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; + + skb = dev_alloc_skb(length); + if (!skb) { + wl12xx_error("Couldn't allocate RX frame"); + return; + } + + rx_buffer = skb_put(skb, length); + wl12xx_spi_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); + + /* The actual lenght doesn't include the target's alignment */ + skb->len = desc->length - PLCP_HEADER_LENGTH; + + fc = (u16 *)skb->data; + + if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) + beacon = 1; + + wl12xx_rx_status(wl, desc, &status, beacon); + + wl12xx_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, + beacon ? "beacon" : ""); + + ieee80211_rx(wl->hw, skb, &status); +} + +static void wl12xx_rx_ack(struct wl12xx *wl) +{ + u32 data, addr; + + if (wl->rx_current_buffer) { + addr = ACX_REG_INTERRUPT_TRIG_H; + data = INTR_TRIG_RX_PROC1; + } else { + addr = ACX_REG_INTERRUPT_TRIG; + data = INTR_TRIG_RX_PROC0; + } + + wl12xx_reg_write32(wl, addr, data); + + /* Toggle buffer ring */ + wl->rx_current_buffer = !wl->rx_current_buffer; +} + + +void wl12xx_rx(struct wl12xx *wl) +{ + struct wl12xx_rx_descriptor rx_desc; + + if (wl->state != WL12XX_STATE_ON) + return; + + /* We first read the frame's header */ + wl12xx_rx_header(wl, &rx_desc); + + /* Now we can read the body */ + wl12xx_rx_body(wl, &rx_desc); + + /* Finally, we need to ACK the RX */ + wl12xx_rx_ack(wl); + + return; +} diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h new file mode 100644 index 000000000000..8a23fdea5016 --- /dev/null +++ b/drivers/net/wireless/wl12xx/rx.h @@ -0,0 +1,122 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_RX_H__ +#define __WL12XX_RX_H__ + +#include + +/* + * RX PATH + * + * The Rx path uses a double buffer and an rx_contro structure, each located + * at a fixed address in the device memory. The host keeps track of which + * buffer is available and alternates between them on a per packet basis. + * The size of each of the two buffers is large enough to hold the longest + * 802.3 packet. + * The RX path goes like that: + * 1) The target generates an interrupt each time a new packet is received. + * There are 2 RX interrupts, one for each buffer. + * 2) The host reads the received packet from one of the double buffers. + * 3) The host triggers a target interrupt. + * 4) The target prepares the next RX packet. + */ + +#define WL12XX_RX_MAX_RSSI -30 +#define WL12XX_RX_MIN_RSSI -95 + +#define WL12XX_RX_ALIGN_TO 4 +#define WL12XX_RX_ALIGN(len) (((len) + WL12XX_RX_ALIGN_TO - 1) & \ + ~(WL12XX_RX_ALIGN_TO - 1)) + +#define SHORT_PREAMBLE_BIT BIT(0) +#define OFDM_RATE_BIT BIT(6) +#define PBCC_RATE_BIT BIT(7) + +#define PLCP_HEADER_LENGTH 8 +#define RX_DESC_PACKETID_SHIFT 11 +#define RX_MAX_PACKET_ID 3 + +#define RX_DESC_VALID_FCS 0x0001 +#define RX_DESC_MATCH_RXADDR1 0x0002 +#define RX_DESC_MCAST 0x0004 +#define RX_DESC_STAINTIM 0x0008 +#define RX_DESC_VIRTUAL_BM 0x0010 +#define RX_DESC_BCAST 0x0020 +#define RX_DESC_MATCH_SSID 0x0040 +#define RX_DESC_MATCH_BSSID 0x0080 +#define RX_DESC_ENCRYPTION_MASK 0x0300 +#define RX_DESC_MEASURMENT 0x0400 +#define RX_DESC_SEQNUM_MASK 0x1800 +#define RX_DESC_MIC_FAIL 0x2000 +#define RX_DESC_DECRYPT_FAIL 0x4000 + +struct wl12xx_rx_descriptor { + u32 timestamp; /* In microseconds */ + u16 length; /* Paylod length, including headers */ + u16 flags; + + /* + * 0 - 802.11 + * 1 - 802.3 + * 2 - IP + * 3 - Raw Codec + */ + u8 type; + + /* + * Recevied Rate: + * 0x0A - 1MBPS + * 0x14 - 2MBPS + * 0x37 - 5_5MBPS + * 0x0B - 6MBPS + * 0x0F - 9MBPS + * 0x6E - 11MBPS + * 0x0A - 12MBPS + * 0x0E - 18MBPS + * 0xDC - 22MBPS + * 0x09 - 24MBPS + * 0x0D - 36MBPS + * 0x08 - 48MBPS + * 0x0C - 54MBPS + */ + u8 rate; + + u8 mod_pre; /* Modulation and preamble */ + u8 channel; + + /* + * 0 - 2.4 Ghz + * 1 - 5 Ghz + */ + u8 band; + + s8 rssi; /* in dB */ + u8 rcpi; /* in dB */ + u8 snr; /* in dB */ +} __attribute__ ((packed)); + +void wl12xx_rx(struct wl12xx *wl); + +#endif diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c new file mode 100644 index 000000000000..abdf171a47e7 --- /dev/null +++ b/drivers/net/wireless/wl12xx/spi.c @@ -0,0 +1,358 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include + +#include "wl12xx.h" +#include "wl12xx_80211.h" +#include "reg.h" +#include "spi.h" +#include "ps.h" + +static int wl12xx_translate_reg_addr(struct wl12xx *wl, int addr) +{ + /* If the address is lower than REGISTERS_BASE, it means that this is + * a chip-specific register address, so look it up in the registers + * table */ + if (addr < REGISTERS_BASE) { + /* Make sure we don't go over the table */ + if (addr >= ACX_REG_TABLE_LEN) { + wl12xx_error("address out of range (%d)", addr); + return -EINVAL; + } + addr = wl->chip.acx_reg_table[addr]; + } + + return addr - wl->physical_reg_addr + wl->virtual_reg_addr; +} + +static int wl12xx_translate_mem_addr(struct wl12xx *wl, int addr) +{ + return addr - wl->physical_mem_addr + wl->virtual_mem_addr; +} + + +void wl12xx_spi_reset(struct wl12xx *wl) +{ + u8 *cmd; + struct spi_transfer t; + struct spi_message m; + + cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); + if (!cmd) { + wl12xx_error("could not allocate cmd for spi reset"); + return; + } + + memset(&t, 0, sizeof(t)); + spi_message_init(&m); + + memset(cmd, 0xff, WSPI_INIT_CMD_LEN); + + t.tx_buf = cmd; + t.len = WSPI_INIT_CMD_LEN; + spi_message_add_tail(&t, &m); + + spi_sync(wl->spi, &m); + + wl12xx_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); +} + +void wl12xx_spi_init(struct wl12xx *wl) +{ + u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; + struct spi_transfer t; + struct spi_message m; + + cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); + if (!cmd) { + wl12xx_error("could not allocate cmd for spi init"); + return; + } + + memset(crc, 0, sizeof(crc)); + memset(&t, 0, sizeof(t)); + spi_message_init(&m); + + /* + * Set WSPI_INIT_COMMAND + * the data is being send from the MSB to LSB + */ + cmd[2] = 0xff; + cmd[3] = 0xff; + cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; + cmd[0] = 0; + cmd[7] = 0; + cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; + cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; + + if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) + cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; + else + cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; + + cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS + | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; + + crc[0] = cmd[1]; + crc[1] = cmd[0]; + crc[2] = cmd[7]; + crc[3] = cmd[6]; + crc[4] = cmd[5]; + + cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; + cmd[4] |= WSPI_INIT_CMD_END; + + t.tx_buf = cmd; + t.len = WSPI_INIT_CMD_LEN; + spi_message_add_tail(&t, &m); + + spi_sync(wl->spi, &m); + + wl12xx_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); +} + +/* Set the SPI partitions to access the chip addresses + * + * There are two VIRTUAL (SPI) partitions (the memory partition and the + * registers partition), which are mapped to two different areas of the + * PHYSICAL (hardware) memory. This function also makes other checks to + * ensure that the partitions are not overlapping. In the diagram below, the + * memory partition comes before the register partition, but the opposite is + * also supported. + * + * PHYSICAL address + * space + * + * | | + * ...+----+--> mem_start + * VIRTUAL address ... | | + * space ... | | [PART_0] + * ... | | + * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size + * | | ... | | + * |MEM | ... | | + * | | ... | | + * part_size <--+----+... | | {unused area) + * | | ... | | + * |REG | ... | | + * part_size | | ... | | + * + <--+----+... ...+----+--> reg_start + * reg_size ... | | + * ... | | [PART_1] + * ... | | + * ...+----+--> reg_start + reg_size + * | | + * + */ +void wl12xx_set_partition(struct wl12xx *wl, + u32 mem_start, u32 mem_size, + u32 reg_start, u32 reg_size) +{ + u8 tx_buf[sizeof(u32) + 2 * sizeof(struct wl12xx_partition)]; + struct wl12xx_partition *partition; + struct spi_transfer t; + struct spi_message m; + u32 *cmd; + size_t len; + int addr; + + spi_message_init(&m); + memset(&t, 0, sizeof(t)); + memset(tx_buf, 0, sizeof(tx_buf)); + + cmd = (u32 *) tx_buf; + partition = (struct wl12xx_partition *) (tx_buf + sizeof(u32)); + addr = HW_ACCESS_PART0_SIZE_ADDR; + len = 2 * sizeof(struct wl12xx_partition); + + *cmd |= WSPI_CMD_WRITE; + *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; + *cmd |= addr & WSPI_CMD_BYTE_ADDR; + + wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + mem_start, mem_size); + wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", + reg_start, reg_size); + + /* Make sure that the two partitions together don't exceed the + * address range */ + if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { + wl12xx_debug(DEBUG_SPI, "Total size exceeds maximum virtual" + " address range. Truncating partition[0]."); + mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; + wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + mem_start, mem_size); + wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", + reg_start, reg_size); + } + + if ((mem_start < reg_start) && + ((mem_start + mem_size) > reg_start)) { + /* Guarantee that the memory partition doesn't overlap the + * registers partition */ + wl12xx_debug(DEBUG_SPI, "End of partition[0] is " + "overlapping partition[1]. Adjusted."); + mem_size = reg_start - mem_start; + wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + mem_start, mem_size); + wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", + reg_start, reg_size); + } else if ((reg_start < mem_start) && + ((reg_start + reg_size) > mem_start)) { + /* Guarantee that the register partition doesn't overlap the + * memory partition */ + wl12xx_debug(DEBUG_SPI, "End of partition[1] is" + " overlapping partition[0]. Adjusted."); + reg_size = mem_start - reg_start; + wl12xx_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + mem_start, mem_size); + wl12xx_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", + reg_start, reg_size); + } + + partition[0].start = mem_start; + partition[0].size = mem_size; + partition[1].start = reg_start; + partition[1].size = reg_size; + + wl->physical_mem_addr = mem_start; + wl->physical_reg_addr = reg_start; + + wl->virtual_mem_addr = 0; + wl->virtual_reg_addr = mem_size; + + t.tx_buf = tx_buf; + t.len = sizeof(tx_buf); + spi_message_add_tail(&t, &m); + + spi_sync(wl->spi, &m); +} + +void wl12xx_spi_read(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + struct spi_transfer t[3]; + struct spi_message m; + char busy_buf[TNETWIF_READ_OFFSET_BYTES]; + u32 cmd; + + cmd = 0; + cmd |= WSPI_CMD_READ; + cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; + cmd |= addr & WSPI_CMD_BYTE_ADDR; + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &cmd; + t[0].len = 4; + spi_message_add_tail(&t[0], &m); + + /* Busy and non busy words read */ + t[1].rx_buf = busy_buf; + t[1].len = TNETWIF_READ_OFFSET_BYTES; + spi_message_add_tail(&t[1], &m); + + t[2].rx_buf = buf; + t[2].len = len; + spi_message_add_tail(&t[2], &m); + + spi_sync(wl->spi, &m); + + /* FIXME: check busy words */ + + wl12xx_dump(DEBUG_SPI, "spi_read cmd -> ", &cmd, sizeof(cmd)); + wl12xx_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); +} + +void wl12xx_spi_write(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + struct spi_transfer t[2]; + struct spi_message m; + u32 cmd; + + cmd = 0; + cmd |= WSPI_CMD_WRITE; + cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; + cmd |= addr & WSPI_CMD_BYTE_ADDR; + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &cmd; + t[0].len = sizeof(cmd); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + spi_sync(wl->spi, &m); + + wl12xx_dump(DEBUG_SPI, "spi_write cmd -> ", &cmd, sizeof(cmd)); + wl12xx_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); +} + +void wl12xx_spi_mem_read(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + int physical; + + physical = wl12xx_translate_mem_addr(wl, addr); + + wl12xx_spi_read(wl, physical, buf, len); +} + +void wl12xx_spi_mem_write(struct wl12xx *wl, int addr, void *buf, + size_t len) +{ + int physical; + + physical = wl12xx_translate_mem_addr(wl, addr); + + wl12xx_spi_write(wl, physical, buf, len); +} + +u32 wl12xx_mem_read32(struct wl12xx *wl, int addr) +{ + return wl12xx_read32(wl, wl12xx_translate_mem_addr(wl, addr)); +} + +void wl12xx_mem_write32(struct wl12xx *wl, int addr, u32 val) +{ + wl12xx_write32(wl, wl12xx_translate_mem_addr(wl, addr), val); +} + +u32 wl12xx_reg_read32(struct wl12xx *wl, int addr) +{ + return wl12xx_read32(wl, wl12xx_translate_reg_addr(wl, addr)); +} + +void wl12xx_reg_write32(struct wl12xx *wl, int addr, u32 val) +{ + wl12xx_write32(wl, wl12xx_translate_reg_addr(wl, addr), val); +} diff --git a/drivers/net/wireless/wl12xx/spi.h b/drivers/net/wireless/wl12xx/spi.h new file mode 100644 index 000000000000..fd3227e904a8 --- /dev/null +++ b/drivers/net/wireless/wl12xx/spi.h @@ -0,0 +1,109 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_SPI_H__ +#define __WL12XX_SPI_H__ + +#include "cmd.h" +#include "acx.h" +#include "reg.h" + +#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 + +#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0 +#define HW_ACCESS_PART0_START_ADDR 0x1FFC4 +#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8 +#define HW_ACCESS_PART1_START_ADDR 0x1FFCC + +#define HW_ACCESS_REGISTER_SIZE 4 + +#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 + +#define WSPI_CMD_READ 0x40000000 +#define WSPI_CMD_WRITE 0x00000000 +#define WSPI_CMD_FIXED 0x20000000 +#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 +#define WSPI_CMD_BYTE_LENGTH_OFFSET 17 +#define WSPI_CMD_BYTE_ADDR 0x0001FFFF + +#define WSPI_INIT_CMD_CRC_LEN 5 + +#define WSPI_INIT_CMD_START 0x00 +#define WSPI_INIT_CMD_TX 0x40 +/* the extra bypass bit is sampled by the TNET as '1' */ +#define WSPI_INIT_CMD_BYPASS_BIT 0x80 +#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 +#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 +#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 +#define WSPI_INIT_CMD_IOD 0x40 +#define WSPI_INIT_CMD_IP 0x20 +#define WSPI_INIT_CMD_CS 0x10 +#define WSPI_INIT_CMD_WS 0x08 +#define WSPI_INIT_CMD_WSPI 0x01 +#define WSPI_INIT_CMD_END 0x01 + +#define WSPI_INIT_CMD_LEN 8 + +#define TNETWIF_READ_OFFSET_BYTES 8 +#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ + ((TNETWIF_READ_OFFSET_BYTES - 4) / sizeof(u32)) +#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 + + +/* Raw target IO, address is not translated */ +void wl12xx_spi_read(struct wl12xx *wl, int addr, void *buf, size_t len); +void wl12xx_spi_write(struct wl12xx *wl, int addr, void *buf, size_t len); + +/* Memory target IO, address is tranlated to partition 0 */ +void wl12xx_spi_mem_read(struct wl12xx *wl, int addr, void *buf, size_t len); +void wl12xx_spi_mem_write(struct wl12xx *wl, int addr, void *buf, size_t len); +u32 wl12xx_mem_read32(struct wl12xx *wl, int addr); +void wl12xx_mem_write32(struct wl12xx *wl, int addr, u32 val); + +/* Registers IO */ +u32 wl12xx_reg_read32(struct wl12xx *wl, int addr); +void wl12xx_reg_write32(struct wl12xx *wl, int addr, u32 val); + +/* INIT and RESET words */ +void wl12xx_spi_reset(struct wl12xx *wl); +void wl12xx_spi_init(struct wl12xx *wl); +void wl12xx_set_partition(struct wl12xx *wl, + u32 part_start, u32 part_size, + u32 reg_start, u32 reg_size); + +static inline u32 wl12xx_read32(struct wl12xx *wl, int addr) +{ + u32 response; + + wl12xx_spi_read(wl, addr, &response, sizeof(u32)); + + return response; +} + +static inline void wl12xx_write32(struct wl12xx *wl, int addr, u32 val) +{ + wl12xx_spi_write(wl, addr, &val, sizeof(u32)); +} + +#endif /* __WL12XX_SPI_H__ */ diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c new file mode 100644 index 000000000000..62145e205a8c --- /dev/null +++ b/drivers/net/wireless/wl12xx/tx.c @@ -0,0 +1,557 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include + +#include "wl12xx.h" +#include "reg.h" +#include "spi.h" +#include "tx.h" +#include "ps.h" + +static bool wl12xx_tx_double_buffer_busy(struct wl12xx *wl, u32 data_out_count) +{ + int used, data_in_count; + + data_in_count = wl->data_in_count; + + if (data_in_count < data_out_count) + /* data_in_count has wrapped */ + data_in_count += TX_STATUS_DATA_OUT_COUNT_MASK + 1; + + used = data_in_count - data_out_count; + + WARN_ON(used < 0); + WARN_ON(used > DP_TX_PACKET_RING_CHUNK_NUM); + + if (used >= DP_TX_PACKET_RING_CHUNK_NUM) + return true; + else + return false; +} + +static int wl12xx_tx_path_status(struct wl12xx *wl) +{ + u32 status, addr, data_out_count; + bool busy; + + addr = wl->data_path->tx_control_addr; + status = wl12xx_mem_read32(wl, addr); + data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK; + busy = wl12xx_tx_double_buffer_busy(wl, data_out_count); + + if (busy) + return -EBUSY; + + return 0; +} + +static int wl12xx_tx_id(struct wl12xx *wl, struct sk_buff *skb) +{ + int i; + + for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) + if (wl->tx_frames[i] == NULL) { + wl->tx_frames[i] = skb; + return i; + } + + return -EBUSY; +} + +static void wl12xx_tx_control(struct tx_double_buffer_desc *tx_hdr, + struct ieee80211_tx_info *control, u16 fc) +{ + *(u16 *)&tx_hdr->control = 0; + + tx_hdr->control.rate_policy = 0; + + /* 802.11 packets */ + tx_hdr->control.packet_type = 0; + + if (control->flags & IEEE80211_TX_CTL_NO_ACK) + tx_hdr->control.ack_policy = 1; + + tx_hdr->control.tx_complete = 1; + + if ((fc & IEEE80211_FTYPE_DATA) && + ((fc & IEEE80211_STYPE_QOS_DATA) || + (fc & IEEE80211_STYPE_QOS_NULLFUNC))) + tx_hdr->control.qos = 1; +} + +/* RSN + MIC = 8 + 8 = 16 bytes (worst case - AES). */ +#define MAX_MSDU_SECURITY_LENGTH 16 +#define MAX_MPDU_SECURITY_LENGTH 16 +#define WLAN_QOS_HDR_LEN 26 +#define MAX_MPDU_HEADER_AND_SECURITY (MAX_MPDU_SECURITY_LENGTH + \ + WLAN_QOS_HDR_LEN) +#define HW_BLOCK_SIZE 252 +static void wl12xx_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr) +{ + u16 payload_len, frag_threshold, mem_blocks; + u16 num_mpdus, mem_blocks_per_frag; + + frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; + tx_hdr->frag_threshold = cpu_to_le16(frag_threshold); + + payload_len = tx_hdr->length + MAX_MSDU_SECURITY_LENGTH; + + if (payload_len > frag_threshold) { + mem_blocks_per_frag = + ((frag_threshold + MAX_MPDU_HEADER_AND_SECURITY) / + HW_BLOCK_SIZE) + 1; + num_mpdus = payload_len / frag_threshold; + mem_blocks = num_mpdus * mem_blocks_per_frag; + payload_len -= num_mpdus * frag_threshold; + num_mpdus++; + + } else { + mem_blocks_per_frag = 0; + mem_blocks = 0; + num_mpdus = 1; + } + + mem_blocks += (payload_len / HW_BLOCK_SIZE) + 1; + + if (num_mpdus > 1) + mem_blocks += min(num_mpdus, mem_blocks_per_frag); + + tx_hdr->num_mem_blocks = mem_blocks; +} + +static int wl12xx_tx_fill_hdr(struct wl12xx *wl, struct sk_buff *skb, + struct ieee80211_tx_info *control) +{ + struct tx_double_buffer_desc *tx_hdr; + struct ieee80211_rate *rate; + int id; + u16 fc; + + if (!skb) + return -EINVAL; + + id = wl12xx_tx_id(wl, skb); + if (id < 0) + return id; + + fc = *(u16 *)skb->data; + tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb, + sizeof(*tx_hdr)); + + tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr)); + rate = ieee80211_get_tx_rate(wl->hw, control); + tx_hdr->rate = cpu_to_le16(rate->hw_value); + tx_hdr->expiry_time = cpu_to_le32(1 << 16); + tx_hdr->id = id; + + /* FIXME: how to get the correct queue id? */ + tx_hdr->xmit_queue = 0; + + wl12xx_tx_control(tx_hdr, control, fc); + wl12xx_tx_frag_block_num(tx_hdr); + + return 0; +} + +/* We copy the packet to the target */ +static int wl12xx_tx_send_packet(struct wl12xx *wl, struct sk_buff *skb, + struct ieee80211_tx_info *control) +{ + struct tx_double_buffer_desc *tx_hdr; + int len; + u32 addr; + + if (!skb) + return -EINVAL; + + tx_hdr = (struct tx_double_buffer_desc *) skb->data; + + if (control->control.hw_key && + control->control.hw_key->alg == ALG_TKIP) { + int hdrlen; + u16 fc; + u8 *pos; + + fc = *(u16 *)(skb->data + sizeof(*tx_hdr)); + tx_hdr->length += WL12XX_TKIP_IV_SPACE; + + hdrlen = ieee80211_hdrlen(fc); + + pos = skb_push(skb, WL12XX_TKIP_IV_SPACE); + memmove(pos, pos + WL12XX_TKIP_IV_SPACE, + sizeof(*tx_hdr) + hdrlen); + } + + /* Revisit. This is a workaround for getting non-aligned packets. + This happens at least with EAPOL packets from the user space. + Our DMA requires packets to be aligned on a 4-byte boundary. + */ + if (unlikely((long)skb->data & 0x03)) { + int offset = (4 - (long)skb->data) & 0x03; + wl12xx_debug(DEBUG_TX, "skb offset %d", offset); + + /* check whether the current skb can be used */ + if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { + unsigned char *src = skb->data; + + /* align the buffer on a 4-byte boundary */ + skb_reserve(skb, offset); + memmove(skb->data, src, skb->len); + } else { + wl12xx_info("No handler, fixme!"); + return -EINVAL; + } + } + + /* Our skb->data at this point includes the HW header */ + len = WL12XX_TX_ALIGN(skb->len); + + if (wl->data_in_count & 0x1) + addr = wl->data_path->tx_packet_ring_addr + + wl->data_path->tx_packet_ring_chunk_size; + else + addr = wl->data_path->tx_packet_ring_addr; + + wl12xx_spi_mem_write(wl, addr, skb->data, len); + + wl12xx_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", + tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); + + return 0; +} + +static void wl12xx_tx_trigger(struct wl12xx *wl) +{ + u32 data, addr; + + if (wl->data_in_count & 0x1) { + addr = ACX_REG_INTERRUPT_TRIG_H; + data = INTR_TRIG_TX_PROC1; + } else { + addr = ACX_REG_INTERRUPT_TRIG; + data = INTR_TRIG_TX_PROC0; + } + + wl12xx_reg_write32(wl, addr, data); + + /* Bumping data in */ + wl->data_in_count = (wl->data_in_count + 1) & + TX_STATUS_DATA_OUT_COUNT_MASK; +} + +/* caller must hold wl->mutex */ +static int wl12xx_tx_frame(struct wl12xx *wl, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info; + int ret = 0; + u8 idx; + + info = IEEE80211_SKB_CB(skb); + + if (info->control.hw_key) { + idx = info->control.hw_key->hw_key_idx; + if (unlikely(wl->default_key != idx)) { + ret = wl12xx_acx_default_key(wl, idx); + if (ret < 0) + return ret; + } + } + + ret = wl12xx_tx_path_status(wl); + if (ret < 0) + return ret; + + ret = wl12xx_tx_fill_hdr(wl, skb, info); + if (ret < 0) + return ret; + + ret = wl12xx_tx_send_packet(wl, skb, info); + if (ret < 0) + return ret; + + wl12xx_tx_trigger(wl); + + return ret; +} + +void wl12xx_tx_work(struct work_struct *work) +{ + struct wl12xx *wl = container_of(work, struct wl12xx, tx_work); + struct sk_buff *skb; + bool woken_up = false; + int ret; + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL12XX_STATE_OFF)) + goto out; + + while ((skb = skb_dequeue(&wl->tx_queue))) { + if (!woken_up) { + wl12xx_ps_elp_wakeup(wl); + woken_up = true; + } + + ret = wl12xx_tx_frame(wl, skb); + if (ret == -EBUSY) { + /* firmware buffer is full, stop queues */ + wl12xx_debug(DEBUG_TX, "tx_work: fw buffer full, " + "stop queues"); + ieee80211_stop_queues(wl->hw); + wl->tx_queue_stopped = true; + skb_queue_head(&wl->tx_queue, skb); + goto out; + } else if (ret < 0) { + dev_kfree_skb(skb); + goto out; + } + } + +out: + if (woken_up) + wl12xx_ps_elp_sleep(wl); + + mutex_unlock(&wl->mutex); +} + +static const char *wl12xx_tx_parse_status(u8 status) +{ + /* 8 bit status field, one character per bit plus null */ + static char buf[9]; + int i = 0; + + memset(buf, 0, sizeof(buf)); + + if (status & TX_DMA_ERROR) + buf[i++] = 'm'; + if (status & TX_DISABLED) + buf[i++] = 'd'; + if (status & TX_RETRY_EXCEEDED) + buf[i++] = 'r'; + if (status & TX_TIMEOUT) + buf[i++] = 't'; + if (status & TX_KEY_NOT_FOUND) + buf[i++] = 'k'; + if (status & TX_ENCRYPT_FAIL) + buf[i++] = 'e'; + if (status & TX_UNAVAILABLE_PRIORITY) + buf[i++] = 'p'; + + /* bit 0 is unused apparently */ + + return buf; +} + +static void wl12xx_tx_packet_cb(struct wl12xx *wl, + struct tx_result *result) +{ + struct ieee80211_tx_info *info; + struct sk_buff *skb; + int hdrlen, ret; + u8 *frame; + + skb = wl->tx_frames[result->id]; + if (skb == NULL) { + wl12xx_error("SKB for packet %d is NULL", result->id); + return; + } + + info = IEEE80211_SKB_CB(skb); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (result->status == TX_SUCCESS)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = result->ack_failures + 1; + wl->stats.retry_count += result->ack_failures; + + /* + * We have to remove our private TX header before pushing + * the skb back to mac80211. + */ + frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); + if (info->control.hw_key && + info->control.hw_key->alg == ALG_TKIP) { + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + memmove(frame + WL12XX_TKIP_IV_SPACE, frame, hdrlen); + skb_pull(skb, WL12XX_TKIP_IV_SPACE); + } + + wl12xx_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" + " status 0x%x (%s)", + result->id, skb, result->ack_failures, result->rate, + result->status, wl12xx_tx_parse_status(result->status)); + + + ieee80211_tx_status(wl->hw, skb); + + wl->tx_frames[result->id] = NULL; + + if (wl->tx_queue_stopped) { + wl12xx_debug(DEBUG_TX, "cb: queue was stopped"); + + skb = skb_dequeue(&wl->tx_queue); + + /* The skb can be NULL because tx_work might have been + scheduled before the queue was stopped making the + queue empty */ + + if (skb) { + ret = wl12xx_tx_frame(wl, skb); + if (ret == -EBUSY) { + /* firmware buffer is still full */ + wl12xx_debug(DEBUG_TX, "cb: fw buffer " + "still full"); + skb_queue_head(&wl->tx_queue, skb); + return; + } else if (ret < 0) { + dev_kfree_skb(skb); + return; + } + } + + wl12xx_debug(DEBUG_TX, "cb: waking queues"); + ieee80211_wake_queues(wl->hw); + wl->tx_queue_stopped = false; + } +} + +/* Called upon reception of a TX complete interrupt */ +void wl12xx_tx_complete(struct wl12xx *wl) +{ + int i, result_index, num_complete = 0; + struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; + + if (unlikely(wl->state != WL12XX_STATE_ON)) + return; + + /* First we read the result */ + wl12xx_spi_mem_read(wl, wl->data_path->tx_complete_addr, + result, sizeof(result)); + + result_index = wl->next_tx_complete; + + for (i = 0; i < ARRAY_SIZE(result); i++) { + result_ptr = &result[result_index]; + + if (result_ptr->done_1 == 1 && + result_ptr->done_2 == 1) { + wl12xx_tx_packet_cb(wl, result_ptr); + + result_ptr->done_1 = 0; + result_ptr->done_2 = 0; + + result_index = (result_index + 1) & + (FW_TX_CMPLT_BLOCK_SIZE - 1); + num_complete++; + } else { + break; + } + } + + /* Every completed frame needs to be acknowledged */ + if (num_complete) { + /* + * If we've wrapped, we have to clear + * the results in 2 steps. + */ + if (result_index > wl->next_tx_complete) { + /* Only 1 write is needed */ + wl12xx_spi_mem_write(wl, + wl->data_path->tx_complete_addr + + (wl->next_tx_complete * + sizeof(struct tx_result)), + &result[wl->next_tx_complete], + num_complete * + sizeof(struct tx_result)); + + + } else if (result_index < wl->next_tx_complete) { + /* 2 writes are needed */ + wl12xx_spi_mem_write(wl, + wl->data_path->tx_complete_addr + + (wl->next_tx_complete * + sizeof(struct tx_result)), + &result[wl->next_tx_complete], + (FW_TX_CMPLT_BLOCK_SIZE - + wl->next_tx_complete) * + sizeof(struct tx_result)); + + wl12xx_spi_mem_write(wl, + wl->data_path->tx_complete_addr, + result, + (num_complete - + FW_TX_CMPLT_BLOCK_SIZE + + wl->next_tx_complete) * + sizeof(struct tx_result)); + + } else { + /* We have to write the whole array */ + wl12xx_spi_mem_write(wl, + wl->data_path->tx_complete_addr, + result, + FW_TX_CMPLT_BLOCK_SIZE * + sizeof(struct tx_result)); + } + + } + + wl->next_tx_complete = result_index; +} + +/* caller must hold wl->mutex */ +void wl12xx_tx_flush(struct wl12xx *wl) +{ + int i; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + + /* TX failure */ +/* control->flags = 0; FIXME */ + + while ((skb = skb_dequeue(&wl->tx_queue))) { + info = IEEE80211_SKB_CB(skb); + + wl12xx_debug(DEBUG_TX, "flushing skb 0x%p", skb); + + if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) + continue; + + ieee80211_tx_status(wl->hw, skb); + } + + for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) + if (wl->tx_frames[i] != NULL) { + skb = wl->tx_frames[i]; + info = IEEE80211_SKB_CB(skb); + + if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) + continue; + + ieee80211_tx_status(wl->hw, skb); + wl->tx_frames[i] = NULL; + } +} diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h new file mode 100644 index 000000000000..dc82691f4c14 --- /dev/null +++ b/drivers/net/wireless/wl12xx/tx.h @@ -0,0 +1,215 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_TX_H__ +#define __WL12XX_TX_H__ + +#include + +/* + * + * TX PATH + * + * The Tx path uses a double buffer and a tx_control structure, each located + * at a fixed address in the device's memory. On startup, the host retrieves + * the pointers to these addresses. A double buffer allows for continuous data + * flow towards the device. The host keeps track of which buffer is available + * and alternates between these two buffers on a per packet basis. + * + * The size of each of the two buffers is large enough to hold the longest + * 802.3 packet - maximum size Ethernet packet + header + descriptor. + * TX complete indication will be received a-synchronously in a TX done cyclic + * buffer which is composed of 16 tx_result descriptors structures and is used + * in a cyclic manner. + * + * The TX (HOST) procedure is as follows: + * 1. Read the Tx path status, that will give the data_out_count. + * 2. goto 1, if not possible. + * i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double + * buffer). + * 3. Copy the packet (preceded by double_buffer_desc), if possible. + * i.e. if data_in_count - data_out_count < HwBuffer size (2 for double + * buffer). + * 4. increment data_in_count. + * 5. Inform the firmware by generating a firmware internal interrupt. + * 6. FW will increment data_out_count after it reads the buffer. + * + * The TX Complete procedure: + * 1. To get a TX complete indication the host enables the tx_complete flag in + * the TX descriptor Structure. + * 2. For each packet with a Tx Complete field set, the firmware adds the + * transmit results to the cyclic buffer (txDoneRing) and sets both done_1 + * and done_2 to 1 to indicate driver ownership. + * 3. The firmware sends a Tx Complete interrupt to the host to trigger the + * host to process the new data. Note: interrupt will be send per packet if + * TX complete indication was requested in tx_control or per crossing + * aggregation threshold. + * 4. After receiving the Tx Complete interrupt, the host reads the + * TxDescriptorDone information in a cyclic manner and clears both done_1 + * and done_2 fields. + * + */ + +#define TX_COMPLETE_REQUIRED_BIT 0x80 +#define TX_STATUS_DATA_OUT_COUNT_MASK 0xf +#define WL12XX_TX_ALIGN_TO 4 +#define WL12XX_TX_ALIGN(len) (((len) + WL12XX_TX_ALIGN_TO - 1) & \ + ~(WL12XX_TX_ALIGN_TO - 1)) +#define WL12XX_TKIP_IV_SPACE 4 + +struct tx_control { + /* Rate Policy (class) index */ + unsigned rate_policy:3; + + /* When set, no ack policy is expected */ + unsigned ack_policy:1; + + /* + * Packet type: + * 0 -> 802.11 + * 1 -> 802.3 + * 2 -> IP + * 3 -> raw codec + */ + unsigned packet_type:2; + + /* If set, this is a QoS-Null or QoS-Data frame */ + unsigned qos:1; + + /* + * If set, the target triggers the tx complete INT + * upon frame sending completion. + */ + unsigned tx_complete:1; + + /* 2 bytes padding before packet header */ + unsigned xfer_pad:1; + + unsigned reserved:7; +} __attribute__ ((packed)); + + +struct tx_double_buffer_desc { + /* Length of payload, including headers. */ + u16 length; + + /* + * A bit mask that specifies the initial rate to be used + * Possible values are: + * 0x0001 - 1Mbits + * 0x0002 - 2Mbits + * 0x0004 - 5.5Mbits + * 0x0008 - 6Mbits + * 0x0010 - 9Mbits + * 0x0020 - 11Mbits + * 0x0040 - 12Mbits + * 0x0080 - 18Mbits + * 0x0100 - 22Mbits + * 0x0200 - 24Mbits + * 0x0400 - 36Mbits + * 0x0800 - 48Mbits + * 0x1000 - 54Mbits + */ + u16 rate; + + /* Time in us that a packet can spend in the target */ + u32 expiry_time; + + /* index of the TX queue used for this packet */ + u8 xmit_queue; + + /* Used to identify a packet */ + u8 id; + + struct tx_control control; + + /* + * The FW should cut the packet into fragments + * of this size. + */ + u16 frag_threshold; + + /* Numbers of HW queue blocks to be allocated */ + u8 num_mem_blocks; + + u8 reserved; +} __attribute__ ((packed)); + +enum { + TX_SUCCESS = 0, + TX_DMA_ERROR = BIT(7), + TX_DISABLED = BIT(6), + TX_RETRY_EXCEEDED = BIT(5), + TX_TIMEOUT = BIT(4), + TX_KEY_NOT_FOUND = BIT(3), + TX_ENCRYPT_FAIL = BIT(2), + TX_UNAVAILABLE_PRIORITY = BIT(1), +}; + +struct tx_result { + /* + * Ownership synchronization between the host and + * the firmware. If done_1 and done_2 are cleared, + * owned by the FW (no info ready). + */ + u8 done_1; + + /* same as double_buffer_desc->id */ + u8 id; + + /* + * Total air access duration consumed by this + * packet, including all retries and overheads. + */ + u16 medium_usage; + + /* Total media delay (from 1st EDCA AIFS counter until TX Complete). */ + u32 medium_delay; + + /* Time between host xfer and tx complete */ + u32 fw_hnadling_time; + + /* The LS-byte of the last TKIP sequence number. */ + u8 lsb_seq_num; + + /* Retry count */ + u8 ack_failures; + + /* At which rate we got a ACK */ + u16 rate; + + u16 reserved; + + /* TX_* */ + u8 status; + + /* See done_1 */ + u8 done_2; +} __attribute__ ((packed)); + +void wl12xx_tx_work(struct work_struct *work); +void wl12xx_tx_complete(struct wl12xx *wl); +void wl12xx_tx_flush(struct wl12xx *wl); + +#endif diff --git a/drivers/net/wireless/wl12xx/wl1251.c b/drivers/net/wireless/wl12xx/wl1251.c new file mode 100644 index 000000000000..bd0decdcad23 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1251.c @@ -0,0 +1,709 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include + +#include "wl1251.h" +#include "reg.h" +#include "spi.h" +#include "boot.h" +#include "event.h" +#include "acx.h" +#include "tx.h" +#include "rx.h" +#include "ps.h" +#include "init.h" + +static struct wl12xx_partition_set wl1251_part_table[PART_TABLE_LEN] = { + [PART_DOWN] = { + .mem = { + .start = 0x00000000, + .size = 0x00016800 + }, + .reg = { + .start = REGISTERS_BASE, + .size = REGISTERS_DOWN_SIZE + }, + }, + + [PART_WORK] = { + .mem = { + .start = 0x00028000, + .size = 0x00014000 + }, + .reg = { + .start = REGISTERS_BASE, + .size = REGISTERS_WORK_SIZE + }, + }, + + /* WL1251 doesn't use the DRPW partition, so we don't set it here */ +}; + +static enum wl12xx_acx_int_reg wl1251_acx_reg_table[ACX_REG_TABLE_LEN] = { + [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474), + [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478), + [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494), + [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498), + [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C), + [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0), + [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4), + [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8), + [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000), + [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C), + [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804) +}; + +static int wl1251_upload_firmware(struct wl12xx *wl) +{ + struct wl12xx_partition_set *p_table = wl->chip.p_table; + int addr, chunk_num, partition_limit; + size_t fw_data_len; + u8 *p; + + /* whal_FwCtrl_LoadFwImageSm() */ + + wl12xx_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x", + wl12xx_reg_read32(wl, CHIP_ID_B)); + + /* 10.0 check firmware length and set partition */ + fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) | + (wl->fw[6] << 8) | (wl->fw[7]); + + wl12xx_debug(DEBUG_BOOT, "fw_data_len %d chunk_size %d", fw_data_len, + CHUNK_SIZE); + + if ((fw_data_len % 4) != 0) { + wl12xx_error("firmware length not multiple of four"); + return -EIO; + } + + wl12xx_set_partition(wl, + p_table[PART_DOWN].mem.start, + p_table[PART_DOWN].mem.size, + p_table[PART_DOWN].reg.start, + p_table[PART_DOWN].reg.size); + + /* 10.1 set partition limit and chunk num */ + chunk_num = 0; + partition_limit = p_table[PART_DOWN].mem.size; + + while (chunk_num < fw_data_len / CHUNK_SIZE) { + /* 10.2 update partition, if needed */ + addr = p_table[PART_DOWN].mem.start + + (chunk_num + 2) * CHUNK_SIZE; + if (addr > partition_limit) { + addr = p_table[PART_DOWN].mem.start + + chunk_num * CHUNK_SIZE; + partition_limit = chunk_num * CHUNK_SIZE + + p_table[PART_DOWN].mem.size; + wl12xx_set_partition(wl, + addr, + p_table[PART_DOWN].mem.size, + p_table[PART_DOWN].reg.start, + p_table[PART_DOWN].reg.size); + } + + /* 10.3 upload the chunk */ + addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE; + p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; + wl12xx_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", + p, addr); + wl12xx_spi_mem_write(wl, addr, p, CHUNK_SIZE); + + chunk_num++; + } + + /* 10.4 upload the last chunk */ + addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE; + p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; + wl12xx_debug(DEBUG_BOOT, "uploading fw last chunk (%d B) 0x%p to 0x%x", + fw_data_len % CHUNK_SIZE, p, addr); + wl12xx_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); + + return 0; +} + +static int wl1251_upload_nvs(struct wl12xx *wl) +{ + size_t nvs_len, nvs_bytes_written, burst_len; + int nvs_start, i; + u32 dest_addr, val; + u8 *nvs_ptr, *nvs; + + nvs = wl->nvs; + if (nvs == NULL) + return -ENODEV; + + nvs_ptr = nvs; + + nvs_len = wl->nvs_len; + nvs_start = wl->fw_len; + + /* + * Layout before the actual NVS tables: + * 1 byte : burst length. + * 2 bytes: destination address. + * n bytes: data to burst copy. + * + * This is ended by a 0 length, then the NVS tables. + */ + + while (nvs_ptr[0]) { + burst_len = nvs_ptr[0]; + dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); + + /* We move our pointer to the data */ + nvs_ptr += 3; + + for (i = 0; i < burst_len; i++) { + val = (nvs_ptr[0] | (nvs_ptr[1] << 8) + | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); + + wl12xx_debug(DEBUG_BOOT, + "nvs burst write 0x%x: 0x%x", + dest_addr, val); + wl12xx_mem_write32(wl, dest_addr, val); + + nvs_ptr += 4; + dest_addr += 4; + } + } + + /* + * We've reached the first zero length, the first NVS table + * is 7 bytes further. + */ + nvs_ptr += 7; + nvs_len -= nvs_ptr - nvs; + nvs_len = ALIGN(nvs_len, 4); + + /* Now we must set the partition correctly */ + wl12xx_set_partition(wl, nvs_start, + wl->chip.p_table[PART_DOWN].mem.size, + wl->chip.p_table[PART_DOWN].reg.start, + wl->chip.p_table[PART_DOWN].reg.size); + + /* And finally we upload the NVS tables */ + nvs_bytes_written = 0; + while (nvs_bytes_written < nvs_len) { + val = (nvs_ptr[0] | (nvs_ptr[1] << 8) + | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); + + val = cpu_to_le32(val); + + wl12xx_debug(DEBUG_BOOT, + "nvs write table 0x%x: 0x%x", + nvs_start, val); + wl12xx_mem_write32(wl, nvs_start, val); + + nvs_ptr += 4; + nvs_bytes_written += 4; + nvs_start += 4; + } + + return 0; +} + +static int wl1251_boot(struct wl12xx *wl) +{ + int ret = 0, minor_minor_e2_ver; + u32 tmp, boot_data; + + ret = wl12xx_boot_soft_reset(wl); + if (ret < 0) + goto out; + + /* 2. start processing NVS file */ + ret = wl->chip.op_upload_nvs(wl); + if (ret < 0) + goto out; + + /* write firmware's last address (ie. it's length) to + * ACX_EEPROMLESS_IND_REG */ + wl12xx_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); + + /* 6. read the EEPROM parameters */ + tmp = wl12xx_reg_read32(wl, SCR_PAD2); + + /* 7. read bootdata */ + wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8; + wl->boot_attr.major = (tmp & 0x00FF0000) >> 16; + tmp = wl12xx_reg_read32(wl, SCR_PAD3); + + /* 8. check bootdata and call restart sequence */ + wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16; + minor_minor_e2_ver = (tmp & 0xFF000000) >> 24; + + wl12xx_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x " + "minorE2Ver 0x%x minor_minor_e2_ver 0x%x", + wl->boot_attr.radio_type, wl->boot_attr.major, + wl->boot_attr.minor, minor_minor_e2_ver); + + ret = wl12xx_boot_init_seq(wl); + if (ret < 0) + goto out; + + /* 9. NVS processing done */ + boot_data = wl12xx_reg_read32(wl, ACX_REG_ECPU_CONTROL); + + wl12xx_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data); + + /* 10. check that ECPU_CONTROL_HALT bits are set in + * pWhalBus->uBootData and start uploading firmware + */ + if ((boot_data & ECPU_CONTROL_HALT) == 0) { + wl12xx_error("boot failed, ECPU_CONTROL_HALT not set"); + ret = -EIO; + goto out; + } + + ret = wl->chip.op_upload_fw(wl); + if (ret < 0) + goto out; + + /* 10.5 start firmware */ + ret = wl12xx_boot_run_firmware(wl); + if (ret < 0) + goto out; + + /* Get and save the firmware version */ + wl12xx_acx_fw_version(wl, wl->chip.fw_ver, sizeof(wl->chip.fw_ver)); + +out: + return ret; +} + +static int wl1251_mem_cfg(struct wl12xx *wl) +{ + struct wl1251_acx_config_memory mem_conf; + int ret, i; + + wl12xx_debug(DEBUG_ACX, "wl1251 mem cfg"); + + /* memory config */ + mem_conf.mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); + mem_conf.mem_config.rx_mem_block_num = 35; + mem_conf.mem_config.tx_min_mem_block_num = 64; + mem_conf.mem_config.num_tx_queues = MAX_TX_QUEUES; + mem_conf.mem_config.host_if_options = HOSTIF_PKT_RING; + mem_conf.mem_config.num_ssid_profiles = 1; + mem_conf.mem_config.debug_buffer_size = + cpu_to_le16(TRACE_BUFFER_MAX_SIZE); + + /* RX queue config */ + mem_conf.rx_queue_config.dma_address = 0; + mem_conf.rx_queue_config.num_descs = ACX_RX_DESC_DEF; + mem_conf.rx_queue_config.priority = DEFAULT_RXQ_PRIORITY; + mem_conf.rx_queue_config.type = DEFAULT_RXQ_TYPE; + + /* TX queue config */ + for (i = 0; i < MAX_TX_QUEUES; i++) { + mem_conf.tx_queue_config[i].num_descs = ACX_TX_DESC_DEF; + mem_conf.tx_queue_config[i].attributes = i; + } + + mem_conf.header.id = ACX_MEM_CFG; + mem_conf.header.len = sizeof(struct wl1251_acx_config_memory) - + sizeof(struct acx_header); + mem_conf.header.len -= + (MAX_TX_QUEUE_CONFIGS - mem_conf.mem_config.num_tx_queues) * + sizeof(struct wl1251_acx_tx_queue_config); + + ret = wl12xx_cmd_configure(wl, &mem_conf, + sizeof(struct wl1251_acx_config_memory)); + if (ret < 0) + wl12xx_warning("wl1251 mem config failed: %d", ret); + + return ret; +} + +static int wl1251_hw_init_mem_config(struct wl12xx *wl) +{ + int ret; + + ret = wl1251_mem_cfg(wl); + if (ret < 0) + return ret; + + wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map), + GFP_KERNEL); + if (!wl->target_mem_map) { + wl12xx_error("couldn't allocate target memory map"); + return -ENOMEM; + } + + /* we now ask for the firmware built memory map */ + ret = wl12xx_acx_mem_map(wl, wl->target_mem_map, + sizeof(struct wl1251_acx_mem_map)); + if (ret < 0) { + wl12xx_error("couldn't retrieve firmware memory map"); + kfree(wl->target_mem_map); + wl->target_mem_map = NULL; + return ret; + } + + return 0; +} + +static void wl1251_set_ecpu_ctrl(struct wl12xx *wl, u32 flag) +{ + u32 cpu_ctrl; + + /* 10.5.0 run the firmware (I) */ + cpu_ctrl = wl12xx_reg_read32(wl, ACX_REG_ECPU_CONTROL); + + /* 10.5.1 run the firmware (II) */ + cpu_ctrl &= ~flag; + wl12xx_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); +} + +static void wl1251_target_enable_interrupts(struct wl12xx *wl) +{ + /* Enable target's interrupts */ + wl->intr_mask = WL1251_ACX_INTR_RX0_DATA | + WL1251_ACX_INTR_RX1_DATA | + WL1251_ACX_INTR_TX_RESULT | + WL1251_ACX_INTR_EVENT_A | + WL1251_ACX_INTR_EVENT_B | + WL1251_ACX_INTR_INIT_COMPLETE; + wl12xx_boot_target_enable_interrupts(wl); +} + +static void wl1251_irq_work(struct work_struct *work) +{ + u32 intr; + struct wl12xx *wl = + container_of(work, struct wl12xx, irq_work); + + mutex_lock(&wl->mutex); + + wl12xx_debug(DEBUG_IRQ, "IRQ work"); + + if (wl->state == WL12XX_STATE_OFF) + goto out; + + wl12xx_ps_elp_wakeup(wl); + + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL); + + intr = wl12xx_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); + wl12xx_debug(DEBUG_IRQ, "intr: 0x%x", intr); + + if (wl->data_path) { + wl12xx_spi_mem_read(wl, wl->data_path->rx_control_addr, + &wl->rx_counter, sizeof(u32)); + + /* We handle a frmware bug here */ + switch ((wl->rx_counter - wl->rx_handled) & 0xf) { + case 0: + wl12xx_debug(DEBUG_IRQ, "RX: FW and host in sync"); + intr &= ~WL1251_ACX_INTR_RX0_DATA; + intr &= ~WL1251_ACX_INTR_RX1_DATA; + break; + case 1: + wl12xx_debug(DEBUG_IRQ, "RX: FW +1"); + intr |= WL1251_ACX_INTR_RX0_DATA; + intr &= ~WL1251_ACX_INTR_RX1_DATA; + break; + case 2: + wl12xx_debug(DEBUG_IRQ, "RX: FW +2"); + intr |= WL1251_ACX_INTR_RX0_DATA; + intr |= WL1251_ACX_INTR_RX1_DATA; + break; + default: + wl12xx_warning("RX: FW and host out of sync: %d", + wl->rx_counter - wl->rx_handled); + break; + } + + wl->rx_handled = wl->rx_counter; + + + wl12xx_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter); + } + + intr &= wl->intr_mask; + + if (intr == 0) { + wl12xx_debug(DEBUG_IRQ, "INTR is 0"); + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, + ~(wl->intr_mask)); + + goto out_sleep; + } + + if (intr & WL1251_ACX_INTR_RX0_DATA) { + wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); + wl12xx_rx(wl); + } + + if (intr & WL1251_ACX_INTR_RX1_DATA) { + wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); + wl12xx_rx(wl); + } + + if (intr & WL1251_ACX_INTR_TX_RESULT) { + wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); + wl12xx_tx_complete(wl); + } + + if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) { + wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr); + if (intr & WL1251_ACX_INTR_EVENT_A) + wl12xx_event_handle(wl, 0); + else + wl12xx_event_handle(wl, 1); + } + + if (intr & WL1251_ACX_INTR_INIT_COMPLETE) + wl12xx_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); + + wl12xx_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); + +out_sleep: + wl12xx_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); +} + +static int wl1251_hw_init_txq_fill(u8 qid, + struct acx_tx_queue_qos_config *config, + u32 num_blocks) +{ + config->qid = qid; + + switch (qid) { + case QOS_AC_BE: + config->high_threshold = + (QOS_TX_HIGH_BE_DEF * num_blocks) / 100; + config->low_threshold = + (QOS_TX_LOW_BE_DEF * num_blocks) / 100; + break; + case QOS_AC_BK: + config->high_threshold = + (QOS_TX_HIGH_BK_DEF * num_blocks) / 100; + config->low_threshold = + (QOS_TX_LOW_BK_DEF * num_blocks) / 100; + break; + case QOS_AC_VI: + config->high_threshold = + (QOS_TX_HIGH_VI_DEF * num_blocks) / 100; + config->low_threshold = + (QOS_TX_LOW_VI_DEF * num_blocks) / 100; + break; + case QOS_AC_VO: + config->high_threshold = + (QOS_TX_HIGH_VO_DEF * num_blocks) / 100; + config->low_threshold = + (QOS_TX_LOW_VO_DEF * num_blocks) / 100; + break; + default: + wl12xx_error("Invalid TX queue id: %d", qid); + return -EINVAL; + } + + return 0; +} + +static int wl1251_hw_init_tx_queue_config(struct wl12xx *wl) +{ + struct acx_tx_queue_qos_config config; + struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; + int ret, i; + + wl12xx_debug(DEBUG_ACX, "acx tx queue config"); + + config.header.id = ACX_TX_QUEUE_CFG; + config.header.len = sizeof(struct acx_tx_queue_qos_config) - + sizeof(struct acx_header); + + for (i = 0; i < MAX_NUM_OF_AC; i++) { + ret = wl1251_hw_init_txq_fill(i, &config, + wl_mem_map->num_tx_mem_blocks); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_configure(wl, &config, sizeof(config)); + if (ret < 0) + return ret; + } + + return 0; +} + +static int wl1251_hw_init_data_path_config(struct wl12xx *wl) +{ + int ret; + + /* asking for the data path parameters */ + wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), + GFP_KERNEL); + if (!wl->data_path) { + wl12xx_error("Couldnt allocate data path parameters"); + return -ENOMEM; + } + + ret = wl12xx_acx_data_path_params(wl, wl->data_path); + if (ret < 0) { + kfree(wl->data_path); + wl->data_path = NULL; + return ret; + } + + return 0; +} + +static int wl1251_hw_init(struct wl12xx *wl) +{ + struct wl1251_acx_mem_map *wl_mem_map; + int ret; + + ret = wl12xx_hw_init_hwenc_config(wl); + if (ret < 0) + return ret; + + /* Template settings */ + ret = wl12xx_hw_init_templates_config(wl); + if (ret < 0) + return ret; + + /* Default memory configuration */ + ret = wl1251_hw_init_mem_config(wl); + if (ret < 0) + return ret; + + /* Default data path configuration */ + ret = wl1251_hw_init_data_path_config(wl); + if (ret < 0) + goto out_free_memmap; + + /* RX config */ + ret = wl12xx_hw_init_rx_config(wl, + RX_CFG_PROMISCUOUS | RX_CFG_TSF, + RX_FILTER_OPTION_DEF); + /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, + RX_FILTER_OPTION_FILTER_ALL); */ + if (ret < 0) + goto out_free_data_path; + + /* TX queues config */ + ret = wl1251_hw_init_tx_queue_config(wl); + if (ret < 0) + goto out_free_data_path; + + /* PHY layer config */ + ret = wl12xx_hw_init_phy_config(wl); + if (ret < 0) + goto out_free_data_path; + + /* Beacon filtering */ + ret = wl12xx_hw_init_beacon_filter(wl); + if (ret < 0) + goto out_free_data_path; + + /* Bluetooth WLAN coexistence */ + ret = wl12xx_hw_init_pta(wl); + if (ret < 0) + goto out_free_data_path; + + /* Energy detection */ + ret = wl12xx_hw_init_energy_detection(wl); + if (ret < 0) + goto out_free_data_path; + + /* Beacons and boradcast settings */ + ret = wl12xx_hw_init_beacon_broadcast(wl); + if (ret < 0) + goto out_free_data_path; + + /* Enable data path */ + ret = wl12xx_cmd_data_path(wl, wl->channel, 1); + if (ret < 0) + goto out_free_data_path; + + /* Default power state */ + ret = wl12xx_hw_init_power_auth(wl); + if (ret < 0) + goto out_free_data_path; + + wl_mem_map = wl->target_mem_map; + wl12xx_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x", + wl_mem_map->num_tx_mem_blocks, + wl->data_path->tx_control_addr, + wl_mem_map->num_rx_mem_blocks, + wl->data_path->rx_control_addr); + + return 0; + + out_free_data_path: + kfree(wl->data_path); + + out_free_memmap: + kfree(wl->target_mem_map); + + return ret; +} + +static int wl1251_plt_init(struct wl12xx *wl) +{ + int ret; + + ret = wl1251_hw_init_mem_config(wl); + if (ret < 0) + return ret; + + ret = wl12xx_cmd_data_path(wl, wl->channel, 1); + if (ret < 0) + return ret; + + return 0; +} + +void wl1251_setup(struct wl12xx *wl) +{ + /* FIXME: Is it better to use strncpy here or is this ok? */ + wl->chip.fw_filename = WL1251_FW_NAME; + wl->chip.nvs_filename = WL1251_NVS_NAME; + + /* Now we know what chip we're using, so adjust the power on sleep + * time accordingly */ + wl->chip.power_on_sleep = WL1251_POWER_ON_SLEEP; + + wl->chip.intr_cmd_complete = WL1251_ACX_INTR_CMD_COMPLETE; + wl->chip.intr_init_complete = WL1251_ACX_INTR_INIT_COMPLETE; + + wl->chip.op_upload_nvs = wl1251_upload_nvs; + wl->chip.op_upload_fw = wl1251_upload_firmware; + wl->chip.op_boot = wl1251_boot; + wl->chip.op_set_ecpu_ctrl = wl1251_set_ecpu_ctrl; + wl->chip.op_target_enable_interrupts = wl1251_target_enable_interrupts; + wl->chip.op_hw_init = wl1251_hw_init; + wl->chip.op_plt_init = wl1251_plt_init; + + wl->chip.p_table = wl1251_part_table; + wl->chip.acx_reg_table = wl1251_acx_reg_table; + + INIT_WORK(&wl->irq_work, wl1251_irq_work); +} diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h new file mode 100644 index 000000000000..1f4a44330394 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -0,0 +1,165 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL1251_H__ +#define __WL1251_H__ + +#include + +#include "wl12xx.h" +#include "acx.h" + +#define WL1251_FW_NAME "wl1251-fw.bin" +#define WL1251_NVS_NAME "wl1251-nvs.bin" + +#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */ + +void wl1251_setup(struct wl12xx *wl); + + +struct wl1251_acx_memory { + __le16 num_stations; /* number of STAs to be supported. */ + u16 reserved_1; + + /* + * Nmber of memory buffers for the RX mem pool. + * The actual number may be less if there are + * not enough blocks left for the minimum num + * of TX ones. + */ + u8 rx_mem_block_num; + u8 reserved_2; + u8 num_tx_queues; /* From 1 to 16 */ + u8 host_if_options; /* HOST_IF* */ + u8 tx_min_mem_block_num; + u8 num_ssid_profiles; + __le16 debug_buffer_size; +} __attribute__ ((packed)); + + +#define ACX_RX_DESC_MIN 1 +#define ACX_RX_DESC_MAX 127 +#define ACX_RX_DESC_DEF 32 +struct wl1251_acx_rx_queue_config { + u8 num_descs; + u8 pad; + u8 type; + u8 priority; + __le32 dma_address; +} __attribute__ ((packed)); + +#define ACX_TX_DESC_MIN 1 +#define ACX_TX_DESC_MAX 127 +#define ACX_TX_DESC_DEF 16 +struct wl1251_acx_tx_queue_config { + u8 num_descs; + u8 pad[2]; + u8 attributes; +} __attribute__ ((packed)); + +#define MAX_TX_QUEUE_CONFIGS 5 +#define MAX_TX_QUEUES 4 +struct wl1251_acx_config_memory { + struct acx_header header; + + struct wl1251_acx_memory mem_config; + struct wl1251_acx_rx_queue_config rx_queue_config; + struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS]; +} __attribute__ ((packed)); + +struct wl1251_acx_mem_map { + struct acx_header header; + + void *code_start; + void *code_end; + + void *wep_defkey_start; + void *wep_defkey_end; + + void *sta_table_start; + void *sta_table_end; + + void *packet_template_start; + void *packet_template_end; + + void *queue_memory_start; + void *queue_memory_end; + + void *packet_memory_pool_start; + void *packet_memory_pool_end; + + void *debug_buffer1_start; + void *debug_buffer1_end; + + void *debug_buffer2_start; + void *debug_buffer2_end; + + /* Number of blocks FW allocated for TX packets */ + u32 num_tx_mem_blocks; + + /* Number of blocks FW allocated for RX packets */ + u32 num_rx_mem_blocks; +} __attribute__ ((packed)); + +/************************************************************************* + + Host Interrupt Register (WiLink -> Host) + +**************************************************************************/ + +/* RX packet is ready in Xfer buffer #0 */ +#define WL1251_ACX_INTR_RX0_DATA BIT(0) + +/* TX result(s) are in the TX complete buffer */ +#define WL1251_ACX_INTR_TX_RESULT BIT(1) + +/* OBSOLETE */ +#define WL1251_ACX_INTR_TX_XFR BIT(2) + +/* RX packet is ready in Xfer buffer #1 */ +#define WL1251_ACX_INTR_RX1_DATA BIT(3) + +/* Event was entered to Event MBOX #A */ +#define WL1251_ACX_INTR_EVENT_A BIT(4) + +/* Event was entered to Event MBOX #B */ +#define WL1251_ACX_INTR_EVENT_B BIT(5) + +/* OBSOLETE */ +#define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6) + +/* Trace meassge on MBOX #A */ +#define WL1251_ACX_INTR_TRACE_A BIT(7) + +/* Trace meassge on MBOX #B */ +#define WL1251_ACX_INTR_TRACE_B BIT(8) + +/* Command processing completion */ +#define WL1251_ACX_INTR_CMD_COMPLETE BIT(9) + +/* Init sequence is done */ +#define WL1251_ACX_INTR_INIT_COMPLETE BIT(14) + +#define WL1251_ACX_INTR_ALL 0xFFFFFFFF + +#endif diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h new file mode 100644 index 000000000000..48641437414b --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -0,0 +1,409 @@ +/* + * This file is part of wl12xx + * + * Copyright (c) 1998-2007 Texas Instruments Incorporated + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_H__ +#define __WL12XX_H__ + +#include +#include +#include +#include + +#define DRIVER_NAME "wl12xx" +#define DRIVER_PREFIX DRIVER_NAME ": " + +enum { + DEBUG_NONE = 0, + DEBUG_IRQ = BIT(0), + DEBUG_SPI = BIT(1), + DEBUG_BOOT = BIT(2), + DEBUG_MAILBOX = BIT(3), + DEBUG_NETLINK = BIT(4), + DEBUG_EVENT = BIT(5), + DEBUG_TX = BIT(6), + DEBUG_RX = BIT(7), + DEBUG_SCAN = BIT(8), + DEBUG_CRYPT = BIT(9), + DEBUG_PSM = BIT(10), + DEBUG_MAC80211 = BIT(11), + DEBUG_CMD = BIT(12), + DEBUG_ACX = BIT(13), + DEBUG_ALL = ~0, +}; + +#define DEBUG_LEVEL (DEBUG_NONE) + +#define DEBUG_DUMP_LIMIT 1024 + +#define wl12xx_error(fmt, arg...) \ + printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) + +#define wl12xx_warning(fmt, arg...) \ + printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) + +#define wl12xx_notice(fmt, arg...) \ + printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) + +#define wl12xx_info(fmt, arg...) \ + printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) + +#define wl12xx_debug(level, fmt, arg...) \ + do { \ + if (level & DEBUG_LEVEL) \ + printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ + } while (0) + +#define wl12xx_dump(level, prefix, buf, len) \ + do { \ + if (level & DEBUG_LEVEL) \ + print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, \ + min_t(size_t, len, DEBUG_DUMP_LIMIT), \ + 0); \ + } while (0) + +#define wl12xx_dump_ascii(level, prefix, buf, len) \ + do { \ + if (level & DEBUG_LEVEL) \ + print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, \ + min_t(size_t, len, DEBUG_DUMP_LIMIT), \ + true); \ + } while (0) + +#define WL12XX_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ + CFG_BSSID_FILTER_EN) + +#define WL12XX_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \ + CFG_RX_MGMT_EN | \ + CFG_RX_DATA_EN | \ + CFG_RX_CTL_EN | \ + CFG_RX_BCN_EN | \ + CFG_RX_AUTH_EN | \ + CFG_RX_ASSOC_EN) + + +struct boot_attr { + u32 radio_type; + u8 mac_clock; + u8 arm_clock; + int firmware_debug; + u32 minor; + u32 major; + u32 bugfix; +}; + +enum wl12xx_state { + WL12XX_STATE_OFF, + WL12XX_STATE_ON, + WL12XX_STATE_PLT, +}; + +enum wl12xx_partition_type { + PART_DOWN, + PART_WORK, + PART_DRPW, + + PART_TABLE_LEN +}; + +struct wl12xx_partition { + u32 size; + u32 start; +}; + +struct wl12xx_partition_set { + struct wl12xx_partition mem; + struct wl12xx_partition reg; +}; + +struct wl12xx; + +/* FIXME: I'm not sure about this structure name */ +struct wl12xx_chip { + u32 id; + + const char *fw_filename; + const char *nvs_filename; + + char fw_ver[21]; + + unsigned int power_on_sleep; + int intr_cmd_complete; + int intr_init_complete; + + int (*op_upload_fw)(struct wl12xx *wl); + int (*op_upload_nvs)(struct wl12xx *wl); + int (*op_boot)(struct wl12xx *wl); + void (*op_set_ecpu_ctrl)(struct wl12xx *wl, u32 flag); + void (*op_target_enable_interrupts)(struct wl12xx *wl); + int (*op_hw_init)(struct wl12xx *wl); + int (*op_plt_init)(struct wl12xx *wl); + + struct wl12xx_partition_set *p_table; + enum wl12xx_acx_int_reg *acx_reg_table; +}; + +struct wl12xx_stats { + struct acx_statistics *fw_stats; + unsigned long fw_stats_update; + + unsigned int retry_count; + unsigned int excessive_retries; +}; + +struct wl12xx_debugfs { + struct dentry *rootdir; + struct dentry *fw_statistics; + + struct dentry *tx_internal_desc_overflow; + + struct dentry *rx_out_of_mem; + struct dentry *rx_hdr_overflow; + struct dentry *rx_hw_stuck; + struct dentry *rx_dropped; + struct dentry *rx_fcs_err; + struct dentry *rx_xfr_hint_trig; + struct dentry *rx_path_reset; + struct dentry *rx_reset_counter; + + struct dentry *dma_rx_requested; + struct dentry *dma_rx_errors; + struct dentry *dma_tx_requested; + struct dentry *dma_tx_errors; + + struct dentry *isr_cmd_cmplt; + struct dentry *isr_fiqs; + struct dentry *isr_rx_headers; + struct dentry *isr_rx_mem_overflow; + struct dentry *isr_rx_rdys; + struct dentry *isr_irqs; + struct dentry *isr_tx_procs; + struct dentry *isr_decrypt_done; + struct dentry *isr_dma0_done; + struct dentry *isr_dma1_done; + struct dentry *isr_tx_exch_complete; + struct dentry *isr_commands; + struct dentry *isr_rx_procs; + struct dentry *isr_hw_pm_mode_changes; + struct dentry *isr_host_acknowledges; + struct dentry *isr_pci_pm; + struct dentry *isr_wakeups; + struct dentry *isr_low_rssi; + + struct dentry *wep_addr_key_count; + struct dentry *wep_default_key_count; + /* skipping wep.reserved */ + struct dentry *wep_key_not_found; + struct dentry *wep_decrypt_fail; + struct dentry *wep_packets; + struct dentry *wep_interrupt; + + struct dentry *pwr_ps_enter; + struct dentry *pwr_elp_enter; + struct dentry *pwr_missing_bcns; + struct dentry *pwr_wake_on_host; + struct dentry *pwr_wake_on_timer_exp; + struct dentry *pwr_tx_with_ps; + struct dentry *pwr_tx_without_ps; + struct dentry *pwr_rcvd_beacons; + struct dentry *pwr_power_save_off; + struct dentry *pwr_enable_ps; + struct dentry *pwr_disable_ps; + struct dentry *pwr_fix_tsf_ps; + /* skipping cont_miss_bcns_spread for now */ + struct dentry *pwr_rcvd_awake_beacons; + + struct dentry *mic_rx_pkts; + struct dentry *mic_calc_failure; + + struct dentry *aes_encrypt_fail; + struct dentry *aes_decrypt_fail; + struct dentry *aes_encrypt_packets; + struct dentry *aes_decrypt_packets; + struct dentry *aes_encrypt_interrupt; + struct dentry *aes_decrypt_interrupt; + + struct dentry *event_heart_beat; + struct dentry *event_calibration; + struct dentry *event_rx_mismatch; + struct dentry *event_rx_mem_empty; + struct dentry *event_rx_pool; + struct dentry *event_oom_late; + struct dentry *event_phy_transmit_error; + struct dentry *event_tx_stuck; + + struct dentry *ps_pspoll_timeouts; + struct dentry *ps_upsd_timeouts; + struct dentry *ps_upsd_max_sptime; + struct dentry *ps_upsd_max_apturn; + struct dentry *ps_pspoll_max_apturn; + struct dentry *ps_pspoll_utilization; + struct dentry *ps_upsd_utilization; + + struct dentry *rxpipe_rx_prep_beacon_drop; + struct dentry *rxpipe_descr_host_int_trig_rx_data; + struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data; + struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data; + struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; + + struct dentry *tx_queue_len; + + struct dentry *retry_count; + struct dentry *excessive_retries; +}; + +struct wl12xx { + struct ieee80211_hw *hw; + bool mac80211_registered; + + struct spi_device *spi; + + void (*set_power)(bool enable); + int irq; + + enum wl12xx_state state; + struct mutex mutex; + + int physical_mem_addr; + int physical_reg_addr; + int virtual_mem_addr; + int virtual_reg_addr; + + struct wl12xx_chip chip; + + int cmd_box_addr; + int event_box_addr; + struct boot_attr boot_attr; + + u8 *fw; + size_t fw_len; + u8 *nvs; + size_t nvs_len; + + u8 bssid[ETH_ALEN]; + u8 mac_addr[ETH_ALEN]; + u8 bss_type; + u8 listen_int; + int channel; + + void *target_mem_map; + struct acx_data_path_params_resp *data_path; + + /* Number of TX packets transferred to the FW, modulo 16 */ + u32 data_in_count; + + /* Frames scheduled for transmission, not handled yet */ + struct sk_buff_head tx_queue; + bool tx_queue_stopped; + + struct work_struct tx_work; + struct work_struct filter_work; + + /* Pending TX frames */ + struct sk_buff *tx_frames[16]; + + /* + * Index pointing to the next TX complete entry + * in the cyclic XT complete array we get from + * the FW. + */ + u32 next_tx_complete; + + /* FW Rx counter */ + u32 rx_counter; + + /* Rx frames handled */ + u32 rx_handled; + + /* Current double buffer */ + u32 rx_current_buffer; + u32 rx_last_id; + + /* The target interrupt mask */ + u32 intr_mask; + struct work_struct irq_work; + + /* The mbox event mask */ + u32 event_mask; + + /* Mailbox pointers */ + u32 mbox_ptr[2]; + + /* Are we currently scanning */ + bool scanning; + + /* Our association ID */ + u16 aid; + + /* Default key (for WEP) */ + u32 default_key; + + unsigned int tx_mgmt_frm_rate; + unsigned int tx_mgmt_frm_mod; + + unsigned int rx_config; + unsigned int rx_filter; + + /* is firmware in elp mode */ + bool elp; + + /* we can be in psm, but not in elp, we have to differentiate */ + bool psm; + + /* PSM mode requested */ + bool psm_requested; + + /* in dBm */ + int power_level; + + struct wl12xx_stats stats; + struct wl12xx_debugfs debugfs; +}; + +int wl12xx_plt_start(struct wl12xx *wl); +int wl12xx_plt_stop(struct wl12xx *wl); + +#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */ +#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS +#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ + +#define WL12XX_DEFAULT_POWER_LEVEL 20 + +#define WL12XX_TX_QUEUE_MAX_LENGTH 20 + +/* Different chips need different sleep times after power on. WL1271 needs + * 200ms, WL1251 needs only 10ms. By default we use 200ms, but as soon as we + * know the chip ID, we change the sleep value in the wl12xx chip structure, + * so in subsequent power ons, we don't waste more time then needed. */ +#define WL12XX_DEFAULT_POWER_ON_SLEEP 200 + +#define CHIP_ID_1251_PG10 (0x7010101) +#define CHIP_ID_1251_PG11 (0x7020101) +#define CHIP_ID_1251_PG12 (0x7030101) +#define CHIP_ID_1271_PG10 (0x4030101) + +#endif diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h new file mode 100644 index 000000000000..657c2dbcb7d3 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -0,0 +1,156 @@ +#ifndef __WL12XX_80211_H__ +#define __WL12XX_80211_H__ + +#include /* ETH_ALEN */ + +/* RATES */ +#define IEEE80211_CCK_RATE_1MB 0x02 +#define IEEE80211_CCK_RATE_2MB 0x04 +#define IEEE80211_CCK_RATE_5MB 0x0B +#define IEEE80211_CCK_RATE_11MB 0x16 +#define IEEE80211_OFDM_RATE_6MB 0x0C +#define IEEE80211_OFDM_RATE_9MB 0x12 +#define IEEE80211_OFDM_RATE_12MB 0x18 +#define IEEE80211_OFDM_RATE_18MB 0x24 +#define IEEE80211_OFDM_RATE_24MB 0x30 +#define IEEE80211_OFDM_RATE_36MB 0x48 +#define IEEE80211_OFDM_RATE_48MB 0x60 +#define IEEE80211_OFDM_RATE_54MB 0x6C +#define IEEE80211_BASIC_RATE_MASK 0x80 + +#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) +#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) +#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) +#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) +#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) +#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) +#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) +#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) +#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) +#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) +#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) +#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) + +#define IEEE80211_CCK_RATES_MASK 0x0000000F +#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ + IEEE80211_CCK_RATE_2MB_MASK) +#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ + IEEE80211_CCK_RATE_5MB_MASK | \ + IEEE80211_CCK_RATE_11MB_MASK) + +#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 +#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ + IEEE80211_OFDM_RATE_12MB_MASK | \ + IEEE80211_OFDM_RATE_24MB_MASK) +#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ + IEEE80211_OFDM_RATE_9MB_MASK | \ + IEEE80211_OFDM_RATE_18MB_MASK | \ + IEEE80211_OFDM_RATE_36MB_MASK | \ + IEEE80211_OFDM_RATE_48MB_MASK | \ + IEEE80211_OFDM_RATE_54MB_MASK) +#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ + IEEE80211_CCK_DEFAULT_RATES_MASK) + + +/* This really should be 8, but not for our firmware */ +#define MAX_SUPPORTED_RATES 32 +#define COUNTRY_STRING_LEN 3 +#define MAX_COUNTRY_TRIPLETS 32 + +/* Headers */ +struct ieee80211_header { + __le16 frame_ctl; + __le16 duration_id; + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct wl12xx_ie_header { + u8 id; + u8 len; +} __attribute__ ((packed)); + +/* IEs */ + +struct wl12xx_ie_ssid { + struct wl12xx_ie_header header; + char ssid[IW_ESSID_MAX_SIZE]; +} __attribute__ ((packed)); + +struct wl12xx_ie_rates { + struct wl12xx_ie_header header; + u8 rates[MAX_SUPPORTED_RATES]; +} __attribute__ ((packed)); + +struct wl12xx_ie_ds_params { + struct wl12xx_ie_header header; + u8 channel; +} __attribute__ ((packed)); + +struct country_triplet { + u8 channel; + u8 num_channels; + u8 max_tx_power; +} __attribute__ ((packed)); + +struct wl12xx_ie_country { + struct wl12xx_ie_header header; + u8 country_string[COUNTRY_STRING_LEN]; + struct country_triplet triplets[MAX_COUNTRY_TRIPLETS]; +} __attribute__ ((packed)); + + +/* Templates */ + +struct wl12xx_beacon_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __attribute__ ((packed)); + +struct wl12xx_null_data_template { + struct ieee80211_header header; +} __attribute__ ((packed)); + +struct wl12xx_ps_poll_template { + u16 fc; + u16 aid; + u8 bssid[ETH_ALEN]; + u8 ta[ETH_ALEN]; +} __attribute__ ((packed)); + +struct wl12xx_qos_null_data_template { + struct ieee80211_header header; + __le16 qos_ctl; +} __attribute__ ((packed)); + +struct wl12xx_probe_req_template { + struct ieee80211_header header; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; +} __attribute__ ((packed)); + + +struct wl12xx_probe_resp_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __attribute__ ((packed)); + +#endif diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h new file mode 100644 index 000000000000..11430cab2aad --- /dev/null +++ b/include/linux/spi/wl12xx.h @@ -0,0 +1,31 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef _LINUX_SPI_WL12XX_H +#define _LINUX_SPI_WL12XX_H + +struct wl12xx_platform_data { + void (*set_power)(bool enable); +}; + +#endif -- cgit v1.2.3 From e430d6074dede3b4d7d87e30296fe3894cb4709c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 27 Apr 2009 23:58:31 +0200 Subject: rt2x00: Add new USB ID for rt2800usb Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 812912e508cd..93ebf2458762 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -2942,6 +2942,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Linksys */ { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Logitec */ { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, -- cgit v1.2.3 From 15e469284d5e89c9113379b68566b0e059a97704 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 28 Apr 2009 20:14:58 +0200 Subject: rt2x00: Synchronize initialization with rt2870 driver Ralink released a new rt2870 driver, these are the obvious differences I could find. It doesn't same to make my device work better, but neither does it seem to regress... Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 47 ++++++++++++++++++++++++--------- drivers/net/wireless/rt2x00/rt2800usb.h | 11 ++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 93ebf2458762..cf4a97f32ab3 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -984,9 +984,9 @@ static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); - rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); } else { - rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); @@ -1171,7 +1171,9 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, /* * Check which section of the firmware we need. */ - if ((chipset == 0x2860) || (chipset == 0x2872) || (chipset == 0x3070)) { + if ((chipset == 0x2860) || + (chipset == 0x2872) || + (chipset == 0x3070)) { offset = 0; length = 4096; } else { @@ -1218,6 +1220,22 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, return status; } + msleep(10); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + + /* + * Send signal to firmware during boot time. + */ + rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + + if ((chipset == 0x3070) || + (chipset == 0x3071) || + (chipset == 0x3572)) { + udelay(200); + rt2800usb_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); + udelay(10); + } + /* * Wait for device to stabilize. */ @@ -1566,6 +1584,14 @@ static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) unsigned int i; u8 value; + /* + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ + rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800usb_bbp_read(rt2x00dev, 0, &value); if ((value != 0xff) && (value != 0x00)) @@ -1823,8 +1849,12 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, (rt2x00dev->rx->usb_maxpacket == 512)); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); - /* FIXME: Calculate this value based on Aggregation defines */ - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, 21); + /* + * Total room for RX frames in kilobytes, PBF might still exceed + * this limit so reduce the number to prevent errors. + */ + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, + ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); @@ -1834,11 +1864,6 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - /* - * Send signal to firmware during boot time. - */ - rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); - /* * Initialize LED control */ @@ -1879,8 +1904,6 @@ static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { - rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); - if (state == STATE_AWAKE) rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); else diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 8e4291d280b3..61a8be61d3f5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -1375,6 +1375,10 @@ struct mac_iveiv_entry { * H2M_MAILBOX_CID: */ #define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) +#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) +#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) +#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) /* * H2M_MAILBOX_STATUS: @@ -1715,6 +1719,7 @@ struct mac_iveiv_entry { #define MCU_SLEEP 0x30 #define MCU_WAKEUP 0x31 #define MCU_RADIO_OFF 0x35 +#define MCU_CURRENT 0x36 #define MCU_LED 0x50 #define MCU_LED_STRENGTH 0x51 #define MCU_LED_1 0x52 @@ -1723,6 +1728,12 @@ struct mac_iveiv_entry { #define MCU_RADAR 0x60 #define MCU_BOOT_SIGNAL 0x72 #define MCU_BBP_SIGNAL 0x80 +#define MCU_POWER_SAVE 0x83 + +/* + * MCU mailbox tokens + */ +#define TOKEN_WAKUP 3 /* * DMA descriptor defines. -- cgit v1.2.3 From a082381044ce026e83dbd17f8837722b028fc07d Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 30 Apr 2009 15:55:44 -0400 Subject: ath5k: Allow user/driver to set txpower * Now that we have regulatory control enable the driver to set txpower on hw * Also use txpower table offset so that we can match power range set by user/driver with indices on power table. Tested 2 different cards (a CM9 and an RF5112-based ubnt) and got the same output using a remote machine to measure per-packet rssi (conected the cards using attenuators). I also switched between various tx power levels and i saw an equal power change on the remote machine (so txpower changes as expected) and verified that we have the same output on each rate. Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 7 +++--- drivers/net/wireless/ath/ath5k/base.c | 11 ++++++++- drivers/net/wireless/ath/ath5k/phy.c | 45 ++++++++++++++++++++++++++++------ drivers/net/wireless/ath/ath5k/reset.c | 2 +- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 60c6d2edc4b9..04b73453f6a5 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1100,11 +1100,12 @@ struct ath5k_hw { /* Values in 0.25dB units */ s16 txp_min_pwr; s16 txp_max_pwr; + /* Values in 0.5dB units */ s16 txp_offset; s16 txp_ofdm; - /* Values in dB units */ - s16 txp_cck_ofdm_pwr_delta; s16 txp_cck_ofdm_gainf_delta; + /* Value in dB units */ + s16 txp_cck_ofdm_pwr_delta; } ah_txpower; struct { @@ -1271,7 +1272,7 @@ extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); /* TX power setup */ extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); -extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); +extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); /* * Functions used internaly diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7b80cebffd41..d70856a9520e 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2747,12 +2747,21 @@ static int ath5k_config(struct ieee80211_hw *hw, u32 changed) { struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; struct ieee80211_conf *conf = &hw->conf; int ret; mutex_lock(&sc->lock); - sc->power_level = conf->power_level; + sc->bintval = conf->beacon_int; + + if ((changed & IEEE80211_CONF_CHANGE_POWER) && + (sc->power_level != conf->power_level)) { + sc->power_level = conf->power_level; + + /* Half dB steps */ + ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); + } ret = ath5k_chan_set(sc, conf->channel); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index b48b29dca3d2..bb61b8e2dce9 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -168,9 +168,6 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) * tx power and a Peak to Average Power Detector (PAPD) will try * to measure the gain. * - * TODO: Use propper tx power setting for the probe packet so - * that we don't observe a serious power drop on the receiver - * * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) * just after we enable the probe so that we don't mess with * standard traffic ? Maybe it's time to use sw interrupts and @@ -186,7 +183,7 @@ static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) /* Send the packet with 2dB below max power as * patent doc suggest */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, + ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4, AR5K_PHY_PAPD_PROBE_TXPOWER) | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); @@ -2482,8 +2479,19 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, for (i = 8; i <= 15; i++) rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; - ah->ah_txpower.txp_min_pwr = rates[7]; - ah->ah_txpower.txp_max_pwr = rates[0]; + /* Now that we have all rates setup use table offset to + * match the power range set by user with the power indices + * on PCDAC/PDADC table */ + for (i = 0; i < 16; i++) { + rates[i] += ah->ah_txpower.txp_offset; + /* Don't get out of bounds */ + if (rates[i] > 63) + rates[i] = 63; + } + + /* Min/max in 0.25dB units */ + ah->ah_txpower.txp_min_pwr = 2 * rates[7]; + ah->ah_txpower.txp_max_pwr = 2 * rates[0]; ah->ah_txpower.txp_ofdm = rates[7]; } @@ -2591,16 +2599,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return 0; } -int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) +int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) { /*Just a try M.F.*/ struct ieee80211_channel *channel = &ah->ah_current_channel; + u8 ee_mode; ATH5K_TRACE(ah->ah_sc); + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + case CHANNEL_T: + case CHANNEL_XR: + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + case CHANNEL_TG: + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_B: + ee_mode = AR5K_EEPROM_MODE_11B; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return -EINVAL; + } + ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, "changing txpower to %d\n", txpower); - return ath5k_hw_txpower(ah, channel, mode, txpower); + return ath5k_hw_txpower(ah, channel, ee_mode, txpower); } #undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 775fdf78554b..cb8a9a1398c9 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1000,7 +1000,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * Set TX power (FIXME) */ ret = ath5k_hw_txpower(ah, channel, ee_mode, - AR5K_TUNE_DEFAULT_TXPOWER); + ah->ah_txpower.txp_max_pwr / 2); if (ret) return ret; -- cgit v1.2.3 From cd417519086b223562b50c364d7beab12ef4c62c Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 30 Apr 2009 15:55:45 -0400 Subject: ath5k: Read Spur channels from EEPROM * Read Spur channel information from EEPROM and use default channels for RF5413 compatible chips that don't have this info on EEPROM. Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 37 ++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath5k/eeprom.h | 20 ++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index c85429d2de3f..587c5b8ddc2c 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -1694,9 +1694,40 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) return 0; } +static int +ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 offset; + u16 val; + int ret = 0, i; + + offset = AR5K_EEPROM_CTL(ee->ee_version) + + AR5K_EEPROM_N_CTLS(ee->ee_version); + + if (ee->ee_version < AR5K_EEPROM_VERSION_5_3) { + /* No spur info for 5GHz */ + ee->ee_spur_chans[0][0] = AR5K_EEPROM_NO_SPUR; + /* 2 channels for 2GHz (2464/2420) */ + ee->ee_spur_chans[0][1] = AR5K_EEPROM_5413_SPUR_CHAN_1; + ee->ee_spur_chans[1][1] = AR5K_EEPROM_5413_SPUR_CHAN_2; + ee->ee_spur_chans[2][1] = AR5K_EEPROM_NO_SPUR; + } else if (ee->ee_version >= AR5K_EEPROM_VERSION_5_3) { + for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { + AR5K_EEPROM_READ(offset, val); + ee->ee_spur_chans[i][0] = val; + AR5K_EEPROM_READ(offset + AR5K_EEPROM_N_SPUR_CHANS, + val); + ee->ee_spur_chans[i][1] = val; + offset++; + } + } + + return ret; +} /* - * Initialize eeprom power tables + * Initialize eeprom data structure */ int ath5k_eeprom_init(struct ath5k_hw *ah) @@ -1719,6 +1750,10 @@ ath5k_eeprom_init(struct ath5k_hw *ah) if (err < 0) return err; + err = ath5k_eeprom_read_spur_chans(ah); + if (err < 0) + return err; + return 0; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index b0c0606dea0b..df9ffa044ea6 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -211,6 +211,23 @@ #define AR5K_EEPROM_I_GAIN 10 #define AR5K_EEPROM_CCK_OFDM_DELTA 15 #define AR5K_EEPROM_N_IQ_CAL 2 +/* 5GHz/2GHz */ +enum ath5k_eeprom_freq_bands{ + AR5K_EEPROM_BAND_5GHZ = 0, + AR5K_EEPROM_BAND_2GHZ = 1, + AR5K_EEPROM_N_FREQ_BANDS, +}; +/* Spur chans per freq band */ +#define AR5K_EEPROM_N_SPUR_CHANS 5 +/* fbin value for chan 2464 x2 */ +#define AR5K_EEPROM_5413_SPUR_CHAN_1 1640 +/* fbin value for chan 2420 x2 */ +#define AR5K_EEPROM_5413_SPUR_CHAN_2 1200 +#define AR5K_EEPROM_SPUR_CHAN_MASK 0x3FFF +#define AR5K_EEPROM_NO_SPUR 0x8000 +#define AR5K_SPUR_CHAN_WIDTH 87 +#define AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz 3125 +#define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 #define AR5K_EEPROM_READ(_o, _v) do { \ ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ @@ -436,6 +453,9 @@ struct ath5k_eeprom_info { s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES]; s8 ee_pd_gain_overlap; + /* Spur mitigation data (fbin values for spur channels) */ + u16 ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS]; + u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; }; -- cgit v1.2.3 From 1889ba0a48688b639c2b2e9e1b0fd8f84e2c37d1 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 30 Apr 2009 15:55:46 -0400 Subject: ath5k: Put remaining EEPROM data on ee struct * Put remaining EEPROM information on ee struct and remove is_hb63 function. Now we also have rfkill stuff available. Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/eeprom.c | 24 +++++++++++------------- drivers/net/wireless/ath/ath5k/eeprom.h | 15 ++++++++++----- drivers/net/wireless/ath/ath5k/reset.c | 5 +++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 587c5b8ddc2c..8c9dd019d761 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -156,6 +156,17 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; } + AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val); + + if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val) + ee->ee_is_hb63 = true; + else + ee->ee_is_hb63 = false; + + AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val); + ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL); + ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false; + return 0; } @@ -1789,16 +1800,3 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) return 0; } - -bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah) -{ - u16 data; - - ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data); - - if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data) - return true; - else - return false; -} - diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index df9ffa044ea6..46e4d22591f6 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -26,6 +26,13 @@ #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ + +#define AR5K_EEPROM_RFKILL 0x0f +#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c +#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 +#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 +#define AR5K_EEPROM_RFKILL_POLARITY_S 1 + #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ @@ -66,11 +73,6 @@ #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ -#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c -#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 -#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 -#define AR5K_EEPROM_RFKILL_POLARITY_S 1 - /* Newer EEPROMs are using a different offset */ #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) @@ -386,6 +388,9 @@ struct ath5k_eeprom_info { u16 ee_version; u16 ee_header; u16 ee_ant_gain; + u8 ee_rfkill_pin; + bool ee_rfkill_pol; + bool ee_is_hb63; u16 ee_misc0; u16 ee_misc1; u16 ee_misc2; diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index cb8a9a1398c9..d419c6a3ded7 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -507,7 +507,7 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ath5k_eeprom_is_hb63(ah)) + else if (ee->ee_is_hb63) scal = AR5K_PHY_SCAL_32MHZ_HB63; else scal = AR5K_PHY_SCAL_32MHZ; @@ -598,9 +598,10 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, /* Set DAC/ADC delays */ if (ah->ah_version == AR5K_AR5212) { u32 scal; + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ath5k_eeprom_is_hb63(ah)) + else if (ee->ee_is_hb63) scal = AR5K_PHY_SCAL_32MHZ_HB63; else scal = AR5K_PHY_SCAL_32MHZ; -- cgit v1.2.3 From 428cbd4ff4d0f2423f49e499f499f04a636cb152 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 30 Apr 2009 15:55:47 -0400 Subject: ath5k: Beaconing fixes * Write next beacon timer even on AP mode since without this we get no beacons + ath9k does it too. Docs say that we must write 0 on this register on AP mode to start TSF increment, we do both to be on the safe side. * Fix num_tx_pending function, we never read the register :P that's why we got all those "beacon queue 7 didn't stop messages". * Put full prioriy on beacon queue, lock all queues with lower priority using the arblock and also bypass any arblock by seting the arblock ignore flag. * For the CAB queue (do we need this thing ?, it seems crap) since it's supposed to fire up after each beacon (we don't use it on driver part, ath9k/MadWiFi does), don't make it DBA gated but instead make it fire after each beacon by using the beacon sent gated flag. * Increase bmiss threshold to 10, that's what we used on MadWiFi for a long time. Also when we have pending frames on the beacon queue (we got a beacon that didn't make it on the air) it's more likely that the beacon queue never started, probably due to faulty DBA setting, so change that "beacon queue didn't stop" message. Tested this with AP mode and IBSS mode and seems to work fine ;-) Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 64 ++++++++++++++++++----------------- drivers/net/wireless/ath/ath5k/pcu.c | 4 +-- drivers/net/wireless/ath/ath5k/qcu.c | 7 ++-- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index d70856a9520e..b48ff7ded325 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1738,35 +1738,6 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, } } -static void ath5k_tasklet_beacon(unsigned long data) -{ - struct ath5k_softc *sc = (struct ath5k_softc *) data; - - /* - * Software beacon alert--time to send a beacon. - * - * In IBSS mode we use this interrupt just to - * keep track of the next TBTT (target beacon - * transmission time) in order to detect wether - * automatic TSF updates happened. - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* XXX: only if VEOL suppported */ - u64 tsf = ath5k_hw_get_tsf64(sc->ah); - sc->nexttbtt += sc->bintval; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "SWBA nexttbtt: %x hw_tu: %x " - "TSF: %llx\n", - sc->nexttbtt, - TSF_TO_TU(tsf), - (unsigned long long) tsf); - } else { - spin_lock(&sc->block); - ath5k_beacon_send(sc); - spin_unlock(&sc->block); - } -} - static void ath5k_tasklet_rx(unsigned long data) { @@ -2120,7 +2091,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) sc->bmisscount++; ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "missed %u consecutive beacons\n", sc->bmisscount); - if (sc->bmisscount > 3) { /* NB: 3 is a guess */ + if (sc->bmisscount > 10) { /* NB: 10 is a guess */ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "stuck beacon time (%u missed)\n", sc->bmisscount); @@ -2141,10 +2112,12 @@ ath5k_beacon_send(struct ath5k_softc *sc) * are still pending on the queue. */ if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { - ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); + ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } + /* Note: Beacon buffer is updated on beacon_update when mac80211 + * calls config_interface */ ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); ath5k_hw_start_tx_dma(ah, sc->bhalq); ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", @@ -2301,6 +2274,35 @@ ath5k_beacon_config(struct ath5k_softc *sc) ath5k_hw_set_imr(ah, sc->imask); } +static void ath5k_tasklet_beacon(unsigned long data) +{ + struct ath5k_softc *sc = (struct ath5k_softc *) data; + + /* + * Software beacon alert--time to send a beacon. + * + * In IBSS mode we use this interrupt just to + * keep track of the next TBTT (target beacon + * transmission time) in order to detect wether + * automatic TSF updates happened. + */ + if (sc->opmode == NL80211_IFTYPE_ADHOC) { + /* XXX: only if VEOL suppported */ + u64 tsf = ath5k_hw_get_tsf64(sc->ah); + sc->nexttbtt += sc->bintval; + ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, + "SWBA nexttbtt: %x hw_tu: %x " + "TSF: %llx\n", + sc->nexttbtt, + TSF_TO_TU(tsf), + (unsigned long long) tsf); + } else { + spin_lock(&sc->block); + ath5k_beacon_send(sc); + spin_unlock(&sc->block); + } +} + /********************\ * Interrupt handling * diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 5f07e876d4bd..579aa0a96ab8 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -736,8 +736,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) /* When in AP mode zero timer0 to start TSF */ if (ah->ah_op_mode == NL80211_IFTYPE_AP) ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - else - ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); + + ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 5094c394a4b2..73407b3f53ef 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -160,7 +160,8 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) if (ah->ah_version == AR5K_AR5210) return false; - pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); + pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); + pending &= AR5K_QCU_STS_FRMPENDCNT; /* It's possible to have no frames pending even if TXE * is set. To indicate that q has not stopped return @@ -401,14 +402,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << AR5K_DCU_MISC_ARBLOCK_CTL_S) | + AR5K_DCU_MISC_ARBLOCK_IGNORE | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | AR5K_DCU_MISC_BCN_ENABLE); break; case AR5K_TX_QUEUE_CAB: AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | + AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | AR5K_QCU_MISC_CBREXP_DIS | + AR5K_QCU_MISC_RDY_VEOL_POLICY | AR5K_QCU_MISC_CBREXP_BCN_DIS); ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - -- cgit v1.2.3 From 6f5f39c95af519c24c0187950147eb79d07d1940 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 30 Apr 2009 15:55:48 -0400 Subject: ath5k: Enable AP mode After some debuging we were hitting the following bugs so far... * Due to huge channel list hostapd couldn't get infos from the driver and couldn't set the channel. If we manualy set the channel after hostapd starts (by setting channel to 0 -auto), beacons are sent but they wont show up on scan because they are malformed (they have channel = 0 because hostapd doesn't update the channel info -this is probably a hostapd bug so i'm CCing Jouni) and they get dropped. Bob fixed this by only allowing standard channels to be registered so now hostapd works as expected. * Docs (and HAL source) say that we must write 0 on timer0 when operating on AP mode to start TSF increment but this seems to mess with DBA in many cases and beacon queue never gets started. We fixed that on the previous patch. We have some more things to deal with... * For some reason (hw bug or something else) after restarting hostapd a few times, beacon inteval seems to change from 100ms to a sec (we get one beacon per sec). * We need to set sleep timers on STA mode and enable power saving + support PCF. ...but i think it's time we enable AP support "officialy" so that we can get more feedback from users. I ran ath5k with the mentioned patches + hostapd 0.6.8 and AP mode worked fine (it had some less throughput on my tests than IBSS but it worked). Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b48ff7ded325..912ffc5c0203 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -516,6 +516,7 @@ ath5k_pci_probe(struct pci_dev *pdev, IEEE80211_HW_NOISE_DBM; hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); -- cgit v1.2.3 From 2bed03ebf62f9d013a455209bf30d7e086120443 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 30 Apr 2009 15:55:49 -0400 Subject: ath5k: Implement antenna control * Add code to support the various antenna scenarios supported by hw * For now hardcode the default scenario (single or dual omnis with tx/rx diversity working and tx antenna handled by session -hw keeps track on which antenna it got ack from each ap/station and maps each ap/station to one of the antennas-). Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 25 ++++- drivers/net/wireless/ath/ath5k/attach.c | 1 - drivers/net/wireless/ath/ath5k/base.c | 66 +++++++++--- drivers/net/wireless/ath/ath5k/eeprom.c | 8 +- drivers/net/wireless/ath/ath5k/eeprom.h | 11 +- drivers/net/wireless/ath/ath5k/phy.c | 174 +++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath5k/reg.h | 9 +- drivers/net/wireless/ath/ath5k/reset.c | 28 ++--- 8 files changed, 271 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 04b73453f6a5..33da290e4bb5 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -209,7 +209,6 @@ #define AR5K_TUNE_MAX_TXPOWER 63 #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false -#define AR5K_TUNE_ANT_DIVERSITY true #define AR5K_TUNE_HWTXTRIES 4 #define AR5K_INIT_CARR_SENSE_EN 1 @@ -420,6 +419,17 @@ enum ath5k_driver_mode { AR5K_MODE_MAX = 5 }; +enum ath5k_ant_mode { + AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ + AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ + AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ + AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ + AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ + AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ + AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ + AR5K_ANTMODE_MAX, +}; + /****************\ TX DEFINITIONS @@ -1051,8 +1061,11 @@ struct ath5k_hw { bool ah_software_retry; u32 ah_limit_tx_retries; - u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; - bool ah_ant_diversity; + /* Antenna Control */ + u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; + u8 ah_ant_mode; + u8 ah_tx_ant; + u8 ah_def_ant; u8 ah_sta_id[ETH_ALEN]; @@ -1267,9 +1280,11 @@ extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); /* Misc PHY functions */ extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant); -extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); +/* Antenna control */ +extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); +extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); +extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); /* TX power setup */ extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 70d376c63aac..c41ef58393e7 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -133,7 +133,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_cw_min = AR5K_TUNE_CWMIN; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_software_retry = false; - ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; /* * Set the mac version based on the pci id diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 912ffc5c0203..6789c5dfcc76 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1279,7 +1279,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, (sc->power_level * 2), hw_rate, - info->control.rates[0].count, keyidx, 0, flags, + info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, cts_rate, duration); if (ret) goto err_unmap; @@ -2009,7 +2009,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath5k_hw *ah = sc->ah; struct ath5k_desc *ds; - int ret, antenna = 0; + int ret = 0; + u8 antenna; u32 flags; bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, @@ -2023,23 +2024,35 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) } ds = bf->desc; + antenna = ah->ah_tx_ant; flags = AR5K_TXDESC_NOACK; if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { ds->ds_link = bf->daddr; /* self-linked */ flags |= AR5K_TXDESC_VEOL; - /* - * Let hardware handle antenna switching if txantenna is not set - */ - } else { + } else ds->ds_link = 0; - /* - * Switch antenna every 4 beacons if txantenna is not set - * XXX assumes two antennas - */ - if (antenna == 0) - antenna = sc->bsent & 4 ? 2 : 1; - } + + /* + * If we use multiple antennas on AP and use + * the Sectored AP scenario, switch antenna every + * 4 beacons to make sure everybody hears our AP. + * When a client tries to associate, hw will keep + * track of the tx antenna to be used for this client + * automaticaly, based on ACKed packets. + * + * Note: AP still listens and transmits RTS on the + * default antenna which is supposed to be an omni. + * + * Note2: On sectored scenarios it's possible to have + * multiple antennas (1omni -the default- and 14 sectors) + * so if we choose to actually support this mode we need + * to allow user to set how many antennas we have and tweak + * the code below to send beacons on all of them. + */ + if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) + antenna = sc->bsent & 4 ? 2 : 1; + /* FIXME: If we are in g mode and rate is a CCK rate * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta @@ -2752,12 +2765,16 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; struct ieee80211_conf *conf = &hw->conf; - int ret; + int ret = 0; mutex_lock(&sc->lock); sc->bintval = conf->beacon_int; + ret = ath5k_chan_set(sc, conf->channel); + if (ret < 0) + return ret; + if ((changed & IEEE80211_CONF_CHANGE_POWER) && (sc->power_level != conf->power_level)) { sc->power_level = conf->power_level; @@ -2766,10 +2783,27 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); } - ret = ath5k_chan_set(sc, conf->channel); + /* TODO: + * 1) Move this on config_interface and handle each case + * separately eg. when we have only one STA vif, use + * AR5K_ANTMODE_SINGLE_AP + * + * 2) Allow the user to change antenna mode eg. when only + * one antenna is present + * + * 3) Allow the user to set default/tx antenna when possible + * + * 4) Default mode should handle 90% of the cases, together + * with fixed a/b and single AP modes we should be able to + * handle 99%. Sectored modes are extreme cases and i still + * haven't found a usage for them. If we decide to support them, + * then we must allow the user to set how many tx antennas we + * have available + */ + ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); mutex_unlock(&sc->lock); - return ret; + return 0; } #define SUPPORTED_FIF_FLAGS \ diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 8c9dd019d761..c56b494d417a 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -208,16 +208,16 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; ee->ee_ant_control[mode][i++] = val & 0x3f; - /* Get antenna modes */ - ah->ah_antenna[mode][0] = + /* Get antenna switch tables */ + ah->ah_ant_ctl[mode][AR5K_ANT_CTL] = (ee->ee_ant_control[mode][0] << 4); - ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = + ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] = ee->ee_ant_control[mode][1] | (ee->ee_ant_control[mode][2] << 6) | (ee->ee_ant_control[mode][3] << 12) | (ee->ee_ant_control[mode][4] << 18) | (ee->ee_ant_control[mode][5] << 24); - ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = + ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] = ee->ee_ant_control[mode][6] | (ee->ee_ant_control[mode][7] << 6) | (ee->ee_ant_control[mode][8] << 12) | diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 46e4d22591f6..64be73a5edae 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -240,11 +240,11 @@ enum ath5k_eeprom_freq_bands{ #define AR5K_EEPROM_READ_HDR(_o, _v) \ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ -enum ath5k_ant_setting { - AR5K_ANT_VARIABLE = 0, /* variable by programming */ - AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ - AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ - AR5K_ANT_MAX = 3, +enum ath5k_ant_table { + AR5K_ANT_CTL = 0, /* Idle switch table settings */ + AR5K_ANT_SWTABLE_A = 1, /* Switch table for antenna A */ + AR5K_ANT_SWTABLE_B = 2, /* Switch table for antenna B */ + AR5K_ANT_MAX, }; enum ath5k_ctl_mode { @@ -461,6 +461,7 @@ struct ath5k_eeprom_info { /* Spur mitigation data (fbin values for spur channels) */ u16 ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS]; + /* Antenna raw switch tables */ u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; }; diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index bb61b8e2dce9..fd93c4e20214 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1414,25 +1414,189 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) return ret; } +/*****************\ +* Antenna control * +\*****************/ + void /*TODO:Boundary check*/ -ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant) +ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) { ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ + if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA); + ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ + if (ah->ah_version != AR5K_AR5210) - return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); + return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; return false; /*XXX: What do we return for 5210 ?*/ } +/* + * Enable/disable fast rx antenna diversity + */ +static void +ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) +{ + switch (ee_mode) { + case AR5K_EEPROM_MODE_11G: + /* XXX: This is set to + * disabled on initvals !!! */ + case AR5K_EEPROM_MODE_11A: + if (enable) + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_OFDM_DIV_DIS); + else + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_OFDM_DIV_DIS); + break; + case AR5K_EEPROM_MODE_11B: + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_OFDM_DIV_DIS); + break; + default: + return; + } + + if (enable) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, + AR5K_PHY_RESTART_DIV_GC, 0xc); + + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, + AR5K_PHY_FAST_ANT_DIV_EN); + } else { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, + AR5K_PHY_RESTART_DIV_GC, 0x8); + + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, + AR5K_PHY_FAST_ANT_DIV_EN); + } +} + +/* + * Set antenna operating mode + */ +void +ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) +{ + struct ieee80211_channel *channel = &ah->ah_current_channel; + bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; + bool use_def_for_sg; + u8 def_ant, tx_ant, ee_mode; + u32 sta_id1 = 0; + + def_ant = ah->ah_def_ant; + + ATH5K_TRACE(ah->ah_sc); + + switch (channel->hw_value & CHANNEL_MODES) { + case CHANNEL_A: + case CHANNEL_T: + case CHANNEL_XR: + ee_mode = AR5K_EEPROM_MODE_11A; + break; + case CHANNEL_G: + case CHANNEL_TG: + ee_mode = AR5K_EEPROM_MODE_11G; + break; + case CHANNEL_B: + ee_mode = AR5K_EEPROM_MODE_11B; + break; + default: + ATH5K_ERR(ah->ah_sc, + "invalid channel: %d\n", channel->center_freq); + return; + } + + switch (ant_mode) { + case AR5K_ANTMODE_DEFAULT: + tx_ant = 0; + use_def_for_tx = false; + update_def_on_tx = false; + use_def_for_rts = false; + use_def_for_sg = false; + fast_div = true; + break; + case AR5K_ANTMODE_FIXED_A: + def_ant = 1; + tx_ant = 0; + use_def_for_tx = true; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = true; + fast_div = false; + break; + case AR5K_ANTMODE_FIXED_B: + def_ant = 2; + tx_ant = 0; + use_def_for_tx = true; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = true; + fast_div = false; + break; + case AR5K_ANTMODE_SINGLE_AP: + def_ant = 1; /* updated on tx */ + tx_ant = 0; + use_def_for_tx = true; + update_def_on_tx = true; + use_def_for_rts = true; + use_def_for_sg = true; + fast_div = true; + break; + case AR5K_ANTMODE_SECTOR_AP: + tx_ant = 1; /* variable */ + use_def_for_tx = false; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = false; + fast_div = false; + break; + case AR5K_ANTMODE_SECTOR_STA: + tx_ant = 1; /* variable */ + use_def_for_tx = true; + update_def_on_tx = false; + use_def_for_rts = true; + use_def_for_sg = false; + fast_div = true; + break; + case AR5K_ANTMODE_DEBUG: + def_ant = 1; + tx_ant = 2; + use_def_for_tx = false; + update_def_on_tx = false; + use_def_for_rts = false; + use_def_for_sg = false; + fast_div = false; + break; + default: + return; + } + + ah->ah_tx_ant = tx_ant; + ah->ah_ant_mode = ant_mode; + + sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; + sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; + sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0; + sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0; + + AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS); + + if (sta_id1) + AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); + + /* Note: set diversity before default antenna + * because it won't work correctly */ + ath5k_hw_set_fast_div(ah, ee_mode, fast_div); + ath5k_hw_set_def_antenna(ah, def_ant); +} + /****************\ * TX power setup * diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 7070d1543cdc..6809b54a2ad7 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -1148,6 +1148,11 @@ #define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ #define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ +#define AR5K_STA_ID1_ANTENNA_SETTINGS (AR5K_STA_ID1_DEFAULT_ANTENNA | \ + AR5K_STA_ID1_DESC_ANTENNA | \ + AR5K_STA_ID1_RTS_DEF_ANTENNA | \ + AR5K_STA_ID1_SELFGEN_DEF_ANT) + /* * First BSSID register (MAC address, lower 32bits) */ @@ -2028,7 +2033,9 @@ #define AR5K_PHY_AGCCTL 0x9860 /* Register address */ #define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ #define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ +#define AR5K_PHY_AGCCTL_OFDM_DIV_DIS 0x00000008 /* Disable antenna diversity on OFDM modes */ #define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ +#define AR5K_PHY_AGCTL_FLTR_CAL 0x00010000 /* Allow filter calibration (?) */ #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ /* @@ -2528,7 +2535,7 @@ * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] */ #define AR5K_PHY_CCK_CROSSCORR 0xa208 -#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f +#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000003f #define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 /* Same address is used for antenna diversity activation */ diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index d419c6a3ded7..0e075bca384f 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -698,13 +698,13 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, /* Set antenna idle switch table */ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, AR5K_PHY_ANT_CTL_SWTABLE_IDLE, - (ah->ah_antenna[ee_mode][0] | + (ah->ah_ant_ctl[ee_mode][0] | AR5K_PHY_ANT_CTL_TXRX_EN)); - /* Set antenna switch table */ - ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]], + /* Set antenna switch tables */ + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], AR5K_PHY_ANT_SWITCH_TABLE_0); - ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]], + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], AR5K_PHY_ANT_SWITCH_TABLE_1); /* Noise floor threshold */ @@ -1042,17 +1042,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* * In case a fixed antenna was set as default - * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE - * registers. + * use the same switch table twice. */ - if (s_ant != 0) { - if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */ - ant[0] = ant[1] = AR5K_ANT_FIXED_A; - else /* 2 - Aux */ - ant[0] = ant[1] = AR5K_ANT_FIXED_B; - } else { - ant[0] = AR5K_ANT_FIXED_A; - ant[1] = AR5K_ANT_FIXED_B; + if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) + ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; + else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) + ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; + else { + ant[0] = AR5K_ANT_SWTABLE_A; + ant[1] = AR5K_ANT_SWTABLE_B; } /* Commit values from EEPROM */ @@ -1260,6 +1258,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, */ ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + /* Restore antenna mode */ + ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); /* * Configure QCUs/DCUs -- cgit v1.2.3 From 57e6c56dbb52d680f61dd629759fe2974840ed93 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 30 Apr 2009 15:55:50 -0400 Subject: ath5k: Add Spur filter support on newer chips * Add spur filter support for RF5413 and later chips Signed-off-by: Nick Kossifidis Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 5 + drivers/net/wireless/ath/ath5k/phy.c | 255 ++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath5k/reset.c | 35 ++--- 3 files changed, 270 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 33da290e4bb5..813718210338 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1278,6 +1278,11 @@ extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *chann /* PHY calibration */ extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); +/* Spur mitigation */ +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel); +void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, + struct ieee80211_channel *channel); /* Misc PHY functions */ extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index fd93c4e20214..6737ba0a4de3 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1353,6 +1353,257 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, return ret; } +/***************************\ +* Spur mitigation functions * +\***************************/ + +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u8 refclk_freq; + + if ((ah->ah_radio == AR5K_RF5112) || + (ah->ah_radio == AR5K_RF5413) || + (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) + refclk_freq = 40; + else + refclk_freq = 32; + + if ((channel->center_freq % refclk_freq != 0) && + ((channel->center_freq % refclk_freq < 10) || + (channel->center_freq % refclk_freq > 22))) + return true; + else + return false; +} + +void +ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; + u32 mag_mask[4] = {0, 0, 0, 0}; + u32 pilot_mask[2] = {0, 0}; + /* Note: fbin values are scaled up by 2 */ + u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window; + s32 spur_delta_phase, spur_freq_sigma_delta; + s32 spur_offset, num_symbols_x16; + u8 num_symbol_offsets, i, freq_band; + + /* Convert current frequency to fbin value (the same way channels + * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale + * up by 2 so we can compare it later */ + if (channel->hw_value & CHANNEL_2GHZ) { + chan_fbin = (channel->center_freq - 2300) * 10; + freq_band = AR5K_EEPROM_BAND_2GHZ; + } else { + chan_fbin = (channel->center_freq - 4900) * 10; + freq_band = AR5K_EEPROM_BAND_5GHZ; + } + + /* Check if any spur_chan_fbin from EEPROM is + * within our current channel's spur detection range */ + spur_chan_fbin = AR5K_EEPROM_NO_SPUR; + spur_detection_window = AR5K_SPUR_CHAN_WIDTH; + /* XXX: Half/Quarter channels ?*/ + if (channel->hw_value & CHANNEL_TURBO) + spur_detection_window *= 2; + + for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { + spur_chan_fbin = ee->ee_spur_chans[i][freq_band]; + + /* Note: mask cleans AR5K_EEPROM_NO_SPUR flag + * so it's zero if we got nothing from EEPROM */ + if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) { + spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; + break; + } + + if ((chan_fbin - spur_detection_window <= + (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) && + (chan_fbin + spur_detection_window >= + (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) { + spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; + break; + } + } + + /* We need to enable spur filter for this channel */ + if (spur_chan_fbin) { + spur_offset = spur_chan_fbin - chan_fbin; + /* + * Calculate deltas: + * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 + * spur_delta_phase -> spur_offset / chip_freq << 11 + * Note: Both values have 100KHz resolution + */ + /* XXX: Half/Quarter rate channels ? */ + switch (channel->hw_value) { + case CHANNEL_A: + /* Both sample_freq and chip_freq are 40MHz */ + spur_delta_phase = (spur_offset << 17) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + break; + case CHANNEL_G: + /* sample_freq -> 40MHz chip_freq -> 44MHz + * (for b compatibility) */ + spur_freq_sigma_delta = (spur_offset << 8) / 55; + spur_delta_phase = (spur_offset << 17) / 25; + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; + break; + case CHANNEL_T: + case CHANNEL_TG: + /* Both sample_freq and chip_freq are 80MHz */ + spur_delta_phase = (spur_offset << 16) / 25; + spur_freq_sigma_delta = (spur_delta_phase >> 10); + symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; + break; + default: + return; + } + + /* Calculate pilot and magnitude masks */ + + /* Scale up spur_offset by 1000 to switch to 100HZ resolution + * and divide by symbol_width to find how many symbols we have + * Note: number of symbols is scaled up by 16 */ + num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width; + + /* Spur is on a symbol if num_symbols_x16 % 16 is zero */ + if (!(num_symbols_x16 & 0xF)) + /* _X_ */ + num_symbol_offsets = 3; + else + /* _xx_ */ + num_symbol_offsets = 4; + + for (i = 0; i < num_symbol_offsets; i++) { + + /* Calculate pilot mask */ + s32 curr_sym_off = + (num_symbols_x16 / 16) + i + 25; + + /* Pilot magnitude mask seems to be a way to + * declare the boundaries for our detection + * window or something, it's 2 for the middle + * value(s) where the symbol is expected to be + * and 1 on the boundary values */ + u8 plt_mag_map = + (i == 0 || i == (num_symbol_offsets - 1)) + ? 1 : 2; + + if (curr_sym_off >= 0 && curr_sym_off <= 32) { + if (curr_sym_off <= 25) + pilot_mask[0] |= 1 << curr_sym_off; + else if (curr_sym_off >= 27) + pilot_mask[0] |= 1 << (curr_sym_off - 1); + } else if (curr_sym_off >= 33 && curr_sym_off <= 52) + pilot_mask[1] |= 1 << (curr_sym_off - 33); + + /* Calculate magnitude mask (for viterbi decoder) */ + if (curr_sym_off >= -1 && curr_sym_off <= 14) + mag_mask[0] |= + plt_mag_map << (curr_sym_off + 1) * 2; + else if (curr_sym_off >= 15 && curr_sym_off <= 30) + mag_mask[1] |= + plt_mag_map << (curr_sym_off - 15) * 2; + else if (curr_sym_off >= 31 && curr_sym_off <= 46) + mag_mask[2] |= + plt_mag_map << (curr_sym_off - 31) * 2; + else if (curr_sym_off >= 46 && curr_sym_off <= 53) + mag_mask[3] |= + plt_mag_map << (curr_sym_off - 47) * 2; + + } + + /* Write settings on hw to enable spur filter */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_RATE, 0xff); + /* XXX: Self correlator also ? */ + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_PILOT_MASK_EN | + AR5K_PHY_IQ_CHAN_MASK_EN | + AR5K_PHY_IQ_SPUR_FILT_EN); + + /* Set delta phase and freq sigma delta */ + ath5k_hw_reg_write(ah, + AR5K_REG_SM(spur_delta_phase, + AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) | + AR5K_REG_SM(spur_freq_sigma_delta, + AR5K_PHY_TIMING_11_SPUR_FREQ_SD) | + AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC, + AR5K_PHY_TIMING_11); + + /* Write pilot masks */ + ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, + AR5K_PHY_TIMING_8_PILOT_MASK_2, + pilot_mask[1]); + + ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, + AR5K_PHY_TIMING_10_PILOT_MASK_2, + pilot_mask[1]); + + /* Write magnitude masks */ + ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1); + ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2); + ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_MASK_4, + mag_mask[3]); + + ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1); + ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2); + ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, + AR5K_PHY_BIN_MASK2_4_MASK_4, + mag_mask[3]); + + } else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & + AR5K_PHY_IQ_SPUR_FILT_EN) { + /* Clean up spur mitigation settings and disable fliter */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_RATE, 0); + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_PILOT_MASK_EN | + AR5K_PHY_IQ_CHAN_MASK_EN | + AR5K_PHY_IQ_SPUR_FILT_EN); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11); + + /* Clear pilot masks */ + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, + AR5K_PHY_TIMING_8_PILOT_MASK_2, + 0); + + ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, + AR5K_PHY_TIMING_10_PILOT_MASK_2, + 0); + + /* Clear magnitude masks */ + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, + AR5K_PHY_BIN_MASK_CTL_MASK_4, + 0); + + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2); + ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, + AR5K_PHY_BIN_MASK2_4_MASK_4, + 0); + } +} + +/********************\ + Misc PHY functions +\********************/ + int ath5k_hw_phy_disable(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); @@ -1362,10 +1613,6 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah) return 0; } -/********************\ - Misc PHY functions -\********************/ - /* * Get the PHY Chip revision */ diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 0e075bca384f..c1862f8a2e7b 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -536,26 +536,6 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) return; } -static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u8 refclk_freq; - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - refclk_freq = 40; - else - refclk_freq = 32; - - if ((channel->center_freq % refclk_freq != 0) && - ((channel->center_freq % refclk_freq < 10) || - (channel->center_freq % refclk_freq > 22))) - return true; - else - return false; -} - /* TODO: Half/Quarter rate */ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel) @@ -998,7 +978,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_tweak_initval_settings(ah, channel); /* - * Set TX power (FIXME) + * Set TX power */ ret = ath5k_hw_txpower(ah, channel, ee_mode, ah->ah_txpower.txp_max_pwr / 2); @@ -1024,9 +1004,22 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Write OFDM timings on 5212*/ if (ah->ah_version == AR5K_AR5212 && channel->hw_value & CHANNEL_OFDM) { + struct ath5k_eeprom_info *ee = + &ah->ah_capabilities.cap_eeprom; + ret = ath5k_hw_write_ofdm_timings(ah, channel); if (ret) return ret; + + /* Note: According to docs we can have a newer + * EEPROM on old hardware, so we need to verify + * that our hardware is new enough to have spur + * mitigation registers (delta phase etc) */ + if (ah->ah_mac_srev >= AR5K_SREV_AR5424 || + (ah->ah_mac_srev >= AR5K_SREV_AR5424 && + ee->ee_version >= AR5K_EEPROM_VERSION_5_3)) + ath5k_hw_set_spur_mitigation_filter(ah, + channel); } /*Enable/disable 802.11b mode on 5111 -- cgit v1.2.3 From 6752ee90aa7c933294a10dbd9ea51f12dece7eb1 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Thu, 30 Apr 2009 15:55:51 -0400 Subject: ath5k: use ctl settings based on current regdomain Update ath5k to use the ctl settings for tx power based on current regulatory domain. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6737ba0a4de3..d0d1c350025a 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2158,8 +2158,6 @@ done: * Get the max edge power for this channel if * we have such data from EEPROM's Conformance Test * Limits (CTL), and limit max power if needed. - * - * FIXME: Only works for world regulatory domains */ static void ath5k_get_max_ctl_power(struct ath5k_hw *ah, @@ -2175,26 +2173,23 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, u8 ctl_idx = 0xFF; u32 target = channel->center_freq; - /* Find out a CTL for our mode that's not mapped - * on a specific reg domain. - * - * TODO: Map our current reg domain to one of the 3 available - * reg domain ids so that we can support more CTLs. */ + ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band); + switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_11A; break; case CHANNEL_G: - ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_11G; break; case CHANNEL_B: - ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_11B; break; case CHANNEL_T: - ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_TURBO; break; case CHANNEL_TG: - ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN; + ctl_mode |= AR5K_CTL_TURBOG; break; case CHANNEL_XR: /* Fall through */ -- cgit v1.2.3 From 84379cba44042a4caf793f821be8bd1a9b8235c2 Mon Sep 17 00:00:00 2001 From: Paride Legovini Date: Thu, 30 Apr 2009 15:55:52 -0400 Subject: Add LED support for AR5BXB6 IBM Thinkpad PCIe adapters Add LED support on the IBM ThinkPad 11a/b/g Wireless LAN Mini Express Adapter (AR5BXB6), found on the IBM/Lenovo Thinkpad X60/T60/Z60 series. Signed-off-by: Paride Legovini Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/led.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index cbdc0b308429..876725f08b6c 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -53,8 +53,6 @@ /* Devices we match on for LED config info (typically laptops) */ static const struct pci_device_id ath5k_led_devices[] = { - /* IBM-specific AR5212 */ - { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, /* AR5211 */ { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, /* HP Compaq nc6xx, nc4000, nx6000 */ @@ -69,6 +67,10 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, + /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ + { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, + /* IBM-specific AR5212 (all others) */ + { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, { } }; -- cgit v1.2.3 From 722404983b9deb21e4f786224201ca2ab27a1c48 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Thu, 30 Apr 2009 13:56:26 -0700 Subject: iwl3945: fix lock dependency Patch seperates rx_used and rx_free into two different atomic contexts. We can now avoid using GFP_ATOMIC for skb allocation and use GFP_KERNEL. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 37 +++++++++++++---------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5cd4321d7cf5..dc0359ce1ec0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1344,15 +1344,24 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; - spin_lock_irqsave(&rxq->lock, flags); - while (!list_empty(&rxq->rx_used)) { + + while (1) { + spin_lock_irqsave(&rxq->lock, flags); + + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + return; + } + element = rxq->rx_used.next; rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + spin_unlock_irqrestore(&rxq->lock, flags); /* Alloc a new receive buffer */ rxb->skb = alloc_skb(priv->hw_params.rx_buf_size, - __GFP_NOWARN | GFP_ATOMIC); + GFP_KERNEL); if (!rxb->skb) { if (net_ratelimit()) IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); @@ -1370,18 +1379,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) */ skb_reserve(rxb->skb, 4); - priv->alloc_rxb_skb++; - list_del(element); - /* Get physical address of RB/SKB */ rxb->real_dma_addr = pci_map_single(priv->pci_dev, rxb->skb->data, priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); + + spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &rxq->rx_free); + priv->alloc_rxb_skb++; rxq->free_count++; + spin_unlock_irqrestore(&rxq->lock, flags); } - spin_unlock_irqrestore(&rxq->lock, flags); } void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) @@ -1414,18 +1423,6 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) spin_unlock_irqrestore(&rxq->lock, flags); } -/* - * this should be called while priv->lock is locked - */ -static void __iwl3945_rx_replenish(void *data) -{ - struct iwl_priv *priv = data; - - iwl3945_rx_allocate(priv); - iwl3945_rx_queue_restock(priv); -} - - void iwl3945_rx_replenish(void *data) { struct iwl_priv *priv = data; @@ -1644,7 +1641,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) count++; if (count >= 8) { priv->rxq.read = i; - __iwl3945_rx_replenish(priv); + iwl3945_rx_queue_restock(priv); count = 0; } } -- cgit v1.2.3 From 286d94906587901851906a5e2ddc09bc1a7ba1d9 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 30 Apr 2009 13:56:27 -0700 Subject: iwlagn: disable PS support for iwlagn Some issues in PS prevent us from supporting it reliably. When 4965 goes to sleep it stores some data in host DRAM, reads it back when device wakes up. In 4965 there is a problem that the data is not correct when ucode starts using it upon wakeup. For all iwlagn devices there is a problem where command is sent when PS is enabled. At the moment there is a locking problem with priv->lock not being held and thus not requesting nic access correctly. We disable PS until these issues have been resolved. Signed-off-by: Reinette Chatre Signed-off-by: Mohamed Abbas Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0f21fc136ca7..1366222bb50a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1298,8 +1298,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SUPPORTS_PS; + IEEE80211_HW_SPECTRUM_MGMT; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); -- cgit v1.2.3 From a30199f129e17998f802d3307907560431e78493 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 30 Apr 2009 13:56:28 -0700 Subject: iwlwifi: "is_fat" bit in rate scale match RXON flag This patch change the "is_fat" checking in rate scale to use iwl_is_fat_tx_allowed() to match the sta and RX_ON command setting. Signed-off-by: Wey-Yi Guy Tested-by: Conrad Kostecki Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 29d38b938f38..0a71bb55d0ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1207,8 +1207,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, tbl->action = 0; rate_mask = lq_sta->active_mimo2_rate; - if (priv->current_ht_config.supported_chan_width - == IWL_CHANNEL_WIDTH_40MHZ) + if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) tbl->is_fat = 1; else tbl->is_fat = 0; @@ -1273,8 +1272,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, tbl->action = 0; rate_mask = lq_sta->active_mimo3_rate; - if (priv->current_ht_config.supported_chan_width - == IWL_CHANNEL_WIDTH_40MHZ) + if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) tbl->is_fat = 1; else tbl->is_fat = 0; @@ -1332,8 +1330,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, tbl->action = 0; rate_mask = lq_sta->active_siso_rate; - if (priv->current_ht_config.supported_chan_width - == IWL_CHANNEL_WIDTH_40MHZ) + if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) tbl->is_fat = 1; else tbl->is_fat = 0; -- cgit v1.2.3 From 4e8e2c824027ed433be3c599294bf093a120ad9d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 30 Apr 2009 13:56:29 -0700 Subject: iwlwifi: replace test_and_set_bit by set_bit in clear stations function This patch replaces test_and_set_bit by set_bit since the bit is not tested anyway Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 17a4dd2be1f2..28dd225269ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -490,7 +490,7 @@ void iwl_clear_stations_table(struct iwl_priv *priv) /* keep track of static keys */ for (i = 0; i < WEP_KEYS_MAX ; i++) { if (priv->wep_keys[i].key_size) - test_and_set_bit(i, &priv->ucode_key_table); + set_bit(i, &priv->ucode_key_table); } spin_unlock_irqrestore(&priv->sta_lock, flags); -- cgit v1.2.3 From 8bce6121706dd82c266c3f527e592abfb3e164d1 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 1 May 2009 08:20:07 -0400 Subject: wl12xx: correct printk format warnings Fixes warnings: drivers/net/wireless/wl12xx/main.c:87: warning: int format, different type arg (arg 2) drivers/net/wireless/wl12xx/main.c: In function `wl12xx_fetch_nvs': drivers/net/wireless/wl12xx/main.c:125: warning: int format, different type arg (arg 2) drivers/net/wireless/wl12xx/wl1251.c: In function 'wl1251_upload_firmware': drivers/net/wireless/wl12xx/wl1251.c:94: warning: int format, different type arg (arg 2) drivers/net/wireless/wl12xx/wl1251.c:141: warning: int format, different type arg (arg 2) Signed-off-by: Bob Copeland Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/main.c | 4 ++-- drivers/net/wireless/wl12xx/wl1251.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 744f4ce5993b..603d6114882e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -84,7 +84,7 @@ static int wl12xx_fetch_firmware(struct wl12xx *wl) } if (fw->size % 4) { - wl12xx_error("firmware size is not multiple of 32 bits: %d", + wl12xx_error("firmware size is not multiple of 32 bits: %zu", fw->size); ret = -EILSEQ; goto out; @@ -122,7 +122,7 @@ static int wl12xx_fetch_nvs(struct wl12xx *wl) } if (fw->size % 4) { - wl12xx_error("nvs size is not multiple of 32 bits: %d", + wl12xx_error("nvs size is not multiple of 32 bits: %zu", fw->size); ret = -EILSEQ; goto out; diff --git a/drivers/net/wireless/wl12xx/wl1251.c b/drivers/net/wireless/wl12xx/wl1251.c index bd0decdcad23..ce1561a41fa4 100644 --- a/drivers/net/wireless/wl12xx/wl1251.c +++ b/drivers/net/wireless/wl12xx/wl1251.c @@ -91,7 +91,7 @@ static int wl1251_upload_firmware(struct wl12xx *wl) fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) | (wl->fw[6] << 8) | (wl->fw[7]); - wl12xx_debug(DEBUG_BOOT, "fw_data_len %d chunk_size %d", fw_data_len, + wl12xx_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len, CHUNK_SIZE); if ((fw_data_len % 4) != 0) { @@ -138,7 +138,7 @@ static int wl1251_upload_firmware(struct wl12xx *wl) /* 10.4 upload the last chunk */ addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE; p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; - wl12xx_debug(DEBUG_BOOT, "uploading fw last chunk (%d B) 0x%p to 0x%x", + wl12xx_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", fw_data_len % CHUNK_SIZE, p, addr); wl12xx_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); -- cgit v1.2.3 From 928841b1538df117658ec5977bcf336c27f7747b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 30 Apr 2009 23:02:47 -0700 Subject: Wireless: remove driver_data direct access of struct device In the near future, the driver core is going to not allow direct access to the driver_data pointer in struct device. Instead, the functions dev_get_drvdata() and dev_set_drvdata() should be used. These functions have been around since the beginning, so are backwards compatible with all older kernel versions. Cc: John W. Linville Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: John W. Linville --- drivers/net/wireless/atmel_cs.c | 2 +- drivers/net/wireless/ipw2x00/ipw2100.c | 8 ++--- drivers/net/wireless/ipw2x00/ipw2200.c | 47 +++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl-agn.c | 20 ++++++------ drivers/net/wireless/iwlwifi/iwl3945-base.c | 26 ++++++++-------- 5 files changed, 53 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 77406245dc7b..ddaa859c3491 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -279,7 +279,7 @@ static int atmel_config(struct pcmcia_device *link) struct pcmcia_device_id *did; dev = link->priv; - did = handle_to_dev(link).driver_data; + did = dev_get_drvdata(&handle_to_dev(link)); DEBUG(0, "atmel_config(0x%p)\n", link); diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 97e5647ff050..742432388ca3 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -3488,7 +3488,7 @@ static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL); static ssize_t show_cfg(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw2100_priv *p = d->driver_data; + struct ipw2100_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->config); } @@ -3497,7 +3497,7 @@ static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw2100_priv *p = d->driver_data; + struct ipw2100_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->status); } @@ -3506,7 +3506,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static ssize_t show_capability(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw2100_priv *p = d->driver_data; + struct ipw2100_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->capability); } @@ -4224,7 +4224,7 @@ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, 1 - SW based RF kill active (sysfs) 2 - HW based RF kill active 3 - Both HW and SW baed RF kill active */ - struct ipw2100_priv *priv = (struct ipw2100_priv *)d->driver_data; + struct ipw2100_priv *priv = dev_get_drvdata(d); int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | (rf_kill_active(priv) ? 0x2 : 0x0); return sprintf(buf, "%i\n", val); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 9a123fbcc359..c3b3dfe43d1a 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -1527,7 +1527,7 @@ static DEVICE_ATTR(led, S_IWUSR | S_IRUGO, show_led, store_led); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->status); } @@ -1536,7 +1536,7 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static ssize_t show_cfg(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); return sprintf(buf, "0x%08x\n", (int)p->config); } @@ -1545,7 +1545,7 @@ static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); static ssize_t show_nic_type(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); return sprintf(buf, "TYPE: %d\n", priv->nic_type); } @@ -1555,7 +1555,7 @@ static ssize_t show_ucode_version(struct device *d, struct device_attribute *attr, char *buf) { u32 len = sizeof(u32), tmp = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); if (ipw_get_ordinal(p, IPW_ORD_STAT_UCODE_VERSION, &tmp, &len)) return 0; @@ -1569,7 +1569,7 @@ static ssize_t show_rtc(struct device *d, struct device_attribute *attr, char *buf) { u32 len = sizeof(u32), tmp = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); if (ipw_get_ordinal(p, IPW_ORD_STAT_RTC, &tmp, &len)) return 0; @@ -1586,14 +1586,15 @@ static DEVICE_ATTR(rtc, S_IWUSR | S_IRUGO, show_rtc, NULL); static ssize_t show_eeprom_delay(struct device *d, struct device_attribute *attr, char *buf) { - int n = ((struct ipw_priv *)d->driver_data)->eeprom_delay; + struct ipw_priv *p = dev_get_drvdata(d); + int n = p->eeprom_delay; return sprintf(buf, "%i\n", n); } static ssize_t store_eeprom_delay(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); sscanf(buf, "%i", &p->eeprom_delay); return strnlen(buf, count); } @@ -1605,7 +1606,7 @@ static ssize_t show_command_event_reg(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT); return sprintf(buf, "0x%08x\n", reg); @@ -1615,7 +1616,7 @@ static ssize_t store_command_event_reg(struct device *d, const char *buf, size_t count) { u32 reg; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); sscanf(buf, "%x", ®); ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg); @@ -1629,7 +1630,7 @@ static ssize_t show_mem_gpio_reg(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); reg = ipw_read_reg32(p, 0x301100); return sprintf(buf, "0x%08x\n", reg); @@ -1639,7 +1640,7 @@ static ssize_t store_mem_gpio_reg(struct device *d, const char *buf, size_t count) { u32 reg; - struct ipw_priv *p = d->driver_data; + struct ipw_priv *p = dev_get_drvdata(d); sscanf(buf, "%x", ®); ipw_write_reg32(p, 0x301100, reg); @@ -1653,7 +1654,7 @@ static ssize_t show_indirect_dword(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (priv->status & STATUS_INDIRECT_DWORD) reg = ipw_read_reg32(priv, priv->indirect_dword); @@ -1666,7 +1667,7 @@ static ssize_t store_indirect_dword(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); sscanf(buf, "%x", &priv->indirect_dword); priv->status |= STATUS_INDIRECT_DWORD; @@ -1680,7 +1681,7 @@ static ssize_t show_indirect_byte(struct device *d, struct device_attribute *attr, char *buf) { u8 reg = 0; - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (priv->status & STATUS_INDIRECT_BYTE) reg = ipw_read_reg8(priv, priv->indirect_byte); @@ -1693,7 +1694,7 @@ static ssize_t store_indirect_byte(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); sscanf(buf, "%x", &priv->indirect_byte); priv->status |= STATUS_INDIRECT_BYTE; @@ -1707,7 +1708,7 @@ static ssize_t show_direct_dword(struct device *d, struct device_attribute *attr, char *buf) { u32 reg = 0; - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (priv->status & STATUS_DIRECT_DWORD) reg = ipw_read32(priv, priv->direct_dword); @@ -1720,7 +1721,7 @@ static ssize_t store_direct_dword(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); sscanf(buf, "%x", &priv->direct_dword); priv->status |= STATUS_DIRECT_DWORD; @@ -1747,7 +1748,7 @@ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, 1 - SW based RF kill active (sysfs) 2 - HW based RF kill active 3 - Both HW and SW baed RF kill active */ - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | (rf_kill_active(priv) ? 0x2 : 0x0); return sprintf(buf, "%i\n", val); @@ -1791,7 +1792,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); ipw_radio_kill_sw(priv, buf[0] == '1'); @@ -1803,7 +1804,7 @@ static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); int pos = 0, len = 0; if (priv->config & CFG_SPEED_SCAN) { while (priv->speed_scan[pos] != 0) @@ -1818,7 +1819,7 @@ static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); int channel, pos = 0; const char *p = buf; @@ -1857,14 +1858,14 @@ static DEVICE_ATTR(speed_scan, S_IWUSR | S_IRUGO, show_speed_scan, static ssize_t show_net_stats(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0'); } static ssize_t store_net_stats(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + struct ipw_priv *priv = dev_get_drvdata(d); if (buf[0] == '1') priv->config |= CFG_NET_STATS; else diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index dd8b15ed8296..6cdee0b4b486 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2268,7 +2268,7 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%08X\n", priv->debug_level); } @@ -2276,7 +2276,7 @@ static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -2299,7 +2299,7 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_version(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); struct iwl_alive_resp *palive = &priv->card_alive; ssize_t pos = 0; u16 eeprom_ver; @@ -2330,7 +2330,7 @@ static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL); static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_alive(priv)) return -EAGAIN; @@ -2343,7 +2343,7 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_ready_rf(priv)) return sprintf(buf, "off\n"); @@ -2355,7 +2355,7 @@ static ssize_t store_tx_power(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -2373,7 +2373,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); } @@ -2382,7 +2382,7 @@ static ssize_t store_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; u32 flags; int ret = strict_strtoul(buf, 0, &val); @@ -2411,7 +2411,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.filter_flags)); @@ -2421,7 +2421,7 @@ static ssize_t store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; u32 filter_flags; int ret = strict_strtoul(buf, 0, &val); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index dc0359ce1ec0..9f5191a84a13 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3595,7 +3595,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%08X\n", priv->debug_level); } @@ -3603,7 +3603,7 @@ static ssize_t store_debug_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -3624,7 +3624,7 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_alive(priv)) return -EAGAIN; @@ -3637,7 +3637,7 @@ static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%d\n", priv->tx_power_user_lmt); } @@ -3645,7 +3645,7 @@ static ssize_t store_tx_power(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); char *p = (char *)buf; u32 val; @@ -3663,7 +3663,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); } @@ -3672,7 +3672,7 @@ static ssize_t store_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); u32 flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -3697,7 +3697,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.filter_flags)); @@ -3707,7 +3707,7 @@ static ssize_t store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -3992,7 +3992,7 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "0x%08x\n", (int)priv->status); @@ -4004,10 +4004,11 @@ static ssize_t dump_error_log(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { + struct iwl_priv *priv = dev_get_drvdata(d); char *p = (char *)buf; if (p[0] == '1') - iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data); + iwl3945_dump_nic_error_log(priv); return strnlen(buf, count); } @@ -4018,10 +4019,11 @@ static ssize_t dump_event_log(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { + struct iwl_priv *priv = dev_get_drvdata(d); char *p = (char *)buf; if (p[0] == '1') - iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data); + iwl3945_dump_nic_event_log(priv); return strnlen(buf, count); } -- cgit v1.2.3 From 13792578c88961256dd30e3a5d3fa1ac1ec9a7e0 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Fri, 1 May 2009 13:12:36 +0200 Subject: p54usb: Fixes compile error with CONFIG_PM=n /drivers/net/wireless/p54/p54usb.c: In function 'p54u_probe': /drivers/net/wireless/p54/p54usb.c:923: error: 'struct usb_device' has no member named 'reset_resume' In the struct usb_device the reset_resume attribute is only available when CONFIG_PM is defined. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index ec6c95474f1a..f40c0f468b27 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -919,9 +919,11 @@ static int __devinit p54u_probe(struct usb_interface *intf, priv->common.open = p54u_open; priv->common.stop = p54u_stop; if (recognized_pipes < P54U_PIPE_NUMBER) { +#ifdef CONFIG_PM /* ISL3887 needs a full reset on resume */ udev->reset_resume = 1; err = p54u_device_reset(dev); +#endif priv->hw_type = P54U_3887; dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); -- cgit v1.2.3 From 1b06bb4087d195d8289919df2f4d95ec3b89769e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Sat, 2 May 2009 00:34:48 -0400 Subject: cfg80211: make nl80211_send_mlme_timeout() static Fixes sparse complaint: CHECK net/wireless/nl80211.c net/wireless/nl80211.c:3694:6: warning: symbol 'nl80211_send_mlme_timeout' was not declared. Should it be static? Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b1fc98225fd1..3c53c5cbc3a9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3696,9 +3696,9 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, NL80211_CMD_DISASSOCIATE); } -void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, - struct net_device *netdev, int cmd, - const u8 *addr) +static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, + struct net_device *netdev, int cmd, + const u8 *addr) { struct sk_buff *msg; void *hdr; -- cgit v1.2.3 From 7738231f98578c8cd5b367441b4aa79ce864856f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 4 May 2009 17:52:10 +0200 Subject: mac80211: report operating frequency rather than current It's not very helpful to see, in iwconfig, the current frequency the card is tuned to if that frequency is currently somewhere across the board because we're scanning. Since we keep track of the frequency the user wants, display that instead. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/wext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1a649da42c41..6b4eb8d43a4e 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -185,7 +185,7 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); - freq->m = local->hw.conf.channel->center_freq; + freq->m = local->oper_channel->center_freq; freq->e = 6; return 0; -- cgit v1.2.3 From 8a7130404948b966e98b1285e777972b4b3f2fa2 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Mon, 4 May 2009 20:46:25 +0400 Subject: ar9170: fix build when !CONFIG_PM Fix this build error when CONFIG_PM is not set: drivers/net/wireless/ath/ar9170/usb.c: In function 'ar9170_usb_probe': drivers/net/wireless/ath/ar9170/usb.c:692: error: 'struct usb_device' has no member named 'reset_resume' Signed-off-by: Alexander Beregalov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index d7b562dcebd2..d7c13c0177ca 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -689,7 +689,9 @@ static int ar9170_usb_probe(struct usb_interface *intf, aru->common.exec_cmd = ar9170_usb_exec_cmd; aru->common.callback_cmd = ar9170_usb_callback_cmd; +#ifdef CONFIG_PM udev->reset_resume = 1; +#endif err = ar9170_usb_reset(aru); if (err) goto err_freehw; -- cgit v1.2.3 From 83f8b478ff5ed7d7df0bf91336bbede7b4714771 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 6 May 2009 14:16:15 -0400 Subject: p54: correct merge damage from "p54: more SoftLED updates" Ooops... Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 7fda1a9e263b..db3df947d8ed 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -189,10 +189,10 @@ struct p54_common { unsigned long *used_rxkeys; /* LED management */ -#ifdef CONFIG_MAC80211_LEDS +#ifdef CONFIG_P54_LEDS struct p54_led_dev leds[4]; struct delayed_work led_work; -#endif /* CONFIG_MAC80211_LEDS */ +#endif /* CONFIG_P54_LEDS */ u16 softled_state; /* bit field of glowing LEDs */ /* statistics */ -- cgit v1.2.3 From 6cfe62cd58da862db04d4eb61f218f65b0cedbb3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 5 May 2009 15:48:39 -0400 Subject: mac80211: Fix sparse warning for ssid_len on ieee80211_sta_config_auth() net/mac80211/mlme.c:2079:28: warning: symbol 'ssid_len' shadows an earlier one net/mac80211/mlme.c:2022:12: originally declared here ssid_len is already being declared and checked above so there is no need for it again. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5509c5aa6beb..75c487229f2e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2076,10 +2076,6 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) return 0; } else { if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { - u8 ssid_len = 0; - - if (!(ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL)) - ssid_len = ifmgd->ssid_len; ifmgd->assoc_scan_tries++; -- cgit v1.2.3 From 358623c22c9fd837b3b1b444377037f72553dc9f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 5 May 2009 19:46:08 +0200 Subject: rt2x00: Simplify rt2x00_check_rev rt2x00_check_rev() was too specific for rt2500usb and rt73usb, by adding the mask argument (instead of hardcoding it into the function itself) we can use the function in rt2800usb as well. v2: Fix revision mask for rt2800usb Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2800usb.c | 7 ++++--- drivers/net/wireless/rt2x00/rt2x00.h | 7 +++---- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 08e88333b0ff..1debb88bc60e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1559,7 +1559,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index cf4a97f32ab3..257bfb5483c9 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -2348,9 +2348,10 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * The check for rt2860 is not a typo, some rt2870 hardware * identifies itself as rt2860 in the CSR register. */ - if ((rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x2860) && - (rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x2870) && - (rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x3070)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28600000) && + !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28700000) && + !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28800000) && + !rt2x00_check_rev(&rt2x00dev->chip, 0xffff0000, 0x30700000)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8d933ee30583..419b1b9f998e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -915,11 +915,10 @@ static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) return chipset->rev; } -static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, - const u32 rev) +static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, + const u32 mask, const u32 rev) { - return (((chipset->rev & 0xffff0) == rev) && - !!(chipset->rev & 0x0000f)); + return ((chipset->rev & mask) == rev); } /** diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6bd28a6bcef2..d10af3687a8e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1846,7 +1846,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || + !rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } -- cgit v1.2.3 From 2d3babd11f91501f49c6af212e6795bd8954f4d4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 May 2009 20:35:13 +0300 Subject: mac80211: Use a shared function to release frames from RX reorder buf No need to duplicate the same code in two places (and that would be three after the followup patch). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/rx.c | 70 ++++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6a9d89b392e3..9f2a29d1890b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2284,6 +2284,34 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) } +static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, + struct tid_ampdu_rx *tid_agg_rx, + int index) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_rate *rate; + struct ieee80211_rx_status status; + + if (!tid_agg_rx->reorder_buf[index]) + goto no_frame; + + /* release the reordered frames to stack */ + memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); + sband = hw->wiphy->bands[status.band]; + if (status.flag & RX_FLAG_HT) + rate = sband->bitrates; /* TODO: HT rates */ + else + rate = &sband->bitrates[status.rate_idx]; + __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], + &status, rate); + tid_agg_rx->stored_mpdu_num--; + tid_agg_rx->reorder_buf[index] = NULL; + +no_frame: + tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); +} + + /* * As it function blongs to Rx path it must be called with * the proper rcu_read_lock protection for its flow. @@ -2295,12 +2323,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, u16 mpdu_seq_num, int bar_req) { - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_rx_status status; u16 head_seq_num, buf_size; int index; - struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate; buf_size = tid_agg_rx->buf_size; head_seq_num = tid_agg_rx->head_seq_num; @@ -2325,28 +2349,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; - - if (tid_agg_rx->reorder_buf[index]) { - /* release the reordered frames to stack */ - memcpy(&status, - tid_agg_rx->reorder_buf[index]->cb, - sizeof(status)); - sband = local->hw.wiphy->bands[status.band]; - if (status.flag & RX_FLAG_HT) { - /* TODO: HT rates */ - rate = sband->bitrates; - } else { - rate = &sband->bitrates - [status.rate_idx]; - } - __ieee80211_rx_handle_packet(hw, - tid_agg_rx->reorder_buf[index], - &status, rate); - tid_agg_rx->stored_mpdu_num--; - tid_agg_rx->reorder_buf[index] = NULL; - } - tid_agg_rx->head_seq_num = - seq_inc(tid_agg_rx->head_seq_num); + ieee80211_release_reorder_frame(hw, tid_agg_rx, + index); } if (bar_req) return 1; @@ -2380,19 +2384,7 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; while (tid_agg_rx->reorder_buf[index]) { - /* release the reordered frame back to stack */ - memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, - sizeof(status)); - sband = local->hw.wiphy->bands[status.band]; - if (status.flag & RX_FLAG_HT) - rate = sband->bitrates; /* TODO: HT rates */ - else - rate = &sband->bitrates[status.rate_idx]; - __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], - &status, rate); - tid_agg_rx->stored_mpdu_num--; - tid_agg_rx->reorder_buf[index] = NULL; - tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); + ieee80211_release_reorder_frame(hw, tid_agg_rx, index); index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; } -- cgit v1.2.3 From 4d050f1daed3babf6fcc337f862a245d31af4452 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 May 2009 20:35:14 +0300 Subject: mac80211: Add a timeout for frames in the RX reorder buffer This patch allows skbs to be released from the RX reorder buffer in case they have been there for an unexpectedly long time without us having received the missing frames before them. Previously, these frames were only released when the reorder window moved and that could take very long time unless new frames were received constantly (e.g., TCP connections could be killed more or less indefinitely). This situation should not happen very frequently, but it looks like there are some scenarious that trigger it for some reason. As such, this should be considered mostly a workaround to speed up recovery from unexpected siutation that could result in connections hanging for long periods of time. The changes here will only check for timeout situation when adding new RX frames to the reorder buffer. It does not handle all possible cases, but seems to help for most cases that could result from common network usage (e.g., TCP retrying at least couple of times). For more completely coverage, a timer could be used to periodically check whether there are any frames remaining in the reorder buffer if no new frames are received. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 8 +++++++- net/mac80211/rx.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- net/mac80211/sta_info.h | 2 ++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index fff24c3d6460..bc064d7933ff 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -68,6 +68,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, spin_lock_bh(&sta->lock); /* free resources */ kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); + kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { kfree(sta->ampdu_mlme.tid_rx[tid]); @@ -268,13 +269,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, /* prepare reordering buffer */ tid_agg_rx->reorder_buf = kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); - if (!tid_agg_rx->reorder_buf) { + tid_agg_rx->reorder_time = + kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); + if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) printk(KERN_ERR "can not allocate reordering buffer " "to tid %d\n", tid); #endif + kfree(tid_agg_rx->reorder_buf); + kfree(tid_agg_rx->reorder_time); kfree(sta->ampdu_mlme.tid_rx[tid]); + sta->ampdu_mlme.tid_rx[tid] = NULL; goto end; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9f2a29d1890b..24d41705ac0b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2312,6 +2312,15 @@ no_frame: } +/* + * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If + * the skb was added to the buffer longer than this time ago, the earlier + * frames that have not yet been received are assumed to be lost and the skb + * can be released for processing. This may also release other skb's from the + * reorder buffer if there are no additional gaps between the frames. + */ +#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) + /* * As it function blongs to Rx path it must be called with * the proper rcu_read_lock protection for its flow. @@ -2377,13 +2386,49 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, /* put the frame in the reordering buffer */ tid_agg_rx->reorder_buf[index] = skb; + tid_agg_rx->reorder_time[index] = jiffies; memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, sizeof(*rxstatus)); tid_agg_rx->stored_mpdu_num++; /* release the buffer until next missing frame */ index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; - while (tid_agg_rx->reorder_buf[index]) { + if (!tid_agg_rx->reorder_buf[index] && + tid_agg_rx->stored_mpdu_num > 1) { + /* + * No buffers ready to be released, but check whether any + * frames in the reorder buffer have timed out. + */ + int j; + int skipped = 1; + for (j = (index + 1) % tid_agg_rx->buf_size; j != index; + j = (j + 1) % tid_agg_rx->buf_size) { + if (tid_agg_rx->reorder_buf[j] == NULL) { + skipped++; + continue; + } + if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + + HZ / 10)) + break; + +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: release an RX reorder " + "frame due to timeout on earlier " + "frames\n", + wiphy_name(hw->wiphy)); +#endif + ieee80211_release_reorder_frame(hw, tid_agg_rx, j); + + /* + * Increment the head seq# also for the skipped slots. + */ + tid_agg_rx->head_seq_num = + (tid_agg_rx->head_seq_num + skipped) & + SEQ_MASK; + skipped = 0; + } + } else while (tid_agg_rx->reorder_buf[index]) { ieee80211_release_reorder_frame(hw, tid_agg_rx, index); index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 31a8990ce401..164b16cbe0a5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -88,6 +88,7 @@ struct tid_ampdu_tx { * struct tid_ampdu_rx - TID aggregation information (Rx). * * @reorder_buf: buffer to reorder incoming aggregated MPDUs + * @reorder_time: jiffies when skb was added * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer @@ -99,6 +100,7 @@ struct tid_ampdu_tx { */ struct tid_ampdu_rx { struct sk_buff **reorder_buf; + unsigned long *reorder_time; struct timer_list session_timer; u16 head_seq_num; u16 stored_mpdu_num; -- cgit v1.2.3 From aec6795210db6ba3f4592056d41ac5b1ab41e980 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 May 2009 20:35:15 +0300 Subject: mac80211: Comment the order of HT RX reorder handler vs. RX handlers We are currently processing block ack reordering as a separate task before all other RX handlers. In theory, this is wrong since this step should be done only after duplicate removal (see Figure 6-1 in IEEE 802.11n). However, moving this needs some work and the current situation is not too bad. Add a comment here so that this small detail does not get forgotten and who knows, maybe someone has some extra time to take a look at cleaning this up. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/rx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 24d41705ac0b..d052f4004829 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2551,6 +2551,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, return; } + /* + * In theory, the block ack reordering should happen after duplicate + * removal (ieee80211_rx_h_check(), which is an RX handler). As such, + * the call to ieee80211_rx_reorder_ampdu() should really be moved to + * happen as a new RX handler between ieee80211_rx_h_check and + * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for + * the time being, the call can be here since RX reorder buf processing + * will implicitly skip duplicates. We could, in theory at least, + * process frames that ieee80211_rx_h_passive_scan would drop (e.g., + * frames from other than operational channel), but that should not + * happen in normal networks. + */ if (!ieee80211_rx_reorder_ampdu(local, skb, status)) __ieee80211_rx_handle_packet(hw, skb, status, rate); -- cgit v1.2.3 From 7c5a189dc6a43def594fedc7cd8f6886596b65de Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 6 May 2009 01:47:02 +0400 Subject: p54: call p54_wake_free_queues on every p54_free_skb and p54_rx_frame_sent Currently queues are stopped when their length reaches their length limit, but are restarted only when the size of freed range of packet buffer is not less than the size of the largest possible packet. This causes permanent queue stop on radio visibility loss in the middle of ping series: there is plenty of room in the packet buffer, but it is never freed more than 3 (size of 'best effort' queue) * 288 (ping packet plus headers) bytes at once. Signed-off-by: Max Filippov Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b85785291803..48d81d98e12d 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -822,7 +822,6 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_tx_info *info; struct p54_tx_info *range; unsigned long flags; - u32 freed = 0, last_addr = priv->rx_start; if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) return; @@ -842,7 +841,6 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) ni = IEEE80211_SKB_CB(skb->prev); mr = (struct p54_tx_info *)ni->rate_driver_data; - last_addr = mr->end_addr; } if (skb->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; @@ -850,16 +848,11 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) ni = IEEE80211_SKB_CB(skb->next); mr = (struct p54_tx_info *)ni->rate_driver_data; - freed = mr->start_addr - last_addr; - } else - freed = priv->rx_end - last_addr; + } __skb_unlink(skb, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); dev_kfree_skb_any(skb); - - if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 + - IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom) - p54_wake_free_queues(dev); + p54_wake_free_queues(dev); } EXPORT_SYMBOL_GPL(p54_free_skb); @@ -893,8 +886,6 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct sk_buff *entry; u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom; struct p54_tx_info *range = NULL; - u32 freed = 0; - u32 last_addr = priv->rx_start; unsigned long flags; int count, idx; @@ -908,7 +899,6 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) range = (void *)info->rate_driver_data; if (range->start_addr != addr) { - last_addr = range->end_addr; entry = entry->next; continue; } @@ -919,11 +909,8 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) ni = IEEE80211_SKB_CB(entry->next); mr = (struct p54_tx_info *)ni->rate_driver_data; - freed = mr->start_addr - last_addr; - } else - freed = priv->rx_end - last_addr; + } - last_addr = range->end_addr; __skb_unlink(entry, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); @@ -1010,9 +997,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) spin_unlock_irqrestore(&priv->tx_queue.lock, flags); out: - if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 + - IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom) - p54_wake_free_queues(dev); + p54_wake_free_queues(dev); } static void p54_rx_eeprom_readback(struct ieee80211_hw *dev, -- cgit v1.2.3 From 4f0fc7c39f2a224b939f22d4dca552b266319525 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 6 May 2009 02:20:00 -0400 Subject: ath9k: make private driver rate tables const On x86 this allows us to do the following small savings: shave off 23 % off of the module's data, and shave off 6 % off of the module's text. We save 456 bytes, for those counting. $ size ath9k.ko text data bss dec hex filename 250794 3628 1600 256022 3e816 ath9k.ko $ size ath9k-old.ko text data bss dec hex filename 239114 15308 1600 256022 3e816 ath9k-old.ko $ du -b ath9k.ko 4034244 ath9k.ko $ du -b ath9k-old.ko 4033788 ath9k-old.ko Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 4 +-- drivers/net/wireless/ath/ath9k/beacon.c | 2 +- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 3 +- drivers/net/wireless/ath/ath9k/main.c | 2 +- drivers/net/wireless/ath/ath9k/rc.c | 61 +++++++++++++++++---------------- drivers/net/wireless/ath/ath9k/xmit.c | 8 ++--- 7 files changed, 43 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 90b6314a8169..10ffc9442859 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -576,8 +576,8 @@ struct ath_softc { struct ath_tx tx; struct ath_beacon beacon; struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; - struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; - struct ath_rate_table *cur_rate_table; + const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; + const struct ath_rate_table *cur_rate_table; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ath_led radio_led; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index c17b8382e328..3a7154beeae1 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -63,7 +63,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_hw *ah = sc->sc_ah; struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; - struct ath_rate_table *rt; + const struct ath_rate_table *rt; int flags, antenna, ctsrate = 0, ctsduration = 0; u8 rate; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 02f40154e831..041c0f518ac7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -168,7 +168,7 @@ bool ath9k_get_channel_edges(struct ath_hw *ah, } u16 ath9k_hw_computetxtime(struct ath_hw *ah, - struct ath_rate_table *rates, + const struct ath_rate_table *rates, u32 frameLen, u16 rateix, bool shortPreamble) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ab3412672e36..ddb24c47ebcf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -580,7 +580,8 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah, bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); u32 ath9k_hw_reverse_bits(u32 val, u32 n); bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); -u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates, +u16 ath9k_hw_computetxtime(struct ath_hw *ah, + const struct ath_rate_table *rates, u32 frameLen, u16 rateix, bool shortPreamble); void ath9k_hw_get_channel_centers(struct ath_hw *ah, struct ath9k_channel *chan, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d3dc8e2c77b2..bbbfdcde2727 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -189,7 +189,7 @@ static u8 parse_mpdudensity(u8 mpdudensity) static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) { - struct ath_rate_table *rate_table = NULL; + const struct ath_rate_table *rate_table = NULL; struct ieee80211_supported_band *sband; struct ieee80211_rate *rate; int i, maxrates; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e526dbce57d1..ba06e78b2f50 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -17,7 +17,7 @@ #include "ath9k.h" -static struct ath_rate_table ar5416_11na_ratetable = { +static const struct ath_rate_table ar5416_11na_ratetable = { 42, { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ @@ -155,7 +155,7 @@ static struct ath_rate_table ar5416_11na_ratetable = { /* 4ms frame limit not used for NG mode. The values filled * for HT are the 64K max aggregate limit */ -static struct ath_rate_table ar5416_11ng_ratetable = { +static const struct ath_rate_table ar5416_11ng_ratetable = { 46, { { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -302,7 +302,7 @@ static struct ath_rate_table ar5416_11ng_ratetable = { WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ }; -static struct ath_rate_table ar5416_11a_ratetable = { +static const struct ath_rate_table ar5416_11a_ratetable = { 8, { { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ @@ -335,7 +335,7 @@ static struct ath_rate_table ar5416_11a_ratetable = { 0, /* Phy rates allowed initially */ }; -static struct ath_rate_table ar5416_11g_ratetable = { +static const struct ath_rate_table ar5416_11g_ratetable = { 12, { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -380,7 +380,7 @@ static struct ath_rate_table ar5416_11g_ratetable = { 0, /* Phy rates allowed initially */ }; -static struct ath_rate_table ar5416_11b_ratetable = { +static const struct ath_rate_table ar5416_11b_ratetable = { 4, { { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ @@ -420,7 +420,7 @@ static inline int8_t median(int8_t a, int8_t b, int8_t c) } } -static void ath_rc_sort_validrates(struct ath_rate_table *rate_table, +static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv) { u8 i, j, idx, idx_next; @@ -461,10 +461,11 @@ static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, return ath_rc_priv->valid_rate_index[index]; } -static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, - u8 *next_idx) +static inline +int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, + struct ath_rate_priv *ath_rc_priv, + u8 cur_valid_txrate, + u8 *next_idx) { u8 i; @@ -500,7 +501,7 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) } static inline int -ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, +ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, u8 cur_valid_txrate, u8 *next_idx) { @@ -517,7 +518,7 @@ ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, } static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, u32 capflag) { u8 i, hi = 0; @@ -547,7 +548,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, } static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, struct ath_rateset *rateset, u32 capflag) { @@ -592,7 +593,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, } static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, u8 *mcs_set, u32 capflag) { struct ath_rateset *rateset = (struct ath_rateset *)mcs_set; @@ -630,7 +631,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, static u8 ath_rc_ratefind_ht(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, int *is_probing) { u32 dt, best_thruput, this_thruput, now_msec; @@ -748,7 +749,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, return rate; } -static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, +static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate, struct ieee80211_tx_rate_control *txrc, u8 tries, u8 rix, int rtsctsenable) @@ -769,7 +770,7 @@ static void ath_rc_rate_set_series(struct ath_rate_table *rate_table, } static void ath_rc_rate_set_rtscts(struct ath_softc *sc, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, struct ieee80211_tx_info *tx_info) { struct ieee80211_tx_rate *rates = tx_info->control.rates; @@ -807,7 +808,7 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, static u8 ath_rc_rate_getidx(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, u8 rix, u16 stepdown, u16 min_rate) { @@ -838,7 +839,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_tx_rate_control *txrc) { - struct ath_rate_table *rate_table; + const struct ath_rate_table *rate_table; struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; @@ -937,7 +938,7 @@ static void ath_rc_ratefind(struct ath_softc *sc, } static bool ath_rc_update_per(struct ath_softc *sc, - struct ath_rate_table *rate_table, + const struct ath_rate_table *rate_table, struct ath_rate_priv *ath_rc_priv, struct ath_tx_info_priv *tx_info_priv, int tx_rate, int xretries, int retries, @@ -1142,7 +1143,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, int rate; u8 last_per; bool state_change = false; - struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = sc->cur_rate_table; int size = ath_rc_priv->rate_table_size; if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) @@ -1276,7 +1277,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, #undef CHK_RSSI } -static int ath_rc_get_rateindex(struct ath_rate_table *rate_table, +static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate) { int rix; @@ -1300,7 +1301,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, int final_ts_idx, int xretries, int long_retry) { struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - struct ath_rate_table *rate_table; + const struct ath_rate_table *rate_table; struct ieee80211_tx_rate *rates = tx_info->status.rates; u8 flags; u32 i = 0, rix; @@ -1354,9 +1355,11 @@ static void ath_rc_tx_status(struct ath_softc *sc, xretries, long_retry); } -static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, - enum ieee80211_band band, - bool is_ht, bool is_cw_40) +static const +struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, + enum ieee80211_band band, + bool is_ht, + bool is_cw_40) { int mode = 0; @@ -1390,7 +1393,7 @@ static void ath_rc_init(struct ath_softc *sc, struct ath_rate_priv *ath_rc_priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, - struct ath_rate_table *rate_table) + const struct ath_rate_table *rate_table) { struct ath_rateset *rateset = &ath_rc_priv->neg_rates; u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; @@ -1587,7 +1590,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_rate_table *rate_table = NULL; + const struct ath_rate_table *rate_table = NULL; bool is_cw40, is_sgi40; int i, j = 0; @@ -1636,7 +1639,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_rate_table *rate_table = NULL; + const struct ath_rate_table *rate_table = NULL; bool oper_cw40 = false, oper_sgi40; bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? true : false; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 501493ffc3a7..41c42824a5ca 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -434,7 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, struct ath_atx_tid *tid) { - struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = sc->cur_rate_table; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; struct ieee80211_tx_rate *rates; @@ -497,7 +497,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, struct ath_buf *bf, u16 frmlen) { - struct ath_rate_table *rt = sc->cur_rate_table; + const struct ath_rate_table *rt = sc->cur_rate_table; struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); u32 nsymbits, nsymbols, mpdudensity; @@ -1407,7 +1407,7 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, int width, int half_gi, bool shortPreamble) { - struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = sc->cur_rate_table; u32 nbits, nsymbits, duration, nsymbols; u8 rc; int streams, pktlen; @@ -1439,7 +1439,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) { - struct ath_rate_table *rt = sc->cur_rate_table; + const struct ath_rate_table *rt = sc->cur_rate_table; struct ath9k_11n_rate_series series[4]; struct sk_buff *skb; struct ieee80211_tx_info *tx_info; -- cgit v1.2.3 From f9dd6b52873ad9fda51a3881c80c96d06ee6a57d Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 6 May 2009 09:47:30 +0200 Subject: ath9k: remove redundant AR9285 checks The AR_SREV_9285_1[12]_OR_LATER macros already contains the AR_SREV_9285 check. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 6 +++--- drivers/net/wireless/ath/ath9k/hw.c | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index a197041d76b5..a32d7e7fecbe 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -863,7 +863,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, } if (longcal) { - if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + if (AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah); if (OLC_FOR_AR9280_20_LATER) @@ -917,7 +917,7 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { - if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { + if (AR_SREV_9285_12_OR_LATER(ah)) { if (!ar9285_clc(ah, chan)) return false; } else { @@ -947,7 +947,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) } /* Do PA Calibration */ - if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) + if (AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah); /* Do NF Calibration after DC offset and other calibrations */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 041c0f518ac7..5879c731e9e7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1345,8 +1345,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, if (AR_SREV_9280(ah)) REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) && - AR_SREV_9285_12_OR_LATER(ah))) + if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah)) REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); for (i = 0; i < ah->iniCommon.ia_rows; i++) { -- cgit v1.2.3 From 9dfd6ba353b993d648dcda72480c7ce92cd27c7e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 May 2009 20:34:10 +0300 Subject: mac80211: Update SA Query transaction id length IEEE 802.11w/D8.0 changed the length of the SA Query transaction identifier from 16 to 2 octets. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index c52e7fba4e40..dc92359f37e6 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -543,7 +543,7 @@ struct ieee80211_tim_ie { u8 virtual_map[1]; } __attribute__ ((packed)); -#define WLAN_SA_QUERY_TR_ID_LEN 16 +#define WLAN_SA_QUERY_TR_ID_LEN 2 struct ieee80211_mgmt { __le16 frame_control; -- cgit v1.2.3 From 22527864ed7ee6c50f3c4d4b03c83c963caf5c0b Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 5 May 2009 19:05:06 +0000 Subject: netxen: fix race in tx ring acccess Fix the distance check between tx ring producer and consumer that could lead to tx ring wrap around. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 4 ++-- drivers/net/netxen/netxen_nic_init.c | 8 ++++---- drivers/net/netxen/netxen_nic_main.c | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 9f5ced3eaf9d..23c974a7e0e4 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -526,7 +526,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, producer = tx_ring->producer; consumer = tx_ring->sw_consumer; - if (nr_desc > find_diff_among(producer, consumer, tx_ring->num_desc)) { + if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) { netif_tx_unlock_bh(adapter->netdev); return -EBUSY; } @@ -752,7 +752,7 @@ int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); req.req_hdr = cpu_to_le64(word); - req.words[0] = cpu_to_le64(enable); + req.words[0] = cpu_to_le64(enable | (enable << 8)); rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); if (rv != 0) { diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index d18216779a09..de9ebbd841b7 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1319,10 +1319,11 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) break; } - if (count) { - tx_ring->sw_consumer = sw_consumer; + tx_ring->sw_consumer = sw_consumer; + + if (count && netif_running(netdev)) { smp_mb(); - if (netif_queue_stopped(netdev) && netif_running(netdev)) { + if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { netif_tx_lock(netdev); netif_wake_queue(netdev); smp_mb(); @@ -1450,7 +1451,6 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, rds_ring->producer = producer; NXWR32(adapter, rds_ring->crb_rcv_producer, (producer - 1) & (rds_ring->num_desc - 1)); - wmb(); } spin_unlock(&rds_ring->lock); } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 5d79c19a6ec0..6a496b1909eb 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -809,6 +809,7 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) { netif_carrier_off(netdev); netif_stop_queue(netdev); + smp_mb(); netxen_napi_disable(adapter); if (adapter->stop_port) @@ -1340,7 +1341,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) producer = tx_ring->producer; smp_mb(); consumer = tx_ring->sw_consumer; - if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) { + if ((no_of_desc+2) >= find_diff_among(producer, consumer, num_txd)) { netif_stop_queue(netdev); smp_mb(); return NETDEV_TX_BUSY; -- cgit v1.2.3 From 5cf4d323f8864dab818d500ec74f2fcb9ad5bf89 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 5 May 2009 19:05:07 +0000 Subject: netxen: fix mac list management o use standard linked list api for mac addr list management in NX3031. o release mac addresses in firmware in dev close(). Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 6 +- drivers/net/netxen/netxen_nic_hw.c | 124 ++++++++++++++--------------------- drivers/net/netxen/netxen_nic_main.c | 7 +- 3 files changed, 58 insertions(+), 79 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 8dacfbb003e2..d368e24c0235 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1019,8 +1019,8 @@ typedef struct { #define NETXEN_MAC_DEL 2 typedef struct nx_mac_list_s { - struct nx_mac_list_s *next; - uint8_t mac_addr[MAX_ADDR_LEN]; + struct list_head list; + uint8_t mac_addr[ETH_ALEN+2]; } nx_mac_list_t; /* @@ -1213,7 +1213,7 @@ struct netxen_adapter { struct net_device *netdev; struct pci_dev *pdev; - nx_mac_list_t *mac_list; + struct list_head mac_list; u32 curr_window; u32 crb_win; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 23c974a7e0e4..be643ea35233 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -470,45 +470,6 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) netxen_nic_set_mcast_addr(adapter, index, null_addr); } -static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, - u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list) -{ - nx_mac_list_t *cur, *prev; - - /* if in del_list, move it to adapter->mac_list */ - for (cur = *del_list, prev = NULL; cur;) { - if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { - if (prev == NULL) - *del_list = cur->next; - else - prev->next = cur->next; - cur->next = adapter->mac_list; - adapter->mac_list = cur; - return 0; - } - prev = cur; - cur = cur->next; - } - - /* make sure to add each mac address only once */ - for (cur = adapter->mac_list; cur; cur = cur->next) { - if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) - return 0; - } - /* not in del_list, create new entry and add to add_list */ - cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL); - if (cur == NULL) { - printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may" - "not work properly from now.\n", __func__); - return -1; - } - - memcpy(cur->mac_addr, addr, ETH_ALEN); - cur->next = *add_list; - *add_list = cur; - return 0; -} - static int netxen_send_cmd_descs(struct netxen_adapter *adapter, struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) @@ -555,14 +516,12 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, return 0; } -static int nx_p3_sre_macaddr_change(struct net_device *dev, - u8 *addr, unsigned op) +static int +nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op) { - struct netxen_adapter *adapter = netdev_priv(dev); nx_nic_req_t req; nx_mac_req_t *mac_req; u64 word; - int rv; memset(&req, 0, sizeof(nx_nic_req_t)); req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); @@ -574,28 +533,51 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev, mac_req->op = op; memcpy(mac_req->mac_addr, addr, 6); - rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); - if (rv != 0) { - printk(KERN_ERR "ERROR. Could not send mac update\n"); - return rv; + return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); +} + +static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, + u8 *addr, struct list_head *del_list) +{ + struct list_head *head; + nx_mac_list_t *cur; + + /* look up if already exists */ + list_for_each(head, del_list) { + cur = list_entry(head, nx_mac_list_t, list); + + if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { + list_move_tail(head, &adapter->mac_list); + return 0; + } } - return 0; + cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC); + if (cur == NULL) { + printk(KERN_ERR "%s: failed to add mac address filter\n", + adapter->netdev->name); + return -ENOMEM; + } + memcpy(cur->mac_addr, addr, ETH_ALEN); + list_add_tail(&cur->list, &adapter->mac_list); + return nx_p3_sre_macaddr_change(adapter, + cur->mac_addr, NETXEN_MAC_ADD); } void netxen_p3_nic_set_multi(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - nx_mac_list_t *cur, *next, *del_list, *add_list = NULL; struct dev_mc_list *mc_ptr; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; + LIST_HEAD(del_list); + struct list_head *head; + nx_mac_list_t *cur; - del_list = adapter->mac_list; - adapter->mac_list = NULL; + list_splice_tail_init(&adapter->mac_list, &del_list); - nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list); - nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list); + nx_p3_nic_add_mac(adapter, netdev->dev_addr, &del_list); + nx_p3_nic_add_mac(adapter, bcast_addr, &del_list); if (netdev->flags & IFF_PROMISC) { mode = VPORT_MISS_MODE_ACCEPT_ALL; @@ -611,25 +593,20 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) if (netdev->mc_count > 0) { for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { - nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, - &add_list, &del_list); + nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); } } send_fw_cmd: adapter->set_promisc(adapter, mode); - for (cur = del_list; cur;) { - nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL); - next = cur->next; + head = &del_list; + while (!list_empty(head)) { + cur = list_entry(head->next, nx_mac_list_t, list); + + nx_p3_sre_macaddr_change(adapter, + cur->mac_addr, NETXEN_MAC_DEL); + list_del(&cur->list); kfree(cur); - cur = next; - } - for (cur = add_list; cur;) { - nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD); - next = cur->next; - cur->next = adapter->mac_list; - adapter->mac_list = cur; - cur = next; } } @@ -654,14 +631,15 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) void netxen_p3_free_mac_list(struct netxen_adapter *adapter) { - nx_mac_list_t *cur, *next; - - cur = adapter->mac_list; - - while (cur) { - next = cur->next; + nx_mac_list_t *cur; + struct list_head *head = &adapter->mac_list; + + while (!list_empty(head)) { + cur = list_entry(head->next, nx_mac_list_t, list); + nx_p3_sre_macaddr_change(adapter, + cur->mac_addr, NETXEN_MAC_DEL); + list_del(&cur->list); kfree(cur); - cur = next; } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6a496b1909eb..a5577f8b6c0a 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -815,6 +815,9 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) if (adapter->stop_port) adapter->stop_port(adapter); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_p3_free_mac_list(adapter); + netxen_release_tx_buffers(adapter); FLUSH_SCHEDULED_WORK(); @@ -961,6 +964,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rwlock_init(&adapter->adapter_lock); spin_lock_init(&adapter->tx_clean_lock); + INIT_LIST_HEAD(&adapter->mac_list); err = netxen_setup_pci_map(adapter); if (err) @@ -1114,9 +1118,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { netxen_nic_detach(adapter); - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - netxen_p3_free_mac_list(adapter); } if (adapter->portnum == 0) -- cgit v1.2.3 From 3d0a3cc9d72047e4baa76021c897f64fc84cc543 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Tue, 5 May 2009 19:05:08 +0000 Subject: netxen: fix bonding support o Pause traffic during mac addr change. o Enable setting mac address for NX3031. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 6 +- drivers/net/netxen/netxen_nic_hw.c | 28 ++----- drivers/net/netxen/netxen_nic_hw.h | 10 --- drivers/net/netxen/netxen_nic_init.c | 7 +- drivers/net/netxen/netxen_nic_main.c | 45 +++++++--- drivers/net/netxen/netxen_nic_niu.c | 154 ++++++++--------------------------- 6 files changed, 82 insertions(+), 168 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index d368e24c0235..9350c8663fd8 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1264,9 +1264,10 @@ struct netxen_adapter { int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); - int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t); + int (*macaddr_set) (struct netxen_adapter *, u8 *); int (*set_mtu) (struct netxen_adapter *, int); int (*set_promisc) (struct netxen_adapter *, u32); + void (*set_multi) (struct net_device *); int (*phy_read) (struct netxen_adapter *, long reg, u32 *); int (*phy_write) (struct netxen_adapter *, long reg, u32 val); int (*init_port) (struct netxen_adapter *, int); @@ -1331,6 +1332,9 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu); int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu); +int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr); +int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr); + #define NXRD32(adapter, off) \ (adapter->hw_read_wx(adapter, off)) #define NXWR32(adapter, off, val) \ diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index be643ea35233..86c9e78ec39e 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -321,27 +321,6 @@ static unsigned crb_hub_agt[64] = #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ -int netxen_nic_set_mac(struct net_device *netdev, void *p) -{ - struct netxen_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (netif_running(netdev)) - return -EBUSY; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - - /* For P3, MAC addr is not set in NIU */ - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - if (adapter->macaddr_set) - adapter->macaddr_set(adapter, addr->sa_data); - - return 0; -} - #define NETXEN_UNICAST_ADDR(port, index) \ (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8)) #define NETXEN_MCAST_ADDR(port, index) \ @@ -643,6 +622,13 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter) } } +int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) +{ + /* assuming caller has already copied new addr to netdev */ + netxen_p3_nic_set_multi(adapter->netdev); + return 0; +} + #define NETXEN_CONFIG_INTR_COALESCE 3 /* diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index f20c96591a87..d4e833339781 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -42,8 +42,6 @@ struct netxen_adapter; void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); -typedef u8 netxen_ethernet_macaddr_t[6]; - /* Nibble or Byte mode for phy interface (GbE mode only) */ #define _netxen_crb_get_bit(var, bit) ((var >> bit) & 0x1) @@ -395,14 +393,6 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, u32 mode); -/* set the MAC address for a given MAC */ -int netxen_niu_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr); - -/* XG version */ -int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr); - /* Generic enable for GbE ports. Will detect the speed of the link. */ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index de9ebbd841b7..4a51c31330da 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -319,13 +319,15 @@ err_out: void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) { + adapter->macaddr_set = netxen_p2_nic_set_mac_addr; + adapter->set_multi = netxen_p2_nic_set_multi; + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: adapter->enable_phy_interrupts = netxen_niu_gbe_enable_phy_interrupts; adapter->disable_phy_interrupts = netxen_niu_gbe_disable_phy_interrupts; - adapter->macaddr_set = netxen_niu_macaddr_set; adapter->set_mtu = netxen_nic_set_mtu_gb; adapter->set_promisc = netxen_niu_set_promiscuous_mode; adapter->phy_read = netxen_niu_gbe_phy_read; @@ -339,7 +341,6 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) netxen_niu_xgbe_enable_phy_interrupts; adapter->disable_phy_interrupts = netxen_niu_xgbe_disable_phy_interrupts; - adapter->macaddr_set = netxen_niu_xg_macaddr_set; adapter->set_mtu = netxen_nic_set_mtu_xgb; adapter->init_port = netxen_niu_xg_init_port; adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode; @@ -353,6 +354,8 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { adapter->set_mtu = nx_fw_cmd_set_mtu; adapter->set_promisc = netxen_p3_nic_set_promisc; + adapter->macaddr_set = netxen_p3_nic_set_mac_addr; + adapter->set_multi = netxen_p3_nic_set_multi; } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index a5577f8b6c0a..83dadfd78c3c 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -442,20 +442,38 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) if (!is_valid_ether_addr(netdev->perm_addr)) dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr); - else - adapter->macaddr_set(adapter, netdev->dev_addr); return 0; } +int netxen_nic_set_mac(struct net_device *netdev, void *p) +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + if (netif_running(netdev)) { + netif_device_detach(netdev); + netxen_napi_disable(adapter); + } + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + adapter->macaddr_set(adapter, addr->sa_data); + + if (netif_running(netdev)) { + netif_device_attach(netdev); + netxen_napi_enable(adapter); + } + return 0; +} + static void netxen_set_multicast_list(struct net_device *dev) { struct netxen_adapter *adapter = netdev_priv(dev); - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - netxen_p3_nic_set_multi(dev); - else - netxen_p2_nic_set_multi(dev); + adapter->set_multi(dev); } static const struct net_device_ops netxen_netdev_ops = { @@ -782,16 +800,13 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) netxen_nic_driver_name, adapter->portnum); return err; } - adapter->macaddr_set(adapter, netdev->dev_addr); - - netxen_nic_set_link_parameters(adapter); + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + adapter->macaddr_set(adapter, netdev->dev_addr); - netxen_set_multicast_list(netdev); - if (adapter->set_mtu) - adapter->set_mtu(adapter, netdev->mtu); + adapter->set_multi(netdev); + adapter->set_mtu(adapter, netdev->mtu); adapter->ahw.linkup = 0; - mod_timer(&adapter->watchdog_timer, jiffies); netxen_napi_enable(adapter); @@ -800,6 +815,10 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) netxen_linkevent_request(adapter, 1); + else + netxen_nic_set_link_parameters(adapter); + + mod_timer(&adapter->watchdog_timer, jiffies); return 0; } diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index 5e2698bf575a..5941c79be723 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -402,76 +402,6 @@ int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) return 0; } -/* - * Return the current station MAC address. - * Note that the passed-in value must already be in network byte order. - */ -static int netxen_niu_macaddr_get(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t * addr) -{ - u32 stationhigh; - u32 stationlow; - int phy = adapter->physical_port; - u8 val[8]; - - if (addr == NULL) - return -EINVAL; - if ((phy < 0) || (phy > 3)) - return -EINVAL; - - stationhigh = NXRD32(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy)); - stationlow = NXRD32(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy)); - ((__le32 *)val)[1] = cpu_to_le32(stationhigh); - ((__le32 *)val)[0] = cpu_to_le32(stationlow); - - memcpy(addr, val + 2, 6); - - return 0; -} - -/* - * Set the station MAC address. - * Note that the passed-in value must already be in network byte order. - */ -int netxen_niu_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr) -{ - u8 temp[4]; - u32 val; - int phy = adapter->physical_port; - unsigned char mac_addr[6]; - int i; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - for (i = 0; i < 10; i++) { - temp[0] = temp[1] = 0; - memcpy(temp + 2, addr, 2); - val = le32_to_cpu(*(__le32 *)temp); - if (NXWR32(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), val)) - return -EIO; - - memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32)); - val = le32_to_cpu(*(__le32 *)temp); - if (NXWR32(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), val)) - return -2; - - netxen_niu_macaddr_get(adapter, - (netxen_ethernet_macaddr_t *) mac_addr); - if (memcmp(mac_addr, addr, 6) == 0) - break; - } - - if (i == 10) { - printk(KERN_ERR "%s: cannot set Mac addr for %s\n", - netxen_nic_driver_name, adapter->netdev->name); - printk(KERN_ERR "MAC address set: %pM.\n", addr); - printk(KERN_ERR "MAC address get: %pM.\n", mac_addr); - } - return 0; -} - /* Disable a GbE interface */ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) { @@ -561,57 +491,6 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, return 0; } -/* - * Set the MAC address for an XG port - * Note that the passed-in value must already be in network byte order. - */ -int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t addr) -{ - int phy = adapter->physical_port; - u8 temp[4]; - u32 val; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS)) - return -EIO; - - temp[0] = temp[1] = 0; - switch (phy) { - case 0: - memcpy(temp + 2, addr, 2); - val = le32_to_cpu(*(__le32 *)temp); - if (NXWR32(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, val)) - return -EIO; - - memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); - val = le32_to_cpu(*(__le32 *)temp); - if (NXWR32(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, val)) - return -EIO; - break; - - case 1: - memcpy(temp + 2, addr, 2); - val = le32_to_cpu(*(__le32 *)temp); - if (NXWR32(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1, val)) - return -EIO; - - memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); - val = le32_to_cpu(*(__le32 *)temp); - if (NXWR32(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI, val)) - return -EIO; - break; - - default: - printk(KERN_ERR "Unknown port %d\n", phy); - break; - } - - return 0; -} - int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, u32 mode) { @@ -636,3 +515,36 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, return 0; } + +int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) +{ + u32 mac_hi, mac_lo; + u32 reg_hi, reg_lo; + + u8 phy = adapter->physical_port; + u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ? + NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS; + + if (phy >= phy_count) + return -EINVAL; + + mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24); + mac_hi = addr[2] | ((u32)addr[3] << 8) | + ((u32)addr[4] << 16) | ((u32)addr[5] << 24); + + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { + reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy); + reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy); + } else { + reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy); + reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy); + } + + /* write twice to flush */ + if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) + return -EIO; + if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) + return -EIO; + + return 0; +} -- cgit v1.2.3 From 7eaa2b20ca0a471e1c73f72d8c6a0eac2c7838a7 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 6 May 2009 03:00:59 +0000 Subject: mv643xx_eth: fix variable shadowing sparse warning Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index a400d7115f78..352c77227a6f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1807,7 +1807,6 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev) if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { int port_num; u32 accept; - int i; oom: port_num = mp->port_num; -- cgit v1.2.3 From 26ef1f17d4741756763d1a399968ce17f236e2fb Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 6 May 2009 03:01:10 +0000 Subject: mv643xx_eth: count handling a link event as one unit of napi work Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 352c77227a6f..92a867cf8d56 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2178,6 +2178,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) if (mp->work_link) { mp->work_link = 0; handle_link_event(mp); + work_done++; continue; } -- cgit v1.2.3 From becfad979d1875aca15ef2a1eda68782e7ac7769 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 6 May 2009 03:01:17 +0000 Subject: mv643xx_eth: minor register definition cleanup Move the definitions for the SDMA and port serial configuration register values to where all the other register definitions live, and expand the shifts to 32 bit constants. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 92a867cf8d56..cc16f3e4d89c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -88,7 +88,24 @@ static char mv643xx_eth_driver_version[] = "1.4"; #define MAC_ADDR_LOW 0x0014 #define MAC_ADDR_HIGH 0x0018 #define SDMA_CONFIG 0x001c +#define TX_BURST_SIZE_16_64BIT 0x01000000 +#define TX_BURST_SIZE_4_64BIT 0x00800000 +#define BLM_TX_NO_SWAP 0x00000020 +#define BLM_RX_NO_SWAP 0x00000010 +#define RX_BURST_SIZE_16_64BIT 0x00000008 +#define RX_BURST_SIZE_4_64BIT 0x00000004 #define PORT_SERIAL_CONTROL 0x003c +#define SET_MII_SPEED_TO_100 0x01000000 +#define SET_GMII_SPEED_TO_1000 0x00800000 +#define SET_FULL_DUPLEX_MODE 0x00200000 +#define MAX_RX_PACKET_9700BYTE 0x000a0000 +#define DISABLE_AUTO_NEG_SPEED_GMII 0x00002000 +#define DO_NOT_FORCE_LINK_FAIL 0x00000400 +#define SERIAL_PORT_CONTROL_RESERVED 0x00000200 +#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL 0x00000008 +#define DISABLE_AUTO_NEG_FOR_DUPLEX 0x00000004 +#define FORCE_LINK_PASS 0x00000002 +#define SERIAL_PORT_ENABLE 0x00000001 #define PORT_STATUS 0x0044 #define TX_FIFO_EMPTY 0x00000400 #define TX_IN_PROGRESS 0x00000080 @@ -135,15 +152,8 @@ static char mv643xx_eth_driver_version[] = "1.4"; /* - * SDMA configuration register. + * SDMA configuration register default value. */ -#define RX_BURST_SIZE_4_64BIT (2 << 1) -#define RX_BURST_SIZE_16_64BIT (4 << 1) -#define BLM_RX_NO_SWAP (1 << 4) -#define BLM_TX_NO_SWAP (1 << 5) -#define TX_BURST_SIZE_4_64BIT (2 << 22) -#define TX_BURST_SIZE_16_64BIT (4 << 22) - #if defined(__BIG_ENDIAN) #define PORT_SDMA_CONFIG_DEFAULT_VALUE \ (RX_BURST_SIZE_4_64BIT | \ @@ -160,22 +170,10 @@ static char mv643xx_eth_driver_version[] = "1.4"; /* - * Port serial control register. + * Misc definitions. */ -#define SET_MII_SPEED_TO_100 (1 << 24) -#define SET_GMII_SPEED_TO_1000 (1 << 23) -#define SET_FULL_DUPLEX_MODE (1 << 21) -#define MAX_RX_PACKET_9700BYTE (5 << 17) -#define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13) -#define DO_NOT_FORCE_LINK_FAIL (1 << 10) -#define SERIAL_PORT_CONTROL_RESERVED (1 << 9) -#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1 << 3) -#define DISABLE_AUTO_NEG_FOR_DUPLEX (1 << 2) -#define FORCE_LINK_PASS (1 << 1) -#define SERIAL_PORT_ENABLE (1 << 0) - -#define DEFAULT_RX_QUEUE_SIZE 128 -#define DEFAULT_TX_QUEUE_SIZE 256 +#define DEFAULT_RX_QUEUE_SIZE 128 +#define DEFAULT_TX_QUEUE_SIZE 256 /* -- cgit v1.2.3 From 7fd96ce47ff83fc17ab78d465d8e067467a7f51e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 6 May 2009 03:01:22 +0000 Subject: mv643xx_eth: rework receive skb cache alignment On the platforms that mv643xx_eth is used on, the manual skb->data alignment logic in mv643xx_eth can be simplified, as the only case we need to handle is where NET_SKB_PAD is not a multiple of the cache line size. If this is the case, the extra padding we need can be computed at compile time, while if NET_SKB_PAD _is_ a multiple of the cache line size, the code can be optimised out entirely. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index cc16f3e4d89c..05bb1c55da66 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -174,6 +174,7 @@ static char mv643xx_eth_driver_version[] = "1.4"; */ #define DEFAULT_RX_QUEUE_SIZE 128 #define DEFAULT_TX_QUEUE_SIZE 256 +#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) /* @@ -649,23 +650,20 @@ static int rxq_refill(struct rx_queue *rxq, int budget) refilled = 0; while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) { struct sk_buff *skb; - int unaligned; int rx; struct rx_desc *rx_desc; skb = __skb_dequeue(&mp->rx_recycle); if (skb == NULL) - skb = dev_alloc_skb(mp->skb_size + - dma_get_cache_alignment() - 1); + skb = dev_alloc_skb(mp->skb_size); if (skb == NULL) { mp->oom = 1; goto oom; } - unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1); - if (unaligned) - skb_reserve(skb, dma_get_cache_alignment() - unaligned); + if (SKB_DMA_REALIGN) + skb_reserve(skb, SKB_DMA_REALIGN); refilled++; rxq->rx_desc_count++; @@ -964,8 +962,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) if (skb != NULL) { if (skb_queue_len(&mp->rx_recycle) < mp->rx_ring_size && - skb_recycle_check(skb, mp->skb_size + - dma_get_cache_alignment() - 1)) + skb_recycle_check(skb, mp->skb_size)) __skb_queue_head(&mp->rx_recycle, skb); else dev_kfree_skb(skb); @@ -2336,6 +2333,14 @@ static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) * size field are ignored by the hardware. */ mp->skb_size = (skb_size + 7) & ~7; + + /* + * If NET_SKB_PAD is smaller than a cache line, + * netdev_alloc_skb() will cause skb->data to be misaligned + * to a cache line boundary. If this is the case, include + * some extra space to allow re-aligning the data area. + */ + mp->skb_size += SKB_DMA_REALIGN; } static int mv643xx_eth_open(struct net_device *dev) -- cgit v1.2.3 From e0ca84105bca8691f39ef7ff221a88046ba11f23 Mon Sep 17 00:00:00 2001 From: Saeed Bishara Date: Wed, 6 May 2009 03:02:01 +0000 Subject: mv643xx_eth: only unmask RX and TX_END interrupts for available queues It is not a good idea to blindly unmask the RX and TX_END interrupts for all eight queues on all mv643xx_eth hardware, since some variations of the hardware have less than eight transmit/receive queues, and the RX/TX_END interrupts for the queues they don't have can be in use by other interrupt sources. Signed-off-by: Saeed Bishara Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 05bb1c55da66..d5838528791f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -123,7 +123,9 @@ static char mv643xx_eth_driver_version[] = "1.4"; #define TX_BW_BURST 0x005c #define INT_CAUSE 0x0060 #define INT_TX_END 0x07f80000 +#define INT_TX_END_0 0x00080000 #define INT_RX 0x000003fc +#define INT_RX_0 0x00000004 #define INT_EXT 0x00000002 #define INT_CAUSE_EXT 0x0064 #define INT_EXT_LINK_PHY 0x00110000 @@ -392,6 +394,7 @@ struct mv643xx_eth_private { struct work_struct tx_timeout_task; struct napi_struct napi; + u32 int_mask; u8 oom; u8 work_link; u8 work_tx; @@ -2058,15 +2061,16 @@ static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp) u32 int_cause; u32 int_cause_ext; - int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT); + int_cause = rdlp(mp, INT_CAUSE) & mp->int_mask; if (int_cause == 0) return 0; int_cause_ext = 0; - if (int_cause & INT_EXT) + if (int_cause & INT_EXT) { + int_cause &= ~INT_EXT; int_cause_ext = rdlp(mp, INT_CAUSE_EXT); + } - int_cause &= INT_TX_END | INT_RX; if (int_cause) { wrlp(mp, INT_CAUSE, ~int_cause); mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) & @@ -2212,7 +2216,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) if (mp->oom) mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); napi_complete(napi); - wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); + wrlp(mp, INT_MASK, mp->int_mask); } return work_done; @@ -2366,6 +2370,8 @@ static int mv643xx_eth_open(struct net_device *dev) skb_queue_head_init(&mp->rx_recycle); + mp->int_mask = INT_EXT; + for (i = 0; i < mp->rxq_count; i++) { err = rxq_init(mp, i); if (err) { @@ -2375,6 +2381,7 @@ static int mv643xx_eth_open(struct net_device *dev) } rxq_refill(mp->rxq + i, INT_MAX); + mp->int_mask |= INT_RX_0 << i; } if (mp->oom) { @@ -2389,12 +2396,13 @@ static int mv643xx_eth_open(struct net_device *dev) txq_deinit(mp->txq + i); goto out_free; } + mp->int_mask |= INT_TX_END_0 << i; } port_start(mp); wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); - wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); + wrlp(mp, INT_MASK, mp->int_mask); return 0; @@ -2538,7 +2546,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev) mv643xx_eth_irq(dev->irq, dev); - wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); + wrlp(mp, INT_MASK, mp->int_mask); } #endif -- cgit v1.2.3 From 0364d6fd2c353d2d82da865a6f093f97c69b669c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 May 2009 10:25:01 +0000 Subject: igbvf: cleanup flags and allow for rx checksum to be disabled This patch cleans up a number of unused or unneeded feature flags. As a result of these changes the user should now be able to enable or disable rx checksumming via ethtool. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igbvf/ethtool.c | 36 ++++++++++++++++++++---------------- drivers/net/igbvf/igbvf.h | 6 +----- drivers/net/igbvf/netdev.c | 17 +++++------------ 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index 1dcaa6905312..ee17a097d1ca 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -133,6 +133,24 @@ static int igbvf_set_pauseparam(struct net_device *netdev, return -EOPNOTSUPP; } +static u32 igbvf_get_rx_csum(struct net_device *netdev) +{ + struct igbvf_adapter *adapter = netdev_priv(netdev); + return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED); +} + +static int igbvf_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct igbvf_adapter *adapter = netdev_priv(netdev); + + if (data) + adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED; + else + adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED; + + return 0; +} + static u32 igbvf_get_tx_csum(struct net_device *netdev) { return ((netdev->features & NETIF_F_IP_CSUM) != 0); @@ -150,8 +168,6 @@ static int igbvf_set_tx_csum(struct net_device *netdev, u32 data) static int igbvf_set_tso(struct net_device *netdev, u32 data) { struct igbvf_adapter *adapter = netdev_priv(netdev); - int i; - struct net_device *v_netdev; if (data) { netdev->features |= NETIF_F_TSO; @@ -159,24 +175,10 @@ static int igbvf_set_tso(struct net_device *netdev, u32 data) } else { netdev->features &= ~NETIF_F_TSO; netdev->features &= ~NETIF_F_TSO6; - /* disable TSO on all VLANs if they're present */ - if (!adapter->vlgrp) - goto tso_out; - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { - v_netdev = vlan_group_get_device(adapter->vlgrp, i); - if (!v_netdev) - continue; - - v_netdev->features &= ~NETIF_F_TSO; - v_netdev->features &= ~NETIF_F_TSO6; - vlan_group_set_device(adapter->vlgrp, i, v_netdev); - } } -tso_out: dev_info(&adapter->pdev->dev, "TSO is %s\n", data ? "Enabled" : "Disabled"); - adapter->flags |= FLAG_TSO_FORCE; return 0; } @@ -517,6 +519,8 @@ static const struct ethtool_ops igbvf_ethtool_ops = { .set_ringparam = igbvf_set_ringparam, .get_pauseparam = igbvf_get_pauseparam, .set_pauseparam = igbvf_set_pauseparam, + .get_rx_csum = igbvf_get_rx_csum, + .set_rx_csum = igbvf_set_rx_csum, .get_tx_csum = igbvf_get_tx_csum, .set_tx_csum = igbvf_set_tx_csum, .get_sg = ethtool_op_get_sg, diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index 4bff35e46871..2ad6cd756539 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -286,11 +286,7 @@ struct igbvf_info { }; /* hardware capability, feature, and workaround flags */ -#define FLAG_HAS_HW_VLAN_FILTER (1 << 0) -#define FLAG_HAS_JUMBO_FRAMES (1 << 1) -#define FLAG_MSI_ENABLED (1 << 2) -#define FLAG_RX_CSUM_ENABLED (1 << 3) -#define FLAG_TSO_FORCE (1 << 4) +#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0) #define IGBVF_RX_DESC_ADV(R, i) \ (&((((R).desc))[i].rx_desc)) diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index b774666ad3cf..44a8eef03a74 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -58,8 +58,7 @@ static void igbvf_reset_interrupt_capability(struct igbvf_adapter *); static struct igbvf_info igbvf_vf_info = { .mac = e1000_vfadapt, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_RX_CSUM_ENABLED, + .flags = 0, .pba = 10, .init_ops = e1000_init_function_pointers_vf, }; @@ -107,8 +106,10 @@ static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, skb->ip_summed = CHECKSUM_NONE; /* Ignore Checksum bit is set or checksum is disabled through ethtool */ - if ((status_err & E1000_RXD_STAT_IXSM)) + if ((status_err & E1000_RXD_STAT_IXSM) || + (adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED)) return; + /* TCP/UDP checksum error bit is set */ if (status_err & (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { @@ -116,6 +117,7 @@ static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, adapter->hw_csum_err++; return; } + /* It must be a TCP or UDP packet with a valid checksum */ if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2351,15 +2353,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } - /* Jumbo frame size limits */ - if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { - if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - dev_err(&adapter->pdev->dev, - "Jumbo Frames not supported.\n"); - return -EINVAL; - } - } - #define MAX_STD_JUMBO_FRAME_SIZE 9234 if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n"); -- cgit v1.2.3 From 7beb0146fc965ffee928eff53525aac0173b0b07 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 May 2009 10:25:23 +0000 Subject: igb/igbvf: set rx csum always enabled in hw, disable via sw An issue was found in which rx checksum could not be enabled without resetting the interface. The issue was the hardware enable was not being done via ethtool. To resolve this issue and prevent conflicts with VF configuration we will leave the feature always enabled in hardware, and then in software we will choose to ignore the results via a sw flag. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 2 +- drivers/net/igb/igb_ethtool.c | 8 ++++++-- drivers/net/igb/igb_main.c | 12 +++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 4e8464b9df2e..154c5acc6fce 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -238,7 +238,6 @@ struct igb_adapter { u64 hw_csum_err; u64 hw_csum_good; u32 alloc_rx_buff_failed; - bool rx_csum; u32 gorc; u64 gorc_old; u16 rx_ps_hdr_size; @@ -286,6 +285,7 @@ struct igb_adapter { #define IGB_FLAG_DCA_ENABLED (1 << 1) #define IGB_FLAG_QUAD_PORT_A (1 << 2) #define IGB_FLAG_NEED_CTX_IDX (1 << 3) +#define IGB_FLAG_RX_CSUM_DISABLED (1 << 4) enum e1000_state_t { __IGB_TESTING, diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index b1367ce6586e..b8551a57dd3f 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -275,13 +275,17 @@ static int igb_set_pauseparam(struct net_device *netdev, static u32 igb_get_rx_csum(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); - return adapter->rx_csum; + return !(adapter->flags & IGB_FLAG_RX_CSUM_DISABLED); } static int igb_set_rx_csum(struct net_device *netdev, u32 data) { struct igb_adapter *adapter = netdev_priv(netdev); - adapter->rx_csum = data; + + if (data) + adapter->flags &= ~IGB_FLAG_RX_CSUM_DISABLED; + else + adapter->flags |= IGB_FLAG_RX_CSUM_DISABLED; return 0; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index bca7e9f76be4..8de8629b07ec 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1395,8 +1395,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, igb_validate_mdi_setting(hw); - adapter->rx_csum = 1; - /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM, * enable the ACPI Magic Packet filter */ @@ -2249,13 +2247,12 @@ static void igb_configure_rx(struct igb_adapter *adapter) rxcsum = rd32(E1000_RXCSUM); /* Disable raw packet checksumming */ rxcsum |= E1000_RXCSUM_PCSD; - /* Don't need to set TUOFL or IPOFL, they default to 1 */ - if (!adapter->rx_csum) - rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL); - else if (adapter->hw.mac.type == e1000_82576) + + if (adapter->hw.mac.type == e1000_82576) /* Enable Receive Checksum Offload for SCTP */ rxcsum |= E1000_RXCSUM_CRCOFL; + /* Don't need to set TUOFL or IPOFL, they default to 1 */ wr32(E1000_RXCSUM, rxcsum); /* Set the default pool for the PF's first queue */ @@ -4455,7 +4452,8 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter, skb->ip_summed = CHECKSUM_NONE; /* Ignore Checksum bit is set or checksum is disabled through ethtool */ - if ((status_err & E1000_RXD_STAT_IXSM) || !adapter->rx_csum) + if ((status_err & E1000_RXD_STAT_IXSM) || + (adapter->flags & IGB_FLAG_RX_CSUM_DISABLED)) return; /* TCP/UDP checksum error bit is set */ if (status_err & -- cgit v1.2.3 From dcb4ea2ea2ba990a59db5a4cc402df3c2bd389b3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 May 2009 10:25:42 +0000 Subject: pci: update 82576 sr-iov quirk with latest device IDs The current quirk doesn't include all 82576 device IDs. This update resolves that. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/pci/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0254741bece0..c01c1196d45e 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2460,6 +2460,8 @@ static void __devinit quirk_i82576_sriov(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); #endif /* CONFIG_PCI_IOV */ -- cgit v1.2.3 From 7a921c93626e7481b5d8788d8511995aa2d2b591 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 May 2009 10:43:28 +0000 Subject: ixgbe: make q_vectors dynamic to reduce netdev size Currently the q_vectors are being allocated statically inside of the adapter struct. This increases the overall size of the adapter struct when we can easily allocate the vectors dynamically. This patch changes that behavior so that the q_vectors are allocated dynamically and the napi structures are automatically allocated inside of the q_vectors as needed. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 5 +- drivers/net/ixgbe/ixgbe_dcb_nl.c | 16 +-- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 268 +++++++++++++++++++++----------------- 4 files changed, 158 insertions(+), 133 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 4b44a8efac8c..61cb4153a183 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -187,6 +187,7 @@ struct ixgbe_q_vector { u8 tx_itr; u8 rx_itr; u32 eitr; + u32 v_idx; /* vector index in list */ }; /* Helper macros to switch between ints/sec and what the register uses. @@ -230,7 +231,7 @@ struct ixgbe_adapter { struct vlan_group *vlgrp; u16 bd_number; struct work_struct reset_task; - struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS]; + struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; char name[MAX_MSIX_COUNT][IFNAMSIZ + 9]; struct ixgbe_dcb_config dcb_cfg; struct ixgbe_dcb_config temp_dcb_cfg; @@ -367,8 +368,8 @@ extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *) extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); -extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); +extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); void ixgbe_napi_add_all(struct ixgbe_adapter *adapter); void ixgbe_napi_del_all(struct ixgbe_adapter *adapter); extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32); diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index bd0a0c276952..99e0c106e671 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -124,13 +124,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); - ixgbe_reset_interrupt_capability(adapter); - ixgbe_napi_del_all(adapter); - INIT_LIST_HEAD(&netdev->napi_list); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - adapter->tx_ring = NULL; - adapter->rx_ring = NULL; + ixgbe_clear_interrupt_scheme(adapter); adapter->hw.fc.requested_mode = ixgbe_fc_pfc; adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; @@ -144,13 +138,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->hw.fc.requested_mode = ixgbe_fc_default; if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); - ixgbe_reset_interrupt_capability(adapter); - ixgbe_napi_del_all(adapter); - INIT_LIST_HEAD(&netdev->napi_list); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - adapter->tx_ring = NULL; - adapter->rx_ring = NULL; + ixgbe_clear_interrupt_scheme(adapter); adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index d822c92058c3..c0167d617b1e 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1114,7 +1114,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, } for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; + struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; if (q_vector->txr_count && !q_vector->rxr_count) /* tx vector gets half the rate */ q_vector->eitr = (adapter->eitr_param >> 1); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index be5eabce9e35..165bfa600b4b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -468,7 +468,7 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]); + skb_record_rx_queue(skb, q_vector->v_idx); if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag != 0)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); @@ -835,7 +835,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) * corresponding register. */ for (v_idx = 0; v_idx < q_vectors; v_idx++) { - q_vector = &adapter->q_vector[v_idx]; + q_vector = adapter->q_vector[v_idx]; /* XXX for_each_bit(...) */ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); @@ -984,8 +984,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) struct ixgbe_adapter *adapter = q_vector->adapter; u32 new_itr; u8 current_itr, ret_itr; - int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) / - sizeof(struct ixgbe_q_vector); + int i, r_idx, v_idx = q_vector->v_idx; struct ixgbe_ring *rx_ring, *tx_ring; r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); @@ -1303,19 +1302,21 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget) static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, int r_idx) { - a->q_vector[v_idx].adapter = a; - set_bit(r_idx, a->q_vector[v_idx].rxr_idx); - a->q_vector[v_idx].rxr_count++; + struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; + + set_bit(r_idx, q_vector->rxr_idx); + q_vector->rxr_count++; a->rx_ring[r_idx].v_idx = 1 << v_idx; } static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, - int r_idx) + int t_idx) { - a->q_vector[v_idx].adapter = a; - set_bit(r_idx, a->q_vector[v_idx].txr_idx); - a->q_vector[v_idx].txr_count++; - a->tx_ring[r_idx].v_idx = 1 << v_idx; + struct ixgbe_q_vector *q_vector = a->q_vector[v_idx]; + + set_bit(t_idx, q_vector->txr_idx); + q_vector->txr_count++; + a->tx_ring[t_idx].v_idx = 1 << v_idx; } /** @@ -1411,7 +1412,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \ &ixgbe_msix_clean_many) for (vector = 0; vector < q_vectors; vector++) { - handler = SET_HANDLER(&adapter->q_vector[vector]); + handler = SET_HANDLER(adapter->q_vector[vector]); if(handler == &ixgbe_msix_clean_rx) { sprintf(adapter->name[vector], "%s-%s-%d", @@ -1427,7 +1428,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) err = request_irq(adapter->msix_entries[vector].vector, handler, 0, adapter->name[vector], - &(adapter->q_vector[vector])); + adapter->q_vector[vector]); if (err) { DPRINTK(PROBE, ERR, "request_irq failed for MSIX interrupt " @@ -1450,7 +1451,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) free_queue_irqs: for (i = vector - 1; i >= 0; i--) free_irq(adapter->msix_entries[--vector].vector, - &(adapter->q_vector[i])); + adapter->q_vector[i]); adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); @@ -1461,7 +1462,7 @@ out: static void ixgbe_set_itr(struct ixgbe_adapter *adapter) { - struct ixgbe_q_vector *q_vector = adapter->q_vector; + struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; u8 current_itr; u32 new_itr = q_vector->eitr; struct ixgbe_ring *rx_ring = &adapter->rx_ring[0]; @@ -1539,6 +1540,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data) struct net_device *netdev = data; struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; u32 eicr; /* @@ -1566,13 +1568,13 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); - if (napi_schedule_prep(&adapter->q_vector[0].napi)) { + if (napi_schedule_prep(&(q_vector->napi))) { adapter->tx_ring[0].total_packets = 0; adapter->tx_ring[0].total_bytes = 0; adapter->rx_ring[0].total_packets = 0; adapter->rx_ring[0].total_bytes = 0; /* would disable interrupts here but EIAM disabled it */ - __napi_schedule(&adapter->q_vector[0].napi); + __napi_schedule(&(q_vector->napi)); } return IRQ_HANDLED; @@ -1583,7 +1585,7 @@ static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter) int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; for (i = 0; i < q_vectors; i++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[i]; + struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES); bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES); q_vector->rxr_count = 0; @@ -1634,7 +1636,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) i--; for (; i >= 0; i--) { free_irq(adapter->msix_entries[i].vector, - &(adapter->q_vector[i])); + adapter->q_vector[i]); } ixgbe_reset_q_vectors(adapter); @@ -2135,7 +2137,7 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) for (q_idx = 0; q_idx < q_vectors; q_idx++) { struct napi_struct *napi; - q_vector = &adapter->q_vector[q_idx]; + q_vector = adapter->q_vector[q_idx]; if (!q_vector->rxr_count) continue; napi = &q_vector->napi; @@ -2158,7 +2160,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) q_vectors = 1; for (q_idx = 0; q_idx < q_vectors; q_idx++) { - q_vector = &adapter->q_vector[q_idx]; + q_vector = adapter->q_vector[q_idx]; if (!q_vector->rxr_count) continue; napi_disable(&q_vector->napi); @@ -2498,8 +2500,6 @@ int ixgbe_up(struct ixgbe_adapter *adapter) /* hardware has been reset, we need to reload some things */ ixgbe_configure(adapter); - ixgbe_napi_add_all(adapter); - return ixgbe_up_complete(adapter); } @@ -2877,9 +2877,6 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; kfree(adapter->msix_entries); adapter->msix_entries = NULL; - adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; - adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; - ixgbe_set_num_queues(adapter); } else { adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */ /* @@ -3103,31 +3100,20 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) * mean we disable MSI-X capabilities of the adapter. */ adapter->msix_entries = kcalloc(v_budget, sizeof(struct msix_entry), GFP_KERNEL); - if (!adapter->msix_entries) { - adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; - adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; - ixgbe_set_num_queues(adapter); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - err = ixgbe_alloc_queues(adapter); - if (err) { - DPRINTK(PROBE, ERR, "Unable to allocate memory " - "for queues\n"); - goto out; - } - - goto try_msi; - } + if (adapter->msix_entries) { + for (vector = 0; vector < v_budget; vector++) + adapter->msix_entries[vector].entry = vector; - for (vector = 0; vector < v_budget; vector++) - adapter->msix_entries[vector].entry = vector; + ixgbe_acquire_msix_vectors(adapter, v_budget); - ixgbe_acquire_msix_vectors(adapter, v_budget); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) + goto out; + } - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) - goto out; + adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; + adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; + ixgbe_set_num_queues(adapter); -try_msi: err = pci_enable_msi(adapter->pdev); if (!err) { adapter->flags |= IXGBE_FLAG_MSI_ENABLED; @@ -3142,6 +3128,87 @@ out: return err; } +/** + * ixgbe_alloc_q_vectors - Allocate memory for interrupt vectors + * @adapter: board private structure to initialize + * + * We allocate one q_vector per queue interrupt. If allocation fails we + * return -ENOMEM. + **/ +static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) +{ + int q_idx, num_q_vectors; + struct ixgbe_q_vector *q_vector; + int napi_vectors; + int (*poll)(struct napi_struct *, int); + + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + napi_vectors = adapter->num_rx_queues; + poll = &ixgbe_clean_rxonly; + } else { + num_q_vectors = 1; + napi_vectors = 1; + poll = &ixgbe_poll; + } + + for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { + q_vector = kzalloc(sizeof(struct ixgbe_q_vector), GFP_KERNEL); + if (!q_vector) + goto err_out; + q_vector->adapter = adapter; + q_vector->v_idx = q_idx; + q_vector->eitr = adapter->eitr_param; + if (q_idx < napi_vectors) + netif_napi_add(adapter->netdev, &q_vector->napi, + (*poll), 64); + adapter->q_vector[q_idx] = q_vector; + } + + return 0; + +err_out: + while (q_idx) { + q_idx--; + q_vector = adapter->q_vector[q_idx]; + netif_napi_del(&q_vector->napi); + kfree(q_vector); + adapter->q_vector[q_idx] = NULL; + } + return -ENOMEM; +} + +/** + * ixgbe_free_q_vectors - Free memory allocated for interrupt vectors + * @adapter: board private structure to initialize + * + * This function frees the memory allocated to the q_vectors. In addition if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + **/ +static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter) +{ + int q_idx, num_q_vectors; + int napi_vectors; + + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + napi_vectors = adapter->num_rx_queues; + } else { + num_q_vectors = 1; + napi_vectors = 1; + } + + for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { + struct ixgbe_q_vector *q_vector = adapter->q_vector[q_idx]; + + adapter->q_vector[q_idx] = NULL; + if (q_idx < napi_vectors) + netif_napi_del(&q_vector->napi); + kfree(q_vector); + } +} + void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) { if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { @@ -3173,18 +3240,25 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) /* Number of supported queues */ ixgbe_set_num_queues(adapter); - err = ixgbe_alloc_queues(adapter); - if (err) { - DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); - goto err_alloc_queues; - } - err = ixgbe_set_interrupt_capability(adapter); if (err) { DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n"); goto err_set_interrupt; } + err = ixgbe_alloc_q_vectors(adapter); + if (err) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queue " + "vectors\n"); + goto err_alloc_q_vectors; + } + + err = ixgbe_alloc_queues(adapter); + if (err) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + goto err_alloc_queues; + } + DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, " "Tx Queue count = %u\n", (adapter->num_rx_queues > 1) ? "Enabled" : @@ -3194,11 +3268,30 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) return 0; +err_alloc_queues: + ixgbe_free_q_vectors(adapter); +err_alloc_q_vectors: + ixgbe_reset_interrupt_capability(adapter); err_set_interrupt: + return err; +} + +/** + * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings + * @adapter: board private structure to clear interrupt scheme on + * + * We go through and clear interrupt specific resources and reset the structure + * to pre-load conditions + **/ +void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) +{ kfree(adapter->tx_ring); kfree(adapter->rx_ring); -err_alloc_queues: - return err; + adapter->tx_ring = NULL; + adapter->rx_ring = NULL; + + ixgbe_free_q_vectors(adapter); + ixgbe_reset_interrupt_capability(adapter); } /** @@ -3619,8 +3712,6 @@ static int ixgbe_open(struct net_device *netdev) ixgbe_configure(adapter); - ixgbe_napi_add_all(adapter); - err = ixgbe_request_irq(adapter); if (err) goto err_req_irq; @@ -3672,55 +3763,6 @@ static int ixgbe_close(struct net_device *netdev) return 0; } -/** - * ixgbe_napi_add_all - prep napi structs for use - * @adapter: private struct - * - * helper function to napi_add each possible q_vector->napi - */ -void ixgbe_napi_add_all(struct ixgbe_adapter *adapter) -{ - int q_idx, q_vectors; - struct net_device *netdev = adapter->netdev; - int (*poll)(struct napi_struct *, int); - - /* check if we already have our netdev->napi_list populated */ - if (&netdev->napi_list != netdev->napi_list.next) - return; - - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - poll = &ixgbe_clean_rxonly; - /* Only enable as many vectors as we have rx queues. */ - q_vectors = adapter->num_rx_queues; - } else { - poll = &ixgbe_poll; - /* only one q_vector for legacy modes */ - q_vectors = 1; - } - - for (q_idx = 0; q_idx < q_vectors; q_idx++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; - netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); - } -} - -void ixgbe_napi_del_all(struct ixgbe_adapter *adapter) -{ - int q_idx; - int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - - /* legacy and MSI only use one vector */ - if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) - q_vectors = 1; - - for (q_idx = 0; q_idx < q_vectors; q_idx++) { - struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx]; - if (!q_vector->rxr_count) - continue; - netif_napi_del(&q_vector->napi); - } -} - #ifdef CONFIG_PM static int ixgbe_resume(struct pci_dev *pdev) { @@ -3782,11 +3824,7 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) ixgbe_free_all_tx_resources(adapter); ixgbe_free_all_rx_resources(adapter); } - ixgbe_reset_interrupt_capability(adapter); - ixgbe_napi_del_all(adapter); - INIT_LIST_HEAD(&netdev->napi_list); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); + ixgbe_clear_interrupt_scheme(adapter); #ifdef CONFIG_PM retval = pci_save_state(pdev); @@ -5012,8 +5050,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, err_register: ixgbe_release_hw_control(adapter); err_hw_init: + ixgbe_clear_interrupt_scheme(adapter); err_sw_init: - ixgbe_reset_interrupt_capability(adapter); err_eeprom: clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); del_timer_sync(&adapter->sfp_timer); @@ -5071,7 +5109,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); - ixgbe_reset_interrupt_capability(adapter); + ixgbe_clear_interrupt_scheme(adapter); ixgbe_release_hw_control(adapter); @@ -5079,8 +5117,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) pci_release_regions(pdev); DPRINTK(PROBE, INFO, "complete\n"); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); free_netdev(netdev); -- cgit v1.2.3 From fdaff1ceac32e1748353e91a420c18141ea153c0 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 May 2009 10:43:47 +0000 Subject: ixgbe: skb_record_rx_queue should record rx queue instead of vector currently ixgbe_receive_skb is passing the vector index to skb_record_rx_queue instead of the queue index. This patch changes that so that the ring index is passed instead. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 165bfa600b4b..2c70fa0add3e 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -461,6 +461,7 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) **/ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, struct sk_buff *skb, u8 status, + struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { struct ixgbe_adapter *adapter = q_vector->adapter; @@ -468,7 +469,7 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector, bool is_vlan = (status & IXGBE_RXD_STAT_VP); u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); - skb_record_rx_queue(skb, q_vector->v_idx); + skb_record_rx_queue(skb, ring->queue_index); if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { if (adapter->vlgrp && is_vlan && (tag != 0)) vlan_gro_receive(napi, adapter->vlgrp, tag, skb); @@ -782,7 +783,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, total_rx_packets++; skb->protocol = eth_type_trans(skb, adapter->netdev); - ixgbe_receive_skb(q_vector, skb, staterr, rx_desc); + ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc); next_desc: rx_desc->wb.upper.status_error = 0; -- cgit v1.2.3 From 2012bdc8a5553fc864e78f582c8ce79e762dec42 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 6 May 2009 10:44:07 +0000 Subject: ixgbe: remove ixgbe_napi_add/del_all references There were still some references to napi_add/del_all left after the dynamic vector allocation patch. This patch removes those references since the ixgbe_napi_add/del_all calls are no longer needed as the napi struct is added when the vector is created, and deleted when the vector is freed. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 61cb4153a183..d743d0ed5c2e 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -370,8 +370,6 @@ extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *) extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); -void ixgbe_napi_add_all(struct ixgbe_adapter *adapter); -void ixgbe_napi_del_all(struct ixgbe_adapter *adapter); extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32); #endif /* _IXGBE_H_ */ -- cgit v1.2.3 From 3044b8d1ff8c05237652a692fb572a34e4d70146 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 6 May 2009 10:44:26 +0000 Subject: ixgbe: Return PCI_ERS_RESULT_DISCONNECT when bus is disabled According to the "PCI Error Recovery" document, if after a recovery, the bus is disabled, the error_detected function should return PCI_ERS_RESULT_DISCONNECT. Actually ixgbe error_detected function is always returning PCI_ERS_RESULT_NEED_RESET, even if the bus is in failure. This patch just check if the bus is disabled and then returns PCI_ERS_RESULT_DISCONNET. Signed-off-by: Breno Leitao Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2c70fa0add3e..dd56adb2191a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5145,6 +5145,9 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, netif_device_detach(netdev); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + if (netif_running(netdev)) ixgbe_down(adapter); pci_disable_device(pdev); -- cgit v1.2.3 From 9ce77666da48513058e330634a766d4752324f8e Mon Sep 17 00:00:00 2001 From: gouji-new Date: Wed, 6 May 2009 10:44:45 +0000 Subject: ixgbe: Proposed PARCH PCIE legacy I/O port free intel 10Gb NIC driver Traditionally Intel based NIC drivers request I/O port even though it doesn't need that really. Intel PCIE 10Gb driver (ixgbe) also requests I/O port but it doesn't need it either. This is a little inconvenient situation because sometimes we have to handle those cards on the slots where any I/O space is not attached. So we made pach which makes ixgbe driver legacy I/O port free. Signed-off-by: Masayuki Gouji Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index dd56adb2191a..08f4a13a602f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3773,7 +3773,8 @@ static int ixgbe_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - err = pci_enable_device(pdev); + + err = pci_enable_device_mem(pdev); if (err) { printk(KERN_ERR "ixgbe: Cannot enable PCI device from " "suspend\n"); @@ -4778,7 +4779,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, int i, err, pci_using_dac; u32 part_num, eec; - err = pci_enable_device(pdev); + err = pci_enable_device_mem(pdev); if (err) return err; @@ -4798,9 +4799,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, pci_using_dac = 0; } - err = pci_request_regions(pdev, ixgbe_driver_name); + err = pci_request_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM), ixgbe_driver_name); if (err) { - dev_err(&pdev->dev, "pci_request_regions failed 0x%x\n", err); + dev_err(&pdev->dev, + "pci_request_selected_regions failed 0x%x\n", err); goto err_pci_reg; } @@ -5063,7 +5066,8 @@ err_eeprom: err_ioremap: free_netdev(netdev); err_alloc_etherdev: - pci_release_regions(pdev); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); err_pci_reg: err_dma: pci_disable_device(pdev); @@ -5115,7 +5119,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) ixgbe_release_hw_control(adapter); iounmap(adapter->hw.hw_addr); - pci_release_regions(pdev); + pci_release_selected_regions(pdev, pci_select_bars(pdev, + IORESOURCE_MEM)); DPRINTK(PROBE, INFO, "complete\n"); @@ -5169,7 +5174,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) pci_ers_result_t result; int err; - if (pci_enable_device(pdev)) { + if (pci_enable_device_mem(pdev)) { DPRINTK(PROBE, ERR, "Cannot re-enable PCI device after reset.\n"); result = PCI_ERS_RESULT_DISCONNECT; -- cgit v1.2.3 From 4dbc8ef7e1123bb8a591d75a2b84413aa261a9f4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 6 May 2009 16:50:52 -0700 Subject: net: Make inet_twsk_put similar to sock_put By separating the freeing code from the refcounting decrementing. Probably reducing icache pressure when we still have reference counts to go. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipv4/inet_timewait_sock.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 8554d0ea1719..68a8d892c711 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -49,19 +49,22 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw, inet_twsk_put(tw); } -void inet_twsk_put(struct inet_timewait_sock *tw) +static noinline void inet_twsk_free(struct inet_timewait_sock *tw) { - if (atomic_dec_and_test(&tw->tw_refcnt)) { - struct module *owner = tw->tw_prot->owner; - twsk_destructor((struct sock *)tw); + struct module *owner = tw->tw_prot->owner; + twsk_destructor((struct sock *)tw); #ifdef SOCK_REFCNT_DEBUG - printk(KERN_DEBUG "%s timewait_sock %p released\n", - tw->tw_prot->name, tw); + pr_debug("%s timewait_sock %p released\n", tw->tw_prot->name, tw); #endif - release_net(twsk_net(tw)); - kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw); - module_put(owner); - } + release_net(twsk_net(tw)); + kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw); + module_put(owner); +} + +void inet_twsk_put(struct inet_timewait_sock *tw) +{ + if (atomic_dec_and_test(&tw->tw_refcnt)) + inet_twsk_free(tw); } EXPORT_SYMBOL_GPL(inet_twsk_put); -- cgit v1.2.3 From 4d5b78c055c76bb563c4a43d2adb92735b3b9405 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 6 May 2009 16:52:51 -0700 Subject: net: Add missing rculist.h include to netdevice.h Otherwise list_for_each_entry_rcu() et al. aren't visible and we get build failures in some configurations. Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 02882e2ebd49..2af89b662cad 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -39,6 +39,7 @@ #include #include +#include #include #include -- cgit v1.2.3 From f5f8d86b231e0489c33542c42afbb14d32411ee8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 7 May 2009 07:08:38 +0000 Subject: tcp: tcp_prequeue() cleanup Small cleanup patch to reduce line lengths, before a change in tcp_prequeue(). Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index b55b4891029e..ac37228b7001 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -890,30 +890,31 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); - if (!sysctl_tcp_low_latency && tp->ucopy.task) { - __skb_queue_tail(&tp->ucopy.prequeue, skb); - tp->ucopy.memory += skb->truesize; - if (tp->ucopy.memory > sk->sk_rcvbuf) { - struct sk_buff *skb1; - - BUG_ON(sock_owned_by_user(sk)); - - while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) { - sk_backlog_rcv(sk, skb1); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPREQUEUEDROPPED); - } - - tp->ucopy.memory = 0; - } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) { - wake_up_interruptible(sk->sk_sleep); - if (!inet_csk_ack_scheduled(sk)) - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - (3 * TCP_RTO_MIN) / 4, - TCP_RTO_MAX); + if (sysctl_tcp_low_latency || !tp->ucopy.task) + return 0; + + __skb_queue_tail(&tp->ucopy.prequeue, skb); + tp->ucopy.memory += skb->truesize; + if (tp->ucopy.memory > sk->sk_rcvbuf) { + struct sk_buff *skb1; + + BUG_ON(sock_owned_by_user(sk)); + + while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) { + sk_backlog_rcv(sk, skb1); + NET_INC_STATS_BH(sock_net(sk), + LINUX_MIB_TCPPREQUEUEDROPPED); } - return 1; + + tp->ucopy.memory = 0; + } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) { + wake_up_interruptible(sk->sk_sleep); + if (!inet_csk_ack_scheduled(sk)) + inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, + (3 * TCP_RTO_MIN) / 4, + TCP_RTO_MAX); } - return 0; + return 1; } -- cgit v1.2.3 From 7aedec2ad5314b173e78ca3f4edb4ceaa02248bb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 7 May 2009 07:20:39 +0000 Subject: tcp: tcp_prequeue() can use keyed wakeups We can avoid waking up tasks not interested in receive notifications, using wake_up_interruptible_poll() instead of wake_up_interruptible() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index ac37228b7001..87d210bb12a4 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -908,7 +908,8 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) tp->ucopy.memory = 0; } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) { - wake_up_interruptible(sk->sk_sleep); + wake_up_interruptible_poll(sk->sk_sleep, + POLLIN | POLLRDNORM | POLLRDBAND); if (!inet_csk_ack_scheduled(sk)) inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, (3 * TCP_RTO_MIN) / 4, -- cgit v1.2.3 From afafd5b020a60b72d064e89244cb44a975eb2407 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 7 May 2009 10:38:56 +0000 Subject: ixgbe: always set header length in SRRCTL As per the documentation for 82599 in order to support hardware RSC the header size must be set. This is only currently done for packet split mode. This patch sets the header buffer length for all modes. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 08f4a13a602f..4c38d51397ce 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1754,28 +1754,20 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK; + srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & + IXGBE_SRRCTL_BSIZEHDR_MASK; + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { - u16 bufsz = IXGBE_RXBUFFER_2048; - /* grow the amount we can receive on large page machines */ - if (bufsz < (PAGE_SIZE / 2)) - bufsz = (PAGE_SIZE / 2); - /* cap the bufsz at our largest descriptor size */ - bufsz = min((u16)IXGBE_MAX_RXBUFFER, bufsz); - - srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; +#if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER + srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; +#else + srrctl |= (PAGE_SIZE / 2) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; +#endif srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; - srrctl |= ((IXGBE_RX_HDR_SIZE << - IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & - IXGBE_SRRCTL_BSIZEHDR_MASK); } else { + srrctl |= ALIGN(rx_ring->rx_buf_len, 1024) >> + IXGBE_SRRCTL_BSIZEPKT_SHIFT; srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; - - if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE) - srrctl |= IXGBE_RXBUFFER_2048 >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; - else - srrctl |= rx_ring->rx_buf_len >> - IXGBE_SRRCTL_BSIZEPKT_SHIFT; } IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl); -- cgit v1.2.3 From 163de42e240623694562656542adedbca369beaf Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 7 May 2009 10:39:16 +0000 Subject: ixgbe: set queue0 for srrctl configuration correctly for DCB The current configuration is not setting queue 0 correctly for DCB configurations. As a result unconfigured queues are being used to setup the SRRCTL register rx buffer len sizes. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 4c38d51397ce..d64a2d7d5fa5 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1740,7 +1740,18 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index) unsigned long mask; if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - queue0 = index; + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + int dcb_i = adapter->ring_feature[RING_F_DCB].indices; + if (dcb_i == 8) + queue0 = index >> 4; + else if (dcb_i == 4) + queue0 = index >> 5; + else + dev_err(&adapter->pdev->dev, "Invalid DCB " + "configuration\n"); + } else { + queue0 = index; + } } else { mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask; queue0 = index & mask; -- cgit v1.2.3 From dfa12f05f60eb23b1670f3a7756ed814f886a7fb Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Thu, 7 May 2009 10:39:35 +0000 Subject: ixgbe: Enable L2 header split in 82599 This enables L2 header split when packet split is enabled for 82599. Signed-off-by: Yi Zou Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 3 ++- drivers/net/ixgbe/ixgbe_type.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d64a2d7d5fa5..01d8b6b12be6 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1818,7 +1818,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) u32 psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR | IXGBE_PSRTYPE_IPV4HDR | - IXGBE_PSRTYPE_IPV6HDR; + IXGBE_PSRTYPE_IPV6HDR | + IXGBE_PSRTYPE_L2HDR; IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); } } else { diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index e49e8af59eda..9fd79a05ff0f 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1604,6 +1604,7 @@ #define IXGBE_PSRTYPE_UDPHDR 0x00000020 #define IXGBE_PSRTYPE_IPV4HDR 0x00000100 #define IXGBE_PSRTYPE_IPV6HDR 0x00000200 +#define IXGBE_PSRTYPE_L2HDR 0x00001000 /* SRRCTL bit definitions */ #define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ -- cgit v1.2.3 From bf069c9726b592432ed646e72b910ac3c098d025 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 7 May 2009 10:39:54 +0000 Subject: ixgbe: fix failing to log fan failures We weren't logging the 82598AT fan failure if it occurred before (ixgbe_open) as we hadn't sent up to catch the interrupt that event caused. This patch checks for this failure in: ixgbe_probe - So we can log the failure asap. We check right after we set up the adapter->flags, which is when we know that we have a fan. ixgbe_up_complete - To catch failures that may have happened between probe and when we set up the interrupt that would normally detect the fan failure. To enable all of this we need to initialize the adapter flag with IXGBE_FLAG_FAN_FAIL_CAPABLE when the NIC contained a fan. Signed-off-by: Don Skidmore Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 01d8b6b12be6..4a316e9c0541 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2457,6 +2457,17 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ixgbe_irq_enable(adapter); + /* + * If this adapter has a fan, check to see if we had a failure + * before we enabled the interrupt. + */ + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { + u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (esdp & IXGBE_ESDP_SDP1) + DPRINTK(DRV, CRIT, + "Fan has stopped, replace the adapter\n"); + } + /* * For hot-pluggable SFP+ devices, a new SFP+ module may have * arrived before interrupts were enabled. We need to kick off @@ -3382,9 +3393,11 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->ring_feature[RING_F_RSS].indices = rss; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES; - if (hw->mac.type == ixgbe_mac_82598EB) + if (hw->mac.type == ixgbe_mac_82598EB) { + if (hw->device_id == IXGBE_DEV_ID_82598AT) + adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598; - else if (hw->mac.type == ixgbe_mac_82599EB) { + } else if (hw->mac.type == ixgbe_mac_82599EB) { adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; adapter->flags |= IXGBE_FLAG_RSC_CAPABLE; adapter->flags |= IXGBE_FLAG_RSC_ENABLED; @@ -4915,6 +4928,17 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_sw_init; + /* + * If there is a fan on this device and it has failed log the + * failure. + */ + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { + u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (esdp & IXGBE_ESDP_SDP1) + DPRINTK(PROBE, CRIT, + "Fan has stopped, replace the adapter\n"); + } + /* reset_hw fills in the perm_addr as well */ err = hw->mac.ops.reset_hw(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { -- cgit v1.2.3 From c9c7d2e5a06cd3a26b6be096949e3371ec2aa123 Mon Sep 17 00:00:00 2001 From: "Nelson, Shannon" Date: Thu, 7 May 2009 10:40:15 +0000 Subject: ixgbe: Typecase '1' for 64 bit shift Make sure we don't get any sign-extend issues when we shift a 1 into bit 31. Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 4a316e9c0541..efb175b1e438 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1307,7 +1307,7 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, set_bit(r_idx, q_vector->rxr_idx); q_vector->rxr_count++; - a->rx_ring[r_idx].v_idx = 1 << v_idx; + a->rx_ring[r_idx].v_idx = (u64)1 << v_idx; } static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, @@ -1317,7 +1317,7 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, set_bit(t_idx, q_vector->txr_idx); q_vector->txr_count++; - a->tx_ring[t_idx].v_idx = 1 << v_idx; + a->tx_ring[t_idx].v_idx = (u64)1 << v_idx; } /** @@ -4057,7 +4057,7 @@ static void ixgbe_watchdog(unsigned long data) int i; for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) - eics |= (1 << i); + eics |= ((u64)1 << i); /* Cause software interrupt to ensure rx rings are cleaned */ switch (hw->mac.type) { -- cgit v1.2.3 From c2d5ab4973bfaa72cbb677801825ce56c8f69b56 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 7 May 2009 11:07:35 +0000 Subject: e1000/e1000e/igb/ixgb: don't txhang after link down after the recent changes to wired drivers to use only netif_carrier_off the driver can have outstanding tx work to complete that will never complete once link is down. Since the intel hardware will hold this tx work forever, the driver notices a tx timeout condition internally and might try to instigate printk and reset of the part with a netif_stop_queue, which doesn't work because link is down. Don't bother arming to tx hang detection when link is down. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 2 ++ drivers/net/e1000e/netdev.c | 2 ++ drivers/net/igb/igb_main.c | 2 ++ drivers/net/ixgb/ixgb_main.c | 2 ++ 4 files changed, 8 insertions(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 71d4fe15976a..b455dca0901e 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2646,6 +2646,8 @@ static void e1000_watchdog(unsigned long data) * (Do the reset outside of interrupt context). */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index da6b37e05bea..ccaaee0951cf 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3651,6 +3651,8 @@ link_up: */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8de8629b07ec..8784c051707e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2711,6 +2711,8 @@ link_up: * (Do the reset outside of interrupt context). */ adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); + /* return immediately since reset is imminent */ + return; } } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index cb9ecc48f6d0..04cb81a739c2 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1140,6 +1140,8 @@ ixgb_watchdog(unsigned long data) * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ schedule_work(&adapter->tx_timeout_task); + /* return immediately since reset is imminent */ + return; } } -- cgit v1.2.3 From 928f308f556f4943e50c5064b546f47bce301f02 Mon Sep 17 00:00:00 2001 From: Matthias Ludwig Date: Thu, 7 May 2009 15:00:12 -0700 Subject: smsc911x: fix calculation of res_size for ioremap fix size of remaped iomem, which is 1 byte to small (e.g. mappes only 0xff bytes instead of 0x100) Signed-off-by: Matthias Ludwig Acked-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a8528c5bb5e..3cff84078a9e 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1976,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = -ENODEV; goto out_0; } - res_size = res->end - res->start; + res_size = res->end - res->start + 1; irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { -- cgit v1.2.3 From dd21ca6de703230785b755c8290365fc1640200e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 5 May 2009 23:22:01 +0000 Subject: bnx2x: free workqueue when driver fail to register Signed-off-by: Stanislaw Gruszka Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index a669bb7eb00c..519e2079f03a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -11630,13 +11630,20 @@ static struct pci_driver bnx2x_pci_driver = { static int __init bnx2x_init(void) { + int ret; + bnx2x_wq = create_singlethread_workqueue("bnx2x"); if (bnx2x_wq == NULL) { printk(KERN_ERR PFX "Cannot create workqueue\n"); return -ENOMEM; } - return pci_register_driver(&bnx2x_pci_driver); + ret = pci_register_driver(&bnx2x_pci_driver); + if (ret) { + printk(KERN_ERR PFX "Cannot register driver\n"); + destroy_workqueue(bnx2x_wq); + } + return ret; } static void __exit bnx2x_cleanup(void) -- cgit v1.2.3 From 17cb4006bc40eea949f62adbbad99d8b980c0678 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 5 May 2009 23:22:12 +0000 Subject: bnx2x: do not return negative number of received packages Signed-off-by: Stanislaw Gruszka Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 519e2079f03a..e01539c33b8a 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1546,7 +1546,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) len, cqe, comp_ring_cons); #ifdef BNX2X_STOP_ON_ERROR if (bp->panic) - return -EINVAL; + return 0; #endif bnx2x_update_sge_prod(fp, -- cgit v1.2.3 From 61de71c67caec39df0a854a1ef5be0c6be385c2a Mon Sep 17 00:00:00 2001 From: John Dykstra Date: Fri, 8 May 2009 14:57:01 -0700 Subject: Network Drop Monitor: Fix skb_kill_datagram Commit ead2ceb0ec9f85cff19c43b5cdb2f8a054484431 ("Network Drop Monitor: Adding kfree_skb_clean for non-drops and modifying end-of-line points for skbs") established new conventions for identifying dropped packets. Align skb_kill_datagram() with these conventions so that packets that get dropped just before the copy to userspace are properly tracked. Signed-off-by: John Dykstra Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/core/datagram.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/datagram.c b/net/core/datagram.c index 22ea437c5023..e2a36f05cdf7 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -260,7 +260,9 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) spin_unlock_bh(&sk->sk_receive_queue.lock); } - skb_free_datagram(sk, skb); + kfree_skb(skb); + sk_mem_reclaim_partial(sk); + return err; } -- cgit v1.2.3 From 7a2469ce4d8984722d65628969ad6f8b09da136f Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 May 2009 22:02:27 +0000 Subject: netxen: cache msi register offset Store msi target status register offset in adapter struct. This avoids contention on msi_tgt_status table from interrupt hadlers of different pci function. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 3 +++ drivers/net/netxen/netxen_nic_main.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 9350c8663fd8..ab11c2b3f0fe 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1257,6 +1257,9 @@ struct netxen_adapter { u32 irq; u32 temp; + u32 msi_tgt_status; + u32 resv4; + struct netxen_adapter_stats stats; struct netxen_recv_context recv_ctx; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 83dadfd78c3c..edb4bcda71ea 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -525,6 +525,8 @@ netxen_setup_intr(struct netxen_adapter *adapter) request_msi: if (use_msi && !pci_enable_msi(pdev)) { adapter->flags |= NETXEN_NIC_MSI_ENABLED; + adapter->msi_tgt_status = + msi_tgt_status[adapter->ahw.pci_func]; dev_info(&pdev->dev, "using msi interrupts\n"); } else dev_info(&pdev->dev, "using legacy interrupts\n"); @@ -1701,7 +1703,7 @@ static irqreturn_t netxen_msi_intr(int irq, void *data) /* clear interrupt */ adapter->pci_write_immediate(adapter, - msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); + adapter->msi_tgt_status, 0xffffffff); napi_schedule(&sds_ring->napi); return IRQ_HANDLED; -- cgit v1.2.3 From be339aee634d5cb98a8df8d6febe04002ec497f3 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 May 2009 22:02:28 +0000 Subject: netxen: fix irq tear down and msix leak. o Fix the order of irq and hardware context teardown. Also synchronize the interrupt in dev close() before releasing tx buffers. o Fix possible msi-x vector leak if available vectors are less than requested. o Request multiple msix vectors only if hardware supports multiple rx queues. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 74 +++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index edb4bcda71ea..c61c1d187a9e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -175,12 +175,6 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) struct nx_host_sds_ring *sds_ring; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - if ((adapter->flags & NETXEN_NIC_MSIX_ENABLED) && - adapter->rss_supported) - adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2; - else - adapter->max_sds_rings = 1; - if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) return 1; @@ -216,8 +210,9 @@ netxen_napi_disable(struct netxen_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; - netxen_nic_disable_int(sds_ring); napi_disable(&sds_ring->napi); + netxen_nic_disable_int(sds_ring); + synchronize_irq(sds_ring->irq); } } @@ -407,11 +402,11 @@ static void netxen_set_msix_bit(struct pci_dev *pdev, int enable) } } -static void netxen_init_msix_entries(struct netxen_adapter *adapter) +static void netxen_init_msix_entries(struct netxen_adapter *adapter, int count) { int i; - for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++) + for (i = 0; i < count; i++) adapter->msix_entries[i].entry = i; } @@ -496,6 +491,15 @@ netxen_setup_intr(struct netxen_adapter *adapter) { struct netxen_legacy_intr_set *legacy_intrp; struct pci_dev *pdev = adapter->pdev; + int err, num_msix; + + if (adapter->rss_supported) { + num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? + MSIX_ENTRIES_PER_ADAPTER : 2; + } else + num_msix = 1; + + adapter->max_sds_rings = 1; adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); @@ -512,26 +516,35 @@ netxen_setup_intr(struct netxen_adapter *adapter) if (adapter->msix_supported) { - netxen_init_msix_entries(adapter); - if (pci_enable_msix(pdev, adapter->msix_entries, - MSIX_ENTRIES_PER_ADAPTER)) - goto request_msi; + netxen_init_msix_entries(adapter, num_msix); + err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); + if (err == 0) { + adapter->flags |= NETXEN_NIC_MSIX_ENABLED; + netxen_set_msix_bit(pdev, 1); - adapter->flags |= NETXEN_NIC_MSIX_ENABLED; - netxen_set_msix_bit(pdev, 1); - dev_info(&pdev->dev, "using msi-x interrupts\n"); + if (adapter->rss_supported) + adapter->max_sds_rings = num_msix; - } else { -request_msi: - if (use_msi && !pci_enable_msi(pdev)) { - adapter->flags |= NETXEN_NIC_MSI_ENABLED; - adapter->msi_tgt_status = - msi_tgt_status[adapter->ahw.pci_func]; - dev_info(&pdev->dev, "using msi interrupts\n"); - } else - dev_info(&pdev->dev, "using legacy interrupts\n"); - adapter->msix_entries[0].vector = pdev->irq; + dev_info(&pdev->dev, "using msi-x interrupts\n"); + return; + } + + if (err > 0) + pci_disable_msix(pdev); + + /* fall through for msi */ } + + if (use_msi && !pci_enable_msi(pdev)) { + adapter->flags |= NETXEN_NIC_MSI_ENABLED; + adapter->msi_tgt_status = + msi_tgt_status[adapter->ahw.pci_func]; + dev_info(&pdev->dev, "using msi interrupts\n"); + return; + } + + dev_info(&pdev->dev, "using legacy interrupts\n"); + adapter->msix_entries[0].vector = pdev->irq; } static void @@ -767,7 +780,7 @@ netxen_nic_request_irq(struct netxen_adapter *adapter) for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; - sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring); + sprintf(sds_ring->name, "%s[%d]", netdev->name, ring); err = request_irq(sds_ring->irq, handler, flags, sds_ring->name, sds_ring); if (err) @@ -830,8 +843,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) { netif_carrier_off(netdev); netif_stop_queue(netdev); - smp_mb(); - netxen_napi_disable(adapter); if (adapter->stop_port) adapter->stop_port(adapter); @@ -839,6 +850,8 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_p3_free_mac_list(adapter); + netxen_napi_disable(adapter); + netxen_release_tx_buffers(adapter); FLUSH_SCHEDULED_WORK(); @@ -917,10 +930,9 @@ err_out_free_sw: static void netxen_nic_detach(struct netxen_adapter *adapter) { - netxen_nic_free_irq(adapter); - netxen_release_rx_buffers(adapter); netxen_free_hw_resources(adapter); + netxen_nic_free_irq(adapter); netxen_free_sw_resources(adapter); adapter->is_up = 0; -- cgit v1.2.3 From b0b3a75b36afe3b1ed2c12b8817b6326db8ed003 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 May 2009 22:02:29 +0000 Subject: netxen: disable msi-x for NC512m adapter This board doesn't suppot msi-x well due to msi-x table mapping (hardware) issue. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index c61c1d187a9e..86ca0812dd48 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -292,7 +292,6 @@ static void netxen_check_options(struct netxen_adapter *adapter) switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P2_SB31_10G_CX4: - case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: adapter->msix_supported = !!use_msi_x; adapter->rss_supported = !!use_msi_x; break; -- cgit v1.2.3 From 23b6cc425d718fce2501d5f60e368cfa44ef7d86 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 May 2009 22:02:30 +0000 Subject: netxen: trivial register access cleanup Remove unnecessary length parameter since it's always 4 bytes. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 86c9e78ec39e..42ffb825ebf1 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -914,17 +914,15 @@ netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw) * In: 'off' is offset from base in 128M pci map */ static int -netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, - ulong *off, int len) +netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) { - unsigned long end = *off + len; crb_128M_2M_sub_block_map_t *m; if (*off >= NETXEN_CRB_MAX) return -1; - if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) { + if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) { *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE + (ulong)adapter->ahw.pci_base0; return 0; @@ -934,14 +932,13 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, return -1; *off -= NETXEN_PCI_CRBSPACE; - end = *off + len; /* * Try direct map */ m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; - if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) { + if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { *off = *off + m->start_2M - m->start_128M + (ulong)adapter->ahw.pci_base0; return 0; @@ -1036,7 +1033,7 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) unsigned long flags = 0; int rv; - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, 4); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); if (rv == -1) { printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", @@ -1066,7 +1063,7 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) int rv; u32 data; - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, 4); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); if (rv == -1) { printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", -- cgit v1.2.3 From 9948bb6a6db6ad6a8bf2ccaaceb780404f1f43df Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 8 May 2009 06:30:25 +0000 Subject: decnet: Use data ready call back, rather than hand coding it Signed-off-by: Steven Whitehouse Signed-off-by: David S. Miller --- net/decnet/dn_nsp_in.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 5d8a2a56fd39..932408dca86d 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -578,6 +578,7 @@ out: static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue) { int err; + int skb_len; /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces number of warnings when compiling with -W --ANK @@ -592,22 +593,12 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig if (err) goto out; + skb_len = skb->len; skb_set_owner_r(skb, sk); skb_queue_tail(queue, skb); - /* This code only runs from BH or BH protected context. - * Therefore the plain read_lock is ok here. -DaveM - */ - read_lock(&sk->sk_callback_lock); - if (!sock_flag(sk, SOCK_DEAD)) { - struct socket *sock = sk->sk_socket; - wake_up_interruptible(sk->sk_sleep); - if (sock && sock->fasync_list && - !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) - __kill_fasync(sock->fasync_list, sig, - (sig == SIGURG) ? POLL_PRI : POLL_IN); - } - read_unlock(&sk->sk_callback_lock); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, skb_len); out: return err; } -- cgit v1.2.3 From ab9c73ccb52f40576ce017528d542eda3c6ae766 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 May 2009 13:30:17 +0000 Subject: net: check retval of dev_addr_init() Add missed checking of dev_addr_init return value in alloc_netdev_mq. Signed-off-by: Jiri Pirko net/core/dev.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) Signed-off-by: David S. Miller --- net/core/dev.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 637ea71b0a0d..14dd725aaab7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5007,13 +5007,16 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, if (!tx) { printk(KERN_ERR "alloc_netdev: Unable to allocate " "tx qdiscs.\n"); - kfree(p); - return NULL; + goto free_p; } dev = (struct net_device *) (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); dev->padded = (char *)dev - (char *)p; + + if (dev_addr_init(dev)) + goto free_tx; + dev_net_set(dev, &init_net); dev->_tx = tx; @@ -5022,13 +5025,19 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, dev->gso_max_size = GSO_MAX_SIZE; - dev_addr_init(dev); netdev_init_queues(dev); INIT_LIST_HEAD(&dev->napi_list); setup(dev); strcpy(dev->name, name); return dev; + +free_tx: + kfree(tx); + +free_p: + kfree(p); + return NULL; } EXPORT_SYMBOL(alloc_netdev_mq); -- cgit v1.2.3 From ed9b58bc443a1210b5be1ded6421b17e015bf985 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Sat, 9 May 2009 06:59:16 +0000 Subject: Remove duplicate slow protocol define in bond_3ad.h ETH_P_SLOW is already defined in include/linux/if_ether.h. There's no need to define BOND_ETH_P_LACPDU in drivers/net/bonding/bond_3ad.h Signed-off-by: Richard Genoud Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index a306230381c8..2c46a154f2c6 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -26,10 +26,10 @@ #include #include #include +#include // General definitions -#define BOND_ETH_P_LACPDU 0x8809 -#define PKT_TYPE_LACPDU cpu_to_be16(BOND_ETH_P_LACPDU) +#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW) #define AD_TIMER_INTERVAL 100 /*msec*/ #define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02} -- cgit v1.2.3 From 980c9e8ceeb69ac4c921173d0d06323f5c678647 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 9 May 2009 22:54:21 -0700 Subject: tun: add tun_flags, owner, group attributes in sysfs This patch adds three attribute files in /sys/class/net/$dev/ for tun devices; allowing userspace to obtain the information which TUNGETIFF offers, and more, but without having to attach to the device in question (which may not be possible if it's in use). It also fixes a bug which has been present in the TUNGETIFF ioctl since its inception, where it would never set IFF_TUN or IFF_TAP according to the device type. (Look carefully at the code which I remove from tun_get_iff() and how the new tun_flags() helper is subtly different). Signed-off-by: David Woodhouse Signed-off-by: David S. Miller --- drivers/net/tun.c | 67 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 94622e5fb936..4cda69b6b28c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -865,6 +865,52 @@ static struct proto tun_proto = { .obj_size = sizeof(struct tun_sock), }; +static int tun_flags(struct tun_struct *tun) +{ + int flags = 0; + + if (tun->flags & TUN_TUN_DEV) + flags |= IFF_TUN; + else + flags |= IFF_TAP; + + if (tun->flags & TUN_NO_PI) + flags |= IFF_NO_PI; + + if (tun->flags & TUN_ONE_QUEUE) + flags |= IFF_ONE_QUEUE; + + if (tun->flags & TUN_VNET_HDR) + flags |= IFF_VNET_HDR; + + return flags; +} + +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "0x%x\n", tun_flags(tun)); +} + +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "%d\n", tun->owner); +} + +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "%d\n", tun->group); +} + +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); + static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) { struct sock *sk; @@ -950,6 +996,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (err < 0) goto err_free_sk; + if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || + device_create_file(&tun->dev->dev, &dev_attr_owner) || + device_create_file(&tun->dev->dev, &dev_attr_group)) + printk(KERN_ERR "Failed to create tun sysfs files\n"); + sk->sk_destruct = tun_sock_destruct; err = tun_attach(tun, file); @@ -1002,21 +1053,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) strcpy(ifr->ifr_name, tun->dev->name); - ifr->ifr_flags = 0; - - if (ifr->ifr_flags & TUN_TUN_DEV) - ifr->ifr_flags |= IFF_TUN; - else - ifr->ifr_flags |= IFF_TAP; - - if (tun->flags & TUN_NO_PI) - ifr->ifr_flags |= IFF_NO_PI; - - if (tun->flags & TUN_ONE_QUEUE) - ifr->ifr_flags |= IFF_ONE_QUEUE; - - if (tun->flags & TUN_VNET_HDR) - ifr->ifr_flags |= IFF_VNET_HDR; + ifr->ifr_flags = tun_flags(tun); tun_put(tun); return 0; -- cgit v1.2.3 From 8b3521eeb7598c3b10c7e14361a7974464527702 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 11 May 2009 05:52:49 +0000 Subject: ipv4: remove an unused parameter from configure method of fib_rules_ops. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- include/net/fib_rules.h | 1 - net/core/fib_rules.c | 2 +- net/decnet/dn_rules.c | 2 +- net/ipv4/fib_rules.c | 2 +- net/ipv6/fib6_rules.c | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index c2bb5cae6515..b9b63395d002 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -48,7 +48,6 @@ struct fib_rules_ops struct flowi *, int); int (*configure)(struct fib_rule *, struct sk_buff *, - struct nlmsghdr *, struct fib_rule_hdr *, struct nlattr **); int (*compare)(struct fib_rule *, diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 98691e1466b8..17d9f497b797 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -299,7 +299,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) } else if (rule->action == FR_ACT_GOTO) goto errout_free; - err = ops->configure(rule, skb, nlh, frh, tb); + err = ops->configure(rule, skb, frh, tb); if (err < 0) goto errout_free; diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 14fbca55e908..a2690b12e03c 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -115,7 +115,7 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) } static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, + struct fib_rule_hdr *frh, struct nlattr **tb) { int err = -EINVAL; diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 6080d7120821..38904be4102e 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -134,7 +134,7 @@ static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = { }; static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, + struct fib_rule_hdr *frh, struct nlattr **tb) { struct net *net = sock_net(skb->sk); diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index f5de3f9dc692..e1a36dbb5a27 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -151,7 +151,7 @@ static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = { }; static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, + struct fib_rule_hdr *frh, struct nlattr **tb) { int err = -EINVAL; -- cgit v1.2.3 From 3a6d54c56326c29c5357655779cfe6cf36481b17 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 11 May 2009 23:37:15 +0000 Subject: net: remove needless (now buggy) & from dev->dev_addr Patch fixes issues with dev->dev_addr changing from array to pointer. Hopefully there are no others. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 5 +++-- drivers/net/ibmveth.c | 4 ++-- drivers/net/wireless/hostap/hostap_hw.c | 2 +- drivers/net/wireless/ray_cs.c | 2 +- net/ipv6/ip6_tunnel.c | 4 ++-- net/tipc/eth_media.c | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 8c2e5ab51f08..06009dc50b19 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1845,9 +1845,10 @@ static u16 aggregator_identifier; * Can be called only after the mac address of the bond is set. */ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast) -{ +{ // check that the bond is not initialized yet - if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->dev->dev_addr))) { + if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), + bond->dev->dev_addr)) { aggregator_identifier = 0; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 7902e5e16a1a..53af71aceb8a 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1374,8 +1374,8 @@ static void ibmveth_proc_unregister_driver(void) static int ibmveth_show(struct seq_file *seq, void *v) { struct ibmveth_adapter *adapter = seq->private; - char *current_mac = ((char*) &adapter->netdev->dev_addr); - char *firmware_mac = ((char*) &adapter->mac_addr) ; + char *current_mac = (char *) adapter->netdev->dev_addr; + char *firmware_mac = (char *) &adapter->mac_addr; seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 3dad1cf8f241..ff9b5c882184 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -1423,7 +1423,7 @@ static int prism2_hw_init2(struct net_device *dev, int initial) prism2_check_sta_fw_version(local); if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR, - &dev->dev_addr, 6, 1) < 0) { + dev->dev_addr, 6, 1) < 0) { printk("%s: could not get own MAC address\n", dev->name); } diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index fa90d1d8d82e..22e71856aa24 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -892,7 +892,7 @@ static int ray_dev_init(struct net_device *dev) #endif /* RAY_IMMEDIATE_INIT */ /* copy mac and broadcast addresses to linux device */ - memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); + memcpy(dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); memset(dev->broadcast, 0xff, ETH_ALEN); DEBUG(2, "ray_dev_init ending\n"); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index d994c55a5b16..af256d47fd35 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1100,8 +1100,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) struct ip6_tnl_parm *p = &t->parms; struct flowi *fl = &t->fl; - memcpy(&dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); - memcpy(&dev->broadcast, &p->raddr, sizeof(struct in6_addr)); + memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); + memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); /* Set up flowi template */ ipv6_addr_copy(&fl->fl6_src, &p->laddr); diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index f72ba774c246..524ba5696d4d 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -167,7 +167,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) tb_ptr->mtu = dev->mtu; tb_ptr->blocked = 0; tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH); - memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN); + memcpy(&tb_ptr->addr.dev_addr, dev->dev_addr, ETH_ALEN); return 0; } -- cgit v1.2.3 From cb1c4b71f6da18fa98bab4af055f391d01bee8ba Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 12 May 2009 10:47:33 +0000 Subject: cls_cgroup: remove unneeded cgroup_lock We can remove this lock here, since we are in cgroup write handler and thus the cgrp is guaranteed to be valid, and no lock is needed when writing a u32 variable. Signed-off-by: Li Zefan Acked-by: Paul Menage Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/sched/cls_cgroup.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 91a3db4a76f8..1ab4542e61e0 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -62,13 +62,7 @@ static u64 read_classid(struct cgroup *cgrp, struct cftype *cft) static int write_classid(struct cgroup *cgrp, struct cftype *cft, u64 value) { - if (!cgroup_lock_live_group(cgrp)) - return -ENODEV; - cgrp_cls_state(cgrp)->classid = (u32) value; - - cgroup_unlock(); - return 0; } -- cgit v1.2.3 From 3977d0334b98770b81dfeb248db232c9bb3d3c88 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Tue, 12 May 2009 10:48:36 +0000 Subject: sfc: modify allocation error message Change error message when alloc_cpumask_var fails. Repairs "cpumask: convert drivers/net/sfc". Signed-off-by: Mike Travis Acked-by: Ben Hutchings Acked-by: David S. Miller Cc: Rusty Russell Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index d3e240b736c7..bde8b7ac398a 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -894,9 +894,9 @@ static int efx_wanted_rx_queues(void) int count; int cpu; - if (!alloc_cpumask_var(&core_mask, GFP_KERNEL)) { + if (unlikely(!alloc_cpumask_var(&core_mask, GFP_KERNEL))) { printk(KERN_WARNING - "efx.c: allocation failure, irq balancing hobbled\n"); + "sfc: RSS disabled due to allocation failure\n"); return 1; } -- cgit v1.2.3 From 3699a1c7d42f9a694bb512d91ca457f363a48e38 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 12 May 2009 10:48:37 +0000 Subject: drivers/net/82596.c: suppress warnings i386 allmodconfig: drivers/net/82596.c: In function 'init_rx_bufs': drivers/net/82596.c:544: warning: cast to pointer from integer of different size drivers/net/82596.c:545: warning: cast to pointer from integer of different size drivers/net/82596.c:548: warning: cast to pointer from integer of different size drivers/net/82596.c:557: warning: cast to pointer from integer of different size drivers/net/82596.c:565: warning: cast to pointer from integer of different size drivers/net/82596.c:569: warning: cast to pointer from integer of different size drivers/net/82596.c:575: warning: cast to pointer from integer of different size drivers/net/82596.c: In function 'rebuild_rx_bufs': drivers/net/82596.c:606: warning: cast to pointer from integer of different size drivers/net/82596.c:608: warning: cast to pointer from integer of different size drivers/net/82596.c: In function 'init_i596_mem': drivers/net/82596.c:680: warning: cast to pointer from integer of different size drivers/net/82596.c:681: warning: cast to pointer from integer of different size drivers/net/82596.c: In function 'i596_rx': drivers/net/82596.c:818: warning: cast to pointer from integer of different size drivers/net/82596.c: In function 'i596_add_cmd': drivers/net/82596.c:975: warning: cast to pointer from integer of different size drivers/net/82596.c:979: warning: cast to pointer from integer of different size drivers/net/82596.c: In function 'i596_start_xmit': drivers/net/82596.c:1088: warning: cast to pointer from integer of different size drivers/net/82596.c:1099: warning: cast to pointer from integer of different size drivers/net/82596.c: In function 'i596_interrupt': drivers/net/82596.c:1404: warning: cast to pointer from integer of different size (ugh) Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/82596.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index cca94b9c08ae..77547545509b 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -122,13 +122,13 @@ static char version[] __initdata = #define ISCP_BUSY 0x00010000 #define MACH_IS_APRICOT 0 #else -#define WSWAPrfd(x) ((struct i596_rfd *)(x)) -#define WSWAPrbd(x) ((struct i596_rbd *)(x)) -#define WSWAPiscp(x) ((struct i596_iscp *)(x)) -#define WSWAPscb(x) ((struct i596_scb *)(x)) -#define WSWAPcmd(x) ((struct i596_cmd *)(x)) -#define WSWAPtbd(x) ((struct i596_tbd *)(x)) -#define WSWAPchar(x) ((char *)(x)) +#define WSWAPrfd(x) ((struct i596_rfd *)((long)x)) +#define WSWAPrbd(x) ((struct i596_rbd *)((long)x)) +#define WSWAPiscp(x) ((struct i596_iscp *)((long)x)) +#define WSWAPscb(x) ((struct i596_scb *)((long)x)) +#define WSWAPcmd(x) ((struct i596_cmd *)((long)x)) +#define WSWAPtbd(x) ((struct i596_tbd *)((long)x)) +#define WSWAPchar(x) ((char *)((long)x)) #define ISCP_BUSY 0x0001 #define MACH_IS_APRICOT 1 #endif -- cgit v1.2.3 From a186d2aead8beb164ddb76245d189c66f7021b59 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 12 May 2009 22:40:12 +0000 Subject: net: remove needless (now buggy) & from dev->dev_addr (part2) Missed part of "&" removal. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/llc/af_llc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index febae702685c..9208cf5f2bd5 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -935,7 +935,7 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, if (llc->dev) { sllc.sllc_arphrd = llc->dev->type; - memcpy(&sllc.sllc_mac, &llc->dev->dev_addr, + memcpy(&sllc.sllc_mac, llc->dev->dev_addr, IFHWADDRLEN); } } -- cgit v1.2.3 From 952ee9df26c487f2d73b2dced58ec904f19ea0f8 Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Wed, 13 May 2009 06:04:58 +0000 Subject: mv643xx_eth: Remove a stale PPC_MULTIPLATFORM PPC_MULTIPLATFORM was killed in commit 28794d3 but this stale occurrence was hiding the mv643xx_eth driver in some cases (e.g. Pegasos II) Signed-off-by: Emil Medve Signed-off-by: David S. Miller --- drivers/net/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index b8727d54bdbb..48b73b077156 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1,4 +1,3 @@ - # # Network device configuration # @@ -2351,7 +2350,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "Marvell Discovery (643XX) and Orion ethernet support" - depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION + depends on MV64360 || MV64X60 || PPC32 || PLAT_ORION select INET_LRO select PHYLIB help -- cgit v1.2.3 From bff66176bb47b2cf3331d9e42d37ea4094826756 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:09:39 +0000 Subject: ixgbe: Add FCoE feature register defines to 82599 This adds FCoE related register defines to 82599. Signed-off-by: Yi Zou Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_type.h | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 9fd79a05ff0f..c2d9ed5b9e05 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -478,6 +478,63 @@ #define IXGBE_RTTDTECC_NO_BCN 0x00000100 #define IXGBE_RTTBCNRC 0x04984 +/* FCoE registers */ +#define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */ +#define IXGBE_FCPTRH 0x02414 /* FC USer Desc. PTR High */ +#define IXGBE_FCBUFF 0x02418 /* FC Buffer Control */ +#define IXGBE_FCDMARW 0x02420 /* FC Receive DMA RW */ +#define IXGBE_FCINVST0 0x03FC0 /* FC Invalid DMA Context Status Reg 0 */ +#define IXGBE_FCINVST(_i) (IXGBE_FCINVST0 + ((_i) * 4)) +#define IXGBE_FCBUFF_VALID (1 << 0) /* DMA Context Valid */ +#define IXGBE_FCBUFF_BUFFSIZE (3 << 3) /* User Buffer Size */ +#define IXGBE_FCBUFF_WRCONTX (1 << 7) /* 0: Initiator, 1: Target */ +#define IXGBE_FCBUFF_BUFFCNT 0x0000ff00 /* Number of User Buffers */ +#define IXGBE_FCBUFF_OFFSET 0xffff0000 /* User Buffer Offset */ +#define IXGBE_FCBUFF_BUFFSIZE_SHIFT 3 +#define IXGBE_FCBUFF_BUFFCNT_SHIFT 8 +#define IXGBE_FCBUFF_OFFSET_SHIFT 16 +#define IXGBE_FCDMARW_WE (1 << 14) /* Write enable */ +#define IXGBE_FCDMARW_RE (1 << 15) /* Read enable */ +#define IXGBE_FCDMARW_FCOESEL 0x000001ff /* FC X_ID: 11 bits */ +#define IXGBE_FCDMARW_LASTSIZE 0xffff0000 /* Last User Buffer Size */ +#define IXGBE_FCDMARW_LASTSIZE_SHIFT 16 + +/* FCoE SOF/EOF */ +#define IXGBE_TEOFF 0x04A94 /* Tx FC EOF */ +#define IXGBE_TSOFF 0x04A98 /* Tx FC SOF */ +#define IXGBE_REOFF 0x05158 /* Rx FC EOF */ +#define IXGBE_RSOFF 0x051F8 /* Rx FC SOF */ +/* FCoE Filter Context Registers */ +#define IXGBE_FCFLT 0x05108 /* FC FLT Context */ +#define IXGBE_FCFLTRW 0x05110 /* FC Filter RW Control */ +#define IXGBE_FCPARAM 0x051d8 /* FC Offset Parameter */ +#define IXGBE_FCFLT_VALID (1 << 0) /* Filter Context Valid */ +#define IXGBE_FCFLT_FIRST (1 << 1) /* Filter First */ +#define IXGBE_FCFLT_SEQID 0x00ff0000 /* Sequence ID */ +#define IXGBE_FCFLT_SEQCNT 0xff000000 /* Sequence Count */ +#define IXGBE_FCFLTRW_RVALDT (1 << 13) /* Fast Re-Validation */ +#define IXGBE_FCFLTRW_WE (1 << 14) /* Write Enable */ +#define IXGBE_FCFLTRW_RE (1 << 15) /* Read Enable */ +/* FCoE Receive Control */ +#define IXGBE_FCRXCTRL 0x05100 /* FC Receive Control */ +#define IXGBE_FCRXCTRL_FCOELLI (1 << 0) /* Low latency interrupt */ +#define IXGBE_FCRXCTRL_SAVBAD (1 << 1) /* Save Bad Frames */ +#define IXGBE_FCRXCTRL_FRSTRDH (1 << 2) /* EN 1st Read Header */ +#define IXGBE_FCRXCTRL_LASTSEQH (1 << 3) /* EN Last Header in Seq */ +#define IXGBE_FCRXCTRL_ALLH (1 << 4) /* EN All Headers */ +#define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5) /* EN 1st Seq. Header */ +#define IXGBE_FCRXCTRL_ICRC (1 << 6) /* Ignore Bad FC CRC */ +#define IXGBE_FCRXCTRL_FCCRCBO (1 << 7) /* FC CRC Byte Ordering */ +#define IXGBE_FCRXCTRL_FCOEVER 0x00000f00 /* FCoE Version: 4 bits */ +#define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8 +/* FCoE Redirection */ +#define IXGBE_FCRECTL 0x0ED00 /* FC Redirection Control */ +#define IXGBE_FCRETA0 0x0ED10 /* FC Redirection Table 0 */ +#define IXGBE_FCRETA(_i) (IXGBE_FCRETA0 + ((_i) * 4)) /* FCoE Redir */ +#define IXGBE_FCRECTL_ENA 0x1 /* FCoE Redir Table Enable */ +#define IXGBE_FCRETA_SIZE 8 /* Max entries in FCRETA */ +#define IXGBE_FCRETA_ENTRY_MASK 0x0000007f /* 7 bits for the queue index */ + /* Stats registers */ #define IXGBE_CRCERRS 0x04000 #define IXGBE_ILLERRC 0x04004 @@ -549,6 +606,13 @@ #define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */ #define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */ +#define IXGBE_FCCRC 0x05118 /* Count of Good Eth CRC w/ Bad FC CRC */ +#define IXGBE_FCOERPDC 0x0241C /* FCoE Rx Packets Dropped Count */ +#define IXGBE_FCLAST 0x02424 /* FCoE Last Error Count */ +#define IXGBE_FCOEPRC 0x02428 /* Number of FCoE Packets Received */ +#define IXGBE_FCOEDWRC 0x0242C /* Number of FCoE DWords Received */ +#define IXGBE_FCOEPTC 0x08784 /* Number of FCoE Packets Transmitted */ +#define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */ /* Management */ #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */ @@ -1153,6 +1217,7 @@ /* ETYPE Queue Filter/Select Bit Masks */ #define IXGBE_MAX_ETQF_FILTERS 8 +#define IXGBE_ETQF_FCOE 0x08000000 /* bit 27 */ #define IXGBE_ETQF_BCN 0x10000000 /* bit 28 */ #define IXGBE_ETQF_1588 0x40000000 /* bit 30 */ #define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */ @@ -1175,6 +1240,7 @@ */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_BCN 1 +#define IXGBE_ETQF_FILTER_FCOE 2 #define IXGBE_ETQF_FILTER_1588 3 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ @@ -1579,6 +1645,8 @@ #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ #define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */ #define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ +#define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCoEFe/IPE */ +#define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */ #define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */ #define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */ #define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */ @@ -1598,6 +1666,12 @@ #define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM /* FDir Match */ #define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP /* IEEE VLAN Pkt */ #define IXGBE_RXDADV_STAT_MASK 0x000fffff /* Stat/NEXTP: bit 0-19 */ +#define IXGBE_RXDADV_STAT_FCEOFS 0x00000040 /* FCoE EOF/SOF Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT 0x00000030 /* FCoE Pkt Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */ +#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */ +#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */ +#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */ /* PSRTYPE bit definitions */ #define IXGBE_PSRTYPE_TCPHDR 0x00000010 @@ -1831,6 +1905,16 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ #define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ #define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */ +#define IXGBE_ADVTXT_TUCMD_FCOE 0x00008000 /* FCoE Frame Type */ +#define IXGBE_ADVTXD_FCOEF_EOF_MASK (0x3 << 10) /* FC EOF index */ +#define IXGBE_ADVTXD_FCOEF_SOF ((1 << 2) << 10) /* FC SOF index */ +#define IXGBE_ADVTXD_FCOEF_PARINC ((1 << 3) << 10) /* Rel_Off in F_CTL */ +#define IXGBE_ADVTXD_FCOEF_ORIE ((1 << 4) << 10) /* Orientation: End */ +#define IXGBE_ADVTXD_FCOEF_ORIS ((1 << 5) << 10) /* Orientation: Start */ +#define IXGBE_ADVTXD_FCOEF_EOF_N (0x0 << 10) /* 00: EOFn */ +#define IXGBE_ADVTXD_FCOEF_EOF_T (0x1 << 10) /* 01: EOFt */ +#define IXGBE_ADVTXD_FCOEF_EOF_NI (0x2 << 10) /* 10: EOFni */ +#define IXGBE_ADVTXD_FCOEF_EOF_A (0x3 << 10) /* 11: EOFa */ #define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ -- cgit v1.2.3 From e92cbeac89d4c7b228894a9b8eb37e3ac51afe73 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:10:01 +0000 Subject: ixgbe: Add FCoE feature header to 82599 This adds the FCoE feature header ixgbe_fcoe.h to 82599. This header includes the defines and structures required by the ixgbe driver to support various offload features in 82599 for Fiber Channel over Ethernet (FCoE). These offloads features include Fiber Channel CRC calculation, FCoE SOF/EOF auto insertion, FCoE Sequence Offload (FSO) for large send, and Direct Data Placement (DDP) for large receive. Signed-off-by: Yi Zou Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_fcoe.h | 66 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 drivers/net/ixgbe/ixgbe_fcoe.h diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h new file mode 100644 index 000000000000..d054c1dada50 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_fcoe.h @@ -0,0 +1,66 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBE_FCOE_H +#define _IXGBE_FCOE_H + +#include + +/* shift bits within STAT fo FCSTAT */ +#define IXGBE_RXDADV_FCSTAT_SHIFT 4 + +/* ddp user buffer */ +#define IXGBE_BUFFCNT_MAX 256 /* 8 bits bufcnt */ +#define IXGBE_FCPTR_ALIGN 16 +#define IXGBE_FCPTR_MAX (IXGBE_BUFFCNT_MAX * sizeof(dma_addr_t)) +#define IXGBE_FCBUFF_4KB 0x0 +#define IXGBE_FCBUFF_8KB 0x1 +#define IXGBE_FCBUFF_16KB 0x2 +#define IXGBE_FCBUFF_64KB 0x3 +#define IXGBE_FCBUFF_MAX 65536 /* 64KB max */ +#define IXGBE_FCBUFF_MIN 4096 /* 4KB min */ +#define IXGBE_FCOE_DDP_MAX 512 /* 9 bits xid */ + +/* fcerr */ +#define IXGBE_FCERR_BADCRC 0x00100000 + +struct ixgbe_fcoe_ddp { + int len; + u32 err; + unsigned int sgc; + struct scatterlist *sgl; + dma_addr_t udp; + unsigned long *udl; +}; + +struct ixgbe_fcoe { + spinlock_t lock; + struct pci_pool *pool; + struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX]; +}; + +#endif /* _IXGBE_FCOE_H */ -- cgit v1.2.3 From d3a2ae6d315382b2dcc7747c5b3b70f0490e9157 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:10:21 +0000 Subject: ixgbe: Add FCoE feature code to 82599 This adds the FCoE feature code ixgbe_fcoe.c to 82599. For a start, this patch only adds ixgbe_configure_fcoe() to configure related register for FCoE to 82599. In patches that follow, I will be adding more functions to ixgbe_fcoe.c to add support of FCoE offload features to 82599. Signed-off-by: Yi Zou Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_fcoe.c | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 drivers/net/ixgbe/ixgbe_fcoe.c diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c new file mode 100644 index 000000000000..f8c4d357636d --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -0,0 +1,60 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + +#include "ixgbe.h" +#include +#include +#include +#include +#include +#include +#include + +/** + * ixgbe_configure_fcoe - configures registers for fcoe at start + * @adapter: ptr to ixgbe adapter + * + * This sets up FCoE related registers + * + * Returns : none + */ +void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + + /* L2 filter for FCoE: default to queue 0 */ + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE), + (ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN)); + IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0); + IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), + IXGBE_ETQS_QUEUE_EN); + IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, + IXGBE_FCRXCTRL_FCOELLI | + IXGBE_FCRXCTRL_FCCRCBO | + (FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT)); +} -- cgit v1.2.3 From bc079228e74d63742255c466d2bce1f42423f219 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:10:44 +0000 Subject: ixgbe: Add infrastructure code for FCoE large send offload to 82599 This adds infrastructure code for FCoE Tx side offload feature to 82599, including Fiber Channel CRC calculation, auto insertion of the start of frame (SOF) and end of frame (EOF) of FCoE packets, and large send by FCoE Sequence Offload (FSO). Signed-off-by: Yi Zou Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_fcoe.c | 132 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index f8c4d357636d..e20facd1f2df 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -35,6 +35,138 @@ #include #include +/** + * ixgbe_fso - ixgbe FCoE Sequence Offload (FSO) + * @adapter: ixgbe adapter + * @tx_ring: tx desc ring + * @skb: associated skb + * @tx_flags: tx flags + * @hdr_len: hdr_len to be returned + * + * This sets up large send offload for FCoE + * + * Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error + */ +int ixgbe_fso(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring, struct sk_buff *skb, + u32 tx_flags, u8 *hdr_len) +{ + u8 sof, eof; + u32 vlan_macip_lens; + u32 fcoe_sof_eof; + u32 type_tucmd; + u32 mss_l4len_idx; + int mss = 0; + unsigned int i; + struct ixgbe_tx_buffer *tx_buffer_info; + struct ixgbe_adv_tx_context_desc *context_desc; + struct fc_frame_header *fh; + + if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) { + DPRINTK(DRV, ERR, "Wrong gso type %d:expecting SKB_GSO_FCOE\n", + skb_shinfo(skb)->gso_type); + return -EINVAL; + } + + /* resets the header to point fcoe/fc */ + skb_set_network_header(skb, skb->mac_len); + skb_set_transport_header(skb, skb->mac_len + + sizeof(struct fcoe_hdr)); + + /* sets up SOF and ORIS */ + fcoe_sof_eof = 0; + sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof; + switch (sof) { + case FC_SOF_I2: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS; + break; + case FC_SOF_I3: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF; + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS; + break; + case FC_SOF_N2: + break; + case FC_SOF_N3: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF; + break; + default: + DPRINTK(DRV, WARNING, "unknown sof = 0x%x\n", sof); + return -EINVAL; + } + + /* the first byte of the last dword is EOF */ + skb_copy_bits(skb, skb->len - 4, &eof, 1); + /* sets up EOF and ORIE */ + switch (eof) { + case FC_EOF_N: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N; + break; + case FC_EOF_T: + /* lso needs ORIE */ + if (skb_is_gso(skb)) { + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N; + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE; + } else { + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T; + } + break; + case FC_EOF_NI: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI; + break; + case FC_EOF_A: + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A; + break; + default: + DPRINTK(DRV, WARNING, "unknown eof = 0x%x\n", eof); + return -EINVAL; + } + + /* sets up PARINC indicating data offset */ + fh = (struct fc_frame_header *)skb_transport_header(skb); + if (fh->fh_f_ctl[2] & FC_FC_REL_OFF) + fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC; + + /* hdr_len includes fc_hdr if FCoE lso is enabled */ + *hdr_len = sizeof(struct fcoe_crc_eof); + if (skb_is_gso(skb)) + *hdr_len += (skb_transport_offset(skb) + + sizeof(struct fc_frame_header)); + /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ + vlan_macip_lens = (skb_transport_offset(skb) + + sizeof(struct fc_frame_header)); + vlan_macip_lens |= ((skb_transport_offset(skb) - 4) + << IXGBE_ADVTXD_MACLEN_SHIFT); + vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK); + + /* type_tycmd and mss: set TUCMD.FCoE to enable offload */ + type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT | + IXGBE_ADVTXT_TUCMD_FCOE; + if (skb_is_gso(skb)) + mss = skb_shinfo(skb)->gso_size; + /* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */ + mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) | + (1 << IXGBE_ADVTXD_IDX_SHIFT); + + /* write context desc */ + i = tx_ring->next_to_use; + context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); + + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + tx_buffer_info->time_stamp = jiffies; + tx_buffer_info->next_to_watch = i; + + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; + + return skb_is_gso(skb); +} + /** * ixgbe_configure_fcoe - configures registers for fcoe at start * @adapter: ptr to ixgbe adapter -- cgit v1.2.3 From eacd73f79a106c6a0bc429003ab691024860ab2d Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:11:06 +0000 Subject: ixgbe: Implement FCoE Tx side offload features in base driver of 82599 This patch implements the FCoE Tx side offload features in ixgbe_main.c to 82599 using the Tx offload infrastructure code added in the previous patch. This is achieved by the calling the FCoE Sequence Offload (FSO) function ixgbe_fso() on the transmit path of ixgbe. This patch also includes an EEPROM check to make sure the NIC we're loading on is an offload-enabled SKU. Signed-off-by: Yi Zou Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/Makefile | 2 + drivers/net/ixgbe/ixgbe.h | 13 +++++ drivers/net/ixgbe/ixgbe_82599.c | 1 - drivers/net/ixgbe/ixgbe_main.c | 104 ++++++++++++++++++++++++++++++++-------- drivers/net/ixgbe/ixgbe_type.h | 1 + 5 files changed, 101 insertions(+), 20 deletions(-) diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index b3f8208ec7be..21b41f42b61c 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -37,3 +37,5 @@ ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o + +ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index d743d0ed5c2e..06859f687f19 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -36,6 +36,10 @@ #include "ixgbe_type.h" #include "ixgbe_common.h" #include "ixgbe_dcb.h" +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) +#define IXGBE_FCOE +#include "ixgbe_fcoe.h" +#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */ #ifdef CONFIG_IXGBE_DCA #include #endif @@ -84,6 +88,8 @@ #define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1) #define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) #define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) +#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 4) +#define IXGBE_TX_FLAGS_FSO (u32)(1 << 5) #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 @@ -298,6 +304,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 25) #define IXGBE_FLAG_RSC_CAPABLE (u32)(1 << 26) #define IXGBE_FLAG_RSC_ENABLED (u32)(1 << 27) +#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29) /* default to trying for four seconds */ #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) @@ -371,5 +378,11 @@ extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32); +#ifdef IXGBE_FCOE +extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); +extern int ixgbe_fso(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring, struct sk_buff *skb, + u32 tx_flags, u8 *hdr_len); +#endif /* IXGBE_FCOE */ #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 6038ed14c9f9..23be4dbac7ed 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1294,7 +1294,6 @@ s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps) return 0; } - static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index efb175b1e438..ee80f6f45015 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "ixgbe.h" #include "ixgbe_common.h" @@ -1810,6 +1811,11 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) /* Decide whether to use packet split mode or not */ adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; +#endif /* IXGBE_FCOE */ + /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { rx_buf_len = IXGBE_RX_HDR_SIZE; @@ -2241,6 +2247,11 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) netif_set_gso_max_size(netdev, 65536); #endif +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + ixgbe_configure_fcoe(adapter); + +#endif /* IXGBE_FCOE */ ixgbe_configure_tx(adapter); ixgbe_configure_rx(adapter); for (i = 0; i < adapter->num_rx_queues; i++) @@ -3401,6 +3412,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; adapter->flags |= IXGBE_FLAG_RSC_CAPABLE; adapter->flags |= IXGBE_FLAG_RSC_ENABLED; +#ifdef IXGBE_FCOE + adapter->flags |= IXGBE_FLAG_FCOE_ENABLED; +#endif /* IXGBE_FCOE */ } #ifdef CONFIG_IXGBE_DCB @@ -4416,10 +4430,12 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, static int ixgbe_tx_map(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, - struct sk_buff *skb, unsigned int first) + struct sk_buff *skb, u32 tx_flags, + unsigned int first) { struct ixgbe_tx_buffer *tx_buffer_info; - unsigned int len = skb_headlen(skb); + unsigned int len; + unsigned int total = skb->len; unsigned int offset = 0, size, count = 0, i; unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; @@ -4434,6 +4450,11 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, map = skb_shinfo(skb)->dma_maps; + if (tx_flags & IXGBE_TX_FLAGS_FCOE) + /* excluding fcoe_crc_eof for FCoE */ + total -= sizeof(struct fcoe_crc_eof); + + len = min(skb_headlen(skb), total); while (len) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD); @@ -4444,6 +4465,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, tx_buffer_info->next_to_watch = i; len -= size; + total -= size; offset += size; count++; @@ -4458,7 +4480,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, struct skb_frag_struct *frag; frag = &skb_shinfo(skb)->frags[f]; - len = frag->size; + len = min((unsigned int)frag->size, total); offset = 0; while (len) { @@ -4475,9 +4497,12 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter, tx_buffer_info->next_to_watch = i; len -= size; + total -= size; offset += size; count++; } + if (total == 0) + break; } tx_ring->tx_buffer_info[i].skb = skb; @@ -4519,6 +4544,13 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, olinfo_status |= IXGBE_TXD_POPTS_TXSM << IXGBE_ADVTXD_POPTS_SHIFT; + if (tx_flags & IXGBE_TX_FLAGS_FCOE) { + olinfo_status |= IXGBE_ADVTXD_CC; + olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT); + if (tx_flags & IXGBE_TX_FLAGS_FSO) + cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE; + } + olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT); i = tx_ring->next_to_use; @@ -4615,10 +4647,16 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; tx_flags |= IXGBE_TX_FLAGS_VLAN; } - /* three things can cause us to need a context descriptor */ + + if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && + (skb->protocol == htons(ETH_P_FCOE))) + tx_flags |= IXGBE_TX_FLAGS_FCOE; + + /* four things can cause us to need a context descriptor */ if (skb_is_gso(skb) || (skb->ip_summed == CHECKSUM_PARTIAL) || - (tx_flags & IXGBE_TX_FLAGS_VLAN)) + (tx_flags & IXGBE_TX_FLAGS_VLAN) || + (tx_flags & IXGBE_TX_FLAGS_FCOE)) count++; count += TXD_USE_COUNT(skb_headlen(skb)); @@ -4630,23 +4668,35 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } - if (skb->protocol == htons(ETH_P_IP)) - tx_flags |= IXGBE_TX_FLAGS_IPV4; first = tx_ring->next_to_use; - tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len); - if (tso < 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (tso) - tx_flags |= IXGBE_TX_FLAGS_TSO; - else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) && - (skb->ip_summed == CHECKSUM_PARTIAL)) - tx_flags |= IXGBE_TX_FLAGS_CSUM; + if (tx_flags & IXGBE_TX_FLAGS_FCOE) { +#ifdef IXGBE_FCOE + /* setup tx offload for FCoE */ + tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + if (tso) + tx_flags |= IXGBE_TX_FLAGS_FSO; +#endif /* IXGBE_FCOE */ + } else { + if (skb->protocol == htons(ETH_P_IP)) + tx_flags |= IXGBE_TX_FLAGS_IPV4; + tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } - count = ixgbe_tx_map(adapter, tx_ring, skb, first); + if (tso) + tx_flags |= IXGBE_TX_FLAGS_TSO; + else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) && + (skb->ip_summed == CHECKSUM_PARTIAL)) + tx_flags |= IXGBE_TX_FLAGS_CSUM; + } + count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first); if (count) { ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len, hdr_len); @@ -4794,6 +4844,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; static int cards_found; int i, err, pci_using_dac; +#ifdef IXGBE_FCOE + u16 device_caps; +#endif u32 part_num, eec; err = pci_enable_device_mem(pdev); @@ -4976,6 +5029,19 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->dcbnl_ops = &dcbnl_ops; #endif +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { + if (hw->mac.ops.get_device_caps) { + hw->mac.ops.get_device_caps(hw, &device_caps); + if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) { + netdev->features |= NETIF_F_FCOE_CRC; + netdev->features |= NETIF_F_FSO; + } else { + adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; + } + } + } +#endif /* IXGBE_FCOE */ if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index c2d9ed5b9e05..b3de7233eeb1 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1483,6 +1483,7 @@ #endif #define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 +#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 /* PCI Bus Info */ #define IXGBE_PCI_LINK_STATUS 0xB2 -- cgit v1.2.3 From d0ed89373f2da1a0d83697d87441e519caf18cf7 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:11:29 +0000 Subject: ixgbe: Add infrastructure code for FCoE large receive offload to 82599 This adds infrastructure code for FCoE Rx side offload feature to 82599, which provides large receive offload for FCoE by Direct Data Placement (DDP). The ixgbe_fcoe_ddp_get() and ixgbe_fcoe_ddp_put() pair corresponds to the netdev support to FCoE by the function pointers provided in net_device_ops as ndo_fcoe_ddp_setup and ndo_fcoe_ddp_done. The implementation of these in ixgbe is shown in the next patch. Signed-off-by: Yi Zou Signed-off-by: Chris Leech Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 3 + drivers/net/ixgbe/ixgbe_fcoe.c | 340 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_fcoe.h | 2 +- 3 files changed, 344 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 06859f687f19..5581fa3976df 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -336,6 +336,9 @@ struct ixgbe_adapter { struct timer_list sfp_timer; struct work_struct multispeed_fiber_task; struct work_struct sfp_config_module_task; +#ifdef IXGBE_FCOE + struct ixgbe_fcoe fcoe; +#endif /* IXGBE_FCOE */ u64 rsc_count; u32 wol; u16 eeprom_version; diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index e20facd1f2df..a11c6207b748 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -35,6 +35,311 @@ #include #include +/** + * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type + * @rx_desc: advanced rx descriptor + * + * Returns : true if it is FCoE pkt + */ +static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc) +{ + u16 p; + + p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info); + if (p & IXGBE_RXDADV_PKTTYPE_ETQF) { + p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK; + p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT; + return p == IXGBE_ETQF_FILTER_FCOE; + } + return false; +} + +/** + * ixgbe_fcoe_clear_ddp - clear the given ddp context + * @ddp - ptr to the ixgbe_fcoe_ddp + * + * Returns : none + * + */ +static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp) +{ + ddp->len = 0; + ddp->err = 0; + ddp->udl = NULL; + ddp->udp = 0UL; + ddp->sgl = NULL; + ddp->sgc = 0; +} + +/** + * ixgbe_fcoe_ddp_put - free the ddp context for a given xid + * @netdev: the corresponding net_device + * @xid: the xid that corresponding ddp will be freed + * + * This is the implementation of net_device_ops.ndo_fcoe_ddp_done + * and it is expected to be called by ULD, i.e., FCP layer of libfc + * to release the corresponding ddp context when the I/O is done. + * + * Returns : data length already ddp-ed in bytes + */ +int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid) +{ + int len = 0; + struct ixgbe_fcoe *fcoe; + struct ixgbe_adapter *adapter; + struct ixgbe_fcoe_ddp *ddp; + + if (!netdev) + goto out_ddp_put; + + if (xid >= IXGBE_FCOE_DDP_MAX) + goto out_ddp_put; + + adapter = netdev_priv(netdev); + fcoe = &adapter->fcoe; + ddp = &fcoe->ddp[xid]; + if (!ddp->udl) + goto out_ddp_put; + + len = ddp->len; + /* if there an error, force to invalidate ddp context */ + if (ddp->err) { + spin_lock_bh(&fcoe->lock); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLT, 0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLTRW, + (xid | IXGBE_FCFLTRW_WE)); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW, + (xid | IXGBE_FCDMARW_WE)); + spin_unlock_bh(&fcoe->lock); + } + if (ddp->sgl) + pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc, + DMA_FROM_DEVICE); + pci_pool_free(fcoe->pool, ddp->udl, ddp->udp); + ixgbe_fcoe_clear_ddp(ddp); + +out_ddp_put: + return len; +} + +/** + * ixgbe_fcoe_ddp_get - called to set up ddp context + * @netdev: the corresponding net_device + * @xid: the exchange id requesting ddp + * @sgl: the scatter-gather list for this request + * @sgc: the number of scatter-gather items + * + * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup + * and is expected to be called from ULD, e.g., FCP layer of libfc + * to set up ddp for the corresponding xid of the given sglist for + * the corresponding I/O. + * + * Returns : 1 for success and 0 for no ddp + */ +int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, + struct scatterlist *sgl, unsigned int sgc) +{ + struct ixgbe_adapter *adapter; + struct ixgbe_hw *hw; + struct ixgbe_fcoe *fcoe; + struct ixgbe_fcoe_ddp *ddp; + struct scatterlist *sg; + unsigned int i, j, dmacount; + unsigned int len; + static const unsigned int bufflen = 4096; + unsigned int firstoff = 0; + unsigned int lastsize; + unsigned int thisoff = 0; + unsigned int thislen = 0; + u32 fcbuff, fcdmarw, fcfltrw; + dma_addr_t addr; + + if (!netdev || !sgl) + return 0; + + adapter = netdev_priv(netdev); + if (xid >= IXGBE_FCOE_DDP_MAX) { + DPRINTK(DRV, WARNING, "xid=0x%x out-of-range\n", xid); + return 0; + } + + fcoe = &adapter->fcoe; + if (!fcoe->pool) { + DPRINTK(DRV, WARNING, "xid=0x%x no ddp pool for fcoe\n", xid); + return 0; + } + + ddp = &fcoe->ddp[xid]; + if (ddp->sgl) { + DPRINTK(DRV, ERR, "xid 0x%x w/ non-null sgl=%p nents=%d\n", + xid, ddp->sgl, ddp->sgc); + return 0; + } + ixgbe_fcoe_clear_ddp(ddp); + + /* setup dma from scsi command sgl */ + dmacount = pci_map_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE); + if (dmacount == 0) { + DPRINTK(DRV, ERR, "xid 0x%x DMA map error\n", xid); + return 0; + } + + /* alloc the udl from our ddp pool */ + ddp->udl = pci_pool_alloc(fcoe->pool, GFP_KERNEL, &ddp->udp); + if (!ddp->udl) { + DPRINTK(DRV, ERR, "failed allocated ddp context\n"); + goto out_noddp_unmap; + } + ddp->sgl = sgl; + ddp->sgc = sgc; + + j = 0; + for_each_sg(sgl, sg, dmacount, i) { + addr = sg_dma_address(sg); + len = sg_dma_len(sg); + while (len) { + /* get the offset of length of current buffer */ + thisoff = addr & ((dma_addr_t)bufflen - 1); + thislen = min((bufflen - thisoff), len); + /* + * all but the 1st buffer (j == 0) + * must be aligned on bufflen + */ + if ((j != 0) && (thisoff)) + goto out_noddp_free; + /* + * all but the last buffer + * ((i == (dmacount - 1)) && (thislen == len)) + * must end at bufflen + */ + if (((i != (dmacount - 1)) || (thislen != len)) + && ((thislen + thisoff) != bufflen)) + goto out_noddp_free; + + ddp->udl[j] = (u64)(addr - thisoff); + /* only the first buffer may have none-zero offset */ + if (j == 0) + firstoff = thisoff; + len -= thislen; + addr += thislen; + j++; + /* max number of buffers allowed in one DDP context */ + if (j > IXGBE_BUFFCNT_MAX) { + DPRINTK(DRV, ERR, "xid=%x:%d,%d,%d:addr=%llx " + "not enough descriptors\n", + xid, i, j, dmacount, (u64)addr); + goto out_noddp_free; + } + } + } + /* only the last buffer may have non-full bufflen */ + lastsize = thisoff + thislen; + + fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT); + fcbuff |= (j << IXGBE_FCBUFF_BUFFCNT_SHIFT); + fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT); + fcbuff |= (IXGBE_FCBUFF_VALID); + + fcdmarw = xid; + fcdmarw |= IXGBE_FCDMARW_WE; + fcdmarw |= (lastsize << IXGBE_FCDMARW_LASTSIZE_SHIFT); + + fcfltrw = xid; + fcfltrw |= IXGBE_FCFLTRW_WE; + + /* program DMA context */ + hw = &adapter->hw; + spin_lock_bh(&fcoe->lock); + IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_32BIT_MASK); + IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32); + IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff); + IXGBE_WRITE_REG(hw, IXGBE_FCDMARW, fcdmarw); + /* program filter context */ + IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0); + IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID); + IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw); + spin_unlock_bh(&fcoe->lock); + + return 1; + +out_noddp_free: + pci_pool_free(fcoe->pool, ddp->udl, ddp->udp); + ixgbe_fcoe_clear_ddp(ddp); + +out_noddp_unmap: + pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE); + return 0; +} + +/** + * ixgbe_fcoe_ddp - check ddp status and mark it done + * @adapter: ixgbe adapter + * @rx_desc: advanced rx descriptor + * @skb: the skb holding the received data + * + * This checks ddp status. + * + * Returns : 0 for success and skb will not be delivered to ULD + */ +int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u16 xid; + u32 sterr, fceofe, fcerr, fcstat; + int rc = -EINVAL; + struct ixgbe_fcoe *fcoe; + struct ixgbe_fcoe_ddp *ddp; + struct fc_frame_header *fh; + + if (!ixgbe_rx_is_fcoe(rx_desc)) + goto ddp_out; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + sterr = le32_to_cpu(rx_desc->wb.upper.status_error); + fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR); + fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE); + if (fcerr == IXGBE_FCERR_BADCRC) + skb->ip_summed = CHECKSUM_NONE; + + skb_reset_network_header(skb); + skb_set_transport_header(skb, skb_network_offset(skb) + + sizeof(struct fcoe_hdr)); + fh = (struct fc_frame_header *)skb_transport_header(skb); + xid = be16_to_cpu(fh->fh_ox_id); + if (xid >= IXGBE_FCOE_DDP_MAX) + goto ddp_out; + + fcoe = &adapter->fcoe; + ddp = &fcoe->ddp[xid]; + if (!ddp->udl) + goto ddp_out; + + ddp->err = (fcerr | fceofe); + if (ddp->err) + goto ddp_out; + + fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT); + if (fcstat) { + /* update length of DDPed data */ + ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); + /* unmap the sg list when FCP_RSP is received */ + if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_FCPRSP) { + pci_unmap_sg(adapter->pdev, ddp->sgl, + ddp->sgc, DMA_FROM_DEVICE); + ddp->sgl = NULL; + ddp->sgc = 0; + } + /* return 0 to bypass going to ULD for DDPed data */ + if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_DDP) + rc = 0; + } + +ddp_out: + return rc; +} + /** * ixgbe_fso - ixgbe FCoE Sequence Offload (FSO) * @adapter: ixgbe adapter @@ -178,7 +483,20 @@ int ixgbe_fso(struct ixgbe_adapter *adapter, void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_fcoe *fcoe = &adapter->fcoe; + + /* create the pool for ddp if not created yet */ + if (!fcoe->pool) { + /* allocate ddp pool */ + fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp", + adapter->pdev, IXGBE_FCPTR_MAX, + IXGBE_FCPTR_ALIGN, PAGE_SIZE); + if (!fcoe->pool) + DPRINTK(DRV, ERR, + "failed to allocated FCoE DDP pool\n"); + spin_lock_init(&fcoe->lock); + } /* L2 filter for FCoE: default to queue 0 */ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE), (ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN)); @@ -190,3 +508,25 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) IXGBE_FCRXCTRL_FCCRCBO | (FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT)); } + +/** + * ixgbe_cleanup_fcoe - release all fcoe ddp context resources + * @adapter : ixgbe adapter + * + * Cleans up outstanding ddp context resources + * + * Returns : none + */ +void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter) +{ + int i; + struct ixgbe_fcoe *fcoe = &adapter->fcoe; + + /* release ddp resource */ + if (fcoe->pool) { + for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++) + ixgbe_fcoe_ddp_put(adapter->netdev, i); + pci_pool_destroy(fcoe->pool); + fcoe->pool = NULL; + } +} diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h index d054c1dada50..b7f9b63aa49f 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.h +++ b/drivers/net/ixgbe/ixgbe_fcoe.h @@ -54,7 +54,7 @@ struct ixgbe_fcoe_ddp { unsigned int sgc; struct scatterlist *sgl; dma_addr_t udp; - unsigned long *udl; + u64 *udl; }; struct ixgbe_fcoe { -- cgit v1.2.3 From 332d4a7d981e25d239c5d723a4f35020397dc606 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:11:53 +0000 Subject: ixgbe: Implement FCoE Rx side large receive offload feature to 82599 This patch implements the FCoE Rx side offload feature in ixgbe_main.c to 82599 using the Rx offload infrastructure code added in the previous patch. The large receive offload by Direct Data Placement (DDP) for FCoE is achieved by implementing the ndo_fcoe_ddp_setup and ndo_fcoe_ddp_done in net_device_ops via netdev. It is up to the ULD, i.e., fcoe and libfc to query and setup large receive offload accordingly through the corresponding netdev upon creating fcoe instances. Signed-off-by: Yi Zou Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 7 +++++++ drivers/net/ixgbe/ixgbe_main.c | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 5581fa3976df..db6d3ea1b9f0 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -386,6 +386,13 @@ extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); extern int ixgbe_fso(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, struct sk_buff *skb, u32 tx_flags, u8 *hdr_len); +extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); +extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, + union ixgbe_adv_rx_desc *rx_desc, + struct sk_buff *skb); +extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, + struct scatterlist *sgl, unsigned int sgc); +extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid); #endif /* IXGBE_FCOE */ #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ee80f6f45015..e7c44a3d9c8c 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -784,6 +784,12 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, total_rx_packets++; skb->protocol = eth_type_trans(skb, adapter->netdev); +#ifdef IXGBE_FCOE + /* if ddp, not passing to ULD unless for FCP_RSP or error */ + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + if (!ixgbe_fcoe_ddp(adapter, rx_desc, skb)) + goto next_desc; +#endif /* IXGBE_FCOE */ ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc); next_desc: @@ -4822,6 +4828,10 @@ static const struct net_device_ops ixgbe_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ixgbe_netpoll, #endif +#ifdef IXGBE_FCOE + .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get, + .ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put, +#endif /* IXGBE_FCOE */ }; /** @@ -5036,6 +5046,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) { netdev->features |= NETIF_F_FCOE_CRC; netdev->features |= NETIF_F_FSO; + netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; } else { adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; } @@ -5205,6 +5216,11 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) } #endif +#ifdef IXGBE_FCOE + if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) + ixgbe_cleanup_fcoe(adapter); + +#endif /* IXGBE_FCOE */ if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); -- cgit v1.2.3 From 6d45522c532be430b2ed63ed48a6a9e15328af66 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 13 May 2009 13:12:16 +0000 Subject: ixgbe: Add FCoE related statistics to 82599 This adds FCoE related statistics to 82599, including number Rx-ed and Tx-ed FCoE packets, number of Rx-ed and Tx-ed FCoE packets in dwords, number of bad Fiber Channel CRCs detected in FCoE packets, and number of FCoE packets dropped on the Rx side. Signed-off-by: Yi Zou Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_ethtool.c | 8 ++++++++ drivers/net/ixgbe/ixgbe_main.c | 8 ++++++++ drivers/net/ixgbe/ixgbe_type.h | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index c0167d617b1e..39fb98faffd0 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -91,6 +91,14 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { {"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)}, {"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)}, {"rx_no_dma_resources", IXGBE_STAT(hw_rx_no_dma_resources)}, +#ifdef IXGBE_FCOE + {"fcoe_bad_fccrc", IXGBE_STAT(stats.fccrc)}, + {"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)}, + {"rx_fcoe_packets", IXGBE_STAT(stats.fcoeprc)}, + {"rx_fcoe_dwords", IXGBE_STAT(stats.fcoedwrc)}, + {"tx_fcoe_packets", IXGBE_STAT(stats.fcoeptc)}, + {"tx_fcoe_dwords", IXGBE_STAT(stats.fcoedwtc)}, +#endif /* IXGBE_FCOE */ }; #define IXGBE_QUEUE_STATS_LEN \ diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e7c44a3d9c8c..d69a0526f24d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4002,6 +4002,14 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */ adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); +#ifdef IXGBE_FCOE + adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); + adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); + adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); + adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); + adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); + adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); +#endif /* IXGBE_FCOE */ } else { adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index b3de7233eeb1..38f835da4b90 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2157,6 +2157,12 @@ struct ixgbe_hw_stats { u64 fdirfstat_fremove; u64 fdirmatch; u64 fdirmiss; + u64 fccrc; + u64 fcoerpdc; + u64 fcoeprc; + u64 fcoeptc; + u64 fcoedwrc; + u64 fcoedwtc; }; /* forward declaration */ -- cgit v1.2.3 From d44b5e07c6813e6d747f7f947f1da5f0abf14eb4 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 11 May 2009 21:44:51 +0000 Subject: net/ibmveth: fix panic in probe netdev->dev_addr changed from being an array to being a pointer, so we should not take its address for memcpy(). Signed-off-by: Stephen Rothwell Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 53af71aceb8a..0995c438f286 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1285,7 +1285,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ netdev->features |= NETIF_F_LLTX; spin_lock_init(&adapter->stats_lock); - memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); + memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); for(i = 0; irx_buff_pool[i].kobj; -- cgit v1.2.3